@sd-angular/core 19.0.0-beta.101 → 19.0.0-beta.102

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 (66) hide show
  1. package/components/operator/src/operator.component.d.ts +0 -4
  2. package/components/query-bar/src/actions-bar.component.d.ts +31 -0
  3. package/components/query-bar/src/build-chip.component.d.ts +67 -0
  4. package/components/query-bar/src/chip-popover.component.d.ts +73 -0
  5. package/components/query-bar/src/field-picker.component.d.ts +37 -0
  6. package/components/query-bar/src/inline-chip.component.d.ts +82 -0
  7. package/components/query-bar/src/popover-chip.component.d.ts +35 -0
  8. package/components/query-bar/src/query-bar.component.d.ts +46 -89
  9. package/components/query-bar/src/query-bar.model.d.ts +44 -29
  10. package/components/query-bar/src/saved-filters-menu.component.d.ts +39 -0
  11. package/components/view/src/view.component.d.ts +2 -1
  12. package/fesm2022/sd-angular-core-components-anchor.mjs +73 -47
  13. package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
  14. package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
  15. package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
  16. package/fesm2022/sd-angular-core-components-form-generic.mjs +10 -10
  17. package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
  18. package/fesm2022/sd-angular-core-components-operator.mjs +3 -16
  19. package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -1
  20. package/fesm2022/sd-angular-core-components-query-bar.mjs +812 -385
  21. package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
  22. package/fesm2022/sd-angular-core-components-table.mjs +6 -6
  23. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  24. package/fesm2022/sd-angular-core-components-view.mjs +5 -2
  25. package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
  26. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +3 -3
  27. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  28. package/fesm2022/sd-angular-core-forms-checkbox.mjs +5 -2
  29. package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
  30. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +3 -3
  31. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
  32. package/fesm2022/sd-angular-core-forms-chip.mjs +3 -3
  33. package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
  34. package/fesm2022/sd-angular-core-forms-date-range.mjs +41 -4
  35. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  36. package/fesm2022/sd-angular-core-forms-date.mjs +4 -4
  37. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  38. package/fesm2022/sd-angular-core-forms-datetime.mjs +4 -4
  39. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  40. package/fesm2022/sd-angular-core-forms-input-number.mjs +3 -3
  41. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  42. package/fesm2022/sd-angular-core-forms-input.mjs +3 -4
  43. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  44. package/fesm2022/sd-angular-core-forms-radio.mjs +11 -3
  45. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  46. package/fesm2022/sd-angular-core-forms-select.mjs +14 -6
  47. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  48. package/fesm2022/sd-angular-core-forms-switch.mjs +4 -2
  49. package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
  50. package/fesm2022/sd-angular-core-forms-textarea.mjs +3 -3
  51. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  52. package/fesm2022/sd-angular-core-i18n.mjs +35 -0
  53. package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
  54. package/fesm2022/sd-angular-core-modules-layout.mjs +2 -2
  55. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  56. package/fesm2022/sd-angular-core-services-confirm.mjs +1 -1
  57. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  58. package/forms/checkbox/src/checkbox.component.d.ts +4 -2
  59. package/forms/date-range/src/date-range.component.d.ts +16 -2
  60. package/forms/input/src/input.component.d.ts +1 -2
  61. package/forms/radio/src/radio.component.d.ts +3 -1
  62. package/forms/switch/src/switch.component.d.ts +2 -1
  63. package/i18n/src/en.d.ts +5 -0
  64. package/package.json +66 -66
  65. package/sd-angular-core-19.0.0-beta.102.tgz +0 -0
  66. package/sd-angular-core-19.0.0-beta.101.tgz +0 -0
