@crewlethq/ui 0.28.0 → 0.30.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 (95) hide show
  1. package/README.md +45 -4
  2. package/dist/AccessDeniedCard/index.js +3 -3
  3. package/dist/Accordion/index.js +3 -3
  4. package/dist/AppShell/index.js +1 -1
  5. package/dist/{AppShell-APHZKJYH.css → AppShell-GCM4TDVY.css} +4 -1
  6. package/dist/ArtifactBar/ArtifactBar.d.ts +143 -0
  7. package/dist/ArtifactBar/index.d.ts +3 -0
  8. package/dist/ArtifactBar/index.js +25 -0
  9. package/dist/ArtifactBar-IBWB5POL.css +358 -0
  10. package/dist/ArtifactCard/index.js +3 -3
  11. package/dist/ArtifactCover/index.js +5 -5
  12. package/dist/ArtifactIcon/index.js +4 -4
  13. package/dist/ArtifactPanel/ArtifactPanel.d.ts +81 -0
  14. package/dist/ArtifactPanel/index.d.ts +3 -0
  15. package/dist/ArtifactPanel/index.js +5 -0
  16. package/dist/ArtifactPanel-YFXT5O77.css +132 -0
  17. package/dist/AuthLayout/index.js +3 -3
  18. package/dist/AvatarPicker/index.js +4 -4
  19. package/dist/Card/index.js +2 -2
  20. package/dist/ChangeMark/index.js +1 -1
  21. package/dist/CommandPalette/index.js +3 -3
  22. package/dist/CommentThread/index.js +5 -5
  23. package/dist/Composer/index.js +2 -2
  24. package/dist/DataView/index.js +4 -4
  25. package/dist/Disclosure/index.js +3 -3
  26. package/dist/Document/Document.d.ts +8 -1
  27. package/dist/Document/index.js +1 -1
  28. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  29. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  30. package/dist/EditingStatus/index.d.ts +3 -0
  31. package/dist/EditingStatus/index.js +2 -0
  32. package/dist/EditingStatus-NFADEPSX.css +53 -0
  33. package/dist/Editor-YZ7KG2RD.js +2099 -0
  34. package/dist/HuePicker/index.js +2 -2
  35. package/dist/ListInput/index.js +2 -2
  36. package/dist/Markdown/grammar.d.ts +170 -0
  37. package/dist/Markdown/index.d.ts +2 -0
  38. package/dist/Markdown/index.js +1 -0
  39. package/dist/MarkdownEditor/index.js +1 -1
  40. package/dist/PeopleRail/PeopleRail.d.ts +8 -1
  41. package/dist/PeopleRail/index.js +1 -1
  42. package/dist/{PeopleRail-R64WVOSH.css → PeopleRail-SZGHZXVT.css} +8 -0
  43. package/dist/RichEditor/Editor.d.ts +17 -0
  44. package/dist/RichEditor/RichEditor.d.ts +26 -0
  45. package/dist/RichEditor/codec.d.ts +78 -0
  46. package/dist/RichEditor/commands.d.ts +89 -0
  47. package/dist/RichEditor/index.d.ts +4 -0
  48. package/dist/RichEditor/index.js +8 -0
  49. package/dist/RichEditor/keys.d.ts +16 -0
  50. package/dist/RichEditor/nodeviews.d.ts +60 -0
  51. package/dist/RichEditor/paste.d.ts +47 -0
  52. package/dist/RichEditor/plugins.d.ts +49 -0
  53. package/dist/RichEditor/roundtrip.d.ts +14 -0
  54. package/dist/RichEditor/schema.d.ts +23 -0
  55. package/dist/RichEditor/types.d.ts +140 -0
  56. package/dist/RichEditor-NPD2KAPS.css +419 -0
  57. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  58. package/dist/RichEditorMarkdown/index.js +3 -0
  59. package/dist/SheetGrid/index.js +1 -1
  60. package/dist/ThemeSwitcher/index.js +1 -1
  61. package/dist/VersionCompare/index.js +2 -2
  62. package/dist/chunk-3DPIU2Q7.js +28 -0
  63. package/dist/{chunk-V2Z24W2Z.js → chunk-4JUKWWUD.js} +1 -1
  64. package/dist/{chunk-MQEEQVG6.js → chunk-6AH2XJ3Q.js} +2 -2
  65. package/dist/chunk-A4E5YLXO.js +85 -0
  66. package/dist/{chunk-WENCSQ47.js → chunk-EBNI36UQ.js} +1 -1
  67. package/dist/{chunk-6J35F334.js → chunk-GOSQXEZU.js} +1 -1
  68. package/dist/{chunk-M2VJGNCD.js → chunk-GR55WT4R.js} +3 -3
  69. package/dist/chunk-I3BSQUKN.js +121 -0
  70. package/dist/chunk-IDBHX5SR.js +12 -0
  71. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  72. package/dist/{chunk-S4RCG44T.js → chunk-MICH6QSJ.js} +1 -1
  73. package/dist/chunk-QMBP23BL.js +347 -0
  74. package/dist/{chunk-G2AVKPSL.js → chunk-RIAZM6L3.js} +1 -1
  75. package/dist/chunk-SKOYC2CF.js +288 -0
  76. package/dist/{chunk-PRNX5AFE.js → chunk-TGYDROIB.js} +1 -1
  77. package/dist/{chunk-G3EEUNZQ.js → chunk-UB7TJEKZ.js} +1 -1
  78. package/dist/chunk-UQHKFF2N.js +106 -0
  79. package/dist/{chunk-WHZFDS62.js → chunk-VDPJGP4Q.js} +1 -1
  80. package/dist/chunk-VOX3YRFO.js +76 -0
  81. package/dist/chunk-YFW4MTK4.js +749 -0
  82. package/dist/generated/index.d.ts +6 -0
  83. package/dist/generated/index.js +83 -75
  84. package/dist/index.js +83 -75
  85. package/dist/styles.css +8849 -7793
  86. package/package.json +13 -3
  87. package/dist/chunk-FVLCTCMV.js +0 -96
  88. package/dist/{chunk-RIEDQSA4.js → chunk-7DZDSSJS.js} +1 -1
  89. package/dist/{chunk-YZCJ63JF.js → chunk-ACA27MZH.js} +1 -1
  90. package/dist/{chunk-ENJUPIND.js → chunk-FZVJDJFN.js} +1 -1
  91. package/dist/{chunk-SGIQCI6Y.js → chunk-LIXSV5YI.js} +1 -1
  92. package/dist/{chunk-NWW4IQJU.js → chunk-OC46246T.js} +0 -0
  93. package/dist/{chunk-VOMYRJV5.js → chunk-RODMM35O.js} +2 -2
  94. package/dist/{chunk-HCKJGBQH.js → chunk-VVRL27HM.js} +1 -1
  95. package/dist/{chunk-D5JZN3ML.js → chunk-Z6VW6CXX.js} +1 -1
