@tensor_1/react 2.48.0 → 2.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +70 -1
  2. package/dist/components/Chip.d.ts +7 -3
  3. package/dist/components/Chip.js +2 -2
  4. package/dist/components/DashboardCanvas.js +14 -0
  5. package/dist/components/DataWorkspace.js +1 -4
  6. package/dist/components/Dialogs.js +5 -5
  7. package/dist/components/FocusOnMount.d.ts +282 -0
  8. package/dist/components/FocusOnMount.js +12 -0
  9. package/dist/components/Kanban.d.ts +14 -3
  10. package/dist/components/Kanban.js +9 -4
  11. package/dist/components/MotionList.d.ts +303 -0
  12. package/dist/components/MotionList.js +175 -0
  13. package/dist/components/Popover.js +9 -0
  14. package/dist/components/RelationshipGraph.js +4 -1
  15. package/dist/components/RelationshipGraphLayered.js +107 -32
  16. package/dist/components/SearchSuggest.js +8 -1
  17. package/dist/components/Segmented.js +8 -2
  18. package/dist/components/Select.js +6 -0
  19. package/dist/components/SortableList.d.ts +2 -2
  20. package/dist/components/SortableList.js +16 -3
  21. package/dist/components/States.d.ts +33 -1
  22. package/dist/components/States.js +43 -1
  23. package/dist/components/Tabs.js +9 -2
  24. package/dist/components/Toast.d.ts +1 -1
  25. package/dist/components/Toast.js +106 -2
  26. package/dist/components/Tooltip.js +62 -7
  27. package/dist/emoji.cjs +115 -14
  28. package/dist/hooks/useAnchoredPosition.js +14 -2
  29. package/dist/hooks/useDeferredReorder.d.ts +32 -0
  30. package/dist/hooks/useDeferredReorder.js +47 -0
  31. package/dist/hooks/useDialog.js +15 -2
  32. package/dist/hooks/useKeyboardGrab.d.ts +58 -0
  33. package/dist/hooks/useKeyboardGrab.js +118 -0
  34. package/dist/hooks/useSlidingIndicator.d.ts +18 -0
  35. package/dist/hooks/useSlidingIndicator.js +80 -0
  36. package/dist/index.cjs +2208 -1378
  37. package/dist/index.d.cts +477 -13
  38. package/dist/index.d.ts +7 -3
  39. package/dist/index.js +14 -2
  40. package/dist/labels-context.d.ts +3 -0
  41. package/dist/motion.d.ts +11 -0
  42. package/dist/motion.js +35 -0
  43. package/dist/relationship-graph-model.d.ts +17 -3
  44. package/dist/relationship-graph-model.js +28 -16
  45. package/dist/rich-text.cjs +42 -2
  46. package/dist/toast-store.d.ts +5 -2
  47. package/dist/toast-store.js +3 -2
  48. package/package.json +1 -1
