@nxgt/material 3.27.0 → 3.28.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 (100) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/dist/{async-slice-gAbGnQT8.js → async-slice-DmhasXmq.js} +2 -2
  4. package/dist/{button-Cr9GIIj4.js → button-BjIg_Lz6.js} +1 -1
  5. package/dist/charts.js +3 -3
  6. package/dist/{chip-s11lOfxB.js → chip-DIBIDUZH.js} +1 -1
  7. package/dist/{code-editor-DGIjL8Hr.js → code-editor-2EU-q9FV.js} +4 -4
  8. package/dist/code-editor.js +4 -4
  9. package/dist/{code-language-items-DCOQnaCo.js → code-language-items-C_UeMQMm.js} +2 -2
  10. package/dist/components/ui/display/chip/chip-parts.css +19 -0
  11. package/dist/{components-DgpD3FJo.js → components-Cl3Zyoe-.js} +11757 -11283
  12. package/dist/components.js +26 -26
  13. package/dist/{dialog-Crvg-MN5.js → dialog-LtXwv6N3.js} +1 -1
  14. package/dist/dnd.js +1 -1
  15. package/dist/{dropdown-menu-B71aggp0.js → dropdown-menu-ppMPD12c.js} +1 -1
  16. package/dist/editor.js +7 -7
  17. package/dist/{empty-state-8LddxMU4.js → empty-state-X_nikpBS.js} +1 -1
  18. package/dist/hooks.js +2 -2
  19. package/dist/{i18n-provider-BDi9-6DO.js → i18n-provider-BfyDgd2o.js} +1 -1
  20. package/dist/i18n.js +5 -5
  21. package/dist/{icon-badge-DG7wLnHh.js → icon-badge-oLBh3Mlk.js} +1 -1
  22. package/dist/lib/components/ui/collections/facet-group/facet-group.d.ts +1 -1
  23. package/dist/lib/components/ui/collections/facet-group/types.d.ts +2 -0
  24. package/dist/lib/components/ui/collections/filter/bar/filter-bar-classes.d.ts +11 -1
  25. package/dist/lib/components/ui/collections/filter/bar/{filter-bar.d.ts → filter-bar-view.d.ts} +2 -2
  26. package/dist/lib/components/ui/collections/filter/bar/partials/filter-clear-all.d.ts +2 -2
  27. package/dist/lib/components/ui/collections/filter/bar/partials/filter-quick-pill.d.ts +4 -1
  28. package/dist/lib/components/ui/collections/filter/bar/partials/filter-quick-toggle.d.ts +3 -0
  29. package/dist/lib/components/ui/collections/filter/bar/partials/filter-scope-list.d.ts +6 -0
  30. package/dist/lib/components/ui/collections/filter/bar/partials/filter-scope-pill.d.ts +13 -0
  31. package/dist/lib/components/ui/collections/filter/bar/partials/use-quick-condition.d.ts +19 -0
  32. package/dist/lib/components/ui/collections/filter/bar/partials/use-quick-pill.d.ts +30 -0
  33. package/dist/lib/components/ui/collections/filter/bar/use-filter-bar-wiring.d.ts +5 -0
  34. package/dist/lib/components/ui/collections/filter/editors/boolean-editor.d.ts +3 -2
  35. package/dist/lib/components/ui/collections/filter/editors/checkbox-editor.d.ts +1 -1
  36. package/dist/lib/components/ui/collections/filter/editors/switch-editor.d.ts +1 -1
  37. package/dist/lib/components/ui/collections/filter/facets/filter-facets.d.ts +2 -2
  38. package/dist/lib/components/ui/collections/filter/filter-bar-url.d.ts +51 -0
  39. package/dist/lib/components/ui/collections/filter/index.d.ts +2 -0
  40. package/dist/lib/components/ui/collections/filter/internal.d.ts +3 -1
  41. package/dist/lib/components/ui/collections/filter/query/filter-results-status.d.ts +4 -1
  42. package/dist/lib/components/ui/collections/filter/query/types.d.ts +21 -3
  43. package/dist/lib/components/ui/collections/{server-table → filter/query}/use-answer-wait.d.ts +3 -1
  44. package/dist/lib/components/ui/collections/filter/query/use-apply-now.d.ts +6 -0
  45. package/dist/lib/components/ui/collections/filter/query/use-defaults.d.ts +15 -0
  46. package/dist/lib/components/ui/collections/filter/query/use-field-error.d.ts +5 -0
  47. package/dist/lib/components/ui/collections/filter/query/use-filter-query-options.d.ts +14 -0
  48. package/dist/lib/components/ui/collections/filter/query/use-filter-query-value.d.ts +2 -0
  49. package/dist/lib/components/ui/collections/filter/query/use-filter-query.d.ts +6 -2
  50. package/dist/lib/components/ui/collections/filter/query/use-filter-url-query.d.ts +52 -0
  51. package/dist/lib/components/ui/collections/filter/query/use-refusal-announcement.d.ts +10 -0
  52. package/dist/lib/components/ui/collections/filter/sections/chips/condition-panel.d.ts +2 -1
  53. package/dist/lib/components/ui/collections/filter/sections/chips/filter-chip-body.d.ts +4 -2
  54. package/dist/lib/components/ui/collections/filter/sections/chips/filter-chip-list.d.ts +3 -2
  55. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-chip.d.ts +14 -0
  56. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-group.d.ts +16 -0
  57. package/dist/lib/components/ui/collections/filter/sections/chips/filter-default-parts.d.ts +12 -0
  58. package/dist/lib/components/ui/collections/filter/sections/chips/filter-error-parts.d.ts +22 -0
  59. package/dist/lib/components/ui/collections/filter/sections/chips/use-control-description.d.ts +13 -0
  60. package/dist/lib/components/ui/collections/filter/sections/filter-facet-section.d.ts +5 -0
  61. package/dist/lib/components/ui/collections/filter/sections/filter-search.d.ts +4 -3
  62. package/dist/lib/components/ui/collections/filter/sections/filter-sections-classes.d.ts +8 -0
  63. package/dist/lib/components/ui/collections/filter/sections/renderers/choice-facet.d.ts +1 -1
  64. package/dist/lib/components/ui/collections/filter/sections/use-filter-shortcuts.d.ts +4 -3
  65. package/dist/lib/components/ui/collections/server-table/partials/server-table-empty-chips.d.ts +1 -1
  66. package/dist/lib/components/ui/collections/server-table/types.d.ts +13 -1
  67. package/dist/lib/components/ui/collections/server-table/use-filter-params.d.ts +5 -4
  68. package/dist/lib/components/ui/collections/server-table/use-table-answer.d.ts +1 -1
  69. package/dist/lib/i18n/resources/en/en.d.ts +11 -0
  70. package/dist/lib/i18n/resources/en/material.json.d.ts +11 -0
  71. package/dist/lib/i18n/resources/fr/fr.d.ts +11 -0
  72. package/dist/lib/i18n/resources/fr/material.json.d.ts +11 -0
  73. package/dist/lib/i18n/resources/resources.d.ts +22 -0
  74. package/dist/lib/i18n/translator.d.ts +1 -1
  75. package/dist/lib.js +1 -1
  76. package/dist/main.js +43 -43
  77. package/dist/map.js +4 -4
  78. package/dist/material.css +1 -1
  79. package/dist/pdf-reader.js +1 -1
  80. package/dist/print.js +2 -2
  81. package/dist/{public-QUiFLEoj.js → public-BeM7-x-m.js} +6 -6
  82. package/dist/{rich-code-block-CjD54THr.js → rich-code-block-B4TIjZRA.js} +4 -4
  83. package/dist/{sortable-provider-DYnyzfgR.js → sortable-provider-Dcsw0pgW.js} +1 -1
  84. package/dist/{spinner-CJtTRNAX.js → spinner-1Ia6Akhy.js} +1 -1
  85. package/dist/{stored-language-ClkfkueV.js → stored-language-DoWMr969.js} +22 -0
  86. package/dist/theme-picker.js +2 -2
  87. package/dist/{theme-toggle-ufQL3SO6.js → theme-toggle-GlKtdgYz.js} +1 -1
  88. package/dist/{toolbar-items-DlioFgpM.js → toolbar-items-C1GdN9P9.js} +2 -2
  89. package/dist/{translate-material-O-uasx3u.js → translate-material-BneuBHXZ.js} +2 -2
  90. package/dist/{translator-C0uxN1Nh.js → translator-D88BbpXZ.js} +1 -1
  91. package/dist/{use-chat-composer-DzVO5mwz.js → use-chat-composer-beyfZPBD.js} +12 -12
  92. package/dist/{use-heading-spy-BHCVdJfr.js → use-heading-spy-BN0yeBod.js} +1 -1
  93. package/dist/{use-material-translation-B4Frk3vC.js → use-material-translation-Cqcwkuur.js} +2 -2
  94. package/docs/components/data-table-filter-and-lists.md +184 -3
  95. package/docs/guides/i18n.md +7 -0
  96. package/docs/guides/server-lists-url.md +114 -1
  97. package/docs/roadmap.md +16 -0
  98. package/docs/troubleshooting.md +59 -2
  99. package/lib/components/ui/display/chip/chip-parts.css +19 -0
  100. package/package.json +2 -2
