@crewlethq/ui 0.23.0 → 0.25.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 (175) hide show
  1. package/README.md +75 -3
  2. package/dist/ArrangeList/index.js +2 -2
  3. package/dist/ArtifactCard/ArtifactCard.d.ts +3 -2
  4. package/dist/ArtifactCard/index.js +1 -1
  5. package/dist/ArtifactCover/ArtifactCover.d.ts +37 -0
  6. package/dist/ArtifactCover/DashboardCover.d.ts +46 -0
  7. package/dist/ArtifactCover/index.d.ts +6 -0
  8. package/dist/ArtifactCover/index.js +14 -0
  9. package/dist/ArtifactCover-D4MBEJ5H.css +67 -0
  10. package/dist/ArtifactIcon/ArtifactIcon.d.ts +29 -0
  11. package/dist/ArtifactIcon/index.d.ts +2 -0
  12. package/dist/ArtifactIcon/index.js +13 -0
  13. package/dist/AvatarPicker/index.js +6 -6
  14. package/dist/Canvas/Canvas.d.ts +13 -2
  15. package/dist/Canvas/index.js +1 -1
  16. package/dist/CanvasBoard/CanvasBoard.d.ts +117 -0
  17. package/dist/CanvasBoard/budget.d.ts +38 -0
  18. package/dist/CanvasBoard/index.d.ts +5 -0
  19. package/dist/CanvasBoard/index.js +10 -0
  20. package/dist/CanvasBoard-ZLPDINSM.css +236 -0
  21. package/dist/CanvasSchematic/CanvasSchematic.d.ts +31 -0
  22. package/dist/CanvasSchematic/index.d.ts +3 -0
  23. package/dist/CanvasSchematic/index.js +2 -0
  24. package/dist/CanvasSchematic-PLB3N46J.css +36 -0
  25. package/dist/ChangeMark/index.js +3 -3
  26. package/dist/CharacterPicker/index.js +2 -2
  27. package/dist/Checkbox/Checkbox.d.ts +6 -0
  28. package/dist/Checkbox/index.js +1 -1
  29. package/dist/{Checkbox-KT7RS6QQ.css → Checkbox-5UORUG3F.css} +16 -0
  30. package/dist/CommentThread/index.js +2 -2
  31. package/dist/DashboardCover-RMINBODB.css +143 -0
  32. package/dist/DataTable/index.js +3 -3
  33. package/dist/DataView/index.js +5 -5
  34. package/dist/DatasetSource/DatasetSource.d.ts +83 -0
  35. package/dist/DatasetSource/index.d.ts +3 -0
  36. package/dist/DatasetSource/index.js +7 -0
  37. package/dist/DatasetSource-47LBDMPR.css +129 -0
  38. package/dist/DocTabsEditor/DocTabsEditor.d.ts +60 -0
  39. package/dist/DocTabsEditor/index.d.ts +3 -0
  40. package/dist/DocTabsEditor/index.js +9 -0
  41. package/dist/DocTabsEditor-RCOWHX5J.css +78 -0
  42. package/dist/DownloadButton/index.js +2 -2
  43. package/dist/HuePicker/index.js +4 -4
  44. package/dist/LinkInterstitial/index.js +2 -2
  45. package/dist/MarkdownEditor/index.js +5 -5
  46. package/dist/MergeConflicts/MergeConflicts.d.ts +51 -0
  47. package/dist/MergeConflicts/index.d.ts +3 -0
  48. package/dist/MergeConflicts/index.js +9 -0
  49. package/dist/MergeConflicts-O44ESH4T.css +77 -0
  50. package/dist/Meter/index.js +1 -1
  51. package/dist/{Meter-5VCSFMZW.css → Meter-ZZRFUEOH.css} +15 -0
  52. package/dist/ObjectHeader/ObjectHeader.d.ts +7 -1
  53. package/dist/ObjectHeader/index.js +1 -1
  54. package/dist/{ObjectHeader-UNVYM2KD.css → ObjectHeader-D7GU7QNI.css} +15 -0
  55. package/dist/PeopleRail/index.js +3 -3
  56. package/dist/PresenceModel/index.d.ts +1 -1
  57. package/dist/PresenceModel/index.js +1 -1
  58. package/dist/PresenceModel/presence.d.ts +10 -2
  59. package/dist/PresenceStack/index.js +3 -3
  60. package/dist/PresenterView/PresenterView.d.ts +52 -0
  61. package/dist/PresenterView/index.d.ts +3 -0
  62. package/dist/PresenterView/index.js +8 -0
  63. package/dist/PresenterView-T2C6ZZ3N.css +103 -0
  64. package/dist/Section/index.js +1 -1
  65. package/dist/{Section-QRUPRIQ2.css → Section-QR3ILQVK.css} +4 -1
  66. package/dist/SegmentedControl/SegmentedControl.d.ts +17 -0
  67. package/dist/SegmentedControl/index.js +4 -4
  68. package/dist/{SegmentedControl-PKBLJVSA.css → SegmentedControl-FLI45IOW.css} +13 -0
  69. package/dist/ShareDialog/index.js +3 -3
  70. package/dist/SheetGrid/SheetGrid.d.ts +24 -2
  71. package/dist/SheetGrid/index.js +11 -7
  72. package/dist/{SheetGrid-4HOXDVIB.css → SheetGrid-J3TKKXZL.css} +87 -17
  73. package/dist/SheetModel/edits.d.ts +7 -1
  74. package/dist/SheetModel/index.js +2 -2
  75. package/dist/SheetModel/labels.d.ts +9 -0
  76. package/dist/SheetModel/types.d.ts +6 -0
  77. package/dist/SlideCompare/SlideCompare.d.ts +52 -0
  78. package/dist/SlideCompare/index.d.ts +3 -0
  79. package/dist/SlideCompare/index.js +7 -0
  80. package/dist/SlideCompare-MGM3U2ME.css +80 -0
  81. package/dist/SlideFilmstrip/SlideFilmstrip.d.ts +50 -0
  82. package/dist/SlideFilmstrip/index.d.ts +3 -0
  83. package/dist/SlideFilmstrip/index.js +8 -0
  84. package/dist/SlideFilmstrip-BCLNAHFX.css +108 -0
  85. package/dist/SlideGrid/SlideGrid.d.ts +32 -0
  86. package/dist/SlideGrid/index.d.ts +3 -0
  87. package/dist/SlideGrid/index.js +5 -0
  88. package/dist/SlideGrid-RT6QEQEE.css +82 -0
  89. package/dist/SlideStage/SlideStage.d.ts +47 -0
  90. package/dist/SlideStage/index.d.ts +5 -0
  91. package/dist/SlideStage/index.js +4 -0
  92. package/dist/SlideStage/useSlideKeys.d.ts +21 -0
  93. package/dist/SlideStage-XIOTMMRU.css +32 -0
  94. package/dist/Switcher/index.js +2 -2
  95. package/dist/TableCells/index.js +2 -2
  96. package/dist/Tabs/index.js +2 -2
  97. package/dist/Tabs/roving.d.ts +1 -0
  98. package/dist/TagGroup/TagGroup.d.ts +16 -1
  99. package/dist/TagGroup/index.js +1 -1
  100. package/dist/{TagGroup-BCQZD7ZD.css → TagGroup-NAXTJHDS.css} +22 -0
  101. package/dist/ThemeGallery/index.js +2 -2
  102. package/dist/ThemeSwitcher/index.js +5 -5
  103. package/dist/TreeCanvas/index.js +2 -2
  104. package/dist/VersionCompare/VersionCompare.d.ts +8 -1
  105. package/dist/VersionCompare/index.js +5 -5
  106. package/dist/VersionTimeline/index.js +1 -1
  107. package/dist/{VersionTimeline-EBJ6MIPJ.css → VersionTimeline-6KRXEEOO.css} +7 -7
  108. package/dist/WidgetFrame/WidgetFrame.d.ts +73 -0
  109. package/dist/WidgetFrame/index.d.ts +3 -0
  110. package/dist/WidgetFrame/index.js +6 -0
  111. package/dist/WidgetFrame-4EFJOJMW.css +127 -0
  112. package/dist/chunk-3D7PSL2L.js +438 -0
  113. package/dist/{chunk-SJCKMSQK.js → chunk-5LUI3WQP.js} +1 -1
  114. package/dist/{chunk-TODND5AD.js → chunk-6J35F334.js} +7 -4
  115. package/dist/{chunk-IASV5UCP.js → chunk-7T42VQQT.js} +3 -1
  116. package/dist/{chunk-BJCFNRGH.js → chunk-BEHFTRMZ.js} +1 -1
  117. package/dist/chunk-BQYQWJPK.js +80 -0
  118. package/dist/{chunk-KLIEPFEZ.js → chunk-C2FRTWKO.js} +1 -1
  119. package/dist/{chunk-APS747CR.js → chunk-EHQTPVV4.js} +5 -3
  120. package/dist/{chunk-A2UXBCLO.js → chunk-FAQGGX2Z.js} +1 -1
  121. package/dist/chunk-FQCLKD7U.js +2 -0
  122. package/dist/{chunk-J4OKGJQ6.js → chunk-FVLCTCMV.js} +1 -1
  123. package/dist/{chunk-XJFOOXCF.js → chunk-HJEVSQN6.js} +1 -1
  124. package/dist/chunk-HONZQ4UR.js +107 -0
  125. package/dist/{chunk-5PSXBL73.js → chunk-HVIX5ECM.js} +1 -1
  126. package/dist/{chunk-36CWC2NH.js → chunk-INTEH4F3.js} +271 -143
  127. package/dist/{chunk-F6NZOVWL.js → chunk-IW55G7XG.js} +6 -2
  128. package/dist/chunk-KNLJL3VP.js +101 -0
  129. package/dist/chunk-KSSSFLE2.js +105 -0
  130. package/dist/{chunk-TXAFKH2A.js → chunk-KZOGQXSP.js} +6 -0
  131. package/dist/{chunk-CS65QSIJ.js → chunk-LZHLSQYK.js} +2 -2
  132. package/dist/chunk-MQEEQVG6.js +62 -0
  133. package/dist/chunk-NBWNLYWZ.js +62 -0
  134. package/dist/{chunk-YYZRLLLY.js → chunk-NHBP2XS5.js} +19 -3
  135. package/dist/chunk-O2EGEONV.js +90 -0
  136. package/dist/{chunk-YM3GJHGW.js → chunk-ODT5H4MN.js} +1 -1
  137. package/dist/{chunk-JCSXFAXG.js → chunk-OJRDEVHV.js} +1 -1
  138. package/dist/{chunk-U63Y5OCW.js → chunk-PRNX5AFE.js} +2 -2
  139. package/dist/chunk-Q4A5CGUB.js +43 -0
  140. package/dist/{chunk-7QL2OFP6.js → chunk-RCQXUT5K.js} +25 -9
  141. package/dist/{chunk-CBOICT64.js → chunk-RKKO7QHH.js} +2 -0
  142. package/dist/{chunk-TBIZSQHB.js → chunk-RSC7UJCR.js} +1 -1
  143. package/dist/chunk-RWA4H2TV.js +73 -0
  144. package/dist/{chunk-OQT7GSKJ.js → chunk-SGIQCI6Y.js} +1 -1
  145. package/dist/{chunk-35UKQ33X.js → chunk-SVW3VG72.js} +2 -2
  146. package/dist/{chunk-4PZ6FJKW.js → chunk-UGNUUVRI.js} +2 -2
  147. package/dist/chunk-UOR7TOAU.js +191 -0
  148. package/dist/{chunk-XMGB3ZAT.js → chunk-URUGEAFB.js} +3 -2
  149. package/dist/chunk-UZ7ZUSLH.js +179 -0
  150. package/dist/chunk-V2Z24W2Z.js +75 -0
  151. package/dist/{chunk-I7WXZOWA.js → chunk-VGE3G3T4.js} +3 -1
  152. package/dist/{chunk-UNZ7TVV5.js → chunk-W4XYY73O.js} +7 -9
  153. package/dist/{chunk-IPM2E6UI.js → chunk-WJDQ7XQA.js} +1 -1
  154. package/dist/{chunk-PPAQFGS2.js → chunk-YEKYVJQR.js} +1 -1
  155. package/dist/chunk-Z54BPRL6.js +74 -0
  156. package/dist/{chunk-S35G6PNC.js → chunk-Z7JYG5TF.js} +5 -4
  157. package/dist/chunk-ZZDY4XL7.js +112 -0
  158. package/dist/generated/index.d.ts +13 -0
  159. package/dist/generated/index.js +92 -79
  160. package/dist/index.js +92 -79
  161. package/dist/styles.css +1644 -153
  162. package/dist/utils/csv.d.ts +18 -0
  163. package/dist/utils/elementToPng.d.ts +49 -0
  164. package/dist/utils/index.d.ts +4 -1
  165. package/dist/utils/index.js +2 -2
  166. package/dist/utils/useDownload.d.ts +14 -4
  167. package/package.json +3 -3
  168. package/dist/chunk-E6UWRXNM.js +0 -52
  169. package/dist/chunk-M54K52ZU.js +0 -2
  170. package/dist/chunk-U5LQ2AS5.js +0 -1
  171. package/dist/{chunk-KG6XRG5Z.js → chunk-5OY4LJFH.js} +1 -1
  172. package/dist/{chunk-ZM7HLFOA.js → chunk-L2OQRPXJ.js} +1 -1
  173. package/dist/{chunk-MUGM7SEG.js → chunk-LFNUH4GY.js} +1 -1
  174. package/dist/{chunk-PBNP7H2C.js → chunk-M2VJGNCD.js} +1 -1
  175. /package/dist/{chunk-MSSZHDZI.js → chunk-SLRKS5PF.js} +0 -0
