@crewlethq/ui 0.82.0 → 0.83.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 (139) hide show
  1. package/README.md +29 -1
  2. package/dist/AppShell/AccountRow.d.ts +6 -1
  3. package/dist/AppShell/AppShell.d.ts +15 -6
  4. package/dist/AppShell/index.d.ts +1 -1
  5. package/dist/AppShell/index.js +8 -5
  6. package/dist/AppShell/railMotion.d.ts +60 -0
  7. package/dist/AppShell/railShape.d.ts +5 -0
  8. package/dist/{AppShell-F7RID4P4.css → AppShell-U7D2MUUF.css} +177 -56
  9. package/dist/ArrangeList/index.js +3 -2
  10. package/dist/ArtifactBar/index.js +7 -5
  11. package/dist/ArtifactCard/index.js +2 -2
  12. package/dist/AuthLayout/index.js +3 -3
  13. package/dist/AvatarPicker/index.js +7 -6
  14. package/dist/BrandLockup/index.js +2 -2
  15. package/dist/Canvas/index.js +4 -2
  16. package/dist/CanvasBoard/index.js +6 -4
  17. package/dist/CanvasToolbar/index.js +5 -3
  18. package/dist/ChangeMark/index.js +4 -2
  19. package/dist/ChatThread/index.js +2 -2
  20. package/dist/CommandPalette/index.js +3 -2
  21. package/dist/CompactNav/index.js +2 -1
  22. package/dist/ContrastHelp/index.js +3 -2
  23. package/dist/DataGrid/index.js +2 -2
  24. package/dist/DataTable/index.js +4 -3
  25. package/dist/DataView/index.js +7 -6
  26. package/dist/DateTimePicker/index.js +3 -2
  27. package/dist/DeepWorkCard/index.js +2 -2
  28. package/dist/DocTabsEditor/index.js +5 -3
  29. package/dist/DockColumn/DockColumn.d.ts +68 -0
  30. package/dist/DockColumn/index.d.ts +3 -0
  31. package/dist/DockColumn/index.js +6 -0
  32. package/dist/DockColumn-SMJCXHS4.css +61 -0
  33. package/dist/{Editor-7EQWP3RN.js → Editor-5D5Z3LBQ.js} +3 -2
  34. package/dist/EmojiPicker/index.js +5 -3
  35. package/dist/FactList/index.js +4 -2
  36. package/dist/HuePicker/index.js +5 -4
  37. package/dist/LinkInterstitial/index.js +3 -2
  38. package/dist/ListInput/index.js +3 -2
  39. package/dist/MarkdownEditor/index.js +5 -4
  40. package/dist/MediaMatch/index.d.ts +1 -1
  41. package/dist/MediaMatch/index.js +1 -1
  42. package/dist/MediaMatch/useMediaMatch.d.ts +14 -0
  43. package/dist/Menu/index.js +2 -1
  44. package/dist/MergeConflicts/index.js +5 -4
  45. package/dist/MessageActions/index.js +6 -4
  46. package/dist/Modal/index.js +2 -1
  47. package/dist/OpenInAppCard/index.js +2 -2
  48. package/dist/Outline/index.js +2 -1
  49. package/dist/Popover/index.js +2 -1
  50. package/dist/Presence/index.d.ts +2 -0
  51. package/dist/Presence/index.js +4 -0
  52. package/dist/Presence/usePresence.d.ts +109 -0
  53. package/dist/ReactionBar/index.js +6 -4
  54. package/dist/RecordChip/index.js +3 -2
  55. package/dist/Reorder/index.js +2 -1
  56. package/dist/RichEditor/index.js +1 -1
  57. package/dist/SegmentedControl/index.js +4 -3
  58. package/dist/SetupWizard/index.js +2 -2
  59. package/dist/ShareDialog/index.js +4 -3
  60. package/dist/SheetColumnEditor/index.js +6 -5
  61. package/dist/SheetGrid/index.js +8 -6
  62. package/dist/SlideFilmstrip/index.js +5 -3
  63. package/dist/Switcher/index.js +5 -4
  64. package/dist/Tabs/index.js +3 -2
  65. package/dist/ThemeSwitcher/index.js +5 -4
  66. package/dist/TimeRangePicker/index.js +6 -5
  67. package/dist/TimeWindowPicker/index.js +3 -2
  68. package/dist/Tooltip/index.js +3 -1
  69. package/dist/TreeCanvas/index.js +6 -3
  70. package/dist/VersionCompare/index.js +5 -4
  71. package/dist/{chunk-KJR5X4II.js → chunk-22CU7V4J.js} +2 -2
  72. package/dist/{chunk-4RYELYWG.js → chunk-2SVQBQAD.js} +2 -2
  73. package/dist/{chunk-HQFOZJQ4.js → chunk-46FIBJCV.js} +4 -4
  74. package/dist/{chunk-LQRN2XZK.js → chunk-4DEKONVJ.js} +2 -2
  75. package/dist/chunk-5JPOFAVN.js +58 -0
  76. package/dist/{chunk-C7UHDM7Y.js → chunk-5V6GW6HK.js} +1 -1
  77. package/dist/{chunk-XGLMPPDW.js → chunk-7K6LVM5I.js} +1 -1
  78. package/dist/{chunk-FKAJBN6G.js → chunk-7M7WKYOV.js} +3 -3
  79. package/dist/{chunk-A5YKNRG6.js → chunk-7QCSISHM.js} +2 -1
  80. package/dist/{chunk-3QQIGMY3.js → chunk-7ZSEUO5Q.js} +6 -30
  81. package/dist/{chunk-57BFL323.js → chunk-ABRWL5FJ.js} +1 -1
  82. package/dist/{chunk-HFOTRZFU.js → chunk-AQNP3KQU.js} +2 -2
  83. package/dist/{chunk-N2T7Y5KR.js → chunk-AUSFKGKL.js} +1 -1
  84. package/dist/{chunk-GZVAZ3LL.js → chunk-AZYE7NR4.js} +1 -1
  85. package/dist/{chunk-6IOQWMYJ.js → chunk-BN5FEJL5.js} +1 -1
  86. package/dist/{chunk-MPVMB2DV.js → chunk-BVML4UVB.js} +3 -2
  87. package/dist/{chunk-XY4O2XMR.js → chunk-BXGBGYKH.js} +3 -3
  88. package/dist/{chunk-OAHRMR4U.js → chunk-C42XW5YP.js} +1 -1
  89. package/dist/{chunk-HA2PL7PA.js → chunk-DRFOTWJE.js} +1 -1
  90. package/dist/{chunk-SM4P2SHB.js → chunk-EC6EUIAD.js} +7 -4
  91. package/dist/{chunk-AMUXSJ2A.js → chunk-FPU7AA3X.js} +4 -15
  92. package/dist/{chunk-KLAVEJIO.js → chunk-GLKQHN7G.js} +1 -1
  93. package/dist/chunk-HTS5RJ7S.js +6 -0
  94. package/dist/{chunk-GP5TNTZH.js → chunk-ICE3D63E.js} +3 -5
  95. package/dist/{chunk-ISQANI6Q.js → chunk-JLOESTT2.js} +2 -1
  96. package/dist/{chunk-C75WZMXG.js → chunk-K6RWEQ6P.js} +1 -1
  97. package/dist/{chunk-GVPUCEWH.js → chunk-KXWJJWBD.js} +1 -1
  98. package/dist/chunk-L72URIHR.js +36 -0
  99. package/dist/{chunk-2TOGGCDM.js → chunk-LT44RL62.js} +2 -2
  100. package/dist/{chunk-HCUECVZ3.js → chunk-MVKUE4FI.js} +1 -1
  101. package/dist/{chunk-6YBBQAEM.js → chunk-MYAARF4Z.js} +1 -1
  102. package/dist/{chunk-SEKO6P3Y.js → chunk-NCUSI4ZU.js} +1 -1
  103. package/dist/chunk-PCAT2EFB.js +104 -0
  104. package/dist/{chunk-T4IEESXN.js → chunk-PGBKZSSQ.js} +87 -24
  105. package/dist/{chunk-TGCGLKD4.js → chunk-RBQRTGXX.js} +1 -1
  106. package/dist/{chunk-B3X4DHRB.js → chunk-RDIQB5ZE.js} +2 -2
  107. package/dist/{chunk-T7WESRZF.js → chunk-RO5JU6SN.js} +2 -2
  108. package/dist/{chunk-IUWP2LSE.js → chunk-SGMWLUYQ.js} +2 -2
  109. package/dist/{chunk-LSOR77RZ.js → chunk-SHH7UD5U.js} +1 -1
  110. package/dist/{chunk-JV6JM6W6.js → chunk-SNQ7PH3D.js} +1 -1
  111. package/dist/{chunk-MPYRC3GO.js → chunk-SPNTUQBV.js} +2 -2
  112. package/dist/{chunk-YM77TZ7Q.js → chunk-T3S3D4FC.js} +1 -1
  113. package/dist/{chunk-YOJAGKTS.js → chunk-TGGYSQRD.js} +3 -4
  114. package/dist/{chunk-2KJCUCVE.js → chunk-TQKQRS2J.js} +2 -2
  115. package/dist/{chunk-ONNXUS5Y.js → chunk-VB3FVKNI.js} +1 -1
  116. package/dist/{chunk-JHQGNFN3.js → chunk-VONEKR3J.js} +2 -2
  117. package/dist/{chunk-P6F3PE4V.js → chunk-WANKINXG.js} +2 -2
  118. package/dist/{chunk-PXLS6JKL.js → chunk-WMO722J2.js} +1 -1
  119. package/dist/{chunk-SYVQXMLO.js → chunk-XRWHDW6F.js} +4 -4
  120. package/dist/{chunk-WT3B76MG.js → chunk-XTJHMP3W.js} +1 -1
  121. package/dist/{chunk-RTPQDNW3.js → chunk-YJQXESOJ.js} +5 -1
  122. package/dist/{chunk-VGOWSOUA.js → chunk-YXKSUILG.js} +1 -1
  123. package/dist/{chunk-G6ZFSUIH.js → chunk-ZJVLGYE3.js} +2 -2
  124. package/dist/{chunk-BSAU7QRW.js → chunk-ZPTKAYJK.js} +1 -1
  125. package/dist/{chunk-XXDB6KPV.js → chunk-ZXXZESCD.js} +3 -4
  126. package/dist/generated/index.d.ts +2 -0
  127. package/dist/generated/index.js +97 -93
  128. package/dist/index.js +97 -93
  129. package/dist/styles.css +242 -57
  130. package/dist/utils/composedRef.d.ts +39 -0
  131. package/dist/utils/index.d.ts +2 -0
  132. package/dist/utils/index.js +3 -1
  133. package/dist/utils/tokenMs.d.ts +6 -0
  134. package/package.json +5 -5
  135. package/dist/{chunk-IYI6HWKN.js → chunk-CV2LU2T2.js} +1 -1
  136. package/dist/{chunk-FVZPSTL2.js → chunk-G4EHZHKM.js} +1 -1
  137. package/dist/{chunk-FEJANUZK.js → chunk-KBSD476L.js} +0 -0
  138. package/dist/{chunk-2H6YDUR5.js → chunk-QM3432PH.js} +1 -1
  139. /package/dist/{chunk-KLWWNV25.js → chunk-REEZQCML.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { tabId } from './chunk-HCUECVZ3.js';
1
+ import { tabId } from './chunk-MVKUE4FI.js';
2
2
  import { useRoving, tabStop } from './chunk-EGMQURBR.js';
3
3
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
4
4
  import { Count } from './chunk-D2GT3CR4.js';
@@ -1,4 +1,4 @@
1
- import { BrandLockup } from './chunk-GVPUCEWH.js';
1
+ import { BrandLockup } from './chunk-KXWJJWBD.js';
2
2
  import { Card } from './chunk-U2IQNDDR.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './AuthLayout-ODHBUPHQ.css';
@@ -1,3 +1,4 @@
1
+ import { prefersReducedMotion } from './chunk-YJQXESOJ.js';
1
2
  import { announce } from './chunk-2G355KDJ.js';
2
3
  import { useId, useState, useRef, useCallback, useLayoutEffect, useMemo } from 'react';
3
4
 
@@ -24,7 +25,7 @@ function place(lists, key, list, index) {
24
25
  return next;
25
26
  }
26
27
  var SETTLE_MS = 200;
27
- var settleMs = () => typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? 20 : SETTLE_MS;
28
+ var settleMs = () => prefersReducedMotion() ? 20 : SETTLE_MS;
28
29
  var now = () => typeof performance !== "undefined" ? performance.now() : Date.now();
29
30
  function byRows(node, axis) {
30
31
  if (axis === "vertical") return true;
@@ -79,7 +80,7 @@ function useReorderLists({
79
80
  const last = before.current;
80
81
  before.current = /* @__PURE__ */ new Map();
81
82
  if (last.size === 0) return;
82
- if (typeof window === "undefined" || window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
83
+ if (typeof window === "undefined" || prefersReducedMotion()) return;
83
84
  for (const [key, node] of nodes.current) {
84
85
  const was = last.get(key);
85
86
  if (!was) continue;
@@ -1,7 +1,7 @@
1
- import { SegmentedControl } from './chunk-GZVAZ3LL.js';
1
+ import { SegmentedControl } from './chunk-AZYE7NR4.js';
2
2
  import { ArtifactIcon } from './chunk-AVL52EME.js';
3
- import { Tooltip } from './chunk-3QQIGMY3.js';
4
- import { Menu } from './chunk-YOJAGKTS.js';
3
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
4
+ import { Menu } from './chunk-TGGYSQRD.js';
5
5
  import { isApplePlatform, Kbd, ariaKeyshortcuts } from './chunk-CMAZZY2I.js';
6
6
  import { Button } from './chunk-DGXZ635L.js';
7
7
  import { returnFocus } from './chunk-4ITETIGZ.js';
@@ -1,4 +1,4 @@
1
- import { SegmentedControl } from './chunk-GZVAZ3LL.js';
1
+ import { SegmentedControl } from './chunk-AZYE7NR4.js';
2
2
  import { Button } from './chunk-DGXZ635L.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './MergeConflicts-HCXPRQVR.css';
@@ -1,5 +1,5 @@
1
1
  import { Toolbar } from './chunk-NXFTCPF6.js';
2
- import { ShortcutTip } from './chunk-SEKO6P3Y.js';
2
+ import { ShortcutTip } from './chunk-NCUSI4ZU.js';
3
3
  import { IconButton } from './chunk-UAUP6XGK.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './CanvasToolbar-EM5EVZED.css';
@@ -1,3 +1,4 @@
1
+ import { useComposedRef } from './chunk-L72URIHR.js';
1
2
  import { useLayerContainer, viewportBounds, LAYER_GAP, anchorGone, placePopup, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
2
3
  import { usePopupLayer, focusables } from './chunk-TUEM2XIW.js';
3
4
  import { returnFocus } from './chunk-4ITETIGZ.js';
@@ -122,11 +123,13 @@ function Popover({
122
123
  }, [close, open, setOpen]);
123
124
  const triggerEl = trigger(open, toggle);
124
125
  const haspopup = role === "none" ? void 0 : role;
126
+ const anchorRef = useComposedRef(
127
+ anchor,
128
+ layer.insideRef,
129
+ triggerEl.props.ref
130
+ );
125
131
  const anchored = cloneElement(triggerEl, {
126
- ref: (el) => {
127
- anchor.current = el;
128
- layer.insideRef(el);
129
- },
132
+ ref: anchorRef,
130
133
  "aria-expanded": open,
131
134
  "aria-haspopup": triggerEl.props["aria-haspopup"] ?? haspopup,
132
135
  "aria-controls": open ? panelId : void 0
@@ -1,9 +1,10 @@
1
1
  import { useTreeState, useMeasuredSizes, layoutForest, treeAncestors, useLayoutAnchor, treeExpandable, layoutConnectors, treeItemAction, treeStep, treePosInSet, treeSetSize, treeLevel, placeGroups } from './chunk-MY374UUD.js';
2
- import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-SEKO6P3Y.js';
2
+ import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-NCUSI4ZU.js';
3
+ import { useMediaMatch, REDUCED_MOTION_QUERY } from './chunk-YJQXESOJ.js';
3
4
  import { focusables } from './chunk-TUEM2XIW.js';
4
5
  import { cx } from './chunk-ODEQTPFM.js';
5
6
  import './TreeCanvas-5FPK4CII.css';
6
- import { useState, useRef, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useId, useSyncExternalStore } from 'react';
7
+ import { useState, useRef, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useId } from 'react';
7
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
9
 
9
10
  var ENTRANCE_STEP_MS = 60;
@@ -14,19 +15,7 @@ function entranceOrder(layout) {
14
15
  return [...layout.nodes].sort((a, b) => row(a) - row(b) || a.x - b.x || (a.id < b.id ? -1 : 1)).map((one) => one.id);
15
16
  }
16
17
  function useStillness() {
17
- const query = "(prefers-reduced-motion: reduce)";
18
- const subscribe = useCallback((notify) => {
19
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
20
- };
21
- const list = window.matchMedia(query);
22
- list.addEventListener("change", notify);
23
- return () => list.removeEventListener("change", notify);
24
- }, []);
25
- const read = useCallback(
26
- () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false,
27
- []
28
- );
29
- return useSyncExternalStore(subscribe, read, () => false);
18
+ return useMediaMatch(REDUCED_MOTION_QUERY);
30
19
  }
31
20
  function useEntrance(layout, still) {
32
21
  const [shown, setShown] = useState(null);
@@ -1,4 +1,4 @@
1
- import { useReorder } from './chunk-MPVMB2DV.js';
1
+ import { useReorder } from './chunk-BVML4UVB.js';
2
2
  import { FormField, Textarea } from './chunk-O7N6W52M.js';
3
3
  import { characterCountState, CharacterCount, countCharacters } from './chunk-PGCLHYVP.js';
4
4
  import { Kbd } from './chunk-CMAZZY2I.js';
@@ -0,0 +1,6 @@
1
+ // src/utils/tokenMs.ts
2
+ function tokenMs(value) {
3
+ return Number.parseFloat(value);
4
+ }
5
+
6
+ export { tokenMs };
@@ -1,4 +1,5 @@
1
1
  import { LockedLabel } from './chunk-TEV5REGB.js';
2
+ import { tokenMs } from './chunk-HTS5RJ7S.js';
2
3
  import { LAYER_GAP, useLayerContainer, viewportBounds, anchorGone, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
3
4
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
4
5
  import { usePopupLayer } from './chunk-TUEM2XIW.js';
@@ -126,11 +127,8 @@ function placeFlyout(tile, railEnd, size, bounds, lift = 0) {
126
127
  const left = Math.max(bounds.x, Math.min(railEnd + LAYER_GAP, maxLeft));
127
128
  return { left, top };
128
129
  }
129
- function ms(value) {
130
- return Number.parseFloat(value);
131
- }
132
- var OPEN_DELAY = ms(motion.duration.fast);
133
- var CLOSE_DELAY = ms(motion.duration.moderate);
130
+ var OPEN_DELAY = tokenMs(motion.duration.fast);
131
+ var CLOSE_DELAY = tokenMs(motion.duration.moderate);
134
132
  function CompactNavGroup({ label, icon, links, renderLink, className }) {
135
133
  const [open, setOpen] = useState(false);
136
134
  const [place, setPlace] = useState(null);
@@ -5,5 +5,6 @@ var RailShapeContext = createContext("full");
5
5
  function useRailShape() {
6
6
  return useContext(RailShapeContext);
7
7
  }
8
+ var RailLeavingContext = createContext(false);
8
9
 
9
- export { RailShapeContext, useRailShape };
10
+ export { RailLeavingContext, RailShapeContext, useRailShape };
@@ -1,6 +1,6 @@
1
1
  import { Stepper } from './chunk-RJWO2PC5.js';
2
2
  import { PageHeader } from './chunk-FPDIHEM4.js';
3
- import { useMediaMatch } from './chunk-RTPQDNW3.js';
3
+ import { useMediaMatch } from './chunk-YJQXESOJ.js';
4
4
  import { Disclosure } from './chunk-LVJGN5II.js';
5
5
  import { useHeadingLevel, nextHeadingLevel, headingTag, HeadingLevelProvider } from './chunk-PQADV6P6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,4 +1,4 @@
1
- import { useRailShape } from './chunk-ISQANI6Q.js';
1
+ import { useRailShape } from './chunk-JLOESTT2.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './BrandLockup-JKGXFCZF.css';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -0,0 +1,36 @@
1
+ import { useRef } from 'react';
2
+
3
+ // src/utils/composedRef.ts
4
+ function attachRef(ref, element) {
5
+ if (typeof ref === "function") {
6
+ const release = ref(element);
7
+ return typeof release === "function" ? release : () => void ref(null);
8
+ }
9
+ if (!ref) return () => {
10
+ };
11
+ const box = ref;
12
+ box.current = element;
13
+ return () => {
14
+ box.current = null;
15
+ };
16
+ }
17
+ function composeRefs(...refs) {
18
+ return (element) => {
19
+ const releases = refs.map((ref) => attachRef(ref, element));
20
+ return () => {
21
+ for (const release of releases) release();
22
+ };
23
+ };
24
+ }
25
+ function sameRefs(a, b) {
26
+ return a.length === b.length && a.every((ref, index) => ref === b[index]);
27
+ }
28
+ function useComposedRef(...refs) {
29
+ const joined = useRef(null);
30
+ if (!joined.current || !sameRefs(joined.current.refs, refs)) {
31
+ joined.current = { refs, callback: composeRefs(...refs) };
32
+ }
33
+ return joined.current.callback;
34
+ }
35
+
36
+ export { attachRef, composeRefs, useComposedRef };
@@ -1,7 +1,7 @@
1
1
  import { heldHint } from './chunk-TDFLCUBE.js';
2
- import { emojiName } from './chunk-MPYRC3GO.js';
2
+ import { emojiName } from './chunk-SPNTUQBV.js';
3
3
  import { Toolbar } from './chunk-NXFTCPF6.js';
4
- import { Tooltip } from './chunk-3QQIGMY3.js';
4
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
5
5
  import { IconButton } from './chunk-UAUP6XGK.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './ChatScale-L4SIHSKL.css';
@@ -1,6 +1,6 @@
1
1
  import { useRoving, tabStop } from './chunk-EGMQURBR.js';
2
2
  import { StatusDot } from './chunk-CYQBDZ6M.js';
3
- import { Menu } from './chunk-YOJAGKTS.js';
3
+ import { Menu } from './chunk-TGGYSQRD.js';
4
4
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
5
5
  import { Count } from './chunk-D2GT3CR4.js';
6
6
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
@@ -1,4 +1,4 @@
1
- import { ConfirmModal } from './chunk-XXDB6KPV.js';
1
+ import { ConfirmModal } from './chunk-ZXXZESCD.js';
2
2
  import { InlineCode } from './chunk-PLL7ZJHY.js';
3
3
  import { Callout } from './chunk-BPCY7ZID.js';
4
4
  import './LinkInterstitial-ET4MSVSV.css';
@@ -1,5 +1,5 @@
1
1
  import { LayerNodeBridge } from './chunk-LM3ISVJA.js';
2
- import { Tooltip } from './chunk-3QQIGMY3.js';
2
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
3
3
  import { Kbd } from './chunk-CMAZZY2I.js';
4
4
  import { Button } from './chunk-DGXZ635L.js';
5
5
  import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-OMV5W53A.js';
@@ -0,0 +1,104 @@
1
+ import { useMediaMatch, REDUCED_MOTION_QUERY } from './chunk-YJQXESOJ.js';
2
+ import { tokenMs } from './chunk-HTS5RJ7S.js';
3
+ import { returnFocus } from './chunk-4ITETIGZ.js';
4
+ import { useState, useLayoutEffect } from 'react';
5
+ import { motion } from '@crewlethq/tokens';
6
+
7
+ var MOTION_MARGIN_MS = tokenMs(motion.duration.fast);
8
+ function transitionProperty(animation) {
9
+ const property = animation.transitionProperty;
10
+ return typeof property === "string" ? property : null;
11
+ }
12
+ function animationName(animation) {
13
+ const name = animation.animationName;
14
+ return typeof name === "string" ? name : null;
15
+ }
16
+ function targetOf(animation) {
17
+ const effect = animation.effect;
18
+ return effect && "target" in effect ? effect.target : null;
19
+ }
20
+ function runningMotion(element, owned = {}) {
21
+ if (typeof element.getAnimations !== "function") return [];
22
+ const names = owned.animations ?? [];
23
+ return element.getAnimations({ subtree: names.length > 0 }).filter((animation) => {
24
+ if (animation.playState !== "running") return false;
25
+ const end = animation.effect?.getComputedTiming().endTime;
26
+ if (typeof end !== "number" || !Number.isFinite(end)) return false;
27
+ const property = transitionProperty(animation);
28
+ if (property !== null) {
29
+ return targetOf(animation) === element && (owned.transitions?.includes(property) ?? true);
30
+ }
31
+ const name = animationName(animation);
32
+ return name !== null && names.includes(name);
33
+ });
34
+ }
35
+ function remainingMs(running) {
36
+ return Math.max(
37
+ 0,
38
+ ...running.map((animation) => {
39
+ const end = Number(animation.effect?.getComputedTiming().endTime ?? 0);
40
+ const now = typeof animation.currentTime === "number" ? animation.currentTime : 0;
41
+ return end - now;
42
+ })
43
+ );
44
+ }
45
+ function afterMotion(element, done, owned = {}) {
46
+ let live = true;
47
+ let bound;
48
+ const stop = () => {
49
+ live = false;
50
+ if (bound !== void 0) clearTimeout(bound);
51
+ };
52
+ const finish = () => {
53
+ if (!live) return;
54
+ stop();
55
+ done();
56
+ };
57
+ const wait = () => {
58
+ if (!live) return;
59
+ const running = element ? runningMotion(element, owned) : [];
60
+ if (running.length === 0) {
61
+ finish();
62
+ return;
63
+ }
64
+ if (bound !== void 0) clearTimeout(bound);
65
+ bound = setTimeout(finish, remainingMs(running) + MOTION_MARGIN_MS);
66
+ void Promise.allSettled(running.map((animation) => animation.finished)).then(wait);
67
+ };
68
+ wait();
69
+ return stop;
70
+ }
71
+ function releaseFocus(container, target) {
72
+ const held = container?.ownerDocument.activeElement;
73
+ if (!container || !(held instanceof HTMLElement) || !container.contains(held)) return;
74
+ if (target?.isConnected && !container.contains(target) && returnFocus(target)) return;
75
+ held.blur();
76
+ }
77
+ function usePresence(shown, motion, { transitions, animations, instant = false } = {}) {
78
+ const still = useMediaMatch(REDUCED_MOTION_QUERY) || instant;
79
+ const [state, setState] = useState({ shown, leaving: false, entering: false, returning: false });
80
+ let current = state;
81
+ if (state.shown !== shown) {
82
+ current = { shown, leaving: !shown && !still, entering: shown && !still, returning: shown && !still && state.leaving };
83
+ }
84
+ if (still && (current.leaving || current.entering)) current = { ...current, leaving: false, entering: false, returning: false };
85
+ if (current !== state) setState(current);
86
+ const { leaving, entering, returning } = current;
87
+ const moving = leaving || entering;
88
+ const ownTransitions = transitions?.join(" ");
89
+ const ownAnimations = animations?.join(" ");
90
+ useLayoutEffect(() => {
91
+ if (!moving) return void 0;
92
+ return afterMotion(
93
+ motion.current,
94
+ () => setState((now) => now.shown === shown ? { ...now, leaving: false, entering: false, returning: false } : now),
95
+ {
96
+ transitions: ownTransitions === void 0 ? void 0 : ownTransitions.split(" ").filter(Boolean),
97
+ animations: ownAnimations === void 0 ? void 0 : ownAnimations.split(" ").filter(Boolean)
98
+ }
99
+ );
100
+ }, [moving, shown, motion, ownTransitions, ownAnimations]);
101
+ return { present: shown || leaving, leaving, entering, returning };
102
+ }
103
+
104
+ export { afterMotion, releaseFocus, runningMotion, usePresence };
@@ -1,7 +1,8 @@
1
- import { useMediaMatch } from './chunk-RTPQDNW3.js';
2
- import { useRailShape, RailShapeContext } from './chunk-ISQANI6Q.js';
3
- import { Tooltip } from './chunk-3QQIGMY3.js';
4
- import { Menu } from './chunk-YOJAGKTS.js';
1
+ import { releaseFocus, usePresence } from './chunk-PCAT2EFB.js';
2
+ import { useRailShape, RailShapeContext, RailLeavingContext } from './chunk-JLOESTT2.js';
3
+ import { useMediaMatch } from './chunk-YJQXESOJ.js';
4
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
5
+ import { Menu } from './chunk-TGGYSQRD.js';
5
6
  import { PeekContext, AsideContext, ResizeHandle, clampSize } from './chunk-PIYJNCN7.js';
6
7
  import { isApplePlatform, ariaKeyshortcuts, Kbd } from './chunk-CMAZZY2I.js';
7
8
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
@@ -11,11 +12,11 @@ import { IconButton } from './chunk-UAUP6XGK.js';
11
12
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
12
13
  import { cx } from './chunk-ODEQTPFM.js';
13
14
  import './HitArea-QUOS6ZDJ.css';
14
- import './AppShell-F7RID4P4.css';
15
+ import './AppShell-U7D2MUUF.css';
15
16
  import './ResizeHandle-2UNSZ4ZQ.css';
16
17
  import { createContext, forwardRef, useContext, useSyncExternalStore, useCallback, useId, useState, useRef, useEffect, useLayoutEffect } from 'react';
17
18
  import { breakpoint } from '@crewlethq/tokens';
18
- import { ChevronUpGlyph, ChevronsUpDownGlyph, ChevronRightGlyph, ChevronsRightGlyph, ChevronsLeftGlyph, MenuGlyph } from '@crewlethq/icons/glyphs';
19
+ import { ChevronUpGlyph, ChevronsUpDownGlyph, ChevronRightGlyph, PlusGlyph, MinusGlyph, MenuGlyph } from '@crewlethq/icons/glyphs';
19
20
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
20
21
 
21
22
  function AccountRow({
@@ -183,6 +184,22 @@ function useScreenBelow(width) {
183
184
  const measured = useSyncExternalStore(store ? store.subscribe : noSubscription, read, () => null);
184
185
  return measured ?? window2;
185
186
  }
187
+ var RAIL_MOTION = {
188
+ transitions: ["width"],
189
+ animations: ["crewlet-app-shell-rail-unfold", "crewlet-app-shell-rail-settle"]
190
+ };
191
+ function useRailMotion(target, moves, rail) {
192
+ const [moved, setMoved] = useState(moves);
193
+ if (moved !== moves) setMoved(moves);
194
+ const instant = !moves || !moved;
195
+ const full = usePresence(target === "full", rail, { ...RAIL_MOTION, instant });
196
+ const compact = usePresence(target === "compact" && !full.leaving, rail, { ...RAIL_MOTION, instant });
197
+ let motion = null;
198
+ if (full.leaving) motion = "fold";
199
+ else if (full.entering) motion = full.returning ? "reverse" : "unfold";
200
+ else if (compact.entering) motion = "folded";
201
+ return { drawn: full.present ? "full" : "compact", motion, leaving: full.leaving };
202
+ }
186
203
  var APP_SHELL_ASIDE_WIDTH = 420;
187
204
  var NARROW = `(width < ${breakpoint.shell})`;
188
205
  var AppShellContext = createContext(null);
@@ -246,16 +263,29 @@ function AppShell({
246
263
  },
247
264
  [mainRef]
248
265
  );
266
+ const railMoving = useRef(false);
267
+ const heldMeasures = useRef(/* @__PURE__ */ new Set());
268
+ const unlessRailMoving = useCallback(
269
+ (measure) => () => {
270
+ if (railMoving.current) heldMeasures.current.add(measure);
271
+ else measure();
272
+ },
273
+ []
274
+ );
249
275
  const [gutter, setGutter] = useState(0);
250
276
  useLayoutEffect(() => {
251
277
  if (!scroller) return void 0;
252
278
  const measure = () => setGutter(Math.max(0, scroller.offsetWidth - scroller.clientWidth));
253
279
  measure();
254
280
  if (typeof ResizeObserver === "undefined") return void 0;
255
- const observer = new ResizeObserver(measure);
281
+ const observer = new ResizeObserver(unlessRailMoving(measure));
256
282
  observer.observe(scroller);
257
- return () => observer.disconnect();
258
- }, [scroller]);
283
+ const held = heldMeasures.current;
284
+ return () => {
285
+ observer.disconnect();
286
+ held.delete(measure);
287
+ };
288
+ }, [scroller, unlessRailMoving]);
259
289
  const root = useRef(null);
260
290
  const sheet = useRef(null);
261
291
  const asideColumn = hasAside && asideShape === "column";
@@ -270,11 +300,15 @@ function AppShell({
270
300
  const measure = () => setOccupied(Math.max(0, Math.round(frame.getBoundingClientRect().right - page.getBoundingClientRect().right)));
271
301
  measure();
272
302
  if (typeof ResizeObserver === "undefined") return void 0;
273
- const observer = new ResizeObserver(measure);
303
+ const observer = new ResizeObserver(unlessRailMoving(measure));
274
304
  observer.observe(page);
275
305
  observer.observe(frame);
276
- return () => observer.disconnect();
277
- }, [asideColumn]);
306
+ const held = heldMeasures.current;
307
+ return () => {
308
+ observer.disconnect();
309
+ held.delete(measure);
310
+ };
311
+ }, [asideColumn, unlessRailMoving]);
278
312
  const content = useRef(null);
279
313
  const [screenWidth] = useState(createScreenWidthStore);
280
314
  useLayoutEffect(() => {
@@ -283,16 +317,44 @@ function AppShell({
283
317
  const measure = () => screenWidth.set(contentInlineSize(column));
284
318
  measure();
285
319
  if (typeof ResizeObserver === "undefined") return void 0;
286
- const observer = new ResizeObserver(measure);
320
+ const observer = new ResizeObserver(unlessRailMoving(measure));
287
321
  observer.observe(column);
322
+ const held = heldMeasures.current;
288
323
  return () => {
289
324
  observer.disconnect();
325
+ held.delete(measure);
290
326
  screenWidth.set(null);
291
327
  };
292
- }, [screenWidth]);
328
+ }, [screenWidth, unlessRailMoving]);
293
329
  const hasRail = sidebar !== void 0 && sidebar !== null;
294
- const railShape = hasRail && railChoice === "compact" && !narrow ? "compact" : "full";
330
+ const railTarget = hasRail && railChoice === "compact" && !narrow ? "compact" : "full";
331
+ const { drawn: railShape, motion: railMotion, leaving: railLeaving } = useRailMotion(railTarget, hasRail && !narrow, rail);
295
332
  const foldable = hasRail && onRailChange !== void 0 && !narrow;
333
+ railMoving.current = railMotion !== null;
334
+ useLayoutEffect(() => {
335
+ if (railMotion !== null) return;
336
+ const held = [...heldMeasures.current];
337
+ heldMeasures.current.clear();
338
+ for (const measure of held) measure();
339
+ }, [railMotion]);
340
+ const refocusFolded = useRef(false);
341
+ useLayoutEffect(() => {
342
+ const aside2 = rail.current;
343
+ if (!aside2) return;
344
+ if (railLeaving) {
345
+ const held2 = aside2.ownerDocument.activeElement;
346
+ const leavingPart = held2 instanceof HTMLElement ? held2.closest("[inert]") : null;
347
+ if (!leavingPart || !aside2.contains(leavingPart)) return;
348
+ const live = focusables(aside2).find((element) => !element.closest("[inert]")) ?? null;
349
+ releaseFocus(leavingPart, live);
350
+ refocusFolded.current = live === null;
351
+ return;
352
+ }
353
+ if (!refocusFolded.current) return;
354
+ refocusFolded.current = false;
355
+ const held = aside2.ownerDocument.activeElement;
356
+ if (held === null || held === aside2.ownerDocument.body) focusables(aside2)[0]?.focus();
357
+ }, [railLeaving]);
296
358
  const shell = {
297
359
  narrow,
298
360
  drawerOpen,
@@ -323,6 +385,7 @@ function AppShell({
323
385
  "data-aside": hasAside ? asideShape : void 0,
324
386
  "data-peek": hasPeek ? peekShape : void 0,
325
387
  "data-rail": hasRail ? railShape : void 0,
388
+ "data-rail-motion": railMotion ?? void 0,
326
389
  style: {
327
390
  ...style,
328
391
  ["--crewlet-app-shell-gutter"]: `${gutter}px`,
@@ -362,8 +425,8 @@ function AppShell({
362
425
  "aria-modal": drawerOpen || void 0,
363
426
  "aria-label": drawerOpen ? toggleLabel : void 0,
364
427
  children: [
365
- foldable ? /* @__PURE__ */ jsx(RailFold, { rail: railShape, onRailChange, keys: railFoldKeys, labels: railFoldLabels, railId }) : null,
366
- /* @__PURE__ */ jsx(RailShapeContext.Provider, { value: railShape, children: sidebar })
428
+ foldable ? /* @__PURE__ */ jsx(RailFold, { rail: railTarget, onRailChange, keys: railFoldKeys, labels: railFoldLabels, railId }) : null,
429
+ /* @__PURE__ */ jsx(RailShapeContext.Provider, { value: railShape, children: /* @__PURE__ */ jsx(RailLeavingContext.Provider, { value: railLeaving, children: sidebar }) })
367
430
  ]
368
431
  }
369
432
  ) : null,
@@ -556,8 +619,9 @@ function RailFold({
556
619
  label,
557
620
  size: "sm",
558
621
  variant: "ghost",
559
- icon: compact ? /* @__PURE__ */ jsx(ChevronsRightGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(ChevronsLeftGlyph, { size: "sm" }),
622
+ icon: compact ? /* @__PURE__ */ jsx(PlusGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(MinusGlyph, { size: "sm" }),
560
623
  "aria-controls": railId,
624
+ "aria-expanded": !compact,
561
625
  "aria-keyshortcuts": keys ? ariaKeyshortcuts(keys, apple) : void 0,
562
626
  onClick: () => onRailChange?.(compact ? "full" : "compact")
563
627
  }
@@ -567,20 +631,19 @@ function RailFold({
567
631
  }
568
632
  function AppShellRail({ header, search, status, footer, className, children }) {
569
633
  const compact = useRailShape() === "compact";
570
- const statusSlot = status ? /* @__PURE__ */ jsx("div", { className: "crewlet-app-shell__rail-status", children: status }) : null;
634
+ const leaving = useContext(RailLeavingContext) || void 0;
635
+ const statusSlot = status ? /* @__PURE__ */ jsx("div", { className: "crewlet-app-shell__rail-status", inert: leaving, children: status }) : null;
571
636
  return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-app-shell__rail-inner", className), children: [
572
637
  header || status && !compact ? /* @__PURE__ */ jsxs("div", { className: "crewlet-app-shell__rail-head", children: [
573
638
  header,
574
639
  compact ? null : statusSlot
575
640
  ] }) : null,
576
- /* @__PURE__ */ jsxs("div", { className: "crewlet-app-shell__rail-body", children: [
641
+ compact ? statusSlot : null,
642
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-app-shell__rail-body", inert: leaving, children: [
577
643
  search && !compact ? /* @__PURE__ */ jsx("div", { className: "crewlet-app-shell__rail-search", children: search }) : null,
578
644
  children
579
645
  ] }),
580
- footer || status && compact ? /* @__PURE__ */ jsxs("div", { className: "crewlet-app-shell__rail-foot", children: [
581
- compact ? statusSlot : null,
582
- footer
583
- ] }) : null
646
+ footer ? /* @__PURE__ */ jsx("div", { className: "crewlet-app-shell__rail-foot", inert: leaving, children: footer }) : null
584
647
  ] });
585
648
  }
586
649
  function countWords(count) {
@@ -1,5 +1,5 @@
1
1
  import { diffLines, diffStat, collapseDiff, DiffSummary, DiffView } from './chunk-AOFVXE6V.js';
2
- import { SegmentedControl } from './chunk-GZVAZ3LL.js';
2
+ import { SegmentedControl } from './chunk-AZYE7NR4.js';
3
3
  import { EmptyState } from './chunk-PPUR46MK.js';
4
4
  import { useHeadingLevel, headingTag, nextHeadingLevel, HeadingLevelProvider } from './chunk-PQADV6P6.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,5 +1,5 @@
1
- import { useReorder } from './chunk-MPVMB2DV.js';
2
- import { Menu } from './chunk-YOJAGKTS.js';
1
+ import { useReorder } from './chunk-BVML4UVB.js';
2
+ import { Menu } from './chunk-TGGYSQRD.js';
3
3
  import { Input } from './chunk-O7N6W52M.js';
4
4
  import { IconButton } from './chunk-UAUP6XGK.js';
5
5
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
@@ -1,6 +1,6 @@
1
1
  import { SlideStage } from './chunk-O6EV6GKI.js';
2
- import { useReorder } from './chunk-MPVMB2DV.js';
3
- import { Menu } from './chunk-YOJAGKTS.js';
2
+ import { useReorder } from './chunk-BVML4UVB.js';
3
+ import { Menu } from './chunk-TGGYSQRD.js';
4
4
  import { Kbd, isApplePlatform } from './chunk-CMAZZY2I.js';
5
5
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,9 +1,9 @@
1
1
  import { Select } from './chunk-3IWZVEXA.js';
2
2
  import { SHEET_LABELS, SHEET_COLUMN_TYPES, optionHue, retypeColumn } from './chunk-LFSIKGRQ.js';
3
- import { HueSwatch } from './chunk-LSOR77RZ.js';
3
+ import { HueSwatch } from './chunk-SHH7UD5U.js';
4
4
  import { NODE_HUES, NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
5
5
  import { Checkbox } from './chunk-YQ7Q52XU.js';
6
- import { Menu } from './chunk-YOJAGKTS.js';
6
+ import { Menu } from './chunk-TGGYSQRD.js';
7
7
  import { FormField, Input } from './chunk-O7N6W52M.js';
8
8
  import { Kbd } from './chunk-CMAZZY2I.js';
9
9
  import { Button } from './chunk-DGXZ635L.js';
@@ -1,5 +1,5 @@
1
1
  import { NODE_HUES, NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
2
- import { SegmentedControl } from './chunk-GZVAZ3LL.js';
2
+ import { SegmentedControl } from './chunk-AZYE7NR4.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
@@ -1,4 +1,4 @@
1
- import { Tooltip } from './chunk-3QQIGMY3.js';
1
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
2
2
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './FactList-QEOHLHX3.css';
@@ -1,5 +1,5 @@
1
- import { Popover } from './chunk-SM4P2SHB.js';
2
- import { Tooltip } from './chunk-3QQIGMY3.js';
1
+ import { Popover } from './chunk-EC6EUIAD.js';
2
+ import { Tooltip } from './chunk-7ZSEUO5Q.js';
3
3
  import { Input } from './chunk-O7N6W52M.js';
4
4
  import { isComposing } from './chunk-TUEM2XIW.js';
5
5
  import './EmojiPicker-FMWYN2WX.css';
@@ -1,6 +1,6 @@
1
1
  import { Select } from './chunk-3IWZVEXA.js';
2
2
  import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-EE3DJMSQ.js';
3
- import { Popover } from './chunk-SM4P2SHB.js';
3
+ import { Popover } from './chunk-EC6EUIAD.js';
4
4
  import { Input } from './chunk-O7N6W52M.js';
5
5
  import { Button } from './chunk-DGXZ635L.js';
6
6
  import { isComposing } from './chunk-TUEM2XIW.js';