@crewlethq/ui 0.24.0 → 0.26.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 (172) hide show
  1. package/README.md +85 -3
  2. package/dist/ArrangeList/index.js +2 -2
  3. package/dist/ArtifactCover/ArtifactCover.d.ts +37 -0
  4. package/dist/ArtifactCover/DashboardCover.d.ts +46 -0
  5. package/dist/ArtifactCover/index.d.ts +6 -0
  6. package/dist/ArtifactCover/index.js +14 -0
  7. package/dist/ArtifactCover-D4MBEJ5H.css +67 -0
  8. package/dist/ArtifactIcon/ArtifactIcon.d.ts +29 -0
  9. package/dist/ArtifactIcon/index.d.ts +2 -0
  10. package/dist/ArtifactIcon/index.js +13 -0
  11. package/dist/AvatarPicker/index.js +6 -6
  12. package/dist/Canvas/Canvas.d.ts +13 -2
  13. package/dist/Canvas/index.js +1 -1
  14. package/dist/CanvasBoard/CanvasBoard.d.ts +117 -0
  15. package/dist/CanvasBoard/budget.d.ts +38 -0
  16. package/dist/CanvasBoard/index.d.ts +5 -0
  17. package/dist/CanvasBoard/index.js +10 -0
  18. package/dist/CanvasBoard-ZLPDINSM.css +236 -0
  19. package/dist/CanvasSchematic/CanvasSchematic.d.ts +31 -0
  20. package/dist/CanvasSchematic/index.d.ts +3 -0
  21. package/dist/CanvasSchematic/index.js +2 -0
  22. package/dist/CanvasSchematic-PLB3N46J.css +36 -0
  23. package/dist/ChangeMark/index.js +3 -3
  24. package/dist/CharacterPicker/index.js +2 -2
  25. package/dist/Checkbox/Checkbox.d.ts +6 -0
  26. package/dist/Checkbox/index.js +1 -1
  27. package/dist/{Checkbox-KT7RS6QQ.css → Checkbox-5UORUG3F.css} +16 -0
  28. package/dist/CommentThread/index.js +2 -2
  29. package/dist/DashboardCover-RMINBODB.css +143 -0
  30. package/dist/DataTable/index.js +3 -3
  31. package/dist/DataView/index.js +5 -5
  32. package/dist/DatasetSource/DatasetSource.d.ts +83 -0
  33. package/dist/DatasetSource/index.d.ts +3 -0
  34. package/dist/DatasetSource/index.js +7 -0
  35. package/dist/DatasetSource-47LBDMPR.css +129 -0
  36. package/dist/DocTabsEditor/DocTabsEditor.d.ts +60 -0
  37. package/dist/DocTabsEditor/index.d.ts +3 -0
  38. package/dist/DocTabsEditor/index.js +9 -0
  39. package/dist/DocTabsEditor-RCOWHX5J.css +78 -0
  40. package/dist/DownloadButton/index.js +2 -2
  41. package/dist/HuePicker/index.js +4 -4
  42. package/dist/LinkInterstitial/index.js +2 -2
  43. package/dist/MarkdownEditor/index.js +5 -5
  44. package/dist/MergeConflicts/MergeConflicts.d.ts +51 -0
  45. package/dist/MergeConflicts/index.d.ts +3 -0
  46. package/dist/MergeConflicts/index.js +9 -0
  47. package/dist/MergeConflicts-O44ESH4T.css +77 -0
  48. package/dist/Meter/index.js +1 -1
  49. package/dist/{Meter-5VCSFMZW.css → Meter-ZZRFUEOH.css} +15 -0
  50. package/dist/ObjectHeader/ObjectHeader.d.ts +7 -1
  51. package/dist/ObjectHeader/index.js +1 -1
  52. package/dist/{ObjectHeader-UNVYM2KD.css → ObjectHeader-D7GU7QNI.css} +15 -0
  53. package/dist/PeopleRail/index.js +2 -2
  54. package/dist/PresenceModel/index.d.ts +1 -1
  55. package/dist/PresenceModel/index.js +1 -1
  56. package/dist/PresenceModel/presence.d.ts +10 -2
  57. package/dist/PresenceStack/index.js +2 -2
  58. package/dist/PresenterView/PresenterView.d.ts +52 -0
  59. package/dist/PresenterView/index.d.ts +3 -0
  60. package/dist/PresenterView/index.js +8 -0
  61. package/dist/PresenterView-T2C6ZZ3N.css +103 -0
  62. package/dist/Section/index.js +1 -1
  63. package/dist/{Section-QRUPRIQ2.css → Section-QR3ILQVK.css} +4 -1
  64. package/dist/SegmentedControl/SegmentedControl.d.ts +17 -0
  65. package/dist/SegmentedControl/index.js +4 -4
  66. package/dist/{SegmentedControl-PKBLJVSA.css → SegmentedControl-FLI45IOW.css} +13 -0
  67. package/dist/ShareDialog/index.js +3 -3
  68. package/dist/SheetGrid/SheetGrid.d.ts +24 -2
  69. package/dist/SheetGrid/index.js +10 -6
  70. package/dist/{SheetGrid-4HOXDVIB.css → SheetGrid-J3TKKXZL.css} +87 -17
  71. package/dist/SheetModel/edits.d.ts +7 -1
  72. package/dist/SheetModel/index.js +2 -2
  73. package/dist/SheetModel/labels.d.ts +9 -0
  74. package/dist/SheetModel/types.d.ts +6 -0
  75. package/dist/SlideCompare/SlideCompare.d.ts +52 -0
  76. package/dist/SlideCompare/index.d.ts +3 -0
  77. package/dist/SlideCompare/index.js +7 -0
  78. package/dist/SlideCompare-MGM3U2ME.css +80 -0
  79. package/dist/SlideFilmstrip/SlideFilmstrip.d.ts +50 -0
  80. package/dist/SlideFilmstrip/index.d.ts +3 -0
  81. package/dist/SlideFilmstrip/index.js +8 -0
  82. package/dist/SlideFilmstrip-BCLNAHFX.css +108 -0
  83. package/dist/SlideGrid/SlideGrid.d.ts +32 -0
  84. package/dist/SlideGrid/index.d.ts +3 -0
  85. package/dist/SlideGrid/index.js +5 -0
  86. package/dist/SlideGrid-RT6QEQEE.css +82 -0
  87. package/dist/SlideStage/SlideStage.d.ts +47 -0
  88. package/dist/SlideStage/index.d.ts +5 -0
  89. package/dist/SlideStage/index.js +4 -0
  90. package/dist/SlideStage/useSlideKeys.d.ts +21 -0
  91. package/dist/SlideStage-XIOTMMRU.css +32 -0
  92. package/dist/Switcher/index.js +2 -2
  93. package/dist/TableCells/index.js +2 -2
  94. package/dist/Tabs/index.js +2 -2
  95. package/dist/Tabs/roving.d.ts +1 -0
  96. package/dist/TagGroup/TagGroup.d.ts +16 -1
  97. package/dist/TagGroup/index.js +1 -1
  98. package/dist/{TagGroup-BCQZD7ZD.css → TagGroup-NAXTJHDS.css} +22 -0
  99. package/dist/ThemeGallery/index.js +2 -2
  100. package/dist/ThemeSwitcher/index.js +5 -5
  101. package/dist/TreeCanvas/index.js +2 -2
  102. package/dist/VersionCompare/VersionCompare.d.ts +8 -1
  103. package/dist/VersionCompare/index.js +5 -5
  104. package/dist/VersionTimeline/index.js +1 -1
  105. package/dist/{VersionTimeline-EBJ6MIPJ.css → VersionTimeline-6KRXEEOO.css} +7 -7
  106. package/dist/WidgetFrame/WidgetFrame.d.ts +73 -0
  107. package/dist/WidgetFrame/index.d.ts +3 -0
  108. package/dist/WidgetFrame/index.js +6 -0
  109. package/dist/WidgetFrame-4EFJOJMW.css +127 -0
  110. package/dist/chunk-3D7PSL2L.js +438 -0
  111. package/dist/{chunk-SJCKMSQK.js → chunk-5LUI3WQP.js} +1 -1
  112. package/dist/{chunk-IASV5UCP.js → chunk-7T42VQQT.js} +3 -1
  113. package/dist/{chunk-BJCFNRGH.js → chunk-BEHFTRMZ.js} +1 -1
  114. package/dist/chunk-BQYQWJPK.js +80 -0
  115. package/dist/{chunk-KLIEPFEZ.js → chunk-C2FRTWKO.js} +1 -1
  116. package/dist/{chunk-APS747CR.js → chunk-EHQTPVV4.js} +5 -3
  117. package/dist/{chunk-A2UXBCLO.js → chunk-FAQGGX2Z.js} +1 -1
  118. package/dist/chunk-FQCLKD7U.js +2 -0
  119. package/dist/{chunk-J4OKGJQ6.js → chunk-FVLCTCMV.js} +1 -1
  120. package/dist/{chunk-XJFOOXCF.js → chunk-HJEVSQN6.js} +1 -1
  121. package/dist/chunk-HONZQ4UR.js +107 -0
  122. package/dist/{chunk-5PSXBL73.js → chunk-HVIX5ECM.js} +1 -1
  123. package/dist/{chunk-36CWC2NH.js → chunk-INTEH4F3.js} +271 -143
  124. package/dist/{chunk-F6NZOVWL.js → chunk-IW55G7XG.js} +6 -2
  125. package/dist/chunk-KNLJL3VP.js +101 -0
  126. package/dist/chunk-KSSSFLE2.js +105 -0
  127. package/dist/{chunk-TXAFKH2A.js → chunk-KZOGQXSP.js} +6 -0
  128. package/dist/{chunk-CS65QSIJ.js → chunk-LZHLSQYK.js} +2 -2
  129. package/dist/chunk-MQEEQVG6.js +62 -0
  130. package/dist/chunk-NBWNLYWZ.js +62 -0
  131. package/dist/{chunk-YYZRLLLY.js → chunk-NHBP2XS5.js} +19 -3
  132. package/dist/chunk-O2EGEONV.js +90 -0
  133. package/dist/{chunk-YM3GJHGW.js → chunk-ODT5H4MN.js} +1 -1
  134. package/dist/{chunk-JCSXFAXG.js → chunk-OJRDEVHV.js} +1 -1
  135. package/dist/{chunk-U63Y5OCW.js → chunk-PRNX5AFE.js} +2 -2
  136. package/dist/chunk-Q4A5CGUB.js +43 -0
  137. package/dist/{chunk-7QL2OFP6.js → chunk-RCQXUT5K.js} +25 -9
  138. package/dist/{chunk-CBOICT64.js → chunk-RKKO7QHH.js} +2 -0
  139. package/dist/{chunk-TBIZSQHB.js → chunk-RSC7UJCR.js} +1 -1
  140. package/dist/chunk-RWA4H2TV.js +73 -0
  141. package/dist/{chunk-OQT7GSKJ.js → chunk-SGIQCI6Y.js} +1 -1
  142. package/dist/{chunk-35UKQ33X.js → chunk-SVW3VG72.js} +2 -2
  143. package/dist/{chunk-4PZ6FJKW.js → chunk-UGNUUVRI.js} +2 -2
  144. package/dist/chunk-UOR7TOAU.js +191 -0
  145. package/dist/{chunk-XMGB3ZAT.js → chunk-URUGEAFB.js} +3 -2
  146. package/dist/chunk-UZ7ZUSLH.js +179 -0
  147. package/dist/chunk-V2Z24W2Z.js +75 -0
  148. package/dist/{chunk-I7WXZOWA.js → chunk-VGE3G3T4.js} +3 -1
  149. package/dist/{chunk-UNZ7TVV5.js → chunk-W4XYY73O.js} +7 -9
  150. package/dist/{chunk-IPM2E6UI.js → chunk-WJDQ7XQA.js} +1 -1
  151. package/dist/{chunk-PPAQFGS2.js → chunk-YEKYVJQR.js} +1 -1
  152. package/dist/chunk-Z54BPRL6.js +74 -0
  153. package/dist/{chunk-S35G6PNC.js → chunk-Z7JYG5TF.js} +5 -4
  154. package/dist/chunk-ZZDY4XL7.js +112 -0
  155. package/dist/generated/index.d.ts +13 -0
  156. package/dist/generated/index.js +84 -71
  157. package/dist/index.js +84 -71
  158. package/dist/styles.css +1644 -153
  159. package/dist/utils/csv.d.ts +18 -0
  160. package/dist/utils/elementToPng.d.ts +49 -0
  161. package/dist/utils/index.d.ts +4 -1
  162. package/dist/utils/index.js +2 -2
  163. package/dist/utils/useDownload.d.ts +14 -4
  164. package/package.json +3 -3
  165. package/dist/chunk-E6UWRXNM.js +0 -52
  166. package/dist/chunk-M54K52ZU.js +0 -2
  167. package/dist/chunk-U5LQ2AS5.js +0 -1
  168. package/dist/{chunk-KG6XRG5Z.js → chunk-5OY4LJFH.js} +1 -1
  169. package/dist/{chunk-ZM7HLFOA.js → chunk-L2OQRPXJ.js} +1 -1
  170. package/dist/{chunk-MUGM7SEG.js → chunk-LFNUH4GY.js} +1 -1
  171. package/dist/{chunk-PBNP7H2C.js → chunk-M2VJGNCD.js} +1 -1
  172. /package/dist/{chunk-MSSZHDZI.js → chunk-SLRKS5PF.js} +0 -0