@@ -0,0 +1,438 @@
1
+ import { Note } from './chunk-63WJLRB2.js';
2
+ import { IDENTITY_VIEW, Canvas } from './chunk-KZOGQXSP.js';
3
+ import { IconButton } from './chunk-4FQT6ZAY.js';
4
+ import { cx } from './chunk-ODEQTPFM.js';
5
+ import './CanvasBoard-ZLPDINSM.css';
6
+ import { useState, useCallback, useMemo, useRef } from 'react';
7
+ import { MaximizeGlyph, PencilGlyph, TrashGlyph } from '@crewlethq/icons/glyphs';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+
10
+ // src/CanvasBoard/budget.ts
11
+ var CANVAS_BOARD_MAX_LIVE = 12;
12
+ var CANVAS_BOARD_MIN_LIVE_WIDTH = 160;
13
+ function liveBoards(boards, view, viewport, max = CANVAS_BOARD_MAX_LIVE, minWidth = CANVAS_BOARD_MIN_LIVE_WIDTH) {
14
+ if (max <= 0 || viewport.width <= 0 || viewport.height <= 0) return [];
15
+ const ranked = [];
16
+ boards.forEach((b, index) => {
17
+ const left = b.x * view.k + view.x;
18
+ const top = b.y * view.k + view.y;
19
+ const width = b.w * view.k;
20
+ const height = b.h * view.k;
21
+ if (width < minWidth) return;
22
+ const seenW = Math.min(left + width, viewport.width) - Math.max(left, 0);
23
+ const seenH = Math.min(top + height, viewport.height) - Math.max(top, 0);
24
+ if (seenW <= 0 || seenH <= 0) return;
25
+ ranked.push({ id: b.id, area: seenW * seenH, index });
26
+ });
27
+ ranked.sort((a, b) => b.area - a.area || a.index - b.index);
28
+ return ranked.slice(0, max).sort((a, b) => a.index - b.index).map((r) => r.id);
29
+ }
30
+ var CANVAS_NOTE_COLORS = [
31
+ "yellow",
32
+ "pink",
33
+ "blue",
34
+ "green",
35
+ "purple"
36
+ ];
37
+ var NOTE_TONES = {
38
+ yellow: "amber",
39
+ pink: "rose",
40
+ blue: "blue",
41
+ green: "green",
42
+ purple: "purple"
43
+ };
44
+ function noteName(note) {
45
+ const words = note.text.trim().replace(/\s+/g, " ");
46
+ return words.length > 40 ? `${words.slice(0, 39)}\u2026` : words;
47
+ }
48
+ var LABELS = {
49
+ size: (w, h) => `${w} by ${h}`,
50
+ open: (title) => `Open ${title} full size`,
51
+ move: (title) => `Move ${title}`,
52
+ resize: (title) => `Resize ${title}`,
53
+ editNote: "Edit note",
54
+ removeNote: "Delete note",
55
+ noteText: "Note text",
56
+ paused: "Zoom in to run this board",
57
+ active: "Press Escape to return to the canvas"
58
+ };
59
+ var KEY_STEP = 8;
60
+ var KEY_STEP_LARGE = 64;
61
+ var CONTENT_MARGIN = 160;
62
+ function contentOf(boards, notes) {
63
+ const all = [...boards, ...notes];
64
+ if (all.length === 0) return null;
65
+ let minX = Infinity;
66
+ let minY = Infinity;
67
+ let maxX = -Infinity;
68
+ let maxY = -Infinity;
69
+ for (const r of all) {
70
+ minX = Math.min(minX, r.x);
71
+ minY = Math.min(minY, r.y);
72
+ maxX = Math.max(maxX, r.x + r.w);
73
+ maxY = Math.max(maxY, r.y + r.h);
74
+ }
75
+ return {
76
+ x: minX - CONTENT_MARGIN,
77
+ y: minY - CONTENT_MARGIN,
78
+ width: maxX - minX + 2 * CONTENT_MARGIN,
79
+ height: maxY - minY + 2 * CONTENT_MARGIN
80
+ };
81
+ }
82
+ var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
83
+ function useFrameGestures(zoom, minSide, maxSide, commit) {
84
+ const [preview, setPreview] = useState(null);
85
+ const drag = useRef(null);
86
+ const next = useCallback(
87
+ (d, dx, dy) => d.mode === "move" ? { ...d.from, x: Math.round(d.from.x + dx), y: Math.round(d.from.y + dy) } : {
88
+ ...d.from,
89
+ w: clamp(Math.round(d.from.w + dx), minSide, maxSide),
90
+ h: clamp(Math.round(d.from.h + dy), minSide, maxSide)
91
+ },
92
+ [minSide, maxSide]
93
+ );
94
+ const handle = (id, mode, item) => {
95
+ const from = { x: item.x, y: item.y, w: item.w, h: item.h };
96
+ return {
97
+ onPointerDown: (event) => {
98
+ if (event.pointerType === "mouse" && event.button !== 0) return;
99
+ event.preventDefault();
100
+ try {
101
+ event.currentTarget.setPointerCapture(event.pointerId);
102
+ } catch {
103
+ }
104
+ drag.current = {
105
+ id,
106
+ mode,
107
+ pointer: event.pointerId,
108
+ startX: event.clientX,
109
+ startY: event.clientY,
110
+ from,
111
+ moved: false
112
+ };
113
+ },
114
+ onPointerMove: (event) => {
115
+ const d = drag.current;
116
+ if (!d || d.pointer !== event.pointerId) return;
117
+ d.moved = true;
118
+ setPreview({
119
+ id,
120
+ rect: next(d, (event.clientX - d.startX) / zoom, (event.clientY - d.startY) / zoom)
121
+ });
122
+ },
123
+ onPointerUp: (event) => {
124
+ const d = drag.current;
125
+ if (!d || d.pointer !== event.pointerId) return;
126
+ drag.current = null;
127
+ setPreview(null);
128
+ if (!d.moved) return;
129
+ const rect = next(d, (event.clientX - d.startX) / zoom, (event.clientY - d.startY) / zoom);
130
+ const start = d.from;
131
+ if (rect.x !== start.x || rect.y !== start.y || rect.w !== start.w || rect.h !== start.h) {
132
+ commit(id, rect);
133
+ }
134
+ },
135
+ onPointerCancel: () => {
136
+ drag.current = null;
137
+ setPreview(null);
138
+ },
139
+ onKeyDown: (event) => {
140
+ const step = event.shiftKey ? KEY_STEP_LARGE : KEY_STEP;
141
+ const delta = {
142
+ ArrowLeft: [-step, 0],
143
+ ArrowRight: [step, 0],
144
+ ArrowUp: [0, -step],
145
+ ArrowDown: [0, step]
146
+ };
147
+ const d = delta[event.key];
148
+ if (!d) return;
149
+ event.preventDefault();
150
+ event.stopPropagation();
151
+ const rect = next(
152
+ { id, mode, pointer: -1, startX: 0, startY: 0, from, moved: true },
153
+ d[0],
154
+ d[1]
155
+ );
156
+ if (rect.x !== from.x || rect.y !== from.y || rect.w !== from.w || rect.h !== from.h) {
157
+ commit(id, rect);
158
+ }
159
+ }
160
+ };
161
+ };
162
+ return { preview, handle };
163
+ }
164
+ function CanvasBoard({
165
+ label,
166
+ boards,
167
+ notes = [],
168
+ renderBoard,
169
+ maxLive = CANVAS_BOARD_MAX_LIVE,
170
+ minLiveWidth = CANVAS_BOARD_MIN_LIVE_WIDTH,
171
+ editable = false,
172
+ minSide = 40,
173
+ maxSide = 8e3,
174
+ onBoardChange,
175
+ onNoteChange,
176
+ onNoteRemove,
177
+ onOpen,
178
+ onActivate,
179
+ controlsExtra,
180
+ labels,
181
+ canvasLabels,
182
+ canvasRef,
183
+ className
184
+ }) {
185
+ const text = { ...LABELS, ...labels };
186
+ const [view, setView] = useState(IDENTITY_VIEW);
187
+ const [viewport, setViewport] = useState({ width: 0, height: 0 });
188
+ const [active, setActive] = useState(null);
189
+ const [editing, setEditing] = useState(null);
190
+ const activate = (id) => {
191
+ setActive(id);
192
+ onActivate?.(id);
193
+ };
194
+ const commitBoard = useCallback(
195
+ (id, rect) => onBoardChange?.(id, rect),
196
+ [onBoardChange]
197
+ );
198
+ const commitNote = useCallback(
199
+ (id, rect) => {
200
+ const note = notes.find((n) => n.id === id);
201
+ if (note) onNoteChange?.({ ...note, ...rect });
202
+ },
203
+ [notes, onNoteChange]
204
+ );
205
+ const boardGestures = useFrameGestures(view.k, minSide, maxSide, commitBoard);
206
+ const noteGestures = useFrameGestures(view.k, minSide, maxSide, commitNote);
207
+ const frameOf = (item, preview) => preview?.id === item.id ? { ...item, ...preview.rect } : item;
208
+ const drawnBoards = boards.map((b) => frameOf(b, boardGestures.preview));
209
+ const drawnNotes = notes.map((n) => frameOf(n, noteGestures.preview));
210
+ const content = useMemo(
211
+ () => contentOf(boards, notes),
212
+ // The content's bounds follow the committed frames, never a drag in
213
+ // progress: a bound that moved under the pointer would pan the canvas.
214
+ [boards, notes]
215
+ );
216
+ const largest = boards.reduce((w, b) => Math.max(w, b.w), 0);
217
+ const live = new Set(liveBoards(drawnBoards, view, viewport, maxLive, minLiveWidth));
218
+ const onKeyDown = (event) => {
219
+ if (event.key === "Escape" && active !== null) {
220
+ event.stopPropagation();
221
+ activate(null);
222
+ }
223
+ };
224
+ const zoomVar = { "--crewlet-canvas-board-zoom": String(view.k) };
225
+ return (
226
+ // The wrapper only hears Escape bubbling from inside the canvas; the
227
+ // canvas's own viewport is the focusable, labelled control.
228
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
229
+ /* @__PURE__ */ jsx(
230
+ "div",
231
+ {
232
+ className: cx("crewlet-canvas-board", className),
233
+ "data-editable": editable || void 0,
234
+ onKeyDown,
235
+ children: /* @__PURE__ */ jsx(
236
+ Canvas,
237
+ {
238
+ label,
239
+ content,
240
+ largestItemWidth: largest || void 0,
241
+ ground: "dotted",
242
+ controlsExtra,
243
+ labels: canvasLabels,
244
+ onViewChange: (nextView, size) => {
245
+ setView(nextView);
246
+ setViewport(size);
247
+ },
248
+ ref: canvasRef,
249
+ children: /* @__PURE__ */ jsxs("div", { className: "crewlet-canvas-board__layer", style: zoomVar, children: [
250
+ drawnBoards.map((b) => {
251
+ const isLive = live.has(b.id);
252
+ const isActive = !editable && active === b.id && isLive;
253
+ return /* @__PURE__ */ jsxs(
254
+ "section",
255
+ {
256
+ className: "crewlet-canvas-board__board",
257
+ "data-live": isLive || void 0,
258
+ "data-active": isActive || void 0,
259
+ "aria-label": `${b.title}, ${text.size(b.w, b.h)}`,
260
+ style: { left: b.x, top: b.y, width: b.w, height: b.h },
261
+ children: [
262
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-canvas-board__chrome", children: [
263
+ editable ? /* @__PURE__ */ jsx(
264
+ "button",
265
+ {
266
+ type: "button",
267
+ className: "crewlet-canvas-board__title crewlet-canvas-board__handle",
268
+ "aria-label": text.move(b.title),
269
+ ...boardGestures.handle(b.id, "move", b),
270
+ children: b.title
271
+ }
272
+ ) : /* @__PURE__ */ jsx("span", { className: "crewlet-canvas-board__title", children: b.title }),
273
+ onOpen && /* @__PURE__ */ jsx(
274
+ IconButton,
275
+ {
276
+ size: "sm",
277
+ variant: "ghost",
278
+ label: text.open(b.title),
279
+ icon: /* @__PURE__ */ jsx(MaximizeGlyph, {}),
280
+ onClick: () => onOpen(b.id)
281
+ }
282
+ )
283
+ ] }),
284
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-canvas-board__body", children: [
285
+ isLive ? renderBoard(b) : /* @__PURE__ */ jsx("div", { className: "crewlet-canvas-board__placeholder", children: /* @__PURE__ */ jsxs("span", { className: "crewlet-canvas-board__placeholder-text", children: [
286
+ /* @__PURE__ */ jsx("span", { className: "crewlet-canvas-board__placeholder-title", children: b.title }),
287
+ /* @__PURE__ */ jsx("span", { children: text.size(b.w, b.h) }),
288
+ /* @__PURE__ */ jsx("span", { children: text.paused })
289
+ ] }) }),
290
+ isLive && !isActive && // A press here pans the canvas like the field around it;
291
+ // a click without a drag hands this board the pointer.
292
+ // The board's page stays reachable by keyboard through
293
+ // its own frame, so the shield is pointer only.
294
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
295
+ /* @__PURE__ */ jsx(
296
+ "div",
297
+ {
298
+ className: "crewlet-canvas-board__shield",
299
+ onClick: editable ? void 0 : () => activate(b.id)
300
+ }
301
+ )
302
+ ] }),
303
+ isActive && /* @__PURE__ */ jsx("p", { className: "crewlet-canvas-board__hint", children: text.active }),
304
+ editable && /* @__PURE__ */ jsx(
305
+ "button",
306
+ {
307
+ type: "button",
308
+ className: "crewlet-canvas-board__resize",
309
+ "aria-label": text.resize(b.title),
310
+ ...boardGestures.handle(b.id, "resize", b)
311
+ }
312
+ )
313
+ ]
314
+ },
315
+ b.id
316
+ );
317
+ }),
318
+ drawnNotes.map((n) => /* @__PURE__ */ jsx(
319
+ NoteView,
320
+ {
321
+ note: n,
322
+ editable,
323
+ editing: editing === n.id,
324
+ text,
325
+ moveHandle: noteGestures.handle(n.id, "move", n),
326
+ resizeHandle: noteGestures.handle(n.id, "resize", n),
327
+ onEdit: () => setEditing(n.id),
328
+ onDone: (value) => {
329
+ setEditing(null);
330
+ const trimmed = value.trim();
331
+ if (trimmed !== "" && value !== n.text) {
332
+ const original = notes.find((o) => o.id === n.id);
333
+ if (original) onNoteChange?.({ ...original, text: value });
334
+ }
335
+ },
336
+ onCancel: () => setEditing(null),
337
+ onRemove: () => onNoteRemove?.(n.id)
338
+ },
339
+ n.id
340
+ ))
341
+ ] })
342
+ }
343
+ )
344
+ }
345
+ )
346
+ );
347
+ }
348
+ function NoteView({
349
+ note,
350
+ editable,
351
+ editing,
352
+ text,
353
+ moveHandle,
354
+ resizeHandle,
355
+ onEdit,
356
+ onDone,
357
+ onCancel,
358
+ onRemove
359
+ }) {
360
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
361
+ editing ? /* @__PURE__ */ jsx(
362
+ "textarea",
363
+ {
364
+ className: "crewlet-canvas-board__note-field",
365
+ "aria-label": text.noteText,
366
+ defaultValue: note.text,
367
+ autoFocus: true,
368
+ onBlur: (event) => onDone(event.currentTarget.value),
369
+ onKeyDown: (event) => {
370
+ if (event.key === "Escape") {
371
+ event.preventDefault();
372
+ event.stopPropagation();
373
+ onCancel();
374
+ } else if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
375
+ event.preventDefault();
376
+ onDone(event.currentTarget.value);
377
+ }
378
+ }
379
+ }
380
+ ) : /* @__PURE__ */ jsx("p", { className: "crewlet-canvas-board__note-text", children: note.text }),
381
+ editable && !editing && /* @__PURE__ */ jsxs("div", { className: "crewlet-canvas-board__note-tools", children: [
382
+ /* @__PURE__ */ jsx(
383
+ "button",
384
+ {
385
+ type: "button",
386
+ className: "crewlet-canvas-board__handle crewlet-canvas-board__note-move",
387
+ "aria-label": text.move(noteName(note)),
388
+ ...moveHandle
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx(
392
+ IconButton,
393
+ {
394
+ size: "sm",
395
+ variant: "ghost",
396
+ label: text.editNote,
397
+ icon: /* @__PURE__ */ jsx(PencilGlyph, {}),
398
+ onClick: onEdit
399
+ }
400
+ ),
401
+ /* @__PURE__ */ jsx(
402
+ IconButton,
403
+ {
404
+ size: "sm",
405
+ variant: "ghost",
406
+ label: text.removeNote,
407
+ icon: /* @__PURE__ */ jsx(TrashGlyph, {}),
408
+ onClick: onRemove
409
+ }
410
+ )
411
+ ] }),
412
+ editable && !editing && /* @__PURE__ */ jsx(
413
+ "button",
414
+ {
415
+ type: "button",
416
+ className: "crewlet-canvas-board__resize",
417
+ "aria-label": text.resize(noteName(note)),
418
+ ...resizeHandle
419
+ }
420
+ )
421
+ ] });
422
+ const frame = { left: note.x, top: note.y, width: note.w, height: note.h };
423
+ if (note.kind === "sticky") {
424
+ return /* @__PURE__ */ jsx(
425
+ Note,
426
+ {
427
+ tone: NOTE_TONES[note.color ?? CANVAS_NOTE_COLORS[0]],
428
+ className: "crewlet-canvas-board__note",
429
+ "data-kind": "sticky",
430
+ style: frame,
431
+ children: body
432
+ }
433
+ );
434
+ }
435
+ return /* @__PURE__ */ jsx("div", { className: "crewlet-canvas-board__note", "data-kind": "title", style: frame, children: body });
436
+ }
437
+
438
+ export { CANVAS_BOARD_MAX_LIVE, CANVAS_BOARD_MIN_LIVE_WIDTH, CANVAS_NOTE_COLORS, CanvasBoard, liveBoards };
@@ -1,6 +1,6 @@
1
1
  import { Switch } from './chunk-A722MUNR.js';
