@cratis/components 4.20.0 → 4.21.1

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 (146) hide show
  1. package/MIGRATION.md +3 -3
  2. package/compat-manifest.json +11 -11
  3. package/dist/esm/Chat/ChatConversation.d.ts +8 -1
  4. package/dist/esm/Chat/ChatConversation.d.ts.map +1 -1
  5. package/dist/esm/Chat/ChatConversation.js +2 -2
  6. package/dist/esm/Chat/ChatConversation.js.map +1 -1
  7. package/dist/esm/Chat/ChatSidebar.d.ts +9 -2
  8. package/dist/esm/Chat/ChatSidebar.d.ts.map +1 -1
  9. package/dist/esm/Chat/ChatSidebar.js +2 -2
  10. package/dist/esm/Chat/ChatSidebar.js.map +1 -1
  11. package/dist/esm/Common/ActionMenubar.d.ts.map +1 -1
  12. package/dist/esm/Common/ActionMenubar.js +11 -6
  13. package/dist/esm/Common/ActionMenubar.js.map +1 -1
  14. package/dist/esm/Common/ToolbarFocusMode.d.ts +9 -1
  15. package/dist/esm/Common/ToolbarFocusMode.d.ts.map +1 -1
  16. package/dist/esm/Common/ToolbarFocusMode.js +1 -0
  17. package/dist/esm/Common/ToolbarFocusMode.js.map +1 -1
  18. package/dist/esm/Common/ToolbarRovingContext.d.ts +39 -0
  19. package/dist/esm/Common/ToolbarRovingContext.d.ts.map +1 -0
  20. package/dist/esm/Common/ToolbarRovingContext.js +40 -0
  21. package/dist/esm/Common/ToolbarRovingContext.js.map +1 -0
  22. package/dist/esm/Common/useToolbarKeyboardNavigation.d.ts +2 -0
  23. package/dist/esm/Common/useToolbarKeyboardNavigation.d.ts.map +1 -1
  24. package/dist/esm/Common/useToolbarKeyboardNavigation.js +164 -15
  25. package/dist/esm/Common/useToolbarKeyboardNavigation.js.map +1 -1
  26. package/dist/esm/DataTables/DataTableBody.d.ts +22 -0
  27. package/dist/esm/DataTables/DataTableBody.d.ts.map +1 -0
  28. package/dist/esm/DataTables/DataTableBody.js +10 -0
  29. package/dist/esm/DataTables/DataTableBody.js.map +1 -0
  30. package/dist/esm/DataTables/DataTableCore.d.ts +25 -47
  31. package/dist/esm/DataTables/DataTableCore.d.ts.map +1 -1
  32. package/dist/esm/DataTables/DataTableCore.js +50 -273
  33. package/dist/esm/DataTables/DataTableCore.js.map +1 -1
  34. package/dist/esm/DataTables/DataTableHeaderCell.d.ts +25 -0
  35. package/dist/esm/DataTables/DataTableHeaderCell.d.ts.map +1 -0
  36. package/dist/esm/DataTables/DataTableHeaderCell.js +26 -0
  37. package/dist/esm/DataTables/DataTableHeaderCell.js.map +1 -0
  38. package/dist/esm/DataTables/DataTableMessageOverrides.d.ts +12 -0
  39. package/dist/esm/DataTables/DataTableMessageOverrides.d.ts.map +1 -0
  40. package/dist/esm/DataTables/DataTableMessageOverrides.js +4 -0
  41. package/dist/esm/DataTables/DataTableMessageOverrides.js.map +1 -0
  42. package/dist/esm/DataTables/DataTableMessages.d.ts +12 -0
  43. package/dist/esm/DataTables/DataTableMessages.d.ts.map +1 -0
  44. package/dist/esm/DataTables/DataTableMessages.js +4 -0
  45. package/dist/esm/DataTables/DataTableMessages.js.map +1 -0
  46. package/dist/esm/DataTables/DataTableParts.d.ts +40 -0
  47. package/dist/esm/DataTables/DataTableParts.d.ts.map +1 -0
  48. package/dist/esm/DataTables/DataTableParts.js +4 -0
  49. package/dist/esm/DataTables/DataTableParts.js.map +1 -0
  50. package/dist/esm/DataTables/DataTableRow.d.ts +22 -0
  51. package/dist/esm/DataTables/DataTableRow.d.ts.map +1 -0
  52. package/dist/esm/DataTables/DataTableRow.js +25 -0
  53. package/dist/esm/DataTables/DataTableRow.js.map +1 -0
  54. package/dist/esm/DataTables/DataTableRowClickEvent.d.ts +8 -0
  55. package/dist/esm/DataTables/DataTableRowClickEvent.d.ts.map +1 -0
  56. package/dist/esm/DataTables/DataTableRowClickEvent.js +4 -0
  57. package/dist/esm/DataTables/DataTableRowClickEvent.js.map +1 -0
  58. package/dist/esm/DataTables/DataTableRowProcessing.d.ts +11 -0
  59. package/dist/esm/DataTables/DataTableRowProcessing.d.ts.map +1 -0
  60. package/dist/esm/DataTables/DataTableRowProcessing.js +8 -0
  61. package/dist/esm/DataTables/DataTableRowProcessing.js.map +1 -0
  62. package/dist/esm/DataTables/DataTableSearch.d.ts +13 -0
  63. package/dist/esm/DataTables/DataTableSearch.d.ts.map +1 -0
  64. package/dist/esm/DataTables/DataTableSearch.js +7 -0
  65. package/dist/esm/DataTables/DataTableSearch.js.map +1 -0
  66. package/dist/esm/DataTables/DataTableSort.d.ts +9 -0
  67. package/dist/esm/DataTables/DataTableSort.d.ts.map +1 -0
  68. package/dist/esm/DataTables/DataTableSort.js +4 -0
  69. package/dist/esm/DataTables/DataTableSort.js.map +1 -0
  70. package/dist/esm/DataTables/DataTableSortDirection.d.ts +8 -0
  71. package/dist/esm/DataTables/DataTableSortDirection.d.ts.map +1 -0
  72. package/dist/esm/DataTables/DataTableSortDirection.js +8 -0
  73. package/dist/esm/DataTables/DataTableSortDirection.js.map +1 -0
  74. package/dist/esm/DataTables/DataTableState.d.ts +18 -0
  75. package/dist/esm/DataTables/DataTableState.d.ts.map +1 -0
  76. package/dist/esm/DataTables/DataTableState.js +4 -0
  77. package/dist/esm/DataTables/DataTableState.js.map +1 -0
  78. package/dist/esm/DataTables/DataTableStateProps.d.ts +20 -0
  79. package/dist/esm/DataTables/DataTableStateProps.d.ts.map +1 -0
  80. package/dist/esm/DataTables/DataTableStateProps.js +4 -0
  81. package/dist/esm/DataTables/DataTableStateProps.js.map +1 -0
  82. package/dist/esm/DataTables/ProcessedRow.d.ts +8 -0
  83. package/dist/esm/DataTables/ProcessedRow.d.ts.map +1 -0
  84. package/dist/esm/DataTables/ProcessedRow.js +4 -0
  85. package/dist/esm/DataTables/ProcessedRow.js.map +1 -0
  86. package/dist/esm/DataTables/RowProcessingState.d.ts +17 -0
  87. package/dist/esm/DataTables/RowProcessingState.d.ts.map +1 -0
  88. package/dist/esm/DataTables/RowProcessingState.js +4 -0
  89. package/dist/esm/DataTables/RowProcessingState.js.map +1 -0
  90. package/dist/esm/DataTables/RowSelection.d.ts +19 -0
  91. package/dist/esm/DataTables/RowSelection.d.ts.map +1 -0
  92. package/dist/esm/DataTables/RowSelection.js +4 -0
  93. package/dist/esm/DataTables/RowSelection.js.map +1 -0
  94. package/dist/esm/DataTables/RowSelectionSource.d.ts +16 -0
  95. package/dist/esm/DataTables/RowSelectionSource.d.ts.map +1 -0
  96. package/dist/esm/DataTables/RowSelectionSource.js +4 -0
  97. package/dist/esm/DataTables/RowSelectionSource.js.map +1 -0
  98. package/dist/esm/DataTables/classNames.d.ts +7 -0
  99. package/dist/esm/DataTables/classNames.d.ts.map +1 -0
  100. package/dist/esm/DataTables/classNames.js +4 -0
  101. package/dist/esm/DataTables/classNames.js.map +1 -0
  102. package/dist/esm/DataTables/index.d.ts +3 -0
  103. package/dist/esm/DataTables/index.d.ts.map +1 -1
  104. package/dist/esm/DataTables/index.js +2 -0
  105. package/dist/esm/DataTables/index.js.map +1 -1
  106. package/dist/esm/DataTables/matchesFilterEntry.d.ts +15 -0
  107. package/dist/esm/DataTables/matchesFilterEntry.d.ts.map +1 -0
  108. package/dist/esm/DataTables/matchesFilterEntry.js +70 -0
  109. package/dist/esm/DataTables/matchesFilterEntry.js.map +1 -0
  110. package/dist/esm/DataTables/processRows.d.ts +10 -0
  111. package/dist/esm/DataTables/processRows.d.ts.map +1 -0
  112. package/dist/esm/DataTables/processRows.js +42 -0
  113. package/dist/esm/DataTables/processRows.js.map +1 -0
  114. package/dist/esm/DataTables/useControllableState.d.ts +10 -0
  115. package/dist/esm/DataTables/useControllableState.d.ts.map +1 -0
  116. package/dist/esm/DataTables/useControllableState.js +15 -0
  117. package/dist/esm/DataTables/useControllableState.js.map +1 -0
  118. package/dist/esm/DataTables/useDataTableMessages.d.ts +9 -0
  119. package/dist/esm/DataTables/useDataTableMessages.d.ts.map +1 -0
  120. package/dist/esm/DataTables/useDataTableMessages.js +33 -0
  121. package/dist/esm/DataTables/useDataTableMessages.js.map +1 -0
  122. package/dist/esm/DataTables/useDataTableState.d.ts +10 -0
  123. package/dist/esm/DataTables/useDataTableState.d.ts.map +1 -0
  124. package/dist/esm/DataTables/useDataTableState.js +19 -0
  125. package/dist/esm/DataTables/useDataTableState.js.map +1 -0
  126. package/dist/esm/DataTables/useRowSelection.d.ts +9 -0
  127. package/dist/esm/DataTables/useRowSelection.d.ts.map +1 -0
  128. package/dist/esm/DataTables/useRowSelection.js +87 -0
  129. package/dist/esm/DataTables/useRowSelection.js.map +1 -0
  130. package/dist/esm/DataTables/valueAtPath.d.ts +10 -0
  131. package/dist/esm/DataTables/valueAtPath.d.ts.map +1 -0
  132. package/dist/esm/DataTables/valueAtPath.js +18 -0
  133. package/dist/esm/DataTables/valueAtPath.js.map +1 -0
  134. package/dist/esm/Toolbar/Toolbar.d.ts.map +1 -1
  135. package/dist/esm/Toolbar/Toolbar.js +3 -2
  136. package/dist/esm/Toolbar/Toolbar.js.map +1 -1
  137. package/dist/esm/Toolbar/ToolbarButton.d.ts.map +1 -1
  138. package/dist/esm/Toolbar/ToolbarButton.js +4 -2
  139. package/dist/esm/Toolbar/ToolbarButton.js.map +1 -1
  140. package/dist/esm/Toolbar/ToolbarFanOutItem.d.ts.map +1 -1
  141. package/dist/esm/Toolbar/ToolbarFanOutItem.js +10 -2
  142. package/dist/esm/Toolbar/ToolbarFanOutItem.js.map +1 -1
  143. package/dist/esm/Toolbar/ToolbarFolder.d.ts.map +1 -1
  144. package/dist/esm/Toolbar/ToolbarFolder.js +10 -2
  145. package/dist/esm/Toolbar/ToolbarFolder.js.map +1 -1
  146. package/package.json +5 -2
