@cratis/components 4.19.2 → 4.21.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.
- package/README.md +2 -2
- package/compat-manifest.json +11 -11
- package/dist/esm/Chat/ChatConversation.d.ts +8 -1
- package/dist/esm/Chat/ChatConversation.d.ts.map +1 -1
- package/dist/esm/Chat/ChatConversation.js +2 -2
- package/dist/esm/Chat/ChatConversation.js.map +1 -1
- package/dist/esm/Chat/ChatSidebar.d.ts +12 -2
- package/dist/esm/Chat/ChatSidebar.d.ts.map +1 -1
- package/dist/esm/Chat/ChatSidebar.js +2 -2
- package/dist/esm/Chat/ChatSidebar.js.map +1 -1
- package/dist/esm/Chat/ChatTopicAction.d.ts +23 -0
- package/dist/esm/Chat/ChatTopicAction.d.ts.map +1 -0
- package/dist/esm/Chat/ChatTopicAction.js +4 -0
- package/dist/esm/Chat/ChatTopicAction.js.map +1 -0
- package/dist/esm/Chat/ChatTopicActions.d.ts +25 -0
- package/dist/esm/Chat/ChatTopicActions.d.ts.map +1 -0
- package/dist/esm/Chat/ChatTopicActions.js +6 -0
- package/dist/esm/Chat/ChatTopicActions.js.map +1 -0
- package/dist/esm/Chat/ChatTopicList.d.ts +5 -2
- package/dist/esm/Chat/ChatTopicList.d.ts.map +1 -1
- package/dist/esm/Chat/ChatTopicList.js +17 -9
- package/dist/esm/Chat/ChatTopicList.js.map +1 -1
- package/dist/esm/Chat/index.d.ts +1 -0
- package/dist/esm/Chat/index.d.ts.map +1 -1
- package/dist/esm/Chat/useTopicActionFocusRecovery.d.ts +19 -0
- package/dist/esm/Chat/useTopicActionFocusRecovery.d.ts.map +1 -0
- package/dist/esm/Chat/useTopicActionFocusRecovery.js +41 -0
- package/dist/esm/Chat/useTopicActionFocusRecovery.js.map +1 -0
- package/dist/esm/Common/ActionMenubar.d.ts.map +1 -1
- package/dist/esm/Common/ActionMenubar.js +11 -6
- package/dist/esm/Common/ActionMenubar.js.map +1 -1
- package/dist/esm/Common/ToolbarFocusMode.d.ts +9 -1
- package/dist/esm/Common/ToolbarFocusMode.d.ts.map +1 -1
- package/dist/esm/Common/ToolbarFocusMode.js +1 -0
- package/dist/esm/Common/ToolbarFocusMode.js.map +1 -1
- package/dist/esm/Common/ToolbarRovingContext.d.ts +39 -0
- package/dist/esm/Common/ToolbarRovingContext.d.ts.map +1 -0
- package/dist/esm/Common/ToolbarRovingContext.js +40 -0
- package/dist/esm/Common/ToolbarRovingContext.js.map +1 -0
- package/dist/esm/Common/useToolbarKeyboardNavigation.d.ts +2 -0
- package/dist/esm/Common/useToolbarKeyboardNavigation.d.ts.map +1 -1
- package/dist/esm/Common/useToolbarKeyboardNavigation.js +164 -15
- package/dist/esm/Common/useToolbarKeyboardNavigation.js.map +1 -1
- package/dist/esm/DataTables/DataTableCore.d.ts +19 -1
- package/dist/esm/DataTables/DataTableCore.d.ts.map +1 -1
- package/dist/esm/DataTables/DataTableCore.js +19 -14
- package/dist/esm/DataTables/DataTableCore.js.map +1 -1
- package/dist/esm/DataTables/DataTableRowProcessing.d.ts +11 -0
- package/dist/esm/DataTables/DataTableRowProcessing.d.ts.map +1 -0
- package/dist/esm/DataTables/DataTableRowProcessing.js +8 -0
- package/dist/esm/DataTables/DataTableRowProcessing.js.map +1 -0
- package/dist/esm/DataTables/DataTableSort.d.ts +9 -0
- package/dist/esm/DataTables/DataTableSort.d.ts.map +1 -0
- package/dist/esm/DataTables/DataTableSort.js +4 -0
- package/dist/esm/DataTables/DataTableSort.js.map +1 -0
- package/dist/esm/DataTables/DataTableSortDirection.d.ts +8 -0
- package/dist/esm/DataTables/DataTableSortDirection.d.ts.map +1 -0
- package/dist/esm/DataTables/DataTableSortDirection.js +8 -0
- package/dist/esm/DataTables/DataTableSortDirection.js.map +1 -0
- package/dist/esm/DataTables/index.d.ts +3 -0
- package/dist/esm/DataTables/index.d.ts.map +1 -1
- package/dist/esm/DataTables/index.js +2 -0
- package/dist/esm/DataTables/index.js.map +1 -1
- package/dist/esm/DataTables/useControllableState.d.ts +10 -0
- package/dist/esm/DataTables/useControllableState.d.ts.map +1 -0
- package/dist/esm/DataTables/useControllableState.js +15 -0
- package/dist/esm/DataTables/useControllableState.js.map +1 -0
- package/dist/esm/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/esm/Toolbar/Toolbar.js +3 -2
- package/dist/esm/Toolbar/Toolbar.js.map +1 -1
- package/dist/esm/Toolbar/ToolbarButton.d.ts.map +1 -1
- package/dist/esm/Toolbar/ToolbarButton.js +4 -2
- package/dist/esm/Toolbar/ToolbarButton.js.map +1 -1
- package/dist/esm/Toolbar/ToolbarFanOutItem.d.ts.map +1 -1
- package/dist/esm/Toolbar/ToolbarFanOutItem.js +10 -2
- package/dist/esm/Toolbar/ToolbarFanOutItem.js.map +1 -1
- package/dist/esm/Toolbar/ToolbarFolder.d.ts.map +1 -1
- package/dist/esm/Toolbar/ToolbarFolder.js +10 -2
- package/dist/esm/Toolbar/ToolbarFolder.js.map +1 -1
- package/dist/esm/styles.Canvas.css +17 -1
- package/dist/esm/styles.Chat.css +17 -1
- package/dist/esm/styles.css +17 -1
- package/package.json +8 -2
|
@@ -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(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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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"}
|
|
@@ -2,6 +2,8 @@ import React, { type CSSProperties, type HTMLAttributes, type ReactNode, type Ta
|
|
|
2
2
|
import type { DataTableSelectionChangeEvent } from './DataTableSelectionChangeEvent.js';
|
|
3
3
|
import { type DataTableFilterMeta } from './DataTableFilterMeta.js';
|
|
4
4
|
import { DataTableStatus } from './DataTableStatus.js';
|
|
5
|
+
import type { DataTableSort } from './DataTableSort.js';
|
|
6
|
+
import { DataTableRowProcessing } from './DataTableRowProcessing.js';
|
|
5
7
|
/** Event emitted when a DataTable row is activated. */
|
|
6
8
|
export interface DataTableRowClickEvent<TData> {
|
|
7
9
|
/** Activated row data. */
|
|
@@ -94,8 +96,24 @@ export interface DataTableCoreProps<TData extends object> {
|
|
|
94
96
|
globalSearchAriaLabel?: string;
|
|
95
97
|
/** Initial per-field filter constraints. */
|
|
96
98
|
defaultFilters?: DataTableFilterMeta;
|
|
99
|
+
/** Controlled per-field filter constraints. Leave undefined to let the table keep its own. */
|
|
100
|
+
filters?: DataTableFilterMeta;
|
|
97
101
|
/** Invoked when applied field filters change. */
|
|
98
102
|
onFilter?: (filters: DataTableFilterMeta) => void;
|
|
103
|
+
/** Controlled search text. Leave undefined to let the table keep its own. */
|
|
104
|
+
globalFilter?: string;
|
|
105
|
+
/** Invoked when the search text changes. */
|
|
106
|
+
onGlobalFilterChange?: (globalFilter: string) => void;
|
|
107
|
+
/** Controlled sort; null means not sorted. Leave undefined to let the table keep its own. */
|
|
108
|
+
sort?: DataTableSort | null;
|
|
109
|
+
/** Invoked when a sortable column header changes the sort. */
|
|
110
|
+
onSortChange?: (sort: DataTableSort | null) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Whether the table filters and sorts the rows it is given (default:
|
|
113
|
+
* {@link DataTableRowProcessing.Loaded}). Use {@link DataTableRowProcessing.None} when the
|
|
114
|
+
* source already applied the controlled filter and sort state.
|
|
115
|
+
*/
|
|
116
|
+
rowProcessing?: DataTableRowProcessing;
|
|
99
117
|
/** Enables the bounded scroll container. */
|
|
100
118
|
scrollable?: boolean;
|
|
101
119
|
/** Scroll-container maximum height. */
|
|
@@ -116,5 +134,5 @@ export interface DataTableCoreProps<TData extends object> {
|
|
|
116
134
|
unstyled?: boolean;
|
|
117
135
|
}
|
|
118
136
|
/** 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;
|
|
137
|
+
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
138
|
//# sourceMappingURL=DataTableCore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableCore.d.ts","sourceRoot":"","sources":["../../../DataTables/DataTableCore.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"DataTableCore.d.ts","sourceRoot":"","sources":["../../../DataTables/DataTableCore.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React, { useId,
|
|
2
|
+
import React, { useId, useMemo, useRef, useEffect } from 'react';
|
|
3
3
|
import 'react-aria-components/I18nProvider';
|
|
4
4
|
import 'ts-deepmerge';
|
|
5
5
|
import 'react-dom';
|
|
@@ -11,6 +11,9 @@ import { ColumnFilterMenu } from './ColumnFilterMenu.js';
|
|
|
11
11
|
import { DataTableFilterMatchMode } from './DataTableFilterMeta.js';
|
|
12
12
|
import { resolveDataTableFilterMatcher } from './DataTableFilterMatcherRegistry.js';
|
|
13
13
|
import { DataTableStatus } from './DataTableStatus.js';
|
|
14
|
+
import { DataTableSortDirection } from './DataTableSortDirection.js';
|
|
15
|
+
import { DataTableRowProcessing } from './DataTableRowProcessing.js';
|
|
16
|
+
import { useControllableState } from './useControllableState.js';
|
|
14
17
|
|
|
15
18
|
const useColumns = (children) => useMemo(() => React.Children.toArray(children).filter(React.isValidElement), [children]);
|
|
16
19
|
const asCellValue = (value) => typeof value === 'function' ? String(value) : value;
|
|
@@ -109,7 +112,7 @@ const compareValues = (left, right) => {
|
|
|
109
112
|
});
|
|
110
113
|
};
|
|
111
114
|
const classNames = (...values) => values.filter(Boolean).join(' ');
|
|
112
|
-
const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTableStatus.Ready, loadingMessage, failureMessage, unauthorizedMessage, selectionMode, selectionAriaLabel, selectAllAriaLabel, selection, onSelectionChange, selectedItems, onSelectedItemsChange, onRowClick, rowClassName, globalFilterFields, globalSearchPlaceholder, globalSearchAriaLabel, defaultFilters, onFilter, scrollable, scrollHeight, className, style, pt, }) => {
|
|
115
|
+
const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTableStatus.Ready, 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 = DataTableRowProcessing.Loaded, scrollable, scrollHeight, className, style, pt, }) => {
|
|
113
116
|
const { messages } = useCratisComponentsConfig();
|
|
114
117
|
const dataTableMessages = messages?.dataTable;
|
|
115
118
|
const resolvedSelectionAriaLabel = selectionAriaLabel ?? dataTableMessages?.selectRow ?? 'Select row';
|
|
@@ -126,10 +129,13 @@ const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTab
|
|
|
126
129
|
const sortDescendingIcon = icon('sortDescending', '▼');
|
|
127
130
|
const columns = useColumns(children);
|
|
128
131
|
const selectionGroupName = useId();
|
|
129
|
-
const [filters, setFilters] =
|
|
130
|
-
const [globalFilter, setGlobalFilter] =
|
|
131
|
-
const [sort, setSort] =
|
|
132
|
+
const [filters, setFilters] = useControllableState(filtersProp, defaultFilters ?? {}, onFilter);
|
|
133
|
+
const [globalFilter, setGlobalFilter] = useControllableState(globalFilterProp, '', onGlobalFilterChange);
|
|
134
|
+
const [sort, setSort] = useControllableState(sortProp, null, onSortChange);
|
|
132
135
|
const filteredRows = useMemo(() => {
|
|
136
|
+
if (rowProcessing === DataTableRowProcessing.None) {
|
|
137
|
+
return data.map((row, loadedIndex) => ({ row, loadedIndex }));
|
|
138
|
+
}
|
|
133
139
|
const term = globalFilter.trim().toLocaleLowerCase();
|
|
134
140
|
const rows = data
|
|
135
141
|
.map((row, loadedIndex) => ({ row, loadedIndex }))
|
|
@@ -150,7 +156,7 @@ const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTab
|
|
|
150
156
|
const comparison = compareValues(valueAtPath(left.row, sort.field), valueAtPath(right.row, sort.field));
|
|
151
157
|
return sort.direction === 'ascending' ? comparison : -comparison;
|
|
152
158
|
});
|
|
153
|
-
}, [data, filters, globalFilter, globalFilterFields, sort]);
|
|
159
|
+
}, [data, filters, globalFilter, globalFilterFields, sort, rowProcessing]);
|
|
154
160
|
const updateFilter = (field, constraint) => {
|
|
155
161
|
const next = { ...filters };
|
|
156
162
|
if (constraint)
|
|
@@ -158,7 +164,6 @@ const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTab
|
|
|
158
164
|
else
|
|
159
165
|
delete next[field];
|
|
160
166
|
setFilters(next);
|
|
161
|
-
onFilter?.(next);
|
|
162
167
|
};
|
|
163
168
|
const activateRow = (row, index, originalEvent) => {
|
|
164
169
|
onRowClick?.({ data: row, index });
|
|
@@ -258,16 +263,16 @@ const DataTableCore = ({ data, children, dataKey, emptyMessage, status = DataTab
|
|
|
258
263
|
...column.props.headerStyle,
|
|
259
264
|
}, className: classNames('cratis-datatable__header-cell', pt?.headerCell?.className, column.props.headerClassName), "data-cratis-part": 'header-cell', "data-selected": Boolean(ariaSort) || undefined, children: jsxs("div", { className: 'cratis-datatable-header-cell', "data-cratis-part": 'header-content', "data-selected": Boolean(ariaSort) || undefined, children: [column.props.selectionMode ===
|
|
260
265
|
'multiple' ? (jsx("input", { type: 'checkbox', "aria-label": resolvedSelectAllAriaLabel, "data-cratis-part": 'select-all', checked: allFilteredRowsSelected, ref: selectAllRef, onChange: toggleSelectAll })) : (column.props.selectionMode && (jsx("span", { className: 'cratis-datatable__sr-only', children: resolvedSelectionAriaLabel }))), column.props.sortable &&
|
|
261
|
-
column.props.field ? (jsxs("button", { type: 'button', className: 'cratis-datatable__sort', "data-cratis-part": 'sort', "data-pressed": Boolean(ariaSort) || undefined, onClick: () => setSort(
|
|
266
|
+
column.props.field ? (jsxs("button", { type: 'button', className: 'cratis-datatable__sort', "data-cratis-part": 'sort', "data-pressed": Boolean(ariaSort) || undefined, onClick: () => setSort({
|
|
262
267
|
field: column.props
|
|
263
268
|
.field,
|
|
264
|
-
direction:
|
|
269
|
+
direction: sort?.field ===
|
|
265
270
|
column.props.field &&
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
?
|
|
269
|
-
:
|
|
270
|
-
})
|
|
271
|
+
sort?.direction ===
|
|
272
|
+
DataTableSortDirection.Ascending
|
|
273
|
+
? DataTableSortDirection.Descending
|
|
274
|
+
: DataTableSortDirection.Ascending,
|
|
275
|
+
}), children: [jsx("span", { children: column.props.header }), ariaSort && (jsx("span", { "aria-hidden": 'true', children: ariaSort === 'ascending'
|
|
271
276
|
? sortAscendingIcon
|
|
272
277
|
: sortDescendingIcon }))] })) : (column.props.header), column.props.filter && field && (jsx(ColumnFilterMenu, { field: field, dataType: column.props.dataType, placeholder: column.props.filterPlaceholder, showMatchModes: column.props.showFilterMatchModes, filterElement: column.props.filterElement, filterOptions: column.props.filterOptions, labels: column.props.filterLabels, pt: column.props.filterPt, constraint: firstConstraint(filters[field]), onApply: (constraint) => updateFilter(field, constraint), onClear: () => updateFilter(field, undefined) }))] }) }, index));
|
|
273
278
|
}) }) }), jsx("tbody", { ...pt?.body, className: classNames('cratis-datatable__body', pt?.body?.className), "data-cratis-part": 'body', children: status === DataTableStatus.Failed ||
|