2
2
  import { useReorder } from './chunk-XJ2QEBMM.js';
3
- import { Checkbox } from './chunk-IASV5UCP.js';
3
+ import { Checkbox } from './chunk-7T42VQQT.js';
4
4
  import { IconButton } from './chunk-4FQT6ZAY.js';
5
5
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -6,13 +6,16 @@ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './ArtifactCard-EXVAEBV6.css';
8
8
  import { useId } from 'react';
9
- import { TableGlyph, FileTextGlyph, FileCodeGlyph, PinGlyph } from '@crewlethq/icons/glyphs';
9
+ import { TableGlyph, LayoutDashboardGlyph, PaletteGlyph, PresentationGlyph, FileTextGlyph, FileCodeGlyph, PinGlyph } from '@crewlethq/icons/glyphs';
10
10
  import { jsx, jsxs } from 'react/jsx-runtime';
11
11
 
12
- var ARTIFACT_KINDS = ["html", "markdown", "sheet"];
12
+ var ARTIFACT_KINDS = ["html", "doc", "slides", "design", "dashboard", "sheet"];
13
13
  var KIND_GLYPHS = {
14
14
  html: FileCodeGlyph,
15
- markdown: FileTextGlyph,
15
+ doc: FileTextGlyph,
16
+ slides: PresentationGlyph,
17
+ design: PaletteGlyph,
18
+ dashboard: LayoutDashboardGlyph,
16
19
  sheet: TableGlyph
17
20
  };