@@ -1,5 +1,5 @@
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-TXAFKH2A.js';
2
+ import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-KZOGQXSP.js';
3
3
  import { focusables } from './chunk-R25RGPUB.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './TreeCanvas-L2XYONWL.css';
@@ -0,0 +1,73 @@
1
+ import { SegmentedControl } from './chunk-RCQXUT5K.js';
2
+ import { Button } from './chunk-OG6CL3EB.js';
3
+ import { cx } from './chunk-ODEQTPFM.js';
4
+ import './MergeConflicts-O44ESH4T.css';
5
+ import { useState, useId, useRef, useEffect } from 'react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var MERGE_CONFLICTS_LABELS = {
9
+ heading: (count, theirs) => count === 1 ? `You and ${theirs} changed the same lines` : `You and ${theirs} changed the same lines in ${count} places`,
10
+ intro: "For each conflict, keep their lines, yours or both.",
11
+ theirsCaption: (theirs) => `Theirs \xB7 ${theirs}`,
12
+ mineCaption: "Yours",
13
+ removed: "(removed)",
14
+ choiceLabel: (place) => `Place ${place}: which lines to keep`,
15
+ choices: { theirs: "Theirs", mine: "Yours", both: "Both" },
16
+ apply: "Apply to my draft",
17
+ applyBlocked: "Settle every place first.",
18
+ cancel: "Not now",
19
+ remaining: (count) => count === 1 ? "1 place still to settle." : `${count} places still to settle.`
20
+ };
21
+ var ORDER = ["theirs", "mine", "both"];
22
+ function MergeConflicts({ clashes, theirs, onApply, onCancel, className, labels: overrides }) {
23
+ const labels = overrides ? { ...MERGE_CONFLICTS_LABELS, ...overrides } : MERGE_CONFLICTS_LABELS;
24
+ const [choices, setChoices] = useState(() => clashes.map(() => void 0));
25
+ const left = choices.filter((c) => c === void 0).length;
26
+ const heading = useId();
27
+ const first = useRef(null);
28
+ useEffect(() => first.current?.focus(), []);
29
+ const options = ORDER.map((value) => ({ value, label: labels.choices[value] }));
30
+ return /* @__PURE__ */ jsxs("section", { className: cx("crewlet-merge-conflicts", className), "aria-labelledby": heading, children: [
31
+ /* @__PURE__ */ jsx("h2", { className: "crewlet-merge-conflicts__title", id: heading, ref: first, tabIndex: -1, children: labels.heading(clashes.length, theirs) }),
32
+ /* @__PURE__ */ jsx("p", { className: "crewlet-merge-conflicts__note", children: labels.intro }),
33
+ /* @__PURE__ */ jsx("ol", { className: "crewlet-merge-conflicts__list", children: clashes.map((clash, i) => /* @__PURE__ */ jsxs("li", { className: "crewlet-merge-conflicts__item", children: [
34
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-merge-conflicts__sides", children: [
35
+ /* @__PURE__ */ jsxs("figure", { className: "crewlet-merge-conflicts__side", children: [
36
+ /* @__PURE__ */ jsx("figcaption", { children: labels.theirsCaption(theirs) }),
37
+ /* @__PURE__ */ jsx("pre", { children: clash.theirs.join("\n") || labels.removed })
38
+ ] }),
39
+ /* @__PURE__ */ jsxs("figure", { className: "crewlet-merge-conflicts__side", children: [
40
+ /* @__PURE__ */ jsx("figcaption", { children: labels.mineCaption }),
41
+ /* @__PURE__ */ jsx("pre", { children: clash.mine.join("\n") || labels.removed })
42
+ ] })
43
+ ] }),
44
+ /* @__PURE__ */ jsx(
45
+ SegmentedControl,
46
+ {
47
+ semantics: "radio",
48
+ size: "sm",
49
+ label: labels.choiceLabel(i + 1),
50
+ value: choices[i] ?? "",
51
+ onValueChange: (v) => setChoices(choices.map((c, k) => k === i ? v : c)),
52
+ options
53
+ }
54
+ )
55
+ ] }, i)) }),
56
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-merge-conflicts__foot", children: [
57
+ /* @__PURE__ */ jsx(
58
+ Button,
59
+ {
60
+ size: "small",
61
+ variant: "primary",
62
+ disabledReason: left === 0 ? void 0 : labels.applyBlocked,
63
+ onClick: () => onApply(choices),
64
+ children: labels.apply
65
+ }
66
+ ),
67
+ /* @__PURE__ */ jsx(Button, { size: "small", variant: "ghost", onClick: onCancel, children: labels.cancel }),
68
+ left > 0 && /* @__PURE__ */ jsx("span", { className: "crewlet-merge-conflicts__note", children: labels.remaining(left) })
69
+ ] })
70
+ ] });
71
+ }
72
+
73
+ export { MERGE_CONFLICTS_LABELS, MergeConflicts };
@@ -1,4 +1,4 @@
1
- import { SegmentedControl } from './chunk-7QL2OFP6.js';
1
+ import { SegmentedControl } from './chunk-RCQXUT5K.js';
2
2
  import { NODE_HUES, NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
- import { useClipboard } from './chunk-STJ7QBC3.js';
2
1
  import { Modal } from './chunk-F4DPAJCN.js';
3
- import { Checkbox } from './chunk-IASV5UCP.js';
2
+ import { useClipboard } from './chunk-STJ7QBC3.js';
3
+ import { Checkbox } from './chunk-7T42VQQT.js';
4
4
  import { EmptyValue } from './chunk-EUCC37WY.js';
5
5
  import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
6
6
  import { Menu } from './chunk-UFKUWVMV.js';
@@ -1,6 +1,6 @@
1
1
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Meter-5VCSFMZW.css';
3
+ import './Meter-ZZRFUEOH.css';
4
4
  import { useId } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -84,7 +84,7 @@ function Meter({
84
84
  "aria-valuemax": bounded ? max : void 0,
85
85
  "aria-valuetext": spoken,
86
86
  "aria-hidden": bounded ? void 0 : true,
87
- children: /* @__PURE__ */ jsx("div", { className: "crewlet-meter__fill", "data-tone": drawn, style: { width: `${percent}%` } })
87
+ children: /* @__PURE__ */ jsx("div", { className: cx("crewlet-meter__fill", bounded && value > 0 && "crewlet-meter__fill--some"), "data-tone": drawn, style: { width: `${percent}%` } })
88
88
  }
89
89
  )
90
90
  ] });
