@godxjp/ui 31.5.0 → 31.6.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 (62) hide show
  1. package/agent/START-HERE.md +5 -5
  2. package/agent/components/BranchScopePicker.json +5 -0
  3. package/agent/components/Cascader.json +1 -1
  4. package/agent/components/DataTable.json +2 -2
  5. package/agent/components/InfiniteQueryState.json +6 -1
  6. package/agent/components/RangeTimeline.json +6 -0
  7. package/agent/components/RecordPicker.json +10 -0
  8. package/agent/components/Transfer.json +5 -0
  9. package/agent/components/Tree.json +21 -4
  10. package/agent/components/TreeSelect.json +1 -1
  11. package/agent/components.json +57 -9
  12. package/agent/index.json +5 -5
  13. package/agent/llms.txt +6 -6
  14. package/agent/tokens.json +6 -0
  15. package/dist/components/data-display/data-table.d.ts +3 -0
  16. package/dist/components/data-display/data-table.js +415 -370
  17. package/dist/components/data-display/range-timeline.d.ts +20 -0
  18. package/dist/components/data-display/range-timeline.js +217 -197
  19. package/dist/components/data-display/tree.js +179 -23
  20. package/dist/components/data-entry/branch-scope-picker.d.ts +1 -0
  21. package/dist/components/data-entry/branch-scope-picker.js +2 -1
  22. package/dist/components/data-entry/cascader.js +4 -5
  23. package/dist/components/data-entry/record-picker.d.ts +2 -0
  24. package/dist/components/data-entry/record-picker.js +22 -3
  25. package/dist/components/data-entry/transfer.d.ts +1 -1
  26. package/dist/components/data-entry/transfer.js +5 -2
  27. package/dist/components/data-entry/tree-select.js +14 -5
  28. package/dist/components/query/infinite-query-state.d.ts +1 -1
  29. package/dist/components/query/infinite-query-state.js +2 -1
  30. package/dist/contracts/measurement.json +1 -1
  31. package/dist/i18n/messages/en.json +16 -2
  32. package/dist/i18n/messages/ja.json +7 -2
  33. package/dist/i18n/messages/vi.json +7 -2
  34. package/dist/lib/hooks.d.ts +8 -4
  35. package/dist/lib/hooks.js +5 -2
  36. package/dist/lib/tree.d.ts +23 -0
  37. package/dist/lib/tree.js +29 -0
  38. package/dist/props/components/data-display.prop.d.ts +21 -2
  39. package/dist/props/components/data-entry.prop.d.ts +31 -4
  40. package/dist/props/components/query.prop.d.ts +8 -1
  41. package/dist/props/registry.d.ts +24 -6
  42. package/dist/props/registry.js +41 -4
  43. package/dist/props/vocabulary/data.prop.d.ts +32 -2
  44. package/dist/props/vocabulary/index.d.ts +1 -1
  45. package/dist/styles/data-display-layout.css +52 -0
  46. package/dist/styles/layers.json +1 -1
  47. package/dist/styles/table-layout.css +16 -1
  48. package/dist/tokens/components/tree.css +2 -0
  49. package/docs/data-display/data-table/examples/server-paged.tsx +23 -0
  50. package/docs/data-display/data-table/index.md +2 -0
  51. package/docs/data-display/timeline.tsx +33 -0
  52. package/docs/data-display/tree.tsx +154 -0
  53. package/docs/data-entry/branch-scope-picker.tsx +6 -1
  54. package/docs/data-entry/record-picker.tsx +1 -0
  55. package/docs/data-entry/transfer.tsx +1 -0
  56. package/docs/i18n/messages/en.json +19 -0
  57. package/docs/i18n/messages/ja.json +18 -0
  58. package/docs/i18n/messages/vi.json +18 -0
  59. package/docs/query/infinite-query-state.tsx +5 -1
  60. package/docs/roadmap/tree-components.md +2 -1
  61. package/package.json +2 -2
  62. package/scripts/ui-audit.mjs +15 -5
@@ -354,7 +354,8 @@
354
354
  "collapse": "Thu gọn",
355
355
  "loading": "Đang tải nút con…",
356
356
  "empty": "Không có gì để hiển thị",
357
- "selected": "Đã chọn"
357
+ "selected": "Đã chọn",
358
+ "filterMatch": "Khớp bộ lọc"
358
359
  },
359
360
  "thoughtChain": {
360
361
  "label": "Các bước suy luận",
@@ -573,7 +574,11 @@
573
574
  "sortDescending": "Sắp xếp giảm dần",
574
575
  "sortCancel": "Bỏ sắp xếp",
575
576
  "selectColumn": "Chọn",
576
- "scrollRegion": "Bảng có thể cuộn"
577
+ "scrollRegion": "Bảng có thể cuộn",
578
+ "selectPage": "Chọn tất cả các dòng trên trang này",
579
+ "matchingPage": "Đã chọn {count} dòng trên trang này.",
580
+ "matchingSelectAll": "Chọn tất cả {count} dòng khớp",
581
+ "matchingSelected": "Đã chọn tất cả {count} dòng khớp."
577
582
  },
