PrimeBrickPrimeBrick
  • Docs
  • Contact
  • MIT License
  • Documentation
  • MCP Server
  • API Catalog
  • Services
  • Libraries
PrimeBrickPrimeBrick

© 2026 PrimeBrick. MIT License. v3.11.2

github
Backend
Frontend
    Developer Guide
      OverviewGetting startedUI stackApp shell & sidebarAuthentication & sessionsSystem settingsUI componentsUI patternsIcon ConventionsInput AnatomyField Hints & TooltipsButton Style StandardsEntity metadatai18n — Translations on the FrontendThe AI Tool Loop (caller-driven)Error HandlingComposables (use* hooks)
      Components
        Entity list tableComboSelectDynamicIconColorSelectorColorPickerAvatarPreviewEventCardCommandPaletteAppShellAppSidebarAppTopbarAppPageLayoutAppPageScaffoldAppPageBreadcrumbAppServerBannerBrowserClientInfoLangSelectThemeToggleSidebarAppLauncherSidebarHealthBadgeSidebarOrgSwitcherSidebarProfileMenuSidebarVersionBadgeButtonButton (async)FormPageLayoutFormLabelWithPriorityHelpPasswordChecklistChoiceboxDateWheelPickerEventToastLoadingBarMetadataLoadingJsonTableViewerNumberTickerStatCardToolbarDialogBorderedEntity Confirm DialogsSheet panelRFCErrorDialogLoginFormPasskeyButtonPasskeyEnrollmentAuthMethodsPromptDialogSessionExpiredDialogInputSliderSliderFieldSwitchFieldSelectableFieldsetBadgeValuesEditorTooltipFormPrimeFieldSmartRegexInput
      API Reference
Microservices
powered by Zudoku
Components

Entity list table

EntityListTable is the generic, reusable component every module uses to render entity lists. It is generic over a row type TRow extends Record<string, unknown> and lives in src/lib/components/entity-list-table/.

Route pages do not wire EntityListTable directly — they render EntityTablePage (see Route-level usage below), which owns data/state via useEntityList and feeds this component. Use EntityListTable directly only in composite hosts (multiple list instances, extra UI).

Component overview

The component is controlled: the parent route owns the data and most state (rows, page, search, sort, filters, selection) and passes them in as props with on*Change callbacks. A few props (selectedKeys, filtersOpen, deletionFilterMode, datetimeIanaModeByKey) are bindable for two-way sync.

Key props

GroupProps
Identityuid, entity, translationKey, columnOrderStorageKey
Columnscolumns — the full root-level meta array via orderedColumns(meta.columns)
Datarows, total, metaLoading, rowsLoading, error
Paginationpage, pageSize, pageSizeOptions, onPageChange, onPageSizeChange
Searchsearch, onSearchInput, searchInKeys, onSearchInKeysChange
SortingsortKey, sortDir, onSortChange, defaultSort
ViewdefaultView (meta.table.default_view)
Column visibilityvisibleKeys, onVisibleKeysChange, onResetColumnVisibility
SelectionselectedKeys (bindable), onSelectedKeysChange, rowSelectionEnabled
ActionsonRefresh, rowActions (snippet), entityActions (meta.actions), entityCustomActions (meta.table.row_custom_actions), customActionHandlers, onCreateAction, onEditAction
FiltersfiltersOpen (bindable), filterValues, onFilterValuesChange, advancedFilters, onAdvancedFiltersChange
Deletion filterdeletionFilterMode (bindable), onDeletionFilterModeChange
Customizationcell (snippet), metaLoadingView, rowsLoadingView, emptyView, errorView

Columns arrive as the single root-level columns array from the entity meta. Sticky/audited groups are derived internally from the sticky and audited column flags — there are no parallel group arrays.

Composable architecture

Behavior is split into composables under composables/, each following the composable state exposure pattern (read-only state getter, mutator functions, individual $derived getters).

