` with:
+- `entityType` — enum value (e.g., `EntityType.DEVICE`)
+- `columns` — array of column definitions (header key, cell property/template, width)
+- `cellActionDescriptors` — per-row action buttons
+- `groupActionDescriptors` — bulk-selection action buttons
+- `headerActionDescriptors` — toolbar action buttons (add, import)
+- `entityComponent` — reference to the detail form component class
+- `entityTabsComponent` — reference to the tabs component class
+- `addDialogComponent` — optional dialog for add flow (e.g., `DeviceWizardDialogComponent`)
+
+### All Table Config Resolvers
+
+| Resolver | Entity Type | Source Dir | Entity Component | Tabs Component |
+|----------|-------------|-----------|------------------|----------------|
+| `TenantsTableConfigResolver` | TENANT | `tenant/` | `TenantComponent` | `TenantTabsComponent` |
+| `TenantProfilesTableConfigResolver` | TENANT_PROFILE | `tenant-profile/` | `TenantProfileComponent` | `TenantProfileTabsComponent` |
+| `DevicesTableConfigResolver` | DEVICE | `device/` | `DeviceComponent` | `DeviceTabsComponent` |
+| `DeviceProfilesTableConfigResolver` | DEVICE_PROFILE | `device-profile/` | `DeviceProfileComponent` | `DeviceProfileTabsComponent` |
+| `AssetsTableConfigResolver` | ASSET | `asset/` | `AssetComponent` | `AssetTabsComponent` |
+| `AssetProfilesTableConfigResolver` | ASSET_PROFILE | `asset-profile/` | `AssetProfileComponent` | `AssetProfileTabsComponent` |
+| `EntityViewsTableConfigResolver` | ENTITY_VIEW | `entity-view/` | `EntityViewComponent` | `EntityViewTabsComponent` |
+| `CustomersTableConfigResolver` | CUSTOMER | `customer/` | `CustomerComponent` | `CustomerTabsComponent` |
+| `UsersTableConfigResolver` | USER | `user/` | `UserComponent` | `UserTabsComponent` |
+| `DashboardsTableConfigResolver` | DASHBOARD | `dashboard/` | `DashboardFormComponent` | `DashboardTabsComponent` |
+| `EdgesTableConfigResolver` | EDGE | `edge/` | `EdgeComponent` | `EdgeTabsComponent` |
+| `RuleChainsTableConfigResolver` | RULE_CHAIN | `rulechain/` | `RuleChainComponent` | `RuleChainTabsComponent` |
+| `OtaUpdateTableConfigResolve` | OTA_PACKAGE | `ota-update/` | `OtaUpdateComponent` | `OtaUpdateTabsComponent` |
+| `CalculatedFieldsTableConfigResolver` | CALCULATED_FIELD | `calculated-fields/` (config in `home/components/calculated-fields/`) | `CalculatedFieldComponent` | `CalculatedFieldsTabsComponent` |
+| `WidgetTypesTableConfigResolver` | WIDGETS_BUNDLE | `widget/` | `WidgetTypeComponent` | `WidgetTypeTabsComponent` |
+| `WidgetsBundlesTableConfigResolver` | WIDGETS_BUNDLE | `widget/` | `WidgetsBundleComponent` | `WidgetsBundleTabsComponent` |
+| `ResourcesLibraryTableConfigResolver` | TB_RESOURCE | `admin/` | `ResourcesLibraryComponent` | `ResourceLibraryTabsComponent` |
+| `JsLibraryTableConfigResolver` | TB_RESOURCE | `admin/` | `JsResourceComponent` | `ResourceTabsComponent` |
+| `QueuesTableConfigResolver` | QUEUE | `admin/queue/` | `QueueComponent` | — |
+| `AiModelsTableConfigResolver` | AI_MODEL | `ai-model/` | — | — |
+| `ClientsTableConfigResolver` | OAUTH2_CLIENT | `admin/oauth2/clients/` | `ClientComponent` | — |
+| `InboxTableConfigResolver` | NOTIFICATION | `notification/inbox/` | — (dialog) | — |
+| `SentTableConfigResolver` | NOTIFICATION_REQUEST | `notification/sent/` | — (dialog) | — |
+| `RecipientTableConfigResolver` | NOTIFICATION_TARGET | `notification/recipient/` | — (dialog) | — |
+| `TemplateTableConfigResolver` | NOTIFICATION_TEMPLATE | `notification/template/` | — (dialog) | — |
+| `RuleTableConfigResolver` | NOTIFICATION_RULE | `notification/rule/` | — (dialog) | — |
+| `MobileAppTableConfigResolver` | MOBILE_APP | `mobile/applications/` | `MobileAppComponent` | — |
+| `MobileBundleTableConfigResolver` | MOBILE_BUNDLE | `mobile/bundes/` | — | — |
+| `AlarmRulesTableConfigResolver` | CALCULATED_FIELD | `alarm/` (config in `home/components/alarm-rules/`) | — | — |
+| `DomainTableConfigResolver` | DOMAIN | `admin/oauth2/domains/` | `DomainComponent` | — |
+
+---
+
+## 4. Shared Component Catalog
+
+### `@shared/components/entity/`
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-entity-autocomplete` | Autocomplete input for selecting a single entity |
+| `tb-entity-select` | Dropdown select for entity |
+| `tb-entity-list` | Chip list for multiple entities |
+| `tb-entity-list-select` | Dropdown with entity list selection |
+| `tb-entity-key-autocomplete` | Autocomplete for entity attribute/telemetry keys |
+| `tb-entity-keys-list` | Chip list for multiple entity keys |
+| `tb-entity-type-select` | Dropdown for entity type enum |
+| `tb-entity-type-list` | Chip list for multiple entity types |
+| `tb-entity-subtype-select` | Dropdown for entity subtype (e.g., device type) |
+| `tb-entity-subtype-list` | Chip list for multiple subtypes |
+| `tb-entity-subtype-autocomplete` | Autocomplete for entity subtype |
+| `tb-entity-gateway-select` | Dropdown for selecting a gateway device |
+
+### `@shared/components/time/`
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-timewindow` | Timewindow selector (realtime/history) |
+| `tb-timewindow-panel` | Expanded panel for timewindow config |
+| `tb-timewindow-config-dialog` | Dialog for advanced timewindow settings |
+| `tb-datetime` | Date-time picker input |
+| `tb-datetime-period` | Date range picker |
+| `tb-timezone` | Timezone display |
+| `tb-timezone-select` | Dropdown for timezone selection |
+| `tb-quick-time-interval` | Quick interval preset selector |
+| `tb-timeinterval` | Duration input (number + unit) |
+| `tb-datapoints-limit` | Numeric input for data point limits |
+| `tb-aggregation-type-select` | Dropdown for aggregation type (AVG, SUM, etc.) |
+| `tb-history-selector` | History navigation selector |
+
+### `@shared/components/image/`
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-image-gallery` | Grid gallery of uploaded images |
+| `tb-image-gallery-dialog` | Dialog wrapper for image gallery |
+| `tb-image-input` | Single image upload input |
+| `tb-gallery-image-input` | Image input that opens gallery for selection |
+| `tb-multiple-gallery-image-input` | Multi-image input with gallery |
+| `tb-upload-image-dialog` | Upload dialog |
+| `tb-embed-image-dialog` | Embed external image dialog |
+| `tb-scada-symbol-input` | SCADA symbol selector input |
+
+### `@shared/components/dialog/`
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-confirm-dialog` | Yes/No confirmation dialog |
+| `tb-alert-dialog` | Information alert dialog |
+| `tb-error-alert-dialog` | Error message dialog |
+| `tb-color-picker-dialog` | Color picker in a dialog |
+| `tb-material-icons-dialog` | Material icon browser dialog |
+| `tb-node-script-test-dialog` | Script testing dialog for rule nodes |
+| `tb-object-edit-dialog` | JSON object editor dialog |
+| `tb-todo-dialog` | Todo/checklist dialog |
+
+### `@shared/components/` (other)
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-json-content` | JSON syntax-highlighted viewer |
+| `tb-json-object-edit` | Editable JSON object component |
+| `tb-json-object-view` | Read-only JSON object display |
+| `tb-markdown` | Markdown editor/viewer |
+| `tb-breadcrumb` | Breadcrumb navigation bar |
+| `tb-icon` | Custom icon component |
+| `tb-logo` | ThingsBoard logo |
+| `tb-copy-button` | Copy-to-clipboard button |
+| `tb-toggle-password` | Password visibility toggle |
+| `tb-file-input` | File upload input |
+| `tb-phone-input` | International phone input |
+| `tb-unit-input` | Measurement unit input |
+| `tb-value-input` | Generic value input with type selection |
+| `tb-color-input` | Color picker input |
+| `tb-color-picker` | Inline color picker |
+| `tb-key-val-map` | Key-value pair map editor |
+| `tb-nav-tree` | Tree navigation component |
+| `tb-user-menu` | User profile dropdown menu |
+| `tb-notification-bell` | Notification bell icon with badge |
+| `tb-footer` | Page footer |
+| `tb-scroll-grid` | Virtual-scroll grid |
+| `tb-social-share-panel` | Social sharing buttons |
+
+### Autocomplete / Select Components
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-dashboard-autocomplete` | Autocomplete for dashboard selection |
+| `tb-dashboard-select` | Dropdown for dashboard |
+| `tb-dashboard-state-autocomplete` | Autocomplete for dashboard states |
+| `tb-country-autocomplete` | Country autocomplete |
+| `tb-string-autocomplete` | Generic string autocomplete |
+| `tb-message-type-autocomplete` | Rule engine message type autocomplete |
+| `tb-queue-autocomplete` | Queue name autocomplete |
+| `tb-relation-type-autocomplete` | Relation type autocomplete |
+| `tb-resource-autocomplete` | Resource autocomplete |
+| `tb-ota-package-autocomplete` | OTA package autocomplete |
+| `tb-branch-autocomplete` | Git branch autocomplete |
+| `tb-rule-chain-select` | Rule chain select dropdown |
+| `tb-widgets-bundle-select` | Widgets bundle select dropdown |
+| `tb-template-autocomplete` | Notification template autocomplete |
+| `tb-material-icon-select` | Material icon picker |
+| `tb-slack-conversation-autocomplete` | Slack conversation autocomplete |
+
+### `@home/components/` (key components)
+
+| Selector | Purpose |
+|----------|---------|
+| `tb-entities-table` | Main entity table (columns, sort, pagination, actions) |
+| `tb-entity-details-panel` | Slide-out panel for entity details |
+| `tb-entity-details-page` | Full-page entity details view |
+| `tb-add-entity-dialog` | Generic add-entity dialog |
+| `tb-entity-filter` | Entity data filter component |
+| `tb-entity-chips` | Chip display for entity references |
+| `tb-details-panel` | Base details panel (toolbar + edit/apply FABs) |
+| `tb-alarm-table` | Alarm list table |
+| `tb-alarm-details-dialog` | Alarm detail dialog with ack/clear |
+| `tb-alarm-assignee` | Alarm assignee selector |
+| `tb-alarm-comment` | Alarm comment thread |
+| `tb-alarm-filter-config` | Alarm filter configuration |
+| `tb-audit-log-table` | Audit log table |
+| `tb-attribute-table` | Entity attribute key-value table |
+| `tb-relation-table` | Entity relation table |
+| `tb-event-table` | Entity event table |
+| `tb-dashboard` | Dashboard renderer |
+| `tb-dashboard-page` | Dashboard page (toolbar + dashboard) |
+| `tb-dashboard-toolbar` | Dashboard edit/view toolbar |
+| `tb-edit-widget` | Widget editor |
+| `tb-router-tabs` | Tab navigation via router (used for section tabs) |
+| `tb-device-credentials` | Device credentials form |
+
+---
+
+## 5. Angular Material DOM Patterns
+
+**No `data-testid` attributes** — selectors must use Angular Material structure, `formControlName`, `matColumnDef`, labels, roles, and classes.
+
+### Login Form
+
+```html
+
+
+
+
+
+```
+
+Key selectors: `#username-input`, `#password-input`, `button[type="submit"]`.
+
+### Main Layout
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+Key selectors: `mat-sidenav#sidenav`, `button#main`, `tb-breadcrumb`, `tb-user-menu`.
+
+### Entity Table
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+Key selectors: `table[mat-table]`, `mat-row`, `mat-cell`, `mat-paginator`, `[matColumnDef="select"]`, `[matColumnDef="actions"]`. Note: the search input uses Angular template ref `#searchInput` (not an HTML `id`); target it via `.tb-entity-table mat-toolbar input[matInput]` in the search toolbar context.
+
+### Entity Details Page
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+Key selectors: `mat-toolbar.details-toolbar`, `button[mat-fab][color="accent"]`, `mat-tab-group`, `mat-tab`.
+
+### Details Panel (Slide-Out Drawer)
+
+```html
+
+
+
+
+```
+
+### Entity Detail Form (inside a tab)
+
+```html
+
+
+
+```
+
+Key selectors: `input[formControlName="name"]`, `mat-slide-toggle[formControlName="..."]`, `textarea[formControlName="description"]`.
+
+### Dialog
+
+```html
+
+```
+
+Key selectors: `[mat-dialog-content]`, `[mat-dialog-actions]`, `button[type="submit"]`, `mat-toolbar[color="primary"] h2`.
+
+### Common Material Selector Patterns
+
+```
+# Find a form field by its control name
+input[formControlName="name"]
+mat-select[formControlName="type"]
+mat-slide-toggle[formControlName="gateway"]
+textarea[formControlName="description"]
+
+# Find table column content
+[matColumnDef="name"] mat-cell
+
+# Find buttons by tooltip
+button[matTooltip="Search"]
+
+# Find a specific tab
+mat-tab-group mat-tab (by index or label text)
+
+# Find menu items (after opening menu)
+button[mat-menu-item]
+
+# Find dialog actions
+[mat-dialog-actions] button[mat-raised-button]
+```
+
+---
+
+## 6. Form Structure Guide
+
+All entity detail forms extend the abstract `EntityComponent` directive (`@home/components/entity/entity.component.ts`).
+
+**Key properties:**
+- `entityForm: UntypedFormGroup` — the reactive form instance
+- `entity: T` — current entity data (input)
+- `isEdit: boolean` — whether form is in edit mode (input)
+
+**Lifecycle:**
+
+1. **`buildForm(entity: T): UntypedFormGroup`** — Called in constructor. Creates the FormGroup with controls, validators, and initial values. Subscribe to valueChanges here for cascading updates.
+
+2. **`updateForm(entity: T): void`** — Called when entity input changes. Uses `entityForm.patchValue({...}, {emitEvent: false})` to populate form without triggering change events.
+
+3. **`updateFormState(): void`** — Called when `isEdit` changes. Calls `entityForm.enable()` or `entityForm.disable()` with `{emitEvent: false}`.
+
+4. **`entityFormValue(): any`** — Returns `entityForm.getRawValue()` (reads disabled fields too), passed through `prepareFormValue()` (default: `deepTrim`).
+
+**Read-only pattern:** Templates use `