@@ -0,0 +1,191 @@
1
+ // src/utils/csv.ts
2
+ var FORMULA_LEAD = /^[=+\-@\t\r]/;
3
+ function toCsv(header, rows) {
4
+ const lines = [header.map((name) => field(name)).join(",")];
5
+ for (const row of rows) {
6
+ lines.push(row.map((value) => field(value)).join(","));
7
+ }
8
+ return lines.map((line) => `${line}\r
9
+ `).join("");
10
+ }
11
+ function field(value) {
12
+ return quote(text(value));
13
+ }
14
+ function text(value) {
15
+ if (value === null || value === void 0) return "";
16
+ if (typeof value === "number" || typeof value === "bigint") return String(value);
17
+ if (typeof value === "boolean") return value ? "true" : "false";
18
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toISOString();
19
+ const written = typeof value === "string" ? value : JSON.stringify(value) ?? "";
20
+ return FORMULA_LEAD.test(written) ? `'${written}` : written;
21
+ }
22
+ function quote(written) {
23
+ return /[",\r\n]/.test(written) ? `"${written.replace(/"/g, '""')}"` : written;
24
+ }
25
+
26
+ // src/utils/elementToPng.ts
27
+ var ElementToPngError = class extends Error {
28
+ reason;
29
+ constructor(reason, message) {
30
+ super(message);
31
+ this.name = "ElementToPngError";
32
+ this.reason = reason;
33
+ }
34
+ };
35
+ var SVG_NS = "http://www.w3.org/2000/svg";
36
+ var MAX_SCALE = 3;
37
+ var SVG_PROPERTIES = [
38
+ "fill",
39
+ "fill-opacity",
40
+ "stroke",
41
+ "stroke-width",
42
+ "stroke-opacity",
43
+ "stroke-dasharray",
44
+ "stroke-linecap",
45
+ "stroke-linejoin",
46
+ "opacity",
47
+ "color",
48
+ "stop-color",
49
+ "stop-opacity",
50
+ "font-family",
51
+ "font-size",
52
+ "font-weight",
53
+ "font-style",
54
+ "text-anchor",
55
+ "dominant-baseline",
56
+ "vector-effect",
57
+ "visibility",
58
+ "display"
59
+ ];
60
+ async function elementToPng(el, options = {}) {
61
+ const box = el.getBoundingClientRect();
62
+ if (box.width <= 0 || box.height <= 0) {
63
+ throw new ElementToPngError("empty", "The element has no size, so there is nothing to draw.");
64
+ }
65
+ const padding = Math.max(0, options.padding ?? 0);
66
+ const width = Math.ceil(box.width + 2 * padding);
67
+ const height = Math.ceil(box.height + 2 * padding);
68
+ const ratio = options.scale ?? (typeof window !== "undefined" ? window.devicePixelRatio : 1);
69
+ const scale = Math.min(MAX_SCALE, Math.max(1, Number.isFinite(ratio) ? ratio : 1));
70
+ const background = options.background ?? opaqueBackground(el);
71
+ const markup = serializeElement(el, { width, height, padding });
72
+ const image = await loadImage(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(markup)}`);
73
+ const canvas = document.createElement("canvas");
74
+ canvas.width = Math.round(width * scale);
75
+ canvas.height = Math.round(height * scale);
76
+ const context = canvas.getContext("2d");
77
+ if (!context) {
78
+ throw new ElementToPngError("unsupported", "This browser cannot draw onto a canvas.");
79
+ }
80
+ context.scale(scale, scale);
81
+ if (background) {
82
+ context.fillStyle = background;
83
+ context.fillRect(0, 0, width, height);
84
+ }
85
+ try {
86
+ context.drawImage(image, 0, 0, width, height);
87
+ } catch {
88
+ throw new ElementToPngError("unsupported", "This browser could not draw the element.");
89
+ }
90
+ return toBlob(canvas);
91
+ }
92
+ function serializeElement(el, { width, height, padding = 0 }) {
93
+ const svg = soleSvg(el);
94
+ const root = document.createElementNS(SVG_NS, "svg");
95
+ root.setAttribute("width", String(width));
96
+ root.setAttribute("height", String(height));
97
+ root.setAttribute("viewBox", `0 0 ${width} ${height}`);
98
+ if (svg) {
99
+ const copy = svg.cloneNode(true);
100
+ inlineSvgStyles(svg, copy);
101
+ const box = svg.getBoundingClientRect();
102
+ copy.setAttribute("x", String(padding));
103
+ copy.setAttribute("y", String(padding));
104
+ copy.setAttribute("width", String(box.width || width - 2 * padding));
105
+ copy.setAttribute("height", String(box.height || height - 2 * padding));
106
+ root.appendChild(copy);
107
+ } else {
108
+ const object = document.createElementNS(SVG_NS, "foreignObject");
109
+ object.setAttribute("x", String(padding));
110
+ object.setAttribute("y", String(padding));
111
+ object.setAttribute("width", String(width - 2 * padding));
112
+ object.setAttribute("height", String(height - 2 * padding));
113
+ const copy = el.cloneNode(true);
114
+ inlineHtmlStyles(el, copy);
115
+ object.appendChild(copy);
116
+ root.appendChild(object);
117
+ }
118
+ return new XMLSerializer().serializeToString(root);
119
+ }
120
+ function soleSvg(el) {
121
+ if (el instanceof SVGSVGElement) return el;
122
+ const svgs = el.querySelectorAll("svg");
123
+ if (svgs.length !== 1) return null;
124
+ const svg = svgs[0];
125
+ const clone = el.cloneNode(true);
126
+ clone.querySelector("svg")?.remove();
127
+ return (clone.textContent ?? "").trim() === "" ? svg : null;
128
+ }
129
+ function inlineSvgStyles(source, copy) {
130
+ const computed = getComputedStyle(source);
131
+ const declarations = [];
132
+ for (const property of SVG_PROPERTIES) {
133
+ const value = computed.getPropertyValue(property);
134
+ if (value && !value.includes("var(")) declarations.push(`${property}:${value}`);
135
+ }
136
+ if (declarations.length > 0) copy.setAttribute("style", declarations.join(";"));
137
+ copy.removeAttribute("class");
138
+ const sourceChildren = source.children;
139
+ const copyChildren = copy.children;
140
+ for (let i = 0; i < sourceChildren.length && i < copyChildren.length; i++) {
141
+ inlineSvgStyles(sourceChildren[i], copyChildren[i]);
142
+ }
143
+ }
144
+ function inlineHtmlStyles(source, copy) {
145
+ const computed = getComputedStyle(source);
146
+ const declarations = [];
147
+ for (let i = 0; i < computed.length; i++) {
148
+ const property = computed.item(i);
149
+ if (property.startsWith("--")) continue;
150
+ const value = computed.getPropertyValue(property);
151
+ if (value && !value.includes("var(")) declarations.push(`${property}:${value}`);
152
+ }
153
+ copy.setAttribute("style", declarations.join(";"));
154
+ copy.removeAttribute("class");
155
+ const sourceChildren = source.children;
156
+ const copyChildren = copy.children;
157
+ for (let i = 0; i < sourceChildren.length && i < copyChildren.length; i++) {
158
+ const child = sourceChildren[i];
159
+ if (child instanceof SVGElement) inlineSvgStyles(child, copyChildren[i]);
160
+ else inlineHtmlStyles(child, copyChildren[i]);
161
+ }
162
+ }
163
+ function opaqueBackground(el) {
164
+ for (let node = el; node; node = node.parentElement) {
165
+ const colour = getComputedStyle(node).backgroundColor;
166
+ if (colour && colour !== "transparent" && !/rgba\([^)]*,\s*0\)$/.test(colour)) return colour;
167
+ }
168
+ return void 0;
169
+ }
170
+ function loadImage(src) {
171
+ return new Promise((resolve, reject) => {
172
+ const image = new Image();
173
+ image.onload = () => resolve(image);
174
+ image.onerror = () => reject(new ElementToPngError("unsupported", "This browser could not draw the element as an image."));
175
+ image.src = src;
176
+ });
177
+ }
178
+ function toBlob(canvas) {
179
+ return new Promise((resolve, reject) => {
180
+ try {
181
+ canvas.toBlob((blob) => {
182
+ if (blob) resolve(blob);
183
+ else reject(new ElementToPngError("tainted", "This browser drew the element and would not let the image be saved."));
184
+ }, "image/png");
185
+ } catch {
186
+ reject(new ElementToPngError("tainted", "This browser drew the element and would not let the image be saved."));
187
+ }
188
+ });
189
+ }
190
+
191
+ export { ElementToPngError, elementToPng, serializeElement, toCsv };
@@ -1,6 +1,6 @@
1
1
  import { Select } from './chunk-FC4YTTFJ.js';
2
- import { CopyButton } from './chunk-W46LPU4R.js';
3
2
  import { Modal } from './chunk-F4DPAJCN.js';
3
+ import { CopyButton } from './chunk-W46LPU4R.js';
4
4
  import { Callout } from './chunk-SVSCLHHI.js';
5
5
  import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
6
6
  import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
@@ -28,7 +28,8 @@ var AGENT_CAN = {
28
28
  owner: "read, edit, publish and share this artifact in its turns"
29
29
  };
30
30
  var LABELS = {
31
- title: (artifact) => `Share "${artifact}"`,
31
+ // Curly quotes, as every other dialog title in the product draws them.
32
+ title: (artifact) => `Share \u201C${artifact}\u201D`,
32
33
  addRole: "Role for people you add",
33
34
  audience: "Who has access",
34
35
  you: "(you)",
@@ -0,0 +1,179 @@
1
+ import { useReorder } from './chunk-XJ2QEBMM.js';
2
+ import { Input } from './chunk-6QFAK2WV.js';
3
+ import { Button } from './chunk-OG6CL3EB.js';
4
+ import { IconButton } from './chunk-4FQT6ZAY.js';
5
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
+ import { cx } from './chunk-ODEQTPFM.js';
7
+ import './DocTabsEditor-RCOWHX5J.css';
8
+ import { useState, useId } from 'react';
9
+ import { GripVerticalGlyph, PencilGlyph, ChevronUpGlyph, ChevronDownGlyph, TrashGlyph, PlusGlyph } from '@crewlethq/icons/glyphs';
10
+ import { jsxs, jsx } from 'react/jsx-runtime';
11
+
12
+ var DOC_TABS_EDITOR_LABELS = {
13
+ handle: (name) => `Move ${name}`,
14
+ hint: "Drag to move, or press the up or down arrow key.",
15
+ moved: (name, position, total) => `${name} moved to position ${position} of ${total}.`,
16
+ titleField: (position) => `Title of tab ${position}`,
17
+ editText: (title) => `Edit the text of ${title}`,
18
+ remove: (title) => `Remove ${title}`,
19
+ lastTab: "A doc keeps at least one tab.",
20
+ moveUp: (title) => `Move ${title} up`,
21
+ moveDown: (title) => `Move ${title} down`,
22
+ atTop: (title) => `${title} is first.`,
23
+ atBottom: (title) => `${title} is last.`,
24
+ newTitle: "New tab title",
25
+ add: "Add tab",
26
+ addNeedsTitle: "Give the new tab a title.",
27
+ untitled: "Untitled tab"
28
+ };
29
+ function DocTabsEditor({
30
+ label,
31
+ items,
32
+ selected,
33
+ onSelect,
34
+ onRename,
35
+ onReorder,
36
+ onRemove,
37
+ onAdd,
38
+ titleProblem,
39
+ addBlocked,
40
+ disabled = false,
41
+ labels: overrides,
42
+ className
43
+ }) {
44
+ const labels = { ...DOC_TABS_EDITOR_LABELS, ...overrides };
45
+ const byKey = new Map(items.map((item) => [item.key, item]));
46
+ const nameOf = (key) => byKey.get(key)?.title.trim() || labels.untitled;
47
+ const reorder = useReorder({ keys: items.map((item) => item.key), onReorder, nameOf, labels });
48
+ const [title, setTitle] = useState("");
49
+ const id = useId();
50
+ const last = reorder.order.length - 1;
51
+ const add = () => {
52
+ if (title.trim() === "" || addBlocked || disabled) return;
53
+ onAdd(title.trim());
54
+ setTitle("");
55
+ };
56
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-doc-tabs-editor", className), children: [
57
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: reorder.hintId, children: reorder.hint }),
58
+ /* @__PURE__ */ jsx("ol", { className: "crewlet-doc-tabs-editor__list", "aria-label": label, ...reorder.containerProps, children: reorder.order.map((key, index) => {
59
+ const item = byKey.get(key);
60
+ if (!item) return null;
61
+ const name = nameOf(key);
62
+ const problem = titleProblem?.(item.title) ?? null;
63
+ const problemId = `${id}-${index}-problem`;
64
+ const open = key === selected;
65
+ const { "aria-label": handleName, ...handle } = reorder.handleProps(key);
66
+ return /* @__PURE__ */ jsxs("li", { className: cx("crewlet-doc-tabs-editor__item", open && "is-open"), ...reorder.itemProps(key), children: [
67
+ /* @__PURE__ */ jsx(
68
+ IconButton,
69
+ {
70
+ size: "sm",
71
+ variant: "ghost",
72
+ className: "crewlet-doc-tabs-editor__handle",
73
+ label: handleName,
74
+ icon: /* @__PURE__ */ jsx(GripVerticalGlyph, { size: "md" }),
75
+ disabled,
76
+ ...handle
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-doc-tabs-editor__field", children: [
80
+ /* @__PURE__ */ jsx(
81
+ Input,
82
+ {
83
+ inputSize: "sm",
84
+ value: item.title,
85
+ "aria-label": labels.titleField(index + 1),
86
+ error: problem !== null,
87
+ disabled,
88
+ ...problem !== null ? { "aria-describedby": problemId } : {},
89
+ onChange: (event) => onRename(key, event.target.value)
90
+ }
91
+ ),
92
+ problem !== null && /* @__PURE__ */ jsx("span", { id: problemId, className: "crewlet-doc-tabs-editor__problem", children: problem })
93
+ ] }),
94
+ /* @__PURE__ */ jsx(
95
+ IconButton,
96
+ {
97
+ size: "sm",
98
+ variant: open ? "secondary" : "ghost",
99
+ pressed: open,
100
+ label: labels.editText(name),
101
+ icon: /* @__PURE__ */ jsx(PencilGlyph, { size: "sm" }),
102
+ disabled,
103
+ onClick: () => onSelect(key)
104
+ }
105
+ ),
106
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-doc-tabs-editor__moves", children: [
107
+ /* @__PURE__ */ jsx(
108
+ IconButton,
109
+ {
110
+ size: "sm",
111
+ variant: "ghost",
112
+ label: labels.moveUp(name),
113
+ icon: /* @__PURE__ */ jsx(ChevronUpGlyph, { size: "sm" }),
114
+ ...index === 0 ? { disabledReason: labels.atTop(name) } : {},
115
+ disabled,
116
+ onClick: () => reorder.move(key, -1)
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsx(
120
+ IconButton,
121
+ {
122
+ size: "sm",
123
+ variant: "ghost",
124
+ label: labels.moveDown(name),
125
+ icon: /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "sm" }),
126
+ ...index === last ? { disabledReason: labels.atBottom(name) } : {},
127
+ disabled,
128
+ onClick: () => reorder.move(key, 1)
129
+ }
130
+ )
131
+ ] }),
132
+ /* @__PURE__ */ jsx(
133
+ IconButton,
134
+ {
135
+ size: "sm",
136
+ variant: "ghost",
137
+ label: labels.remove(name),
138
+ icon: /* @__PURE__ */ jsx(TrashGlyph, { size: "sm" }),
139
+ ...items.length <= 1 ? { disabledReason: labels.lastTab } : {},
140
+ disabled,
141
+ onClick: () => onRemove(key)
142
+ }
143
+ )
144
+ ] }, key);
145
+ }) }),
146
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-doc-tabs-editor__add", children: [
147
+ /* @__PURE__ */ jsx(
148
+ Input,
149
+ {
150
+ inputSize: "sm",
151
+ value: title,
152
+ "aria-label": labels.newTitle,
153
+ placeholder: labels.newTitle,
154
+ disabled,
155
+ onChange: (event) => setTitle(event.target.value),
156
+ onKeyDown: (event) => {
157
+ if (event.key !== "Enter") return;
158
+ event.preventDefault();
159
+ add();
160
+ }
161
+ }
162
+ ),
163
+ /* @__PURE__ */ jsx(
164
+ Button,
165
+ {
166
+ size: "small",
167
+ variant: "secondary",
168
+ leadingIcon: /* @__PURE__ */ jsx(PlusGlyph, { size: "sm" }),
169
+ disabled,
170
+ disabledReason: addBlocked ?? (title.trim() === "" ? labels.addNeedsTitle : void 0),
171
+ onClick: add,
172
+ children: labels.add
173
+ }
174
+ )
175
+ ] })
176
+ ] });
177
+ }
178
+
179
+ export { DOC_TABS_EDITOR_LABELS, DocTabsEditor };
@@ -0,0 +1,75 @@
1
+ import { ArtifactKindGlyph } from './chunk-6J35F334.js';
2
+ import { ShieldGlyph, ActivityGlyph, GaugeGlyph, PackageGlyph, FolderGlyph, ClockGlyph, DatabaseGlyph, Settings2Glyph, BookOpenGlyph, FlagGlyph, StarGlyph, WandSparklesGlyph, BugGlyph, TargetGlyph, ImageGlyph, CodeGlyph, CoinsGlyph, UserGlyph, UsersGlyph, ChartNoAxesGanttGlyph, SquareKanbanGlyph, ListChecksGlyph, ListGlyph, GlobeGlyph, CompassGlyph, FileTextGlyph, TableGlyph, CalendarGlyph, LayoutDashboardGlyph, ChartPieGlyph, ChartColumnGlyph } from '@crewlethq/icons/glyphs';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var WORDS = {
6
+ chart: ChartColumnGlyph,
7
+ graph: ChartColumnGlyph,
8
+ metrics: ChartColumnGlyph,
9
+ analytics: ChartColumnGlyph,
10
+ pie: ChartPieGlyph,
11
+ dashboard: LayoutDashboardGlyph,
12
+ calendar: CalendarGlyph,
13
+ schedule: CalendarGlyph,
14
+ table: TableGlyph,
15
+ sheet: TableGlyph,
16
+ spreadsheet: TableGlyph,
17
+ doc: FileTextGlyph,
18
+ document: FileTextGlyph,
19
+ notes: FileTextGlyph,
20
+ report: FileTextGlyph,
21
+ memo: FileTextGlyph,
22
+ map: CompassGlyph,
23
+ compass: CompassGlyph,
24
+ globe: GlobeGlyph,
25
+ web: GlobeGlyph,
26
+ list: ListGlyph,
27
+ checklist: ListChecksGlyph,
28
+ tasks: ListChecksGlyph,
29
+ todo: ListChecksGlyph,
30
+ board: SquareKanbanGlyph,
31
+ kanban: SquareKanbanGlyph,
32
+ plan: ChartNoAxesGanttGlyph,
33
+ roadmap: ChartNoAxesGanttGlyph,
34
+ timeline: ChartNoAxesGanttGlyph,
35
+ people: UsersGlyph,
36
+ team: UsersGlyph,
37
+ person: UserGlyph,
38
+ profile: UserGlyph,
39
+ money: CoinsGlyph,
40
+ budget: CoinsGlyph,
41
+ finance: CoinsGlyph,
42
+ cost: CoinsGlyph,
43
+ code: CodeGlyph,
44
+ image: ImageGlyph,
45
+ goal: TargetGlyph,
46
+ target: TargetGlyph,
47
+ bug: BugGlyph,
48
+ idea: WandSparklesGlyph,
49
+ star: StarGlyph,
50
+ flag: FlagGlyph,
51
+ book: BookOpenGlyph,
52
+ guide: BookOpenGlyph,
53
+ settings: Settings2Glyph,
54
+ database: DatabaseGlyph,
55
+ data: DatabaseGlyph,
56
+ clock: ClockGlyph,
57
+ time: ClockGlyph,
58
+ folder: FolderGlyph,
59
+ package: PackageGlyph,
60
+ health: GaugeGlyph,
61
+ gauge: GaugeGlyph,
62
+ activity: ActivityGlyph,
63
+ security: ShieldGlyph
64
+ };
65
+ var ARTIFACT_ICON_WORDS = Object.freeze(Object.keys(WORDS).sort());
66
+ function artifactIconGlyph(word) {
67
+ const key = word?.trim().toLowerCase() ?? "";
68
+ return Object.hasOwn(WORDS, key) ? WORDS[key] : null;
69
+ }
70
+ function ArtifactIcon({ icon, kind, size = "md" }) {
71
+ const Drawn = artifactIconGlyph(icon);
72
+ return Drawn ? /* @__PURE__ */ jsx(Drawn, { size }) : /* @__PURE__ */ jsx(ArtifactKindGlyph, { kind, size });
73
+ }
74
+
75
+ export { ARTIFACT_ICON_WORDS, ArtifactIcon, artifactIconGlyph };
@@ -1,6 +1,6 @@
1
1
  import { Link } from './chunk-FBSEJO2C.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './ObjectHeader-UNVYM2KD.css';