ComposableResponsibility
useColumnOrderColumn ordering within sticky/data/auditing groups; persists to sessionStorage
useViewModetable / cards / cards_list mode; persists to sessionStorage
useDeletionFilternon_deleted / deleted / all mode; persists to sessionStorage
useToolbarModeAuto-switches toolbar between filters and bulk modes
useClientSelectionSelected-only view with client-side pagination
useRowRangeSelectionMouse-drag brush selection across rows
useKeyboardNavigationArrow keys, space, enter, escape shortcuts
useStickyColumnsSticky column positioning
useScrollPreservationPreserves scroll position across re-renders
useSheetPanelsOrchestrates columns/filters/search-in panels (wraps useSheetPanelManagement)
useDialogsCentralized dialog open/close state
useBulkActionsBulk delete/restore/duplicate; dispatch on meta.actions[].endpoint with /api/v1/entities/{entity} fallback
useRowActionsSingle-row edit/preview/delete/restore/duplicate; declared-endpoint dispatch + purge detection
useExportXLSX/CSV export with HTML preview via the declared export endpoint
usePreviewPanelPreview row, inline edit mode, prev/next navigation

List data/state (meta fetch, rows, search/sort/page/filter state, persistence, sync) is NOT a composable of this component — it is owned by useEntityList, consumed directly by EntityTablePage or by composite hosts.

View modes

Three view modes: table, cards, cards_list. The initial mode comes from meta.table.default_view via the defaultView prop; the active mode is stored in sessionStorage under {columnOrderStorageKey}:viewMode (fallback pb.entityList:{uid}:viewMode). The toolbar's ViewModeToggle switches between them. Rendering is handled by EntityListTableTableView and EntityListTableCardView.

Selection model

Two complementary models:

  • Server selection (default) — selectedKeys is owned by the parent and persists across page navigation. Used for server-side bulk operations and export.
  • Client selection (selected-only view) — useClientSelection maintains a Map<string, TRow> of selected rows and provides client-side pagination for the selected-only view. It automatically exits this view on server reload, when selection empties, or when row selection is disabled.

Selection interactions: row checkboxes, header select-all, mouse-drag range selection (useRowRangeSelection), and keyboard space to toggle the focused row. The toolbar auto-switches to bulk mode when items are selected.

Dialogs

All dialogs are centralized through useDialogs and rendered as separate Svelte components in dialogs/:

DialogAction
DeleteDialogSingle-row soft delete
RestoreDialogSingle-row restore
DuplicateDialogSingle or bulk duplicate (50-item limit for bulk)
BulkDeleteDialogBulk soft delete
BulkRestoreDialogBulk restore
ExportDialogExport format (XLSX/CSV) and scope (selected/all)
ExportPreviewDialogHTML export preview (PDF/email modes)
HtmlExportDialogHTML export confirmation

On success, dialogs refresh the list, clear selection, close, and switch the toolbar back to filters mode. Errors go through pushNotification.

Sheet panels

Panels are mounted via the global SheetHost (see App shell) and orchestrated by useSheetPanels:

Panel IDComponentPurpose
entity.columnsColumnsPanelColumn visibility checkboxes + drag-and-drop reordering within groups
entity.filtersFiltersPanelBasic filters + advanced filter builder with operators (=, !=, >, <, >=, <=, contains, startsWith, endsWith, BETWEEN) and AND/OR connector
entity.searchInSearchInPanelToggles which columns are included in search
previewPreviewPanelFull row preview with inline editing and prev/next navigation
version historyVersionHistoryPanelAudit trail from /api/v1/entities/{entity}/{uuid}/audit with a timeline UI

Column types

MetaColumn defines a column — the root-level entity field dictionary shared by table, form, and preview pages. All fields are snake_case:

FieldPurpose
keyColumn identifier (row field key)
label_keyi18n key for the header/form label
typetext, badge, date, datetime, color, boolean, number
orderRequired 0..N position within its group
stickyPinned to the left (typically meta.display_field)
auditedSystem audit column — rendered last
sortable, searchable, filterable, hideableCapability flags
default_visiblefalse = selectable but hidden by default (e.g. uuid)
badgePer-value { label_key, label_text, color } mapping
datetime_iana_toggle{ record_iana_field } for IANA timezone toggle
tooltip, tooltip_priority, tooltip_titleTooltip configuration
show_form_tooltip, show_list_tooltipTooltip visibility per context

