@tensor_1/react 2.47.0 → 2.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +470 -1
  2. package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
  3. package/dist/announce.d.ts +10 -0
  4. package/dist/announce.js +30 -0
  5. package/dist/chart-analytic.cjs +33 -25
  6. package/dist/chart-preset.cjs +23 -15
  7. package/dist/chart.cjs +23 -15
  8. package/dist/combobox-model.d.ts +10 -1
  9. package/dist/combobox-model.js +15 -0
  10. package/dist/command-palette-model.d.ts +44 -0
  11. package/dist/command-palette-model.js +36 -0
  12. package/dist/components/AccountMenu.d.ts +44 -0
  13. package/dist/components/AccountMenu.js +43 -0
  14. package/dist/components/AppShell.d.ts +45 -2
  15. package/dist/components/AppShell.js +116 -5
  16. package/dist/components/AuditLog.d.ts +128 -0
  17. package/dist/components/AuditLog.js +196 -0
  18. package/dist/components/BrandProfiles.js +4 -3
  19. package/dist/components/Breadcrumbs.d.ts +9 -2
  20. package/dist/components/Breadcrumbs.js +3 -2
  21. package/dist/components/Button.d.ts +12 -5
  22. package/dist/components/Button.js +7 -3
  23. package/dist/components/Card.d.ts +18 -1
  24. package/dist/components/Card.js +5 -1
  25. package/dist/components/ChangeHighlight.d.ts +30 -0
  26. package/dist/components/ChangeHighlight.js +21 -0
  27. package/dist/components/ChartCore.js +2 -1
  28. package/dist/components/Checkbox.d.ts +27 -1
  29. package/dist/components/Checkbox.js +31 -2
  30. package/dist/components/CodeDisplay.d.ts +65 -0
  31. package/dist/components/CodeDisplay.js +124 -0
  32. package/dist/components/Combobox.d.ts +27 -6
  33. package/dist/components/Combobox.js +195 -58
  34. package/dist/components/CommandPalette.d.ts +36 -1
  35. package/dist/components/CommandPalette.js +254 -2
  36. package/dist/components/ContactCard.d.ts +66 -0
  37. package/dist/components/ContactCard.js +74 -0
  38. package/dist/components/Count.d.ts +24 -0
  39. package/dist/components/Count.js +32 -0
  40. package/dist/components/DataWorkspace.d.ts +167 -0
  41. package/dist/components/DataWorkspace.js +383 -0
  42. package/dist/components/DateFieldParts.d.ts +2 -1
  43. package/dist/components/DateFieldParts.js +7 -0
  44. package/dist/components/DatePicker.d.ts +9 -2
  45. package/dist/components/DatePicker.js +67 -28
  46. package/dist/components/DateRangePicker.d.ts +12 -2
  47. package/dist/components/DateRangePicker.js +13 -12
  48. package/dist/components/DetailPage.d.ts +7 -1
  49. package/dist/components/DetailPage.js +2 -1
  50. package/dist/components/Dialogs.d.ts +71 -10
  51. package/dist/components/Dialogs.js +130 -30
  52. package/dist/components/DiffViewer.d.ts +23 -3
  53. package/dist/components/DiffViewer.js +26 -12
  54. package/dist/components/DiscardPrompt.js +16 -0
  55. package/dist/components/DisplayPreferences.d.ts +83 -0
  56. package/dist/components/DisplayPreferences.js +185 -0
  57. package/dist/components/EditorialHome.d.ts +23 -3
  58. package/dist/components/EditorialHome.js +16 -11
  59. package/dist/components/EntityPicker.d.ts +20 -3
  60. package/dist/components/EntityPicker.js +32 -13
  61. package/dist/components/FilterEditor.d.ts +18 -4
  62. package/dist/components/FilterEditor.js +141 -19
  63. package/dist/components/InfoTip.js +11 -12
  64. package/dist/components/InlineEdit.d.ts +87 -20
  65. package/dist/components/InlineEdit.js +197 -54
  66. package/dist/components/Input.d.ts +12 -2
  67. package/dist/components/Input.js +5 -3
  68. package/dist/components/Kbd.d.ts +6 -1
  69. package/dist/components/Kbd.js +6 -6
  70. package/dist/components/Lightbox.d.ts +41 -5
  71. package/dist/components/Lightbox.js +95 -9
  72. package/dist/components/MatchReview.d.ts +40 -1
  73. package/dist/components/MatchReview.js +130 -4
  74. package/dist/components/MetricInput.js +3 -2
  75. package/dist/components/Modal.d.ts +2 -1
  76. package/dist/components/Modal.js +13 -4
  77. package/dist/components/NavFavourites.d.ts +5 -0
  78. package/dist/components/NavFavourites.js +7 -7
  79. package/dist/components/OtpInput.d.ts +33 -0
  80. package/dist/components/OtpInput.js +123 -0
  81. package/dist/components/PageHeader.d.ts +7 -1
  82. package/dist/components/PageHeader.js +2 -2
  83. package/dist/components/Pagination.js +6 -5
  84. package/dist/components/PasswordInput.d.ts +34 -0
  85. package/dist/components/PasswordInput.js +101 -0
  86. package/dist/components/Peek.js +3 -3
  87. package/dist/components/Popover.js +2 -0
  88. package/dist/components/PrintLayout.d.ts +63 -0
  89. package/dist/components/PrintLayout.js +114 -0
  90. package/dist/components/QrCode.d.ts +47 -0
  91. package/dist/components/QrCode.js +55 -0
  92. package/dist/components/QrScanner.d.ts +95 -0
  93. package/dist/components/QrScanner.js +266 -0
  94. package/dist/components/RelationshipGraph.d.ts +32 -1
  95. package/dist/components/RelationshipGraph.js +18 -5
  96. package/dist/components/RelationshipGraphLayered.d.ts +1 -1
  97. package/dist/components/RelationshipGraphLayered.js +190 -115
  98. package/dist/components/RelationshipGraphList.js +33 -6
  99. package/dist/components/RuleBuilder.js +39 -7
  100. package/dist/components/SchedulingAgenda.d.ts +3 -1
  101. package/dist/components/SchedulingCalendar.d.ts +3 -1
  102. package/dist/components/SchedulingCalendar.js +43 -4
  103. package/dist/components/SchedulingResourceDay.d.ts +57 -0
  104. package/dist/components/SchedulingResourceDay.js +287 -0
  105. package/dist/components/SchedulingTimeGrid.d.ts +3 -1
  106. package/dist/components/SchedulingTimeline.d.ts +3 -1
  107. package/dist/components/SearchSuggest.d.ts +23 -3
  108. package/dist/components/SearchSuggest.js +48 -17
  109. package/dist/components/Segmented.d.ts +39 -4
  110. package/dist/components/Segmented.js +31 -3
  111. package/dist/components/Select.d.ts +3 -2
  112. package/dist/components/Select.js +1 -1
  113. package/dist/components/ShortcutHint.d.ts +11 -10
  114. package/dist/components/ShortcutHint.js +44 -38
  115. package/dist/components/Sidebar.d.ts +36 -4
  116. package/dist/components/Sidebar.js +37 -12
  117. package/dist/components/SortableList.d.ts +45 -0
  118. package/dist/components/SortableList.js +134 -0
  119. package/dist/components/Stat.d.ts +28 -3
  120. package/dist/components/Stat.js +13 -3
  121. package/dist/components/StatusPill.d.ts +14 -3
  122. package/dist/components/StatusPill.js +11 -3
  123. package/dist/components/Steps.js +2 -1
  124. package/dist/components/Table.d.ts +9 -2
  125. package/dist/components/Table.js +4 -2
  126. package/dist/components/TableControls.js +18 -58
  127. package/dist/components/TableOverflowProbe.d.ts +12 -0
  128. package/dist/components/TableOverflowProbe.js +27 -0
  129. package/dist/components/Tabs.d.ts +2 -1
  130. package/dist/components/Tabs.js +1 -0
  131. package/dist/components/TagInput.d.ts +67 -0
  132. package/dist/components/TagInput.js +342 -0
  133. package/dist/components/Textarea.d.ts +5 -0
  134. package/dist/components/Textarea.js +2 -2
  135. package/dist/components/TimePicker.d.ts +80 -0
  136. package/dist/components/TimePicker.js +347 -0
  137. package/dist/components/Toast.js +3 -2
  138. package/dist/components/Tooltip.d.ts +8 -4
  139. package/dist/components/Tooltip.js +24 -21
  140. package/dist/components/Tree.d.ts +8 -0
  141. package/dist/components/Tree.js +11 -5
  142. package/dist/display-preferences-model.d.ts +53 -0
  143. package/dist/display-preferences-model.js +64 -0
  144. package/dist/emoji.cjs +28 -35
  145. package/dist/filter-model.d.ts +59 -3
  146. package/dist/filter-model.js +67 -2
  147. package/dist/hooks/useChangeHighlight.d.ts +33 -0
  148. package/dist/hooks/useChangeHighlight.js +44 -0
  149. package/dist/hooks/useDialog.d.ts +5 -0
  150. package/dist/hooks/useDialog.js +3 -2
  151. package/dist/hooks/useOptimisticValue.d.ts +51 -0
  152. package/dist/hooks/useOptimisticValue.js +61 -0
  153. package/dist/hooks/useReducedMotion.d.ts +4 -1
  154. package/dist/hooks/useReducedMotion.js +7 -1
  155. package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
  156. package/dist/hooks/useResolvedFilterLabels.js +34 -0
  157. package/dist/hooks/useVirtualRows.d.ts +21 -2
  158. package/dist/hooks/useVirtualRows.js +30 -3
  159. package/dist/icons/Icon.d.ts +1 -1
  160. package/dist/index.cjs +18644 -13210
  161. package/dist/index.d.cts +3003 -699
  162. package/dist/index.d.ts +42 -16
  163. package/dist/index.js +139 -7
  164. package/dist/labels-context.d.ts +90 -3
  165. package/dist/overlay-stack.d.ts +6 -0
  166. package/dist/overlay-stack.js +13 -0
  167. package/dist/qr-model.d.ts +65 -0
  168. package/dist/qr-model.js +323 -0
  169. package/dist/relationship-graph-model.d.ts +78 -3
  170. package/dist/relationship-graph-model.js +112 -5
  171. package/dist/reorder.d.ts +30 -0
  172. package/dist/reorder.js +74 -0
  173. package/dist/rich-text.cjs +4 -2
  174. package/dist/scheduling-resource-model.d.ts +76 -0
  175. package/dist/scheduling-resource-model.js +74 -0
  176. package/dist/search-suggest-model.js +3 -1
  177. package/dist/shell-context.d.ts +11 -0
  178. package/dist/shell-context.js +7 -0
  179. package/dist/time-field-model.d.ts +46 -0
  180. package/dist/time-field-model.js +152 -0
  181. package/dist/toast-store.d.ts +17 -1
  182. package/dist/toast-store.js +23 -7
  183. package/package.json +2 -1