3
+ import './ObjectHeader-D7GU7QNI.css';
4
4
  import { ArrowUpRightGlyph } from '@crewlethq/icons/glyphs';
5
5
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
6
6
 
@@ -67,6 +67,7 @@ function ObjectHeader({
67
67
  title,
68
68
  status,
69
69
  facts,
70
+ description,
70
71
  actions,
71
72
  size = "page",
72
73
  className
@@ -83,6 +84,7 @@ function ObjectHeader({
83
84
  status ? /* @__PURE__ */ jsx("div", { className: "crewlet-object-header__status", children: status }) : null,
84
85
  actions ? /* @__PURE__ */ jsx("div", { className: "crewlet-object-header__actions", children: actions }) : null
85
86
  ] }),
87
+ description ? /* @__PURE__ */ jsx("p", { className: "crewlet-object-header__description", children: description }) : null,
86
88
  facts ? /* @__PURE__ */ jsx(FactLine, { facts }) : null
87
89
  ] });
88
90
  }
@@ -3,9 +3,9 @@ import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
3
3
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './VersionTimeline-EBJ6MIPJ.css';
6
+ import './VersionTimeline-6KRXEEOO.css';
7
7
  import { RotateCcwClockGlyph, PencilGlyph, ShieldGlyph, DatabaseGlyph, UploadGlyph } from '@crewlethq/icons/glyphs';