@@ -1,12 +1,14 @@
1
- export { FilterBar } from './bar/filter-bar.js';
1
+ export { FilterBarView } from './bar/filter-bar-view.js';
2
2
  export { FilterClearAll } from './bar/partials/filter-clear-all.js';
3
3
  export type { FilterBarFieldProps } from './editors/custom-types.js';
4
4
  export { FilterFacets } from './facets/filter-facets.js';
5
5
  export { FilterQueryProvider, useFilterQueryContext, } from './query/filter-query-context.js';
6
6
  export type { FilterQueryProps } from './query/types.js';
7
+ export { type AnswerWait, useAnswerWait, } from './query/use-answer-wait.js';
7
8
  export { useFilterAnnouncement } from './query/use-filter-announcement.js';
8
9
  export { FilterAnswerHost, useFilterAnswerWatch, } from './query/use-filter-answer-watch.js';
9
10
  export { useFilterQueryValue } from './query/use-filter-query-value.js';
11
+ export { type FilterUrlCodec, type FilterUrlQuery, type UseFilterUrlQueryOptions, useFilterUrlQuery, } from './query/use-filter-url-query.js';
10
12
  export { FilterChipBody } from './sections/chips/filter-chip-body.js';
11
13
  export { FilterChipList } from './sections/chips/filter-chip-list.js';
