commons-shared-web-ui 0.0.60 → 0.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/documentation/alert.md +123 -0
  3. package/documentation/button-dropdown.md +126 -0
  4. package/documentation/button.md +184 -0
  5. package/documentation/cards-usage-guidelines.md +131 -0
  6. package/documentation/configurable-form.md +605 -0
  7. package/documentation/confirmation-modal.md +250 -0
  8. package/documentation/filter-sidebar.md +178 -0
  9. package/documentation/filter-table-selector.md +228 -0
  10. package/documentation/form-builder.md +599 -0
  11. package/documentation/form-components.md +384 -0
  12. package/documentation/form-field-configuration.md +250 -0
  13. package/documentation/nav.md +427 -0
  14. package/documentation/pagination.md +181 -0
  15. package/documentation/side-nav-documentation.md +169 -0
  16. package/documentation/smart-form.md +2819 -0
  17. package/documentation/smart-table.md +1297 -0
  18. package/documentation/snackbar.md +118 -0
  19. package/documentation/style-externalization.md +88 -0
  20. package/documentation/summary-card.md +279 -0
  21. package/documentation/table-column-configuration.md +221 -0
  22. package/documentation/time-picker.md +274 -0
  23. package/ng-package.json +30 -0
  24. package/package.json +53 -34
  25. package/src/lib/modules/alert/alert.models.ts +6 -0
  26. package/src/lib/modules/alert/alert.module.ts +16 -0
  27. package/src/lib/modules/alert/components/alert/alert.component.html +27 -0
  28. package/src/lib/modules/alert/components/alert/alert.component.scss +92 -0
  29. package/src/lib/modules/alert/components/alert/alert.component.ts +81 -0
  30. package/src/lib/modules/button/button.models.ts +13 -0
  31. package/src/lib/modules/button/button.module.ts +16 -0
  32. package/src/lib/modules/button/components/button/button.component.html +22 -0
  33. package/src/lib/modules/button/components/button/button.component.scss +92 -0
  34. package/src/lib/modules/button/components/button/button.component.ts +67 -0
  35. package/src/lib/modules/button-dropdown/button-dropdown.models.ts +26 -0
  36. package/src/lib/modules/button-dropdown/button-dropdown.module.ts +22 -0
  37. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.html +41 -0
  38. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.scss +135 -0
  39. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.ts +160 -0
  40. package/src/lib/modules/configurable-form/component/configurable-form.component.html +294 -0
  41. package/src/lib/modules/configurable-form/component/configurable-form.component.scss +503 -0
  42. package/src/lib/modules/configurable-form/component/configurable-form.component.ts +628 -0
  43. package/src/lib/modules/configurable-form/configurable-form.examples.ts +154 -0
  44. package/src/lib/modules/configurable-form/configurable-form.model.ts +131 -0
  45. package/src/lib/modules/configurable-form/configurable-form.module.ts +19 -0
  46. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.html +77 -0
  47. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.scss +395 -0
  48. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.ts +266 -0
  49. package/src/lib/modules/confirmation-modal/confirmation-modal.models.ts +71 -0
  50. package/src/lib/modules/confirmation-modal/confirmation-modal.module.ts +20 -0
  51. package/src/lib/modules/filter/components/filter/filter.component.html +131 -0
  52. package/src/lib/modules/filter/components/filter/filter.component.scss +245 -0
  53. package/src/lib/modules/filter/components/filter/filter.component.ts +216 -0
  54. package/src/lib/modules/filter/filter.models.ts +88 -0
  55. package/src/lib/modules/filter/filter.module.ts +24 -0
  56. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.html +112 -0
  57. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.scss +186 -0
  58. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.ts +163 -0
  59. package/src/lib/modules/filter-sidebar/filter-sidebar.models.ts +95 -0
  60. package/src/lib/modules/filter-sidebar/filter-sidebar.module.ts +24 -0
  61. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.html +73 -0
  62. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.scss +321 -0
  63. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.ts +361 -0
  64. package/src/lib/modules/filter-table-selector/filter-table-selector.models.ts +91 -0
  65. package/src/lib/modules/filter-table-selector/filter-table-selector.module.ts +22 -0
  66. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.html +63 -0
  67. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.scss +496 -0
  68. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.ts +445 -0
  69. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.html +75 -0
  70. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.scss +210 -0
  71. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.ts +55 -0
  72. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.html +25 -0
  73. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.scss +82 -0
  74. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.ts +95 -0
  75. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.html +20 -0
  76. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.scss +37 -0
  77. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.ts +94 -0
  78. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.html +46 -0
  79. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.scss +102 -0
  80. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.ts +50 -0
  81. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.html +35 -0
  82. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.scss +67 -0
  83. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.ts +34 -0
  84. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.html +68 -0
  85. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.scss +113 -0
  86. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.ts +74 -0
  87. package/src/lib/modules/form-builder/configs/field-type-schema.map.ts +533 -0
  88. package/src/lib/modules/form-builder/form-builder.module.ts +36 -0
  89. package/src/lib/modules/form-builder/index.ts +9 -0
  90. package/src/lib/modules/form-builder/models/builder.models.ts +7 -0
  91. package/src/lib/modules/form-builder/models/field-configurator.models.ts +38 -0
  92. package/src/lib/modules/form-builder/models/field-selection.models.ts +51 -0
  93. package/src/lib/modules/form-builder/services/field-configurator.service.ts +258 -0
  94. package/src/lib/modules/form-builder/services/field-selection.service.ts +299 -0
  95. package/src/lib/modules/form-builder/services/form-schema-tree.service.ts +670 -0
  96. package/src/lib/modules/form-builder/tokens/builder.tokens.ts +10 -0
  97. package/src/lib/modules/form-builder/utils/constants.ts +43 -0
  98. package/src/lib/modules/form-components/components/checkbox/checkbox.component.html +29 -0
  99. package/src/lib/modules/form-components/components/checkbox/checkbox.component.scss +111 -0
  100. package/src/lib/modules/form-components/components/checkbox/checkbox.component.ts +207 -0
  101. package/src/lib/modules/form-components/components/checkbox/checkbox.models.ts +35 -0
  102. package/src/lib/modules/form-components/components/datepicker/datepicker.component.html +42 -0
  103. package/src/lib/modules/form-components/components/datepicker/datepicker.component.scss +115 -0
  104. package/src/lib/modules/form-components/components/datepicker/datepicker.component.ts +267 -0
  105. package/src/lib/modules/form-components/components/datepicker/datepicker.models.ts +45 -0
  106. package/src/lib/modules/form-components/components/dropdown/dropdown.component.html +74 -0
  107. package/src/lib/modules/form-components/components/dropdown/dropdown.component.scss +252 -0
  108. package/src/lib/modules/form-components/components/dropdown/dropdown.component.ts +377 -0
  109. package/src/lib/modules/form-components/components/dropdown/dropdown.models.ts +53 -0
  110. package/src/lib/modules/form-components/components/input/input.component.html +51 -0
  111. package/src/lib/modules/form-components/components/input/input.component.scss +128 -0
  112. package/src/lib/modules/form-components/components/input/input.component.ts +250 -0
  113. package/src/lib/modules/form-components/components/input/input.models.ts +55 -0
  114. package/src/lib/modules/form-components/components/radio/radio.component.html +22 -0
  115. package/src/lib/modules/form-components/components/radio/radio.component.scss +107 -0
  116. package/src/lib/modules/form-components/components/radio/radio.component.ts +181 -0
  117. package/src/lib/modules/form-components/components/radio/radio.models.ts +39 -0
  118. package/src/lib/modules/form-components/components/search/search.component.html +15 -0
  119. package/src/lib/modules/form-components/components/search/search.component.scss +87 -0
  120. package/src/lib/modules/form-components/components/search/search.component.ts +213 -0
  121. package/src/lib/modules/form-components/components/search/search.models.ts +40 -0
  122. package/src/lib/modules/form-components/components/toggle/toggle.component.html +15 -0
  123. package/src/lib/modules/form-components/components/toggle/toggle.component.scss +81 -0
  124. package/src/lib/modules/form-components/components/toggle/toggle.component.ts +166 -0
  125. package/src/lib/modules/form-components/components/toggle/toggle.models.ts +27 -0
  126. package/src/lib/modules/form-components/directives/click-outside.directive.ts +22 -0
  127. package/src/lib/modules/form-components/form-components.module.ts +42 -0
  128. package/src/lib/modules/form-field-configuration/components/_ffc-controls.scss +89 -0
  129. package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.html +68 -0
  130. package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.scss +73 -0
  131. package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.ts +34 -0
  132. package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.html +78 -0
  133. package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.scss +83 -0
  134. package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.ts +94 -0
  135. package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.html +38 -0
  136. package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.scss +42 -0
  137. package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.ts +92 -0
  138. package/src/lib/modules/form-field-configuration/form-field-configuration.module.ts +23 -0
  139. package/src/lib/modules/form-field-configuration/index.ts +7 -0
  140. package/src/lib/modules/form-field-configuration/models/field-configuration.models.ts +62 -0
  141. package/src/lib/modules/form-field-configuration/services/config-schema-tree.service.ts +159 -0
  142. package/src/lib/modules/form-field-configuration/services/field-configuration.service.ts +228 -0
  143. package/src/lib/modules/material/material.module.ts +94 -0
  144. package/src/lib/modules/nav/components/nav/nav.component.html +34 -0
  145. package/src/lib/modules/nav/components/nav/nav.component.scss +171 -0
  146. package/src/lib/modules/nav/components/nav/nav.component.ts +82 -0
  147. package/src/lib/modules/nav/nav.models.ts +31 -0
  148. package/src/lib/modules/nav/nav.module.ts +17 -0
  149. package/src/lib/modules/pagination/components/pagination/pagination.component.html +52 -0
  150. package/src/lib/modules/pagination/components/pagination/pagination.component.scss +155 -0
  151. package/src/lib/modules/pagination/components/pagination/pagination.component.ts +109 -0
  152. package/src/lib/modules/pagination/pagination.module.ts +17 -0
  153. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.html +56 -0
  154. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.scss +342 -0
  155. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.ts +135 -0
  156. package/src/lib/modules/side-nav/side-nav.models.ts +38 -0
  157. package/src/lib/modules/side-nav/side-nav.module.ts +16 -0
  158. package/src/lib/modules/smart-form/components/form-field/form-field.component.html +1379 -0
  159. package/src/lib/modules/smart-form/components/form-field/form-field.component.scss +2255 -0
  160. package/src/lib/modules/smart-form/components/form-field/form-field.component.ts +3174 -0
  161. package/src/lib/modules/smart-form/components/form-section/form-section.component.html +67 -0
  162. package/src/lib/modules/smart-form/components/form-section/form-section.component.scss +209 -0
  163. package/src/lib/modules/smart-form/components/form-section/form-section.component.ts +142 -0
  164. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.html +253 -0
  165. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.scss +689 -0
  166. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.ts +1134 -0
  167. package/src/lib/modules/smart-form/index.ts +10 -0
  168. package/src/lib/modules/smart-form/models/form-schema.model.ts +803 -0
  169. package/src/lib/modules/smart-form/models/hierarchy-config.model.ts +22 -0
  170. package/src/lib/modules/smart-form/services/expression.service.ts +75 -0
  171. package/src/lib/modules/smart-form/services/smart-form-controller.service.ts +67 -0
  172. package/src/lib/modules/smart-form/smart-form.examples.ts +1324 -0
  173. package/src/lib/modules/smart-form/smart-form.module.ts +40 -0
  174. package/src/lib/modules/smart-form/smart-form.theme.scss +1 -0
  175. package/src/lib/modules/smart-form/utils/translation.utils.ts +82 -0
  176. package/src/lib/modules/smart-form/utils/trusted-url.pipe.ts +25 -0
  177. package/src/lib/modules/smart-form/utils/validation.utils.ts +98 -0
  178. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.html +283 -0
  179. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.scss +685 -0
  180. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.ts +1219 -0
  181. package/src/lib/modules/smart-table/models/table-config.model.ts +247 -0
  182. package/src/lib/modules/smart-table/smart-table.module.ts +30 -0
  183. package/src/lib/modules/smart-table/utils/safe-html.pipe.ts +28 -0
  184. package/src/lib/modules/smart-table/utils/smart-table.utils.ts +18 -0
  185. package/src/lib/modules/snackbar/components/snackbar.component.html +41 -0
  186. package/src/lib/modules/snackbar/components/snackbar.component.scss +99 -0
  187. package/src/lib/modules/snackbar/components/snackbar.component.ts +18 -0
  188. package/src/lib/modules/snackbar/models/snackbar.models.ts +10 -0
  189. package/src/lib/modules/snackbar/services/snackbar.service.ts +40 -0
  190. package/src/lib/modules/snackbar/snackbar.module.ts +11 -0
  191. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.html +47 -0
  192. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.scss +199 -0
  193. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.ts +126 -0
  194. package/src/lib/modules/summary-card/summary-card.module.ts +18 -0
  195. package/src/lib/modules/table-column-configuration/components/_tcc-controls.scss +53 -0
  196. package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.html +47 -0
  197. package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.scss +50 -0
  198. package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.ts +33 -0
  199. package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.html +30 -0
  200. package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.scss +36 -0
  201. package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.ts +78 -0
  202. package/src/lib/modules/table-column-configuration/index.ts +5 -0
  203. package/src/lib/modules/table-column-configuration/models/table-column-configuration.models.ts +20 -0
  204. package/src/lib/modules/table-column-configuration/services/table-column-configuration.service.ts +77 -0
  205. package/src/lib/modules/table-column-configuration/table-column-configuration.module.ts +21 -0
  206. package/src/lib/modules/time-picker/components/time-picker/time-picker.component.html +37 -0
  207. package/src/lib/modules/time-picker/components/time-picker/time-picker.component.scss +102 -0
  208. package/src/lib/modules/time-picker/components/time-picker/time-picker.component.ts +178 -0
  209. package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.html +78 -0
  210. package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.scss +226 -0
  211. package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.ts +595 -0
  212. package/src/lib/modules/time-picker/models/time-picker.models.ts +49 -0
  213. package/src/lib/modules/time-picker/time-picker.module.ts +23 -0
  214. package/src/lib/shared-ui.module.ts +55 -0
  215. package/src/lib/utils/constants.ts +11 -0
  216. package/src/lib/utils/storage.utils.ts +37 -0
  217. package/src/lib/utils/string.utils.ts +23 -0
  218. package/src/lib/utils/translation.utils.ts +87 -0
  219. package/src/public-api.ts +127 -0
  220. package/tsconfig.lib.json +15 -0
  221. package/fesm2022/commons-shared-web-ui.mjs +0 -16097
  222. package/fesm2022/commons-shared-web-ui.mjs.map +0 -1
  223. package/index.d.ts +0 -5022