578
583
  "dataGrid": {
579
584
  "search": "Tìm kiếm",
@@ -53,12 +53,16 @@ export declare function useScrollableRegionTabIndex(element: HTMLElement | null)
53
53
  * overflows. Reading it as "no overflow" would strand the overflow from every keyboard user — a
54
54
  * worse failure than an extra tab stop — so an unmeasured box counts as scrolling.
55
55
  *
56
- * `axis` is the box's OWN `overflow`, not a preference: an axis it does not scroll on is `hidden`
57
- * there, so overflow on that axis is CLIPPED rather than reachable, and measuring it would keep a
58
- * tab stop that scrolls nothing. `ScrollArea`'s `orientation` is exactly this union.
56
+ * `axis` names the axes the caller KNOWS scroll; an axis whose computed `overflow` is `auto` or
57
+ * `scroll` is measured as well, because the box scrolls there whatever the caller asked. An axis
58
+ * that is `hidden` CLIPS rather than scrolls, so it is never measured — that would keep a tab stop
59
+ * that scrolls nothing. `ScrollArea`'s `orientation` is exactly this union.
59
60
  */
60
61
  export declare function useScrollsOnAxis(ref: RefObject<HTMLElement | null>, enabled: boolean, axis: "horizontal" | "vertical" | "both"): boolean;
61
- /** A table's wrapper scrolls on one axis only, so it asks the one question it has (gh#817). */
62
+ /**
63
+ * The horizontal question a table asks (gh#817). The block axis is measured TOO whenever the box's
64
+ * computed `overflow-y` scrolls — `overflow-x: auto` computes it to `auto` — see `useScrollsOnAxis`.
65
+ */
62
66
  export declare function useScrollsHorizontally(ref: RefObject<HTMLElement | null>, enabled: boolean): boolean;
63
67
  /**
64
68
  * Nearest scrollable ancestor — the box an element actually scrolls inside — else `null`, which is
package/dist/lib/hooks.js CHANGED
@@ -111,9 +111,12 @@ function useScrollsOnAxis(ref, enabled, axis) {
111
111
  useEffect(() => {
112
112
  const el = ref.current;
113
113
  if (!enabled || !el) return void 0;
114
- const overflows = (client, scroll) => client === 0 || scroll - client > 1;
114
+ const overflows = (client, scroll) => scroll - client > 1;
115
+ const scrollsOn = (value) => value === "auto" || value === "scroll";
115
116
  const update = (sync) => {
116
- const next = axis !== "vertical" && overflows(el.clientWidth, el.scrollWidth) || axis !== "horizontal" && overflows(el.clientHeight, el.scrollHeight);
117
+ const unmeasured = el.clientWidth === 0 && el.clientHeight === 0;
118
+ const style = getComputedStyle(el);
119
+ const next = unmeasured || (axis !== "vertical" || scrollsOn(style.overflowX)) && overflows(el.clientWidth, el.scrollWidth) || (axis !== "horizontal" || scrollsOn(style.overflowY)) && overflows(el.clientHeight, el.scrollHeight);
117
120
  if (next && sync) flushSync(() => setScrolls(true));
118
121
  else setScrolls(next);
119
122
  };
@@ -50,4 +50,27 @@ export declare function filterVisibleTree(options: NormalizedTreeOption[], query
50
50
  }[];
51
51
  export declare function collectAllExpandableKeys(options: NormalizedTreeOption[]): string[];
52
52
  export declare function findNodeByValue(options: NormalizedTreeOption[], value: string): NormalizedTreeOption | undefined;
53
+ /**
54
+ * rc-tree gives up on a node after this many rejected `loadData` calls and treats it as loaded
55
+ * (rc-tree `MAX_RETRY_TIMES`), so a permanently broken endpoint cannot be hammered forever.
56
+ */
57
+ export declare const MAX_LAZY_LOAD_RETRIES = 10;
58
+ /**
59
+ * The lazy-children ledger shared by `Tree`, `TreeSelect` and `Cascader` — rc-tree's
60
+ * `loadedKeys` / `loadingKeys` / `loadingRetryTimes`, in one place (gh#1041).
61
+ *
62
+ * A key is asked for at most once while in flight and never again once it RESOLVED. A REJECTED
63
+ * load is not "loaded": the key leaves the in-flight set and the next expand asks again, until
64
+ * `MAX_LAZY_LOAD_RETRIES` failures. The old per-component ledgers recorded the key before the
65
+ * promise settled and never cleared it, so one network blip left a branch unloadable for the life
66
+ * of the component.
67
+ */
68
+ export type LazyLoadLedger = {
69
+ /**
70
+ * Call `load` for `key` unless it is in flight or already loaded. A synchronous throw counts
71
+ * as a rejection. `onSettle(ok)` runs once the load settles. Returns whether `load` was called.
72
+ */
73
+ run: (key: string, load: () => void | Promise<void>, onSettle?: (ok: boolean) => void) => boolean;
74
+ };
75
+ export declare function createLazyLoadLedger(): LazyLoadLedger;
53
76
  export {};
package/dist/lib/tree.js CHANGED
@@ -136,10 +136,39 @@ function findNodeByValue(options, value) {
136
136
  }
137
137
  return void 0;
138
138
  }
