platformcommons-web-lib 1.0.0

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 (208) hide show
  1. package/commons-shared-web-ui-1.0.0.tgz +0 -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 +597 -0
  11. package/documentation/form-components.md +384 -0
  12. package/documentation/nav.md +427 -0
  13. package/documentation/pagination.md +181 -0
  14. package/documentation/side-nav-documentation.md +169 -0
  15. package/documentation/smart-form.md +2177 -0
  16. package/documentation/smart-table.md +1198 -0
  17. package/documentation/snackbar.md +118 -0
  18. package/documentation/style-externalization.md +88 -0
  19. package/documentation/summary-card.md +279 -0
  20. package/ng-package.json +28 -0
  21. package/package.json +54 -0
  22. package/src/lib/modules/alert/alert.models.ts +6 -0
  23. package/src/lib/modules/alert/alert.module.ts +16 -0
  24. package/src/lib/modules/alert/alert.theme.scss +85 -0
  25. package/src/lib/modules/alert/components/alert/alert.component.html +27 -0
  26. package/src/lib/modules/alert/components/alert/alert.component.scss +92 -0
  27. package/src/lib/modules/alert/components/alert/alert.component.ts +81 -0
  28. package/src/lib/modules/button/button.models.ts +13 -0
  29. package/src/lib/modules/button/button.module.ts +16 -0
  30. package/src/lib/modules/button/button.theme.scss +121 -0
  31. package/src/lib/modules/button/components/button/button.component.html +22 -0
  32. package/src/lib/modules/button/components/button/button.component.scss +88 -0
  33. package/src/lib/modules/button/components/button/button.component.ts +67 -0
  34. package/src/lib/modules/button-dropdown/button-dropdown.models.ts +26 -0
  35. package/src/lib/modules/button-dropdown/button-dropdown.module.ts +22 -0
  36. package/src/lib/modules/button-dropdown/button-dropdown.theme.scss +87 -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/configurable-form/configurable-form.theme.scss +78 -0
  47. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.html +77 -0
  48. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.scss +395 -0
  49. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.ts +266 -0
  50. package/src/lib/modules/confirmation-modal/confirmation-modal.models.ts +71 -0
  51. package/src/lib/modules/confirmation-modal/confirmation-modal.module.ts +20 -0
  52. package/src/lib/modules/confirmation-modal/confirmation-modal.theme.scss +87 -0
  53. package/src/lib/modules/filter/components/filter/filter.component.html +131 -0
  54. package/src/lib/modules/filter/components/filter/filter.component.scss +245 -0
  55. package/src/lib/modules/filter/components/filter/filter.component.ts +216 -0
  56. package/src/lib/modules/filter/filter.models.ts +88 -0
  57. package/src/lib/modules/filter/filter.module.ts +24 -0
  58. package/src/lib/modules/filter/filter.theme.scss +92 -0
  59. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.html +112 -0
  60. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.scss +186 -0
  61. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.ts +163 -0
  62. package/src/lib/modules/filter-sidebar/filter-sidebar.models.ts +95 -0
  63. package/src/lib/modules/filter-sidebar/filter-sidebar.module.ts +24 -0
  64. package/src/lib/modules/filter-sidebar/filter-sidebar.theme.scss +38 -0
  65. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.html +73 -0
  66. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.scss +321 -0
  67. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.ts +361 -0
  68. package/src/lib/modules/filter-table-selector/filter-table-selector.models.ts +91 -0
  69. package/src/lib/modules/filter-table-selector/filter-table-selector.module.ts +22 -0
  70. package/src/lib/modules/filter-table-selector/filter-table-selector.theme.scss +36 -0
  71. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.html +63 -0
  72. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.scss +496 -0
  73. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.ts +445 -0
  74. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.html +75 -0
  75. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.scss +210 -0
  76. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.ts +55 -0
  77. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.html +25 -0
  78. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.scss +82 -0
  79. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.ts +95 -0
  80. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.html +20 -0
  81. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.scss +37 -0
  82. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.ts +94 -0
  83. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.html +46 -0
  84. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.scss +102 -0
  85. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.ts +50 -0
  86. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.html +35 -0
  87. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.scss +67 -0
  88. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.ts +34 -0
  89. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.html +68 -0
  90. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.scss +113 -0
  91. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.ts +74 -0
  92. package/src/lib/modules/form-builder/configs/field-type-schema.map.ts +533 -0
  93. package/src/lib/modules/form-builder/form-builder.module.ts +36 -0
  94. package/src/lib/modules/form-builder/form-builder.theme.scss +212 -0
  95. package/src/lib/modules/form-builder/index.ts +9 -0
  96. package/src/lib/modules/form-builder/models/builder.models.ts +7 -0
  97. package/src/lib/modules/form-builder/models/field-configurator.models.ts +38 -0
  98. package/src/lib/modules/form-builder/models/field-selection.models.ts +51 -0
  99. package/src/lib/modules/form-builder/services/field-configurator.service.ts +258 -0
  100. package/src/lib/modules/form-builder/services/field-selection.service.ts +300 -0
  101. package/src/lib/modules/form-builder/services/form-schema-tree.service.ts +652 -0
  102. package/src/lib/modules/form-builder/tokens/builder.tokens.ts +10 -0
  103. package/src/lib/modules/form-builder/utils/constants.ts +43 -0
  104. package/src/lib/modules/form-components/components/checkbox/_theme.scss +63 -0
  105. package/src/lib/modules/form-components/components/checkbox/checkbox.component.html +29 -0
  106. package/src/lib/modules/form-components/components/checkbox/checkbox.component.scss +111 -0
  107. package/src/lib/modules/form-components/components/checkbox/checkbox.component.ts +207 -0
  108. package/src/lib/modules/form-components/components/checkbox/checkbox.models.ts +35 -0
  109. package/src/lib/modules/form-components/components/datepicker/_theme.scss +82 -0
  110. package/src/lib/modules/form-components/components/datepicker/datepicker.component.html +42 -0
  111. package/src/lib/modules/form-components/components/datepicker/datepicker.component.scss +115 -0
  112. package/src/lib/modules/form-components/components/datepicker/datepicker.component.ts +267 -0
  113. package/src/lib/modules/form-components/components/datepicker/datepicker.models.ts +45 -0
  114. package/src/lib/modules/form-components/components/dropdown/_theme.scss +91 -0
  115. package/src/lib/modules/form-components/components/dropdown/dropdown.component.html +74 -0
  116. package/src/lib/modules/form-components/components/dropdown/dropdown.component.scss +252 -0
  117. package/src/lib/modules/form-components/components/dropdown/dropdown.component.ts +377 -0
  118. package/src/lib/modules/form-components/components/dropdown/dropdown.models.ts +53 -0
  119. package/src/lib/modules/form-components/components/input/_theme.scss +77 -0
  120. package/src/lib/modules/form-components/components/input/input.component.html +51 -0
  121. package/src/lib/modules/form-components/components/input/input.component.scss +128 -0
  122. package/src/lib/modules/form-components/components/input/input.component.ts +250 -0
  123. package/src/lib/modules/form-components/components/input/input.models.ts +55 -0
  124. package/src/lib/modules/form-components/components/radio/_theme.scss +61 -0
  125. package/src/lib/modules/form-components/components/radio/radio.component.html +22 -0
  126. package/src/lib/modules/form-components/components/radio/radio.component.scss +107 -0
  127. package/src/lib/modules/form-components/components/radio/radio.component.ts +181 -0
  128. package/src/lib/modules/form-components/components/radio/radio.models.ts +39 -0
  129. package/src/lib/modules/form-components/components/search/_theme.scss +73 -0
  130. package/src/lib/modules/form-components/components/search/search.component.html +15 -0
  131. package/src/lib/modules/form-components/components/search/search.component.scss +87 -0
  132. package/src/lib/modules/form-components/components/search/search.component.ts +213 -0
  133. package/src/lib/modules/form-components/components/search/search.models.ts +40 -0
  134. package/src/lib/modules/form-components/components/toggle/_theme.scss +45 -0
  135. package/src/lib/modules/form-components/components/toggle/toggle.component.html +15 -0
  136. package/src/lib/modules/form-components/components/toggle/toggle.component.scss +81 -0
  137. package/src/lib/modules/form-components/components/toggle/toggle.component.ts +166 -0
  138. package/src/lib/modules/form-components/components/toggle/toggle.models.ts +27 -0
  139. package/src/lib/modules/form-components/directives/click-outside.directive.ts +22 -0
  140. package/src/lib/modules/form-components/form-components.module.ts +41 -0
  141. package/src/lib/modules/form-components/form-components.theme.scss +25 -0
  142. package/src/lib/modules/material/material.module.ts +94 -0
  143. package/src/lib/modules/nav/components/nav/nav.component.html +34 -0
  144. package/src/lib/modules/nav/components/nav/nav.component.scss +171 -0
  145. package/src/lib/modules/nav/components/nav/nav.component.ts +82 -0
  146. package/src/lib/modules/nav/nav.models.ts +31 -0
  147. package/src/lib/modules/nav/nav.module.ts +17 -0
  148. package/src/lib/modules/nav/nav.theme.scss +86 -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/pagination/pagination.theme.scss +66 -0
  154. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.html +56 -0
  155. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.scss +342 -0
  156. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.ts +135 -0
  157. package/src/lib/modules/side-nav/side-nav.models.ts +38 -0
  158. package/src/lib/modules/side-nav/side-nav.module.ts +16 -0
  159. package/src/lib/modules/side-nav/side-nav.theme.scss +111 -0
  160. package/src/lib/modules/smart-form/components/form-field/form-field.component.html +1109 -0
  161. package/src/lib/modules/smart-form/components/form-field/form-field.component.scss +1860 -0
  162. package/src/lib/modules/smart-form/components/form-field/form-field.component.ts +2232 -0
  163. package/src/lib/modules/smart-form/components/form-section/form-section.component.html +64 -0
  164. package/src/lib/modules/smart-form/components/form-section/form-section.component.scss +209 -0
  165. package/src/lib/modules/smart-form/components/form-section/form-section.component.ts +119 -0
  166. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.html +253 -0
  167. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.scss +689 -0
  168. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.ts +1087 -0
  169. package/src/lib/modules/smart-form/index.ts +10 -0
  170. package/src/lib/modules/smart-form/models/form-schema.model.ts +700 -0
  171. package/src/lib/modules/smart-form/models/hierarchy-config.model.ts +21 -0
  172. package/src/lib/modules/smart-form/services/expression.service.ts +75 -0
  173. package/src/lib/modules/smart-form/services/smart-form-controller.service.ts +65 -0
  174. package/src/lib/modules/smart-form/smart-form.examples.ts +1324 -0
  175. package/src/lib/modules/smart-form/smart-form.module.ts +36 -0
  176. package/src/lib/modules/smart-form/smart-form.theme.scss +890 -0
  177. package/src/lib/modules/smart-form/utils/translation.utils.ts +82 -0
  178. package/src/lib/modules/smart-form/utils/trusted-url.pipe.ts +25 -0
  179. package/src/lib/modules/smart-form/utils/validation.utils.ts +98 -0
  180. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.html +283 -0
  181. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.scss +685 -0
  182. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.ts +1118 -0
  183. package/src/lib/modules/smart-table/models/table-config.model.ts +202 -0
  184. package/src/lib/modules/smart-table/smart-table.module.ts +30 -0
  185. package/src/lib/modules/smart-table/smart-table.theme.scss +335 -0
  186. package/src/lib/modules/smart-table/utils/safe-html.pipe.ts +22 -0
  187. package/src/lib/modules/smart-table/utils/smart-table.utils.ts +18 -0
  188. package/src/lib/modules/snackbar/components/snackbar.component.html +41 -0
  189. package/src/lib/modules/snackbar/components/snackbar.component.scss +99 -0
  190. package/src/lib/modules/snackbar/components/snackbar.component.ts +18 -0
  191. package/src/lib/modules/snackbar/models/snackbar.models.ts +10 -0
  192. package/src/lib/modules/snackbar/services/snackbar.service.ts +40 -0
  193. package/src/lib/modules/snackbar/snackbar.module.ts +11 -0
  194. package/src/lib/modules/snackbar/snackbar.theme.scss +93 -0
  195. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.html +47 -0
  196. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.scss +199 -0
  197. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.ts +126 -0
  198. package/src/lib/modules/summary-card/summary-card.module.ts +18 -0
  199. package/src/lib/modules/summary-card/summary-card.theme.scss +176 -0
  200. package/src/lib/shared-ui.module.ts +44 -0
  201. package/src/lib/styles/global.scss +152 -0
  202. package/src/lib/styles/utilities.scss +250 -0
  203. package/src/lib/utils/constants.ts +11 -0
  204. package/src/lib/utils/storage.utils.ts +37 -0
  205. package/src/lib/utils/string.utils.ts +23 -0
  206. package/src/lib/utils/translation.utils.ts +87 -0
  207. package/src/public-api.ts +104 -0
  208. package/tsconfig.lib.json +15 -0