@@ -0,0 +1,85 @@
1
+ import { MARKDOWN_CALLOUT_NAMES } from './chunk-SKOYC2CF.js';
2
+
3
+ // src/RichEditor/types.ts
4
+ var RICH_EDITOR_LABELS = {
5
+ description: "Type a slash for blocks. Press Alt and F10 to reach the formatting toolbar.",
6
+ placeholder: "Write, or type a slash for blocks",
7
+ emptyLine: "Type / for blocks",
8
+ slashMenu: "Blocks",
9
+ slashEmpty: "No block matches",
10
+ slashGroupBlocks: "Blocks",
11
+ slashGroupInsert: "Insert",
12
+ blocks: {
13
+ paragraph: { label: "Text", description: "A plain paragraph" },
14
+ heading1: { label: "Heading 1", description: "A section heading" },
15
+ heading2: { label: "Heading 2", description: "A subsection heading" },
16
+ heading3: { label: "Heading 3", description: "A smaller heading" },
17
+ bullet: { label: "Bulleted list", description: "A simple list" },
18
+ ordered: { label: "Numbered list", description: "A list in order" },
19
+ task: { label: "Task list", description: "Items with a checkbox" },
20
+ quote: { label: "Quote", description: "Words set off from the text" },
21
+ callout: { label: "Callout", description: "A note that stands out" },
22
+ code: { label: "Code block", description: "Code, with its language" },
23
+ table: { label: "Table", description: "Rows and columns" },
24
+ divider: { label: "Divider", description: "A line between sections" },
25
+ image: { label: "Image", description: "A picture, by its address" }
26
+ },
27
+ toolbar: "Formatting",
28
+ bold: "Bold",
29
+ italic: "Italic",
30
+ strike: "Strikethrough",
31
+ code: "Inline code",
32
+ link: "Link",
33
+ heading: (level) => `Heading ${level}`,
34
+ linkPanel: "Link",
35
+ linkAddress: "Address",
36
+ linkText: "Text",
37
+ linkApply: "Apply",
38
+ linkRemove: "Remove link",
39
+ linkOpen: "Open link",
40
+ linkEdit: "Edit link",
41
+ linkInvalid: "Use an address that starts with https://, http://, mailto: or #/.",
42
+ linkRefused: "This address does not open from a page.",
43
+ imagePanel: "Image",
44
+ imageAddress: "Image address",
45
+ imageAlt: "Alt text",
46
+ imageAltHelp: "Describes the picture for anyone who cannot see it.",
47
+ imageInsert: "Insert image",
48
+ imageEdit: "Edit image",
49
+ imageRemove: "Remove image",
50
+ tableBar: "Table",
51
+ tableRow: "Row",
52
+ tableColumn: "Column",
53
+ rowAbove: "Insert row above",
54
+ rowBelow: "Insert row below",
55
+ rowDelete: "Delete row",
56
+ columnLeft: "Insert column left",
57
+ columnRight: "Insert column right",
58
+ columnDelete: "Delete column",
59
+ alignStart: "Align left",
60
+ alignCenter: "Align center",
61
+ alignEnd: "Align right",
62
+ tableDelete: "Delete table",
63
+ codeLanguage: "Code language",
64
+ codeLanguagePlaceholder: "Language",
65
+ calloutTone: "Callout type",
66
+ calloutRemove: "Remove callout",
67
+ tones: MARKDOWN_CALLOUT_NAMES,
68
+ taskDone: "Mark as done",
69
+ taskNotDone: "Mark as not done",
70
+ loading: "Loading the editor",
71
+ failed: "The editor did not load",
72
+ failedDetail: "The page may have been updated while it was open. Try again, or reload the page.",
73
+ retry: "Try again"
74
+ };
75
+ function richEditorLabels(overrides) {
76
+ if (!overrides) return RICH_EDITOR_LABELS;
77
+ return {
78
+ ...RICH_EDITOR_LABELS,
79
+ ...overrides,
80
+ blocks: { ...RICH_EDITOR_LABELS.blocks, ...overrides.blocks },
81
+ tones: { ...RICH_EDITOR_LABELS.tones, ...overrides.tones }
82
+ };
83
+ }
84
+
85
+ export { RICH_EDITOR_LABELS, richEditorLabels };
@@ -4,7 +4,7 @@ import { useModalLayer, focusables } from './chunk-R25RGPUB.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';
7
- import './AppShell-APHZKJYH.css';
7
+ import './AppShell-GCM4TDVY.css';
8
8
  import { createContext, forwardRef, useContext, useId, useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
9
9
  import { breakpoint } from '@crewlethq/tokens';
10
10
  import { ChevronUpGlyph, ChevronsUpDownGlyph, ChevronRightGlyph, MenuGlyph } from '@crewlethq/icons/glyphs';
@@ -1,7 +1,7 @@
1
1
  import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
2
2
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
3
3
  import { AvatarStack } from './chunk-UAN5NE7M.js';
4
- import { Card } from './chunk-YZCJ63JF.js';
4
+ import { Card } from './chunk-ACA27MZH.js';
5
5
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './ArtifactCard-EXVAEBV6.css';
@@ -1,9 +1,9 @@
1
- import { Composer } from './chunk-RIEDQSA4.js';
2
- import { Document } from './chunk-WI6K5M5X.js';
1
+ import { Composer } from './chunk-7DZDSSJS.js';
2
+ import { Document } from './chunk-M3LUNN7F.js';
3
3
  import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
4
4
  import { toInstant, RelativeTime, formatExact, toISO } from './chunk-3CZ7XAVY.js';
5
- import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
6
5
  import { Count } from './chunk-BHHIIK3M.js';
6
+ import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
7
7
  import { Button } from './chunk-OG6CL3EB.js';
8
8
  import { IconButton } from './chunk-4FQT6ZAY.js';
9
9
  import { cx } from './chunk-ODEQTPFM.js';
@@ -0,0 +1,121 @@
1
+ import { HeadingLevelProvider } from './chunk-PQADV6P6.js';
2
+ import { IconButton } from './chunk-4FQT6ZAY.js';
3
+ import { cx } from './chunk-ODEQTPFM.js';
4
+ import './ArtifactPanel-YFXT5O77.css';
5
+ import { useId, useRef, useLayoutEffect, useEffect } from 'react';
6
+ import { MinimizeGlyph, MaximizeGlyph, XGlyph } from '@crewlethq/icons/glyphs';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var ARTIFACT_PANEL_LABELS = {
10
+ close: (title) => `Close ${title.toLowerCase()}`,
11
+ expand: "Expand to the full view",
12
+ collapse: "Back to the side"
13
+ };
14
+ function ArtifactPanel({
15
+ title,
16
+ icon,
17
+ onClose,
18
+ size = "md",
19
+ expanded = false,
20
+ onExpandedChange,
21
+ actions,
22
+ focusOnOpen = true,
23
+ labels,
24
+ className,
25
+ children
26
+ }) {
27
+ const words = { ...ARTIFACT_PANEL_LABELS, ...labels };
28
+ const titleId = useId();
29
+ const root = useRef(null);
30
+ const heading = useRef(null);
31
+ const before = useRef(null);
32
+ const focusing = useRef(focusOnOpen);
33
+ useLayoutEffect(() => {
34
+ const panel = root.current;
35
+ before.current = document.activeElement;
36
+ if (focusing.current) heading.current?.focus({ preventScroll: true });
37
+ return () => {
38
+ const back = before.current;
39
+ if (panel?.contains(document.activeElement) && back instanceof HTMLElement && back.isConnected) {
40
+ back.focus({ preventScroll: true });
41
+ }
42
+ };
43
+ }, []);
44
+ const close = useRef(onClose);
45
+ close.current = onClose;
46
+ useEffect(() => {
47
+ const panel = root.current;
48
+ if (!panel) return void 0;
49
+ const doc = panel.ownerDocument;
50
+ const onKeyDown = (event) => {
51
+ if (event.key !== "Escape" || event.defaultPrevented || event.isComposing) return;
52
+ if (!(event.target instanceof Node) || !panel.contains(event.target)) return;
53
+ event.preventDefault();
54
+ close.current();
55
+ };
56
+ doc.addEventListener("keydown", onKeyDown);
57
+ return () => doc.removeEventListener("keydown", onKeyDown);
58
+ }, []);
59
+ return /* @__PURE__ */ jsxs(
60
+ "aside",
61
+ {
62
+ ref: root,
63
+ className: cx("crewlet-artifact-panel", `crewlet-artifact-panel--${size}`, className),
64
+ "aria-labelledby": titleId,
65
+ "data-expanded": expanded || void 0,
66
+ children: [
67
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-artifact-panel__head", children: [
68
+ icon ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-panel__icon", "aria-hidden": true, children: icon }) : null,
69
+ /* @__PURE__ */ jsx("h2", { ref: heading, id: titleId, className: "crewlet-artifact-panel__title", tabIndex: -1, children: title }),
70
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-artifact-panel__actions", children: [
71
+ actions,
72
+ onExpandedChange ? /* @__PURE__ */ jsx(
73
+ IconButton,
74
+ {
75
+ label: expanded ? words.collapse : words.expand,
76
+ icon: expanded ? /* @__PURE__ */ jsx(MinimizeGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(MaximizeGlyph, { size: "sm" }),
77
+ size: "sm",
78
+ variant: "ghost",
79
+ onClick: () => onExpandedChange(!expanded)
80
+ }
81
+ ) : null,
82
+ /* @__PURE__ */ jsx(IconButton, { label: words.close(title), icon: /* @__PURE__ */ jsx(XGlyph, { size: "sm" }), size: "sm", variant: "ghost", onClick: onClose })
83
+ ] })
84
+ ] }),
85
+ /* @__PURE__ */ jsx("div", { className: "crewlet-artifact-panel__body", children: /* @__PURE__ */ jsx(HeadingLevelProvider, { level: 3, children }) })
86
+ ]
87
+ }
88
+ );
89
+ }
90
+ function ArtifactWorkspace({
91
+ panel,
92
+ expanded = false,
93
+ bodyRef,
94
+ bodyClassName,
95
+ bodyLabel,
96
+ className,
97
+ children
98
+ }) {
99
+ return /* @__PURE__ */ jsxs(
100
+ "div",
101
+ {
102
+ className: cx("crewlet-artifact-workspace", className),
103
+ "data-panel": panel ? expanded ? "expanded" : "open" : void 0,
104
+ children: [
105
+ /* @__PURE__ */ jsx(
106
+ "div",
107
+ {
108
+ ref: bodyRef,
109
+ className: cx("crewlet-artifact-workspace__body", bodyClassName),
110
+ role: bodyLabel ? "region" : void 0,
111
+ "aria-label": bodyLabel,
112
+ children
113
+ }
114
+ ),
115
+ panel
116
+ ]
117
+ }
118
+ );
119
+ }
120
+
121
+ export { ARTIFACT_PANEL_LABELS, ArtifactPanel, ArtifactWorkspace };
@@ -0,0 +1,12 @@
1
+ import { readMarkdown, writeMarkdown } from './chunk-YFW4MTK4.js';
2
+
3
+ // src/RichEditor/roundtrip.ts
4
+ function roundTripMarkdown(markdown) {
5
+ const { doc, source } = readMarkdown(markdown);
6
+ return writeMarkdown(doc, source);
7
+ }
8
+ function canonicalMarkdown(markdown) {
9
+ return writeMarkdown(readMarkdown(markdown).doc);
10
+ }
11
+
12
+ export { canonicalMarkdown, roundTripMarkdown };
@@ -1,5 +1,5 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './Document-PQGXJHB7.css';
2
+ import './Document-G3YTZIUL.css';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  function Document({ as: Tag = "div", size = "md", measure = "normal", className, children, ...rest }) {
@@ -1,4 +1,4 @@
1
- import { DisclosureAnatomy } from './chunk-ENJUPIND.js';
1
+ import { DisclosureAnatomy } from './chunk-FZVJDJFN.js';
2
2
  import { useHeadingLevel } from './chunk-PQADV6P6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Disclosure-VKBJJIZ7.css';
@@ -0,0 +1,347 @@
1
+ import { isApplePlatform, Kbd } from './chunk-SMBKXWML.js';
2
+ import { Tooltip } from './chunk-QWOPX2MN.js';
3
+ import { SegmentedControl } from './chunk-RCQXUT5K.js';
4
+ import { ArtifactIcon } from './chunk-4JUKWWUD.js';
5
+ import { Menu } from './chunk-2HIOJ4YZ.js';
6
+ import { Button } from './chunk-OG6CL3EB.js';
7
+ import { IconButton } from './chunk-4FQT6ZAY.js';
8
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
9
+ import { cx } from './chunk-ODEQTPFM.js';
10
+ import './ArtifactBar-IBWB5POL.css';
11
+ import { useId, useState, useRef, useEffect } from 'react';
12
+ import { ChevronLeftGlyph, EllipsisGlyph, ChevronDownGlyph } from '@crewlethq/icons/glyphs';
13
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
14
+
15
+ var ARTIFACT_BAR_LABELS = {
16
+ more: (title) => `More for \u201C${title}\u201D`,
17
+ renameHint: "Rename",
18
+ titleField: "Title",
19
+ emptyTitle: "A title cannot be empty."
20
+ };
21
+ function ArtifactBar({
22
+ title,
23
+ kind,
24
+ icon,
25
+ kindLabel,
26
+ back,
27
+ start,
28
+ onRename,
29
+ renaming,
30
+ onRenamingChange,
31
+ version,
32
+ modes,
33
+ presence,
34
+ kindTools = [],
35
+ tools = [],
36
+ menu = [],
37
+ as = "header",
38
+ headingLevel = 1,
39
+ pending = false,
40
+ labels,
41
+ className
42
+ }) {
43
+ const words = { ...ARTIFACT_BAR_LABELS, ...labels };
44
+ const headingId = useId();
45
+ const Root = as;
46
+ const apple = isApplePlatform();
47
+ const folding = [...kindTools, ...tools].filter((t) => !t.labelled);
48
+ const pinned = [...kindTools, ...tools].filter((t) => t.labelled);
49
+ const folded = [
50
+ ...modes ? modes.options.map(
51
+ (option) => ({
52
+ key: `mode:${option.value}`,
53
+ label: option.label,
54
+ icon: option.icon,
55
+ checked: option.value === modes.value,
56
+ onSelect: () => modes.onValueChange(option.value)
57
+ })
58
+ ) : [],
59
+ ...modes && folding.length > 0 ? [{ kind: "separator", key: "sep:modes" }] : [],
60
+ ...folding.map(
61
+ (tool) => ({
62
+ key: `tool:${tool.key}`,
63
+ label: tool.label,
64
+ icon: tool.icon,
65
+ onSelect: tool.onSelect,
66
+ ...tool.disabledReason !== void 0 ? { disabled: true, description: tool.disabledReason } : {},
67
+ ...tool.keys ? { hint: /* @__PURE__ */ jsx(Kbd, { keys: tool.keys, subtle: true, apple }) } : {}
68
+ })
69
+ )
70
+ ];
71
+ const narrowMenu = [
72
+ ...folded,
73
+ ...folded.length > 0 && menu.length > 0 ? [{ kind: "separator", key: "sep:menu" }] : [],
74
+ ...menu
75
+ ];
76
+ return /* @__PURE__ */ jsx(
77
+ Root,
78
+ {
79
+ className: cx("crewlet-artifact-bar", presence ? "crewlet-artifact-bar--present" : null, className),
80
+ "aria-labelledby": pending ? void 0 : headingId,
81
+ children: /* @__PURE__ */ jsxs("div", { className: cx("crewlet-artifact-bar__row", modes && "crewlet-artifact-bar__row--centred"), children: [
82
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-artifact-bar__lead", children: [
83
+ start,
84
+ back ? /* @__PURE__ */ jsx(Tooltip, { content: back.label, placement: "bottom", children: /* @__PURE__ */ jsx(IconButton, { asChild: true, label: back.label, size: "sm", variant: "ghost", title: "", children: /* @__PURE__ */ jsx("a", { href: back.href, children: /* @__PURE__ */ jsx(ChevronLeftGlyph, { size: "sm" }) }) }) }) : null,
85
+ /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__glyph", role: "img", "aria-label": kindLabel, title: kindLabel, children: /* @__PURE__ */ jsx(ArtifactIcon, { icon: icon ?? void 0, kind, size: "sm" }) }),
86
+ pending ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__placeholder", "aria-hidden": true }) : /* @__PURE__ */ jsx(
87
+ BarTitle,
88
+ {
89
+ title,
90
+ id: headingId,
91
+ level: headingLevel,
92
+ onRename,
93
+ renaming,
94
+ onRenamingChange,
95
+ words
96
+ }
97
+ ),
98
+ version ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__version", children: version }) : null
99
+ ] }),
100
+ modes ? /* @__PURE__ */ jsx("div", { className: "crewlet-artifact-bar__modes crewlet-artifact-bar__wide", children: /* @__PURE__ */ jsx(
101
+ SegmentedControl,
102
+ {
103
+ label: modes.label,
104
+ semantics: "radio",
105
+ size: "sm",
106
+ options: modes.options.map((o) => ({ value: o.value, label: o.label, ...o.icon ? { icon: o.icon } : {} })),
107
+ value: modes.value,
108
+ onValueChange: modes.onValueChange
109
+ }
110
+ ) }) : null,
111
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-artifact-bar__end", children: [
112
+ presence ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__presence", children: presence }) : null,
113
+ kindTools.some((t) => !t.labelled) ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__tools crewlet-artifact-bar__wide", children: kindTools.filter((t) => !t.labelled).map((tool) => /* @__PURE__ */ jsx(ToolButton, { tool, apple }, tool.key)) }) : null,
114
+ tools.some((t) => !t.labelled) ? /* @__PURE__ */ jsxs("span", { className: "crewlet-artifact-bar__tools crewlet-artifact-bar__wide", children: [
115
+ kindTools.some((t) => !t.labelled) ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__rule", "aria-hidden": true }) : null,
116
+ tools.filter((t) => !t.labelled).map((tool) => /* @__PURE__ */ jsx(ToolButton, { tool, apple }, tool.key))
117
+ ] }) : null,
118
+ pinned.length > 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__tools", children: pinned.map((tool) => /* @__PURE__ */ jsx(LabelledTool, { tool, apple }, tool.key)) }) : null,
119
+ menu.length > 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__wide", children: /* @__PURE__ */ jsx(Menu, { label: words.more(title), icon: /* @__PURE__ */ jsx(EllipsisGlyph, { size: "sm" }), triggerVariant: "ghost", align: "end", items: menu }) }) : null,
120
+ narrowMenu.length > 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__narrow", children: /* @__PURE__ */ jsx(
121
+ Menu,
122
+ {
123
+ label: words.more(title),
124
+ icon: /* @__PURE__ */ jsx(EllipsisGlyph, { size: "sm" }),
125
+ triggerVariant: "ghost",
126
+ align: "end",
127
+ items: narrowMenu
128
+ }
129
+ ) }) : null
130
+ ] })
131
+ ] })
132
+ }
133
+ );
134
+ }
135
+ function ariaKeys(keys, apple) {
136
+ return keys.map((key) => {
137
+ if (key === "Mod") return apple ? "Meta" : "Control";
138
+ return key.length === 1 ? key.toUpperCase() : key;
139
+ }).join("+");
140
+ }
141
+ function Tip({ tool, apple }) {
142
+ return /* @__PURE__ */ jsxs("span", { className: "crewlet-artifact-bar__tip", children: [
143
+ tool.label,
144
+ tool.keys ? /* @__PURE__ */ jsx(Kbd, { keys: tool.keys, subtle: true, apple }) : null
145
+ ] });
146
+ }
147
+ function ToolButton({ tool, apple }) {
148
+ return /* @__PURE__ */ jsxs("span", { className: "crewlet-artifact-bar__tool", children: [
149
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(Tip, { tool, apple }), placement: "bottom", children: /* @__PURE__ */ jsx(
150
+ IconButton,
151
+ {
152
+ label: tool.label,
153
+ icon: tool.icon,
154
+ size: "sm",
155
+ variant: "ghost",
156
+ title: "",
157
+ pressed: tool.pressed,
158
+ disabledReason: tool.disabledReason,
159
+ "aria-keyshortcuts": tool.keys ? ariaKeys(tool.keys, apple) : void 0,
160
+ onClick: tool.onSelect
161
+ }
162
+ ) }),
163
+ tool.badge !== void 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__badge", "aria-hidden": true, children: tool.badge }) : null
164
+ ] });
165
+ }
166
+ function LabelledTool({ tool, apple }) {
167
+ const shortcut = tool.keys ? ariaKeys(tool.keys, apple) : void 0;
168
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
169
+ /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__roomy", children: /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(Tip, { tool, apple }), placement: "bottom", disabled: !tool.keys, children: /* @__PURE__ */ jsx(
170
+ Button,
171
+ {
172
+ size: "small",
173
+ variant: "secondary",
174
+ leadingIcon: tool.icon,
175
+ pressed: tool.pressed,
176
+ disabledReason: tool.disabledReason,
177
+ "aria-keyshortcuts": shortcut,
178
+ onClick: tool.onSelect,
179
+ children: tool.label
180
+ }
181
+ ) }) }),
182
+ /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__tight", children: /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(Tip, { tool, apple }), placement: "bottom", children: /* @__PURE__ */ jsx(
183
+ IconButton,
184
+ {
185
+ label: tool.label,
186
+ icon: tool.icon,
187
+ size: "sm",
188
+ variant: "ghost",
189
+ title: "",
190
+ pressed: tool.pressed,
191
+ disabledReason: tool.disabledReason,
192
+ "aria-keyshortcuts": shortcut,
193
+ onClick: tool.onSelect
194
+ }
195
+ ) }) })
196
+ ] });
197
+ }
198
+ function BarTitle({
199
+ title,
200
+ id,
201
+ level,
202
+ onRename,
203
+ renaming,
204
+ onRenamingChange,
205
+ words
206
+ }) {
207
+ const Heading = `h${level}`;
208
+ const hintId = useId();
209
+ const errorId = useId();
210
+ const [own, setOwn] = useState(false);
211
+ const editing = (renaming ?? own) && onRename !== void 0;
212
+ const setEditing = (on) => {
213
+ if (renaming === void 0) setOwn(on);
214
+ onRenamingChange?.(on);
215
+ };
216
+ const [draft, setDraft] = useState(title);
217
+ const [error, setError] = useState(null);
218
+ const [busy, setBusy] = useState(false);
219
+ const field = useRef(null);
220
+ const button = useRef(null);
221
+ const settled = useRef(false);
222
+ useEffect(() => {
223
+ if (!editing) return;
224
+ settled.current = false;
225
+ setDraft(title);
226
+ setError(null);
227
+ const el = field.current;
228
+ el?.focus();
229
+ el?.select();
230
+ }, [editing]);
231
+ if (onRename === void 0) {
232
+ return /* @__PURE__ */ jsx(Heading, { id, className: "crewlet-artifact-bar__title", title, children: title });
233
+ }
234
+ const finish = (refocus) => {
235
+ settled.current = true;
236
+ setEditing(false);
237
+ setError(null);
238
+ if (refocus) requestAnimationFrame(() => button.current?.focus());
239
+ };
240
+ const commit = async (refocus) => {
241
+ if (settled.current || busy) return;
242
+ const next = draft.trim();
243
+ if (next === title) {
244
+ finish(refocus);
245
+ return;
246
+ }
247
+ if (next === "") {
248
+ setError(words.emptyTitle);
249
+ return;
250
+ }
251
+ setBusy(true);
252
+ try {
253
+ const answer = await onRename(next);
254
+ if (typeof answer === "string" && answer !== "") {
255
+ setError(answer);
256
+ field.current?.focus();
257
+ return;
258
+ }
259
+ finish(refocus);
260
+ } finally {
261
+ setBusy(false);
262
+ }
263
+ };
264
+ const onKeyDown = (event) => {
265
+ if (event.nativeEvent.isComposing) return;
266
+ if (event.key === "Enter") {
267
+ event.preventDefault();
268
+ void commit(true);
269
+ } else if (event.key === "Escape") {
270
+ event.preventDefault();
271
+ event.stopPropagation();
272
+ finish(true);
273
+ }
274
+ };
275
+ if (editing) {
276
+ return /* @__PURE__ */ jsxs(Heading, { id, className: "crewlet-artifact-bar__title crewlet-artifact-bar__title--editing", children: [
277
+ /* @__PURE__ */ jsx("span", { className: "crewlet-artifact-bar__sizer", "data-value": draft || " ", children: /* @__PURE__ */ jsx(
278
+ "input",
279
+ {
280
+ ref: field,
281
+ className: "crewlet-artifact-bar__field",
282
+ "aria-label": words.titleField,
283
+ "aria-invalid": error ? true : void 0,
284
+ "aria-describedby": error ? errorId : void 0,
285
+ "aria-busy": busy || void 0,
286
+ readOnly: busy,
287
+ value: draft,
288
+ size: 1,
289
+ onChange: (event) => {
290
+ setDraft(event.target.value);
291
+ if (error) setError(null);
292
+ },
293
+ onKeyDown,
294
+ onBlur: () => void commit(false)
295
+ }
296
+ ) }),
297
+ error ? /* @__PURE__ */ jsx("span", { id: errorId, role: "alert", className: "crewlet-artifact-bar__error", children: error }) : null
298
+ ] });
299
+ }
300
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
301
+ /* @__PURE__ */ jsx(Heading, { id, className: "crewlet-artifact-bar__title", children: /* @__PURE__ */ jsx(
302
+ "button",
303
+ {
304
+ ref: button,
305
+ type: "button",
306
+ className: "crewlet-artifact-bar__rename",
307
+ title,
308
+ "aria-describedby": hintId,
309
+ onClick: () => setEditing(true),
310
+ children: title
311
+ }
312
+ ) }),
313
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: hintId, children: words.renameHint })
314
+ ] });
315
+ }
316
+ function ArtifactVersionChip({
317
+ version,
318
+ latest,
319
+ items,
320
+ label = "Versions",
321
+ format = (v, l) => v === l ? `v${v}` : `v${v} of ${l}`
322
+ }) {
323
+ const older = version !== latest;
324
+ return /* @__PURE__ */ jsx(
325
+ Menu,
326
+ {
327
+ label,
328
+ items,
329
+ align: "start",
330
+ renderTrigger: (props) => /* @__PURE__ */ jsxs(
331
+ "button",
332
+ {
333
+ ...props,
334
+ type: "button",
335
+ className: cx("crewlet-version-chip", older && "crewlet-version-chip--older"),
336
+ "aria-label": `${label}: ${format(version, latest)}`,
337
+ children: [
338
+ /* @__PURE__ */ jsx("span", { className: "crewlet-version-chip__words", children: format(version, latest) }),
339
+ /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "xs" })
340
+ ]
341
+ }
342
+ )
343
+ }
344
+ );
345
+ }
346
+
347
+ export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip };
@@ -1,4 +1,4 @@
1
- import { DisclosureAnatomy } from './chunk-ENJUPIND.js';
1
+ import { DisclosureAnatomy } from './chunk-FZVJDJFN.js';
2
2
  import { useHeadingLevel } from './chunk-PQADV6P6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Disclosure-VKBJJIZ7.css';