@@ -9,10 +9,6 @@ interface OperatorItem {
9
9
  export declare class SdOperator {
10
10
  #private;
11
11
  static readonly FALLBACK_ICON = "<path d=\"M4 5h16l-6.5 7.5V19l-3 2v-8.5z\"/>";
12
- static readonly SUPPLEMENT: Partial<Record<Operator, {
13
- icon: string;
14
- display: string;
15
- }>>;
16
12
  /** Operator hiện tại — binding hai chiều [(model)]. */
17
13
  model: import("@angular/core").ModelSignal<Operator | undefined>;
18
14
  /** Danh sách operator cho phép, giữ nguyên thứ tự truyền vào. */
@@ -0,0 +1,31 @@
1
+ import { SdQuery, SdQueryLogic, SdSavedFilter } from './query-bar.model';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Right-pinned toolbar for `sd-query-bar`: AND/OR connector toggle, saved-filters
5
+ * dropdown, clear-all, a save-filter shortcut, and the deferred Search trigger.
6
+ * Owns no business logic — just routes user intent back via outputs
7
+ * (`(logic)` model, `(clear)`, `(search)`, `(applyFilter)`).
8
+ *
9
+ * The "save filter" button forwards to `SdQuerySavedFiltersMenu.promptSave()` so
10
+ * the user can save the current query without first opening the saved-filters
11
+ * dropdown — keeps the save action adjacent to the Search trigger.
12
+ */
13
+ export declare class SdQueryActionsBar {
14
+ readonly showLogicToggle: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
15
+ readonly logic: import("@angular/core").ModelSignal<SdQueryLogic>;
16
+ readonly filtersCount: import("@angular/core").InputSignal<number>;
17
+ readonly showSavedFilters: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
18
+ readonly savedFiltersKey: import("@angular/core").InputSignal<string | undefined>;
19
+ readonly query: import("@angular/core").InputSignal<SdQuery<any>>;
20
+ readonly applyFilter: import("@angular/core").OutputEmitterRef<SdSavedFilter<any>>;
21
+ readonly showClearAll: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
22
+ readonly clear: import("@angular/core").OutputEmitterRef<void>;
23
+ readonly canSearch: import("@angular/core").InputSignal<boolean>;
24
+ readonly search: import("@angular/core").OutputEmitterRef<void>;
25
+ private readonly savedFiltersMenu;
26
+ setLogic(value: SdQueryLogic): void;
27
+ /** Trigger save-current-query via the saved-filters child (no-op when menu absent / no key). */
28
+ promptSave(): void;
29
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryActionsBar, never>;
30
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryActionsBar, "sd-query-actions-bar", never, { "showLogicToggle": { "alias": "showLogicToggle"; "required": false; "isSignal": true; }; "logic": { "alias": "logic"; "required": false; "isSignal": true; }; "filtersCount": { "alias": "filtersCount"; "required": false; "isSignal": true; }; "showSavedFilters": { "alias": "showSavedFilters"; "required": false; "isSignal": true; }; "savedFiltersKey": { "alias": "savedFiltersKey"; "required": false; "isSignal": true; }; "query": { "alias": "query"; "required": false; "isSignal": true; }; "showClearAll": { "alias": "showClearAll"; "required": false; "isSignal": true; }; "canSearch": { "alias": "canSearch"; "required": false; "isSignal": true; }; }, { "logic": "logicChange"; "applyFilter": "applyFilter"; "clear": "clear"; "search": "search"; }, never, never, true, never>;
31
+ }
@@ -0,0 +1,67 @@
1
+ import { Operator } from '@sd-angular/core/utilities/models';
2
+ import { BuildingChip } from './query-bar.model';
3
+ import * as i0 from "@angular/core";
4
+ type Density = 'compact' | 'comfortable';
5
+ /**
6
+ * Visual block for the in-progress build chip (inline mode token builder).
7
+ *
8
+ * why: tách khỏi `<sd-query-bar>` để parent chỉ giữ state (`building()` signal +
9
+ * step transitions) — tất cả render logic của 2 step (operator picker / value
10
+ * picker) cộng với 7 nhánh field type sống tại đây.
11
+ *
12
+ * The chip has two visually distinct branches:
13
+ * - **Seamless** (`string` / `number`) — the entire pill IS an `<sd-query-inline-value-chip>`
14
+ * (its own border, autofocused input). The host's `.c-token-building` shell is skipped.
15
+ * - **Token** (`values` / `lazy-values` / `date` / `datetime` / `boolean` / other) —
16
+ * `.c-token.c-token-building` dashed pill with field label + operator (menu in
17
+ * operator step, disabled badge in value step) + the per-type picker + × cancel.
18
+ */
19
+ export declare class SdQueryBuildChip {
20
+ /** Current build state — drives every visual branch. */
21
+ readonly building: import("@angular/core").InputSignal<BuildingChip<any>>;
22
+ /** Density preset — forwarded to the seamless chip + sizes the .c-token row. */
23
+ readonly density: import("@angular/core").InputSignal<Density>;
24
+ /** Operator set offered in the operator-step menu (parent's `allowedOperatorsFor(field)`). */
25
+ readonly allowedOperators: import("@angular/core").InputSignal<Operator[]>;
26
+ /** Whether the active operator is a multi-select (`IN`/`NOT_IN`) — drives sd-select [multiple]. */
27
+ readonly multiple: import("@angular/core").InputSignal<boolean>;
28
+ /** Show the operator label on the seamless chip's pill (forwarded to inline-value-chip). */
29
+ readonly showOperator: import("@angular/core").InputSignal<boolean>;
30
+ /**
31
+ * Prefix for `data-autoid` on the inner picker / seamless input.
32
+ * why: parent originally hard-coded `'qb-build-value'` everywhere; default preserves that
33
+ * for backward compatibility with existing e2e selectors.
34
+ */
35
+ readonly autoId: import("@angular/core").InputSignal<string>;
36
+ /** Operator chosen from the operator-step menu — parent advances to value step. */
37
+ readonly pickOperator: import("@angular/core").OutputEmitterRef<Operator>;
38
+ /**
39
+ * Value committed from a non-seamless picker (sd-select / sd-date / sd-date-range /
40
+ * sd-datetime) or a boolean toggle. Parent pushes the completed chip and clears building.
41
+ */
42
+ readonly commitValue: import("@angular/core").OutputEmitterRef<unknown>;
43
+ /** × button — abandon the build (parent clears `building` signal). */
44
+ readonly cancel: import("@angular/core").OutputEmitterRef<void>;
45
+ /**
46
+ * Commit from the seamless (string / number) branch. Parent decides empty → cancel
47
+ * vs push complete (see `onBuildSeamlessCommit`); this just forwards the raw value.
48
+ */
49
+ readonly seamlessCommit: import("@angular/core").OutputEmitterRef<unknown>;
50
+ /** Fallback editor (boolean ng-template / other) — staged draft on every change. */
51
+ readonly draftChange: import("@angular/core").OutputEmitterRef<unknown>;
52
+ /** Fallback editor — Enter / click commits the staged draft. */
53
+ readonly draftCommit: import("@angular/core").OutputEmitterRef<void>;
54
+ /** Operator-step menu — auto-opened by parent right after `building` enters operator step. */
55
+ private readonly opMenu;
56
+ /** Value-step picker (the active bare control) — auto-opened by parent at value step. */
57
+ private readonly picker;
58
+ /** Open the operator menu — parent calls after rendering the operator step. */
59
+ openOperator(): void;
60
+ /** Open the value-step picker's native panel — parent calls after rendering the value step. */
61
+ openPicker(): void;
62
+ /** True when the seamless branch (string/number value step) should be rendered. */
63
+ readonly isSeamless: import("@angular/core").Signal<boolean>;
64
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryBuildChip, never>;
65
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryBuildChip, "sd-query-build-chip", never, { "building": { "alias": "building"; "required": true; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "allowedOperators": { "alias": "allowedOperators"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "showOperator": { "alias": "showOperator"; "required": false; "isSignal": true; }; "autoId": { "alias": "autoId"; "required": false; "isSignal": true; }; }, { "pickOperator": "pickOperator"; "commitValue": "commitValue"; "cancel": "cancel"; "seamlessCommit": "seamlessCommit"; "draftChange": "draftChange"; "draftCommit": "draftCommit"; }, never, never, true, never>;
66
+ }
67
+ export {};
@@ -0,0 +1,73 @@
1
+ import { MatMenu } from '@angular/material/menu';
2
+ import { Filter, Operator } from '@sd-angular/core/utilities/models';
3
+ import { SdQueryField, sdQueryFieldIcon } from './query-bar.model';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Popover-mode chip editor — the entire `<mat-menu>` that opens when a popover-mode
7
+ * chip is clicked. Owns ALL operator+value staging signals and async option loading.
8
+ *
9
+ * why: tách khỏi `<sd-query-bar>` để parent chỉ giữ `editingIndex` (chip nào đang
10
+ * mở) + nhận `(commit)` khi popover đóng. Mỗi lần parent gọi `seed(filter, field)`
11
+ * trước khi mở chip popover, child reset staging signals + kích option loading.
12
+ *
13
+ * Public surface (template ref `#cp`):
14
+ * - `cp.menu()` — the `<mat-menu>` to feed `[menu]` of `<sd-query-popover-chip>`
15
+ * - `cp.seed(filter, field)` — parent reseeds staging before opening
16
+ * - `(commit)` output — emitted on mat-menu close with staged Filter
17
+ * - `(swapField)` output — emitted when the nested field switcher picks a new field
18
+ */
19
+ export declare class SdQueryChipPopover {
20
+ #private;
21
+ /** Resolved field of the currently editing chip — parent passes from `fieldByKey()`. */
22
+ readonly field: import("@angular/core").InputSignal<SdQueryField | undefined>;
23
+ /** The chip's current Filter — used by `seed()` for initial staging values. */
24
+ readonly filter: import("@angular/core").InputSignal<Filter | undefined>;
25
+ /** Optional chip index — embedded in the composed autoIds. */
26
+ readonly chipIndex: import("@angular/core").InputSignal<number | null>;
27
+ /** Prefix for `data-autoId` on inner controls. */
28
+ readonly autoIdBase: import("@angular/core").InputSignal<string>;
29
+ /** MatMenu for the field switcher — parent passes its `<sd-query-field-picker>` menu. */
30
+ readonly switchPickerMenu: import("@angular/core").InputSignal<MatMenu | undefined>;
31
+ /** Emitted when mat-menu closes — parent splices `next` into filters[idx]. */
32
+ readonly commit: import("@angular/core").OutputEmitterRef<Filter>;
33
+ /** Emitted when nested field-switcher picks a new field — parent calls changeFilterField. */
34
+ readonly swapField: import("@angular/core").OutputEmitterRef<SdQueryField>;
35
+ /** Staged operator. */
36
+ readonly editingOperator: import("@angular/core").WritableSignal<Operator>;
37
+ /** Staged value (shape depends on field type + operator). */
38
+ readonly editingValue: import("@angular/core").WritableSignal<unknown>;
39
+ /** Resolved option list for values / lazy-values. */
40
+ readonly editingOptions: import("@angular/core").WritableSignal<any[]>;
41
+ /** Loading flag for async option fetch. */
42
+ readonly editingOptionsLoading: import("@angular/core").WritableSignal<boolean>;
43
+ readonly allowedOperators: import("@angular/core").Signal<Operator[]>;
44
+ readonly showOperatorSelector: import("@angular/core").Signal<boolean>;
45
+ /** Whether the staged operator is multi-select (IN/NOT_IN). */
46
+ multiple(op?: Operator): boolean;
47
+ /** Whether the staged operator carries no data (NULL/NOT_NULL). */
48
+ isNoDataOperator(op: Operator | string): boolean;
49
+ /** Compose an autoId for an inner control (`<base>-chip<idx>-<role>`). */
50
+ chipAutoId(role: string): string;
51
+ readonly iconFor: typeof sdQueryFieldIcon;
52
+ readonly menu: import("@angular/core").Signal<MatMenu | undefined>;
53
+ /** Reseed staging from a new filter/field pair — call before opening the menu. */
54
+ seed(filter: Filter | undefined, field: SdQueryField | undefined): void;
55
+ /** Called on operator change in the popover header — reshapes value when family changes. */
56
+ onEditingOperatorChange(next: Operator): void;
57
+ /** Single-value input change. */
58
+ onEditingValueInput(value: unknown): void;
59
+ /** BETWEEN range — mutate only `.from`. */
60
+ onEditingRangeFrom(value: string | number | null): void;
61
+ /** BETWEEN range — mutate only `.to`. */
62
+ onEditingRangeTo(value: string | number | null): void;
63
+ /** Toggle a value in the staged multi-select array. */
64
+ toggleEditingMultiValue(value: unknown): void;
65
+ isEditingMultiSelected(value: unknown): boolean;
66
+ /**
67
+ * mat-menu's (closed) handler — compose the next Filter from staging signals and
68
+ * emit (commit). Parent splices into its filters[] and nulls editingIndex.
69
+ */
70
+ onMenuClosed(): void;
71
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryChipPopover, never>;
72
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryChipPopover, "sd-query-chip-popover", never, { "field": { "alias": "field"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "chipIndex": { "alias": "chipIndex"; "required": false; "isSignal": true; }; "autoIdBase": { "alias": "autoIdBase"; "required": false; "isSignal": true; }; "switchPickerMenu": { "alias": "switchPickerMenu"; "required": false; "isSignal": true; }; }, { "commit": "commit"; "swapField": "swapField"; }, never, never, true, never>;
73
+ }
@@ -0,0 +1,37 @@
1
+ import { MatMenu } from '@angular/material/menu';
2
+ import { SdQueryField, sdQueryFieldIcon } from './query-bar.model';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Field picker mat-menu for `sd-query-bar`.
6
+ *
7
+ * Shared between two flows in the bar:
8
+ * - "Add filter" — pass `[usedKeys]` (a Set of field keys already on the bar) so
9
+ * those entries render disabled with a check.
10
+ * - "Đổi field" inside the chip popover — pass `[currentKey]` to disable the
11
+ * currently-bound field.
12
+ *
13
+ * Parent triggers via `[matMenuTriggerFor]="picker.menu()"` and receives the
14
+ * chosen field through `(pick)`.
15
+ */
16
+ export declare class SdQueryFieldPicker {
17
+ /** Field list shown in the menu (caller-supplied; rendered in input order). */
18
+ readonly fields: import("@angular/core").InputSignal<SdQueryField[]>;
19
+ /** Single key disabled with a trailing check — used in the chip-popover "Đổi field" flow. */
20
+ readonly currentKey: import("@angular/core").InputSignal<string | undefined>;
21
+ /** Set of keys already in use — used in the "Add filter" flow to grey out duplicates. */
22
+ readonly usedKeys: import("@angular/core").InputSignal<Set<string>>;
23
+ /** Emits when the user picks an enabled field. */
24
+ readonly pick: import("@angular/core").OutputEmitterRef<SdQueryField>;
25
+ /** MatMenu instance — parent binds `[matMenuTriggerFor]="picker.menu()"`. */
26
+ readonly menu: import("@angular/core").Signal<MatMenu>;
27
+ readonly iconFor: typeof sdQueryFieldIcon;
28
+ /** Per-field disabled state — current key OR used key OR field's own disabled flag. */
29
+ readonly disabledMap: import("@angular/core").Signal<Set<string>>;
30
+ isDisabled(field: SdQueryField): boolean;
31
+ /** "Current" check icon — only when the field matches `currentKey`. */
32
+ isCurrent(field: SdQueryField): boolean;
33
+ /** "Used" check icon — when the field is in `usedKeys` (not the same as current). */
34
+ isUsed(field: SdQueryField): boolean;
35
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryFieldPicker, never>;
36
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryFieldPicker, "sd-query-field-picker", never, { "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "currentKey": { "alias": "currentKey"; "required": false; "isSignal": true; }; "usedKeys": { "alias": "usedKeys"; "required": false; "isSignal": true; }; }, { "pick": "pick"; }, never, never, true, never>;
37
+ }
@@ -0,0 +1,82 @@
1
+ import { Filter, Operator } from '@sd-angular/core/utilities/models';
2
+ import { SdQueryField } from './query-bar.model';
3
+ import * as i0 from "@angular/core";
4
+ type Density = 'compact' | 'comfortable';
5
+ /**
6
+ * Completed inline chip (non-string/number — those use `<sd-query-inline-value-chip>`).
7
+ *
8
+ * why: tách edit lifecycle ra khỏi parent `<sd-query-bar>` — child tự quản lý
9
+ * `isEditing` signal, auto-open picker, focusout exit. Parent chỉ pass field/filter
10
+ * và nhận commit/remove outputs.
11
+ *
12
+ * Covers types: boolean, date, datetime, values, lazy-values, plus a fallback else
13
+ * branch. BETWEEN (date / datetime) uses a single `<sd-date-range>` (datetime
14
+ * downgrades to date precision).
15
+ */
16
+ export declare class SdQueryInlineChip {
17
+ #private;
18
+ /** Resolved field — parent passes it (no lookup needed inside). */
19
+ readonly field: import("@angular/core").InputSignal<SdQueryField>;
20
+ /** The chip's Filter — used for `data` + `operator`. */
21
+ readonly filter: import("@angular/core").InputSignal<Filter>;
22
+ /** Density preset — sizes the `.c-token` row. */
23
+ readonly density: import("@angular/core").InputSignal<Density>;
24
+ /** Whether the active operator is a multi-select (IN/NOT_IN). */
25
+ readonly multiple: import("@angular/core").InputSignal<boolean>;
26
+ /** Show `<sd-operator>` (disabled badge) on the chip; otherwise show `':'` separator. */
27
+ readonly showOperator: import("@angular/core").InputSignal<boolean>;
28
+ /** autoId prefix for inner controls (parent passes `inlineAutoId(i, 'value')`). */
29
+ readonly autoId: import("@angular/core").InputSignal<string>;
30
+ /** Pre-computed display text — parent owns `chipValueText(filter)` so we don't recompute. */
31
+ readonly valueText: import("@angular/core").InputSignal<string>;
32
+ /** No-data operator (NULL/NOT_NULL) — hide entire value slot when true. */
33
+ readonly isNoData: import("@angular/core").InputSignal<boolean>;
34
+ /** Single-value commit — parent runs `updateFilter(i, { data })`. */
35
+ readonly commit: import("@angular/core").OutputEmitterRef<unknown>;
36
+ /** BETWEEN commit (date/datetime) — parent runs `setFilterRange(i, ev)`. */
37
+ readonly commitRange: import("@angular/core").OutputEmitterRef<{
38
+ from: unknown;
39
+ to: unknown;
40
+ } | null>;
41
+ /** Live edit during multi-select — parent runs `editValueFn(i)(v)`. */
42
+ readonly liveChange: import("@angular/core").OutputEmitterRef<unknown>;
43
+ /** × removal. */
44
+ readonly remove: import("@angular/core").OutputEmitterRef<void>;
45
+ readonly editing: import("@angular/core").Signal<boolean>;
46
+ /** Active picker reference — auto-opened right after entering edit. */
47
+ private readonly chipPicker;
48
+ readonly iconName: import("@angular/core").Signal<string>;
49
+ /** Operator code — convenience accessor for template. */
50
+ readonly operator: import("@angular/core").Signal<Operator>;
51
+ /** Data payload — convenience accessor for template. */
52
+ readonly data: import("@angular/core").Signal<unknown>;
53
+ /** Enter edit mode + auto-open the picker on next render. */
54
+ enterEdit(): void;
55
+ /**
56
+ * Exit edit only when focus actually leaves the wrapper subtree.
57
+ * why: focusout fires for every internal blur — only exit when relatedTarget
58
+ * is OUTSIDE the wrapper AND không thuộc cdk-overlay (mat-select panel, mat-calendar,
59
+ * datetime overlay đều render trong document.body). Tick option trong panel multi-
60
+ * select sẽ chuyển focus sang `<mat-option>` (nằm trong cdk-overlay-container) →
61
+ * nếu exit ngay sẽ flip viewed → kill panel sớm. Chỉ exit khi panel đã close
62
+ * (relatedTarget không nằm trong overlay). markForCheck vì overlay focusout
63
+ * không kéo theo CD cho OnPush parent.
64
+ */
65
+ onFocusOut(ev: FocusEvent): void;
66
+ /** Test-only shim — direct call avoids dispatching real FocusEvent in JSDOM. */
67
+ onFocusOutForTest(ev: FocusEvent): void;
68
+ /** Single-value commit (sd-date, sd-datetime, single sd-select). */
69
+ emitSingleCommit(v: unknown): void;
70
+ /** BETWEEN commit — sd-date-range emits {from, to}. */
71
+ emitRangeCommit(ev: {
72
+ from: unknown;
73
+ to: unknown;
74
+ } | null): void;
75
+ /** Multi-select live emit — does NOT exit edit (focusout handles exit). */
76
+ emitLive(v: unknown): void;
77
+ /** Boolean toggle commit — exits edit. */
78
+ emitBoolean(v: boolean): void;
79
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryInlineChip, never>;
80
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryInlineChip, "sd-query-inline-chip", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "filter": { "alias": "filter"; "required": true; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "showOperator": { "alias": "showOperator"; "required": false; "isSignal": true; }; "autoId": { "alias": "autoId"; "required": false; "isSignal": true; }; "valueText": { "alias": "valueText"; "required": false; "isSignal": true; }; "isNoData": { "alias": "isNoData"; "required": false; "isSignal": true; }; }, { "commit": "commit"; "commitRange": "commitRange"; "liveChange": "liveChange"; "remove": "remove"; }, never, never, true, never>;
81
+ }
82
+ export {};
@@ -0,0 +1,35 @@
1
+ import { MatMenu } from '@angular/material/menu';
2
+ import { Filter, Operator } from '@sd-angular/core/utilities/models';
3
+ import { SdQueryField, sdQueryFieldIcon } from './query-bar.model';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Compact popover-mode chip face. Click → opens the parent-supplied [menu] (mat-menu
7
+ * containing the chip editor). Inert div[role=button] so the nested <sd-operator>
8
+ * doesn't end up as a button-in-button (invalid HTML).
9
+ */
10
+ export declare class SdQueryPopoverChip {
11
+ /** Resolved field (from the bar's `fieldByKey()` map). `undefined` → render raw key. */
12
+ readonly field: import("@angular/core").InputSignal<SdQueryField | undefined>;
13
+ /** The chip's filter — used to read `field` / `operator` / `data` for display text. */
14
+ readonly filter: import("@angular/core").InputSignal<Filter>;
15
+ /** "Active" = chip has a real value or is no-data op. Drives layout + colour. */
16
+ readonly active: import("@angular/core").InputSignal<boolean>;
17
+ /** Operator visible on the chip face (else hidden, ":" separator). */
18
+ readonly showOperator: import("@angular/core").InputSignal<boolean>;
19
+ /** Rendered value text for the value slot. */
20
+ readonly valueText: import("@angular/core").InputSignal<string>;
21
+ /** Chip popover mat-menu instance supplied by the parent. */
22
+ readonly menu: import("@angular/core").InputSignal<MatMenu>;
23
+ /** Fired when the chip popover opens (parent seeds its editing state). */
24
+ readonly open: import("@angular/core").OutputEmitterRef<void>;
25
+ /** Fired when the user clicks the × removal icon. */
26
+ readonly remove: import("@angular/core").OutputEmitterRef<void>;
27
+ readonly iconFor: typeof sdQueryFieldIcon;
28
+ filterField(): string;
29
+ filterOperator(): Operator;
30
+ private readonly trigger;
31
+ openMenu(): void;
32
+ closeMenu(): void;
33
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryPopoverChip, never>;
34
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryPopoverChip, "sd-query-popover-chip", never, { "field": { "alias": "field"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": true; "isSignal": true; }; "active": { "alias": "active"; "required": true; "isSignal": true; }; "showOperator": { "alias": "showOperator"; "required": false; "isSignal": true; }; "valueText": { "alias": "valueText"; "required": false; "isSignal": true; }; "menu": { "alias": "menu"; "required": true; "isSignal": true; }; }, { "open": "open"; "remove": "remove"; }, never, never, true, never>;
35
+ }
@@ -1,23 +1,17 @@
1
- import { MatMenuTrigger } from '@angular/material/menu';
2
- import { SdSearch } from '@sd-angular/core/forms/models';
3
1
  import { Filter, Operator } from '@sd-angular/core/utilities/models';
4
- import { SdQuery, SdQueryField, SdQueryLogic, sdQueryFieldIcon } from './query-bar.model';
2
+ import { SdQueryChipPopover } from './chip-popover.component';
3
+ import { SdQueryPopoverChip } from './popover-chip.component';
4
+ import { BuildingChip, SdQuery, SdQueryField, SdQueryLogic, SdSavedFilter, sdQueryFieldIcon } from './query-bar.model';
5
5
  import * as i0 from "@angular/core";
6
6
  type Density = 'compact' | 'comfortable';
7
- interface BuildingChip {
8
- field: SdQueryField;
9
- operator?: Operator;
10
- step: 'operator' | 'value';
11
- value?: unknown;
12
- }
13
7
  export declare class SdQueryBar {
14
8
  #private;
15
- /** All chip menu triggers (one per chip button). Used to auto-open the popover after addFilter. */
16
- readonly chipTriggers: import("@angular/core").Signal<readonly MatMenuTrigger[]>;
17
- /** The build chip's operator dropdown auto-opened when entering the operator step. */
18
- private readonly buildOperator;
19
- /** The build chip's value picker (bare sd-select / sd-date / sd-datetime) — auto-opened at the value step. */
20
- private readonly buildPicker;
9
+ /** All popover-mode chips in order used to auto-open after addFilter / close before removeFilter. */
10
+ readonly popoverChips: import("@angular/core").Signal<readonly SdQueryPopoverChip[]>;
11
+ /** The extracted in-progress chip owns operator menu + value picker view refs. */
12
+ private readonly buildChip;
13
+ /** The extracted chip popover owns operator+value staging + commit-on-close. */
14
+ readonly chipPopover: import("@angular/core").Signal<SdQueryChipPopover | undefined>;
21
15
  /** Prefix for auto-generated `data-autoid` on inner controls (chips, operator/value editors, buttons). */
22
16
  readonly autoIdInput: import("@angular/core").InputSignalWithTransform<string | undefined, string | null | undefined>;
23
17
  /** Available fields the user can filter by. Required for the field picker. */
@@ -47,8 +41,20 @@ export declare class SdQueryBar {
47
41
  readonly density: import("@angular/core").InputSignalWithTransform<Density, Density | null | undefined>;
48
42
  /** Show free-text search input on the left. */
49
43
  readonly showSearch: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
50
- /** Show saved-views dropdown on the right. */
51
- readonly showSavedViews: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
44
+ /** Show saved-filters dropdown on the right. Requires `[savedFiltersKey]` to actually persist. */
45
+ readonly showSavedFilters: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
46
+ /**
47
+ * Namespace key for persisting saved filters to `localStorage`. When set, the saved-filters
48
+ * dropdown loads/saves under `sd-query-bar:savedFilters:<key>`. Leave undefined to disable.
49
+ */
50
+ readonly savedFiltersKey: import("@angular/core").InputSignal<string | undefined>;
51
+ /**
52
+ * Snapshot of the current query — fed into `<sd-query-saved-filters-menu [query]>` so
53
+ * saving a filter captures live filters/logic/search.
54
+ */
55
+ readonly currentQuery: import("@angular/core").Signal<SdQuery<any>>;
56
+ /** Receive an applied filter from the saved-filters menu — re-install bar state + trigger apply. */
57
+ onApplyFilter(saved: SdSavedFilter): void;
52
58
  /** Show AND/OR segmented toggle (renders only when there are ≥2 filters). */
53
59
  readonly showLogicToggle: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
54
60
  /** Show "Clear all" button when at least one filter is active. */
@@ -67,36 +73,23 @@ export declare class SdQueryBar {
67
73
  readonly showOrConnector: import("@angular/core").Signal<boolean>;
68
74
  /** Search button is actionable only when there is something to apply. */
69
75
  readonly canSearch: import("@angular/core").Signal<boolean>;
70
- /** Index of the chip whose popover is open. Reset to null after Apply / close. */
76
+ /** Index of the chip whose popover is open. Reset to null after commit / close. */
71
77
  readonly editingIndex: import("@angular/core").WritableSignal<number | null>;
72
- /** Staged operator (uncommitted). */
73
- readonly editingOperator: import("@angular/core").WritableSignal<Operator>;
74
- /** Staged value (uncommitted) — type varies by kind. */
75
- readonly editingValue: import("@angular/core").WritableSignal<unknown>;
76
- /** Resolved option list for the currently editing values / lazy-values field. */
77
- readonly editingOptions: import("@angular/core").WritableSignal<any[]>;
78
- /** Loading state for async option fetch. */
79
- readonly editingOptionsLoading: import("@angular/core").WritableSignal<boolean>;
78
+ /** Resolved field of the chip whose popover is currently open (or null). */
80
79
  readonly editingField: import("@angular/core").Signal<SdQueryField | null>;
81
- readonly editingAllowedOperators: import("@angular/core").Signal<Operator[]>;
82
- /** Show the operator dropdown only when the field exposes >1 operator (else simple mode). */
83
- readonly editingShowOperatorSelector: import("@angular/core").Signal<boolean>;
84
- /** Multi-select is derived from the operator (IN / NOT_IN), not a field flag. */
85
- readonly editingIsMulti: import("@angular/core").Signal<boolean>;
86
- /** Compose a deterministic autoId for an inner control inside a chip's editor. */
87
- chipAutoId(role: string): string;
80
+ /**
81
+ * Multi-select is derived from the operator (IN / NOT_IN) not a field flag.
82
+ * Only called by inline-mode + build-mode templates with a known operator;
83
+ * popover-mode chips read `multiple()` from the child popover directly.
84
+ */
85
+ multiple(op: Operator): boolean;
88
86
  readonly iconFor: typeof sdQueryFieldIcon;
89
87
  /** Chip is "active" when it has a non-empty value OR a no-data operator (NULL/NOT_NULL). */
90
88
  isFilterActive(filter: Filter): boolean;
91
89
  /** Rendered value text on a chip. */
92
90
  chipValueText(filter: Filter): string;
93
91
  isNoDataOperator(op: Operator | string): boolean;
94
- isMultiOperator(op: Operator | string): boolean;
95
- lazyItemsFor(field: SdQueryField): SdSearch;
96
- readonly building: import("@angular/core").Signal<BuildingChip | null>;
97
- readonly editingValueIndex: import("@angular/core").Signal<number | null>;
98
- /** True when chip `i` is in inline value-edit mode. */
99
- isEditingValue(i: number): boolean;
92
+ readonly building: import("@angular/core").Signal<BuildingChip<any> | null>;
100
93
  allowedOperatorsFor(field: SdQueryField): Operator[];
101
94
  inlineAutoId(index: number, role: string): string;
102
95
  /** Entry point from the field picker — start building a chip for `field`. */
@@ -112,41 +105,16 @@ export declare class SdQueryBar {
112
105
  onBuildSeamlessCommit(value: unknown): void;
113
106
  /** Abandon the in-progress chip. */
114
107
  cancelBuild(): void;
115
- /** Live-commit an inline edit for a completed chip (bare control path). */
116
- editValueFn(i: number): (v: unknown) => void;
117
- /** Single-value commit from a completed chip in edit mode — write data + exit edit. */
118
- onChipSingleCommit(i: number, v: unknown): void;
119
108
  /**
120
- * Multi-value chips exit edit when focus actually leaves the wrapper subtree.
121
- * why: focusout fires on every internal blur (option click, search input, …) — only
122
- * exit when the new focus target is NOT a descendant of the chip's value wrapper.
109
+ * Commit both ends of a BETWEEN range at once called from `<sd-query-inline-chip>`'s
110
+ * `(commitRange)` output when the user picks a date range.
111
+ * why: sd-date-range emits {from,to} via (sdChange) single call thay cho cặp
112
+ * setFilterRangeFrom / setFilterRangeTo cũ (đã bỏ).
123
113
  */
124
- onChipValueFocusOut(i: number, ev: FocusEvent): void;
125
- /**
126
- * Cập nhật đầu `from` của BETWEEN cho 1 chip đã commit (inline edit).
127
- * why: dual picker BETWEEN trên chip hoàn tất cần ghi từng đầu vào filter mà không reset đầu kia.
128
- */
129
- setFilterRangeFrom(i: number, v: unknown): void;
130
- /**
131
- * Cập nhật đầu `to` của BETWEEN cho 1 chip đã commit (inline edit).
132
- */
133
- setFilterRangeTo(i: number, v: unknown): void;
134
- noop: () => void;
135
- setEditDraftFn(): (v: unknown) => void;
136
- commitEditDraftFn(i: number): () => void;
137
- setBuildDraftFn(): (v: unknown) => void;
138
- /** Update the `from` end of the build chip's BETWEEN range without committing. */
139
- setBuildRangeFrom(v: unknown): void;
140
- /**
141
- * Update the `to` end of the build chip's BETWEEN range. Once both ends are set, commit
142
- * the chip so the user does not need an extra blur / apply press.
143
- */
144
- setBuildRangeTo(v: unknown): void;
145
- commitBuildDraftFn(): () => void;
146
- /** Start inline value edit on a completed chip (operator + field stay locked). */
147
- beginEditValue(i: number): void;
148
- /** Commit an inline value edit — change only `data`, no emit. */
149
- commitEditValue(i: number, value: unknown): void;
114
+ setFilterRange(i: number, ev: {
115
+ from: unknown;
116
+ to: unknown;
117
+ } | null): void;
150
118
  addFilter(field: SdQueryField): void;
151
119
  /** Swap the field of an existing chip — reset operator + value to the new field's defaults. */
152
120
  changeFilterField(index: number, field: SdQueryField): void;
@@ -156,25 +124,14 @@ export declare class SdQueryBar {
156
124
  setLogic(value: SdQueryLogic): void;
157
125
  setSearch(value: string): void;
158
126
  triggerApply(): void;
159
- /** Called when a chip is clicked — copy current operator + value into the staging signals. */
160
- openChipPopover(index: number): void;
161
- /** Called on operator <select> change in the popover. */
162
- onEditingOperatorChange(next: Operator): void;
163
- /** Two-way bind for primitive value control. */
164
- onEditingValueInput(value: unknown): void;
165
- /** BETWEEN range mutators. */
166
- onEditingRangeFrom(value: string | number | null): void;
167
- onEditingRangeTo(value: string | number | null): void;
168
- /** Toggle a value inside the staged multi-select array. */
169
- toggleEditingMultiValue(value: unknown): void;
170
- isEditingMultiSelected(value: unknown): boolean;
171
127
  /**
172
- * Commit the staged operator + value into the chip when the popover closes.
173
- * why: nút Áp dụng đã bị bỏ — đóng popover (out-focus) tự động áp dụng phần
174
- * chỉnh sửa đang staging. Không emit: nút Search toàn cục vẫn là trigger query duy nhất.
128
+ * Called when a popover-mode chip is clicked set editingIndex and seed the
129
+ * child popover's staging signals from the chip's Filter.
175
130
  */
176
- commitChipEditOnClose(): void;
131
+ openChipPopover(index: number): void;
132
+ /** Receive `(commit)` from the child popover — splice into filters, null the index. */
133
+ onChipPopoverCommit(next: Filter): void;
177
134
  static ɵfac: i0.ɵɵFactoryDeclaration<SdQueryBar, never>;
178
- static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryBar, "sd-query-bar", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "filters": { "alias": "filters"; "required": false; "isSignal": true; }; "logic": { "alias": "logic"; "required": false; "isSignal": true; }; "search": { "alias": "search"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "showSearch": { "alias": "showSearch"; "required": false; "isSignal": true; }; "showSavedViews": { "alias": "showSavedViews"; "required": false; "isSignal": true; }; "showLogicToggle": { "alias": "showLogicToggle"; "required": false; "isSignal": true; }; "showClearAll": { "alias": "showClearAll"; "required": false; "isSignal": true; }; "showOperatorOnChip": { "alias": "showOperatorOnChip"; "required": false; "isSignal": true; }; }, { "filters": "filtersChange"; "logic": "logicChange"; "search": "searchChange"; "queryChange": "queryChange"; "apply": "apply"; }, never, never, true, never>;
135
+ static ɵcmp: i0.ɵɵComponentDeclaration<SdQueryBar, "sd-query-bar", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "filters": { "alias": "filters"; "required": false; "isSignal": true; }; "logic": { "alias": "logic"; "required": false; "isSignal": true; }; "search": { "alias": "search"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "showSearch": { "alias": "showSearch"; "required": false; "isSignal": true; }; "showSavedFilters": { "alias": "showSavedFilters"; "required": false; "isSignal": true; }; "savedFiltersKey": { "alias": "savedFiltersKey"; "required": false; "isSignal": true; }; "showLogicToggle": { "alias": "showLogicToggle"; "required": false; "isSignal": true; }; "showClearAll": { "alias": "showClearAll"; "required": false; "isSignal": true; }; "showOperatorOnChip": { "alias": "showOperatorOnChip"; "required": false; "isSignal": true; }; }, { "filters": "filtersChange"; "logic": "logicChange"; "search": "searchChange"; "queryChange": "queryChange"; "apply": "apply"; }, never, never, true, never>;
179
136
  }
180
137
  export {};