@@ -0,0 +1,1297 @@
1
+ # Smart Table Component Documentation
2
+
3
+ The `SmartTableComponent` is a powerful, configuration-driven data table that supports sorting, filtering, searching, pagination, and row actions. It is designed to be highly customizable via a JSON configuration object and CSS variables.
4
+
5
+ ## Features
6
+
7
+ - **Configuration Driven**: Entire table structure and behavior defined by a single config object.
8
+ - **Data Handling**: Built-in support for server-side pagination, sorting, and filtering.
9
+ - **Search**: Integrated global search.
10
+ - **Filters**: Configurable dropdown filters.
11
+ - **Actions**: Row-level actions (Edit, Delete, Custom) and Top-bar actions (Create New, Export).
12
+ - **Selection**: Optional checkbox selection for rows.
13
+ - **Inline Row Editing & Addition**: Support for inline row editing and creation directly in the table.
14
+ - **Responsive**: Adapts to different screen sizes.
15
+ - **Theming**: Externalized theming support using CSS variables.
16
+ - **Badges**: Built-in support for status badges with configurable colors.
17
+
18
+ ## Installation
19
+
20
+ To install the latest version of the `commons-shared-web-ui` library, run the following command:
21
+
22
+ ```bash
23
+ npm install commons-shared-web-ui@latest
24
+ ```
25
+
26
+ Import the `SmartTableModule` into your feature module.
27
+
28
+ ```typescript
29
+ import { SmartTableModule } from "commons-shared-web-ui";
30
+
31
+ @NgModule({
32
+ imports: [
33
+ SmartTableModule,
34
+ // ...
35
+ ],
36
+ })
37
+ export class MyFeatureModule {}
38
+ ```
39
+
40
+ ## Basic Usage
41
+
42
+ ### Standard Mode (Internal API Fetch)
43
+
44
+ 1. **Define Configuration**: In your component, create a `TableConfig` object pointing to your API.
45
+ 2. **Pass to Component**: Use `<lib-smart-table [config]="config"></lib-smart-table>`.
46
+
47
+ ### External Data Mode (Parent Driven)
48
+
49
+ 1. **Define Configuration**: Create a `TableConfig` object (no `apiUrl` needed).
50
+ 2. **Pass Data**: Bind your data array to `[tableData]` and count to `[totalItemsCount]`.
51
+ 3. **Listen to Events**: Bind to `(sortChange)`, `(pageChange)`, and `(searchChange)` to fetch data manually when the user interacts with the table.
52
+
53
+ ### Example
54
+
55
+ ```typescript
56
+ import { TableConfig } from "@campus-cloud/shared-ui";
57
+
58
+ export class MyComponent {
59
+ tableConfig: TableConfig = {
60
+ apiUrl: "https://api.example.com/users",
61
+ columns: [
62
+ { key: "id", label: "ID", type: "number", sortable: true },
63
+ { key: "name", label: "Name", type: "text", sortable: true },
64
+ {
65
+ key: "status",
66
+ label: "Status",
67
+ type: "badge",
68
+ badgeConfig: {
69
+ active: "success",
70
+ draft: "neutral",
71
+ deleted: "danger",
72
+ },
73
+ },
74
+ ],
75
+ pagination: {
76
+ enabled: true,
77
+ pageSize: 10,
78
+ pageSizeOptions: [5, 10, 25],
79
+ },
80
+ actions: [
81
+ {
82
+ label: "Edit",
83
+ type: "callback",
84
+ icon: "fa fa-edit",
85
+ btnVariant: "outline",
86
+ callback: (row) => this.onEdit(row),
87
+ },
88
+ ],
89
+ };
90
+
91
+ onEdit(row: any) {
92
+ console.log("Edit", row);
93
+ }
94
+ }
95
+ ```
96
+
97
+ ```html
98
+ <lib-smart-table
99
+ [config]="tableConfig"
100
+ (action)="onTableAction($event)"
101
+ ></lib-smart-table>
102
+ ```
103
+
104
+ ## Configuration Reference
105
+
106
+ ### TableConfig
107
+
108
+ | Property | Type | Description |
109
+ | ------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- |
110
+ | `apiUrl` | `string` | (Optional in External Mode) Base URL for fetching data. |
111
+ | `apiMethod` | `'GET' \\| 'POST'` | (Optional) HTTP method for fetching data (default: `GET`). |
112
+ | `apiPayload` | `any` | (Optional) Body payload to send if `apiMethod` is `POST`. |
113
+ | `columns` | `TableColumn[]` | Array of column definitions. |
114
+ | `filters` | `TableFilter[]` | Array of filter definitions (dropdowns). |
115
+ | `pagination` | `PaginationConfig` | Pagination settings. |
116
+ | `actions` | `TableAction[]` | Row-level actions. |
117
+ | `topBarButtons` | `TableAction[]` | Buttons to display above the table. |
118
+ | `selectable` | `boolean` | Enable row checkbox selection. |
119
+ | `sortBy` | `string` | Default sort column key. |
120
+ | `orderBy` | `'ASC' \| 'DESC'` | Default sort order. |
121
+ | `searchConfig` | `SearchConfig` | Global search configuration (replaces `searchEnabled`). |
122
+ | `queryParamsConfig` | `QueryParamsConfig` | (Optional) Advanced configuration for query parameter serialization. |
123
+ | `dataResponsePath` | `string` | (Optional) Path to data array in API response (e.g. `data` or `response.list`). Empty for root array. |
124
+ | `labels` | `TableLabels` | (Optional) Override default text labels. |
125
+ | `editingRowClass` | `string` | (Optional) CSS class to apply to rows currently being edited or added. |
126
+ | `emptyValue` | `string` | (Optional) Fallback text shown for any cell whose value is `null`, `undefined`, or empty string. Overridden per-column via `TableColumn.emptyValue`. Default: `'-'`. |
127
+
128
+ ### TableColumn
129
+
130
+ | Property | Type | Description |
131
+ | ------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------- |
132
+ | `key` | `string` | Property key in the data object. |
133
+ | `label` | `string` | Header display text. |
134
+ | `type` | `'text' \| 'number' \| 'date' \| 'html' \| 'badge'` | Data type for display formatting. |
135
+ | `sortable` | `boolean` | Enable sorting for this column. |
136
+ | `editable` | `boolean` | Enables inline editing/adding for this column. |
137
+ | `dataType` | `'text' \| 'number' \| 'date' \| 'email' \| 'select'`| (Optional) Input type for inline editing (uses `mat-datepicker` for `'date'`). |
138
+ | `options` | `TableOption[]` | (Optional) Dropdown select options when `dataType` is `'select'`. |
139
+ | `subFields` | `TableColumnSubField[]` | (Optional) Configures stacked inputs within a single cell for display/edit. |
140
+ | `editConfig` | `object` | (Optional) Configures defaults (`defaultValue`) and disabled state (`disabled`) in edit. |
141
+ | `badgeConfig` | `object` | Map values to badge variants (`success`, `warning`, `danger`, `info`, `neutral`). |
142
+ | `labelPath` | `string` | (Optional) Path to nested data (e.g., `user.address.city`). Overrides `key` for display. |
143
+ | `emptyValue` | `string` | (Optional) Text shown when this column's cell value is `null`, `undefined`, or `''`. Overrides `TableConfig.emptyValue` for this column only. |
144
+ | `dateFormat` | `string` | (Optional) Date format string (e.g., `short`, `dd/MM/yyyy`) for `type: 'date'`. |
145
+ | `clickAction` | `'route' \| 'callback'` | (Optional) Action to perform on cell click. |
146
+ | `clickRoute` | `string` | (Optional) Route pattern for redirection (e.g. `/users/:id`) if action is `route`. |
147
+
148
+ **Empty cell value resolution**
149
+
150
+ When a cell value is `null`, `undefined`, or an empty string, the display text is resolved in this priority order:
151
+
152
+ 1. `TableColumn.emptyValue` — column-level override (e.g. `'N/A'` for one specific column)
153
+ 2. `TableConfig.emptyValue` — table-level fallback (e.g. `'NA'` for all columns in this table)
154
+ 3. Library default: `'-'`
155
+
156
+ ```typescript
157
+ // Example: show 'N/A' everywhere, but 'Not Set' for the notes column
158
+ tableConfig: TableConfig = {
159
+ emptyValue: 'N/A',
160
+ columns: [
161
+ { key: 'name', label: 'Name', type: 'text' },
162
+ { key: 'notes', label: 'Notes', type: 'text', emptyValue: 'Not Set' }
163
+ ]
164
+ };
165
+ ```
166
+
167
+ ### TableFilter
168
+
169
+ | Property | Type | Description |
170
+ | -------------------- | ------------------------------- | -------------------------------------------------------------- |
171
+ | `key` | `string` | Key to use for the filter query param. |
172
+ | `label` | `string` | Display label for the filter dropdown. |
173
+ | `type` | `'select'` | Filter type. |
174
+ | `options` | `array` | (Optional) Static array of `{label, value}` objects. |
175
+ | `apiUrl` | `string` | (Optional) API URL to fetch filter options. |
176
+ | `apiMethod` | `'GET' \\| 'POST'` | (Optional) HTTP method for fetching filter options (default: `GET`). |
177
+ | `apiPayload` | `any` | (Optional) Body payload to send if `apiMethod` is `POST`. |
178
+ | `dataPath` | `string` | (Optional) Path to array in filter API response. |
179
+ | `labelPath` | `string` | (Optional) Path to label property in API object. |
180
+ | `valuePath` | `string` | (Optional) Path to value property in API object. |
181
+ | `requestKey` | `string` | (Optional) Query param key if different from `key`. |
182
+ | `handling` | `'standard' \| 'nested_string'` | Strategy for filter APIs. Appends to `paramName` if nested. |
183
+ | `nestedStringConfig` | `NestedStringConfig` | Configuration for nested string serialization for filter APIs. |
184
+
185
+ ### SearchConfig
186
+
187
+ | Property | Type | Description |
188
+ | -------------- | ------------------------------- | --------------------------------------------------------------------------------- |
189
+ | `enabled` | `boolean` | Enable search input. |
190
+ | `searchKey` | `string` | Query param key to use (default: `search`). |
191
+ | `debounceTime` | `number` | Debounce time in ms (default: `300`). |
192
+ | `handling` | `'standard' \| 'nested_string'` | Strategy. `nested_string` appends `SEARCH_TERM=value` to the nested param string. |
193
+ | `minimumCharacter` | `number` | Min characters typed before the API is called (default: `3`). Below this the table stays idle; clearing the box always re-triggers a call. |
194
+
195
+ ### PaginationConfig
196
+
197
+ | Property | Type | Description |
198
+ | ------------------ | ---------- | ------------------------------------------------- |
199
+ | `enabled` | `boolean` | Enable pagination. |
200
+ | `pageSize` | `number` | Default number of items per page. |
201
+ | `pageSizeOptions` | `number[]` | Array of page size options (e.g. `[10, 25, 50]`). |
202
+ | `totalCountConfig` | `object` | Config for total items count (see below). |
203
+
204
+ #### TotalCountConfig
205
+
206
+ | Property | Type | Description |
207
+ | -------------- | ---------------------- | ------------------------------------------------------------------------------------ |
208
+ | `source` | `'same' \| 'separate'` | `'same'` (default) if count is in data response, `'separate'` for separate API call. |
209
+ | `responsePath` | `string` | Path to total count property (e.g. `total` or `meta.count`). |
210
+ | `apiUrl` | `string` | (Required if source='separate') URL for count API. |
211
+
212
+ SAMPLE:
213
+
214
+ labels: {
215
+ searchPlaceholder: "Search Users...", //fetch from i18ne
216
+ actionColumnHeader: "Manage",
217
+ noDataMessage: "No users found.",
218
+ defaultConfirmationMessage: "Do you really want to proceed?"
219
+ } |
220
+
221
+ ### QueryParamsConfig
222
+
223
+ | Property | Type | Description |
224
+ | -------------------- | ------------------------------- | ------------------------------------------------------------------------------------- |
225
+ | `pageKey` | `string` | Query param for page number (default: `page`). |
226
+ | `sizeKey` | `string` | Query param for page size (default: `pageSize`). |
227
+ | `pageIndexOffset` | `number` | Offset for page index (e.g. `-1` to convert 1-based UI to 0-based API). |
228
+ | `filterHandling` | `'standard' \| 'nested_string'` | implementation strategy. `nested_string` serializes filters into typically one param. |
229
+ | `nestedStringConfig` | `NestedStringConfig` | Configuration for nested string serialization. |
230
+
231
+ ### NestedStringConfig
232
+
233
+ | Property | Type | Description |
234
+ | ------------ | -------- | ------------------------------------------------------- |
235
+ | `paramName` | `string` | The query param key hosting the string (e.g. `params`). |
236
+ | `baseValue` | `string` | Initial value/prefix (e.g. `MARKET_ID=5`). |
237
+ | `separator` | `string` | Separator between key-values (e.g. `--` or `;`). |
238
+ | `assignment` | `string` | Assignment operator (e.g. `=` or `:`). |
239
+
240
+ ### TableLabels
241
+
242
+ | Property | Type | Description |
243
+ | ---------------------------- | -------- | -------------------------------------------------- |
244
+ | `searchPlaceholder` | `string` | Placeholder text for the search input. |
245
+ | `actionColumnHeader` | `string` | Header text for the actions column. |
246
+ | `noDataMessage` | `string` | Message displayed when no data is found. |
247
+ | `itemsPerPageLabel` | `string` | Label for items per page selector (if applicable). |
248
+ | `defaultConfirmationMessage` | `string` | Default message for action confirmation dialogs. |
249
+
250
+ ### TableAction
251
+
252
+ | Property | Type | Description |
253
+ | -------------------- | -------------------------------------------------------- | ------------------------------------------ |
254
+ | `label` | `string` | Button text. |
255
+ | `type` | `'api' \| 'route' \| 'callback' \| 'edit' \| 'dropdown'` | Action type. |
256
+ | `btnVariant` | `ButtonVariant` | Style variant of the button. |
257
+ | `icon` | `string` | Icon class (e.g. `fa fa-edit`). |
258
+ | `route` | `string` | Internal route path (e.g. `/users/:id`). |
259
+ | `apiUrl` | `string` | API endpoint for 'api' type. |
260
+ | `apiMethod` | `'POST' \| ...` | HTTP method for 'api' type. |
261
+ | `callback` | `(row: any) => void` | Function to execute on click. |
262
+ | `confirmationNeeded` | `boolean` | Show confirmation dialog before executing. |
263
+ | `items` | `TableActionItem[]` | Children items for 'dropdown' action. |
264
+ | `isEnabled` | `boolean` | Set to `false` to hide this action (and each `TableActionItem` supports the same flag). Default: `true`. |
265
+ | `visibleWhen` | `VisibilityRule \| VisibilityRule[]` | Row-aware rules — the action shows only when **all** rules match. See [Conditional Action Visibility](#conditional-action-visibility-per-row). |
266
+ | `hiddenWhen` | `VisibilityRule \| VisibilityRule[]` | Row-aware rules — the action is hidden when **any** rule matches. Takes precedence over `visibleWhen`. |
267
+
268
+ Both `visibleWhen` and `hiddenWhen` are also supported on each `TableActionItem` (dropdown menu items), which is the common case.
269
+
270
+ ### VisibilityRule
271
+
272
+ | Property | Type | Description |
273
+ | ---------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
274
+ | `field` | `string` | Path into the row (supports nesting + array index): `'status.code'`, `'subStatus.code'`, `'name[0].text'`. |
275
+ | `operator` | `'eq' \| 'neq' \| 'in' \| 'nin' \| 'truthy' \| 'falsy'` | Comparison operator. Default: `'eq'`. |
276
+ | `value` | `any` | Value to compare against for `eq` / `neq`. |
277
+ | `values` | `any[]` | List to compare against for `in` / `nin`. |
278
+
279
+ **Value normalization:** when `field` resolves to an object shaped like `{ code, name, value }`, it collapses to its `code` (then `name`, then `value`). This means one rule (`field: 'status'`) works whether the API returns `status: { code: 'ACTIVE', name: 'Active' }` **or** a plain `status: 'ACTIVE'`. String comparisons are case-insensitive.
280
+
281
+ ## Conditional Action Visibility (Per Row)
282
+
283
+ Show or hide an action based on the data in each row (e.g. `status`, `subStatus`). Rules are declared in config — no callbacks needed.
284
+
285
+ - **`hiddenWhen`** — hide the action when **any** listed rule matches.
286
+ - **`visibleWhen`** — show the action only when **all** listed rules match.
287
+ - If both are present, `hiddenWhen` wins.
288
+
289
+ ```jsonc
290
+ {
291
+ "actions": [
292
+ {
293
+ "type": "dropdown",
294
+ "icon": "fa-solid fa-ellipsis",
295
+ "items": [
296
+ { "label": "Overview", "type": "callback", "action": "OVERVIEW" },
297
+ {
298
+ "label": "Edit",
299
+ "type": "callback",
300
+ "action": "EDIT",
301
+ // Hidden once the sub-status is Launched
302
+ "hiddenWhen": { "field": "subStatus.code", "operator": "eq", "value": "MASTER_PROGRAMME_STATUS.LAUNCHED" }
303
+ },
304
+ {
305
+ "label": "Delete",
306
+ "type": "callback",
307
+ "action": "DELETE",
308
+ // Only deletable while in Draft
309
+ "visibleWhen": { "field": "status", "operator": "eq", "value": "DRAFT" }
310
+ },
311
+ {
312
+ "label": "Reactivate",
313
+ "type": "callback",
314
+ "action": "REACTIVATE",
315
+ // Hidden while the record is Active
316
+ "hiddenWhen": { "field": "status", "operator": "eq", "value": "ACTIVE" }
317
+ }
318
+ ]
319
+ }
320
+ ]
321
+ }
322
+ ```
323
+
324
+ Because of value normalization, `"field": "status"` matches both response shapes shown above — the object form (`status: { code: 'ACTIVE' }`) and the plain-string form (`status: 'ACTIVE'`). Prefer targeting `.code` explicitly (e.g. `subStatus.code`) when a status and its display name differ.
325
+
326
+ Multiple conditions (AND with `visibleWhen`, OR with `hiddenWhen`, or `in`/`nin` for a set):
327
+
328
+ ```jsonc
329
+ {
330
+ "label": "Archive",
331
+ "type": "callback",
332
+ "action": "ARCHIVE",
333
+ // Show only when status is Active AND sub-status is one of these
334
+ "visibleWhen": [
335
+ { "field": "status", "value": "ACTIVE" },
336
+ { "field": "subStatus.code", "operator": "in",
337
+ "values": ["MASTER_PROGRAMME_STATUS.LAUNCHED", "MASTER_PROGRAMME_STATUS.COMPLETED"] }
338
+ ]
339
+ }
340
+ ```
341
+
342
+ ## Action Examples
343
+
344
+ ### 1. Callback (Opening a Modal)
345
+
346
+ Use `type: 'callback'` to execute a function, such as opening a dialog.
347
+
348
+ ```typescript
349
+ // Component
350
+ actions: [
351
+ {
352
+ label: 'Edit User',
353
+ type: 'callback',
354
+ icon: 'fa fa-edit',
355
+ callback: (row) => this.openEditModal(row)
356
+ }
357
+ ]
358
+
359
+ openEditModal(row: any) {
360
+ this.dialogService.open(EditUserComponent, { data: row });
361
+ }
362
+ ```
363
+
364
+ ### 2. Route Navigation
365
+
366
+ Use `type: 'route'` for internal navigation. Parameters like `:id` are automatically replaced by row values.
367
+
368
+ ```typescript
369
+ actions: [
370
+ {
371
+ label: "View Details",
372
+ type: "route",
373
+ route: "/users/:id/details", // :id will be replaced by row.id
374
+ btnVariant: "primary",
375
+ },
376
+ ];
377
+ ```
378
+
379
+ ### 3. API Action
380
+
381
+ Use `type: 'api'` to emit an event or trigger an HTTP request directly. Use `confirmationNeeded` for critical actions.
382
+
383
+ #### Direct HTTP Execution (New)
384
+
385
+ If `apiUrl` is specified in the configuration, the Smart Table will **automatically execute the HTTP request** (e.g., POST, DELETE) for you. Variable substitution works the same as routing (`:id` gets replaced by `row.id`). Upon success, the table will reload its data automatically.
386
+
387
+ #### Event Emission Strategy
388
+
389
+ If no `apiUrl` is specified, it merely emits the `(action)` or `(topAction)` event to the parent component, allowing you to handle the API call process manually.
390
+
391
+ ```typescript
392
+ actions: [
393
+ {
394
+ label: "Delete",
395
+ type: "api",
396
+ btnVariant: "danger",
397
+ apiUrl: "https://api.example.com/users/:id", // Auto-executes DELETE request
398
+ apiMethod: "DELETE",
399
+ confirmationNeeded: true,
400
+ confirmationMessage: "Are you sure you want to delete this user?",
401
+ },
402
+ ];
403
+ ```
404
+
405
+ ### 4. Dropdown Action Menu
406
+
407
+ Use `type: 'dropdown'` with the `items` array to render a 3-dots action menu with multiple choices.
408
+
409
+ ```typescript
410
+ actions: [
411
+ {
412
+ label: "",
413
+ type: "dropdown",
414
+ icon: "fa fa-ellipsis-v", // or ellipsis-h, etc.
415
+ items: [
416
+ {
417
+ label: "Send Email",
418
+ type: "callback",
419
+ callback: (row) => this.sendEmail(row),
420
+ },
421
+ {
422
+ label: "Assign Badges",
423
+ type: "callback",
424
+ callback: (row) => this.assignBadges(row),
425
+ },
426
+ {
427
+ label: "Convert to Alumni",
428
+ type: "api",
429
+ apiUrl: "...",
430
+ confirmationNeeded: true,
431
+ },
432
+ ],
433
+ },
434
+ ];
435
+ ```
436
+
437
+ ### 5. Native Delete Action (Built-in Confirmation Modal + API)
438
+
439
+ Use `type: 'delete'` inside a dropdown `items` array to get a fully self-contained delete flow without any parent-side code:
440
+
441
+ - Smart table opens the `cc-confirmation-modal` from the shared UI library.
442
+ - On confirm, it calls `DELETE /:id` with the ID dynamically resolved from the row.
443
+ - On success, the table reloads automatically.
444
+ - All modal labels are configurable via `deleteConfig` (pass i18n-resolved strings from your component or JSON config).
445
+
446
+ #### `deleteConfig` Properties
447
+
448
+ | Property | Type | Default | Description |
449
+ | -------------- | -------- | ----------------------------------- | ------------------------------------------------------- |
450
+ | `apiUrl` | `string` | *required* | DELETE endpoint. Use `:id` (or any field name) as token.|
451
+ | `idField` | `string` | `'id'` | Row field used to replace the URL token. |
452
+ | `modalTitle` | `string` | `'Confirm Delete'` | Title shown in the confirmation modal header. |
453
+ | `modalMessage` | `string` | `'Are you sure...'` | Body message inside the modal. |
454
+ | `confirmLabel` | `string` | `'Delete'` | Label for the confirm (danger) button. |
455
+ | `cancelLabel` | `string` | `'Cancel'` | Label for the cancel button. |
456
+
457
+ #### Typescript Example
458
+
459
+ ```typescript
460
+ // In your component or JSON config (after i18n translation is applied)
461
+ actions: [
462
+ {
463
+ label: '',
464
+ type: 'dropdown',
465
+ icon: 'fa fa-ellipsis-h',
466
+ btnVariant: 'text',
467
+ items: [
468
+ {
469
+ label: 'Edit',
470
+ icon: 'fa fa-edit',
471
+ type: 'edit'
472
+ },
473
+ {
474
+ label: 'Delete',
475
+ icon: 'fa fa-trash',
476
+ type: 'delete',
477
+ deleteConfig: {
478
+ apiUrl: 'gateway/my-service/api/v1/items/:id', // :id replaced by row.id
479
+ idField: 'id', // default; can use any row field
480
+ modalTitle: 'Delete Item?',
481
+ modalMessage: 'Are you sure you want to delete this item? This action cannot be undone.',
482
+ confirmLabel: 'Yes, Delete',
483
+ cancelLabel: 'Cancel'
484
+ }
485
+ }
486
+ ]
487
+ }
488
+ ]
489
+ ```
490
+
491
+ #### JSON Config Example (with i18n keys — resolved by MFE before passing to table)
492
+
493
+ ```json
494
+ {
495
+ "actions": [
496
+ {
497
+ "label": "",
498
+ "type": "dropdown",
499
+ "icon": "fa fa-ellipsis-h",
500
+ "btnVariant": "text",
501
+ "items": [
502
+ { "label": "Edit", "icon": "fa fa-edit", "type": "edit" },
503
+ {
504
+ "label": "DELETE_LABEL_I18N_KEY",
505
+ "icon": "fa fa-trash",
506
+ "type": "delete",
507
+ "deleteConfig": {
508
+ "apiUrl": "gateway/commons-learning-center-service/api/v1/learning-center-type-masters/:id",
509
+ "idField": "id",
510
+ "modalTitle": "DELETE_MODAL_TITLE_I18N_KEY",
511
+ "modalMessage": "DELETE_MODAL_MESSAGE_I18N_KEY",
512
+ "confirmLabel": "DELETE_MODAL_CONFIRM_I18N_KEY",
513
+ "cancelLabel": "DELETE_MODAL_CANCEL_I18N_KEY"
514
+ }
515
+ }
516
+ ]
517
+ }
518
+ ]
519
+ }
520
+ ```
521
+
522
+ > **Note**: The `deleteConfig.apiUrl` supports the same `:fieldName` interpolation as `route` and `action.apiUrl`. For a row with `{ id: 42, ... }`, the URL `…/items/:id` becomes `…/items/42` at runtime.
523
+
524
+ ### 6. Advanced Configuration (Query Params & Filters)
525
+
526
+
527
+ Supported advanced features:
528
+
529
+ - Nested string query parameters (e.g. `params=MARKET_ID=5--STATUS=ACTIVE`)
530
+ - Separate API for total count
531
+ - Response path mapping
532
+ - **Externalized Labels**
533
+
534
+ ```typescript
535
+ tableConfig: TableConfig = {
536
+ apiUrl: "https://api.example.com/solutions/execute",
537
+
538
+ // Custom Labels
539
+ labels: {
540
+ searchPlaceholder: "Search Solutions...",
541
+ actionColumnHeader: "Manage",
542
+ noDataMessage: "No solutions found.",
543
+ defaultConfirmationMessage: "Do you really want to proceed?"
544
+ },
545
+
546
+ // ... rest of config
547
+
548
+ // Map data from a nested property in response
549
+ dataResponsePath: "data.elements",
550
+
551
+ columns: [
552
+ { key: "id", label: "ID", type: "number", sortable: true },
553
+ { key: "status", label: "Status", type: "text", sortable: true }
554
+ ],
555
+
556
+ // Dynamic Filters from API
557
+ filters: [
558
+ {
559
+ key: "status",
560
+ label: "Status",
561
+ type: "select",
562
+ apiUrl: "https://api.example.com/ref-data/status",
563
+ // Map options from API response
564
+ dataPath: "elements",
565
+ labelPath: "name",
566
+ valuePath: "code",
567
+ // Example nested string support for filter APIs
568
+ handling: "nested_string",
569
+ nestedStringConfig: {
570
+ paramName: "params",
571
+ baseValue: "TYPE=STATUS" // Append `params=TYPE=STATUS` to fetch call
572
+ }
573
+ }
574
+ ],
575
+
576
+ pagination: {
577
+ enabled: true,
578
+ pageSize: 10,
579
+ pageSizeOptions: [10, 50],
580
+ // Fetch total count from a different API
581
+ totalCountConfig: {
582
+ source: "separate",
583
+ apiUrl: "https://api.example.com/solutions/count/execute",
584
+ responsePath: "0.totalCount"
585
+ }
586
+ },
587
+
588
+ // Enhanced Search Configuration
589
+ searchConfig: {
590
+ enabled: true,
591
+ searchKey: "SEARCH_TERM",
592
+ debounceTime: 500, // 500ms debounce
593
+ handling: "nested_string" // Appends to params=... string
594
+ },
595
+
596
+ // Custom Query Param Serialization
597
+ queryParamsConfig: {
598
+ pageKey: "page",
599
+ sizeKey: "size",
600
+ pageIndexOffset: -1, // UI uses 1-based, API uses 0-based
601
+ filterHandling: "nested_string",
602
+ nestedStringConfig: {
603
+ paramName: "params",
604
+ baseValue: "MARKET_ID=5", // Initial value
605
+ separator: "--", // Separator between filters
606
+ assignment: "=" // Assignment operator
607
+ }
608
+ }
609
+ };
610
+ };
611
+ ```
612
+
613
+ ### 5. Nested Data & Date Formatting
614
+
615
+ You can fetch data from deep nested objects using `labelPath` and format dates using `dateFormat`.
616
+
617
+ #### Example: Nested Data
618
+
619
+ Access properties like `user.profile.name` or `names[0].text`.
620
+
621
+ ```typescript
622
+ columns: [
623
+ {
624
+ key: "curriculumName", // Unique key
625
+ label: "Curriculum Name",
626
+ // Fetch data from names[0].text
627
+ labelPath: "names[0].text",
628
+ },
629
+ {
630
+ key: "category",
631
+ label: "Category",
632
+ // Fetch data from nested object
633
+ labelPath: "meta.category.name",
634
+ },
635
+ ];
636
+ ```
637
+
638
+ #### Example: Date Formatting
639
+
640
+ Use `type: 'date'` and provide a `dateFormat`. Supports Angular's `formatDate` patterns.
641
+
642
+ ```typescript
643
+ columns: [
644
+ {
645
+ key: "startDate",
646
+ label: "Start Date",
647
+ type: "date",
648
+ // Short format: 2/17/26, 9:42 PM
649
+ dateFormat: "short",
650
+ },
651
+ {
652
+ key: "endDate",
653
+ label: "End Date",
654
+ type: "date",
655
+ // Custom format: 17-Feb-2026
656
+ dateFormat: "dd-MMM-yyyy",
657
+ },
658
+ {
659
+ key: "createdAt",
660
+ label: "Created At",
661
+ type: "date",
662
+ // Combine labelPath and dateFormat for nested dates
663
+ labelPath: "meta.audit.createdDate",
664
+ dateFormat: "medium",
665
+ },
666
+ ];
667
+ ```
668
+
669
+ ## Outputs (Events)
670
+
671
+ ### 6. Column Click Actions
672
+
673
+ You can make specific columns clickable, triggering either a route navigation or a callback event.
674
+
675
+ #### Route Navigation
676
+
677
+ Redirects to an internal route. The `:param` syntax is supported.
678
+
679
+ ```typescript
680
+ {
681
+ key: "name",
682
+ label: "Name",
683
+ type: "text",
684
+ clickAction: "route",
685
+ clickRoute: "/users/:id/profile" // :id replaced by row.id
686
+ }
687
+ ```
688
+
689
+ #### Callback Event
690
+
691
+ Emits a `(columnClick)` event which you can handle in your component.
692
+
693
+ ```typescript
694
+ // Component Config
695
+ {
696
+ key: "status",
697
+ label: "Status",
698
+ type: "badge",
699
+ clickAction: "callback"
700
+ }
701
+
702
+ // Template
703
+ <lib-smart-table
704
+ [config]="config"
705
+ (columnClick)="onColumnClick($event)">
706
+ </lib-smart-table>
707
+
708
+ // Component Method
709
+ onColumnClick(event: { row: any, column: string }) {
710
+ if (event.column === 'status') {
711
+ console.log('Status clicked for:', event.row);
712
+ }
713
+ }
714
+ ```
715
+
716
+ ## Inputs / Outputs
717
+
718
+ ### Inputs
719
+
720
+ | Input | Type | Description |
721
+ | ------------------- | --------------- | --------------------------------------------------------------------------------------------- |
722
+ | `[config]` | `TableConfig` | (Required) The main configuration object. |
723
+ | `[tableData]` | `any[]` | (Optional) Bypasses internal API calls and renders explicitly provided row data. |
724
+ | `[totalItemsCount]` | `number` | (Optional) The total count of all items, used for pagination when `[tableData]` is activated. |
725
+
726
+ ### Outputs (Events)
727
+
728
+ | Output | Description | Payload |
729
+ | ---------------- | ---------------------------------------------------------------- | ----------------------------------- |
730
+ | `(action)` | Emitted when any row action is clicked. | `{ action: TableAction, row: any }` |
731
+ | `(topAction)` | Emitted when a top-bar button is clicked. | `TableAction` |
732
+ | `(filterChange)` | Emitted when a filter value changes. | `{ key: string, value: any }` |
733
+ | `(rowSelect)` | Emitted when row selection changes. | `any[]` (Array of selected rows) |
734
+ | `(columnClick)` | Emitted when a column with `clickAction: 'callback'` is clicked. | `{ row: any, column: string }` |
735
+ | `(sortChange)` | **(External Mode)** Emitted when sort column/direction changes. | `TableDataChangeEvent` |
736
+ | `(pageChange)` | **(External Mode)** Emitted when page index/size changes. | `TableDataChangeEvent` |
737
+ | `(searchChange)` | **(External Mode)** Emitted when global search term changes. | `TableDataChangeEvent` |
738
+
739
+ ### TableDataChangeEvent
740
+ When the table operates in **External Data Mode** (by passing `[tableData]`), it emits the `TableDataChangeEvent` interface when sort, pagination, or search changes:
741
+ ```typescript
742
+ interface TableDataChangeEvent {
743
+ page: number;
744
+ pageSize: number;
745
+ sortBy?: string;
746
+ orderBy?: 'ASC' | 'DESC';
747
+ searchTerm?: string;
748
+ filters?: { [key: string]: any };
749
+ }
750
+ ```
751
+
752
+ ---
753
+
754
+ ## Theming & Styling
755
+
756
+ The Smart Table uses CSS custom properties for all visual styling. Every colour, size, shadow, and border is exposed as a variable so you can theme the component without overriding any internal styles.
757
+
758
+ There are two ways to apply a theme:
759
+
760
+ 1. **Direct CSS variables** — set them anywhere in your stylesheet (`:root`, a wrapper class, or inline).
761
+ 2. **SCSS mixin** — use `smart-table-theme()` from `smart-table.theme.scss`, which maps human-readable Sass keys to the CSS variables in one call.
762
+
763
+ ---
764
+
765
+ ### CSS Variable Reference
766
+
767
+ #### General
768
+
769
+ | Variable | Default | Description |
770
+ | ------------------ | ---------------------- | ---------------------------------------- |
771
+ | `--st-font-family` | `'Roboto', sans-serif` | Font family for the entire table |
772
+ | `--st-font-size` | `14px` | Base font size for cells and toolbar |
773
+ | `--st-text-color` | `#333` | Primary text colour |
774
+ | `--st-border-radius` | `8px` | Corner radius of the table card |
775
+ | `--st-box-shadow` | `0 2px 8px rgba(0,0,0,0.08)` | Shadow of the table card |
776
+ | `--st-table-bg` | `#fff` | Background of the table card |
777
+
778
+ #### Table Layout
779
+
780
+ | Variable | Default | Description |
781
+ | ------------------- | ------------------- | ---------------------------------- |
782
+ | `--st-table-padding` | `1rem` | Padding around the table container |
783
+ | `--st-cell-padding` | `1rem` | Padding inside each body cell |
784
+ | `--st-table-border` | `1px solid #e0e0e0` | Outer border of the table wrapper |
785
+ | `--st-row-border` | `1px solid #eee` | Bottom border between rows |
786
+
787
+ #### Header
788
+
789
+ | Variable | Default | Description |
790
+ | ---------------------- | ---------- | ---------------------------------------- |
791
+ | `--st-header-bg` | `#f5f5f5` | Background of the `<thead>` row |
792
+ | `--st-header-color` | `#333` | Text colour of header cells |
793
+ | `--st-header-weight` | `500` | Font weight of header cells |
794
+ | `--st-header-size` | `14px` | Font size of header cells |
795
+ | `--st-header-transform`| `none` | `text-transform` value (`uppercase` etc.)|
796
+ | `--st-header-border` | `1px solid #e0e0e0` | Border applied to the header |
797
+
798
+ #### Rows
799
+
800
+ | Variable | Default | Description |
801
+ | ---------------------- | ---------- | ------------------------------------------ |
802
+ | `--st-row-bg` | `#fff` | Default row background |
803
+ | `--st-row-hover-bg` | `#f5f5f5` | Row background on mouse hover |
804
+ | `--st-row-selected-bg` | `#f3e5f5` | Row background when checkbox is checked |
805
+ | `--st-first-col-color` | `#E84646` | Text colour of the first column on hover |
806
+
807
+ #### Frozen Columns
808
+
809
+ Frozen columns include the checkbox column, the first data column (when sticky), and the pinned Actions column.
810
+
811
+ | Variable | Default | Description |
812
+ | ----------------------- | ---------- | ------------------------------------------------- |
813
+ | `--st-frozen-col-bg` | `#f9f9f9` | Background of all frozen/pinned columns |
814
+ | `--st-actions-col-shadow` | `-4px 0 8px rgba(0,0,0,0.06)` | Shadow on the right-pinned Actions column |
815
+
816
+ #### Toolbar
817
+
818
+ | Variable | Default | Description |
819
+ | ------------------------- | -------------------------------- | ------------------------------------- |
820
+ | `--st-toolbar-bg` | `#fff` | Background of the toolbar bar |
821
+ | `--st-toolbar-padding` | `1.2rem 0rem` | Padding inside the toolbar |
822
+ | `--st-toolbar-border-bottom` | `1px solid rgba(0,0,0,0.08)` | Separator line below the toolbar |
823
+ | `--st-toolbar-gap` | `1rem` | Gap between search, filters, buttons |
824
+
825
+ #### Search
826
+
827
+ | Variable | Default | Description |
828
+ | ----------------------------- | ------------- | -------------------------------------------- |
829
+ | `--st-search-bg` | `#f5f5f5` | Background of the search wrapper pill |
830
+ | `--st-search-radius` | `8px` | Border radius of the search wrapper |
831
+ | `--st-search-wrapper-padding` | `0 0.875rem` | Horizontal padding inside the search wrapper |
832
+ | `--st-search-height` | `36px` | Height of the search input area |
833
+ | `--st-search-min-width` | `200px` | Minimum width of the search input |
834
+ | `--st-search-width` | `auto` | Width of the search input (overrides min) |
835
+ | `--st-search-icon-color` | `#888` | Colour of the search magnifier icon |
836
+ | `--st-search-placeholder-color` | `#999` | Placeholder text colour |
837
+
838
+ #### Filters (Trigger Button)
839
+
840
+ Each filter renders as a styled button. These variables control the trigger appearance.
841
+
842
+ | Variable | Default | Description |
843
+ | ------------------------------- | ------------------- | ------------------------------------------------ |
844
+ | `--st-filter-bg` | `#fff` | Background of the filter trigger |
845
+ | `--st-filter-border` | `1px solid #e0e0e0` | Border of the filter trigger |
846
+ | `--st-filter-radius` | `8px` | Border radius of the filter trigger |
847
+ | `--st-filter-height` | `36px` | Height of the filter trigger |
848
+ | `--st-filter-trigger-padding` | `0 0.75rem` | Horizontal padding inside the filter trigger |
849
+ | `--st-filter-font-size` | `14px` | Font size of the filter label |
850
+ | `--st-filter-color` | `#555` | Default text colour of the filter label |
851
+ | `--st-filter-hover-bg` | `#fafafa` | Background when hovering or open |
852
+ | `--st-filter-hover-border-color`| `#bbb` | Border colour on hover |
853
+ | `--st-filter-active-border-color`| `#999` | Border colour when the dropdown is open |
854
+ | `--st-filter-selected-color` | `#222` | Text colour when a value is selected |
855
+ | `--st-filter-selected-border-color` | `#333` | Border colour when a value is selected |
856
+ | `--st-filter-chevron-color` | `#999` | Colour of the chevron/arrow icon |
857
+
858
+ #### Filter Dropdown Panel
859
+
860
+ These variables style the dropdown drawer that appears when a filter is opened.
861
+
862
+ | Variable | Default | Description |
863
+ | ------------------------------- | ------------------------------------------------- | --------------------------------------------- |
864
+ | `--st-filter-panel-bg` | `#fff` | Background of the dropdown panel |
865
+ | `--st-filter-panel-border` | `1px solid #ebebeb` | Border of the dropdown panel |
866
+ | `--st-filter-panel-radius` | `12px` | Corner radius of the dropdown panel |
867
+ | `--st-filter-panel-shadow` | `0 8px 28px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.06)` | Shadow of the dropdown panel |
868
+ | `--st-filter-panel-min-width` | `180px` | Minimum width of the dropdown panel |
869
+ | `--st-filter-panel-padding` | `6px` | Inner padding of the dropdown panel |
870
+ | `--st-filter-option-padding` | `8px 12px` | Padding of each option row |
871
+ | `--st-filter-option-radius` | `7px` | Corner radius of each option row |
872
+ | `--st-filter-option-hover-bg` | `#f5f5f5` | Background of an option on hover |
873
+ | `--st-filter-option-selected-bg`| `#f0f0f0` | Background of the currently selected option |
874
+ | `--st-filter-option-selected-color` | `#111` | Text colour of the currently selected option |
875
+
876
+ #### Selection Strip
877
+
878
+ Shown above the table header when `config.selectable` is `true`. Displays "X of Y selected".
879
+
880
+ | Variable | Default | Description |
881
+ | -------------------------------- | -------------------------------- | ----------------------------------------- |
882
+ | `--st-selection-strip-bg` | `#fafafa` | Background of the selection count bar |
883
+ | `--st-selection-strip-border` | `1px solid rgba(0,0,0,0.08)` | Bottom border of the selection bar |
884
+ | `--st-selection-strip-padding` | `0.45rem 1rem` | Padding inside the selection bar |
885
+ | `--st-selection-count-color` | `#444` | Text colour of the count label |
886
+ | `--st-selection-count-font-size` | `13px` | Font size of the count label |
887
+ | `--st-selection-count-font-weight`| `500` | Font weight of the count label |
888
+
889
+ #### Checkboxes
890
+
891
+ | Variable | Default | Description |
892
+ | ------------------- | --------- | ------------------------------------ |
893
+ | `--st-checkbox-color` | `#e63e30` | Accent colour for checkboxes |
894
+ | `--st-checkbox-size` | `16px` | Width and height of checkboxes |
895
+
896
+ #### Row Action Dropdown
897
+
898
+ Styles the three-dot (ellipsis) action menu that appears in the Actions column.
899
+
900
+ | Variable | Default | Description |
901
+ | ----------------------------- | ------------------------------ | -------------------------------------------- |
902
+ | `--st-action-circle-size` | `32px` | Diameter of the three-dot trigger circle |
903
+ | `--st-dropdown-min-width` | `150px` | Minimum width of the dropdown menu |
904
+ | `--st-dropdown-bg` | `#fff` | Background of the dropdown menu |
905
+ | `--st-dropdown-border` | `1px solid #e0e0e0` | Border of the dropdown menu |
906
+ | `--st-dropdown-radius` | `8px` | Corner radius of the dropdown menu |
907
+ | `--st-dropdown-shadow` | `0 8px 24px rgba(0,0,0,0.12)` | Shadow of the dropdown menu |
908
+ | `--st-dropdown-padding` | `4px` | Inner padding of the dropdown menu container |
909
+ | `--st-dropdown-item-padding` | `8px 12px` | Padding of each menu item |
910
+ | `--st-dropdown-item-radius` | `6px` | Corner radius of each menu item |
911
+ | `--st-dropdown-item-hover-bg` | `#f5f5f5` | Background of a menu item on hover |
912
+
913
+ #### Badges
914
+
915
+ | Variable | Default | Description |
916
+ | ------------------------- | ----------- | ------------------------------------ |
917
+ | `--st-badge-radius` | `12px` | Border radius of badge pills |
918
+ | `--st-badge-padding` | `4px 12px` | Padding inside badge pills |
919
+ | `--st-badge-font-size` | `12px` | Font size of badge text |
920
+ | `--st-badge-font-weight` | `500` | Font weight of badge text |
921
+ | `--st-badge-success-bg` | `#e8f5e9` | Background — `success` variant |
922
+ | `--st-badge-success-color`| `#2e7d32` | Text colour — `success` variant |
923
+ | `--st-badge-warning-bg` | `#fff3e0` | Background — `warning` variant |
924
+ | `--st-badge-warning-color`| `#ef6c00` | Text colour — `warning` variant |
925
+ | `--st-badge-danger-bg` | `#ffebee` | Background — `danger` variant |
926
+ | `--st-badge-danger-color` | `#c62828` | Text colour — `danger` variant |
927
+ | `--st-badge-info-bg` | `#e3f2fd` | Background — `info` variant |
928
+ | `--st-badge-info-color` | `#1565c0` | Text colour — `info` variant |
929
+ | `--st-badge-neutral-bg` | `#f5f5f5` | Background — `neutral` variant |
930
+ | `--st-badge-neutral-color`| `#616161` | Text colour — `neutral` variant |
931
+
932
+ #### Scrollbar
933
+
934
+ | Variable | Default | Description |
935
+ | ------------------------------- | --------- | -------------------------------------- |
936
+ | `--st-scrollbar-width` | `8px` | Width of the horizontal scrollbar |
937
+ | `--st-scrollbar-height` | `8px` | Height of the horizontal scrollbar |
938
+ | `--st-scrollbar-track-bg` | `#f1f1f1` | Scrollbar track background |
939
+ | `--st-scrollbar-track-radius` | `4px` | Scrollbar track corner radius |
940
+ | `--st-scrollbar-thumb-bg` | `#c1c1c1` | Scrollbar thumb colour |
941
+ | `--st-scrollbar-thumb-radius` | `4px` | Scrollbar thumb corner radius |
942
+ | `--st-scrollbar-thumb-hover-bg` | `#a8a8a8` | Scrollbar thumb colour on hover |
943
+
944
+ #### Sticky Columns
945
+
946
+ | Variable | Default | Description |
947
+ | ------------------------ | ----------------------------- | ------------------------------------ |
948
+ | `--st-sticky-shadow` | `2px 0 5px -2px rgba(0,0,0,0.1)` | Shadow cast by sticky columns |
949
+ | `--st-sticky-border-right` | `1px solid rgba(0,0,0,0.05)` | Right border of sticky columns |
950
+
951
+ #### Loader & Misc
952
+
953
+ | Variable | Default | Description |
954
+ | -------------------------- | -------------------------- | ---------------------------------- |
955
+ | `--st-loader-color` | `#6200EE` | Spinner border colour |
956
+ | `--st-spinner-border-color`| `rgba(0,0,0,0.1)` | Spinner track colour |
957
+ | `--st-no-data-color` | `#888` | Colour of the "No data" message |
958
+ | `--st-sort-icon-size` | `0.8em` | Size of the column sort icon |
959
+ | `--st-pagination-padding` | `0.75rem 0` | Padding around the pagination bar |
960
+
961
+ ---
962
+
963
+ ### Using the Theme Mixin
964
+
965
+ The SCSS mixin in `smart-table.theme.scss` is the recommended way to set multiple variables at once. Pass a map of keys to override — unspecified keys fall back to the defaults above.
966
+
967
+ ```scss
968
+ @use "commons-shared-web-ui/src/lib/modules/smart-table/smart-table.theme" as smart-table;
969
+ @use "commons-shared-web-ui/src/lib/modules/pagination/pagination.theme" as pagination;
970
+ @use "commons-shared-web-ui/src/lib/modules/button/button.theme" as button;
971
+
972
+ :root {
973
+ // Required peer themes
974
+ @include pagination.pagination-theme();
975
+ @include button.button-theme();
976
+
977
+ // Smart Table — only override what you need
978
+ @include smart-table.smart-table-theme((
979
+ header-bg: #1a1a2e,
980
+ header-color: #ffffff,
981
+ row-hover-bg: #f0f4ff,
982
+ search-bg: #ececec,
983
+ filter-panel-radius: 16px,
984
+ loader-color: #0d6efd,
985
+ checkbox-color: #0d6efd,
986
+ ));
987
+ }
988
+ ```
989
+
990
+ #### Full Mixin Key Reference
991
+
992
+ All keys accepted by `smart-table-theme()` and their default values:
993
+
994
+ | Mixin Key | Default | CSS Variable Emitted |
995
+ | ------------------------------ | -------------------------------- | ----------------------------------------- |
996
+ | `font-family` | `('Roboto', sans-serif)` | `--st-font-family` |
997
+ | `font-size` | `14px` | `--st-font-size` |
998
+ | `text-color` | `#333333` | `--st-text-color` |
999
+ | `border-radius` | `8px` | `--st-border-radius` |
1000
+ | `box-shadow` | `0 2px 8px rgba(0,0,0,0.08)` | `--st-box-shadow` |
1001
+ | `table-bg` | `#ffffff` | `--st-table-bg` |
1002
+ | `table-padding` | `1rem` | `--st-table-padding` |
1003
+ | `cell-padding` | `1rem` | `--st-cell-padding` |
1004
+ | `table-border` | `1px solid #e0e0e0` | `--st-table-border` |
1005
+ | `row-border` | `1px solid #f0f0f0` | `--st-row-border` |
1006
+ | `row-bg` | `#ffffff` | `--st-row-bg` |
1007
+ | `row-hover-bg` | `#f9f9f9` | `--st-row-hover-bg` |
1008
+ | `row-selected-bg` | `#f3e5f5` | `--st-row-selected-bg` |
1009
+ | `header-bg` | `#f5f5f5` | `--st-header-bg` |
1010
+ | `header-color` | `#333333` | `--st-header-color` |
1011
+ | `header-font-weight` | `500` | `--st-header-weight` |
1012
+ | `header-font-size` | `14px` | `--st-header-size` |
1013
+ | `header-transform` | `none` | `--st-header-transform` |
1014
+ | `toolbar-bg` | `#ffffff` | `--st-toolbar-bg` |
1015
+ | `toolbar-padding` | `1.2rem 0rem` | `--st-toolbar-padding` |
1016
+ | `toolbar-border-bottom` | `1px solid rgba(0,0,0,0.08)` | `--st-toolbar-border-bottom` |
1017
+ | `toolbar-gap` | `1rem` | `--st-toolbar-gap` |
1018
+ | `search-bg` | `#f5f5f5` | `--st-search-bg` |
1019
+ | `search-radius` | `8px` | `--st-search-radius` |
1020
+ | `search-wrapper-padding` | `0 0.875rem` | `--st-search-wrapper-padding` |
1021
+ | `search-height` | `36px` | `--st-search-height` |
1022
+ | `search-min-width` | `200px` | `--st-search-min-width` |
1023
+ | `search-width` | `auto` | `--st-search-width` |
1024
+ | `search-icon-color` | `#888` | `--st-search-icon-color` |
1025
+ | `search-placeholder-color` | `#999` | `--st-search-placeholder-color` |
1026
+ | `filter-bg` | `#ffffff` | `--st-filter-bg` |
1027
+ | `filter-border` | `1px solid #e0e0e0` | `--st-filter-border` |
1028
+ | `filter-radius` | `8px` | `--st-filter-radius` |
1029
+ | `filter-height` | `36px` | `--st-filter-height` |
1030
+ | `filter-trigger-padding` | `0 0.75rem` | `--st-filter-trigger-padding` |
1031
+ | `filter-font-size` | `14px` | `--st-filter-font-size` |
1032
+ | `filter-color` | `#555` | `--st-filter-color` |
1033
+ | `filter-hover-bg` | `#fafafa` | `--st-filter-hover-bg` |
1034
+ | `filter-hover-border-color` | `#bbb` | `--st-filter-hover-border-color` |
1035
+ | `filter-active-border-color` | `#999` | `--st-filter-active-border-color` |
1036
+ | `filter-selected-color` | `#222` | `--st-filter-selected-color` |
1037
+ | `filter-selected-border-color` | `#333` | `--st-filter-selected-border-color` |
1038
+ | `filter-chevron-color` | `#999` | `--st-filter-chevron-color` |
1039
+ | `filter-panel-bg` | `#ffffff` | `--st-filter-panel-bg` |
1040
+ | `filter-panel-border` | `1px solid #ebebeb` | `--st-filter-panel-border` |
1041
+ | `filter-panel-radius` | `12px` | `--st-filter-panel-radius` |
1042
+ | `filter-panel-shadow` | `0 8px 28px rgba(0,0,0,0.12)...` | `--st-filter-panel-shadow` |
1043
+ | `filter-panel-min-width` | `180px` | `--st-filter-panel-min-width` |
1044
+ | `filter-panel-padding` | `6px` | `--st-filter-panel-padding` |
1045
+ | `filter-option-padding` | `8px 12px` | `--st-filter-option-padding` |
1046
+ | `filter-option-radius` | `7px` | `--st-filter-option-radius` |
1047
+ | `filter-option-hover-bg` | `#f5f5f5` | `--st-filter-option-hover-bg` |
1048
+ | `filter-option-selected-bg` | `#f0f0f0` | `--st-filter-option-selected-bg` |
1049
+ | `filter-option-selected-color` | `#111` | `--st-filter-option-selected-color` |
1050
+ | `frozen-col-bg` | `#f9f9f9` | `--st-frozen-col-bg` |
1051
+ | `actions-col-shadow` | `-4px 0 8px rgba(0,0,0,0.06)` | `--st-actions-col-shadow` |
1052
+ | `action-circle-size` | `32px` | `--st-action-circle-size` |
1053
+ | `dropdown-min-width` | `150px` | `--st-dropdown-min-width` |
1054
+ | `dropdown-bg` | `#ffffff` | `--st-dropdown-bg` |
1055
+ | `dropdown-border` | `1px solid #e0e0e0` | `--st-dropdown-border` |
1056
+ | `dropdown-radius` | `8px` | `--st-dropdown-radius` |
1057
+ | `dropdown-shadow` | `0 8px 24px rgba(0,0,0,0.12)` | `--st-dropdown-shadow` |
1058
+ | `dropdown-padding` | `4px` | `--st-dropdown-padding` |
1059
+ | `dropdown-item-padding` | `8px 12px` | `--st-dropdown-item-padding` |
1060
+ | `dropdown-item-radius` | `6px` | `--st-dropdown-item-radius` |
1061
+ | `dropdown-item-hover-bg` | `#f5f5f5` | `--st-dropdown-item-hover-bg` |
1062
+ | `selection-strip-bg` | `#fafafa` | `--st-selection-strip-bg` |
1063
+ | `selection-strip-border` | `1px solid rgba(0,0,0,0.08)` | `--st-selection-strip-border` |
1064
+ | `selection-strip-padding` | `0.45rem 1rem` | `--st-selection-strip-padding` |
1065
+ | `selection-count-color` | `#444` | `--st-selection-count-color` |
1066
+ | `selection-count-font-size` | `13px` | `--st-selection-count-font-size` |
1067
+ | `selection-count-font-weight` | `500` | `--st-selection-count-font-weight` |
1068
+ | `checkbox-color` | `#e63e30` | `--st-checkbox-color` |
1069
+ | `checkbox-size` | `16px` | `--st-checkbox-size` |
1070
+ | `badge-radius` | `12px` | `--st-badge-radius` |
1071
+ | `badge-padding` | `4px 12px` | `--st-badge-padding` |
1072
+ | `badge-font-size` | `12px` | `--st-badge-font-size` |
1073
+ | `badge-font-weight` | `500` | `--st-badge-font-weight` |
1074
+ | `badge-success-bg` | `#e8f5e9` | `--st-badge-success-bg` |
1075
+ | `badge-success-color` | `#2e7d32` | `--st-badge-success-color` |
1076
+ | `badge-warning-bg` | `#fff3e0` | `--st-badge-warning-bg` |
1077
+ | `badge-warning-color` | `#ef6c00` | `--st-badge-warning-color` |
1078
+ | `badge-danger-bg` | `#ffebee` | `--st-badge-danger-bg` |
1079
+ | `badge-danger-color` | `#c62828` | `--st-badge-danger-color` |
1080
+ | `badge-info-bg` | `#e3f2fd` | `--st-badge-info-bg` |
1081
+ | `badge-info-color` | `#1565c0` | `--st-badge-info-color` |
1082
+ | `badge-neutral-bg` | `#f5f5f5` | `--st-badge-neutral-bg` |
1083
+ | `badge-neutral-color` | `#616161` | `--st-badge-neutral-color` |
1084
+ | `scrollbar-width` | `8px` | `--st-scrollbar-width` |
1085
+ | `scrollbar-height` | `8px` | `--st-scrollbar-height` |
1086
+ | `scrollbar-track-bg` | `#f1f1f1` | `--st-scrollbar-track-bg` |
1087
+ | `scrollbar-track-radius` | `4px` | `--st-scrollbar-track-radius` |
1088
+ | `scrollbar-thumb-bg` | `#c1c1c1` | `--st-scrollbar-thumb-bg` |
1089
+ | `scrollbar-thumb-radius` | `4px` | `--st-scrollbar-thumb-radius` |
1090
+ | `scrollbar-thumb-hover-bg` | `#a8a8a8` | `--st-scrollbar-thumb-hover-bg` |
1091
+ | `sticky-shadow` | `2px 0 5px -2px rgba(0,0,0,0.1)`| `--st-sticky-shadow` |
1092
+ | `sticky-border-right` | `1px solid rgba(0,0,0,0.05)` | `--st-sticky-border-right` |
1093
+ | `loader-color` | `#6200EE` | `--st-loader-color` |
1094
+ | `spinner-border-color` | `rgba(0,0,0,0.1)` | `--st-spinner-border-color` |
1095
+ | `no-data-color` | `#888888` | `--st-no-data-color` |
1096
+ | `sort-icon-size` | `0.8em` | `--st-sort-icon-size` |
1097
+ ## Inline Row Editing & Addition
1098
+
1099
+ The `SmartTableComponent` supports **inline row editing** and **inline row creation**. This allows developers to let users edit cells or add new items directly inside the table row interface rather than using full-page forms or modals.
1100
+
1101
+ This feature is completely opt-in and backward-compatible.
1102
+
1103
+ ### 1. Column Configuration (`TableColumn`)
1104
+
1105
+ To make a column editable, configure the following properties in its `TableColumn` definition:
1106
+
1107
+ | Property | Type | Description |
1108
+ | :--- | :--- | :--- |
1109
+ | `editable` | `boolean` | Determines if the column input is enabled or disabled when the row enters edit mode. |
1110
+ | `dataType` | `'text' \| 'number' \| 'date' \| 'email' \| 'select'` | The input type to render when the row is in edit mode. Note: `'date'` renders Angular Material's `mat-datepicker`. |
1111
+ | `options` | `TableOption[]` | Options array used if `dataType` is `'select'`. |
1112
+ | `subFields` | `TableColumnSubField[]` | Configures multiple stacked inputs inside a single cell (e.g. combined Phone & Email in a `CONTACT` column). |
1113
+ | `editConfig` | `{ disabled?: boolean; defaultValue?: any }` | Configures default patched values and disable states for inputs in editing rows. |
1114
+
1115
+ #### `TableColumnSubField` Schema
1116
+ ```typescript
1117
+ export interface TableColumnSubField {
1118
+ key: string;
1119
+ label?: string;
1120
+ dataType: 'text' | 'number' | 'email' | 'select' | 'date';
1121
+ placeholder?: string;
1122
+ editable?: boolean;
1123
+ options?: TableOption[];
1124
+ editConfig?: {
1125
+ disabled?: boolean;
1126
+ defaultValue?: any;
1127
+ };
1128
+ }
1129
+ ```
1130
+
1131
+ ### 2. Table Configurations (`TableConfig`)
1132
+
1133
+ We can configure inline edit row styling using the optional `editingRowClass` property:
1134
+
1135
+ | Property | Type | Description |
1136
+ | :--- | :--- | :--- |
1137
+ | `editingRowClass` | `string` | An optional CSS class name to apply to rows currently being edited or added. |
1138
+
1139
+ ### 3. Row Actions & Top Bar Actions
1140
+
1141
+ To trigger row addition or editing, use the following action types:
1142
+
1143
+ * **`add-row`** (typically in `topBarButtons`): Prepends a new blank row with `id` / `rowIdField` set to `0` and populates any `defaultValue` rules.
1144
+ * **`edit-row`** (typically in `actions`): Caches the row's values and switches it to editing state.
1145
+
1146
+ When a row enters edit mode, the component automatically displays **Cancel** and **Save** (or **Add Student** for new rows) buttons instead of the standard dropdown kebab menu.
1147
+
1148
+ ### 4. Integration Modes
1149
+
1150
+ #### A. Internal API Mode (Self-Managed)
1151
+ If your table is configured with an `apiUrl`, saving operations are handled automatically:
1152
+ * **Adding a Row**: Submits a `POST` request to `config.apiUrl` with the row values.
1153
+ * **Editing a Row**: Submits a `PUT` request (or configured `apiMethod`) to `config.apiUrl/:id`.
1154
+ * **Cancel**: Discards the new row or restores the original values from local cache.
1155
+ * The component automatically cleans helper properties (`isEditing`, `isNew`, `selected`) before submitting payloads.
1156
+
1157
+ #### B. External Data Mode (Parent-Managed)
1158
+ If you supply data via `[tableData]`, listen to the `(rowSave)` emitter in the parent template.
1159
+
1160
+ ##### HTML Template
1161
+ ```html
1162
+ <lib-smart-table
1163
+ [config]="tableConfig"
1164
+ [tableData]="studentsList"
1165
+ [totalItemsCount]="totalStudents"
1166
+ (rowSave)="onSaveStudent($event)">
1167
+ </lib-smart-table>
1168
+ ```
1169
+
1170
+ ##### TypeScript Controller
1171
+ ```typescript
1172
+ import { TableRowSaveEvent } from 'commons-shared-web-ui';
1173
+
1174
+ onSaveStudent(event: TableRowSaveEvent): void {
1175
+ const { row, isNew } = event;
1176
+
1177
+ if (isNew) {
1178
+ this.apiService.create(row).subscribe(() => this.reloadList());
1179
+ } else {
1180
+ this.apiService.update(row.id, row).subscribe(() => this.reloadList());
1181
+ }
1182
+ }
1183
+ ```
1184
+
1185
+ ### 5. CSS Theming Variables
1186
+
1187
+ The inline inputs and selectors are themed via CSS custom variables. You can override these variables globally in `global.scss` or inside `@mixin smart-table-theme`:
1188
+
1189
+ ```scss
1190
+ :root {
1191
+ /* Mirror variable overrides */
1192
+ --st-cell-input-border: 1px solid #dee2e6;
1193
+ --st-cell-input-focus-outline-color: #c21e25;
1194
+ --st-cell-input-bg: #fcfcfc;
1195
+ --st-cell-select-bg: #fcfcfc;
1196
+ }
1197
+ ```
1198
+
1199
+ ### 6. Date Field Handling (`mat-datepicker`)
1200
+
1201
+ When a column or subfield has `dataType` configured as `'date'`:
1202
+ * **Component Rendering**: Instead of a native HTML input, the table renders an input with Angular Material's `mat-datepicker` along with a calendar toggle icon.
1203
+ * **User Interaction**: Users can select a date using the calendar picker popup or enter/edit it manually.
1204
+ * **Automatic Date Conversions**:
1205
+ * **On Edit Mode**: When a row transitions to edit mode, the component parses the date value (ISO string or timestamp) to a native JavaScript `Date` object to bind it correctly to the datepicker.
1206
+ * **On Save Mode**: When saving/submitting, the component automatically converts the native `Date` object back to an ISO 8601 string (`.toISOString()`) to keep backend communication clean and standard.
1207
+
1208
+ ---
1209
+
1210
+ ## Utility Functions
1211
+
1212
+ ### `appendBaseUrlRecursively`
1213
+
1214
+ The `appendBaseUrlRecursively(obj: any, baseURL: string)` utility function allows you to recursively append a base URL to any `apiUrl` property found within a configuration object (or any object). This is particularly useful when you have a complex `TableConfig` (with nested actions, filters, pagination counts, etc.) and you want to define relative API paths in your config, but prepend a common environment base URL before passing the configuration to the Smart Table.
1215
+
1216
+ #### Usage Example
1217
+
1218
+ ```typescript
1219
+ import { TableConfig, appendBaseUrlRecursively } from "commons-shared-web-ui";
1220
+
1221
+ export class MyComponent {
1222
+ tableConfig: TableConfig = {
1223
+ apiUrl: "/users", // Relative path
1224
+ columns: [
1225
+ { key: "id", label: "ID", type: "number", sortable: true },
1226
+ { key: "name", label: "Name", type: "text", sortable: true },
1227
+ ],
1228
+ filters: [
1229
+ {
1230
+ key: "status",
1231
+ label: "Status",
1232
+ type: "select",
1233
+ apiUrl: "/ref-data/status" // Relative path
1234
+ }
1235
+ ],
1236
+ actions: [
1237
+ {
1238
+ label: "Delete",
1239
+ type: "api",
1240
+ apiUrl: "/users/:id", // Relative path
1241
+ apiMethod: "DELETE"
1242
+ }
1243
+ ]
1244
+ };
1245
+
1246
+ constructor() {
1247
+ const environmentBaseUrl = "https://api.example.com";
1248
+
1249
+ // This will recursively update all `apiUrl` properties in the config
1250
+ // - config.apiUrl becomes "https://api.example.com/users"
1251
+ // - config.filters[0].apiUrl becomes "https://api.example.com/ref-data/status"
1252
+ // - config.actions[0].apiUrl becomes "https://api.example.com/users/:id"
1253
+ appendBaseUrlRecursively(this.tableConfig, environmentBaseUrl);
1254
+ }
1255
+ }
1256
+ ```
1257
+
1258
+ ## Authentication & Interceptors
1259
+
1260
+ The `SmartTableComponent` makes HTTP requests using Angular's `HttpClient`. It does **not** provide its own `HttpClient` instance. Instead, it relies on the `HttpClient` provided by the consuming application (e.g., your Shell or Remote MFE).
1261
+
1262
+ This means that any interceptors configured in your application's root module (using `provideHttpClient(withInterceptors([...]))` or `HTTP_INTERCEPTORS`) will **automatically** intercept and handle requests made by the table.
1263
+
1264
+ To add authentication tokens:
1265
+ 1. Ensure your Shell/Host app provides `HttpClient` with your auth interceptor.
1266
+ 2. Ensure `@angular/common/http` is shared as a singleton in your Module Federation config (`federation.config.js`).
1267
+
1268
+ The table will then automatically use your authenticated `HttpClient`.
1269
+
1270
+ ### Example Interceptor Setup (in App Module)
1271
+
1272
+ ```typescript
1273
+ bootstrapApplication(AppComponent, {
1274
+ providers: [
1275
+ provideHttpClient(
1276
+ withInterceptors([authInterceptor])
1277
+ )
1278
+ ]
1279
+ });
1280
+ ````
1281
+
1282
+ ### Manual Token Configuration
1283
+
1284
+ If you need to bypass default interceptors or provide a specific token for the table's API calls, you can pass a `token` and optionally a `tokenHeader` in the `TableConfig`.
1285
+
1286
+ ```typescript
1287
+ tableConfig: TableConfig = {
1288
+ apiUrl: "...",
1289
+ // Pass the FULL token string including prefix (e.g. Bearer)
1290
+ token: "Bearer eyJhbGc...",
1291
+ // Optional: Custom header key (defaults to 'Authorization' if omitted)
1292
+ tokenHeader: "X-Custom-Auth",
1293
+ // ...
1294
+ };
1295
+ ```
1296
+
1297
+ This token will be added to the request headers exactly as provided. If `tokenHeader` is not specified, it defaults to `Authorization`.