18
21
  function ArtifactKindGlyph({ kind, size = "md" }) {
@@ -20,7 +23,7 @@ function ArtifactKindGlyph({ kind, size = "md" }) {
20
23
  return /* @__PURE__ */ jsx(Drawn, { size });
21
24
  }
22
25
  var LABELS = {
23
- kinds: { html: "Page", markdown: "Document", sheet: "Sheet" },
26
+ kinds: { html: "Page", doc: "Doc", slides: "Slides", design: "Design", dashboard: "Dashboard", sheet: "Sheet" },
24
27
  pinned: "Pinned",
25
28
  version: (version) => `v${version}`,
26
29
  changes: (count) => count === 1 ? "1 change since you looked" : `${count} changes since you looked`,
@@ -1,6 +1,6 @@
1
1
  import { FormField } from './chunk-6QFAK2WV.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Checkbox-KT7RS6QQ.css';
3
+ import './Checkbox-5UORUG3F.css';
4
4
  import { forwardRef, useId, useRef, useCallback, useEffect } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -9,6 +9,7 @@ var Checkbox = forwardRef(function Checkbox2({
9
9
  description,
10
10
  tone = "default",
11
11
  framed = false,
12
+ size = "md",
12
13
  indeterminate = false,
13
14
  onCheckedChange,
14
15
  onChange,
@@ -42,6 +43,7 @@ var Checkbox = forwardRef(function Checkbox2({
42
43
  "crewlet-checkbox",
43
44
  tone === "danger" && "crewlet-checkbox--danger",
44
45
  framed && "crewlet-checkbox--framed",
46
+ size === "sm" && "crewlet-checkbox--sm",
45
47
  disabled && "is-disabled",
46
48
  className
47
49
  ),
@@ -1,4 +1,4 @@
1
- import { useDownload, safeFilename } from './chunk-F6NZOVWL.js';
1
+ import { useDownload, safeFilename } from './chunk-IW55G7XG.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { useMemo, useCallback } from 'react';
@@ -0,0 +1,80 @@
1
+ import { Skeleton } from './chunk-W5J7R5EB.js';
2
+ import { RelativeTime } from './chunk-3CZ7XAVY.js';
3
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
+ import { cx } from './chunk-ODEQTPFM.js';
5
+ import './WidgetFrame-4EFJOJMW.css';
6
+ import { useId } from 'react';
7
+ import { ClockGlyph, LockGlyph, CircleAlertGlyph } from '@crewlethq/icons/glyphs';
8
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
9
+
10
+ var LABELS = {
11
+ live: "live",
12
+ asOf: "as of",
13
+ stale: "stale",
14
+ loading: (title) => `Loading ${title}`,
15
+ refused: "You do not have access to the data behind this figure.",
16
+ failed: "This figure could not be loaded.",
17
+ cite: "Source:"
18
+ };
19
+ function WidgetFrame({
20
+ title,
21
+ source,
22
+ onCite,
23
+ actions,
24
+ headingLevel = 3,
25
+ now,
26
+ labels,
27
+ className,
28
+ children,
29
+ ...rest
30
+ }) {
31
+ const text = { ...LABELS, ...labels };
32
+ const titleId = useId();
33
+ const Heading = `h${headingLevel}`;
34
+ const blocked = source.status === "refused" || source.status === "failed";
35
+ const citation = /* @__PURE__ */ jsxs(Fragment, { children: [
36
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: text.cite }),
37
+ " ",
38
+ /* @__PURE__ */ jsx("span", { className: "crewlet-widget-frame__source", children: source.label }),
39
+ source.status === "live" ? /* @__PURE__ */ jsxs(Fragment, { children: [
40
+ " ",
41
+ /* @__PURE__ */ jsx("span", { className: "crewlet-widget-frame__when", children: text.live })
42
+ ] }) : source.asOf !== void 0 && source.asOf !== null && !blocked ? /* @__PURE__ */ jsxs(Fragment, { children: [
43
+ " ",
44
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-widget-frame__when", children: [
45
+ text.asOf,
46
+ " ",
47
+ /* @__PURE__ */ jsx(RelativeTime, { value: source.asOf, now })
48
+ ] })
49
+ ] }) : null,
50
+ source.status === "stale" ? /* @__PURE__ */ jsxs(Fragment, { children: [
51
+ " ",
52
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-widget-frame__stale", children: [
53
+ /* @__PURE__ */ jsx(ClockGlyph, { size: "xs" }),
54
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: text.stale })
55
+ ] })
56
+ ] }) : null
57
+ ] });
58
+ return /* @__PURE__ */ jsxs(
59
+ "section",
60
+ {
61
+ ...rest,
62
+ className: cx("crewlet-widget-frame", `crewlet-widget-frame--${source.status}`, className),
63
+ "aria-labelledby": titleId,
64
+ "aria-busy": source.status === "loading" || void 0,
65
+ children: [
66
+ /* @__PURE__ */ jsxs("header", { className: "crewlet-widget-frame__head", children: [
67
+ /* @__PURE__ */ jsx(Heading, { id: titleId, className: "crewlet-widget-frame__title", children: title }),
68
+ actions ? /* @__PURE__ */ jsx("div", { className: "crewlet-widget-frame__actions", children: actions }) : null
69
+ ] }),
70
+ /* @__PURE__ */ jsx("div", { className: "crewlet-widget-frame__body", children: source.status === "loading" ? /* @__PURE__ */ jsx(Skeleton, { variant: "text", rows: 3, label: text.loading(title) }) : blocked ? /* @__PURE__ */ jsxs("p", { className: "crewlet-widget-frame__blocked", children: [
71
+ /* @__PURE__ */ jsx("span", { className: "crewlet-widget-frame__blocked-glyph", "aria-hidden": true, children: source.status === "refused" ? /* @__PURE__ */ jsx(LockGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(CircleAlertGlyph, { size: "sm" }) }),
72
+ /* @__PURE__ */ jsx("span", { children: source.detail ?? (source.status === "refused" ? text.refused : text.failed) })
73
+ ] }) : children }),
74
+ /* @__PURE__ */ jsx("footer", { className: "crewlet-widget-frame__cite", children: onCite ? /* @__PURE__ */ jsx("button", { type: "button", className: "crewlet-widget-frame__cite-button", onClick: onCite, children: citation }) : /* @__PURE__ */ jsx("span", { className: "crewlet-widget-frame__cite-text", children: citation }) })
75
+ ]
76
+ }
77
+ );
78
+ }
79
+
80
+ export { WidgetFrame };
@@ -1,6 +1,6 @@
1
1
  import { ThemeSwatch } from './chunk-MNFU2RNT.js';