8
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
9
 
10
10
  var LABELS = {
11
11
  list: "Versions",
@@ -19,8 +19,8 @@ var LABELS = {
19
19
  compareWith: (version) => `Compare with version ${version}`,
20
20
  restoreAction: "Restore",
21
21
  restoreVersion: (version) => `Restore version ${version}`,
22
- labelAction: "Name",
23
- labelVersion: (version) => `Name version ${version}`,
22
+ labelAction: "Label",
23
+ labelVersion: (version) => `Label version ${version}`,
24
24
  retention: (oldestKept) => oldestKept > 2 ? `Versions 1 to ${oldestKept - 1} are past the retention window and are no longer kept.` : "Version 1 is past the retention window and is no longer kept."
25
25
  };
26
26
  var GLYPHS = {
@@ -73,7 +73,7 @@ function VersionTimeline({
73
73
  item.version === newest ? /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__latest", children: text.latest }) : null,
74
74
  item.label ? /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__label", children: item.label }) : null
75
75
  ] }),
76
- /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__summary", children: item.summary ?? what })
76
+ item.summary ? /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__summary", children: item.summary }) : null
77
77
  ]
78
78
  }
79
79
  ),
@@ -82,10 +82,8 @@ function VersionTimeline({
82
82
  /* @__PURE__ */ jsx("span", { children: item.author.name }),
83
83
  /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }),