@@ -73,7 +73,7 @@ var import_components = require("echarts/components");
73
73
  var import_renderers = require("echarts/renderers");
74
74
 
75
75
  // src/components/ChartCore.tsx
76
- var import_react = require("react");
76
+ var import_react2 = require("react");
77
77
 
78
78
  // src/cx.ts
79
79
  function cx(...args) {
@@ -177,6 +177,14 @@ function mergeChartTheme(theme, option) {
177
177
  return merged;
178
178
  }
179
179
 
180
+ // src/hooks/useReducedMotion.ts
181
+ var import_react = require("react");
182
+ var QUERY = "(prefers-reduced-motion: reduce)";
183
+ function prefersReducedMotion() {
184
+ if (typeof document !== "undefined" && document.documentElement.getAttribute("data-motion") === "reduce") return true;
185
+ return typeof matchMedia !== "undefined" && matchMedia(QUERY).matches;
186
+ }
187
+
180
188
  // src/components/ChartCore.tsx
181
189
  var import_jsx_runtime = require("react/jsx-runtime");
182
190
  function readToken(name) {
@@ -191,7 +199,7 @@ function themed(option, theme, element) {
191
199
  return theme === "none" ? resolved : mergeChartTheme(uixChartTheme(element), resolved);
192
200
  }
193
201
  function motionSafe(option) {
194
- if (typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches) {
202
+ if (prefersReducedMotion()) {
195
203
  return { ...option, animation: false };
196
204
  }
197
205
  return option;
@@ -225,23 +233,23 @@ function ChartCore({
225
233
  tables
226
234
  }) {
227
235
  const labels = { ...DEFAULT_CHART_LABELS, ...labelOverrides };
228
- const containerRef = (0, import_react.useRef)(null);
229
- const chartRef = (0, import_react.useRef)(null);
230
- const appliedOptionRef = (0, import_react.useRef)(null);
231
- const onEventsRef = (0, import_react.useRef)(onEvents);
236
+ const containerRef = (0, import_react2.useRef)(null);
237
+ const chartRef = (0, import_react2.useRef)(null);
238
+ const appliedOptionRef = (0, import_react2.useRef)(null);
239
+ const onEventsRef = (0, import_react2.useRef)(onEvents);
232
240
  onEventsRef.current = onEvents;
233
- const latestOptionRef = (0, import_react.useRef)(option);
234
- const onReadyRef = (0, import_react.useRef)(onReady);
235
- const tableId = (0, import_react.useId)();
241
+ const latestOptionRef = (0, import_react2.useRef)(option);
242
+ const onReadyRef = (0, import_react2.useRef)(onReady);
243
+ const tableId = (0, import_react2.useId)();
236
244
  const hasEmpty = empty != null;
237
245
  const hasTextAlternative = Boolean(ariaLabel || title || tableData?.length || tables?.length);
238
- const hasTextAlternativeRef = (0, import_react.useRef)(hasTextAlternative);
239
- const themeRef = (0, import_react.useRef)(theme);
246
+ const hasTextAlternativeRef = (0, import_react2.useRef)(hasTextAlternative);
247
+ const themeRef = (0, import_react2.useRef)(theme);
240
248
  latestOptionRef.current = option;
241
249
  themeRef.current = theme;
242
250
  onReadyRef.current = onReady;
243
251
  hasTextAlternativeRef.current = hasTextAlternative;
244
- (0, import_react.useEffect)(() => {
252
+ (0, import_react2.useEffect)(() => {
245
253
  const element = containerRef.current;
246
254
  if (!element) return;
247
255
  const chart = engine.init(element, null, { renderer: "svg" });
@@ -287,7 +295,7 @@ function ChartCore({
287
295
  };
288
296
  }, [engine, hasEmpty]);
289
297
  const eventNames = Object.keys(onEvents ?? {}).sort().join("|");
290
- (0, import_react.useEffect)(() => {
298
+ (0, import_react2.useEffect)(() => {
291
299
  const chart = chartRef.current;
292
300
  if (!chart || !eventNames) return;
293
301
  const bound = eventNames.split("|").map((name) => {
@@ -300,7 +308,7 @@ function ChartCore({
300
308
  for (const [name, handler] of bound) chart.off(name, handler);
301
309
  };
302
310
  }, [engine, hasEmpty, eventNames]);
303
- (0, import_react.useEffect)(() => {
311
+ (0, import_react2.useEffect)(() => {
304
312
  const chart = chartRef.current;
305
313
  if (!chart || !group) return;
306
314
  chart.group = group;
@@ -309,7 +317,7 @@ function ChartCore({
309
317
  if (!chart.isDisposed()) chart.group = "";
310
318
  };
311
319
  }, [engine, hasEmpty, group]);
312
- (0, import_react.useEffect)(() => {
320
+ (0, import_react2.useEffect)(() => {
313
321
  const chart = chartRef.current;
314
322
  const element = containerRef.current;
315
323
  if (!chart || !element || appliedOptionRef.current === option) return;
@@ -373,7 +381,7 @@ function ChartLegendItem({ label, color, swatch = "block", className, style, ...
373
381
  }
374
382
 
375
383
  // src/components/ChartPanels.tsx
376
- var import_react2 = require("react");
384
+ var import_react3 = require("react");
377
385
 
378
386
  // src/chart-analytic-model.ts
379
387
  var DEFAULT_ANALYTIC_LABELS = {
@@ -1195,10 +1203,10 @@ function ChartPanelsCore({
1195
1203
  onEventClick,
1196
1204
  legend
1197
1205
  }) {
1198
- const spec = (0, import_react2.useMemo)(() => ({ x, panels, events, partialLast, zoom }), [x, panels, events, partialLast, zoom]);
1199
- const layout = (0, import_react2.useMemo)(() => chartPanelsModel(spec, CSS_VAR_TOKENS, labels), [spec, labels]);
1200
- const option = (0, import_react2.useMemo)(() => (tokens) => chartPanelsModel(spec, tokens, labels).option, [spec, labels]);
1201
- const onEvents = (0, import_react2.useMemo)(() => ({
1206
+ const spec = (0, import_react3.useMemo)(() => ({ x, panels, events, partialLast, zoom }), [x, panels, events, partialLast, zoom]);
1207
+ const layout = (0, import_react3.useMemo)(() => chartPanelsModel(spec, CSS_VAR_TOKENS, labels), [spec, labels]);
1208
+ const option = (0, import_react3.useMemo)(() => (tokens) => chartPanelsModel(spec, tokens, labels).option, [spec, labels]);
1209
+ const onEvents = (0, import_react3.useMemo)(() => ({
1202
1210
  click: (raw) => {
1203
1211
  const params = raw;
1204
1212
  const value = Array.isArray(params.value) ? params.value : [];
@@ -1266,14 +1274,14 @@ function CorrelationScatterCore({
1266
1274
  height = 280,
1267
1275
  onPointClick
1268
1276
  }) {
1269
- const spec = (0, import_react2.useMemo)(
1277
+ const spec = (0, import_react3.useMemo)(
1270
1278
  () => ({ points, xLabel, yLabel, trend, percentiles, thresholds, breakpoint, minPoints }),
1271
1279
  [points, xLabel, yLabel, trend, percentiles, thresholds, breakpoint, minPoints]
1272
1280
  );
1273
- const layout = (0, import_react2.useMemo)(() => correlationScatterModel(spec, CSS_VAR_TOKENS, labels), [spec, labels]);
1274
- const option = (0, import_react2.useMemo)(() => (tokens) => correlationScatterModel(spec, tokens, labels).option, [spec, labels]);
1275
- const usable = (0, import_react2.useMemo)(() => spec.points.filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y)), [spec.points]);
1276
- const onEvents = (0, import_react2.useMemo)(() => ({
1281
+ const layout = (0, import_react3.useMemo)(() => correlationScatterModel(spec, CSS_VAR_TOKENS, labels), [spec, labels]);
1282
+ const option = (0, import_react3.useMemo)(() => (tokens) => correlationScatterModel(spec, tokens, labels).option, [spec, labels]);
1283
+ const usable = (0, import_react3.useMemo)(() => spec.points.filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y)), [spec.points]);
1284
+ const onEvents = (0, import_react3.useMemo)(() => ({
1277
1285
  click: (raw) => {
1278
1286
  const params = raw;
1279
1287
  if (params.seriesId !== layout.hitSeriesId || !Array.isArray(params.value)) return;
@@ -49,7 +49,7 @@ var import_components = require("echarts/components");
49
49
  var import_renderers = require("echarts/renderers");
50
50
 
51
51
  // src/components/ChartCore.tsx
52
- var import_react = require("react");
52
+ var import_react2 = require("react");
53
53
 
54
54
  // src/cx.ts
55
55
  function cx(...args) {
@@ -153,6 +153,14 @@ function mergeChartTheme(theme, option) {
153
153
  return merged;
154
154
  }
155
155
 
156
+ // src/hooks/useReducedMotion.ts
157
+ var import_react = require("react");
158
+ var QUERY = "(prefers-reduced-motion: reduce)";
159
+ function prefersReducedMotion() {
160
+ if (typeof document !== "undefined" && document.documentElement.getAttribute("data-motion") === "reduce") return true;
161
+ return typeof matchMedia !== "undefined" && matchMedia(QUERY).matches;
162
+ }
163
+
156
164
  // src/components/ChartCore.tsx
157
165
  var import_jsx_runtime = require("react/jsx-runtime");
158
166
  function readToken(name) {
@@ -167,7 +175,7 @@ function themed(option, theme, element) {
167
175
  return theme === "none" ? resolved : mergeChartTheme(uixChartTheme(element), resolved);
168
176
  }
169
177
  function motionSafe(option) {
170
- if (typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches) {
178
+ if (prefersReducedMotion()) {
171
179
  return { ...option, animation: false };
172
180
  }
173
181
  return option;
@@ -201,23 +209,23 @@ function ChartCore({
201
209
  tables
202
210
  }) {
203
211
  const labels = { ...DEFAULT_CHART_LABELS, ...labelOverrides };
204
- const containerRef = (0, import_react.useRef)(null);
205
- const chartRef = (0, import_react.useRef)(null);
206
- const appliedOptionRef = (0, import_react.useRef)(null);
207
- const onEventsRef = (0, import_react.useRef)(onEvents);
212
+ const containerRef = (0, import_react2.useRef)(null);
213
+ const chartRef = (0, import_react2.useRef)(null);
214
+ const appliedOptionRef = (0, import_react2.useRef)(null);
215
+ const onEventsRef = (0, import_react2.useRef)(onEvents);
208
216
  onEventsRef.current = onEvents;
209
- const latestOptionRef = (0, import_react.useRef)(option);
210
- const onReadyRef = (0, import_react.useRef)(onReady);
211
- const tableId = (0, import_react.useId)();
217
+ const latestOptionRef = (0, import_react2.useRef)(option);
218
+ const onReadyRef = (0, import_react2.useRef)(onReady);
219
+ const tableId = (0, import_react2.useId)();
212
220
  const hasEmpty = empty != null;
213
221
  const hasTextAlternative = Boolean(ariaLabel || title || tableData?.length || tables?.length);
214
- const hasTextAlternativeRef = (0, import_react.useRef)(hasTextAlternative);
215
- const themeRef = (0, import_react.useRef)(theme);
222
+ const hasTextAlternativeRef = (0, import_react2.useRef)(hasTextAlternative);
223
+ const themeRef = (0, import_react2.useRef)(theme);
216
224
  latestOptionRef.current = option;
217
225
  themeRef.current = theme;
218
226
  onReadyRef.current = onReady;
219
227
  hasTextAlternativeRef.current = hasTextAlternative;
220
- (0, import_react.useEffect)(() => {
228
+ (0, import_react2.useEffect)(() => {
221
229
  const element = containerRef.current;
222
230
  if (!element) return;
223
231
  const chart = engine.init(element, null, { renderer: "svg" });
@@ -263,7 +271,7 @@ function ChartCore({
263
271
  };
264
272
  }, [engine, hasEmpty]);
265
273
  const eventNames = Object.keys(onEvents ?? {}).sort().join("|");
266
- (0, import_react.useEffect)(() => {
274
+ (0, import_react2.useEffect)(() => {
267
275
  const chart = chartRef.current;
268
276
  if (!chart || !eventNames) return;
269
277
  const bound = eventNames.split("|").map((name) => {
@@ -276,7 +284,7 @@ function ChartCore({
276
284
  for (const [name, handler] of bound) chart.off(name, handler);
277
285
  };
278
286
  }, [engine, hasEmpty, eventNames]);
279
- (0, import_react.useEffect)(() => {
287
+ (0, import_react2.useEffect)(() => {
280
288
  const chart = chartRef.current;
281
289
  if (!chart || !group) return;
282
290
  chart.group = group;
@@ -285,7 +293,7 @@ function ChartCore({
285
293
  if (!chart.isDisposed()) chart.group = "";
286
294
  };
287
295
  }, [engine, hasEmpty, group]);
288
- (0, import_react.useEffect)(() => {
296
+ (0, import_react2.useEffect)(() => {
289
297
  const chart = chartRef.current;
290
298
  const element = containerRef.current;
291
299
  if (!chart || !element || appliedOptionRef.current === option) return;
package/dist/chart.cjs CHANGED
@@ -47,7 +47,7 @@ module.exports = __toCommonJS(chart_exports);
47
47
  var echarts = __toESM(require("echarts"), 1);
48
48
 
49
49
  // src/components/ChartCore.tsx
50
- var import_react = require("react");
50
+ var import_react2 = require("react");
51
51
 
52
52
  // src/cx.ts
53
53
  function cx(...args) {
@@ -151,6 +151,14 @@ function mergeChartTheme(theme, option) {
151
151
  return merged;
152
152
  }
153
153
 
154
+ // src/hooks/useReducedMotion.ts
155
+ var import_react = require("react");
156
+ var QUERY = "(prefers-reduced-motion: reduce)";
157
+ function prefersReducedMotion() {
158
+ if (typeof document !== "undefined" && document.documentElement.getAttribute("data-motion") === "reduce") return true;
159
+ return typeof matchMedia !== "undefined" && matchMedia(QUERY).matches;
160
+ }
161
+
154
162
  // src/components/ChartCore.tsx
155
163
  var import_jsx_runtime = require("react/jsx-runtime");
156
164
  function readToken(name) {
@@ -165,7 +173,7 @@ function themed(option, theme, element) {
165
173
  return theme === "none" ? resolved : mergeChartTheme(uixChartTheme(element), resolved);
166
174
  }
167
175
  function motionSafe(option) {
168
- if (typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches) {
176
+ if (prefersReducedMotion()) {
169
177
  return { ...option, animation: false };
170
178
  }
171
179
  return option;
@@ -199,23 +207,23 @@ function ChartCore({
199
207
  tables
200
208
  }) {
201
209
  const labels = { ...DEFAULT_CHART_LABELS, ...labelOverrides };
202
- const containerRef = (0, import_react.useRef)(null);
203
- const chartRef = (0, import_react.useRef)(null);
204
- const appliedOptionRef = (0, import_react.useRef)(null);
205
- const onEventsRef = (0, import_react.useRef)(onEvents);
210
+ const containerRef = (0, import_react2.useRef)(null);
211
+ const chartRef = (0, import_react2.useRef)(null);
212
+ const appliedOptionRef = (0, import_react2.useRef)(null);
213
+ const onEventsRef = (0, import_react2.useRef)(onEvents);
206
214
  onEventsRef.current = onEvents;
207
- const latestOptionRef = (0, import_react.useRef)(option);
208
- const onReadyRef = (0, import_react.useRef)(onReady);
209
- const tableId = (0, import_react.useId)();
215
+ const latestOptionRef = (0, import_react2.useRef)(option);
216
+ const onReadyRef = (0, import_react2.useRef)(onReady);
217
+ const tableId = (0, import_react2.useId)();
210
218
  const hasEmpty = empty != null;
211
219
  const hasTextAlternative = Boolean(ariaLabel || title || tableData?.length || tables?.length);
212
- const hasTextAlternativeRef = (0, import_react.useRef)(hasTextAlternative);
213
- const themeRef = (0, import_react.useRef)(theme);
220
+ const hasTextAlternativeRef = (0, import_react2.useRef)(hasTextAlternative);
221
+ const themeRef = (0, import_react2.useRef)(theme);
214
222
  latestOptionRef.current = option;
215
223
  themeRef.current = theme;
216
224
  onReadyRef.current = onReady;
217
225
  hasTextAlternativeRef.current = hasTextAlternative;
218
- (0, import_react.useEffect)(() => {
226
+ (0, import_react2.useEffect)(() => {
219
227
  const element = containerRef.current;
220
228
  if (!element) return;
221
229
  const chart = engine.init(element, null, { renderer: "svg" });
@@ -261,7 +269,7 @@ function ChartCore({
261
269
  };
262
270
  }, [engine, hasEmpty]);
263
271
  const eventNames = Object.keys(onEvents ?? {}).sort().join("|");
264
- (0, import_react.useEffect)(() => {
272
+ (0, import_react2.useEffect)(() => {
265
273
  const chart = chartRef.current;
266
274
  if (!chart || !eventNames) return;
267
275
  const bound = eventNames.split("|").map((name) => {
@@ -274,7 +282,7 @@ function ChartCore({
274
282
  for (const [name, handler] of bound) chart.off(name, handler);
275
283
  };
276
284
  }, [engine, hasEmpty, eventNames]);
277
- (0, import_react.useEffect)(() => {
285
+ (0, import_react2.useEffect)(() => {
278
286
  const chart = chartRef.current;
279
287
  if (!chart || !group) return;
280
288
  chart.group = group;
@@ -283,7 +291,7 @@ function ChartCore({
283
291
  if (!chart.isDisposed()) chart.group = "";
284
292
  };
285
293
  }, [engine, hasEmpty, group]);
286
- (0, import_react.useEffect)(() => {
294
+ (0, import_react2.useEffect)(() => {
287
295
  const chart = chartRef.current;
288
296
  const element = containerRef.current;
289
297
  if (!chart || !element || appliedOptionRef.current === option) return;
@@ -4,6 +4,15 @@ interface ComboboxOption {
4
4
  keywords?: readonly string[];
5
5
  disabled?: boolean;
6
6
  }
7
+ /** A titled group of options (HAR-1588). */
8
+ interface ComboboxGroup {
9
+ label: string;
10
+ options: readonly ComboboxOption[];
11
+ /** Disables every option in the group. */
12
+ disabled?: boolean;
13
+ }
7
14
  declare function filterComboboxOptions(options: readonly ComboboxOption[], query: string): ComboboxOption[];
15
+ /** Options and groups that match `query` (label, value or keywords); a group stays when any of its options does. */
16
+ declare function filterComboboxItems(items: readonly (ComboboxOption | ComboboxGroup)[], query: string): (ComboboxOption | ComboboxGroup)[];
8
17
 
9
- export { type ComboboxOption, filterComboboxOptions };
18
+ export { type ComboboxGroup, type ComboboxOption, filterComboboxItems, filterComboboxOptions };
@@ -1,3 +1,4 @@
1
+ const isGroup = (item) => Array.isArray(item.options);
1
2
  function filterComboboxOptions(options, query) {
2
3
  const needle = query.trim().toLocaleLowerCase();
3
4
  if (!needle) return [...options];
@@ -5,6 +6,20 @@ function filterComboboxOptions(options, query) {
5
6
  (option) => [option.label, option.value, ...option.keywords ?? []].some((part) => part.toLocaleLowerCase().includes(needle))
6
7
  );
7
8
  }
9
+ function filterComboboxItems(items, query) {
10
+ if (!query.trim()) return [...items];
11
+ const out = [];
12
+ for (const item of items) {
13
+ if (isGroup(item)) {
14
+ const options = filterComboboxOptions(item.options, query);
15
+ if (options.length) out.push({ ...item, options });
16
+ } else if (filterComboboxOptions([item], query).length) {
17
+ out.push(item);
18
+ }
19
+ }
20
+ return out;
21
+ }
8
22
  export {
23
+ filterComboboxItems,
9
24
  filterComboboxOptions
10
25
  };
@@ -0,0 +1,44 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ /** One command of a `CommandPalette` in items mode. */
4
+ interface CommandPaletteItem {
5
+ /** Unique among the items; also the option's id suffix. */
6
+ id: string;
7
+ label: string;
8
+ /** Group heading the item is listed under. Items without one form a group without a heading. */
9
+ group?: string;
10
+ /** More words that find the item but are not shown: synonyms, an old name, a record number. */
11
+ keywords?: readonly string[];
12
+ /** A second line, e.g. where the command leads. Not searched. */
13
+ description?: string;
14
+ /** Leading icon (decorative). */
15
+ icon?: ReactNode;
16
+ /** Key names (`['Mod', 'K']`) shown at the end of the row and set as `aria-keyshortcuts`. */
17
+ shortcut?: readonly string[];
18
+ /** Runs when the item is chosen. */
19
+ onSelect?: () => void;
20
+ /** Where the item leads: `onNavigate(href)`, else the browser goes there. */
21
+ href?: string;
22
+ /** Shown but not choosable; skipped by the arrow keys. */
23
+ disabled?: boolean;
24
+ }
25
+ /** A group of found commands, in the order they are shown. */
26
+ interface CommandPaletteGroup {
27
+ /** The group heading; `undefined` for items without a group. */
28
+ label: string | undefined;
29
+ items: CommandPaletteItem[];
30
+ }
31
+ /**
32
+ * The commands `query` finds, best first (HAR-1378): a label that starts with the query, then
33
+ * labels where every word of the query starts a word, then labels that contain every word, then
34
+ * matches through `keywords`. Equal matches keep the order they were given in. An empty query
35
+ * finds every item, in order.
36
+ */
37
+ declare function filterCommandItems(items: readonly CommandPaletteItem[], query: string): CommandPaletteItem[];
38
+ /**
39
+ * `items` in groups, each group where its first item is, its items in their given order. With a
40
+ * ranked list (from `filterCommandItems`) the group of the best match comes first.
41
+ */
42
+ declare function groupCommandItems(items: readonly CommandPaletteItem[]): CommandPaletteGroup[];
43
+
44
+ export { type CommandPaletteGroup, type CommandPaletteItem, filterCommandItems, groupCommandItems };
@@ -0,0 +1,36 @@
1
+ import { foldForSearch } from "./search-suggest-model.js";
2
+ const words = (folded) => folded.split(/[\s\-_/.,:;()[\]'"›>·|]+/u).filter(Boolean);
3
+ function score(item, query, tokens) {
4
+ const label = foldForSearch(item.label).text;
5
+ if (label.startsWith(query)) return 0;
6
+ const labelWords = words(label);
7
+ if (tokens.every((t) => labelWords.some((w) => w.startsWith(t)))) return 1;
8
+ if (tokens.every((t) => label.includes(t))) return 2;
9
+ const keywords = (item.keywords ?? []).map((k) => foldForSearch(k).text);
10
+ if (tokens.every((t) => label.includes(t) || keywords.some((k) => k.includes(t)))) return 3;
11
+ return -1;
12
+ }
13
+ function filterCommandItems(items, query) {
14
+ const folded = foldForSearch(query.trim()).text;
15
+ if (!folded) return [...items];
16
+ const tokens = folded.split(/\s+/).filter(Boolean);
17
+ return items.map((item, index) => ({ item, index, rank: score(item, folded, tokens) })).filter((entry) => entry.rank >= 0).sort((a, b) => a.rank - b.rank || a.index - b.index).map((entry) => entry.item);
18
+ }
19
+ function groupCommandItems(items) {
20
+ const groups = [];
21
+ const byLabel = /* @__PURE__ */ new Map();
22
+ for (const item of items) {
23
+ let group = byLabel.get(item.group);
24
+ if (!group) {
25
+ group = { label: item.group, items: [] };
26
+ byLabel.set(item.group, group);
27
+ groups.push(group);
28
+ }
29
+ group.items.push(item);
30
+ }
31
+ return groups;
32
+ }
33
+ export {
34
+ filterCommandItems,
35
+ groupCommandItems
36
+ };
@@ -0,0 +1,44 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { AvatarPresence } from './Avatar.js';
4
+ import { Placement } from '../overlay-position.js';
5
+
6
+ interface AccountMenuUser {
7
+ /** The person's name, shown on the trigger and used for the avatar's initials. */
8
+ name: string;
9
+ /** A second line: an email, a role, a branch. */
10
+ sub?: ReactNode;
11
+ /** A photo URL, or your own avatar content. Without it the avatar shows the initials. */
12
+ avatar?: string | ReactNode;
13
+ /** A presence dot on the avatar (`online`, `busy`, `away`, `offline`). */
14
+ status?: AvatarPresence;
15
+ }
16
+ interface AccountMenuLabels {
17
+ /** The menu's name (`aria-label` of the list). Default "Account". */
18
+ menu: string;
19
+ }
20
+ declare const DEFAULT_ACCOUNT_MENU_LABELS: AccountMenuLabels;
21
+ interface AccountMenuProps {
22
+ user: AccountMenuUser;
23
+ /**
24
+ * The menu's rows: `MenuItem` (profile, preferences, sign out with `tone="danger"`),
25
+ * `MenuRadioGroup` for a presence choice, `MenuSeparator`.
26
+ */
27
+ items?: ReactNode;
28
+ /**
29
+ * The rail form: the trigger shows the avatar only; the name stays the button's accessible
30
+ * name. Pair it with `Sidebar nav="rail"`.
31
+ */
32
+ collapsed?: boolean;
33
+ /** Where the menu opens. Default `top-start`: the trigger usually sits at the bottom of a sidebar. */
34
+ placement?: Placement;
35
+ labels?: Partial<AccountMenuLabels>;
36
+ /** The spoken presence words (after the name and second line), e.g. `{ online: 'Dostupan' }`. */
37
+ presenceLabels?: Partial<Record<AvatarPresence, string>>;
38
+ className?: string;
39
+ }
40
+ /** Up to two initials from a name, first and last word: "Ada Lovelace" → "AL", "Dževad Hodžić" → "DH". */
41
+ declare function accountInitials(name: string): string;
42
+ declare function AccountMenu({ user, items, collapsed, placement, labels: labelOverrides, presenceLabels, className }: AccountMenuProps): react.JSX.Element;
43
+
44
+ export { AccountMenu, type AccountMenuLabels, type AccountMenuProps, type AccountMenuUser, DEFAULT_ACCOUNT_MENU_LABELS, accountInitials };
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { cx } from "../cx.js";
4
+ import { useUixLabels } from "../labels-context.js";
5
+ import { ChevronsUpDownIcon } from "../icons/components.js";
6
+ import { Avatar, DEFAULT_PRESENCE_LABELS } from "./Avatar.js";
7
+ import { Menu } from "./Menu.js";
8
+ import { useInShellDrawer } from "../shell-context.js";
9
+ const DEFAULT_ACCOUNT_MENU_LABELS = { menu: "Account" };
10
+ function accountInitials(name) {
11
+ const words = name.trim().split(/\s+/).filter(Boolean);
12
+ if (words.length === 0) return "";
13
+ const first = [...words[0]][0] ?? "";
14
+ const last = words.length > 1 ? [...words[words.length - 1]][0] ?? "" : "";
15
+ return (first + last).toLocaleUpperCase();
16
+ }
17
+ const SILENT_PRESENCE = { online: "", busy: "", away: "", offline: "" };
18
+ function AccountMenu({ user, items, collapsed = false, placement = "top-start", labels: labelOverrides, presenceLabels, className }) {
19
+ const uixLabels = useUixLabels();
20
+ const labels = { ...DEFAULT_ACCOUNT_MENU_LABELS, ...uixLabels.accountMenu, ...labelOverrides };
21
+ const inDrawer = useInShellDrawer();
22
+ const rail = collapsed && !inDrawer;
23
+ const photo = typeof user.avatar === "string" ? user.avatar : void 0;
24
+ const custom = typeof user.avatar === "string" ? void 0 : user.avatar;
25
+ const trigger = /* @__PURE__ */ jsxs("button", { type: "button", className: cx("uix-account-menu", rail && "uix-account-menu--collapsed", className), children: [
26
+ /* @__PURE__ */ jsx(Avatar, { src: photo, alt: "", presence: user.status, presenceLabels: SILENT_PRESENCE, className: "uix-account-menu__avatar", children: custom ?? (photo ? null : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: accountInitials(user.name) })) }),
27
+ /* @__PURE__ */ jsxs("span", { className: "uix-account-menu__text", children: [
28
+ /* @__PURE__ */ jsx("span", { className: "uix-account-menu__name", children: user.name }),
29
+ user.sub != null && /* @__PURE__ */ jsx("span", { className: "uix-account-menu__sub", children: user.sub }),
30
+ user.status && /* @__PURE__ */ jsxs("span", { className: "uix-visually-hidden", children: [
31
+ ", ",
32
+ presenceLabels?.[user.status] ?? DEFAULT_PRESENCE_LABELS[user.status]
33
+ ] })
34
+ ] }),
35
+ /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "uix-account-menu__chevron" })
36
+ ] });
37
+ return /* @__PURE__ */ jsx(Menu, { trigger, label: labels.menu, placement, children: items });
38
+ }
39
+ export {
40
+ AccountMenu,
41
+ DEFAULT_ACCOUNT_MENU_LABELS,
42
+ accountInitials
43
+ };
@@ -3,8 +3,47 @@ import { HTMLAttributes, ReactNode } from 'react';
3
3
 
4
4
  type ShellNav = 'full' | 'rail' | 'hidden';
5
5
  interface AppShellProps extends HTMLAttributes<HTMLDivElement> {
6
- /** Sidebar width tier: 'full' (default) → 'rail' (icon only) → 'hidden' (0). */
6
+ /**
7
+ * `frame` (default) is the bordered, rounded box the docs show a shell in. `viewport` is an
8
+ * application's shell (HAR-1815): no frame, the full dynamic viewport height (`100dvh`), no fixed
9
+ * top-bar row (the sidebar and main both run the full height; a `topbar`, if given, sits at the
10
+ * top of the main column), main padding that widens on wide screens, and the phone nav tier by
11
+ * default (`phoneNav`), so below 40rem it is one column with the sidebar in a drawer.
12
+ */
13
+ layout?: 'frame' | 'viewport';
14
+ /**
15
+ * Sidebar width tier: 'full' (default) → 'rail' (icon only) → 'hidden' (0). Controlled when
16
+ * set; leave it out to let the shell keep the tier (`defaultNav`, `navHotkey`,
17
+ * `navTierStorageKey`).
18
+ */
7
19
  nav?: ShellNav;
20
+ /** The starting tier when `nav` is not controlled. Default `full`. */
21
+ defaultNav?: ShellNav;
22
+ /**
23
+ * Called with the tier the hotkey asks for, and once on mount with a remembered tier that
24
+ * differs from `defaultNav` (HAR-1371), so a `Sidebar nav` you render can follow. With `nav`
25
+ * controlled, set it from here.
26
+ */
27
+ onNavChange?: (nav: ShellNav) => void;
28
+ /**
29
+ * A key that switches the sidebar between `full` and `rail` (HAR-1371; MOTUS StaffShell), e.g.
30
+ * `"["`. It is ignored while typing in a field or with Ctrl/⌘/Alt held, and from `hidden` it
31
+ * goes to `full`. The switch is instant.
32
+ */
33
+ navHotkey?: string;
34
+ /**
35
+ * Remember the tier in `localStorage` under this key (HAR-1371), so a reload keeps the rail.
36
+ * Applied before the first paint on the client; the server renders `defaultNav`.
37
+ */
38
+ navTierStorageKey?: string;
39
+ /**
40
+ * The phone nav tier (HAR-1371): at 40rem and under, the sidebar column is hidden and a menu
41
+ * button (at the start of the topbar, or at the top of main) opens the sidebar in a start-side
42
+ * `Drawer`, shown full whatever the tier. Following a link in it closes the drawer. Default
43
+ * `drawer` with `layout="viewport"`, `none` with the frame; `none` keeps the sidebar column at
44
+ * every width.
45
+ */
46
+ phoneNav?: 'drawer' | 'none';
8
47
  /** Back-compat alias for nav="rail". Ignored when `nav` is set. */
9
48
  collapsed?: boolean;
10
49
  /**
@@ -26,7 +65,11 @@ interface AppShellProps extends HTMLAttributes<HTMLDivElement> {
26
65
  skipToContentLabel?: ReactNode;
27
66
  /** TENSOR RX-125 (UIX-04): translatable; English default. */
28
67
  exitFocusLabel?: ReactNode;
68
+ /** The phone menu button's name. Default: `UixLabelsProvider` `appShell.openNav`, then "Open navigation". */
69
+ openNavLabel?: string;
70
+ /** The navigation drawer's title. Default: `appShell.navigation`, then "Navigation". */
71
+ navigationLabel?: ReactNode;
29
72
  }
30
- declare function AppShell({ nav, collapsed, focus, onExitFocus, mainBleed, mainId, sidebar, topbar, children, skipToContentLabel: skipToContentLabelProp, exitFocusLabel: exitFocusLabelProp, className, ...props }: AppShellProps): react.JSX.Element;
73
+ declare function AppShell({ layout, nav, defaultNav, onNavChange, navHotkey, navTierStorageKey, phoneNav: phoneNavProp, collapsed, focus, onExitFocus, mainBleed, mainId, sidebar, topbar, children, skipToContentLabel: skipToContentLabelProp, exitFocusLabel: exitFocusLabelProp, openNavLabel: openNavLabelProp, navigationLabel: navigationLabelProp, className, ...props }: AppShellProps): react.JSX.Element;
31
74
 
32
75
  export { AppShell, type AppShellProps, type ShellNav };