2
2
  import { useHighlightRest } from './chunk-F73MC7EZ.js';
3
- import { useRoving, tabStop } from './chunk-CBOICT64.js';
3
+ import { useRoving, tabStop } from './chunk-RKKO7QHH.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './ThemeGallery-NITASULQ.css';
6
6
  import { useId } from 'react';
@@ -1,5 +1,5 @@
1
1
  import { diffLines, diffStat, collapseDiff, DiffSummary, DiffView } from './chunk-BVWSLXTY.js';
2
- import { SegmentedControl } from './chunk-7QL2OFP6.js';
2
+ import { SegmentedControl } from './chunk-RCQXUT5K.js';
3
3
  import { EmptyState } from './chunk-RA2ULG6H.js';
4
4
  import { useHeadingLevel, headingTag, nextHeadingLevel, HeadingLevelProvider } from './chunk-PQADV6P6.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
@@ -31,6 +31,7 @@ function VersionCompare({
31
31
  context = 3,
32
32
  from,
33
33
  to,
34
+ versions,
34
35
  note,
35
36
  actions,
36
37
  labels: overrides,
@@ -44,7 +45,8 @@ function VersionCompare({
44
45
  const PaneHeading = headingTag(inner);
45
46
  const hostChanges = changes !== void 0 && changes !== null;
46
47
  const canChanges = hostChanges || before !== void 0 && after !== void 0;
47
- const canVersions = from !== void 0 && from !== null || to !== void 0 && to !== null;
48
+ const hostVersions = versions !== void 0 && versions !== null;
49
+ const canVersions = hostVersions || from !== void 0 && from !== null || to !== void 0 && to !== null;
48
50
  const shown = lens === "versions" ? canVersions ? "versions" : "changes" : canChanges ? "changes" : "versions";
49
51
  const diff = useMemo(() => {
50
52
  if (hostChanges || shown !== "changes" || before === void 0 || after === void 0) return null;
@@ -91,7 +93,7 @@ function VersionCompare({
91
93
  /* @__PURE__ */ jsx(DiffView, { sections: diff.sections, "aria-label": labels.region(fromLabel, toLabel) })
92
94
  ] }) : /* @__PURE__ */ jsx("div", { className: "crewlet-version-compare__changes", children: changes }) : /* @__PURE__ */ jsxs("div", { className: "crewlet-version-compare__versions", children: [
93
95
  note !== void 0 && note !== null && /* @__PURE__ */ jsx("p", { className: "crewlet-version-compare__note", children: note }),
94
- /* @__PURE__ */ jsx("div", { className: "crewlet-version-compare__panes", children: panes.map((pane) => /* @__PURE__ */ jsxs("div", { className: "crewlet-version-compare__pane", children: [
96
+ hostVersions ? versions : /* @__PURE__ */ jsx("div", { className: "crewlet-version-compare__panes", children: panes.map((pane) => /* @__PURE__ */ jsxs("div", { className: "crewlet-version-compare__pane", children: [
95
97
  /* @__PURE__ */ jsx(PaneHeading, { className: "crewlet-version-compare__pane-title", children: pane.label }),
96
98
  /* @__PURE__ */ jsx(HeadingLevelProvider, { level: nextHeadingLevel(inner), children: pane.node })
97
99
  ] }, pane.key)) })
@@ -1,6 +1,6 @@
1
1
  import { useHeadingLevel, headingTag, HeadingLevelProvider, nextHeadingLevel } from './chunk-PQADV6P6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Section-QRUPRIQ2.css';
3
+ import './Section-QR3ILQVK.css';
4
4
  import { useId } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -0,0 +1,2 @@
1
+ import './Tabs-CJGO35BH.css';
2
+ import './SegmentedControl-FLI45IOW.css';
@@ -1,4 +1,4 @@
1
- import { PRESENCE_LABELS, presenceOrder, collapseSessions } from './chunk-S35G6PNC.js';
1
+ import { PRESENCE_LABELS, presenceOrder, collapseSessions } from './chunk-Z7JYG5TF.js';
2
2
  import { Avatar } from './chunk-5OM447RW.js';
3
3
  import { headingTag, useHeadingLevel } from './chunk-PQADV6P6.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
@@ -1,4 +1,4 @@
1
- import { useRoving, tabStop } from './chunk-CBOICT64.js';
1
+ import { useRoving, tabStop } from './chunk-RKKO7QHH.js';
2
2
  import { Count } from './chunk-BHHIIK3M.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';