84
84
  /* @__PURE__ */ jsx(RelativeTime, { value: item.at, now }),
85
- item.summary ? /* @__PURE__ */ jsxs(Fragment, { children: [
86
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }),
87
- /* @__PURE__ */ jsx("span", { children: what })
88
- ] }) : null
85
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }),
86
+ /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__kind", children: what })
89
87
  ] }),
90
88
  item.source ? /* @__PURE__ */ jsx("span", { className: "crewlet-version-timeline__source", children: item.source }) : null,
91
89
  onCompare || onRestore || onLabel ? /* @__PURE__ */ jsxs("span", { className: "crewlet-version-timeline__actions", children: [
@@ -1,5 +1,5 @@
1
1
  import { useThemePreference, useDensityPreference } from './chunk-Z24ZUSTX.js';
2
- import { SegmentedControl } from './chunk-7QL2OFP6.js';
2
+ import { SegmentedControl } from './chunk-RCQXUT5K.js';
3
3
  import { SunGlyph, MonitorGlyph, MoonGlyph } from '@crewlethq/icons/glyphs';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
@@ -1,4 +1,4 @@
1
- import { changeText, sheetLabels } from './chunk-YYZRLLLY.js';
1
+ import { changeText, sheetLabels } from './chunk-NHBP2XS5.js';
2
2
  import { Tooltip } from './chunk-QWOPX2MN.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ChangeMark-3VMTW7MT.css';