@@ -0,0 +1,91 @@
1
+ import { FormSchema } from '../smart-form/models/form-schema.model';
2
+ import { TableConfig } from '../smart-table/models/table-config.model';
3
+
4
+ /**
5
+ * Maps a SmartForm field name to its corresponding API query-param key.
6
+ */
7
+ export interface FilterParamMap {
8
+ /** Field name as declared in sectionConfig.children (e.g. "country") */
9
+ formFieldName: string;
10
+ /** Actual query-param key sent to the table API (e.g. "currentCountryCode") */
11
+ apiParamKey: string;
12
+ }
13
+
14
+ /**
15
+ * Configuration for the left-hand filter panel (powered by SmartForm).
16
+ */
17
+ export interface FilterPanelConfig {
18
+ /** Full SmartForm JSON schema (entityType, sectionConfig, actionBarConfig, etc.) */
19
+ smartFormConfig: FormSchema;
20
+ /** Maps each form field to the API query-param that the table expects */
21
+ filterParamMapping: FilterParamMap[];
22
+ /**
23
+ * Optional default values pre-filled when the component opens AND restored on Clear Filter.
24
+ * Key = formFieldName, Value = the field value.
25
+ * When provided, the initial table load will include these params.
26
+ */
27
+ defaultValues?: Record<string, any>;
28
+ /**
29
+ * List of field names that should be rendered as disabled/read-only.
30
+ * The values are still used when building API params, but users cannot change them.
31
+ * Their values are preserved when Clear Filter is triggered.
32
+ */
33
+ disabledFields?: string[];
34
+ /**
35
+ * i18n key or literal text for the "Clear Filter" button.
36
+ * Defaults to 'COMMON.FILTER_TABLE.CLEAR_FILTER'.
37
+ */
38
+ clearFilterLabel?: string;
39
+ /**
40
+ * i18n key or literal text for the "Apply Filter" button.
41
+ * Defaults to 'COMMON.FILTER_TABLE.APPLY_FILTER'.
42
+ */
43
+ applyFilterLabel?: string;
44
+ }
45
+
46
+ /**
47
+ * Controls selection behaviour and bottom action bar labels.
48
+ */
49
+ export interface SelectionConfig {
50
+ /** Allow selecting multiple rows (true = checkbox per row, false = radio). */
51
+ multiSelect: boolean;
52
+ /**
53
+ * i18n token for the "X of Y users Selected" counter.
54
+ * Use placeholders {selected} and {total}.
55
+ * Example: "COMMON.FILTER_TABLE.SELECTION_COUNT"
56
+ */
57
+ selectionCountLabel: string;
58
+ /** i18n token (or literal text) for the primary submit button. */
59
+ submitButtonLabel: string;
60
+ /** i18n token (or literal text) for the secondary cancel/back button. */
61
+ cancelButtonLabel: string;
62
+ }
63
+
64
+ /**
65
+ * Top-level configuration object for FilterTableSelectorComponent.
66
+ */
67
+ export interface FilterTableSelectorConfig {
68
+ /** Dialog / modal heading. */
69
+ title?: string;
70
+ /** Left-panel filter form configuration. */
71
+ filterConfig: FilterPanelConfig;
72
+ /**
73
+ * Right-panel table configuration.
74
+ * Extends the standard SmartTable config; `selectable` should be true.
75
+ * `multiSelect` is controlled via selectionConfig.multiSelect.
76
+ */
77
+ tableConfig: FilterTableConfig;
78
+ /** Selection behaviour and bottom action bar labels. */
79
+ selectionConfig: SelectionConfig;
80
+ }
81
+
82
+ /**
83
+ * Extended TableConfig for FilterTableSelector — adds multiSelect support.
84
+ */
85
+ export interface FilterTableConfig extends TableConfig {
86
+ /**
87
+ * When true (and selectable=true), multiple rows can be selected simultaneously.
88
+ * When false, only one row can be selected at a time (radio behaviour).
89
+ */
90
+ multiSelect?: boolean;
91
+ }
@@ -0,0 +1,22 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FilterTableSelectorComponent } from './components/filter-table-selector/filter-table-selector.component';
4
+ import { SmartFormModule } from '../smart-form/smart-form.module';
5
+ import { SmartTableModule } from '../smart-table/smart-table.module';
6
+ import { ButtonModule } from '../button/button.module';
7
+
8
+ @NgModule({
9
+ declarations: [
10
+ FilterTableSelectorComponent
11
+ ],
12
+ imports: [
13
+ CommonModule,
14
+ SmartFormModule,
15
+ SmartTableModule,
16
+ ButtonModule
17
+ ],
18
+ exports: [
19
+ FilterTableSelectorComponent
20
+ ]
21
+ })
22
+ export class FilterTableSelectorModule { }
@@ -0,0 +1,36 @@
1
+ @use 'sass:map';
2
+
3
+ $filter-table-selector-config: (
4
+ panel-bg: #ffffff,
5
+ filter-panel-width: 220px,
6
+ filter-panel-border: 1px solid #dee2e6,
7
+ header-bg: #ffffff,
8
+ header-border: 1px solid #dee2e6,
9
+ header-height: 56px,
10
+ header-padding: 0 24px,
11
+ header-title-color: #333333,
12
+ header-title-font-size: 18px,
13
+ header-title-font-weight: 600,
14
+ footer-bg: #ffffff,
15
+ footer-border: 1px solid #dee2e6,
16
+ footer-height: 64px,
17
+ footer-padding: 0 24px,
18
+ footer-gap: 12px,
19
+ body-bg: #f8f9fb,
20
+ filter-section-title-color: #666666,
21
+ filter-section-title-font-size: 12px,
22
+ filter-section-title-font-weight: 600,
23
+ selection-count-color: #666666,
24
+ selection-count-font-size: 14px,
25
+ toolbar-border: 1px solid #dee2e6,
26
+ );
27
+
28
+ @mixin filter-table-selector-theme($user-config: ()) {
29
+ $config: map.merge($filter-table-selector-config, $user-config);
30
+
31
+ :root {
32
+ @each $key, $value in $config {
33
+ --fts-#{$key}: #{$value};
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,63 @@
1
+ <div class="fb-config-panel">
2
+ @if (!selectedField) {
3
+ <div class="fb-config-panel__empty">
4
+ <div class="fb-config-panel__empty-icon">
5
+ <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor"
6
+ stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
7
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
8
+ <line x1="3" y1="9" x2="21" y2="9"/>
9
+ <line x1="9" y1="21" x2="9" y2="9"/>
10
+ </svg>
11
+ </div>
12
+ <p class="fb-config-panel__empty-text">
13
+ Select a field from the tree panel to edit its configuration.
14
+ </p>
15
+ </div>
16
+ } @else {
17
+ <div class="fb-config-panel__header">
18
+ <div class="fb-config-panel__header-left">
19
+ <h3 class="fb-config-panel__title">
20
+ {{ selectedField.label || selectedField.name || 'Field Settings' }}
21
+ </h3>
22
+ @if (selectedField.type) {
23
+ <span class="fb-config-panel__badge">{{ selectedField.type }}</span>
24
+ }
25
+ </div>
26
+
27
+ <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->
28
+ @if (!isDropdownType) {
29
+ <div class="fb-config-panel__type-switcher">
30
+ <label class="fb-config-panel__type-label" for="fb-field-type-select">Field Type</label>
31
+ <select
32
+ id="fb-field-type-select"
33
+ class="fb-config-panel__type-select"
34
+ [value]="currentBuilderType"
35
+ (change)="onTypeSelectChange($event)"
36
+ >
37
+ @for (opt of switchableFieldTypes; track opt.value) {
38
+ <option [value]="opt.value">{{ opt.label }}</option>
39
+ }
40
+ </select>
41
+ </div>
42
+ }
43
+ </div>
44
+
45
+ <div class="fb-config-panel__form-wrapper">
46
+ @if (showConfigForm && configFormJson) {
47
+ <div class="fb-config-card">
48
+ <lib-smart-form
49
+ [formJson]="configFormJson"
50
+ [initialValues]="configInitialValues"
51
+ (actionClick)="onActionClick($event)"
52
+ />
53
+ </div>
54
+ } @else if (!showConfigForm) {
55
+ <!-- intentionally empty — SmartForm is being recycled -->
56
+ } @else {
57
+ <div class="fb-config-panel__error">
58
+ No configuration schema available for this field type.
59
+ </div>
60
+ }
61
+ </div>
62
+ }
63
+ </div>
@@ -0,0 +1,496 @@
1
+ @use '../../../form-builder.theme' as theme;
2
+ @use '../../../../smart-form/smart-form.theme' as sf;
3
+
4
+ .fb-config-panel {
5
+ display: flex;
6
+ flex-direction: column;
7
+ height: 100%;
8
+ background: var(--fb-fc-panel-bg, #f9fafb);
9
+ overflow: hidden;
10
+
11
+ // Apply smart-form theme at container level so CSS variables cascade to all nested components
12
+ // This ensures lib-smart-form and form-section components receive the CSS variables
13
+ // regardless of ViewEncapsulation.Emulated boundary
14
+
15
+ // ──────────────────────────────────────────────────────────────────────────────
16
+ // RESPONSIVE THEME CONFIGURATION
17
+ // Optimized for visual hierarchy and readability across all screen sizes
18
+ // ──────────────────────────────────────────────────────────────────────────────
19
+
20
+ // Default (Mobile-First): 480px+
21
+ @include sf.smart-form-theme((
22
+ section-padding: 12px,
23
+ section-border: none,
24
+ section-shadow: none,
25
+ section-bg: transparent,
26
+ form-padding: 0,
27
+ form-bg: transparent,
28
+ form-shadow: none,
29
+ grid-gap: 12px,
30
+ label-size: 0.75rem,
31
+ label-weight: 600,
32
+ input-padding: 0.5rem 0.75rem,
33
+ ));
34
+
35
+ // Tablet Portrait (600px+): Better spacing for readability
36
+ @media (min-width: 600px) {
37
+ @include sf.smart-form-theme((
38
+ section-padding: 14px,
39
+ section-border: none,
40
+ section-shadow: none,
41
+ section-bg: transparent,
42
+ form-padding: 0,
43
+ form-bg: transparent,
44
+ form-shadow: none,
45
+ grid-gap: 14px,
46
+ label-size: 0.8rem,
47
+ label-weight: 600,
48
+ input-padding: 0.5rem 0.75rem,
49
+ ));
50
+ }
51
+
52
+ // Tablet Landscape (768px+): Balanced comfortable spacing
53
+ @media (min-width: 768px) {
54
+ @include sf.smart-form-theme((
55
+ section-padding: 16px,
56
+ section-border: none,
57
+ section-shadow: none,
58
+ section-bg: transparent,
59
+ form-padding: 0,
60
+ form-bg: transparent,
61
+ form-shadow: none,
62
+ grid-gap: 16px,
63
+ label-size: 0.8125rem,
64
+ label-weight: 600,
65
+ input-padding: 0.625rem 0.875rem,
66
+ ));
67
+ }
68
+
69
+ // Desktop (1024px+): Optimal form experience
70
+ @media (min-width: 1024px) {
71
+ @include sf.smart-form-theme((
72
+ section-padding: 16px,
73
+ section-border: none,
74
+ section-shadow: none,
75
+ section-bg: transparent,
76
+ form-padding: 0,
77
+ form-bg: transparent,
78
+ form-shadow: none,
79
+ grid-gap: 16px,
80
+ label-size: 0.8125rem,
81
+ label-weight: 600,
82
+ input-padding: 0.625rem 0.875rem,
83
+ ));
84
+ }
85
+
86
+ // Large Desktop (1440px+): Generous spacing
87
+ @media (min-width: 1440px) {
88
+ @include sf.smart-form-theme((
89
+ section-padding: 18px,
90
+ section-border: none,
91
+ section-shadow: none,
92
+ section-bg: transparent,
93
+ form-padding: 0,
94
+ form-bg: transparent,
95
+ form-shadow: none,
96
+ grid-gap: 18px,
97
+ label-size: 0.8125rem,
98
+ label-weight: 600,
99
+ input-padding: 0.625rem 0.875rem,
100
+ ));
101
+ }
102
+
103
+ // Ultra-wide (1920px+): Maximum breathing room
104
+ @media (min-width: 1920px) {
105
+ @include sf.smart-form-theme((
106
+ section-padding: 18px,
107
+ section-border: none,
108
+ section-shadow: none,
109
+ section-bg: transparent,
110
+ form-padding: 0,
111
+ form-bg: transparent,
112
+ form-shadow: none,
113
+ grid-gap: 18px,
114
+ label-size: 0.8125rem,
115
+ label-weight: 600,
116
+ input-padding: 0.625rem 0.875rem,
117
+ ));
118
+ }
119
+
120
+ &__empty {
121
+ display: flex;
122
+ flex-direction: column;
123
+ align-items: center;
124
+ justify-content: center;
125
+ height: 100%;
126
+ color: var(--fb-fc-empty-color, #9ca3af);
127
+ text-align: center;
128
+ padding: 48px 24px;
129
+
130
+ @media (max-width: 640px) {
131
+ padding: 24px 16px;
132
+ }
133
+
134
+ &-icon {
135
+ margin-bottom: 24px;
136
+ opacity: 0.4;
137
+ color: var(--fb-fc-accent, #3b82f6);
138
+
139
+ @media (max-width: 640px) {
140
+ margin-bottom: 16px;
141
+ }
142
+ }
143
+
144
+ &-text {
145
+ font-size: 15px;
146
+ max-width: 320px;
147
+ line-height: 1.6;
148
+ font-weight: 500;
149
+
150
+ @media (max-width: 640px) {
151
+ font-size: 14px;
152
+ max-width: 100%;
153
+ }
154
+ }
155
+ }
156
+
157
+ &__header {
158
+ background: var(--fb-fc-header-bg, #ffffff);
159
+ padding: 1.4rem; //20px 32px;
160
+ border-bottom: 1px solid var(--fb-fc-border, #e5e7eb);
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: space-between;
164
+ flex-shrink: 0;
165
+ gap: 16px;
166
+ flex-wrap: wrap;
167
+
168
+ @media (max-width: 768px) {
169
+ padding: 16px 24px;
170
+ gap: 12px;
171
+ }
172
+
173
+ @media (max-width: 640px) {
174
+ padding: 12px 16px;
175
+ gap: 8px;
176
+ }
177
+
178
+ &-left {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 12px;
182
+ min-width: 0;
183
+ flex-wrap: wrap;
184
+
185
+ @media (max-width: 640px) {
186
+ gap: 8px;
187
+ }
188
+ }
189
+ }
190
+
191
+ &__type-switcher {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 8px;
195
+ flex-shrink: 0;
196
+
197
+ @media (max-width: 640px) {
198
+ gap: 4px;
199
+ }
200
+ }
201
+
202
+ &__type-label {
203
+ font-size: var(--fb-fc-type-label-size, 0.75rem);
204
+ font-weight: 600;
205
+ color: var(--fb-fc-type-label-color, #6b7280);
206
+ white-space: nowrap;
207
+
208
+ @media (max-width: 640px) {
209
+ font-size: 0.7rem;
210
+ }
211
+ }
212
+
213
+ &__type-select {
214
+ height: var(--fb-fc-type-select-height, 36px);
215
+ padding: 0 32px 0 10px;
216
+ border: 1px solid var(--fb-fc-type-select-border, #d1d5db);
217
+ border-radius: var(--fb-fc-type-select-radius, 8px);
218
+ background-color: var(--fb-fc-type-select-bg, #ffffff);
219
+ color: var(--fb-fc-type-select-color, #111827);
220
+ font-size: 0.8125rem;
221
+ font-weight: 500;
222
+ cursor: pointer;
223
+ appearance: none;
224
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
225
+ background-repeat: no-repeat;
226
+ background-position: right 8px center;
227
+ min-width: 160px;
228
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
229
+
230
+ @media (max-width: 640px) {
231
+ height: 32px;
232
+ font-size: 0.75rem;
233
+ min-width: 140px;
234
+ padding: 0 28px 0 8px;
235
+ }
236
+
237
+ &:hover {
238
+ border-color: var(--fb-fc-type-select-hover-border, #9ca3af);
239
+ }
240
+
241
+ &:focus {
242
+ outline: none;
243
+ border-color: var(--fb-fc-accent, #3b82f6);
244
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
245
+ }
246
+ }
247
+
248
+ &__title {
249
+ margin: 0;
250
+ font-size: 1.25rem;
251
+ font-weight: 700;
252
+ color: var(--fb-fc-title-color, #111827);
253
+
254
+ @media (max-width: 1024px) {
255
+ font-size: 1.125rem;
256
+ }
257
+
258
+ @media (max-width: 640px) {
259
+ font-size: 1rem;
260
+ }
261
+ }
262
+
263
+ &__badge {
264
+ padding: 4px 12px;
265
+ background: var(--fb-fc-badge-bg, #eff6ff);
266
+ color: var(--fb-fc-badge-color, #3b82f6);
267
+ border-radius: 20px;
268
+ font-size: 11px;
269
+ font-weight: 700;
270
+ text-transform: uppercase;
271
+ letter-spacing: 0.05em;
272
+ border: 1px solid var(--fb-fc-badge-border, #dbeafe);
273
+
274
+ @media (max-width: 640px) {
275
+ padding: 3px 8px;
276
+ font-size: 9px;
277
+ }
278
+ }
279
+
280
+ &__form-wrapper {
281
+ flex: 1;
282
+ overflow-y: auto;
283
+ overflow-x: hidden;
284
+ width: 100%;
285
+ min-width: 0;
286
+ display: flex;
287
+ flex-direction: column;
288
+ align-items: stretch;
289
+ box-sizing: border-box;
290
+
291
+ // Mobile First: Tight padding for small screens
292
+ padding: 12px 16px;
293
+
294
+ // Tablet Portrait (600px+): Increase comfort space
295
+ @media (min-width: 600px) {
296
+ padding: 16px 20px;
297
+ }
298
+
299
+ // Tablet Landscape (768px+): Better vertical breathing room
300
+ @media (min-width: 768px) {
301
+ padding: 20px 24px;
302
+ }
303
+
304
+ // Desktop (1024px+): Comfortable padding
305
+ @media (min-width: 1024px) {
306
+ padding: 1rem;
307
+ }
308
+
309
+ // Large Desktop (1440px+): Spacious padding
310
+ @media (min-width: 1440px) {
311
+ padding: 28px 40px;
312
+ }
313
+
314
+ // Ultra-wide (1920px+): Maximum breathing room
315
+ @media (min-width: 1920px) {
316
+ padding: 32px 48px;
317
+ }
318
+
319
+ .fb-config-card {
320
+ width: 100%;
321
+ max-width: none;
322
+ margin: 0;
323
+ background: transparent;
324
+ border: none;
325
+ box-shadow: none;
326
+ display: flex;
327
+ flex-direction: column;
328
+ min-width: 0;
329
+ flex: 1;
330
+ box-sizing: border-box;
331
+
332
+ // ────────────────────────────────────────────────────────────────────────────
333
+ // RESPONSIVE FORM FIELD LAYOUT
334
+ // Professional responsive grid for form fields - centered design
335
+ // ────────────────────────────────────────────────────────────────────────────
336
+
337
+ // Form field wrapper styling
338
+ ::ng-deep .sf-col {
339
+ // display: flex;
340
+ min-width: 0;
341
+ }
342
+
343
+ // Horizontal form rows - flexible responsive layout
344
+ ::ng-deep .form-row.horizontal {
345
+ display: grid;
346
+ grid-auto-flow: dense;
347
+ gap: 12px;
348
+ width: 100%;
349
+ align-items: start;
350
+
351
+ // Mobile (< 600px): Single column, full width
352
+ @media (max-width: 599px) {
353
+ grid-template-columns: 1fr;
354
+ gap: 12px;
355
+ }
356
+
357
+ // Tablet Portrait (600px-768px): Single column with better gap
358
+ @media (min-width: 600px) and (max-width: 767px) {
359
+ grid-template-columns: 1fr;
360
+ gap: 14px;
361
+ }
362
+
363
+ // Tablet Landscape (768px-1024px): 2 columns
364
+ @media (min-width: 768px) and (max-width: 1023px) {
365
+ grid-template-columns: repeat(2, 1fr);
366
+ gap: 14px;
367
+ }
368
+
369
+ // Desktop (1024px-1440px): 2 columns with balanced spacing
370
+ @media (min-width: 1024px) and (max-width: 1439px) {
371
+ grid-template-columns: repeat(2, 1fr);
372
+ gap: 16px;
373
+ }
374
+
375
+ // Large Desktop (1440px+): 3 columns for optimal use of space
376
+ @media (min-width: 1440px) {
377
+ grid-template-columns: repeat(3, 1fr);
378
+ gap: 18px;
379
+ }
380
+
381
+ // Ultra-wide (1920px+): 3 columns with generous gaps
382
+ @media (min-width: 1920px) {
383
+ grid-template-columns: repeat(3, 1fr);
384
+ gap: 20px;
385
+ }
386
+
387
+ // Field wrapper styling
388
+ > * {
389
+ display: flex;
390
+ flex-direction: column;
391
+ min-width: 0;
392
+ overflow: hidden;
393
+
394
+ // Ensure inputs take full width
395
+ ::ng-deep .form-field-wrapper,
396
+ ::ng-deep .field-wrapper,
397
+ ::ng-deep input,
398
+ ::ng-deep select,
399
+ ::ng-deep textarea {
400
+ width: 100%;
401
+ min-width: 0;
402
+ }
403
+ }
404
+ }
405
+
406
+ // Switch field styling - inline horizontal layout
407
+ ::ng-deep .form-row.horizontal .sf-switch-wrapper {
408
+ display: flex;
409
+ flex-direction: row;
410
+ align-items: center;
411
+ gap: 8px;
412
+ white-space: nowrap;
413
+ min-width: 0;
414
+
415
+ @media (max-width: 768px) {
416
+ gap: 6px;
417
+ }
418
+
419
+ .field-label {
420
+ font-size: 0.75rem;
421
+ font-weight: 600;
422
+ margin: 0;
423
+ flex-shrink: 1;
424
+ min-width: 0;
425
+ word-break: keep-all;
426
+
427
+ @media (max-width: 768px) {
428
+ font-size: 0.7rem;
429
+ }
430
+
431
+ @media (max-width: 640px) {
432
+ font-size: 0.65rem;
433
+ }
434
+ }
435
+
436
+ .switch {
437
+ flex-shrink: 0;
438
+ }
439
+ }
440
+
441
+ ::ng-deep .grid-row .sf-col .sf-switch-wrapper {
442
+ display: flex;
443
+ flex-direction: row;
444
+ align-items: center;
445
+ gap: 8px;
446
+ white-space: nowrap;
447
+ min-width: 0;
448
+
449
+ @media (max-width: 768px) {
450
+ gap: 6px;
451
+ }
452
+
453
+ .field-label {
454
+ font-size: 0.75rem;
455
+ font-weight: 600;
456
+ margin: 0;
457
+ flex-shrink: 1;
458
+ min-width: 0;
459
+ word-break: keep-all;
460
+
461
+ @media (max-width: 768px) {
462
+ font-size: 0.7rem;
463
+ }
464
+
465
+ @media (max-width: 640px) {
466
+ font-size: 0.65rem;
467
+ }
468
+ }
469
+
470
+ .switch {
471
+ flex-shrink: 0;
472
+ }
473
+ }
474
+ }
475
+ }
476
+
477
+ &__error {
478
+ padding: 24px;
479
+ background: var(--fb-fc-error-bg, #fef2f2);
480
+ color: var(--fb-fc-error-color, #dc2626);
481
+ border: 1px solid var(--fb-fc-error-border, #fee2e2);
482
+ border-radius: 8px;
483
+ font-size: 14px;
484
+ font-weight: 500;
485
+
486
+ @media (max-width: 768px) {
487
+ padding: 16px;
488
+ font-size: 13px;
489
+ }
490
+
491
+ @media (max-width: 640px) {
492
+ padding: 12px;
493
+ font-size: 12px;
494
+ }
495
+ }
496
+ }