12
14
  export { FILTER_BAND_COMPACT_CLASS, FILTER_BAND_SURFACE_COMPACT_CLASS, } from './sections/filter-band-classes.js';
@@ -4,6 +4,9 @@
4
4
  * "Level is any of CE1, 24 results" after "Add filter"'s Done), never while
5
5
  * loading, pending or adding, never a stale count. Without `resultCount`,
6
6
  * only "Filters cleared" and the filter added. The core's `barAnnouncement`
7
- * decides what is said.
7
+ * decides what is said. The server's refusals (the `errors` prop) are told in
8
+ * the same region, "Period: The period cannot exceed 366 days.", as they are
9
+ * in the page, after the count, once (`useRefusalAnnouncement`): one frame after they first
10
+ * appear or change, and gone when the region next changes for its own reason.
8
11
  */
9
12
  export declare function FilterResultsStatus(): import("react").JSX.Element;
@@ -1,9 +1,9 @@
1
- import { FilterApply, FilterCountsOption, FilterLockedCondition, FilterModel, FilterPreviewCount, FilterQuery, FilterSearchApplyMode, FilterShortcutsOption } from '@nxgt/material-core/filter';
1
+ import { FilterApply, FilterCountsOption, FilterDefaults, FilterFieldErrors, FilterLockedCondition, FilterModel, FilterPreviewCount, FilterQuery, FilterSearchApplyMode, FilterShortcutsOption } from '@nxgt/material-core/filter';
2
2
  import { FilterBarFieldProps } from '../editors/custom-types.js';
3
3
  /** The bar's spacing: `compact` draws small chips; every target stays 24px or more. */
4
4
  export type FilterDensity = 'comfortable' | 'compact';
