@tensor_1/react 2.47.0 → 2.49.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 +540 -2
- package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
- package/dist/announce.d.ts +10 -0
- package/dist/announce.js +30 -0
- package/dist/chart-analytic.cjs +33 -25
- package/dist/chart-preset.cjs +23 -15
- package/dist/chart.cjs +23 -15
- package/dist/combobox-model.d.ts +10 -1
- package/dist/combobox-model.js +15 -0
- package/dist/command-palette-model.d.ts +44 -0
- package/dist/command-palette-model.js +36 -0
- package/dist/components/AccountMenu.d.ts +44 -0
- package/dist/components/AccountMenu.js +43 -0
- package/dist/components/AppShell.d.ts +45 -2
- package/dist/components/AppShell.js +116 -5
- package/dist/components/AuditLog.d.ts +128 -0
- package/dist/components/AuditLog.js +196 -0
- package/dist/components/BrandProfiles.js +4 -3
- package/dist/components/Breadcrumbs.d.ts +9 -2
- package/dist/components/Breadcrumbs.js +3 -2
- package/dist/components/Button.d.ts +12 -5
- package/dist/components/Button.js +7 -3
- package/dist/components/Card.d.ts +18 -1
- package/dist/components/Card.js +5 -1
- package/dist/components/ChangeHighlight.d.ts +30 -0
- package/dist/components/ChangeHighlight.js +21 -0
- package/dist/components/ChartCore.js +2 -1
- package/dist/components/Checkbox.d.ts +27 -1
- package/dist/components/Checkbox.js +31 -2
- package/dist/components/Chip.d.ts +7 -3
- package/dist/components/Chip.js +2 -2
- package/dist/components/CodeDisplay.d.ts +65 -0
- package/dist/components/CodeDisplay.js +124 -0
- package/dist/components/Combobox.d.ts +27 -6
- package/dist/components/Combobox.js +195 -58
- package/dist/components/CommandPalette.d.ts +36 -1
- package/dist/components/CommandPalette.js +254 -2
- package/dist/components/ContactCard.d.ts +66 -0
- package/dist/components/ContactCard.js +74 -0
- package/dist/components/Count.d.ts +24 -0
- package/dist/components/Count.js +32 -0
- package/dist/components/DashboardCanvas.js +14 -0
- package/dist/components/DataWorkspace.d.ts +167 -0
- package/dist/components/DataWorkspace.js +380 -0
- package/dist/components/DateFieldParts.d.ts +2 -1
- package/dist/components/DateFieldParts.js +7 -0
- package/dist/components/DatePicker.d.ts +9 -2
- package/dist/components/DatePicker.js +67 -28
- package/dist/components/DateRangePicker.d.ts +12 -2
- package/dist/components/DateRangePicker.js +13 -12
- package/dist/components/DetailPage.d.ts +7 -1
- package/dist/components/DetailPage.js +2 -1
- package/dist/components/Dialogs.d.ts +71 -10
- package/dist/components/Dialogs.js +130 -30
- package/dist/components/DiffViewer.d.ts +23 -3
- package/dist/components/DiffViewer.js +26 -12
- package/dist/components/DiscardPrompt.js +16 -0
- package/dist/components/DisplayPreferences.d.ts +83 -0
- package/dist/components/DisplayPreferences.js +185 -0
- package/dist/components/EditorialHome.d.ts +23 -3
- package/dist/components/EditorialHome.js +16 -11
- package/dist/components/EntityPicker.d.ts +20 -3
- package/dist/components/EntityPicker.js +32 -13
- package/dist/components/FilterEditor.d.ts +18 -4
- package/dist/components/FilterEditor.js +141 -19
- package/dist/components/FocusOnMount.d.ts +282 -0
- package/dist/components/FocusOnMount.js +12 -0
- package/dist/components/InfoTip.js +11 -12
- package/dist/components/InlineEdit.d.ts +87 -20
- package/dist/components/InlineEdit.js +197 -54
- package/dist/components/Input.d.ts +12 -2
- package/dist/components/Input.js +5 -3
- package/dist/components/Kanban.d.ts +14 -3
- package/dist/components/Kanban.js +9 -4
- package/dist/components/Kbd.d.ts +6 -1
- package/dist/components/Kbd.js +6 -6
- package/dist/components/Lightbox.d.ts +41 -5
- package/dist/components/Lightbox.js +95 -9
- package/dist/components/MatchReview.d.ts +40 -1
- package/dist/components/MatchReview.js +130 -4
- package/dist/components/MetricInput.js +3 -2
- package/dist/components/Modal.d.ts +2 -1
- package/dist/components/Modal.js +13 -4
- package/dist/components/MotionList.d.ts +303 -0
- package/dist/components/MotionList.js +175 -0
- package/dist/components/NavFavourites.d.ts +5 -0
- package/dist/components/NavFavourites.js +7 -7
- package/dist/components/OtpInput.d.ts +33 -0
- package/dist/components/OtpInput.js +123 -0
- package/dist/components/PageHeader.d.ts +7 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Pagination.js +6 -5
- package/dist/components/PasswordInput.d.ts +34 -0
- package/dist/components/PasswordInput.js +101 -0
- package/dist/components/Peek.js +3 -3
- package/dist/components/Popover.js +11 -0
- package/dist/components/PrintLayout.d.ts +63 -0
- package/dist/components/PrintLayout.js +114 -0
- package/dist/components/QrCode.d.ts +47 -0
- package/dist/components/QrCode.js +55 -0
- package/dist/components/QrScanner.d.ts +95 -0
- package/dist/components/QrScanner.js +266 -0
- package/dist/components/RelationshipGraph.d.ts +32 -1
- package/dist/components/RelationshipGraph.js +22 -6
- package/dist/components/RelationshipGraphLayered.d.ts +1 -1
- package/dist/components/RelationshipGraphLayered.js +268 -118
- package/dist/components/RelationshipGraphList.js +33 -6
- package/dist/components/RuleBuilder.js +39 -7
- package/dist/components/SchedulingAgenda.d.ts +3 -1
- package/dist/components/SchedulingCalendar.d.ts +3 -1
- package/dist/components/SchedulingCalendar.js +43 -4
- package/dist/components/SchedulingResourceDay.d.ts +57 -0
- package/dist/components/SchedulingResourceDay.js +287 -0
- package/dist/components/SchedulingTimeGrid.d.ts +3 -1
- package/dist/components/SchedulingTimeline.d.ts +3 -1
- package/dist/components/SearchSuggest.d.ts +23 -3
- package/dist/components/SearchSuggest.js +56 -18
- package/dist/components/Segmented.d.ts +39 -4
- package/dist/components/Segmented.js +39 -5
- package/dist/components/Select.d.ts +3 -2
- package/dist/components/Select.js +7 -1
- package/dist/components/ShortcutHint.d.ts +11 -10
- package/dist/components/ShortcutHint.js +44 -38
- package/dist/components/Sidebar.d.ts +36 -4
- package/dist/components/Sidebar.js +37 -12
- package/dist/components/SortableList.d.ts +45 -0
- package/dist/components/SortableList.js +147 -0
- package/dist/components/Stat.d.ts +28 -3
- package/dist/components/Stat.js +13 -3
- package/dist/components/States.d.ts +33 -1
- package/dist/components/States.js +43 -1
- package/dist/components/StatusPill.d.ts +14 -3
- package/dist/components/StatusPill.js +11 -3
- package/dist/components/Steps.js +2 -1
- package/dist/components/Table.d.ts +9 -2
- package/dist/components/Table.js +4 -2
- package/dist/components/TableControls.js +18 -58
- package/dist/components/TableOverflowProbe.d.ts +12 -0
- package/dist/components/TableOverflowProbe.js +27 -0
- package/dist/components/Tabs.d.ts +2 -1
- package/dist/components/Tabs.js +10 -2
- package/dist/components/TagInput.d.ts +67 -0
- package/dist/components/TagInput.js +342 -0
- package/dist/components/Textarea.d.ts +5 -0
- package/dist/components/Textarea.js +2 -2
- package/dist/components/TimePicker.d.ts +80 -0
- package/dist/components/TimePicker.js +347 -0
- package/dist/components/Toast.d.ts +1 -1
- package/dist/components/Toast.js +109 -4
- package/dist/components/Tooltip.d.ts +8 -4
- package/dist/components/Tooltip.js +86 -28
- package/dist/components/Tree.d.ts +8 -0
- package/dist/components/Tree.js +11 -5
- package/dist/display-preferences-model.d.ts +53 -0
- package/dist/display-preferences-model.js +64 -0
- package/dist/emoji.cjs +143 -49
- package/dist/filter-model.d.ts +59 -3
- package/dist/filter-model.js +67 -2
- package/dist/hooks/useAnchoredPosition.js +14 -2
- package/dist/hooks/useChangeHighlight.d.ts +33 -0
- package/dist/hooks/useChangeHighlight.js +44 -0
- package/dist/hooks/useDeferredReorder.d.ts +32 -0
- package/dist/hooks/useDeferredReorder.js +47 -0
- package/dist/hooks/useDialog.d.ts +5 -0
- package/dist/hooks/useDialog.js +17 -3
- package/dist/hooks/useKeyboardGrab.d.ts +58 -0
- package/dist/hooks/useKeyboardGrab.js +118 -0
- package/dist/hooks/useOptimisticValue.d.ts +51 -0
- package/dist/hooks/useOptimisticValue.js +61 -0
- package/dist/hooks/useReducedMotion.d.ts +4 -1
- package/dist/hooks/useReducedMotion.js +7 -1
- package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
- package/dist/hooks/useResolvedFilterLabels.js +34 -0
- package/dist/hooks/useSlidingIndicator.d.ts +18 -0
- package/dist/hooks/useSlidingIndicator.js +80 -0
- package/dist/hooks/useVirtualRows.d.ts +21 -2
- package/dist/hooks/useVirtualRows.js +30 -3
- package/dist/icons/Icon.d.ts +1 -1
- package/dist/index.cjs +19687 -13423
- package/dist/index.d.cts +3419 -651
- package/dist/index.d.ts +48 -18
- package/dist/index.js +153 -9
- package/dist/labels-context.d.ts +93 -3
- package/dist/motion.d.ts +11 -0
- package/dist/motion.js +35 -0
- package/dist/overlay-stack.d.ts +6 -0
- package/dist/overlay-stack.js +13 -0
- package/dist/qr-model.d.ts +65 -0
- package/dist/qr-model.js +323 -0
- package/dist/relationship-graph-model.d.ts +92 -3
- package/dist/relationship-graph-model.js +134 -15
- package/dist/reorder.d.ts +30 -0
- package/dist/reorder.js +74 -0
- package/dist/rich-text.cjs +46 -4
- package/dist/scheduling-resource-model.d.ts +76 -0
- package/dist/scheduling-resource-model.js +74 -0
- package/dist/search-suggest-model.js +3 -1
- package/dist/shell-context.d.ts +11 -0
- package/dist/shell-context.js +7 -0
- package/dist/time-field-model.d.ts +46 -0
- package/dist/time-field-model.js +152 -0
- package/dist/toast-store.d.ts +22 -3
- package/dist/toast-store.js +26 -9
- package/package.json +2 -1
|
@@ -2,6 +2,8 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { CalendarWeekday } from './calendar-model.js';
|
|
4
4
|
import { MoveProposal, MonthSpanLayout } from './scheduling-calendar-model.js';
|
|
5
|
+
import { SchedulingSlotSelection } from './components/SchedulingResourceDay.js';
|
|
6
|
+
import { SchedulingAvailabilityKind, SchedulingResource, SchedulingResourceSpan } from './scheduling-resource-model.js';
|
|
5
7
|
|
|
6
8
|
interface TimeGridEntryContext {
|
|
7
9
|
/** Whole text lines that fit in the item: 0 shows the markers only. */
|
|
@@ -236,6 +238,18 @@ interface SchedulingCalendarLabels {
|
|
|
236
238
|
moveCancelled?: string;
|
|
237
239
|
/** Announced when the time asked for does not exist that day. `{time}` is the time used instead. */
|
|
238
240
|
gapForward?: string;
|
|
241
|
+
/** Names the resource day (HAR-983). `{date}` placeholder. */
|
|
242
|
+
resourceGrid?: string;
|
|
243
|
+
/** The words for the kinds of a resource span. */
|
|
244
|
+
availability?: Partial<Record<SchedulingAvailabilityKind, string>>;
|
|
245
|
+
/** Time of a resource that no span covers: no schedule, which is not free. */
|
|
246
|
+
noSchedule?: string;
|
|
247
|
+
/** A resource slot's or booking's accessible name. `{resource}`, `{start}`, `{end}`, `{kind}`, `{label}`. */
|
|
248
|
+
slotName?: string;
|
|
249
|
+
/** How to move in the resource day, read with it. */
|
|
250
|
+
resourceHint?: string;
|
|
251
|
+
/** The resource day with no resources. */
|
|
252
|
+
noResources?: string;
|
|
239
253
|
}
|
|
240
254
|
declare const DEFAULT_SCHEDULING_CALENDAR_LABELS: SchedulingCalendarLabels;
|
|
241
255
|
interface SchedulingCalendarProps {
|
|
@@ -376,13 +390,48 @@ interface SchedulingCalendarProps {
|
|
|
376
390
|
topLaneCap?: number;
|
|
377
391
|
/** Lanes side by side in one day column of the time grid, at most. Fewer are used when the column is narrow. Default 4. */
|
|
378
392
|
maxLanes?: number;
|
|
393
|
+
/**
|
|
394
|
+
* With `view="day"`, one column per resource (a practitioner, a room) instead of the time grid
|
|
395
|
+
* (HAR-983). Their stretches of the day come from `resourceSpans`; a time no span covers is
|
|
396
|
+
* shown as "no schedule", never as free.
|
|
397
|
+
*/
|
|
398
|
+
resources?: SchedulingResource[];
|
|
399
|
+
/** The free, booked and off stretches of each resource, as the server composed them. */
|
|
400
|
+
resourceSpans?: SchedulingResourceSpan[];
|
|
401
|
+
/** Minutes per slot of the resource day: each free span is cut into bookable slots of this length. Default 15. */
|
|
402
|
+
slotMinutes?: number;
|
|
403
|
+
/** The first local time of the resource day's axis, `HH:MM`. Default `'07:00'`. */
|
|
404
|
+
dayStart?: string;
|
|
405
|
+
/** The local time the resource day's axis ends, `HH:MM`. Default `'19:00'`. */
|
|
406
|
+
dayEnd?: string;
|
|
407
|
+
/** Called by a click, Enter or Space on a free slot (its own start and end) or a booking. */
|
|
408
|
+
onSelectSlot?: (slot: SchedulingSlotSelection) => void;
|
|
409
|
+
/** Marks the slot or booking that holds this instant for this resource, e.g. while its popover is open. */
|
|
410
|
+
selectedSlot?: {
|
|
411
|
+
resourceId: string;
|
|
412
|
+
start: string;
|
|
413
|
+
};
|
|
414
|
+
/**
|
|
415
|
+
* `auto` (default): columns, and a list of one resource after another when the calendar is
|
|
416
|
+
* narrower than `resourceListBelow`. `columns` or `list` fixes one.
|
|
417
|
+
*/
|
|
418
|
+
resourceLayout?: 'auto' | 'columns' | 'list';
|
|
419
|
+
/** The width in CSS pixels under which `auto` shows the list. Default 480. */
|
|
420
|
+
resourceListBelow?: number;
|
|
421
|
+
/**
|
|
422
|
+
* The first load shows skeletons; a refetch keeps what is on screen, dimmed and `aria-busy`
|
|
423
|
+
* (the resource day; the other views show `labels.loading` instead).
|
|
424
|
+
*/
|
|
379
425
|
loading?: boolean;
|
|
380
426
|
error?: string;
|
|
381
427
|
onRetry?: () => void;
|
|
382
428
|
className?: string;
|
|
383
429
|
labels?: Partial<SchedulingCalendarLabels>;
|
|
384
430
|
}
|
|
385
|
-
/**
|
|
386
|
-
|
|
431
|
+
/**
|
|
432
|
+
* Month/week/day/agenda calendar for UTC ranges rendered in an explicit IANA time zone. With
|
|
433
|
+
* `resources`, the day view is one column per resource (HAR-983).
|
|
434
|
+
*/
|
|
435
|
+
declare function SchedulingCalendar({ entries, anchorDate, timeZone, view: controlledView, onViewChange, onAnchorDateChange, onSelectEntry, overlays, onSelectOverlay, filter, renderEntry, locale, weekStartsOn, formatDate, formatInstant: formatInstantProp, maxEntriesPerDay, onShowMore, renderDayBadge, days: dayInfo, dayEntries, spanLayout, windowLaneCap, spanLaneCap, legend, legendCaption, showHeader, notice, emptyNote, onSelectDate, agendaGroups, agendaHeadingLevel, virtualizeAbove, monthDensity, timeGrid, now, canMove, step, onProposeMove, topLaneCrossMidnightMinutes, topLaneCap, maxLanes, resources, resourceSpans, slotMinutes, dayStart, dayEnd, onSelectSlot, selectedSlot, resourceLayout, resourceListBelow, loading, error, onRetry, className, labels: labelOverrides, }: SchedulingCalendarProps): react.JSX.Element;
|
|
387
436
|
|
|
388
437
|
export { DEFAULT_SCHEDULING_CALENDAR_LABELS as D, type SchedulingAgendaGroup as S, type TimeGridEntryContext as T, type SchedulingBand as a, SchedulingCalendar as b, type SchedulingCalendarDay as c, type SchedulingCalendarEntry as d, type SchedulingCalendarLabels as e, type SchedulingCalendarOverlay as f, type SchedulingCalendarProps as g, type SchedulingCalendarView as h, type SchedulingDatePart as i, type SchedulingEntryState as j, type SchedulingLegendItem as k, type SchedulingMarker as l, type SchedulingMarkerEmphasis as m, type SchedulingOverlayKind as n, type SchedulingOverlayPattern as o, type SchedulingStatus as p, SchedulingTimeGrid as q, type SchedulingTimeGridProps as r };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Create the polite region `announcePolite(…, from)` will use, ahead of its first message. */
|
|
2
|
+
declare function ensureAnnouncer(from?: Element | null): void;
|
|
3
|
+
/**
|
|
4
|
+
* Say `text` through a polite live region (`[data-uix-announcer]`): the page's, or the open
|
|
5
|
+
* dialog's when `from` is inside one. The region is cleared first and filled a moment later,
|
|
6
|
+
* so the same words twice are spoken twice; a newer message replaces one not yet spoken.
|
|
7
|
+
*/
|
|
8
|
+
declare function announcePolite(text: string, from?: Element | null): void;
|
|
9
|
+
|
|
10
|
+
export { announcePolite, ensureAnnouncer };
|
package/dist/announce.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const timers = /* @__PURE__ */ new WeakMap();
|
|
2
|
+
function ensureAnnouncer(from) {
|
|
3
|
+
liveRegion(from);
|
|
4
|
+
}
|
|
5
|
+
function liveRegion(from) {
|
|
6
|
+
if (typeof document === "undefined") return null;
|
|
7
|
+
const container = from?.closest("dialog") ?? document.body;
|
|
8
|
+
let region = container.querySelector(":scope > [data-uix-announcer]");
|
|
9
|
+
if (!region) {
|
|
10
|
+
region = document.createElement("div");
|
|
11
|
+
region.setAttribute("role", "status");
|
|
12
|
+
region.setAttribute("data-uix-announcer", "");
|
|
13
|
+
region.className = "uix-visually-hidden";
|
|
14
|
+
container.append(region);
|
|
15
|
+
}
|
|
16
|
+
return region;
|
|
17
|
+
}
|
|
18
|
+
function announcePolite(text, from) {
|
|
19
|
+
const el = liveRegion(from);
|
|
20
|
+
if (!el) return;
|
|
21
|
+
clearTimeout(timers.get(el));
|
|
22
|
+
el.textContent = "";
|
|
23
|
+
timers.set(el, setTimeout(() => {
|
|
24
|
+
el.textContent = text;
|
|
25
|
+
}, 0));
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
announcePolite,
|
|
29
|
+
ensureAnnouncer
|
|
30
|
+
};
|
package/dist/chart-analytic.cjs
CHANGED
|
@@ -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
|
|
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 (
|
|
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,
|
|
229
|
-
const chartRef = (0,
|
|
230
|
-
const appliedOptionRef = (0,
|
|
231
|
-
const onEventsRef = (0,
|
|
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,
|
|
234
|
-
const onReadyRef = (0,
|
|
235
|
-
const tableId = (0,
|
|
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,
|
|
239
|
-
const themeRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
1199
|
-
const layout = (0,
|
|
1200
|
-
const option = (0,
|
|
1201
|
-
const onEvents = (0,
|
|
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,
|
|
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,
|
|
1274
|
-
const option = (0,
|
|
1275
|
-
const usable = (0,
|
|
1276
|
-
const onEvents = (0,
|
|
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;
|
package/dist/chart-preset.cjs
CHANGED
|
@@ -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
|
|
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 (
|
|
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,
|
|
205
|
-
const chartRef = (0,
|
|
206
|
-
const appliedOptionRef = (0,
|
|
207
|
-
const onEventsRef = (0,
|
|
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,
|
|
210
|
-
const onReadyRef = (0,
|
|
211
|
-
const tableId = (0,
|
|
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,
|
|
215
|
-
const themeRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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 (
|
|
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,
|
|
203
|
-
const chartRef = (0,
|
|
204
|
-
const appliedOptionRef = (0,
|
|
205
|
-
const onEventsRef = (0,
|
|
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,
|
|
208
|
-
const onReadyRef = (0,
|
|
209
|
-
const tableId = (0,
|
|
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,
|
|
213
|
-
const themeRef = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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;
|
package/dist/combobox-model.d.ts
CHANGED
|
@@ -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 };
|
package/dist/combobox-model.js
CHANGED
|
@@ -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
|
+
};
|