Utility functions in src/lib/entity-list/types.ts: orderedColumns() (sticky → normal → audited, each by order), defaultVisibleColumnKeys(), sanitizeVisibleKeys(), searchableTextColumns(), getOperatorsForColumnType().

The default "all fields" search covers visible ∩ searchable ∩ text columns: hidden-by-default columns (e.g. uuid) are excluded until the user shows them or picks them explicitly in the search-scope selector.

Route-level usage — EntityTablePage

EntityTablePage (src/lib/components/entity-table-page/) is the route-level host for the table archetype. A page is ~50 lines: config props

  • snippets, no data logic.
Code
<script lang="ts"> import EntityTablePage from '$lib/components/entity-table-page/EntityTablePage.svelte'; import AppPageBreadcrumb from '$lib/components/AppPageBreadcrumb.svelte'; type MyRow = { uuid: string } & Record<string, unknown>; </script> <EntityTablePage basePath="/api/v1/entities/my_entity" storageKeyPrefix="pb:my-entity:list:" syncChannel="primebrick_my_entity_sync" errorScopeKey="app.common.errors.scope.myEntitiesList" navStrategy="goto" createPath="/system/my-entity/create" editPath="/system/my-entity/:uuid" > {#snippet breadcrumb()} <AppPageBreadcrumb segments={[{ label: 'My entities' }]} /> {/snippet} </EntityTablePage>
GroupProps
DatabasePath (entity API base; /ws/<svc>/api/v1/entities/… for module entities), fixedFilters, onRowsLoaded
List behaviordeletionFilter={false} (no deleted_records param — e.g. role_mapping), searchGate, searchDebounceMs
PersistencestorageKeyPrefix, persist ('session' default) + legacyPersist (read-only legacy medium, 'local' default)
ErrorserrorScopeKey, errorScopeKeyInit
SyncsyncChannel — legacy BroadcastChannel name (receiver mode; child form pages post refresh)
NavigationnavStrategy ('goto' default or 'popup' — new tab + focus), createPath, editPath (:uuid placeholder), onCreateAction/onEditAction overrides
Create CTADerived automatically: EntityTablePage matches the route census kind:"create" route for the current entity and forwards createPath + create_cta (label_key/icon from the census route) to the toolbar entity-create-cta. Pass createPath only to override the census-derived route.
Row actionscustomActionHandlers keyed by meta.table.row_custom_actions[].action_name, rowActions={false} hides the column
Selection labelsselectionLabelKey / selectionLabelSingularKey / selectionLabelText / selectionLabelSingularText
Snippetsbreadcrumb, headerExtras, headerActions(meta) (non-entity page CTAs — entity create belongs to the census-derived toolbar CTA), cell, extraDialogs(uid), metaLoadingView, rowsLoadingView, emptyView, errorView

Canonical examples: system/settings/users (popup nav + extraDialogs), system/settings/roles (deletionFilter={false}), crm/customers (census-derived create CTA).

Persistence

User preferences are persisted to sessionStorage (cleared when the tab closes) — column order, view mode, search scope keys, sort, filter values, advanced filters, deletion filter mode, and datetime IANA toggle mode. useEntityList derives keys from storageKeyPrefix (e.g. pb:users:list:sort); EntityListTable derives its internals from columnOrderStorageKey. Legacy localStorage keys are read once as fallback then orphaned — never rewritten.

Next steps

  • Component catalog — every custom/wrapped component
  • System settings — where EntityListTable is used for the users list
  • UI components — custom components on top of Shadcn-Svelte™
  • API reference — full prop tables for every component
Last modified on October 28, 2026
Composables (use* hooks)ComboSelect
On this page
  • Component overview
  • Key props
  • Composable architecture
  • View modes
  • Selection model
  • Dialogs
  • Sheet panels
  • Column types
  • Route-level usage — EntityTablePage
  • Persistence
  • Next steps