@@ -0,0 +1,303 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactElement, TransitionEvent } from 'react';
3
+
4
+ type Key = string | number;
5
+ interface MotionListProps<T> extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
6
+ /** The items in the order to show them. */
7
+ items: readonly T[];
8
+ /** A stable key per item. */
9
+ getKey: (item: T) => Key;
10
+ /**
11
+ * One element per item: an `<li>` for `ul`/`ol`, a `Tr` for `tbody`. It must pass unknown
12
+ * props through to its DOM element (the list sets `data-uix-key` and, while an item leaves,
13
+ * `data-uix-exiting` and `aria-hidden`; `inert` is set on the element directly).
14
+ */
15
+ renderItem: (item: T, state: {
16
+ exiting: boolean;
17
+ }) => ReactElement;
18
+ /** The list element (default `ul`). */
19
+ as?: 'ul' | 'ol' | 'div' | 'tbody';
20
+ }
21
+ /**
22
+ * A list whose items arrive, leave and move visibly (HAR-2586, motion standard §2.5):
23
+ *
24
+ * - A new item fades in and rises 8 px into place; never on the first render.
25
+ * - A removed item stays for a moment, fades out, and only then leaves; the items after it
26
+ * glide up into the gap instead of jumping.
27
+ * - A reordered item glides from its old place to its new one (FLIP: transform only).
28
+ * - Focus stays put: on an item that moved, and on the next item when the focused one leaves.
29
+ * Focus outside the list is never pulled in.
30
+ *
31
+ * Reduced motion keeps the fades and drops every glide and rise. For a list that re-sorts
32
+ * itself (live data), hold the order while the person is pointing at it: `useDeferredReorder`.
33
+ */
34
+ declare function MotionList<T>({ items, getKey, renderItem, as, className, ...props }: MotionListProps<T>): react.DetailedReactHTMLElement<{
35
+ ref: react.RefObject<HTMLElement>;
36
+ className: string;
37
+ onTransitionEnd: (event: TransitionEvent<HTMLElement>) => void;
38
+ color?: string | undefined | undefined;
39
+ title?: string | undefined | undefined;
40
+ id?: string | undefined | undefined;
41
+ draggable?: (boolean | "false" | "true") | undefined;
42
+ style?: react.CSSProperties | undefined;
43
+ defaultChecked?: boolean | undefined | undefined;
44
+ defaultValue?: string | number | readonly string[] | undefined;
45
+ suppressContentEditableWarning?: boolean | undefined | undefined;
46
+ suppressHydrationWarning?: boolean | undefined | undefined;
47
+ accessKey?: string | undefined | undefined;
48
+ autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
49
+ autoFocus?: boolean | undefined | undefined;
50
+ contentEditable?: "inherit" | (boolean | "false" | "true") | "plaintext-only" | undefined;
51
+ contextMenu?: string | undefined | undefined;
52
+ dir?: string | undefined | undefined;
53
+ enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
54
+ hidden?: boolean | undefined | undefined;
55
+ lang?: string | undefined | undefined;
56
+ nonce?: string | undefined | undefined;
57
+ slot?: string | undefined | undefined;
58
+ spellCheck?: (boolean | "false" | "true") | undefined;
59
+ tabIndex?: number | undefined | undefined;
60
+ translate?: "yes" | "no" | undefined | undefined;
61
+ radioGroup?: string | undefined | undefined;
62
+ role?: react.AriaRole | undefined;
63
+ about?: string | undefined | undefined;
64
+ content?: string | undefined | undefined;
65
+ datatype?: string | undefined | undefined;
66
+ inlist?: any;
67
+ prefix?: string | undefined | undefined;
68
+ property?: string | undefined | undefined;
69
+ rel?: string | undefined | undefined;
70
+ resource?: string | undefined | undefined;
71
+ rev?: string | undefined | undefined;
72
+ typeof?: string | undefined | undefined;
73
+ vocab?: string | undefined | undefined;
74
+ autoCorrect?: string | undefined | undefined;
75
+ autoSave?: string | undefined | undefined;
76
+ itemProp?: string | undefined | undefined;
77
+ itemScope?: boolean | undefined | undefined;
78
+ itemType?: string | undefined | undefined;
79
+ itemID?: string | undefined | undefined;
80
+ itemRef?: string | undefined | undefined;
81
+ results?: number | undefined | undefined;
82
+ security?: string | undefined | undefined;
83
+ unselectable?: "on" | "off" | undefined | undefined;
84
+ inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
85
+ is?: string | undefined | undefined;
86
+ exportparts?: string | undefined | undefined;
87
+ part?: string | undefined | undefined;
88
+ "aria-activedescendant"?: string | undefined | undefined;
89
+ "aria-atomic"?: (boolean | "false" | "true") | undefined;
90
+ "aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
91
+ "aria-braillelabel"?: string | undefined | undefined;
92
+ "aria-brailleroledescription"?: string | undefined | undefined;
93
+ "aria-busy"?: (boolean | "false" | "true") | undefined;
94
+ "aria-checked"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
95
+ "aria-colcount"?: number | undefined | undefined;
96
+ "aria-colindex"?: number | undefined | undefined;
97
+ "aria-colindextext"?: string | undefined | undefined;
98
+ "aria-colspan"?: number | undefined | undefined;
99
+ "aria-controls"?: string | undefined | undefined;
100
+ "aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined | undefined;
101
+ "aria-describedby"?: string | undefined | undefined;
102
+ "aria-description"?: string | undefined | undefined;
103
+ "aria-details"?: string | undefined | undefined;
104
+ "aria-disabled"?: (boolean | "false" | "true") | undefined;
105
+ "aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined | undefined;
106
+ "aria-errormessage"?: string | undefined | undefined;
107
+ "aria-expanded"?: (boolean | "false" | "true") | undefined;
108
+ "aria-flowto"?: string | undefined | undefined;
109
+ "aria-grabbed"?: (boolean | "false" | "true") | undefined;
110
+ "aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined | undefined;
111
+ "aria-hidden"?: (boolean | "false" | "true") | undefined;
112
+ "aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined | undefined;
113
+ "aria-keyshortcuts"?: string | undefined | undefined;
114
+ "aria-label"?: string | undefined | undefined;
115
+ "aria-labelledby"?: string | undefined | undefined;
116
+ "aria-level"?: number | undefined | undefined;
117
+ "aria-live"?: "off" | "assertive" | "polite" | undefined | undefined;
118
+ "aria-modal"?: (boolean | "false" | "true") | undefined;
119
+ "aria-multiline"?: (boolean | "false" | "true") | undefined;
120
+ "aria-multiselectable"?: (boolean | "false" | "true") | undefined;
121
+ "aria-orientation"?: "horizontal" | "vertical" | undefined | undefined;
122
+ "aria-owns"?: string | undefined | undefined;
123
+ "aria-placeholder"?: string | undefined | undefined;
124
+ "aria-posinset"?: number | undefined | undefined;
125
+ "aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
126
+ "aria-readonly"?: (boolean | "false" | "true") | undefined;
127
+ "aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined | undefined;
128
+ "aria-required"?: (boolean | "false" | "true") | undefined;
129
+ "aria-roledescription"?: string | undefined | undefined;
130
+ "aria-rowcount"?: number | undefined | undefined;
131
+ "aria-rowindex"?: number | undefined | undefined;
132
+ "aria-rowindextext"?: string | undefined | undefined;
133
+ "aria-rowspan"?: number | undefined | undefined;
134
+ "aria-selected"?: (boolean | "false" | "true") | undefined;
135
+ "aria-setsize"?: number | undefined | undefined;
136
+ "aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined | undefined;
137
+ "aria-valuemax"?: number | undefined | undefined;
138
+ "aria-valuemin"?: number | undefined | undefined;
139
+ "aria-valuenow"?: number | undefined | undefined;
140
+ "aria-valuetext"?: string | undefined | undefined;
141
+ dangerouslySetInnerHTML?: {
142
+ __html: string | TrustedHTML;
143
+ } | undefined | undefined;
144
+ onCopy?: react.ClipboardEventHandler<HTMLElement> | undefined;
145
+ onCopyCapture?: react.ClipboardEventHandler<HTMLElement> | undefined;
146
+ onCut?: react.ClipboardEventHandler<HTMLElement> | undefined;
147
+ onCutCapture?: react.ClipboardEventHandler<HTMLElement> | undefined;
148
+ onPaste?: react.ClipboardEventHandler<HTMLElement> | undefined;
149
+ onPasteCapture?: react.ClipboardEventHandler<HTMLElement> | undefined;
150
+ onCompositionEnd?: react.CompositionEventHandler<HTMLElement> | undefined;
151
+ onCompositionEndCapture?: react.CompositionEventHandler<HTMLElement> | undefined;
152
+ onCompositionStart?: react.CompositionEventHandler<HTMLElement> | undefined;
153
+ onCompositionStartCapture?: react.CompositionEventHandler<HTMLElement> | undefined;
154
+ onCompositionUpdate?: react.CompositionEventHandler<HTMLElement> | undefined;
155
+ onCompositionUpdateCapture?: react.CompositionEventHandler<HTMLElement> | undefined;
156
+ onFocus?: react.FocusEventHandler<HTMLElement> | undefined;
157
+ onFocusCapture?: react.FocusEventHandler<HTMLElement> | undefined;
158
+ onBlur?: react.FocusEventHandler<HTMLElement> | undefined;
159
+ onBlurCapture?: react.FocusEventHandler<HTMLElement> | undefined;
160
+ onChange?: react.FormEventHandler<HTMLElement> | undefined;
161
+ onChangeCapture?: react.FormEventHandler<HTMLElement> | undefined;
162
+ onBeforeInput?: react.InputEventHandler<HTMLElement> | undefined;
163
+ onBeforeInputCapture?: react.FormEventHandler<HTMLElement> | undefined;
164
+ onInput?: react.FormEventHandler<HTMLElement> | undefined;
165
+ onInputCapture?: react.FormEventHandler<HTMLElement> | undefined;
166
+ onReset?: react.FormEventHandler<HTMLElement> | undefined;
167
+ onResetCapture?: react.FormEventHandler<HTMLElement> | undefined;
168
+ onSubmit?: react.FormEventHandler<HTMLElement> | undefined;
169
+ onSubmitCapture?: react.FormEventHandler<HTMLElement> | undefined;
170
+ onInvalid?: react.FormEventHandler<HTMLElement> | undefined;
171
+ onInvalidCapture?: react.FormEventHandler<HTMLElement> | undefined;
172
+ onLoad?: react.ReactEventHandler<HTMLElement> | undefined;
173
+ onLoadCapture?: react.ReactEventHandler<HTMLElement> | undefined;
174
+ onError?: react.ReactEventHandler<HTMLElement> | undefined;
175
+ onErrorCapture?: react.ReactEventHandler<HTMLElement> | undefined;
176
+ onKeyDown?: react.KeyboardEventHandler<HTMLElement> | undefined;
177
+ onKeyDownCapture?: react.KeyboardEventHandler<HTMLElement> | undefined;
178
+ onKeyPress?: react.KeyboardEventHandler<HTMLElement> | undefined;
179
+ onKeyPressCapture?: react.KeyboardEventHandler<HTMLElement> | undefined;
180
+ onKeyUp?: react.KeyboardEventHandler<HTMLElement> | undefined;
181
+ onKeyUpCapture?: react.KeyboardEventHandler<HTMLElement> | undefined;
182
+ onAbort?: react.ReactEventHandler<HTMLElement> | undefined;
183
+ onAbortCapture?: react.ReactEventHandler<HTMLElement> | undefined;
184
+ onCanPlay?: react.ReactEventHandler<HTMLElement> | undefined;
185
+ onCanPlayCapture?: react.ReactEventHandler<HTMLElement> | undefined;
186
+ onCanPlayThrough?: react.ReactEventHandler<HTMLElement> | undefined;
187
+ onCanPlayThroughCapture?: react.ReactEventHandler<HTMLElement> | undefined;
188
+ onDurationChange?: react.ReactEventHandler<HTMLElement> | undefined;
189
+ onDurationChangeCapture?: react.ReactEventHandler<HTMLElement> | undefined;
190
+ onEmptied?: react.ReactEventHandler<HTMLElement> | undefined;
191
+ onEmptiedCapture?: react.ReactEventHandler<HTMLElement> | undefined;
192
+ onEncrypted?: react.ReactEventHandler<HTMLElement> | undefined;
193
+ onEncryptedCapture?: react.ReactEventHandler<HTMLElement> | undefined;
194
+ onEnded?: react.ReactEventHandler<HTMLElement> | undefined;
195
+ onEndedCapture?: react.ReactEventHandler<HTMLElement> | undefined;
196
+ onLoadedData?: react.ReactEventHandler<HTMLElement> | undefined;
197
+ onLoadedDataCapture?: react.ReactEventHandler<HTMLElement> | undefined;
198
+ onLoadedMetadata?: react.ReactEventHandler<HTMLElement> | undefined;
199
+ onLoadedMetadataCapture?: react.ReactEventHandler<HTMLElement> | undefined;
200
+ onLoadStart?: react.ReactEventHandler<HTMLElement> | undefined;
201
+ onLoadStartCapture?: react.ReactEventHandler<HTMLElement> | undefined;
202
+ onPause?: react.ReactEventHandler<HTMLElement> | undefined;
203
+ onPauseCapture?: react.ReactEventHandler<HTMLElement> | undefined;
204
+ onPlay?: react.ReactEventHandler<HTMLElement> | undefined;
205
+ onPlayCapture?: react.ReactEventHandler<HTMLElement> | undefined;
206
+ onPlaying?: react.ReactEventHandler<HTMLElement> | undefined;
207
+ onPlayingCapture?: react.ReactEventHandler<HTMLElement> | undefined;
208
+ onProgress?: react.ReactEventHandler<HTMLElement> | undefined;
209
+ onProgressCapture?: react.ReactEventHandler<HTMLElement> | undefined;
210
+ onRateChange?: react.ReactEventHandler<HTMLElement> | undefined;
211
+ onRateChangeCapture?: react.ReactEventHandler<HTMLElement> | undefined;
212
+ onSeeked?: react.ReactEventHandler<HTMLElement> | undefined;
213
+ onSeekedCapture?: react.ReactEventHandler<HTMLElement> | undefined;
214
+ onSeeking?: react.ReactEventHandler<HTMLElement> | undefined;
215
+ onSeekingCapture?: react.ReactEventHandler<HTMLElement> | undefined;
216
+ onStalled?: react.ReactEventHandler<HTMLElement> | undefined;
217
+ onStalledCapture?: react.ReactEventHandler<HTMLElement> | undefined;
218
+ onSuspend?: react.ReactEventHandler<HTMLElement> | undefined;
219
+ onSuspendCapture?: react.ReactEventHandler<HTMLElement> | undefined;
220
+ onTimeUpdate?: react.ReactEventHandler<HTMLElement> | undefined;
221
+ onTimeUpdateCapture?: react.ReactEventHandler<HTMLElement> | undefined;
222
+ onVolumeChange?: react.ReactEventHandler<HTMLElement> | undefined;
223
+ onVolumeChangeCapture?: react.ReactEventHandler<HTMLElement> | undefined;
224
+ onWaiting?: react.ReactEventHandler<HTMLElement> | undefined;
225
+ onWaitingCapture?: react.ReactEventHandler<HTMLElement> | undefined;
226
+ onAuxClick?: react.MouseEventHandler<HTMLElement> | undefined;
227
+ onAuxClickCapture?: react.MouseEventHandler<HTMLElement> | undefined;
228
+ onClick?: react.MouseEventHandler<HTMLElement> | undefined;
229
+ onClickCapture?: react.MouseEventHandler<HTMLElement> | undefined;
230
+ onContextMenu?: react.MouseEventHandler<HTMLElement> | undefined;
231
+ onContextMenuCapture?: react.MouseEventHandler<HTMLElement> | undefined;
232
+ onDoubleClick?: react.MouseEventHandler<HTMLElement> | undefined;
233
+ onDoubleClickCapture?: react.MouseEventHandler<HTMLElement> | undefined;
234
+ onDrag?: react.DragEventHandler<HTMLElement> | undefined;
235
+ onDragCapture?: react.DragEventHandler<HTMLElement> | undefined;
236
+ onDragEnd?: react.DragEventHandler<HTMLElement> | undefined;
237
+ onDragEndCapture?: react.DragEventHandler<HTMLElement> | undefined;
238
+ onDragEnter?: react.DragEventHandler<HTMLElement> | undefined;
239
+ onDragEnterCapture?: react.DragEventHandler<HTMLElement> | undefined;
240
+ onDragExit?: react.DragEventHandler<HTMLElement> | undefined;
241
+ onDragExitCapture?: react.DragEventHandler<HTMLElement> | undefined;
242
+ onDragLeave?: react.DragEventHandler<HTMLElement> | undefined;
243
+ onDragLeaveCapture?: react.DragEventHandler<HTMLElement> | undefined;
244
+ onDragOver?: react.DragEventHandler<HTMLElement> | undefined;
245
+ onDragOverCapture?: react.DragEventHandler<HTMLElement> | undefined;
246
+ onDragStart?: react.DragEventHandler<HTMLElement> | undefined;
247
+ onDragStartCapture?: react.DragEventHandler<HTMLElement> | undefined;
248
+ onDrop?: react.DragEventHandler<HTMLElement> | undefined;
249
+ onDropCapture?: react.DragEventHandler<HTMLElement> | undefined;
250
+ onMouseDown?: react.MouseEventHandler<HTMLElement> | undefined;
251
+ onMouseDownCapture?: react.MouseEventHandler<HTMLElement> | undefined;
252
+ onMouseEnter?: react.MouseEventHandler<HTMLElement> | undefined;
253
+ onMouseLeave?: react.MouseEventHandler<HTMLElement> | undefined;
254
+ onMouseMove?: react.MouseEventHandler<HTMLElement> | undefined;
255
+ onMouseMoveCapture?: react.MouseEventHandler<HTMLElement> | undefined;
256
+ onMouseOut?: react.MouseEventHandler<HTMLElement> | undefined;
257
+ onMouseOutCapture?: react.MouseEventHandler<HTMLElement> | undefined;
258
+ onMouseOver?: react.MouseEventHandler<HTMLElement> | undefined;
259
+ onMouseOverCapture?: react.MouseEventHandler<HTMLElement> | undefined;
260
+ onMouseUp?: react.MouseEventHandler<HTMLElement> | undefined;
261
+ onMouseUpCapture?: react.MouseEventHandler<HTMLElement> | undefined;
262
+ onSelect?: react.ReactEventHandler<HTMLElement> | undefined;
263
+ onSelectCapture?: react.ReactEventHandler<HTMLElement> | undefined;
264
+ onTouchCancel?: react.TouchEventHandler<HTMLElement> | undefined;
265
+ onTouchCancelCapture?: react.TouchEventHandler<HTMLElement> | undefined;
266
+ onTouchEnd?: react.TouchEventHandler<HTMLElement> | undefined;
267
+ onTouchEndCapture?: react.TouchEventHandler<HTMLElement> | undefined;
268
+ onTouchMove?: react.TouchEventHandler<HTMLElement> | undefined;
269
+ onTouchMoveCapture?: react.TouchEventHandler<HTMLElement> | undefined;
270
+ onTouchStart?: react.TouchEventHandler<HTMLElement> | undefined;
271
+ onTouchStartCapture?: react.TouchEventHandler<HTMLElement> | undefined;
272
+ onPointerDown?: react.PointerEventHandler<HTMLElement> | undefined;
273
+ onPointerDownCapture?: react.PointerEventHandler<HTMLElement> | undefined;
274
+ onPointerMove?: react.PointerEventHandler<HTMLElement> | undefined;
275
+ onPointerMoveCapture?: react.PointerEventHandler<HTMLElement> | undefined;
276
+ onPointerUp?: react.PointerEventHandler<HTMLElement> | undefined;
277
+ onPointerUpCapture?: react.PointerEventHandler<HTMLElement> | undefined;
278
+ onPointerCancel?: react.PointerEventHandler<HTMLElement> | undefined;
279
+ onPointerCancelCapture?: react.PointerEventHandler<HTMLElement> | undefined;
280
+ onPointerEnter?: react.PointerEventHandler<HTMLElement> | undefined;
281
+ onPointerLeave?: react.PointerEventHandler<HTMLElement> | undefined;
282
+ onPointerOver?: react.PointerEventHandler<HTMLElement> | undefined;
283
+ onPointerOverCapture?: react.PointerEventHandler<HTMLElement> | undefined;
284
+ onPointerOut?: react.PointerEventHandler<HTMLElement> | undefined;
285
+ onPointerOutCapture?: react.PointerEventHandler<HTMLElement> | undefined;
286
+ onGotPointerCapture?: react.PointerEventHandler<HTMLElement> | undefined;
287
+ onGotPointerCaptureCapture?: react.PointerEventHandler<HTMLElement> | undefined;
288
+ onLostPointerCapture?: react.PointerEventHandler<HTMLElement> | undefined;
289
+ onLostPointerCaptureCapture?: react.PointerEventHandler<HTMLElement> | undefined;
290
+ onScroll?: react.UIEventHandler<HTMLElement> | undefined;
291
+ onScrollCapture?: react.UIEventHandler<HTMLElement> | undefined;
292
+ onWheel?: react.WheelEventHandler<HTMLElement> | undefined;
293
+ onWheelCapture?: react.WheelEventHandler<HTMLElement> | undefined;
294
+ onAnimationStart?: react.AnimationEventHandler<HTMLElement> | undefined;
295
+ onAnimationStartCapture?: react.AnimationEventHandler<HTMLElement> | undefined;
296
+ onAnimationEnd?: react.AnimationEventHandler<HTMLElement> | undefined;
297
+ onAnimationEndCapture?: react.AnimationEventHandler<HTMLElement> | undefined;
298
+ onAnimationIteration?: react.AnimationEventHandler<HTMLElement> | undefined;
299
+ onAnimationIterationCapture?: react.AnimationEventHandler<HTMLElement> | undefined;
300
+ onTransitionEndCapture?: react.TransitionEventHandler<HTMLElement> | undefined;
301
+ }, HTMLElement>;
302
+
303
+ export { MotionList, type MotionListProps };
@@ -0,0 +1,175 @@
1
+ "use client";
2
+ import { Children, cloneElement, createElement, isValidElement, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { cx } from "../cx.js";
4
+ import { prefersReducedMotion } from "../hooks/useReducedMotion.js";
5
+ const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
6
+ const EXIT_FALLBACK_MS = 1e3;
7
+ const FOCUSABLE = 'a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"])';
8
+ function MotionList({ items, getKey, renderItem, as = "ul", className, ...props }) {
9
+ const containerRef = useRef(null);
10
+ const [state, setState] = useState(() => ({
11
+ items,
12
+ entries: items.map((item) => ({ key: getKey(item), item, exiting: false })),
13
+ exiting: /* @__PURE__ */ new Map()
14
+ }));
15
+ let { entries } = state;
16
+ if (state.items !== items && !sameItems(state.items, items)) {
17
+ const now = new Set(items.map(getKey));
18
+ const exitingNow = new Map(state.exiting);
19
+ for (const e of state.entries) if (!e.exiting && !now.has(e.key)) exitingNow.set(e.key, e.item);
20
+ for (const key of now) exitingNow.delete(key);
21
+ entries = merge(items, getKey, state.entries, exitingNow);
22
+ setState({ items, entries, exiting: exitingNow });
23
+ }
24
+ const previous = useRef(null);
25
+ const drop = (keys) => setState((current) => {
26
+ const gone = keys.filter((key) => current.exiting.has(key));
27
+ if (!gone.length) return current;
28
+ const exitingNow = new Map(current.exiting);
29
+ for (const key of gone) exitingNow.delete(key);
30
+ const goneSet = new Set(gone);
31
+ return { ...current, exiting: exitingNow, entries: current.entries.filter((e) => !(e.exiting && goneSet.has(e.key))) };
32
+ });
33
+ const boxes = useRef(/* @__PURE__ */ new Map());
34
+ const focusedKey = useRef(null);
35
+ const measuredFor = useRef(null);
36
+ if (measuredFor.current !== entries && containerRef.current) {
37
+ measuredFor.current = entries;
38
+ boxes.current = measure(containerRef.current);
39
+ let holder = typeof document !== "undefined" ? document.activeElement : null;
40
+ while (holder && holder.parentElement !== containerRef.current) holder = holder.parentElement;
41
+ focusedKey.current = holder?.getAttribute("data-uix-key") ?? null;
42
+ }
43
+ useIsomorphicLayoutEffect(() => {
44
+ const container = containerRef.current;
45
+ const before = previous.current;
46
+ previous.current = entries;
47
+ if (!container) return;
48
+ const byKey = new Map(entries.map((e) => [String(e.key), e]));
49
+ const elements = Array.from(container.querySelectorAll(":scope > [data-uix-key]"));
50
+ for (const el of elements) if (byKey.get(el.getAttribute("data-uix-key"))?.exiting) el.setAttribute("inert", "");
51
+ const had = focusedKey.current;
52
+ focusedKey.current = null;
53
+ const active = document.activeElement;
54
+ const lost = active === document.body || active === null || !active.isConnected || !!active.closest("[data-uix-exiting], [inert]");
55
+ if (had !== null && lost) {
56
+ const index = elements.findIndex((el) => el.getAttribute("data-uix-key") === had);
57
+ const stays = (el) => el && !el.hasAttribute("data-uix-exiting");
58
+ const own = stays(elements[index]) ? elements[index] : void 0;
59
+ const target = own ?? elements.slice(index + 1).find(stays) ?? elements.slice(0, Math.max(index, 0)).reverse().find(stays);
60
+ const focusable = target?.matches(FOCUSABLE) ? target : target?.querySelector(FOCUSABLE);
61
+ focusable?.focus({ preventScroll: true });
62
+ }
63
+ if (!before) return;
64
+ const reduced = prefersReducedMotion();
65
+ const was = new Set(before.map((e) => String(e.key)));
66
+ const moves = [];
67
+ if (!reduced) {
68
+ for (const el of elements) el.removeAttribute("data-uix-moving");
69
+ const origin = container.getBoundingClientRect();
70
+ for (const el of elements) {
71
+ const key = el.getAttribute("data-uix-key");
72
+ const entry = byKey.get(key);
73
+ if (!entry || entry.exiting || !was.has(key)) continue;
74
+ const from = boxes.current.get(key);
75
+ if (!from) continue;
76
+ const r = el.getBoundingClientRect();
77
+ const dx = from.x - (r.left - origin.left);
78
+ const dy = from.y - (r.top - origin.top);
79
+ if (dx || dy) moves.push({ el, dx, dy });
80
+ }
81
+ for (const { el, dx, dy } of moves) el.style.transform = `translate(${dx}px, ${dy}px)`;
82
+ if (moves.length) void container.offsetWidth;
83
+ for (const { el } of moves) {
84
+ el.setAttribute("data-uix-moving", "");
85
+ el.style.transform = "";
86
+ }
87
+ }
88
+ for (const el of elements) {
89
+ const key = el.getAttribute("data-uix-key");
90
+ if (!was.has(key) && !byKey.get(key)?.exiting) replay(el, "data-uix-entering");
91
+ }
92
+ }, [entries]);
93
+ const deadlines = useRef(/* @__PURE__ */ new Map());
94
+ const exitingKeys = entries.filter((e) => e.exiting).map((e) => e.key);
95
+ const exitingSignature = exitingKeys.join("\n");
96
+ useEffect(() => {
97
+ const container = containerRef.current;
98
+ const now = Date.now();
99
+ for (const key of Array.from(deadlines.current.keys())) if (!exitingKeys.includes(key)) deadlines.current.delete(key);
100
+ for (const key of exitingKeys) if (!deadlines.current.has(key)) deadlines.current.set(key, now + EXIT_FALLBACK_MS);
101
+ if (!container || !exitingKeys.length) return void 0;
102
+ const onEnd = (event) => {
103
+ const el = event.target;
104
+ if (!el.hasAttribute("data-uix-exiting") || el.parentElement !== container) return;
105
+ const key = exitingKeys.find((k) => String(k) === el.getAttribute("data-uix-key"));
106
+ if (key !== void 0) drop([key]);
107
+ };
108
+ container.addEventListener("animationend", onEnd);
109
+ const next = Math.min(...deadlines.current.values());
110
+ const timer = setTimeout(() => {
111
+ const due = Date.now();
112
+ drop([...deadlines.current].filter(([, at]) => at <= due).map(([key]) => key));
113
+ }, Math.max(0, next - now));
114
+ return () => {
115
+ container.removeEventListener("animationend", onEnd);
116
+ clearTimeout(timer);
117
+ };
118
+ }, [exitingSignature]);
119
+ const children = entries.map(({ key, item, exiting: leaving }) => {
120
+ const element = renderItem(item, { exiting: leaving });
121
+ if (!isValidElement(element)) return element;
122
+ const extra = { key, "data-uix-key": String(key) };
123
+ if (leaving) Object.assign(extra, { "data-uix-exiting": "", "aria-hidden": true });
124
+ return cloneElement(element, extra);
125
+ });
126
+ const onTransitionEnd = (event) => {
127
+ const el = event.target;
128
+ if (event.propertyName === "transform" && el.parentElement === containerRef.current) el.removeAttribute("data-uix-moving");
129
+ };
130
+ return createElement(as, { ...props, ref: containerRef, className: cx("uix-motion-list", className), onTransitionEnd }, Children.toArray(children));
131
+ }
132
+ function sameItems(a, b) {
133
+ if (a.length !== b.length) return false;
134
+ for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
135
+ return true;
136
+ }
137
+ function merge(items, getKey, before, exiting) {
138
+ const list = items.map((item) => ({ key: getKey(item), item, exiting: false }));
139
+ before.forEach((e, i) => {
140
+ if (!exiting.has(e.key)) return;
141
+ let at = -1;
142
+ for (let j = i - 1; j >= 0 && at < 0; j -= 1) {
143
+ const k = before[j].key;
144
+ at = list.findIndex((x) => x.key === k);
145
+ }
146
+ list.splice(at + 1, 0, { key: e.key, item: exiting.get(e.key), exiting: true });
147
+ });
148
+ return list;
149
+ }
150
+ function measure(container) {
151
+ const map = /* @__PURE__ */ new Map();
152
+ const origin = container.getBoundingClientRect();
153
+ for (const el of Array.from(container.querySelectorAll(":scope > [data-uix-key]"))) {
154
+ if (el.hasAttribute("data-uix-exiting")) continue;
155
+ const r = el.getBoundingClientRect();
156
+ map.set(el.getAttribute("data-uix-key"), { x: r.left - origin.left, y: r.top - origin.top });
157
+ }
158
+ return map;
159
+ }
160
+ function replay(el, attribute) {
161
+ if (el.hasAttribute(attribute)) {
162
+ el.removeAttribute(attribute);
163
+ void el.offsetWidth;
164
+ }
165
+ el.setAttribute(attribute, "");
166
+ const done = (event) => {
167
+ if (event.target !== el) return;
168
+ el.removeAttribute(attribute);
169
+ el.removeEventListener("animationend", done);
170
+ };
171
+ el.addEventListener("animationend", done);
172
+ }
173
+ export {
174
+ MotionList
175
+ };
@@ -3,6 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { useEffect, useLayoutEffect, useRef, useState } from "react";
4
4
  import { cx } from "../cx.js";
5
5
  import { resolveAnchor, useAnchoredPosition } from "../hooks/useAnchoredPosition.js";
6
+ import { markKeyOpened, watchInputModality } from "../motion.js";
6
7
  const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
7
8
  const PLACING = "data-uix-placing";
8
9
  const isPopoverOpen = (el) => {
@@ -54,6 +55,14 @@ function Popover({
54
55
  el.hidePopover();
55
56
  } : void 0
56
57
  });
58
+ useEffect(() => {
59
+ watchInputModality();
60
+ const el = ref.current;
61
+ if (!el) return;
62
+ const mark = () => markKeyOpened(el);
63
+ el.addEventListener("beforetoggle", mark);
64
+ return () => el.removeEventListener("beforetoggle", mark);
65
+ }, []);
57
66
  useEffect(() => {
58
67
  const el = ref.current;
59
68
  if (!el || !anchor) return;
@@ -192,7 +192,10 @@ function RadialRelationshipGraph({
192
192
  node.id
193
193
  ))
194
194
  ] }) }) }),
195
- legend.length > 0 && /* @__PURE__ */ jsx("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((item) => /* @__PURE__ */ jsx("li", { "data-type": item.id, style: { "--uix-graph-type-color": typeColor.get(item.id) }, children: item.label }, item.id)) }),
195
+ legend.length > 0 && /* @__PURE__ */ jsx("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((item) => /* @__PURE__ */ jsxs("li", { "data-type": item.id, style: { "--uix-graph-type-color": typeColor.get(item.id) }, children: [
196
+ /* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__legend-mark", "aria-hidden": "true" }),
197
+ item.label
198
+ ] }, item.id)) }),
196
199
  showList && /* @__PURE__ */ jsx(EquivalentRelationshipList, { nodes: bounded.nodes, edges: bounded.edges, selectedId, labels, onSelect: select, onExpandNeighbors, onOpenDetails })
197
200
  ] });
198
201
  }