@@ -1,7 +1,15 @@
1
- /** Keyboard focus behavior for Toolbar and ActionMenubar. A single-Tab-stop mode is planned for #353. */
1
+ /** Keyboard focus behavior for Toolbar and ActionMenubar. */
2
2
  export declare enum ToolbarFocusMode {
3
3
  /** Navigate with arrows and Home/End while retaining every tool's Tab stop (default). */
4
4
  Arrows = "arrows",
5
+ /**
6
+ * Navigate with arrows and Home/End, with one Tab stop for the toolbar's own tools that
7
+ * returns to the last focused tool (the WAI-ARIA toolbar pattern). Controls you add yourself,
8
+ * widgets such as inputs and sliders, tools rendered outside the toolbar's own markup (for example
9
+ * through a portal), and tools with an explicit tab index keep their own Tab stop. An explicit
10
+ * tab index of -1 removes the tool from both Tab and arrow-key navigation.
11
+ */
12
+ SingleTabStop = "singleTabStop",
5
13
  /** Keep native focus behavior with no toolbar keyboard handling. */
6
14
  None = "none"
7
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarFocusMode.d.ts","sourceRoot":"","sources":["../../../Common/ToolbarFocusMode.ts"],"names":[],"mappings":"AAGA,yGAAyG;AACzG,oBAAY,gBAAgB;IACxB,yFAAyF;IACzF,MAAM,WAAW;IACjB,oEAAoE;IACpE,IAAI,SAAS;CAChB"}
1
+ {"version":3,"file":"ToolbarFocusMode.d.ts","sourceRoot":"","sources":["../../../Common/ToolbarFocusMode.ts"],"names":[],"mappings":"AAGA,6DAA6D;AAC7D,oBAAY,gBAAgB;IACxB,yFAAyF;IACzF,MAAM,WAAW;IACjB;;;;;;OAMG;IACH,aAAa,kBAAkB;IAC/B,oEAAoE;IACpE,IAAI,SAAS;CAChB"}
@@ -1,6 +1,7 @@
1
1
  var ToolbarFocusMode;
2
2
  (function (ToolbarFocusMode) {
3
3
  ToolbarFocusMode["Arrows"] = "arrows";
4
+ ToolbarFocusMode["SingleTabStop"] = "singleTabStop";
4
5
  ToolbarFocusMode["None"] = "none";
5
6
  })(ToolbarFocusMode || (ToolbarFocusMode = {}));
6
7
 
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarFocusMode.js","sources":["../../../Common/ToolbarFocusMode.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/** Keyboard focus behavior for Toolbar and ActionMenubar. A single-Tab-stop mode is planned for #353. */\nexport enum ToolbarFocusMode {\n /** Navigate with arrows and Home/End while retaining every tool's Tab stop (default). */\n Arrows = 'arrows',\n /** Keep native focus behavior with no toolbar keyboard handling. */\n None = 'none',\n}\n"],"names":[],"mappings":"IAIY;AAAZ,CAAA,UAAY,gBAAgB,EAAA;AAExB,IAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AAEjB,IAAA,gBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACjB,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,GAAA,EAAA,CAAA,CAAA;;"}
1
+ {"version":3,"file":"ToolbarFocusMode.js","sources":["../../../Common/ToolbarFocusMode.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/** Keyboard focus behavior for Toolbar and ActionMenubar. */\nexport enum ToolbarFocusMode {\n /** Navigate with arrows and Home/End while retaining every tool's Tab stop (default). */\n Arrows = 'arrows',\n /**\n * Navigate with arrows and Home/End, with one Tab stop for the toolbar's own tools that\n * returns to the last focused tool (the WAI-ARIA toolbar pattern). Controls you add yourself,\n * widgets such as inputs and sliders, tools rendered outside the toolbar's own markup (for example\n * through a portal), and tools with an explicit tab index keep their own Tab stop. An explicit\n * tab index of -1 removes the tool from both Tab and arrow-key navigation.\n */\n SingleTabStop = 'singleTabStop',\n /** Keep native focus behavior with no toolbar keyboard handling. */\n None = 'none',\n}\n"],"names":[],"mappings":"IAIY;AAAZ,CAAA,UAAY,gBAAgB,EAAA;AAExB,IAAA,gBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB;AAQjB,IAAA,gBAAA,CAAA,eAAA,CAAA,GAAA,eAA+B;AAE/B,IAAA,gBAAA,CAAA,MAAA,CAAA,GAAA,MAAa;AACjB,CAAC,EAbW,gBAAgB,KAAhB,gBAAgB,GAAA,EAAA,CAAA,CAAA;;"}
@@ -0,0 +1,39 @@
1
+ import { type FocusEvent, type Ref } from 'react';
2
+ /**
3
+ * The single-Tab-stop state a toolbar shares with the tools it owns. Its identity is stable for
4
+ * the toolbar's lifetime in that mode; tools subscribe to the active tool instead of re-rendering
5
+ * with every focus change.
6
+ */
7
+ export interface ToolbarRoving {
8
+ /** The active tool's key, or null until the toolbar has chosen one. */
9
+ getActiveKey(): string | null;
10
+ /**
11
+ * Whether a tool lies in the toolbar's own DOM scope. A tool rendered elsewhere, for example
12
+ * through a portal or under a nested consumer toolbar, keeps its native Tab stop.
13
+ */
14
+ isInScope(key: string): boolean;
15
+ /** Subscribes to changes of the active tool. */
16
+ subscribe(listener: () => void): () => void;
17
+ /** Records the element for a tool, or removes it when the element is null. */
18
+ register(key: string, element: HTMLElement | null): void;
19
+ /** Makes a tool the toolbar's single Tab stop. */
20
+ activate(key: string): void;
21
+ }
22
+ /** Provided by a toolbar in single-Tab-stop mode; null in every other mode. */
23
+ export declare const ToolbarRovingContext: import("react").Context<ToolbarRoving | null>;
24
+ /** The props a Components-owned tool spreads onto its focusable element. */
25
+ export interface RovingToolProps<TElement extends HTMLElement> {
26
+ ref?: Ref<TElement>;
27
+ tabIndex?: number;
28
+ onFocus?: (event: FocusEvent<TElement>) => void;
29
+ }
30
+ /**
31
+ * Makes a Components-owned tool take part in its toolbar's single Tab stop. React renders the
32
+ * tab index, so nothing rewrites DOM attributes that React also owns. A tool with an explicit
33
+ * tab index keeps it and stays outside the roving set.
34
+ * @param explicitTabIndex The tab index the consumer set on the tool, if any.
35
+ * @param onFocus The consumer's focus handler, called before the tool becomes active.
36
+ * @returns The ref, tab index, and focus handler to spread onto the tool's element.
37
+ */
38
+ export declare const useRovingTool: <TElement extends HTMLElement>(explicitTabIndex: number | undefined, onFocus: ((event: FocusEvent<TElement>) => void) | undefined) => RovingToolProps<TElement>;
39
+ //# sourceMappingURL=ToolbarRovingContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolbarRovingContext.d.ts","sourceRoot":"","sources":["../../../Common/ToolbarRovingContext.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuE,KAAK,UAAU,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAEvH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B,uEAAuE;IACvE,YAAY,IAAI,MAAM,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,gDAAgD;IAChD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IACzD,kDAAkD;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,+CAA4C,CAAC;AAE9E,4EAA4E;AAC5E,MAAM,WAAW,eAAe,CAAC,QAAQ,SAAS,WAAW;IACzD,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CACnD;AAQD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,WAAW,oBACpC,MAAM,GAAG,SAAS,WAC3B,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,KAC7D,eAAe,CAAC,QAAQ,CA+B1B,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { createContext, useContext, useId, useSyncExternalStore, useCallback } from 'react';
2
+
3
+ const ToolbarRovingContext = createContext(null);
4
+ const subscribeToNothing = () => () => undefined;
5
+ const unmanaged = 'unmanaged';
6
+ const undecided = 'undecided';
7
+ const active = 'active';
8
+ const inactive = 'inactive';
9
+ const useRovingTool = (explicitTabIndex, onFocus) => {
10
+ const roving = useContext(ToolbarRovingContext);
11
+ const key = useId();
12
+ const store = explicitTabIndex === undefined ? roving : null;
13
+ const state = useSyncExternalStore(store ? store.subscribe : subscribeToNothing, () => {
14
+ if (!store)
15
+ return unmanaged;
16
+ const activeKey = store.getActiveKey();
17
+ if (activeKey === null)
18
+ return undecided;
19
+ if (!store.isInScope(key))
20
+ return unmanaged;
21
+ return activeKey === key ? active : inactive;
22
+ }, () => (store ? undecided : unmanaged));
23
+ const ref = useCallback((element) => {
24
+ store?.register(key, element);
25
+ }, [store, key]);
26
+ const handleFocus = useCallback((event) => {
27
+ onFocus?.(event);
28
+ store?.activate(key);
29
+ }, [onFocus, store, key]);
30
+ if (!store)
31
+ return { tabIndex: explicitTabIndex, onFocus };
32
+ return {
33
+ ref,
34
+ tabIndex: state === active ? 0 : state === inactive ? -1 : undefined,
35
+ onFocus: handleFocus,
36
+ };
37
+ };
38
+
39
+ export { ToolbarRovingContext, useRovingTool };
40
+ //# sourceMappingURL=ToolbarRovingContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolbarRovingContext.js","sources":["../../../Common/ToolbarRovingContext.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { createContext, useCallback, useContext, useId, useSyncExternalStore, type FocusEvent, type Ref } from 'react';\n\n/**\n * The single-Tab-stop state a toolbar shares with the tools it owns. Its identity is stable for\n * the toolbar's lifetime in that mode; tools subscribe to the active tool instead of re-rendering\n * with every focus change.\n */\nexport interface ToolbarRoving {\n /** The active tool's key, or null until the toolbar has chosen one. */\n getActiveKey(): string | null;\n /**\n * Whether a tool lies in the toolbar's own DOM scope. A tool rendered elsewhere, for example\n * through a portal or under a nested consumer toolbar, keeps its native Tab stop.\n */\n isInScope(key: string): boolean;\n /** Subscribes to changes of the active tool. */\n subscribe(listener: () => void): () => void;\n /** Records the element for a tool, or removes it when the element is null. */\n register(key: string, element: HTMLElement | null): void;\n /** Makes a tool the toolbar's single Tab stop. */\n activate(key: string): void;\n}\n\n/** Provided by a toolbar in single-Tab-stop mode; null in every other mode. */\nexport const ToolbarRovingContext = createContext<ToolbarRoving | null>(null);\n\n/** The props a Components-owned tool spreads onto its focusable element. */\nexport interface RovingToolProps<TElement extends HTMLElement> {\n ref?: Ref<TElement>;\n tabIndex?: number;\n onFocus?: (event: FocusEvent<TElement>) => void;\n}\n\nconst subscribeToNothing = () => () => undefined;\nconst unmanaged = 'unmanaged';\nconst undecided = 'undecided';\nconst active = 'active';\nconst inactive = 'inactive';\n\n/**\n * Makes a Components-owned tool take part in its toolbar's single Tab stop. React renders the\n * tab index, so nothing rewrites DOM attributes that React also owns. A tool with an explicit\n * tab index keeps it and stays outside the roving set.\n * @param explicitTabIndex The tab index the consumer set on the tool, if any.\n * @param onFocus The consumer's focus handler, called before the tool becomes active.\n * @returns The ref, tab index, and focus handler to spread onto the tool's element.\n */\nexport const useRovingTool = <TElement extends HTMLElement>(\n explicitTabIndex: number | undefined,\n onFocus: ((event: FocusEvent<TElement>) => void) | undefined,\n): RovingToolProps<TElement> => {\n const roving = useContext(ToolbarRovingContext);\n const key = useId();\n // Only a tool without an explicit tab index is managed by the toolbar.\n const store = explicitTabIndex === undefined ? roving : null;\n const state = useSyncExternalStore(\n store ? store.subscribe : subscribeToNothing,\n () => {\n if (!store) return unmanaged;\n const activeKey = store.getActiveKey();\n if (activeKey === null) return undecided;\n if (!store.isInScope(key)) return unmanaged;\n return activeKey === key ? active : inactive;\n },\n // Server-rendered markup keeps native Tab stops until the toolbar chooses its active tool.\n () => (store ? undecided : unmanaged),\n );\n const ref = useCallback((element: TElement | null) => {\n store?.register(key, element);\n }, [store, key]);\n const handleFocus = useCallback((event: FocusEvent<TElement>) => {\n onFocus?.(event);\n store?.activate(key);\n }, [onFocus, store, key]);\n if (!store) return { tabIndex: explicitTabIndex, onFocus };\n // A tool outside the toolbar's scope still registers, so the toolbar can notice when it enters.\n return {\n ref,\n tabIndex: state === active ? 0 : state === inactive ? -1 : undefined,\n onFocus: handleFocus,\n };\n};\n"],"names":[],"mappings":";;MA2Ba,oBAAoB,GAAG,aAAa,CAAuB,IAAI;AAS5E,MAAM,kBAAkB,GAAG,MAAM,MAAM,SAAS;AAChD,MAAM,SAAS,GAAG,WAAW;AAC7B,MAAM,SAAS,GAAG,WAAW;AAC7B,MAAM,MAAM,GAAG,QAAQ;AACvB,MAAM,QAAQ,GAAG,UAAU;MAUd,aAAa,GAAG,CACzB,gBAAoC,EACpC,OAA4D,KACjC;AAC3B,IAAA,MAAM,MAAM,GAAG,UAAU,CAAC,oBAAoB,CAAC;AAC/C,IAAA,MAAM,GAAG,GAAG,KAAK,EAAE;AAEnB,IAAA,MAAM,KAAK,GAAG,gBAAgB,KAAK,SAAS,GAAG,MAAM,GAAG,IAAI;AAC5D,IAAA,MAAM,KAAK,GAAG,oBAAoB,CAC9B,KAAK,GAAG,KAAK,CAAC,SAAS,GAAG,kBAAkB,EAC5C,MAAK;AACD,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,SAAS;AAC5B,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,EAAE;QACtC,IAAI,SAAS,KAAK,IAAI;AAAE,YAAA,OAAO,SAAS;AACxC,QAAA,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC;AAAE,YAAA,OAAO,SAAS;QAC3C,OAAO,SAAS,KAAK,GAAG,GAAG,MAAM,GAAG,QAAQ;AAChD,IAAA,CAAC,EAED,OAAO,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC,CACxC;AACD,IAAA,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,OAAwB,KAAI;AACjD,QAAA,KAAK,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;AACjC,IAAA,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAChB,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,KAA2B,KAAI;AAC5D,QAAA,OAAO,GAAG,KAAK,CAAC;AAChB,QAAA,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC;IACxB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACzB,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE;IAE1D,OAAO;QACH,GAAG;QACH,QAAQ,EAAE,KAAK,KAAK,MAAM,GAAG,CAAC,GAAG,KAAK,KAAK,QAAQ,GAAG,EAAE,GAAG,SAAS;AACpE,QAAA,OAAO,EAAE,WAAW;KACvB;AACL;;"}
@@ -1,10 +1,12 @@
1
1
  import { type KeyboardEvent } from 'react';
2
2
  import { ToolbarFocusMode } from './ToolbarFocusMode.js';
3
+ import type { ToolbarRoving } from './ToolbarRovingContext.js';
3
4
  type Orientation = 'horizontal' | 'vertical';
4
5
  /** Components-owned toolbar focus behavior; never captures keys from child widgets. */
5
6
  export declare const useToolbarKeyboardNavigation: (orientation: Orientation, focusMode: ToolbarFocusMode) => {
6
7
  rootRef: import("react").RefObject<HTMLDivElement | null>;
7
8
  onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => void;
9
+ roving: ToolbarRoving | null;
8
10
  };
9
11
  export {};
10
12
  //# sourceMappingURL=useToolbarKeyboardNavigation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useToolbarKeyboardNavigation.d.ts","sourceRoot":"","sources":["../../../Common/useToolbarKeyboardNavigation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAoB,CAAC;AAKtD,KAAK,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;AAE7C,uFAAuF;AACvF,eAAO,MAAM,4BAA4B,gBAAiB,WAAW,aAAa,gBAAgB;;uBAiBpE,aAAa,CAAC,cAAc,CAAC;CAwC1D,CAAC"}
1
+ {"version":3,"file":"useToolbarKeyboardNavigation.d.ts","sourceRoot":"","sources":["../../../Common/useToolbarKeyboardNavigation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiD,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAAwB,CAAC;AAK5D,KAAK,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;AAE7C,uFAAuF;AACvF,eAAO,MAAM,4BAA4B,gBAAiB,WAAW,aAAa,gBAAgB;;uBAkLpE,aAAa,CAAC,cAAc,CAAC;;CAwC1D,CAAC"}
@@ -1,29 +1,178 @@
1
- import { useRef, useCallback } from 'react';
1
+ import { useRef, useCallback, useLayoutEffect, useMemo } from 'react';
2
2
  import { ToolbarFocusMode } from './ToolbarFocusMode.js';
3
3
 
4
4
  const toolSelector = 'button, a[href], input, select, textarea, [tabindex]';
5
5
  const widgetSelector = 'input:not([type="button"]):not([type="submit"]):not([type="reset"]), textarea, select, [contenteditable]:not([contenteditable="false"]), [role="slider"], [role="spinbutton"], [role="textbox"], [role="combobox"], [role="listbox"], [role="menu"], [role="menubar"], [role="tree"], [role="grid"], [role="application"]';
6
6
  const useToolbarKeyboardNavigation = (orientation, focusMode) => {
7
7
  const rootRef = useRef(null);
8
+ const singleTabStop = focusMode === ToolbarFocusMode.SingleTabStop;
9
+ const managedByKey = useRef(new Map());
10
+ const keyByManaged = useRef(new Map());
11
+ const activeKeyRef = useRef(null);
12
+ const listeners = useRef(new Set());
13
+ const inScopeRef = useRef(new Set());
14
+ const resizeObserverRef = useRef(null);
15
+ const isInToolbarScope = useCallback((tool) => {
16
+ const root = rootRef.current;
17
+ return !!root && tool !== root && root.contains(tool) && tool.closest('[role="toolbar"]') === root;
18
+ }, []);
19
+ const isAvailable = useCallback((tool) => {
20
+ const root = rootRef.current;
21
+ if (!root || !isInToolbarScope(tool) || tool.matches(':disabled, [disabled], [aria-disabled="true"]'))
22
+ return false;
23
+ if (tool.getAttribute('tabindex') === '-1' && !keyByManaged.current.has(tool))
24
+ return false;
25
+ for (let element = tool; element && element !== root; element = element.parentElement) {
26
+ if (element.hidden || element.hasAttribute('inert') || element.getAttribute('aria-hidden') === 'true')
27
+ return false;
28
+ const style = getComputedStyle(element);
29
+ if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse')
30
+ return false;
31
+ }
32
+ return true;
33
+ }, [isInToolbarScope]);
8
34
  const tools = useCallback(() => {
9
35
  const root = rootRef.current;
10
36
  if (!root)
11
37
  return [];
12
- return Array.from(root.querySelectorAll(toolSelector)).filter(tool => {
13
- if (tool.closest('[role="toolbar"]') !== root || tool.matches(':disabled, [disabled], [aria-disabled="true"]'))
14
- return false;
15
- if (tool.getAttribute('tabindex') === '-1')
16
- return false;
17
- for (let element = tool; element && element !== root; element = element.parentElement) {
18
- if (element.hidden || element.hasAttribute('inert') || element.getAttribute('aria-hidden') === 'true')
19
- return false;
20
- const style = getComputedStyle(element);
21
- if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse')
22
- return false;
38
+ return Array.from(root.querySelectorAll(toolSelector)).filter(isAvailable);
39
+ }, [isAvailable]);
40
+ const notify = useCallback(() => listeners.current.forEach(listener => listener()), []);
41
+ const setActiveKey = useCallback((key) => {
42
+ if (activeKeyRef.current === key)
43
+ return false;
44
+ activeKeyRef.current = key;
45
+ notify();
46
+ return true;
47
+ }, [notify]);
48
+ const reconcile = useCallback(() => {
49
+ if (!singleTabStop)
50
+ return;
51
+ let scopeChanged = false;
52
+ for (const key of inScopeRef.current) {
53
+ if (!managedByKey.current.has(key))
54
+ inScopeRef.current.delete(key);
55
+ }
56
+ for (const [key, element] of managedByKey.current) {
57
+ const inside = isInToolbarScope(element);
58
+ if (inside === inScopeRef.current.has(key))
59
+ continue;
60
+ if (inside)
61
+ inScopeRef.current.add(key);
62
+ else
63
+ inScopeRef.current.delete(key);
64
+ scopeChanged = true;
65
+ }
66
+ const current = activeKeyRef.current;
67
+ const element = current === null ? undefined : managedByKey.current.get(current);
68
+ if (!(element && inScopeRef.current.has(current) && isAvailable(element))) {
69
+ const first = tools().find(tool => inScopeRef.current.has(keyByManaged.current.get(tool) ?? ''));
70
+ if (setActiveKey(first ? keyByManaged.current.get(first) : null))
71
+ return;
72
+ }
73
+ if (scopeChanged)
74
+ notify();
75
+ }, [singleTabStop, isInToolbarScope, isAvailable, tools, setActiveKey, notify]);
76
+ const reconcileScheduled = useRef(false);
77
+ const scheduleReconcile = useCallback(() => {
78
+ if (reconcileScheduled.current)
79
+ return;
80
+ reconcileScheduled.current = true;
81
+ queueMicrotask(() => {
82
+ reconcileScheduled.current = false;
83
+ reconcile();
84
+ });
85
+ }, [reconcile]);
86
+ const pendingRemovalRef = useRef(new Set());
87
+ const removalCheckScheduledRef = useRef(false);
88
+ const scheduleRemovalCheck = useCallback(() => {
89
+ if (removalCheckScheduledRef.current)
90
+ return;
91
+ removalCheckScheduledRef.current = true;
92
+ queueMicrotask(() => {
93
+ removalCheckScheduledRef.current = false;
94
+ if (pendingRemovalRef.current.size === 0)
95
+ return;
96
+ for (const key of pendingRemovalRef.current) {
97
+ const element = managedByKey.current.get(key);
98
+ if (element) {
99
+ keyByManaged.current.delete(element);
100
+ resizeObserverRef.current?.unobserve(element);
101
+ }
102
+ managedByKey.current.delete(key);
23
103
  }
24
- return true;
104
+ pendingRemovalRef.current.clear();
105
+ reconcile();
25
106
  });
26
- }, []);
107
+ }, [reconcile]);
108
+ useLayoutEffect(reconcile);
109
+ useLayoutEffect(() => {
110
+ const root = rootRef.current;
111
+ if (!root || !singleTabStop)
112
+ return;
113
+ const affectsManagedTool = (record) => {
114
+ if (record.type === 'childList')
115
+ return true;
116
+ for (const tool of keyByManaged.current.keys()) {
117
+ if (record.target === tool || record.target.contains(tool))
118
+ return true;
119
+ }
120
+ return false;
121
+ };
122
+ const observer = new MutationObserver(records => {
123
+ if (records.some(affectsManagedTool))
124
+ scheduleReconcile();
125
+ });
126
+ observer.observe(root, {
127
+ childList: true,
128
+ subtree: true,
129
+ attributes: true,
130
+ attributeFilter: ['hidden', 'inert', 'aria-hidden', 'aria-disabled', 'disabled', 'style', 'class'],
131
+ });
132
+ if (typeof ResizeObserver !== 'undefined') {
133
+ resizeObserverRef.current = new ResizeObserver(scheduleReconcile);
134
+ managedByKey.current.forEach(tool => resizeObserverRef.current.observe(tool));
135
+ }
136
+ return () => {
137
+ observer.disconnect();
138
+ resizeObserverRef.current?.disconnect();
139
+ resizeObserverRef.current = null;
140
+ };
141
+ }, [singleTabStop, scheduleReconcile]);
142
+ const roving = useMemo(() => singleTabStop ? {
143
+ getActiveKey: () => activeKeyRef.current,
144
+ isInScope: key => inScopeRef.current.has(key),
145
+ subscribe: listener => {
146
+ listeners.current.add(listener);
147
+ return () => listeners.current.delete(listener);
148
+ },
149
+ register: (key, element) => {
150
+ const previous = managedByKey.current.get(key);
151
+ if (!element) {
152
+ if (previous)
153
+ pendingRemovalRef.current.add(key);
154
+ scheduleRemovalCheck();
155
+ return;
156
+ }
157
+ if (previous === element && pendingRemovalRef.current.delete(key))
158
+ return;
159
+ pendingRemovalRef.current.delete(key);
160
+ if (previous === element)
161
+ return;
162
+ if (previous) {
163
+ keyByManaged.current.delete(previous);
164
+ resizeObserverRef.current?.unobserve(previous);
165
+ }
166
+ managedByKey.current.set(key, element);
167
+ keyByManaged.current.set(element, key);
168
+ resizeObserverRef.current?.observe(element);
169
+ scheduleReconcile();
170
+ },
171
+ activate: key => {
172
+ if (inScopeRef.current.has(key))
173
+ setActiveKey(key);
174
+ },
175
+ } : null, [singleTabStop, scheduleReconcile, scheduleRemovalCheck, setActiveKey]);
27
176
  const onKeyDown = (event) => {
28
177
  if (focusMode === ToolbarFocusMode.None || event.defaultPrevented || event.isPropagationStopped() ||
29
178
  event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.nativeEvent.isComposing)
@@ -69,7 +218,7 @@ const useToolbarKeyboardNavigation = (orientation, focusMode) => {
69
218
  }
70
219
  }
71
220
  };
72
- return { rootRef, onKeyDown };
221
+ return { rootRef, onKeyDown, roving };
73
222
  };
74
223
 
75
224
  export { useToolbarKeyboardNavigation };
@@ -1 +1 @@
1
- {"version":3,"file":"useToolbarKeyboardNavigation.js","sources":["../../../Common/useToolbarKeyboardNavigation.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useRef, type KeyboardEvent } from 'react';\nimport { ToolbarFocusMode } from './ToolbarFocusMode';\n\nconst toolSelector = 'button, a[href], input, select, textarea, [tabindex]';\nconst widgetSelector = 'input:not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]), textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"slider\"], [role=\"spinbutton\"], [role=\"textbox\"], [role=\"combobox\"], [role=\"listbox\"], [role=\"menu\"], [role=\"menubar\"], [role=\"tree\"], [role=\"grid\"], [role=\"application\"]';\n\ntype Orientation = 'horizontal' | 'vertical';\n\n/** Components-owned toolbar focus behavior; never captures keys from child widgets. */\nexport const useToolbarKeyboardNavigation = (orientation: Orientation, focusMode: ToolbarFocusMode) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const tools = useCallback(() => {\n const root = rootRef.current;\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(toolSelector)).filter(tool => {\n if (tool.closest('[role=\"toolbar\"]') !== root || tool.matches(':disabled, [disabled], [aria-disabled=\"true\"]')) return false;\n if (tool.getAttribute('tabindex') === '-1') return false;\n for (let element: HTMLElement | null = tool; element && element !== root; element = element.parentElement) {\n if (element.hidden || element.hasAttribute('inert') || element.getAttribute('aria-hidden') === 'true') return false;\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse') return false;\n }\n return true;\n });\n }, []);\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (focusMode === ToolbarFocusMode.None || event.defaultPrevented || event.isPropagationStopped() ||\n event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.nativeEvent.isComposing) return;\n const root = rootRef.current;\n const target = event.target;\n // React events from a portal may bubble here without a DOM ancestor relationship.\n if (!(target instanceof Element) || !root?.contains(target) ||\n target.closest('[role=\"toolbar\"]') !== root) return;\n for (let element: Element | null = target; element && element !== root; element = element.parentElement) {\n if (element.matches(widgetSelector)) return;\n }\n const available = tools();\n const current = target.closest<HTMLElement>(toolSelector);\n if (!current || current === root || current.closest('[role=\"toolbar\"]') !== root) return;\n const index = available.indexOf(current);\n\n const directionElement = root.closest<HTMLElement>('[dir]');\n const direction = getComputedStyle(root).direction || directionElement?.dir || 'ltr';\n const forward = direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight';\n const backward = direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n let candidates: HTMLElement[] = [];\n if (event.key === 'Home') candidates = available;\n else if (event.key === 'End') candidates = available.slice().reverse();\n else if (event.key === (orientation === 'vertical' ? 'ArrowDown' : forward)) candidates = index >= 0\n ? available.slice(index + 1)\n : available.filter(tool => !!(current.compareDocumentPosition(tool) & Node.DOCUMENT_POSITION_FOLLOWING));\n else if (event.key === (orientation === 'vertical' ? 'ArrowUp' : backward)) candidates = index >= 0\n ? available.slice(0, index).reverse()\n : available.slice().reverse().filter(tool => !!(current.compareDocumentPosition(tool) & Node.DOCUMENT_POSITION_PRECEDING));\n for (const candidate of candidates) {\n if (candidate === current) return;\n candidate.focus();\n if ((candidate.getRootNode() as Document | ShadowRoot).activeElement === candidate || candidate.matches(':focus')) {\n event.preventDefault();\n return;\n }\n }\n };\n\n return { rootRef, onKeyDown };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useToolbarKeyboardNavigation.js","sources":["../../../Common/useToolbarKeyboardNavigation.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useLayoutEffect, useMemo, useRef, type KeyboardEvent } from 'react';\nimport { ToolbarFocusMode } from './ToolbarFocusMode';\nimport type { ToolbarRoving } from './ToolbarRovingContext';\n\nconst toolSelector = 'button, a[href], input, select, textarea, [tabindex]';\nconst widgetSelector = 'input:not([type=\"button\"]):not([type=\"submit\"]):not([type=\"reset\"]), textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"slider\"], [role=\"spinbutton\"], [role=\"textbox\"], [role=\"combobox\"], [role=\"listbox\"], [role=\"menu\"], [role=\"menubar\"], [role=\"tree\"], [role=\"grid\"], [role=\"application\"]';\n\ntype Orientation = 'horizontal' | 'vertical';\n\n/** Components-owned toolbar focus behavior; never captures keys from child widgets. */\nexport const useToolbarKeyboardNavigation = (orientation: Orientation, focusMode: ToolbarFocusMode) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const singleTabStop = focusMode === ToolbarFocusMode.SingleTabStop;\n // Tools the toolbar owns in single-Tab-stop mode. Their -1 tab index comes from this toolbar,\n // so it does not make them unreachable by arrow keys.\n const managedByKey = useRef(new Map<string, HTMLElement>());\n const keyByManaged = useRef(new Map<HTMLElement, string>());\n const activeKeyRef = useRef<string | null>(null);\n const listeners = useRef(new Set<() => void>());\n\n // Keys of managed tools that lie in this toolbar's own DOM scope. A tool rendered through a\n // portal or under a nested consumer toolbar can never be reached from here, so it keeps its\n // native Tab stop instead of a -1 the toolbar could never lift.\n const inScopeRef = useRef(new Set<string>());\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n const isInToolbarScope = useCallback((tool: Element) => {\n const root = rootRef.current;\n return !!root && tool !== root && root.contains(tool) && tool.closest('[role=\"toolbar\"]') === root;\n }, []);\n\n const isAvailable = useCallback((tool: HTMLElement) => {\n const root = rootRef.current;\n if (!root || !isInToolbarScope(tool) || tool.matches(':disabled, [disabled], [aria-disabled=\"true\"]')) return false;\n if (tool.getAttribute('tabindex') === '-1' && !keyByManaged.current.has(tool)) return false;\n for (let element: HTMLElement | null = tool; element && element !== root; element = element.parentElement) {\n if (element.hidden || element.hasAttribute('inert') || element.getAttribute('aria-hidden') === 'true') return false;\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse') return false;\n }\n return true;\n }, [isInToolbarScope]);\n\n const tools = useCallback(() => {\n const root = rootRef.current;\n if (!root) return [];\n return Array.from(root.querySelectorAll<HTMLElement>(toolSelector)).filter(isAvailable);\n }, [isAvailable]);\n\n const notify = useCallback(() => listeners.current.forEach(listener => listener()), []);\n\n const setActiveKey = useCallback((key: string | null) => {\n if (activeKeyRef.current === key) return false;\n activeKeyRef.current = key;\n notify();\n return true;\n }, [notify]);\n\n // Keep the active tool available: when it is removed, disabled, hidden, moved out of scope, or\n // opts out with its own tab index, the first available tool the toolbar owns becomes the single\n // Tab stop. This only changes the toolbar's own state; tools render their tab index from it.\n const reconcile = useCallback(() => {\n if (!singleTabStop) return;\n let scopeChanged = false;\n for (const key of inScopeRef.current) {\n if (!managedByKey.current.has(key)) inScopeRef.current.delete(key);\n }\n for (const [key, element] of managedByKey.current) {\n const inside = isInToolbarScope(element);\n if (inside === inScopeRef.current.has(key)) continue;\n if (inside) inScopeRef.current.add(key);\n else inScopeRef.current.delete(key);\n scopeChanged = true;\n }\n const current = activeKeyRef.current;\n const element = current === null ? undefined : managedByKey.current.get(current);\n // Checking the active tool alone is enough on most renders; the full scan runs only when it is gone.\n if (!(element && inScopeRef.current.has(current!) && isAvailable(element))) {\n const first = tools().find(tool => inScopeRef.current.has(keyByManaged.current.get(tool) ?? ''));\n if (setActiveKey(first ? keyByManaged.current.get(first)! : null)) return;\n }\n if (scopeChanged) notify();\n }, [singleTabStop, isInToolbarScope, isAvailable, tools, setActiveKey, notify]);\n\n // Several registrations and mutations in one commit or frame need only one check.\n const reconcileScheduled = useRef(false);\n const scheduleReconcile = useCallback(() => {\n if (reconcileScheduled.current) return;\n reconcileScheduled.current = true;\n queueMicrotask(() => {\n reconcileScheduled.current = false;\n reconcile();\n });\n }, [reconcile]);\n\n // Tools that unregistered and did not register again: forget them, and choose a new Tab stop\n // if one of them was active (unmounted, or given its own tab index).\n const pendingRemovalRef = useRef(new Set<string>());\n const removalCheckScheduledRef = useRef(false);\n const scheduleRemovalCheck = useCallback(() => {\n if (removalCheckScheduledRef.current) return;\n removalCheckScheduledRef.current = true;\n queueMicrotask(() => {\n removalCheckScheduledRef.current = false;\n if (pendingRemovalRef.current.size === 0) return;\n for (const key of pendingRemovalRef.current) {\n const element = managedByKey.current.get(key);\n if (element) {\n keyByManaged.current.delete(element);\n resizeObserverRef.current?.unobserve(element);\n }\n managedByKey.current.delete(key);\n }\n pendingRemovalRef.current.clear();\n reconcile();\n });\n }, [reconcile]);\n\n useLayoutEffect(reconcile);\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || !singleTabStop) return;\n // Only changes on a managed tool or one of its ancestors can make it unavailable.\n const affectsManagedTool = (record: MutationRecord) => {\n if (record.type === 'childList') return true;\n for (const tool of keyByManaged.current.keys()) {\n if (record.target === tool || record.target.contains(tool)) return true;\n }\n return false;\n };\n const observer = new MutationObserver(records => {\n if (records.some(affectsManagedTool)) scheduleReconcile();\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['hidden', 'inert', 'aria-hidden', 'aria-disabled', 'disabled', 'style', 'class'],\n });\n // Hiding through a stylesheet alone, such as a media query, changes no attribute; the\n // hidden tool's box collapses instead.\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserverRef.current = new ResizeObserver(scheduleReconcile);\n managedByKey.current.forEach(tool => resizeObserverRef.current!.observe(tool));\n }\n return () => {\n observer.disconnect();\n resizeObserverRef.current?.disconnect();\n resizeObserverRef.current = null;\n };\n }, [singleTabStop, scheduleReconcile]);\n\n const roving = useMemo<ToolbarRoving | null>(() => singleTabStop ? {\n getActiveKey: () => activeKeyRef.current,\n isInScope: key => inScopeRef.current.has(key),\n subscribe: listener => {\n listeners.current.add(listener);\n return () => listeners.current.delete(listener);\n },\n register: (key, element) => {\n const previous = managedByKey.current.get(key);\n if (!element) {\n // A tooltip wrapper builds a new merged ref on every render, so React detaches and\n // re-attaches the same element within one commit. Removal waits for a microtask,\n // and a re-attach of the same element in between costs nothing.\n if (previous) pendingRemovalRef.current.add(key);\n scheduleRemovalCheck();\n return;\n }\n if (previous === element && pendingRemovalRef.current.delete(key)) return;\n pendingRemovalRef.current.delete(key);\n if (previous === element) return;\n if (previous) {\n keyByManaged.current.delete(previous);\n resizeObserverRef.current?.unobserve(previous);\n }\n managedByKey.current.set(key, element);\n keyByManaged.current.set(element, key);\n resizeObserverRef.current?.observe(element);\n // A new tool may be the first available one or lie out of scope.\n scheduleReconcile();\n },\n // A tool outside the toolbar's scope cannot hold its single Tab stop.\n activate: key => {\n if (inScopeRef.current.has(key)) setActiveKey(key);\n },\n } : null, [singleTabStop, scheduleReconcile, scheduleRemovalCheck, setActiveKey]);\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (focusMode === ToolbarFocusMode.None || event.defaultPrevented || event.isPropagationStopped() ||\n event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.nativeEvent.isComposing) return;\n const root = rootRef.current;\n const target = event.target;\n // React events from a portal may bubble here without a DOM ancestor relationship.\n if (!(target instanceof Element) || !root?.contains(target) ||\n target.closest('[role=\"toolbar\"]') !== root) return;\n for (let element: Element | null = target; element && element !== root; element = element.parentElement) {\n if (element.matches(widgetSelector)) return;\n }\n const available = tools();\n const current = target.closest<HTMLElement>(toolSelector);\n if (!current || current === root || current.closest('[role=\"toolbar\"]') !== root) return;\n const index = available.indexOf(current);\n\n const directionElement = root.closest<HTMLElement>('[dir]');\n const direction = getComputedStyle(root).direction || directionElement?.dir || 'ltr';\n const forward = direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight';\n const backward = direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n let candidates: HTMLElement[] = [];\n if (event.key === 'Home') candidates = available;\n else if (event.key === 'End') candidates = available.slice().reverse();\n else if (event.key === (orientation === 'vertical' ? 'ArrowDown' : forward)) candidates = index >= 0\n ? available.slice(index + 1)\n : available.filter(tool => !!(current.compareDocumentPosition(tool) & Node.DOCUMENT_POSITION_FOLLOWING));\n else if (event.key === (orientation === 'vertical' ? 'ArrowUp' : backward)) candidates = index >= 0\n ? available.slice(0, index).reverse()\n : available.slice().reverse().filter(tool => !!(current.compareDocumentPosition(tool) & Node.DOCUMENT_POSITION_PRECEDING));\n for (const candidate of candidates) {\n if (candidate === current) return;\n candidate.focus();\n if ((candidate.getRootNode() as Document | ShadowRoot).activeElement === candidate || candidate.matches(':focus')) {\n event.preventDefault();\n return;\n }\n }\n };\n\n return { rootRef, onKeyDown, roving };\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { DataTableMessages } from './DataTableMessages.js';
3
+ import type { DataTableParts } from './DataTableParts.js';
4
+ import { DataTableStatus } from './DataTableStatus.js';
5
+ /** Props for {@link DataTableBody}. */
6
+ export interface DataTableBodyProps {
7
+ status: DataTableStatus;
8
+ /** Whether the table was given any rows, before filtering. */
9
+ hasLoadedRows: boolean;
10
+ /** How many rows are left to render after filtering. */
11
+ rowCount: number;
12
+ columnCount: number;
13
+ /** The table's part attributes. */
14
+ parts?: DataTableParts;
15
+ messages: DataTableMessages;
16
+ emptyMessage: ReactNode;
17
+ /** Renders the data rows; called only when there are rows to show. */
18
+ renderRows: () => ReactNode;
19
+ }
20
+ /** The table body: a failure, loading or empty message row, or the data rows. */
21
+ export declare const DataTableBody: ({ status, hasLoadedRows, rowCount, columnCount, parts: pt, messages, emptyMessage, renderRows, }: DataTableBodyProps) => import("react").JSX.Element;
22
+ //# sourceMappingURL=DataTableBody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableBody.d.ts","sourceRoot":"","sources":["../../../DataTables/DataTableBody.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAkB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAmB,CAAC;AAEpD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,8DAA8D;IAC9D,aAAa,EAAE,OAAO,CAAC;IACvB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,YAAY,EAAE,SAAS,CAAC;IACxB,sEAAsE;IACtE,UAAU,EAAE,MAAM,SAAS,CAAC;CAC/B;AAED,iFAAiF;AACjF,eAAO,MAAM,aAAa,qGASvB,kBAAkB,gCAgFpB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { classNames } from './classNames.js';
3
+ import { DataTableStatus } from './DataTableStatus.js';
4
+
5
+ const DataTableBody = ({ status, hasLoadedRows, rowCount, columnCount, parts: pt, messages, emptyMessage, renderRows, }) => (jsx("tbody", { ...pt?.body, className: classNames('cratis-datatable__body', pt?.body?.className), "data-cratis-part": 'body', children: status === DataTableStatus.Failed || status === DataTableStatus.Unauthorized ? (jsx("tr", { ...pt?.failureRow, className: classNames('cratis-datatable__failure-row', pt?.failureRow?.className), "data-cratis-part": 'failure-row', "data-reason": status, children: jsx("td", { ...pt?.failureCell, colSpan: Math.max(columnCount, 1), className: classNames('cratis-datatable__failure-cell', pt?.failureCell?.className), "data-cratis-part": 'failure-cell', children: jsx("div", { role: 'alert', children: status === DataTableStatus.Failed
6
+ ? messages.resolvedFailureMessage
7
+ : messages.resolvedUnauthorizedMessage }) }) }, status)) : status === DataTableStatus.Loading && !hasLoadedRows ? (jsx("tr", { ...pt?.loadingRow, className: classNames('cratis-datatable__loading-row', pt?.loadingRow?.className), "data-cratis-part": 'loading-row', children: jsx("td", { ...pt?.loadingCell, colSpan: Math.max(columnCount, 1), className: classNames('cratis-datatable__loading-cell', pt?.loadingCell?.className), "data-cratis-part": 'loading-cell', children: jsx("div", { role: 'status', children: messages.resolvedLoadingMessage }) }) }, status)) : rowCount === 0 ? (jsx("tr", { ...pt?.emptyRow, className: classNames('cratis-datatable__empty-row', pt?.emptyRow?.className), "data-cratis-part": 'empty-row', children: jsx("td", { ...pt?.emptyCell, colSpan: Math.max(columnCount, 1), className: classNames('cratis-datatable__empty-cell', pt?.emptyCell?.className), "data-cratis-part": 'empty-cell', children: emptyMessage }) })) : (renderRows()) }));
8
+
9
+ export { DataTableBody };
10
+ //# sourceMappingURL=DataTableBody.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableBody.js","sources":["../../../DataTables/DataTableBody.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type { ReactNode } from 'react';\nimport { classNames } from './classNames';\nimport type { DataTableMessages } from './DataTableMessages';\nimport type { DataTableParts } from './DataTableParts';\nimport { DataTableStatus } from './DataTableStatus';\n\n/** Props for {@link DataTableBody}. */\nexport interface DataTableBodyProps {\n status: DataTableStatus;\n /** Whether the table was given any rows, before filtering. */\n hasLoadedRows: boolean;\n /** How many rows are left to render after filtering. */\n rowCount: number;\n columnCount: number;\n /** The table's part attributes. */\n parts?: DataTableParts;\n messages: DataTableMessages;\n emptyMessage: ReactNode;\n /** Renders the data rows; called only when there are rows to show. */\n renderRows: () => ReactNode;\n}\n\n/** The table body: a failure, loading or empty message row, or the data rows. */\nexport const DataTableBody = ({\n status,\n hasLoadedRows,\n rowCount,\n columnCount,\n parts: pt,\n messages,\n emptyMessage,\n renderRows,\n}: DataTableBodyProps) => (\n <tbody\n {...pt?.body}\n className={classNames('cratis-datatable__body', pt?.body?.className)}\n data-cratis-part='body'\n >\n {status === DataTableStatus.Failed || status === DataTableStatus.Unauthorized ? (\n <tr\n key={status}\n {...pt?.failureRow}\n className={classNames(\n 'cratis-datatable__failure-row',\n pt?.failureRow?.className,\n )}\n data-cratis-part='failure-row'\n data-reason={status}\n >\n <td\n {...pt?.failureCell}\n colSpan={Math.max(columnCount, 1)}\n className={classNames(\n 'cratis-datatable__failure-cell',\n pt?.failureCell?.className,\n )}\n data-cratis-part='failure-cell'\n >\n <div role='alert'>\n {status === DataTableStatus.Failed\n ? messages.resolvedFailureMessage\n : messages.resolvedUnauthorizedMessage}\n </div>\n </td>\n </tr>\n ) : status === DataTableStatus.Loading && !hasLoadedRows ? (\n <tr\n key={status}\n {...pt?.loadingRow}\n className={classNames(\n 'cratis-datatable__loading-row',\n pt?.loadingRow?.className,\n )}\n data-cratis-part='loading-row'\n >\n <td\n {...pt?.loadingCell}\n colSpan={Math.max(columnCount, 1)}\n className={classNames(\n 'cratis-datatable__loading-cell',\n pt?.loadingCell?.className,\n )}\n data-cratis-part='loading-cell'\n >\n <div role='status'>{messages.resolvedLoadingMessage}</div>\n </td>\n </tr>\n ) : rowCount === 0 ? (\n <tr\n {...pt?.emptyRow}\n className={classNames(\n 'cratis-datatable__empty-row',\n pt?.emptyRow?.className,\n )}\n data-cratis-part='empty-row'\n >\n <td\n {...pt?.emptyCell}\n colSpan={Math.max(columnCount, 1)}\n className={classNames(\n 'cratis-datatable__empty-cell',\n pt?.emptyCell?.className,\n )}\n data-cratis-part='empty-cell'\n >\n {emptyMessage}\n </td>\n </tr>\n ) : (\n renderRows()\n )}\n </tbody>\n);\n"],"names":["_jsx"],"mappings":";;;;AA0BO,MAAM,aAAa,GAAG,CAAC,EAC1B,MAAM,EACN,aAAa,EACb,QAAQ,EACR,WAAW,EACX,KAAK,EAAE,EAAE,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,GACO,MACjBA,GAAA,CAAA,OAAA,EAAA,EAAA,GACQ,EAAE,EAAE,IAAI,EACZ,SAAS,EAAE,UAAU,CAAC,wBAAwB,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,EAAA,kBAAA,EACnD,MAAM,EAAA,QAAA,EAEtB,MAAM,KAAK,eAAe,CAAC,MAAM,IAAI,MAAM,KAAK,eAAe,CAAC,YAAY,IACzEA,GAAA,CAAA,IAAA,EAAA,EAAA,GAEQ,EAAE,EAAE,UAAU,EAClB,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,UAAU,EAAE,SAAS,CAC5B,EAAA,kBAAA,EACgB,aAAa,EAAA,aAAA,EACjB,MAAM,EAAA,QAAA,EAEnBA,GAAA,CAAA,IAAA,EAAA,EAAA,GACQ,EAAE,EAAE,WAAW,EACnB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EACjC,SAAS,EAAE,UAAU,CACjB,gCAAgC,EAChC,EAAE,EAAE,WAAW,EAAE,SAAS,CAC7B,EAAA,kBAAA,EACgB,cAAc,EAAA,QAAA,EAE/BA,GAAA,CAAA,KAAA,EAAA,EAAK,IAAI,EAAC,OAAO,EAAA,QAAA,EACZ,MAAM,KAAK,eAAe,CAAC;sBACtB,QAAQ,CAAC;AACX,sBAAE,QAAQ,CAAC,2BAA2B,EAAA,CACxC,GACL,EAAA,EAvBA,MAAM,CAwBV,IACL,MAAM,KAAK,eAAe,CAAC,OAAO,IAAI,CAAC,aAAa,IACpDA,GAAA,CAAA,IAAA,EAAA,EAAA,GAEQ,EAAE,EAAE,UAAU,EAClB,SAAS,EAAE,UAAU,CACjB,+BAA+B,EAC/B,EAAE,EAAE,UAAU,EAAE,SAAS,CAC5B,sBACgB,aAAa,EAAA,QAAA,EAE9BA,GAAA,CAAA,IAAA,EAAA,EAAA,GACQ,EAAE,EAAE,WAAW,EACnB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EACjC,SAAS,EAAE,UAAU,CACjB,gCAAgC,EAChC,EAAE,EAAE,WAAW,EAAE,SAAS,CAC7B,sBACgB,cAAc,EAAA,QAAA,EAE/BA,aAAK,IAAI,EAAC,QAAQ,EAAA,QAAA,EAAE,QAAQ,CAAC,sBAAsB,GAAO,EAAA,CACzD,EAAA,EAlBA,MAAM,CAmBV,IACL,QAAQ,KAAK,CAAC,IACdA,eACQ,EAAE,EAAE,QAAQ,EAChB,SAAS,EAAE,UAAU,CACjB,6BAA6B,EAC7B,EAAE,EAAE,QAAQ,EAAE,SAAS,CAC1B,EAAA,kBAAA,EACgB,WAAW,EAAA,QAAA,EAE5BA,GAAA,CAAA,IAAA,EAAA,EAAA,GACQ,EAAE,EAAE,SAAS,EACjB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EACjC,SAAS,EAAE,UAAU,CACjB,8BAA8B,EAC9B,EAAE,EAAE,SAAS,EAAE,SAAS,CAC3B,EAAA,kBAAA,EACgB,YAAY,EAAA,QAAA,EAE5B,YAAY,GACZ,EAAA,CACJ,KAEL,UAAU,EAAE,CACf,EAAA,CACG;;"}
@@ -1,51 +1,13 @@
1
- import React, { type CSSProperties, type HTMLAttributes, type ReactNode, type TableHTMLAttributes, type TdHTMLAttributes, type ThHTMLAttributes } from 'react';
1
+ import React, { type CSSProperties, type ReactNode } from 'react';
2
+ import type { DataTableFilterMeta } from './DataTableFilterMeta.js';
3
+ import type { DataTableParts } from './DataTableParts.js';
4
+ import type { DataTableRowClickEvent } from './DataTableRowClickEvent.js';
5
+ import { DataTableRowProcessing } from './DataTableRowProcessing.js';
2
6
  import type { DataTableSelectionChangeEvent } from './DataTableSelectionChangeEvent.js';
3
- import { type DataTableFilterMeta } from './DataTableFilterMeta.js';
7
+ import type { DataTableSort } from './DataTableSort.js';
4
8
  import { DataTableStatus } from './DataTableStatus.js';
5
- /** Event emitted when a DataTable row is activated. */
6
- export interface DataTableRowClickEvent<TData> {
7
- /** Activated row data. */
8
- data: TData;
9
- /** Loaded-page row index. */
10
- index: number;
11
- }
12
- /** Stable Cratis-owned parts for styling a {@link DataTableCore}. */
13
- export interface DataTableParts {
14
- /** Outer table composition. */
15
- root?: HTMLAttributes<HTMLDivElement>;
16
- /** Loaded-page search wrapper. */
17
- search?: HTMLAttributes<HTMLDivElement>;
18
- /** Loaded-page search input. */
19
- searchInput?: React.InputHTMLAttributes<HTMLInputElement>;
20
- /** Scroll container. */
21
- tableContainer?: HTMLAttributes<HTMLDivElement>;
22
- /** Semantic table element. */
23
- table?: TableHTMLAttributes<HTMLTableElement>;
24
- /** Table head. */
25
- head?: HTMLAttributes<HTMLTableSectionElement>;
26
- /** Header row. */
27
- headerRow?: HTMLAttributes<HTMLTableRowElement>;
28
- /** Header cell. */
29
- headerCell?: ThHTMLAttributes<HTMLTableCellElement>;
30
- /** Table body. */
31
- body?: HTMLAttributes<HTMLTableSectionElement>;
32
- /** Data row. */
33
- row?: HTMLAttributes<HTMLTableRowElement>;
34
- /** Data cell. */
35
- cell?: TdHTMLAttributes<HTMLTableCellElement>;
36
- /** Empty-state row. */
37
- emptyRow?: HTMLAttributes<HTMLTableRowElement>;
38
- /** Empty-state cell. */
39
- emptyCell?: TdHTMLAttributes<HTMLTableCellElement>;
40
- /** Loading-state row. */
41
- loadingRow?: HTMLAttributes<HTMLTableRowElement>;
42
- /** Loading-state cell. */
43
- loadingCell?: TdHTMLAttributes<HTMLTableCellElement>;
44
- /** Failed or unauthorized row. */
45
- failureRow?: HTMLAttributes<HTMLTableRowElement>;
46
- /** Failed or unauthorized cell. */
47
- failureCell?: TdHTMLAttributes<HTMLTableCellElement>;
48
- }
9
+ export type { DataTableParts } from './DataTableParts.js';
10
+ export type { DataTableRowClickEvent } from './DataTableRowClickEvent.js';
49
11
  /** Props for the semantic loaded-page DataTable renderer. */
50
12
  export interface DataTableCoreProps<TData extends object> {
51
13
  /** Loaded page rows. */
@@ -94,8 +56,24 @@ export interface DataTableCoreProps<TData extends object> {
94
56
  globalSearchAriaLabel?: string;
95
57
  /** Initial per-field filter constraints. */
96
58
  defaultFilters?: DataTableFilterMeta;
59
+ /** Controlled per-field filter constraints. Leave undefined to let the table keep its own. */
60
+ filters?: DataTableFilterMeta;
97
61
  /** Invoked when applied field filters change. */
98
62
  onFilter?: (filters: DataTableFilterMeta) => void;
63
+ /** Controlled search text. Leave undefined to let the table keep its own. */
64
+ globalFilter?: string;
65
+ /** Invoked when the search text changes. */
66
+ onGlobalFilterChange?: (globalFilter: string) => void;
67
+ /** Controlled sort; null means not sorted. Leave undefined to let the table keep its own. */
68
+ sort?: DataTableSort | null;
69
+ /** Invoked when a sortable column header changes the sort. */
70
+ onSortChange?: (sort: DataTableSort | null) => void;
71
+ /**
72
+ * Whether the table filters and sorts the rows it is given (default:
73
+ * {@link DataTableRowProcessing.Loaded}). Use {@link DataTableRowProcessing.None} when the
74
+ * source already applied the controlled filter and sort state.
75
+ */
76
+ rowProcessing?: DataTableRowProcessing;
99
77
  /** Enables the bounded scroll container. */
100
78
  scrollable?: boolean;
101
79
  /** Scroll-container maximum height. */
@@ -116,5 +94,5 @@ export interface DataTableCoreProps<TData extends object> {
116
94
  unstyled?: boolean;
117
95
  }
118
96
  /** A semantic, renderer-independent data table over one already-loaded page. */
119
- export declare const DataTableCore: <TData extends object>({ data, children, dataKey, emptyMessage, status, loadingMessage, failureMessage, unauthorizedMessage, selectionMode, selectionAriaLabel, selectAllAriaLabel, selection, onSelectionChange, selectedItems, onSelectedItemsChange, onRowClick, rowClassName, globalFilterFields, globalSearchPlaceholder, globalSearchAriaLabel, defaultFilters, onFilter, scrollable, scrollHeight, className, style, pt, }: DataTableCoreProps<TData>) => React.JSX.Element;
97
+ export declare const DataTableCore: <TData extends object>({ data, children, dataKey, emptyMessage, status, loadingMessage, failureMessage, unauthorizedMessage, selectionMode, selectionAriaLabel, selectAllAriaLabel, selection, onSelectionChange, selectedItems, onSelectedItemsChange, onRowClick, rowClassName, globalFilterFields, globalSearchPlaceholder, globalSearchAriaLabel, defaultFilters, filters: filtersProp, onFilter, globalFilter: globalFilterProp, onGlobalFilterChange, sort: sortProp, onSortChange, rowProcessing, scrollable, scrollHeight, className, style, pt, }: DataTableCoreProps<TData>) => React.JSX.Element;
120
98
  //# sourceMappingURL=DataTableCore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableCore.d.ts","sourceRoot":"","sources":["../../../DataTables/DataTableCore.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DataTableCore.d.ts","sourceRoot":"","sources":["../../../DataTables/DataTableCore.tsx"],"names":[],"mappings":"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"}