139
+ const MAX_LAZY_LOAD_RETRIES = 10;
140
+ function createLazyLoadLedger() {
141
+ const loaded = /* @__PURE__ */ new Set();
142
+ const inFlight = /* @__PURE__ */ new Set();
143
+ const failures = /* @__PURE__ */ new Map();
144
+ return {
145
+ run(key, load, onSettle) {
146
+ if (loaded.has(key) || inFlight.has(key)) return false;
147
+ inFlight.add(key);
148
+ new Promise((resolve) => resolve(load())).then(
149
+ () => {
150
+ inFlight.delete(key);
151
+ loaded.add(key);
152
+ onSettle?.(true);
153
+ },
154
+ () => {
155
+ inFlight.delete(key);
156
+ const count = (failures.get(key) ?? 0) + 1;
157
+ failures.set(key, count);
158
+ if (count >= MAX_LAZY_LOAD_RETRIES) loaded.add(key);
159
+ onSettle?.(false);
160
+ }
161
+ );
162
+ return true;
163
+ }
164
+ };
165
+ }
139
166
  export {
167
+ MAX_LAZY_LOAD_RETRIES,
140
168
  collectAllExpandableKeys,
141
169
  collectAllPaths,
142
170
  collectLeafPaths,
171
+ createLazyLoadLedger,
143
172
  filterTreeOptions,
144
173
  filterVisibleTree,
145
174
  findNodeByValue,
@@ -743,12 +743,31 @@ export type TreeProp = {
743
743
  /** Start with every branch open (antd `defaultExpandAll`). Seeded once, never re-applied. */
744
744
  defaultExpandAll?: boolean;
745
745
  /**
746
- * Lazy children (antd `loadData`). Called ONCE per node the first time a branch with no
747
- * `children` and `isLeaf !== true` is expanded; push the fetched children into `treeData`.
746
+ * Lazy children (antd `loadData`). Called when a branch with no `children` and
747
+ * `isLeaf !== true` is expanded, and never again once its promise RESOLVES; push the fetched
748
+ * children into `treeData`. A REJECTED promise is not a load: the branch folds back shut
749
+ * (uncontrolled expansion) and the next expand asks again, up to 10 attempts (rc-tree).
748
750
  */
749
751
  loadData?: (node: TreeNodeProp) => void | Promise<void>;
750
752
  /** Render a node's title (antd `titleRender`). */
751
753
  titleRender?: (node: TreeNodeProp) => React.ReactNode;
754
+ /**
755
+ * Highlight the nodes this returns `true` for (antd `filterTreeNode`) — the match of a search
756
+ * box above the tree. Matching rows are marked, NOT hidden: the outline, the keyboard path and
757
+ * every ARIA attribute stay exactly as they were. The row gets `data-filter-node="true"` and its
758
+ * label reads `--tree-node-filter-foreground` in the medium weight, plus an sr-only "matches"
759
+ * so the mark is never colour alone. Receives the node data, as `titleRender` and `loadData` do.
760
+ */
761
+ filterTreeNode?: (node: TreeNodeProp) => boolean;
762
+ /**
763
+ * Viewport height in px (antd `height`). The tree scrolls inside this height, and — unless
764
+ * `virtual` is `false` — renders only the rows in view (plus a small overscan), so a branch of
765
+ * several hundred lazily-loaded children stays a few dozen DOM rows. Rows must share one height
766
+ * (the `size` tier) for the window to be exact.
767
+ */
768
+ height?: number;
769
+ /** Set `false` to render every row even when `height` is set (antd `virtual`). Default `true`. */
770
+ virtual?: boolean;
752
771
  /** Draw the connector rails between a parent and its children (antd `showLine`). */
753
772
  showLine?: boolean;
754
773
  /**
@@ -1209,6 +1209,17 @@ export type RecordPickerProp = Omit<React.ButtonHTMLAttributes<HTMLButtonElement
1209
1209
  };
1210
1210
  placeholder?: string;
1211
1211
  dialogTitle?: string;
1212
+ /**
1213
+ * Node shown when the search finds nothing (antd `notFoundContent`) — in the dropdown shape and
1214
+ * in the dialog alike. Localized `dataEntry.recordPicker.empty` otherwise.
1215
+ */
1216
+ notFoundContent?: NotFoundContentProp;
1217
+ /**
1218
+ * Text of the dialog's load-more button (localized `dataEntry.recordPicker.more` otherwise). Only
1219
+ * the label: the button and when it appears (the server returned a `nextCursor`) stay the
1220
+ * picker's.
1221
+ */
1222
+ loadMoreLabel?: LabelProp;
1212
1223
  size?: "xs" | "sm" | "md" | "lg";
1213
1224
  /**
1214
1225
  * Tên trường, do `FormField` truyền xuống. Khai tường minh vì CẢ HAI nhánh phải giữ nó: một
@@ -1788,8 +1799,9 @@ export type CascaderProp = FieldA11yProps & {
1788
1799
  */
1789
1800
  showCheckedStrategy?: Exclude<ShowCheckedStrategyProp, "SHOW_ALL">;
1790
1801
  /**
1791
- * Lazy children (antd `loadData`). Called ONCE per node the first time a branch with no
1792
- * `children` and `isLeaf !== true` is expanded; push the fetched children into `options`.
1802
+ * Lazy children (antd `loadData`). Called when a branch with no `children` and
1803
+ * `isLeaf !== true` is expanded, and never again once its promise RESOLVES; push the fetched
1804
+ * children into `options`. A REJECTED promise is forgotten, so the next activation asks again.
1793
1805
  */
1794
1806
  loadData?: (selectedOptions: TreeOptionProp[]) => void | Promise<void>;
1795
1807
  /** Render the trigger label from the selected path (antd `displayRender`). */
@@ -1864,8 +1876,10 @@ export type TreeSelectProp = FieldA11yProps & {
1864
1876
  /** Panel open change (antd `onOpenChange`). Fires for both controlled and uncontrolled panels. */
1865
1877
  onOpenChange?: OnOpenChangeProp;
1866
1878
  /**
1867
- * Lazy children (antd `loadData`). Called ONCE per node the first time a branch with no
1868
- * `children` and `isLeaf !== true` is expanded; push the fetched children into `treeData`.
1879
+ * Lazy children (antd `loadData`). Called when a branch with no `children` and
1880
+ * `isLeaf !== true` is expanded, and never again once its promise RESOLVES; push the fetched
1881
+ * children into `treeData`. A REJECTED promise folds the branch shut and the next expand asks
1882
+ * again, up to 10 attempts (rc-tree).
1869
1883
  */
1870
1884
  loadData?: (node: TreeOptionProp) => void | Promise<void>;
1871
1885
  /** Render a node's title (antd `treeTitleRender`). */
@@ -1945,6 +1959,14 @@ export type TransferProp = FieldA11yProps & {
1945
1959
  className?: ClassNameProp;
1946
1960
  selectedKeys?: [string[], string[]];
1947
1961
  onSelectChange?: (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void;
1962
+ /**
1963
+ * antd `locale`, ported for `notFoundContent` only: the node an empty (or search-emptied) pane
1964
+ * shows. A `[source, target]` pair sets each pane separately, as in antd. Localized
1965
+ * `dataEntry.transfer.empty` otherwise.
1966
+ */
1967
+ locale?: {
1968
+ notFoundContent?: NotFoundContentProp | [NotFoundContentProp, NotFoundContentProp];
1969
+ };
1948
1970
  };
1949
1971
  /** @see BranchScopePicker — scope mode: every branch, or an explicit subset. */
1950
1972
  export type BranchScopeModeProp = "all" | "selected";
@@ -1989,6 +2011,11 @@ export type BranchScopePickerProp = FieldA11yProps & {
1989
2011
  loading?: boolean;
1990
2012
  /** Custom empty content when `branches` is empty; defaults to a localized message. */
1991
2013
  empty?: React.ReactNode;
2014
+ /**
2015
+ * Shown when the branch search matches nothing (antd `notFoundContent`); localized
2016
+ * `dataEntry.branchScope.noMatches` otherwise. An empty `branches` list is `empty`'s, not this.
2017
+ */
2018
+ notFoundContent?: NotFoundContentProp;
1992
2019
  /** Branch-collection READ failure (distinct from `error`, which is field validation). */
1993
2020
  listError?: React.ReactNode;
1994
2021
  /** Permission-denied state — the branch read was refused. Takes precedence over `listError`. */
@@ -3,7 +3,7 @@ import type * as React from "react";
3
3
  import type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseMutationResult, UseQueryResult } from "@tanstack/react-query";
4
4
  import type { LinkProps } from "react-router-dom";
5
5
  import type { ButtonProp } from "./general.prop.js";
6
- import type { ClassNameProp, HandlerProp } from "../vocabulary/index.js";
6
+ import type { ClassNameProp, HandlerProp, LabelProp } from "../vocabulary/index.js";
7
7
  /** @see DataState — TanStack Query lifecycle widget (not a visual component). */
8
8
  export type DataStateProp<T> = {
9
9
  query: UseQueryResult<T>;
@@ -103,6 +103,13 @@ export type InfiniteQueryStateProp<TPage, TFlat = TPage extends {
103
103
  loadingMore?: React.ReactNode;
104
104
  /** Custom load-more footer; `false` hides footer entirely. */
105
105
  loadMore?: React.ReactNode | false;
106
+ /**
107
+ * Text of the built-in load-more button (localized `query.loadMore` otherwise) — e.g.
108
+ * 「さらに表示」「さらに古い版を表示」. Only the idle label: the button, its pending label and its
109
+ * disabled-while-fetching behaviour stay the component's. Ignored when `loadMore` replaces the
110
+ * footer.
111
+ */
112
+ loadMoreLabel?: LabelProp;
106
113
  /** Show default load-more button when `hasNextPage`. Default `true`. */
107
114
  showLoadMore?: boolean;
108
115
  children: (flat: TFlat, helpers: InfiniteQueryHelpers) => React.ReactNode;
@@ -304,10 +304,20 @@ export declare const VOCABULARY_REGISTRY: {
304
304
  readonly category: "data";
305
305
  readonly description: "One entry in the selection-column dropdown — { key, text, onSelect } (antd SelectionItem)";
306
306
  };
307
+ readonly TableSelectionBuiltInProp: {
308
+ readonly file: "vocabulary/data.prop.ts";
309
+ readonly category: "data";
310
+ readonly description: "Built-in selections entry — SELECT_ALL | SELECT_INVERT | SELECT_NONE (antd Table.SELECTION_ALL / SELECTION_INVERT / SELECTION_NONE, published as DataTable.SELECTION_*)";
311
+ };
312
+ readonly TableSelectAllMatchingProp: {
313
+ readonly file: "vocabulary/data.prop.ts";
314
+ readonly category: "data";
315
+ readonly description: "Server-paged 'select all N matching' banner — { total, selected, onSelectedChange } (no antd equivalent; Gmail/Jira/GitHub pattern)";
316
+ };
307
317
  readonly TableRowSelectionProp: {
308
318
  readonly file: "vocabulary/data.prop.ts";
309
319
  readonly category: "data";
310
- readonly description: "DataTable row-selection config — type | selectedRowKeys | onChange | getCheckboxProps | preserveSelectedRowKeys | selections | hideSelectAll | columnTitle (antd TableRowSelection)";
320
+ readonly description: "DataTable row-selection config — type | selectedRowKeys | onChange | getCheckboxProps | preserveSelectedRowKeys | selections | hideSelectAll | columnTitle | selectAllLabel | matching (antd TableRowSelection + select-all-matching)";
311
321
  };
312
322
  readonly TableExpandableProp: {
313
323
  readonly file: "vocabulary/data.prop.ts";
@@ -1810,7 +1820,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
1810
1820
  readonly RecordPickerProp: {
1811
1821
  readonly group: "data-entry";
1812
1822
  readonly file: "components/data-entry.prop.ts";
1813
- readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "PlaceholderProp"];
1823
+ readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "PlaceholderProp", "NotFoundContentProp", "LabelProp"];
1814
1824
  readonly note: "One picker whose SHAPE follows the size of the set: Select at or under `threshold`, a searchable Dialog with consumer-declared filters over it (gh#932).";
1815
1825
  };
1816
1826
  readonly RecordPickerFilterProp: {
@@ -1882,7 +1892,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1882
1892
  readonly TransferProp: {
1883
1893
  readonly group: "data-entry";
1884
1894
  readonly file: "components/data-entry.prop.ts";
1885
- readonly vocabulary: readonly ["DisabledProp", "ClassNameProp"];
1895
+ readonly vocabulary: readonly ["DisabledProp", "ClassNameProp", {
1896
+ readonly field: "locale";
1897
+ readonly local: true;
1898
+ readonly reason: "antd Transfer `locale`, ported for `notFoundContent` only (one node, or a [source, target] pair) — gh#1044.";
1899
+ }];
1886
1900
  };
1887
1901
  readonly TransferItemProp: {
1888
1902
  readonly group: "data-entry";
@@ -1940,7 +1954,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
1940
1954
  readonly DataTableProp: {
1941
1955
  readonly group: "data-display";
1942
1956
  readonly file: "components/data-display.prop.ts";
1943
- readonly vocabulary: readonly ["ColumnDefProp", "DensityProp", "SortStateProp", "SelectedIdsProp", "GetRowLabelProp", "HandlerProp", "TablePresetProp", "TableColumnPriorityProp", "BreakpointProp", "ColumnFixedProp", "ColumnFilterItemProp", "ColumnFilterStateProp", "ColumnSorterProp", "TableRowSelectionProp", "TableExpandableProp", "TableSummaryProp", "TableScrollProp", "TableStickyProp", "OnRowProp", "TablePaginationProp", "TablePaginationPositionProp", "SortDirectionProp", "OnColumnFilterChangeProp"];
1957
+ readonly vocabulary: readonly ["ColumnDefProp", "DensityProp", "SortStateProp", "SelectedIdsProp", "GetRowLabelProp", "HandlerProp", "TablePresetProp", "TableColumnPriorityProp", "BreakpointProp", "ColumnFixedProp", "ColumnFilterItemProp", "ColumnFilterStateProp", "ColumnSorterProp", "TableRowSelectionProp", "TableSelectionBuiltInProp", "TableSelectAllMatchingProp", "TableExpandableProp", "TableSummaryProp", "TableScrollProp", "TableStickyProp", "OnRowProp", "TablePaginationProp", "TablePaginationPositionProp", "SortDirectionProp", "OnColumnFilterChangeProp"];
1944
1958
  };
1945
1959
  readonly ListRowDensityProp: {
1946
1960
  readonly group: "data-display";
@@ -2408,7 +2422,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
2408
2422
  readonly InfiniteQueryStateProp: {
2409
2423
  readonly group: "query";
2410
2424
  readonly file: "components/query.prop.ts";
2411
- readonly vocabulary: readonly ["HandlerProp"];
2425
+ readonly vocabulary: readonly ["HandlerProp", "LabelProp"];
2412
2426
  };
2413
2427
  readonly PrefetchLinkProp: {
2414
2428
  readonly group: "query";
@@ -3293,6 +3307,10 @@ export declare const COMPONENT_PROP_REGISTRY: {
3293
3307
  readonly field: "onRangeChange";
3294
3308
  readonly local: true;
3295
3309
  readonly reason: "An endpoint movement command, not an internally owned value; the consumer commits its row data.";
3310
+ }, {
3311
+ readonly field: "sticky";
3312
+ readonly local: true;
3313
+ readonly reason: "antd Table `sticky` — `true` or `{ offsetHeader }` (px) keeps the axis header on screen while the page scrolls (gh#1044).";
3296
3314
  }, {
3297
3315
  readonly field: "expandedValues";
3298
3316
  readonly local: true;
@@ -3476,7 +3494,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
3476
3494
  readonly field: "empty";
3477
3495
  readonly local: true;
3478
3496
  readonly reason: "Custom empty content when there are no branches.";
3479
- }, {
3497
+ }, "NotFoundContentProp", {
3480
3498
  readonly field: "listError";
3481
3499
  readonly local: true;
3482
3500
  readonly reason: "Branch-collection READ failure — deliberately distinct from ErrorProp `error`, which stays field validation.";
@@ -302,10 +302,20 @@ const VOCABULARY_REGISTRY = {
302
302
  category: "data",
303
303
  description: "One entry in the selection-column dropdown \u2014 { key, text, onSelect } (antd SelectionItem)"
304
304
  },
305
+ TableSelectionBuiltInProp: {
306
+ file: "vocabulary/data.prop.ts",
307
+ category: "data",
308
+ description: "Built-in selections entry \u2014 SELECT_ALL | SELECT_INVERT | SELECT_NONE (antd Table.SELECTION_ALL / SELECTION_INVERT / SELECTION_NONE, published as DataTable.SELECTION_*)"
309
+ },
310
+ TableSelectAllMatchingProp: {
311
+ file: "vocabulary/data.prop.ts",
312
+ category: "data",
313
+ description: "Server-paged 'select all N matching' banner \u2014 { total, selected, onSelectedChange } (no antd equivalent; Gmail/Jira/GitHub pattern)"
314
+ },
305
315
  TableRowSelectionProp: {
306
316
  file: "vocabulary/data.prop.ts",
307
317
  category: "data",
308
- description: "DataTable row-selection config \u2014 type | selectedRowKeys | onChange | getCheckboxProps | preserveSelectedRowKeys | selections | hideSelectAll | columnTitle (antd TableRowSelection)"
318
+ description: "DataTable row-selection config \u2014 type | selectedRowKeys | onChange | getCheckboxProps | preserveSelectedRowKeys | selections | hideSelectAll | columnTitle | selectAllLabel | matching (antd TableRowSelection + select-all-matching)"
309
319
  },
310
320
  TableExpandableProp: {
311
321
  file: "vocabulary/data.prop.ts",
@@ -2146,7 +2156,16 @@ const COMPONENT_PROP_REGISTRY = {
2146
2156
  RecordPickerProp: {
2147
2157
  group: "data-entry",
2148
2158
  file: "components/data-entry.prop.ts",
2149
- vocabulary: ["ValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "PlaceholderProp"],
2159
+ vocabulary: [
2160
+ "ValueProp",
2161
+ "OnValueChangeProp",
2162
+ "DisabledProp",
2163
+ "SizeProp",
2164
+ "PlaceholderProp",
2165
+ // gh#1044: antd `notFoundContent` for the empty search, and the dialog's load-more text.
2166
+ "NotFoundContentProp",
2167
+ "LabelProp"
2168
+ ],
2150
2169
  note: "One picker whose SHAPE follows the size of the set: Select at or under `threshold`, a searchable Dialog with consumer-declared filters over it (gh#932)."
2151
2170
  },
2152
2171
  RecordPickerFilterProp: {
@@ -2262,7 +2281,15 @@ const COMPONENT_PROP_REGISTRY = {
2262
2281
  TransferProp: {
2263
2282
  group: "data-entry",
2264
2283
  file: "components/data-entry.prop.ts",
2265
- vocabulary: ["DisabledProp", "ClassNameProp"]
2284
+ vocabulary: [
2285
+ "DisabledProp",
2286
+ "ClassNameProp",
2287
+ {
2288
+ field: "locale",
2289
+ local: true,
2290
+ reason: "antd Transfer `locale`, ported for `notFoundContent` only (one node, or a [source, target] pair) \u2014 gh#1044."
2291
+ }
2292
+ ]
2266
2293
  },
2267
2294
  TransferItemProp: {
2268
2295
  group: "data-entry",
@@ -2350,6 +2377,8 @@ const COMPONENT_PROP_REGISTRY = {
2350
2377
  "ColumnFilterStateProp",
2351
2378
  "ColumnSorterProp",
2352
2379
  "TableRowSelectionProp",
2380
+ "TableSelectionBuiltInProp",
2381
+ "TableSelectAllMatchingProp",
2353
2382
  "TableExpandableProp",
2354
2383
  "TableSummaryProp",
2355
2384
  "TableScrollProp",
@@ -2830,7 +2859,8 @@ const COMPONENT_PROP_REGISTRY = {
2830
2859
  InfiniteQueryStateProp: {
2831
2860
  group: "query",
2832
2861
  file: "components/query.prop.ts",
2833
- vocabulary: ["HandlerProp"]
2862
+ // LabelProp: `loadMoreLabel`, the built-in button's idle text (gh#1044).
2863
+ vocabulary: ["HandlerProp", "LabelProp"]
2834
2864
  },
2835
2865
  PrefetchLinkProp: { group: "query", file: "components/query.prop.ts", vocabulary: [] },
2836
2866
  AuthExpiryProviderProp: {
@@ -3905,6 +3935,11 @@ const COMPONENT_PROP_REGISTRY = {
3905
3935
  local: true,
3906
3936
  reason: "An endpoint movement command, not an internally owned value; the consumer commits its row data."
3907
3937
  },
3938
+ {
3939
+ field: "sticky",
3940
+ local: true,
3941
+ reason: "antd Table `sticky` \u2014 `true` or `{ offsetHeader }` (px) keeps the axis header on screen while the page scrolls (gh#1044)."
3942
+ },
3908
3943
  {
3909
3944
  field: "expandedValues",
3910
3945
  local: true,
@@ -4144,6 +4179,8 @@ const COMPONENT_PROP_REGISTRY = {
4144
4179
  local: true,
4145
4180
  reason: "Custom empty content when there are no branches."
4146
4181
  },
4182
+ // gh#1044: antd `notFoundContent` — the line shown when the branch SEARCH matches nothing.
4183
+ "NotFoundContentProp",
4147
4184
  {
4148
4185
  field: "listError",
4149
4186
  local: true,
@@ -207,6 +207,25 @@ export type TableSelectionItemProp = {
207
207
  text: React.ReactNode;
208
208
  onSelect: (currentRowKeys: string[]) => void;
209
209
  };
210
+ /**
211
+ * A built-in entry for the `selections` list (antd `Table.SELECTION_ALL` / `SELECTION_INVERT` /
212
+ * `SELECTION_NONE`, published here as `DataTable.SELECTION_*`). Mix them with custom
213
+ * {@link TableSelectionItemProp} entries in any order, exactly as antd does.
214
+ */
215
+ export type TableSelectionBuiltInProp = "SELECT_ALL" | "SELECT_INVERT" | "SELECT_NONE";
216
+ /**
217
+ * "Select all N matching" for a server-paged table (Gmail / Jira / GitHub; antd has no
218
+ * equivalent). Once every row of the page is selected, a banner above the header offers the whole
219
+ * result set; choosing it flips `selected`, and the consumer then sends its FILTER to the server
220
+ * instead of the ids. Unticking any row, or "Clear selection", reports `false`.
221
+ */
222
+ export type TableSelectAllMatchingProp = {
223
+ /** Rows the current query matches on the server — the N in "Select all N". */
224
+ total: number;
225
+ /** Controlled: `true` while the whole matching set is selected. */
226
+ selected: boolean;
227
+ onSelectedChange: (selected: boolean) => void;
228
+ };
210
229
  /**
211
230
  * Row-selection configuration (antd `TableRowSelection`). The object form is the full surface;
212
231
  * the older `selectable` / `selected` / `onSelectChange` triple stays and drives the same state.
@@ -224,10 +243,21 @@ export type TableRowSelectionProp<T> = {
224
243
  };
225
244
  /** Keep keys selected even once their row leaves `data` (server paging / filtering). */
226
245
  preserveSelectedRowKeys?: boolean;
227
- /** Extra bulk-select entries under the header checkbox. `true` = the built-in all/none/invert. */
228
- selections?: TableSelectionItemProp[] | boolean;
246
+ /**
247
+ * Extra bulk-select entries under the header checkbox. `true` = the built-in all/invert/none;
248
+ * a list mixes `DataTable.SELECTION_*` built-ins with custom entries, in the order given.
249
+ */
250
+ selections?: (TableSelectionItemProp | TableSelectionBuiltInProp)[] | boolean;
229
251
  hideSelectAll?: boolean;
230
252
  columnTitle?: React.ReactNode;
253
+ /**
254
+ * Accessible name of the header checkbox. Default: "Select all rows", or "Select all rows on
255
+ * this page" once `matching` is set. Name what it really selects — on a server-paged table it
256
+ * is the page, not the result set.
257
+ */
258
+ selectAllLabel?: string;
259
+ /** Opt-in "select all N matching" banner for a server-paged table. */
260
+ matching?: TableSelectAllMatchingProp;
231
261
  };
232
262
  /** Expandable-row configuration (antd/rc-table `ExpandableConfig`). */
233
263
  export type TableExpandableProp<T> = {
@@ -4,4 +4,4 @@ export type { TitleProp, SubtitleProp, StatusProp, DescriptionProp, ExtraProp, F
4
4
  export type { PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, MobileShellWidthProp, OrientationProp, TableDensityProp, DensityProp, GapNameProp, PadProp, PadRawProp, PadSides, GapProp, GapStepProp, } from "./layout.prop.js";
5
5
  export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, AppSettingToggleAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, TextWhitespaceProp, TextBreakProp, TypographyTypeProp, TitleLevelProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyActionsConfigProp, SizeProp, ControlStatusProp, ControlVariantProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, CalloutKindProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, RevealTriggerProp, InViewAmountProp, ActivityVariantProp, ActivityAnnounceProp, IconSizeProp, } from "./interaction.prop.js";
6
6
  export type { BreadcrumbItemProp, BreadcrumbProp, BreadcrumbItemMenuProp, BreadcrumbItemMenuEntryProp, BreadcrumbSeparatorProp, BreadcrumbItemRenderProp, } from "./navigation.prop.js";
7
- export type { GetRowIdProp, GetRowLabelProp, OnRowClickProp, ColumnDefProp, TablePresetProp, TableColumnPriorityProp, TableCellIndentProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, TableRowToneProp, RowToneProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, StickyProp, ColumnFixedProp, ColumnFilterValueProp, ColumnFilterItemProp, ColumnFilterStateProp, OnColumnFilterChangeProp, ColumnCompareProp, ColumnSorterProp, TableSelectionItemProp, TableRowSelectionProp, TableExpandableProp, TableSummaryProp, TableScrollProp, TableStickyProp, OnRowProp, TablePaginationProp, TablePaginationPositionProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, } from "./data.prop.js";
7
+ export type { GetRowIdProp, GetRowLabelProp, OnRowClickProp, ColumnDefProp, TablePresetProp, TableColumnPriorityProp, TableCellIndentProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, TableRowToneProp, RowToneProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, StickyProp, ColumnFixedProp, ColumnFilterValueProp, ColumnFilterItemProp, ColumnFilterStateProp, OnColumnFilterChangeProp, ColumnCompareProp, ColumnSorterProp, TableSelectionItemProp, TableSelectionBuiltInProp, TableSelectAllMatchingProp, TableRowSelectionProp, TableExpandableProp, TableSummaryProp, TableScrollProp, TableStickyProp, OnRowProp, TablePaginationProp, TablePaginationPositionProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, } from "./data.prop.js";
@@ -1129,6 +1129,11 @@
1129
1129
  padding-inline-end: calc(var(--code-block-space-inset) + var(--control-height-xs));
1130
1130
  }
1131
1131
 
1132
+ .ui-code-block[data-copyable][data-wrap="false"] {
1133
+ padding-inline-end: var(--code-block-space-inset);
1134
+ border-inline-end: calc(var(--control-height-xs) + 2 * var(--space-1)) solid transparent;
1135
+ }
1136
+
1132
1137
  .ui-code-block-copy {
1133
1138
  position: absolute;
1134
1139
  inset-block-start: var(--space-1);
@@ -1139,6 +1144,11 @@
1139
1144
  .ui-code-block[data-copyable] {
1140
1145
  padding-inline-end: calc(var(--code-block-space-inset) + var(--control-height-default));
1141
1146
  }
1147
+
1148
+ .ui-code-block[data-copyable][data-wrap="false"] {
1149
+ padding-inline-end: var(--code-block-space-inset);
1150
+ border-inline-end-width: calc(var(--control-height-default) + 2 * var(--space-1));
1151
+ }
1142
1152
  }
1143
1153
 
1144
1154
  .ui-code-block [data-code-token="comment"],
@@ -1545,6 +1555,20 @@
1545
1555
  border: var(--stroke-hairline) solid hsl(var(--range-timeline-border-color));
1546
1556
  border-radius: var(--radius-md, calc(var(--radius) / var(--radius-ratio)));
1547
1557
  }
1558
+
1559
+ .ui-range-timeline[data-sticky="true"] {
1560
+ overflow: clip;
1561
+ }
1562
+ .ui-range-timeline-sticky-header {
1563
+ position: sticky;
1564
+ inset-block-start: var(--range-timeline-sticky-offset, 0px);
1565
+ z-index: 2;
1566
+ overflow: hidden;
1567
+ }
1568
+ .ui-range-timeline-scroller {
1569
+ overflow-x: auto;
1570
+ overflow-y: hidden;
1571
+ }
1548
1572
  .ui-range-timeline-canvas {
1549
1573
  min-inline-size: calc(
1550
1574
  var(--range-timeline-label-width) + var(--range-timeline-columns, 1) *
@@ -2171,6 +2195,34 @@
2171
2195
  border-block-start-color: transparent;
2172
2196
  }
2173
2197
 
2198
+ .ui-tree-node[data-filter-node="true"]:not([data-disabled]) .ui-tree-label {
2199
+ color: var(--tree-node-filter-foreground, hsl(var(--text-brand, var(--primary))));
2200
+ font-weight: var(--font-weight-medium);
2201
+ }
2202
+
2203
+ .ui-tree[data-virtual="true"][data-show-line="true"] .ui-tree-node {
2204
+ position: relative;
2205
+ }
2206
+
2207
+ .ui-tree-rail {
2208
+ position: absolute;
2209
+ inset-block: 0;
2210
+ inset-inline-start: calc(
2211
+ var(--tree-node-padding-inline) + (var(--tree-rail-level, 1) - 1) * var(--tree-indent-width) +
2212
+ var(--tree-switcher-size) / 2
2213
+ );
2214
+ border-inline-start: var(--stroke-hairline) solid var(--tree-line-color, hsl(var(--border)));
2215
+ }
2216
+
2217
+ .ui-tree-spacer {
2218
+ flex: none;
2219
+ }
2220
+
2221
+ .ui-tree[data-virtual="true"][data-divided="true"]
2222
+ > .ui-tree-node[aria-level="1"][aria-posinset="1"] {
2223
+ border-block-start-color: transparent;
2224
+ }
2225
+
2174
2226
  .ui-tree-loading {
2175
2227
  display: flex;
2176
2228
  align-items: center;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "31.5.0",
2
+ "version": "31.6.0",
3
3
  "generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
4
4
  "base": "base.css",
5
5
  "fonts": "fonts.css",
@@ -187,7 +187,9 @@
187
187
  padding: 0;
188
188
  }
189
189
 
190
- .ui-table-row:has(> [data-slot="table-cell"][data-flush] > [data-slot="list-row"][data-unread]) {
190
+ .ui-table-row:not([data-state="selected"]):has(
191
+ > [data-slot="table-cell"][data-flush] > [data-slot="list-row"][data-unread]
192
+ ) {
191
193
  background-color: var(--list-row-unread-background, hsl(var(--muted)));
192
194
  }
193
195
 
@@ -554,6 +556,19 @@
554
556
  gap: var(--table-selection-menu-gap);
555
557
  }
556
558
 
559
+ .ui-data-table-matching[data-active] {
560
+ display: flex;
561
+ flex-wrap: wrap;
562
+ align-items: center;
563
+ justify-content: center;
564
+ gap: var(--space-inline-sm);
565
+ padding-block: var(--space-stack-xs);
566
+ padding-inline: var(--table-cell-space-x, var(--space-section-active));
567
+ border-block-end: var(--stroke-hairline) solid var(--table-border-color, hsl(var(--border)));
568
+ background-color: hsl(var(--muted));
569
+ font-size: var(--font-size-sm);
570
+ }
571
+
557
572
  .ui-data-table-surface .ui-table-bordered {
558
573
  border-width: 0;
559
574
  }
@@ -27,5 +27,7 @@
27
27
  --tree-node-selected-background-alpha: initial;
28
28
  --tree-node-selected-foreground: initial;
29
29
 
30
+ --tree-node-filter-foreground: initial;
31
+
30
32
  --tree-loading-bar-inline-size: 40%;
31
33
  }