commons-shared-web-ui 0.0.83 → 0.0.85

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.
package/index.d.ts CHANGED
@@ -232,6 +232,16 @@ interface MultiSaveConfig {
232
232
  * '+ Add a [label]'.
233
233
  */
234
234
  addLabel?: string;
235
+ /**
236
+ * How many saved entries the section must hold before the form can be submitted.
237
+ * Defaults to 0 — the section is optional, and the blank editor it always renders
238
+ * is ignored so it can't make the whole form unsubmittable.
239
+ *
240
+ * Set to 1 (or more) for a section that genuinely requires entries: the blank editor
241
+ * then counts as the missing entry, and submitting with it empty fails validation and
242
+ * highlights its required fields.
243
+ */
244
+ minEntries?: number;
235
245
  }
236
246
  interface StepperConfig {
237
247
  children: FieldConfig[];
@@ -1381,6 +1391,17 @@ declare class ConfiguratorConfigPanelComponent implements OnChanges {
1381
1391
  static ɵcmp: i0.ɵɵComponentDeclaration<ConfiguratorConfigPanelComponent, "lib-configurator-config-panel", never, { "selectedField": { "alias": "selectedField"; "required": false; }; "selectedFieldInfo": { "alias": "selectedFieldInfo"; "required": false; }; "builderFieldType": { "alias": "builderFieldType"; "required": false; }; "fieldTypeSchemaMap": { "alias": "fieldTypeSchemaMap"; "required": false; }; "showOptionConfig": { "alias": "showOptionConfig"; "required": false; }; "lockedFieldNames": { "alias": "lockedFieldNames"; "required": false; }; }, { "configChange": "configChange"; "typeChange": "typeChange"; }, never, never, false, never>;
1382
1392
  }
1383
1393
 
1394
+ /**
1395
+ * Implemented by any field that hosts a repeatable (allowMulti) group.
1396
+ * Declared here — rather than importing FormFieldComponent — so the controller
1397
+ * stays free of a circular dependency on the component that injects it.
1398
+ */
1399
+ interface RepeaterHost {
1400
+ /** Saves entries the user filled in but never pressed Save on. True = one is incomplete. */
1401
+ commitPendingInstances(): boolean;
1402
+ /** Re-opens collapsed entries whose fields are invalid. True = at least one was revealed. */
1403
+ revealInvalidInstances(): boolean;
1404
+ }
1384
1405
  declare class SmartFormController {
1385
1406
  private formData;
1386
1407
  /** Auth token sourced from the FormSchema configJSON (e.g. "Bearer eyJ…") */
@@ -1404,6 +1425,25 @@ declare class SmartFormController {
1404
1425
  selectedOptionsData: {
1405
1426
  [fieldName: string]: any;
1406
1427
  };
1428
+ /**
1429
+ * Repeater sections register themselves here so SmartFormComponent can reach them
1430
+ * at submit time. A @ViewChildren query can't: the fields are rendered inside
1431
+ * FormSectionComponent's template, which is a separate view, so the query never
1432
+ * matches them.
1433
+ */
1434
+ private repeaters;
1435
+ /**
1436
+ * Set on the per-row controllers a repeater creates for its instances. Registrations
1437
+ * walk up this chain so a repeater nested inside another repeater's row is still
1438
+ * visible to the root form.
1439
+ */
1440
+ parent?: SmartFormController;
1441
+ /** The controller the root SmartFormComponent owns — this one unless it is a row controller. */
1442
+ private get rootController();
1443
+ registerRepeater(host: RepeaterHost): void;
1444
+ unregisterRepeater(host: RepeaterHost): void;
1445
+ /** Every repeater currently rendered under the root form. */
1446
+ get repeaterHosts(): RepeaterHost[];
1407
1447
  initialize(initialData: {
1408
1448
  [key: string]: any;
1409
1449
  }): void;
@@ -1537,7 +1577,7 @@ interface TimePickerConfig {
1537
1577
  disabledColor?: string;
1538
1578
  }
1539
1579
 
1540
- declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1580
+ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy, RepeaterHost {
1541
1581
  private fb;
1542
1582
  private expressionService;
1543
1583
  private http;
@@ -1791,6 +1831,34 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1791
1831
  private setupFormulaValidation;
1792
1832
  addGroupInstance(initialData?: any): void;
1793
1833
  saveGroupInstance(index: number): void;
1834
+ /**
1835
+ * Saves any multi-save entry the user filled in but never pressed Save on.
1836
+ *
1837
+ * The card UI only pushes an entry into `groupFormArray` once Save is clicked, so an
1838
+ * entry left open in the editor is invisible to the root form: its values never reach
1839
+ * the payload and its required fields can't block the submit. SmartForm calls this
1840
+ * before validating, which makes an open entry behave exactly as if Save had been
1841
+ * pressed — complete entries are committed, incomplete ones stop the submit.
1842
+ *
1843
+ * Entries the user never touched are skipped: every multi-save section renders one
1844
+ * blank editor by default, and that blank must not make the whole form unsubmittable.
1845
+ *
1846
+ * @returns true when an entry has content but is still invalid — it stays open with
1847
+ * its field errors and the section-level message on screen.
1848
+ */
1849
+ commitPendingInstances(): boolean;
1850
+ /** Saved entries this section must hold before the form can be submitted (0 = optional). */
1851
+ private get minEntries();
1852
+ /**
1853
+ * True when a blank editor can be passed over at submit time.
1854
+ *
1855
+ * Every multi-save section renders one blank editor, so an optional section (the
1856
+ * default) must ignore it — otherwise its required fields would make the whole form
1857
+ * permanently unsubmittable. A section with `minEntries` set that hasn't reached its
1858
+ * quota is the opposite case: the blank editor IS the entry the user still owes, so
1859
+ * it gets validated and lights up like any other incomplete entry.
1860
+ */
1861
+ private isIgnorableBlank;
1794
1862
  /**
1795
1863
  * Re-opens any repeater instance (multiSave card or standard accordion panel)
1796
1864
  * whose nested FormGroup is invalid, so errors hidden by a collapsed card/panel
@@ -1798,6 +1866,18 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1798
1866
  * Returns true if at least one invalid instance was revealed.
1799
1867
  */
1800
1868
  revealInvalidInstances(): boolean;
1869
+ /**
1870
+ * True when the user has put nothing into this repeater entry.
1871
+ *
1872
+ * Value-based rather than `fg.pristine`, because several fields here (date picker,
1873
+ * rich text, the custom dropdown overlays) write through `setValue`, which never
1874
+ * marks the control dirty. `dirty` is still honoured as a second signal so a field
1875
+ * whose value round-trips back to blank still counts as touched.
1876
+ */
1877
+ private isInstanceBlank;
1878
+ /** Blank = nothing a user could have entered. `false` counts as blank so an unchecked
1879
+ * CHECKBOX (or one defaulted to false) doesn't make an otherwise empty entry look filled. */
1880
+ private static isBlankValue;
1801
1881
  cancelGroupInstance(index: number): void;
1802
1882
  editGroupInstance(index: number): void;
1803
1883
  toggleExpandGroupInstance(index: number): void;
@@ -2218,6 +2298,18 @@ declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
2218
2298
  private buildNestedPayload;
2219
2299
  private setNestedValue;
2220
2300
  private extractGroupValue;
2301
+ /**
2302
+ * Saves every multi-save repeater entry (Event Agenda, FAQs, …) that the user filled in
2303
+ * but left open in its editor, so those values are part of `collectFormData()` even
2304
+ * though the entry's own Save button was never clicked. An entry still missing a
2305
+ * required field is left open with its errors showing rather than committed half-done.
2306
+ *
2307
+ * `validate()` calls this already. Hosts that collect form data on their own — a
2308
+ * "Save as draft" button in an external footer, say — should call it first.
2309
+ *
2310
+ * @returns true when an open entry is incomplete.
2311
+ */
2312
+ commitOpenEntries(): boolean;
2221
2313
  validate(): boolean;
2222
2314
  scrollToFirstInvalidControl(): void;
2223
2315
  submitToApi(formData: any, actionType?: 'submit' | 'draft', btn?: ActionButtonConfig): void;
@@ -4292,6 +4384,18 @@ interface FilterSidebarConfig {
4292
4384
  icon?: string;
4293
4385
  visible?: boolean;
4294
4386
  showClose?: boolean;
4387
+ /**
4388
+ * Header bar look, mirroring cc-confirmation-modal. Defaults to 'light' —
4389
+ * a full-width white bar with black title and a bottom divider across the
4390
+ * top of the panel. 'dark' inverts it (black bar, white title, no divider).
4391
+ */
4392
+ theme?: 'light' | 'dark';
4393
+ /** Overrides the theme's bar colour. */
4394
+ backgroundColor?: string;
4395
+ /** Overrides the theme's title colour. */
4396
+ textColor?: string;
4397
+ /** e.g. '1px solid #E0E0E0' or 'none' — overrides the theme's divider. */
4398
+ borderBottom?: string;
4295
4399
  };
4296
4400
  footer?: {
4297
4401
  visible?: boolean;
@@ -4359,6 +4463,8 @@ declare class FilterSidebarComponent implements OnInit, ControlValueAccessor {
4359
4463
  get sidebarStyles(): {
4360
4464
  [key: string]: string;
4361
4465
  };
4466
+ /** `cc-filter-header cc-filter-header--light|--dark` — light (white bar, black title) is the default. */
4467
+ get headerClass(): string;
4362
4468
  trackByFn(index: number, item: FilterItem): any;
4363
4469
  static ɵfac: i0.ɵɵFactoryDeclaration<FilterSidebarComponent, never>;
4364
4470
  static ɵcmp: i0.ɵɵComponentDeclaration<FilterSidebarComponent, "lib-filter-sidebar", never, { "config": { "alias": "config"; "required": false; }; "initialFilters": { "alias": "initialFilters"; "required": false; }; }, { "filterChange": "filterChange"; "filterApply": "filterApply"; "filterClear": "filterClear"; "showCodeSnippet": "showCodeSnippet"; "close": "close"; }, never, ["[header-actions]"], false, never>;
@@ -5034,6 +5140,12 @@ declare class SmartTableComponent implements OnInit, OnChanges, AfterViewInit, O
5034
5140
  * external-data mode. Must be kept in sync by the parent.
5035
5141
  */
5036
5142
  totalItemsCount?: number;
5143
+ /**
5144
+ * External loading state: when the table operates in external-data mode
5145
+ * (i.e. [tableData] is provided), the parent controls the loading spinner
5146
+ * via this input. Ignored in internal-data mode where loading is self-managed.
5147
+ */
5148
+ externalLoading: boolean;
5037
5149
  action: EventEmitter<{
5038
5150
  action: TableAction;
5039
5151
  row: any;
@@ -5066,6 +5178,12 @@ declare class SmartTableComponent implements OnInit, OnChanges, AfterViewInit, O
5066
5178
  currentPage: number;
5067
5179
  loading: boolean;
5068
5180
  originalRowsCache: Map<any, any>;
5181
+ /**
5182
+ * Unified loading state used by the template. In external-data mode,
5183
+ * defers to `externalLoading` (parent-driven). In internal-data mode,
5184
+ * uses the internally managed `loading` flag.
5185
+ */
5186
+ get isTableLoading(): boolean;
5069
5187
  activeSort: {
5070
5188
  key: string;
5071
5189
  direction: 'ASC' | 'DESC';
@@ -5251,7 +5369,7 @@ declare class SmartTableComponent implements OnInit, OnChanges, AfterViewInit, O
5251
5369
  /** Normalize Date objects back to ISO strings before sending payloads. */
5252
5370
  private normalizeDateFieldsForSave;
5253
5371
  static ɵfac: i0.ɵɵFactoryDeclaration<SmartTableComponent, never>;
5254
- static ɵcmp: i0.ɵɵComponentDeclaration<SmartTableComponent, "lib-smart-table", never, { "config": { "alias": "config"; "required": false; }; "tableData": { "alias": "tableData"; "required": false; }; "totalItemsCount": { "alias": "totalItemsCount"; "required": false; }; "selectedRows": { "alias": "selectedRows"; "required": false; }; }, { "action": "action"; "topAction": "topAction"; "filterChange": "filterChange"; "rowSelect": "rowSelect"; "columnClick": "columnClick"; "sortChange": "sortChange"; "pageChange": "pageChange"; "searchChange": "searchChange"; "rowSave": "rowSave"; }, never, never, false, never>;
5372
+ static ɵcmp: i0.ɵɵComponentDeclaration<SmartTableComponent, "lib-smart-table", never, { "config": { "alias": "config"; "required": false; }; "tableData": { "alias": "tableData"; "required": false; }; "totalItemsCount": { "alias": "totalItemsCount"; "required": false; }; "externalLoading": { "alias": "externalLoading"; "required": false; }; "selectedRows": { "alias": "selectedRows"; "required": false; }; }, { "action": "action"; "topAction": "topAction"; "filterChange": "filterChange"; "rowSelect": "rowSelect"; "columnClick": "columnClick"; "sortChange": "sortChange"; "pageChange": "pageChange"; "searchChange": "searchChange"; "rowSave": "rowSave"; }, never, never, false, never>;
5255
5373
  }
5256
5374
 
5257
5375
  /**
@@ -5501,4 +5619,4 @@ declare class SnackbarModule {
5501
5619
  }
5502
5620
 
5503
5621
  export { AlertComponent, AlertModule, ButtonComponent, ButtonDropdownComponent, ButtonDropdownModule, ButtonModule, CheckboxComponent, ClickOutsideDirective, ConfigColumnNodeComponent, ConfigFieldNodeComponent, ConfigSchemaTreeService, ConfigSectionNodeComponent, ConfigurableFormComponent, configurableForm_examples_d as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_SIDE_NAV_TOOLTIP_POSITION, DatepickerComponent, DropdownComponent, ExpressionService, FieldConfigurationService, FieldConfiguratorComponent, FieldSelectionComponent, FilterComponent, FilterModule, FilterSidebarComponent, FilterSidebarModule, FilterTableSelectorComponent, FilterTableSelectorModule, FormBuilderModule, FormComponentsModule, FormFieldConfigurationComponent, FormFieldConfigurationModule, InputComponent, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, RadioComponent, SearchComponent, SharedUiModule, SideNavComponent, SideNavModule, SmartFormComponent, SmartFormController, smartForm_examples_d as SmartFormExamples, SmartFormModule, SmartTableComponent, SmartTableModule, SnackbarComponent, SnackbarModule, SnackbarService, StringUtils, SummaryCardComponent, SummaryCardModule, TableColumnConfigurationComponent, TableColumnConfigurationModule, TableColumnConfigurationService, TimePickerComponent, TimePickerModule, TimeWheelPanelComponent, ToggleComponent, ValidationUtils, appendBaseUrlRecursively, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem, translateConfig };
5504
- export type { ActionVisibility, AlertLabels, AlertVariant, AttachmentConfig, ButtonLabels, ButtonVariant, CheckboxConfig, CheckboxLabels, CheckboxOption, ColumnLookupConfig, ConfigColumnNode, ConfigFieldNode, ConfigSectionNode, ConfirmationModalConfig, DateConfig, DatePickerConfig, DatepickerLabels, DropdownAction, DropdownConfig, DropdownLabels, DropdownOption, EmailConfig, FieldColSpanPayload, FieldConfig, FieldEventPayload, FieldReorderPayload, FieldType, FilterChangeEvent, FilterConfig, FilterItem, FilterItemType, FilterOutput, FilterPanelConfig, FilterParamMap, FilterSearchConfig, FilterSidebarChangeEvent, FilterSidebarConfig, FilterSidebarOutput, FilterTableConfig, FilterTableSelectorConfig, FormConfig, FormField, FormOption, FormSchema, FormSection, GeneratedConfig, IconInput, InputConfig, InputLabels, InputType, JsonFieldConfig, JsonFormConfig, KeyType, LengthConstraint, LocationConfig, NavItem, NavStyleConfig, NestedStringConfig, NumberConfig, OptionConfig, OptionDTO, OptionItem, PaginationConfig, PaginationLabels, PhoneConfig, QueryParamsConfig, RadioConfig, RadioLabels, RadioOption, RangeConfig, RatingConfig, SearchConfig, SearchLabels, SectionConfig, SelectionConfig, SideNavItem, SideNavSection, SideNavStyleConfig, SnackbarConfig, SnackbarVariant, StepperConfig, SubmitConfig, SuffixActionIcon, SummaryCardConfig, SummaryCardLabels, SummaryCardMeta, TableAction, TableActionItem, TableColumn, TableColumnSubField, TableConfig, TableDataChangeEvent, TableFilter, TableFilterChangeEvent, TableFilterColumn, TableFilterConfig, TableFilterItem, TableFilterLabels, TableFilterOutput, TableLabels, TableOption, TableRowSaveEvent, TableTheme, TextConfig, TimeMode, TimePickerConfig, TimePickerLabels, TimePickerVariant, ToggleConfig, ToggleLabels, UIConfig, UISubType, UIType, UploadedFile, ValidationResult, ValidationRules, VisibilityRule };
5622
+ export type { ActionVisibility, AlertLabels, AlertVariant, AttachmentConfig, ButtonLabels, ButtonVariant, CheckboxConfig, CheckboxLabels, CheckboxOption, ColumnLookupConfig, ConfigColumnNode, ConfigFieldNode, ConfigSectionNode, ConfirmationModalConfig, DateConfig, DatePickerConfig, DatepickerLabels, DropdownAction, DropdownConfig, DropdownLabels, DropdownOption, EmailConfig, FieldColSpanPayload, FieldConfig, FieldEventPayload, FieldReorderPayload, FieldType, FilterChangeEvent, FilterConfig, FilterItem, FilterItemType, FilterOutput, FilterPanelConfig, FilterParamMap, FilterSearchConfig, FilterSidebarChangeEvent, FilterSidebarConfig, FilterSidebarOutput, FilterTableConfig, FilterTableSelectorConfig, FormConfig, FormField, FormOption, FormSchema, FormSection, GeneratedConfig, IconInput, InputConfig, InputLabels, InputType, JsonFieldConfig, JsonFormConfig, KeyType, LengthConstraint, LocationConfig, NavItem, NavStyleConfig, NestedStringConfig, NumberConfig, OptionConfig, OptionDTO, OptionItem, PaginationConfig, PaginationLabels, PhoneConfig, QueryParamsConfig, RadioConfig, RadioLabels, RadioOption, RangeConfig, RatingConfig, RepeaterHost, SearchConfig, SearchLabels, SectionConfig, SelectionConfig, SideNavItem, SideNavSection, SideNavStyleConfig, SnackbarConfig, SnackbarVariant, StepperConfig, SubmitConfig, SuffixActionIcon, SummaryCardConfig, SummaryCardLabels, SummaryCardMeta, TableAction, TableActionItem, TableColumn, TableColumnSubField, TableConfig, TableDataChangeEvent, TableFilter, TableFilterChangeEvent, TableFilterColumn, TableFilterConfig, TableFilterItem, TableFilterLabels, TableFilterOutput, TableLabels, TableOption, TableRowSaveEvent, TableTheme, TextConfig, TimeMode, TimePickerConfig, TimePickerLabels, TimePickerVariant, ToggleConfig, ToggleLabels, UIConfig, UISubType, UIType, UploadedFile, ValidationResult, ValidationRules, VisibilityRule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commons-shared-web-ui",
3
- "version": "0.0.83",
3
+ "version": "0.0.85",
4
4
  "peerDependencies": {
5
5
  "@angular/animations": "20.3.15",
6
6
  "@angular/cdk": "20.2.14",
@@ -8,14 +8,21 @@ $default-filter-sidebar-config: (
8
8
  bg: #FEFEFE,
9
9
  border-radius: 0,
10
10
 
11
- // Header
11
+ // Header — a full-width bar at the top of the panel; 'light' is the default theme:
12
+ // white bar, black title, divider along the bottom. 'dark' inverts it.
12
13
  header-height: 3rem,
14
+ header-padding: 0.5rem 1.5rem,
13
15
  header-title-size: 1.125rem,
14
16
  header-title-weight: 500,
15
17
  header-title-color: #202124,
18
+ header-bg-dark: #262125,
19
+ header-title-color-dark: #FFFFFF,
20
+ header-icon-color-dark: rgba(255, 255, 255, 0.7),
21
+ header-bg-light: #FFFFFF,
22
+ header-border-bottom-light: 1px solid #E0E0E0,
16
23
 
17
24
  // Footer
18
- footer-padding: 1rem 0 0 0,
25
+ footer-padding: 1rem 1.5rem 1.5rem,
19
26
  footer-gap: 1rem,
20
27
  );
21
28
 
@@ -29,9 +36,15 @@ $default-filter-sidebar-config: (
29
36
  --cc-filter-sidebar-border-radius: #{map.get($config, border-radius)};
30
37
 
31
38
  --cc-filter-header-height: #{map.get($config, header-height)};
39
+ --cc-filter-header-padding: #{map.get($config, header-padding)};
32
40
  --cc-filter-header-title-size: #{map.get($config, header-title-size)};
33
41
  --cc-filter-header-title-weight: #{map.get($config, header-title-weight)};
34
42
  --cc-filter-header-title-color: #{map.get($config, header-title-color)};
43
+ --cc-filter-header-bg-dark: #{map.get($config, header-bg-dark)};
44
+ --cc-filter-header-title-color-dark: #{map.get($config, header-title-color-dark)};
45
+ --cc-filter-header-icon-color-dark: #{map.get($config, header-icon-color-dark)};
46
+ --cc-filter-header-bg-light: #{map.get($config, header-bg-light)};
47
+ --cc-filter-header-border-bottom-light: #{map.get($config, header-border-bottom-light)};
35
48
 
36
49
  --cc-filter-footer-padding: #{map.get($config, footer-padding)};
37
50
  --cc-filter-footer-gap: #{map.get($config, footer-gap)};