5
- /** The props `FilterBar` and `FilterFacets` share. */
6
- export type FilterBarProps = {
5
+ /** The props `FilterBarView` and `FilterFacets` share. */
6
+ export type FilterViewProps = {
7
7
  label?: string;
8
8
  searchLabel?: string;
9
9
  searchPlaceholder?: string;
@@ -54,6 +54,24 @@ export type FilterQueryProps = {
54
54
  onQueryChange?: (query: FilterQuery) => void;
55
55
  /** The conditions the page imposes: a lock, no ✕, never in `query`. */
56
56
  locked?: readonly FilterLockedCondition[];
57
+ /**
58
+ * The values of the `default: 'page'` fields, the same object as the
59
+ * loader's (a fixed `default` needs nothing). A field with a default and
60
+ * no condition of the user's shows it, uncounted and with no ✕: a hint
61
+ * chip, a pressed quick toggle, a "Default: …" note in the facets and the
62
+ * sheet. It is never in `query`: choosing a value replaces it, and "Clear
63
+ * all" returns to it.
64
+ */
65
+ defaults?: FilterDefaults;
66
+ /**
67
+ * A server's refusal of a condition, by field id: `{ period: 'The period
68
+ * cannot exceed 366 days.' }`. The field's chip (or quick pill) reads
69
+ * "Invalid" in the error tone, described by the message; its editor and
70
+ * its facets section show the message; the live region tells it. Only a
71
+ * field of the model the page does not lock; cleared by the page when the
72
+ * condition changes (the loader answers again).
73
+ */
74
+ errors?: FilterFieldErrors;
57
75
  /** How long the live apply waits after an edit (ms, default 200). */
58
76
  liveDelayMs?: number;
59
77
  /**
@@ -51,5 +51,7 @@ export declare function graceOf(held: Held | null): number | null;
51
51
  * takes it: the params reach its target (`key`), or a foreign change drops
52
52
  * it, or `WRITE_GRACE_MS` does if the router never takes it. What the page
53
53
  * answers after that is not this hook's: `useTableAnswer` watches it.
54
+ * `enabled: false` (a page that already owns the wait) keeps it inert: no
55
+ * timer, and a `write` that hands the params straight on.
54
56
  */
55
- export declare function useAnswerWait(key: string): AnswerWait;
57
+ export declare function useAnswerWait(key: string, enabled?: boolean): AnswerWait;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * "Apply now", one shot: the edit that asked is applied by the live timer (set
3
+ * in this commit, 0 ms); an edit that changed nothing must not leave the next
4
+ * one without its delay.
5
+ */
6
+ export declare function useApplyNow(): [boolean, () => void];
@@ -0,0 +1,15 @@
1
+ import { FilterCondition, FilterModelField } from '@nxgt/material-core/filter';
2
+ /**
3
+ * The values a field is filtered by when the user chose none: its `default`
4
+ * (the page's `defaults` for a `'page'` one), `undefined` for none or while
5
+ * the page locks the field. Whether they apply now is `useIsDefaulted`.
6
+ */
7
+ export declare function useFieldDefault(field: FilterModelField): readonly string[] | undefined;
8
+ /** Whether the field is filtered by its default now: it has one and the user (or the staged draft) set no value. */
9
+ export declare function useIsDefaulted(field: FilterModelField): boolean;
10
+ /**
11
+ * The defaults that get a hint chip in the active filters: uncounted, no ✕
12
+ * (the core's `defaultHints`: not a toggle that is on, not a quick pill,
13
+ * which show the default themselves).
14
+ */
15
+ export declare function useDefaultHints(): FilterCondition[];
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The server's refusal of this field (the `errors` prop), `undefined` for
3
+ * none, for a field the model lacks and for a field the page locks.
4
+ */
5
+ export declare function useFieldError(field: string): string | undefined;
@@ -0,0 +1,14 @@
1
+ import { FilterQueryProps } from './types.js';
2
+ /** The props the model only carries through, with their defaults. */
3
+ export declare function viewOptions({ defaults, errors, loading, resultCount, density, apply, searchApply, searchMinLength, previewCount, counts, }: FilterQueryProps): {
4
+ defaults: Readonly<Record<string, readonly string[]>> | undefined;
5
+ errors: Readonly<Record<string, string>> | undefined;
6
+ loading: boolean;
7
+ resultCount: number | undefined;
8
+ density: import('./types.js').FilterDensity;
9
+ apply: import('@nxgt/material-core/filter').FilterApply;
10
+ searchApply: import('@nxgt/material-core/filter').FilterSearchApplyMode;
11
+ searchMinLength: number;
12
+ previewCount: import('@nxgt/material-core/filter').FilterPreviewCount | undefined;
13
+ counts: import('@nxgt/material-core/filter').FilterCountsOption | undefined;
14
+ };
@@ -14,6 +14,8 @@ export declare function useFilterQueryValue(props: FilterQueryProps): {
14
14
  shortcuts: import('@nxgt/material-core/filter').FilterShortcutKeys;
15
15
  model: import('@nxgt/material-core/filter').FilterModel;
16
16
  machine: import('@nxgt/material-core/filter').FilterMachineState;
17
+ defaults?: import('@nxgt/material-core/filter').FilterDefaults;
18
+ errors?: import('@nxgt/material-core/filter').FilterFieldErrors;
17
19
  applied: import('@nxgt/material-core/filter').FilterQuery;
18
20
  editing: string | null;
19
21
  pending: boolean;
@@ -1,4 +1,4 @@
1
- import { FilterApply, FilterCountsOption, FilterEvent, FilterFocusTarget, FilterMachineState, FilterModel, FilterPreviewCount, FilterQuery } from '@nxgt/material-core/filter';
1
+ import { FilterApply, FilterCountsOption, FilterDefaults, FilterEvent, FilterFieldErrors, FilterFocusTarget, FilterMachineState, FilterModel, FilterPreviewCount, FilterQuery } from '@nxgt/material-core/filter';
2
2
  import { RefObject } from 'react';
3
3
  import { FilterDensity, FilterQueryProps, FilterSearchApply } from './types.js';
4
4
  import { FilterBarFields } from './use-filter-bar-fields.js';
@@ -6,6 +6,10 @@ import { FilterBarFields } from './use-filter-bar-fields.js';
6
6
  export type FilterQueryModel = FilterBarFields & {
7
7
  model: FilterModel;
8
8
  machine: FilterMachineState;
9
+ /** The `default: 'page'` fields' values (the `defaults` prop). */
10
+ defaults?: FilterDefaults;
11
+ /** A server's refusal per field id (the `errors` prop). */
12
+ errors?: FilterFieldErrors;
9
13
  applied: FilterQuery;
10
14
  editing: string | null;
11
15
  /** An edit not carried yet: the count shown is the previous query's. */
@@ -42,4 +46,4 @@ export type FilterQueryModel = FilterBarFields & {
42
46
  * and `locked` mirrored into it (an equal one changes nothing), and live
43
47
  * apply. Thin by design: every decision is the core's.
44
48
  */
45
- export declare function useFilterQuery({ model, query, defaultQuery, onQueryChange, locked, liveDelayMs, loading, resultCount, density, shortcuts: shortcutsOption, apply, searchApply, searchMinLength, previewCount, counts, }: FilterQueryProps): FilterQueryModel;
49
+ export declare function useFilterQuery(props: FilterQueryProps): FilterQueryModel;
@@ -0,0 +1,52 @@
1
+ import { FilterDefaults, FilterLockedCondition, FilterModel, FilterQuery } from '@nxgt/material-core/filter';
2
+ import { AnswerWait } from './use-answer-wait.js';
3
+ /**
4
+ * How the page reads and writes the URL, to match the loader's
5
+ * `parseFilterQuery` / `serializeFilterQuery` options exactly: without them
6
+ * the chips and the loader's rows can disagree.
7
+ */
8
+ export type FilterUrlCodec = {
9
+ /** Keeps the readable values of a list condition (`status=A&status=zzz`). */
10
+ keepKnownValues?: boolean;
11
+ /** `'standard'` writes `URLSearchParams`' own text; default `'readable'`. */
12
+ encoding?: 'readable' | 'standard';
13
+ };
14
+ export type UseFilterUrlQueryOptions = {
15
+ model: FilterModel;
16
+ /** The search params the page is at (the router's). */
17
+ params: URLSearchParams;
18
+ /** Hands the router the next params; the hook then waits for it to take them. */
19
+ onParamsChange: (next: URLSearchParams) => void;
20
+ /** The conditions the page imposes: never read from, nor written to, the URL. */
21
+ locked?: readonly FilterLockedCondition[];
22
+ /** The values of the `default: 'page'` fields, the loader's own. */
23
+ defaults?: FilterDefaults;
24
+ codec?: FilterUrlCodec;
25
+ /** Params dropped on every write: a cursor, a page, so a new query starts over. */
26
+ reset?: readonly string[];
27
+ /** The write the page has already started waiting on (`ServerTable`'s), else the hook's own. */
28
+ wait?: AnswerWait;
29
+ };
30
+ export type FilterUrlQuery = {
31
+ /** The user's query, read from where the list is heading. */
32
+ query: FilterQuery;
33
+ /** Writes the query into the params (the `reset` ones dropped, the others kept). */
34
+ onQueryChange: (next: FilterQuery) => void;
35
+ /** A write the router has not taken yet: the count on screen is the previous query's. */
36
+ waiting: boolean;
37
+ /** Where the list is heading: the write not taken yet, else the params. */
38
+ heading: string;
39
+ };
40
+ /**
41
+ * A filter's query bound to the search params: read from them, written back
42
+ * on a change with the `reset` params dropped (the cursor starts over), and
43
+ * `waiting` from the write until the router takes it. The page's own params
44
+ * (a sort, a tab) survive a write; the locked conditions are never written.
45
+ * `FilterBar` and `ServerTable` both use it, so they share one URL path.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * const { query, onQueryChange, waiting } = useFilterUrlQuery({ model, params, onParamsChange: setParams });
50
+ * ```
51
+ */
52
+ export declare function useFilterUrlQuery({ model, params, onParamsChange, locked, defaults, codec, reset, wait, }: UseFilterUrlQueryOptions): FilterUrlQuery;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The refusal text the bar's one live region adds to its message, once. It
3
+ * appears one frame after it is first there or changes (a refusal present at
4
+ * mount included, so the region changes after mount and is read), stays while
5
+ * the region says the same thing, and leaves when the region next changes for
6
+ * its own reason (a new count): that change is read anyway, so the count is
7
+ * never read a second time on the refusal's account, and no timer is involved.
8
+ * Clearing the refusal forgets it, so the same one returning is told again.
9
+ */
10
+ export declare function useRefusalAnnouncement(refusal: string, base: string): string;
@@ -12,6 +12,7 @@ export type ConditionPanelProps = {
12
12
  /**
13
13
  * A chip's edit popover: a dialog named by its title ("Level is not", as in
14
14
  * "Add filter"; no operator picker: "Add filter" replaces a condition), the
15
- * field's value editor in it, the focus on its first control.
15
+ * field's value editor in it, the focus on its first control. A condition
16
+ * the server refused shows its message under the title.
16
17
  */
17
18
  export declare function ConditionPanel({ field, condition, Editor, onValues, onInteractOutside, onCloseAutoFocus, }: ConditionPanelProps): import("react").JSX.Element;
@@ -2,11 +2,13 @@ import { FilterLabeledParts } from '@nxgt/material-core/filter';
2
2
  import { ChipProps } from '../../../../display/chip/chip.js';
3
3
  export type FilterChipBodyProps = Omit<ChipProps, 'label' | 'dismissLabel' | 'size'> & {
4
4
  parts: FilterLabeledParts;
5
+ /** The server's refusal of this filter: the error tone and "Invalid" beside the words (`aria-describedby` is the caller's). */
6
+ error?: string;
5
7
  };
6
8
  /**
7
9
  * A user's filter as a chip: its words (`FilterChipLabel`), its ✕ named
8
- * "Remove <filter>", sized by the filter's density and marked with
10
+ * "Remove <filter>" (in the error tone, with "Invalid", when the server refused it), sized by the filter's density and marked with
9
11
  * `FILTER_CHIP_ATTRIBUTE` for the focus rules. `FilterChip` adds its edit
10
12
  * popover; ServerTable's empty page renders it as is.
11
13
  */
12
- export declare function FilterChipBody({ parts, ...props }: FilterChipBodyProps): import("react").JSX.Element;
14
+ export declare function FilterChipBody({ parts, error, ...props }: FilterChipBodyProps): import("react").JSX.Element;
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * The active filters, a list named "Active filters": the page's locked
3
3
  * conditions first, then the user's in the order they were added, but what
4
- * the quick filters show themselves (`chipConditions`). Nothing when there
5
- * is none. The facets panel lists only the fields it has no section for
4
+ * the quick filters show themselves (`chipConditions`), then a hint chip for
5
+ * each default in effect (`FilterDefaultChip`: uncounted, no ✕). Nothing when
6
+ * there is none. The facets panel lists only the fields it has no section for
6
7
  * (`fields`), without the locked ones (it lists them itself), from its
7
8
  * draft while one is staged.
8
9
  */
@@ -0,0 +1,14 @@
1
+ import { FilterCondition, FilterLabeledParts } from '@nxgt/material-core/filter';
2
+ /**
3
+ * A default in effect, as the active filters list it: the field's words and
4
+ * values, then "Default", dashed beside the tinted chips of what the user
5
+ * set. No ✕, no count, no announcement. A button named "Status: Active,
6
+ * Upcoming, default value. Change", described "Default value, …": it opens
7
+ * the field's editor on the default, like an applied chip does, and the first
8
+ * edit makes the choice the user's own. A field with no editor (a custom one
9
+ * without `render`) gets a focusable `group` instead.
10
+ */
11
+ export declare function FilterDefaultChip({ condition, parts, }: {
12
+ condition: FilterCondition;
13
+ parts: FilterLabeledParts;
14
+ }): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { FilterLabeledParts } from '@nxgt/material-core/filter';
2
+ import { ReactNode } from 'react';
3
+ /**
4
+ * The default chip of a field with no editor (a custom one without `render`):
5
+ * nothing to open, so a focusable `group` named by its words, with the hint
6
+ * as its tooltip and description.
7
+ */
8
+ export declare function FilterDefaultGroup({ parts, name, hint, density, describedBy, invalid, children, }: {
9
+ parts: FilterLabeledParts;
10
+ name: string;
11
+ hint: string;
12
+ density: 'comfortable' | 'compact';
13
+ describedBy: string | undefined;
14
+ invalid: boolean;
15
+ children: ReactNode;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ /** "Default" as the hint chip, a pill and a toggle name it (`material.filter.default.*`). */
2
+ export declare function useDefaultWords(): {
3
+ label: string;
4
+ hint: string;
5
+ tag: string;
6
+ };
7
+ /** The "· Default" tag after a pill's or toggle's words: for the eye only, the hint describes it. */
8
+ export declare function FilterDefaultTag(): import("react").JSX.Element;
9
+ /** The hint a defaulted control is described by (`aria-describedby={id}`). */
10
+ export declare function FilterDefaultHint({ id }: {
11
+ id: string;
12
+ }): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ /** "Invalid" and the sentence a screen reader gets (`material.filter.error.*`). */
2
+ export declare function useErrorWords(message: string): {
3
+ tag: string;
4
+ label: string;
5
+ };
6
+ /**
7
+ * The word after a refused chip's or pill's value: an icon and "Invalid", so
8
+ * the state is never colour alone. For the eye only; the description says it.
9
+ */
10
+ export declare function FilterErrorTag({ message }: {
11
+ message: string;
12
+ }): import("react").JSX.Element;
13
+ /** What a refused chip or pill is described by (`aria-describedby={id}`). */
14
+ export declare function FilterErrorDescription({ id, message, }: {
15
+ id: string;
16
+ message: string;
17
+ }): import("react").JSX.Element;
18
+ /** The refusal in a field's editor or section: its icon, the word and the message. */
19
+ export declare function FilterErrorNote({ id, message, }: {
20
+ id: string;
21
+ message: string;
22
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * What a control that can be defaulted and refused is described by: the
4
+ * `aria-describedby` ids, joined, the ids themselves, and the two sr-only nodes they name (the
5
+ * default's hint, the error's sentence), to render beside the control.
6
+ * Shared by the chips, the pills and the toggles, which each carried a copy.
7
+ */
8
+ export declare function useControlDescription(byDefault: boolean, error: string | undefined): {
9
+ describedBy: string | undefined;
10
+ hintId: string;
11
+ errorId: string;
12
+ nodes: ReactNode;
13
+ };
@@ -8,6 +8,11 @@ import { FilterModelField } from '@nxgt/material-core/filter';
8
8
  * focus stays on the control. A lone switch or checkbox sits in a
9
9
  * full-width label, its row, which toggles it. It starts open when `roomy`
10
10
  * (the panel from 1024px), else only with a condition set (`sectionOpen`).
11
+ * A field in effect by its default (no value of the user's) shows it checked,
12
+ * with "Default" beside its title; unchecking or changing one makes the
13
+ * choice the user's own, counted and in the URL. A scope field (`scope: true`)
14
+ * is the first section, with no count, no Clear and no "Default". A condition
15
+ * the server refused shows its message under the title.
11
16
  */
12
17
  export declare function FilterFacetSection({ field, roomy, }: {
13
18
  field: FilterModelField;
@@ -3,9 +3,10 @@
3
3
  * (default) sends it as it is typed, applied after `liveDelayMs`;
4
4
  * `"enter"` keeps the text in a draft until Enter. Below `searchMinLength`
5
5
  * nothing is sent and a hint is announced politely. Clearing (✕, Escape)
6
- * applies at once in `"enter"`; `/` (its hint shown) focuses it.
6
+ * applies at once in `"enter"`; `/` (its hint shown) focuses it. Nothing for
7
+ * a model declared `search: false`.
7
8
  */
8
- export declare function FilterSearch({ label, placeholder, }: {
9
+ export declare function FilterSearch(props: {
9
10
  label?: string;
10
11
  placeholder?: string;
11
- }): import("react").JSX.Element;
12
+ }): import("react").JSX.Element | null;
@@ -36,6 +36,14 @@ export declare const FILTER_LOCKED_CHIP_CLASS: {
36
36
  readonly comfortable: "inline-flex max-w-full cursor-default items-center border border-[color-mix(in_oklab,var(--foreground)_15%,var(--background))] bg-muted/60 font-medium text-foreground outline-0 outline-transparent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--primary-text) h-7 gap-[0.3125rem] rounded-lg px-2 text-[0.8125rem]";
37
37
  readonly compact: "inline-flex max-w-full cursor-default items-center border border-[color-mix(in_oklab,var(--foreground)_15%,var(--background))] bg-muted/60 font-medium text-foreground outline-0 outline-transparent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--primary-text) h-6 gap-1 rounded-[0.4375rem] px-2 text-xs";
38
38
  };
39
+ export declare const FILTER_DEFAULT_CHIP_CLASS: {
40
+ readonly comfortable: "inline-flex max-w-full cursor-default items-center border border-dashed border-[color-mix(in_oklab,var(--foreground)_30%,var(--background))] bg-transparent text-muted-foreground outline-0 outline-transparent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--primary-text) h-7 gap-[0.3125rem] rounded-lg px-2 text-[0.8125rem]";
41
+ readonly compact: "inline-flex max-w-full cursor-default items-center border border-dashed border-[color-mix(in_oklab,var(--foreground)_30%,var(--background))] bg-transparent text-muted-foreground outline-0 outline-transparent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--primary-text) h-6 gap-1 rounded-[0.4375rem] px-2 text-xs";
42
+ };
43
+ /** A refusal in an editor or a section: the error tone's text, an icon, the word and the message. */
44
+ export declare const FILTER_ERROR_NOTE_CLASS = "mb-2 flex items-start gap-1.5 text-sm text-error-text";
45
+ /** The "Default" tag after a hint's words, or a pill's or toggle's. */
46
+ export declare const FILTER_DEFAULT_TAG_CLASS = "shrink-0 text-xs font-normal text-muted-foreground";
39
47
  /** The chip's operator, quieter than the field and its value. */
40
48
  export declare const FILTER_CHIP_OPERATOR_CLASS = "text-muted-foreground";
41
49
  /** The chip's value. */
@@ -6,4 +6,4 @@ import { FilterEditorProps } from '../../editors/types.js';
6
6
  * `disabled`), each option with its count as every option group shows it
7
7
  * ("CE1 24", named "CE1 24 results"). A long list folds behind "Show more".
8
8
  */
9
- export declare function ChoiceFacet({ field, op, values, onValuesChange, labelledBy, }: FilterEditorProps): import("react").JSX.Element;
9
+ export declare function ChoiceFacet({ field, op, values, onValuesChange, labelledBy, describedBy, }: FilterEditorProps): import("react").JSX.Element;
@@ -1,11 +1,12 @@
1
- import { FilterQueryModel } from '../query/use-filter-query.js';
1
+ import { FilterQueryContextValue } from '../query/filter-query-context.js';
2
2
  /**
3
3
  * The bar's keys, on the window: `/` focuses the search and `F` opens "Add
4
4
  * filter", or the sheet on a phone (the core's `shortcutFor`: never while
5
5
  * typing, with a modifier, or while a layer is open, the bar's own popovers
6
- * included). Off with `shortcuts={false}`.
6
+ * included). Off with `shortcuts={false}`. A model with `search: false` sends
7
+ * `/` to the first quick filter.
7
8
  */
8
- export declare function useFilterShortcuts({ shortcuts, machine, editing, send, focus, canAdd, openSheet, }: Pick<FilterQueryModel, 'shortcuts' | 'machine' | 'editing' | 'send' | 'focus'> & {
9
+ export declare function useFilterShortcuts({ shortcuts, model, quick, machine, editing, send, focus, canAdd, openSheet, }: Pick<FilterQueryContextValue, 'shortcuts' | 'model' | 'quick' | 'machine' | 'editing' | 'send' | 'focus'> & {
9
10
  /** The bar shows "Add filter", or the sheet a section (some field is not locked). */
10
11
  canAdd: boolean;
11
12
  /** On a phone: `F` opens the sheet. */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * "Nothing matches": the user's filters that narrow the list, as chips
3
- * removed by their ✕ (a widening switch such as "Show archived" is not
3
+ * removed by their ✕ (a kept field, a widening switch such as "Show archived" or a scope such as the period, is not
4
4
  * one, a locked condition stays in the band), then "Clear all" while two
5
5
  * or a search remain. A removal focuses the next chip, then "Clear all",
6
6
  * then the search (the core's `focusAfterRemove`, from `empty`).
@@ -1,4 +1,4 @@
1
- import { FilterLockedCondition, FilterModel } from '@nxgt/material-core/filter';
1
+ import { FilterDefaults, FilterFieldErrors, FilterLockedCondition, FilterModel } from '@nxgt/material-core/filter';
2
2
  import { IconStyleInput } from '@nxgt/material-core/icons';
3
3
  import { ErrorStateKind } from '@nxgt/material-core/states';
4
4
  import { PagingNames, TableFilterBinding, TableSorting } from '@nxgt/material-core/table-url';
@@ -64,6 +64,18 @@ export type ServerTableFilter = {
64
64
  model: FilterModel;
65
65
  /** The conditions the page imposes: a lock in the band, never in the URL. */
66
66
  locked?: readonly FilterLockedCondition[];
67
+ /**
68
+ * The values of the `default: 'page'` fields, the same object as the
69
+ * loader's. The band shows a defaulted value (a hint chip, a pressed
70
+ * toggle), uncounted and with no ✕; the URL holds explicit choices only.
71
+ */
72
+ defaults?: FilterDefaults;
73
+ /**
74
+ * A server's refusal of a condition, by field id (`{ period: 'The period
75
+ * cannot exceed 366 days.' }`): the chip reads "Invalid", described by the
76
+ * message, the editor shows it and the live region tells it.
77
+ */
78
+ errors?: FilterFieldErrors;
67
79
  /**
68
80
  * How the page reads and writes the URL, to match the loader's
69
81
  * `parseFilterQuery` / `serializeFilterQuery` options exactly:
@@ -3,9 +3,10 @@ import { FilterQueryProps } from '../filter/internal.js';
3
3
  import { ServerTableFilter, ServerTableProps } from './types.js';
4
4
  import { TableAnswer } from './use-table-answer.js';
5
5
  /**
6
- * The Filter's props, bound to the search params: its query read from them,
7
- * and written back on a change, back on the first page (the cursor reset).
8
- * From that write until its answer lands (`announcing`), the Filter is told
9
- * `loading`: the count it would say is the previous query's.
6
+ * The Filter's props, bound to the search params through `useFilterUrlQuery`
7
+ * (the one `FilterBar` uses): its query read from them, and written back on a
8
+ * change, back on the first page (the cursor reset). From that write until
9
+ * its answer lands (`announcing`), the Filter is told `loading`: the count it
10
+ * would say is the previous query's.
10
11
  */
11
12
  export declare function useFilterParams<T extends RowData>(props: ServerTableProps<T>, filter: ServerTableFilter, { wait: answer, announcing }: TableAnswer): FilterQueryProps;
@@ -1,7 +1,7 @@
1
1
  import { FilterAnswerWatch } from '@nxgt/material-core/filter';
2
2
  import { RowData } from '@tanstack/react-table';
3
+ import { AnswerWait } from '../filter/internal.js';
3
4
  import { ServerTableFilter, ServerTableProps } from './types.js';
4
- import { AnswerWait } from './use-answer-wait.js';
5
5
  /** What changes with an answer of the page (pure): the count, the rows
6
6
  * (`rows`: which array, counted), the error. */
7
7
  export declare function tableAnswerCount(totalCount: number, rows: number, errored: boolean): string;
@@ -1332,6 +1332,17 @@ export declare const en: {
1332
1332
  until: string;
1333
1333
  "up-to": string;
1334
1334
  };
1335
+ default: {
1336
+ label: string;
1337
+ hint: string;
1338
+ tag: string;
1339
+ change: string;
1340
+ };
1341
+ error: {
1342
+ tag: string;
1343
+ label: string;
1344
+ announce: string;
1345
+ };
1335
1346
  bar: {
1336
1347
  label: string;
1337
1348
  search: string;
@@ -1322,6 +1322,17 @@ declare const _default: {
1322
1322
  "until": "Until {value}",
1323
1323
  "up-to": "Up to {value}"
1324
1324
  },
1325
+ "default": {
1326
+ "label": "Default",
1327
+ "hint": "Default value, in effect until you choose one",
1328
+ "tag": "· {default}",
1329
+ "change": "{filter}, default value. Change"
1330
+ },
1331
+ "error": {
1332
+ "tag": "Invalid",
1333
+ "label": "Invalid: {message}",
1334
+ "announce": "{field}: {message}"
1335
+ },
1325
1336
  "bar": {
1326
1337
  "label": "Filters",
1327
1338
  "search": "Search",
@@ -1332,6 +1332,17 @@ export declare const fr: {
1332
1332
  until: string;
1333
1333
  "up-to": string;
1334
1334
  };
1335
+ default: {
1336
+ label: string;
1337
+ hint: string;
1338
+ tag: string;
1339
+ change: string;
1340
+ };
1341
+ error: {
1342
+ tag: string;
1343
+ label: string;
1344
+ announce: string;
1345
+ };
1335
1346
  bar: {
1336
1347
  label: string;
1337
1348
  search: string;
@@ -1322,6 +1322,17 @@ declare const _default: {
1322
1322
  "until": "Jusqu'au {value}",
1323
1323
  "up-to": "Jusqu'à {value}"
1324
1324
  },
1325
+ "default": {
1326
+ "label": "Par défaut",
1327
+ "hint": "Valeur par défaut, appliquée tant que vous n'en choisissez pas une",
1328
+ "tag": "· {default}",
1329
+ "change": "{filter}, valeur par défaut. Modifier"
1330
+ },
1331
+ "error": {
1332
+ "tag": "Invalide",
1333
+ "label": "Invalide : {message}",
1334
+ "announce": "{field} : {message}"
1335
+ },
1325
1336
  "bar": {
1326
1337
  "label": "Filtres",
1327
1338
  "search": "Rechercher",
@@ -1330,6 +1330,17 @@ export declare const resources: {
1330
1330
  until: string;
1331
1331
  "up-to": string;
1332
1332
  };
1333
+ default: {
1334
+ label: string;
1335
+ hint: string;
1336
+ tag: string;
1337
+ change: string;
1338
+ };
1339
+ error: {
1340
+ tag: string;
1341
+ label: string;
1342
+ announce: string;
1343
+ };
1333
1344
  bar: {
1334
1345
  label: string;
1335
1346
  search: string;
@@ -4052,6 +4063,17 @@ export declare const resources: {
4052
4063
  until: string;
4053
4064
  "up-to": string;
4054
4065
  };
4066
+ default: {
4067
+ label: string;
4068
+ hint: string;
4069
+ tag: string;
4070
+ change: string;
4071
+ };
4072
+ error: {
4073
+ tag: string;
4074
+ label: string;
4075
+ announce: string;
4076
+ };
4055
4077
  bar: {
4056
4078
  label: string;
4057
4079
  search: string;