@oh-just-another/react-ui 0.57.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 (186) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +54 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/bottom-sheet.d.ts +26 -0
  6. package/dist/bottom-sheet.d.ts.map +1 -0
  7. package/dist/bottom-sheet.js +87 -0
  8. package/dist/bottom-sheet.js.map +1 -0
  9. package/dist/button-group.d.ts +14 -0
  10. package/dist/button-group.d.ts.map +1 -0
  11. package/dist/button-group.js +3 -0
  12. package/dist/button-group.js.map +1 -0
  13. package/dist/color-palette.d.ts +34 -0
  14. package/dist/color-palette.d.ts.map +1 -0
  15. package/dist/color-palette.js +77 -0
  16. package/dist/color-palette.js.map +1 -0
  17. package/dist/color-swatch-picker.d.ts +29 -0
  18. package/dist/color-swatch-picker.d.ts.map +1 -0
  19. package/dist/color-swatch-picker.js +56 -0
  20. package/dist/color-swatch-picker.js.map +1 -0
  21. package/dist/command-palette.d.ts +13 -0
  22. package/dist/command-palette.d.ts.map +1 -0
  23. package/dist/command-palette.js +146 -0
  24. package/dist/command-palette.js.map +1 -0
  25. package/dist/comments-panel.d.ts +27 -0
  26. package/dist/comments-panel.d.ts.map +1 -0
  27. package/dist/comments-panel.js +139 -0
  28. package/dist/comments-panel.js.map +1 -0
  29. package/dist/constants.d.ts +112 -0
  30. package/dist/constants.d.ts.map +1 -0
  31. package/dist/constants.js +119 -0
  32. package/dist/constants.js.map +1 -0
  33. package/dist/context-menu-controller.d.ts +41 -0
  34. package/dist/context-menu-controller.d.ts.map +1 -0
  35. package/dist/context-menu-controller.js +26 -0
  36. package/dist/context-menu-controller.js.map +1 -0
  37. package/dist/context-menu.d.ts +53 -0
  38. package/dist/context-menu.d.ts.map +1 -0
  39. package/dist/context-menu.js +333 -0
  40. package/dist/context-menu.js.map +1 -0
  41. package/dist/context.d.ts +44 -0
  42. package/dist/context.d.ts.map +1 -0
  43. package/dist/context.js +95 -0
  44. package/dist/context.js.map +1 -0
  45. package/dist/diagram-bars.d.ts +21 -0
  46. package/dist/diagram-bars.d.ts.map +1 -0
  47. package/dist/diagram-bars.js +4 -0
  48. package/dist/diagram-bars.js.map +1 -0
  49. package/dist/diagram-canvas.d.ts +39 -0
  50. package/dist/diagram-canvas.d.ts.map +1 -0
  51. package/dist/diagram-canvas.js +9 -0
  52. package/dist/diagram-canvas.js.map +1 -0
  53. package/dist/diagram-root.d.ts +70 -0
  54. package/dist/diagram-root.d.ts.map +1 -0
  55. package/dist/diagram-root.js +180 -0
  56. package/dist/diagram-root.js.map +1 -0
  57. package/dist/diff-panel.d.ts +25 -0
  58. package/dist/diff-panel.d.ts.map +1 -0
  59. package/dist/diff-panel.js +77 -0
  60. package/dist/diff-panel.js.map +1 -0
  61. package/dist/edge-style-panel.d.ts +19 -0
  62. package/dist/edge-style-panel.d.ts.map +1 -0
  63. package/dist/edge-style-panel.js +120 -0
  64. package/dist/edge-style-panel.js.map +1 -0
  65. package/dist/frame-name-editor-overlay.d.ts +13 -0
  66. package/dist/frame-name-editor-overlay.d.ts.map +1 -0
  67. package/dist/frame-name-editor-overlay.js +84 -0
  68. package/dist/frame-name-editor-overlay.js.map +1 -0
  69. package/dist/frame-panel.d.ts +19 -0
  70. package/dist/frame-panel.d.ts.map +1 -0
  71. package/dist/frame-panel.js +66 -0
  72. package/dist/frame-panel.js.map +1 -0
  73. package/dist/help-button.d.ts +16 -0
  74. package/dist/help-button.d.ts.map +1 -0
  75. package/dist/help-button.js +14 -0
  76. package/dist/help-button.js.map +1 -0
  77. package/dist/help-dialog.d.ts +56 -0
  78. package/dist/help-dialog.d.ts.map +1 -0
  79. package/dist/help-dialog.js +142 -0
  80. package/dist/help-dialog.js.map +1 -0
  81. package/dist/hooks.d.ts +54 -0
  82. package/dist/hooks.d.ts.map +1 -0
  83. package/dist/hooks.js +85 -0
  84. package/dist/hooks.js.map +1 -0
  85. package/dist/icon-button.d.ts +28 -0
  86. package/dist/icon-button.d.ts.map +1 -0
  87. package/dist/icon-button.js +14 -0
  88. package/dist/icon-button.js.map +1 -0
  89. package/dist/index.d.ts +45 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +46 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/layer-panel.d.ts +13 -0
  94. package/dist/layer-panel.d.ts.map +1 -0
  95. package/dist/layer-panel.js +109 -0
  96. package/dist/layer-panel.js.map +1 -0
  97. package/dist/library-panel.d.ts +33 -0
  98. package/dist/library-panel.d.ts.map +1 -0
  99. package/dist/library-panel.js +37 -0
  100. package/dist/library-panel.js.map +1 -0
  101. package/dist/link-caption-editor.d.ts +8 -0
  102. package/dist/link-caption-editor.d.ts.map +1 -0
  103. package/dist/link-caption-editor.js +65 -0
  104. package/dist/link-caption-editor.js.map +1 -0
  105. package/dist/link-drop-shape-menu.d.ts +12 -0
  106. package/dist/link-drop-shape-menu.d.ts.map +1 -0
  107. package/dist/link-drop-shape-menu.js +55 -0
  108. package/dist/link-drop-shape-menu.js.map +1 -0
  109. package/dist/link-hover-popup.d.ts +2 -0
  110. package/dist/link-hover-popup.d.ts.map +1 -0
  111. package/dist/link-hover-popup.js +96 -0
  112. package/dist/link-hover-popup.js.map +1 -0
  113. package/dist/main-menu.d.ts +67 -0
  114. package/dist/main-menu.d.ts.map +1 -0
  115. package/dist/main-menu.js +243 -0
  116. package/dist/main-menu.js.map +1 -0
  117. package/dist/markdown.d.ts +10 -0
  118. package/dist/markdown.d.ts.map +1 -0
  119. package/dist/markdown.js +131 -0
  120. package/dist/markdown.js.map +1 -0
  121. package/dist/merge-dialog.d.ts +22 -0
  122. package/dist/merge-dialog.d.ts.map +1 -0
  123. package/dist/merge-dialog.js +46 -0
  124. package/dist/merge-dialog.js.map +1 -0
  125. package/dist/modal.d.ts +19 -0
  126. package/dist/modal.d.ts.map +1 -0
  127. package/dist/modal.js +87 -0
  128. package/dist/modal.js.map +1 -0
  129. package/dist/palette.d.ts +73 -0
  130. package/dist/palette.d.ts.map +1 -0
  131. package/dist/palette.js +330 -0
  132. package/dist/palette.js.map +1 -0
  133. package/dist/popover.d.ts +33 -0
  134. package/dist/popover.d.ts.map +1 -0
  135. package/dist/popover.js +107 -0
  136. package/dist/popover.js.map +1 -0
  137. package/dist/property-panel.d.ts +32 -0
  138. package/dist/property-panel.d.ts.map +1 -0
  139. package/dist/property-panel.js +728 -0
  140. package/dist/property-panel.js.map +1 -0
  141. package/dist/reset-to-content-button.d.ts +10 -0
  142. package/dist/reset-to-content-button.d.ts.map +1 -0
  143. package/dist/reset-to-content-button.js +62 -0
  144. package/dist/reset-to-content-button.js.map +1 -0
  145. package/dist/segmented-control.d.ts +23 -0
  146. package/dist/segmented-control.d.ts.map +1 -0
  147. package/dist/segmented-control.js +5 -0
  148. package/dist/segmented-control.js.map +1 -0
  149. package/dist/selection-floating-panel.d.ts +56 -0
  150. package/dist/selection-floating-panel.d.ts.map +1 -0
  151. package/dist/selection-floating-panel.js +251 -0
  152. package/dist/selection-floating-panel.js.map +1 -0
  153. package/dist/sidebar.d.ts +31 -0
  154. package/dist/sidebar.d.ts.map +1 -0
  155. package/dist/sidebar.js +66 -0
  156. package/dist/sidebar.js.map +1 -0
  157. package/dist/slider.d.ts +20 -0
  158. package/dist/slider.d.ts.map +1 -0
  159. package/dist/slider.js +9 -0
  160. package/dist/slider.js.map +1 -0
  161. package/dist/text-editor-overlay.d.ts +16 -0
  162. package/dist/text-editor-overlay.d.ts.map +1 -0
  163. package/dist/text-editor-overlay.js +112 -0
  164. package/dist/text-editor-overlay.js.map +1 -0
  165. package/dist/toast.d.ts +34 -0
  166. package/dist/toast.d.ts.map +1 -0
  167. package/dist/toast.js +89 -0
  168. package/dist/toast.js.map +1 -0
  169. package/dist/toolbar.d.ts +149 -0
  170. package/dist/toolbar.d.ts.map +1 -0
  171. package/dist/toolbar.js +282 -0
  172. package/dist/toolbar.js.map +1 -0
  173. package/dist/tooltip.d.ts +21 -0
  174. package/dist/tooltip.d.ts.map +1 -0
  175. package/dist/tooltip.js +217 -0
  176. package/dist/tooltip.js.map +1 -0
  177. package/dist/ui-layer.d.ts +22 -0
  178. package/dist/ui-layer.d.ts.map +1 -0
  179. package/dist/ui-layer.js +3 -0
  180. package/dist/ui-layer.js.map +1 -0
  181. package/dist/versioning.d.ts +32 -0
  182. package/dist/versioning.d.ts.map +1 -0
  183. package/dist/versioning.js +206 -0
  184. package/dist/versioning.js.map +1 -0
  185. package/package.json +81 -0
  186. package/src/styles.css +1502 -0
@@ -0,0 +1,282 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Circle, Frame, Hand, Image as ImageIcon, Lock, MousePointer2, PenLine, Redo2, Slash, Square, Type, Undo2, } from "lucide-react";
4
+ import { defaultActionRegistry, formatHotkey } from "@oh-just-another/state";
5
+ import { useEditorSelector } from "./context.js";
6
+ import { useDiagramOptional, useHistory, useMode } from "./hooks.js";
7
+ import { TOOLBAR_SEPARATOR_HEIGHT } from "./constants.js";
8
+ import { Tooltip } from "./tooltip.js";
9
+ /**
10
+ * Pixel size for icons rendered inside `du-icon-button` (32-px
11
+ * inside-group footprint). Lucide draws crisp at 16 px stroke-width
12
+ * 1.75.
13
+ */
14
+ const TOOLBAR_ICON_SIZE = 16;
15
+ const TOOLBAR_ICON_STROKE = 1.75;
16
+ const iconProps = { size: TOOLBAR_ICON_SIZE, strokeWidth: TOOLBAR_ICON_STROKE };
17
+ /**
18
+ * Maps an action's serializable `iconId` (declared in core, no React) to a
19
+ * concrete lucide icon, so a registry-driven `action-ref` button renders
20
+ * identically to the hardcoded toolbar.
21
+ */
22
+ const ACTION_ICONS = {
23
+ "mode-select": MousePointer2,
24
+ "mode-hand": Hand,
25
+ "mode-rect": Square,
26
+ "mode-ellipse": Circle,
27
+ "mode-text": Type,
28
+ "mode-edge": Slash,
29
+ "mode-brush": PenLine,
30
+ "mode-frame": Frame,
31
+ "insert-image": ImageIcon,
32
+ "tool-lock": Lock,
33
+ undo: Undo2,
34
+ redo: Redo2,
35
+ };
36
+ /**
37
+ * Toolbar button sourced entirely from a registered action: label, icon
38
+ * (via `iconId`), hotkey tooltip, pressed state (`checked`) and disabled
39
+ * state (`predicate`) all come from `defaultActionRegistry`. Clicking
40
+ * dispatches the action. Subscribes to the editor's `change` event so the
41
+ * checked/disabled state stays live. Renders nothing if the action isn't
42
+ * registered (e.g. a host that didn't register `insert-image`).
43
+ */
44
+ const ActionRefButton = ({ id }) => {
45
+ const editor = useDiagramOptional();
46
+ const [, force] = useState(0);
47
+ useEffect(() => {
48
+ if (!editor)
49
+ return undefined;
50
+ return editor.on("change", () => { force((n) => n + 1); });
51
+ }, [editor]);
52
+ const action = defaultActionRegistry.get(id);
53
+ if (!action)
54
+ return null;
55
+ const Icon = action.iconId ? ACTION_ICONS[action.iconId] : undefined;
56
+ const ctx = editor ? { editor } : null;
57
+ const active = ctx ? (action.checked?.(ctx) ?? false) : false;
58
+ const enabled = ctx ? (action.predicate ? action.predicate(ctx) : true) : false;
59
+ const matchers = action.hotkey === undefined ? [] : Array.isArray(action.hotkey) ? action.hotkey : [action.hotkey];
60
+ const first = matchers[0];
61
+ const title = `${action.label ?? id}${first ? ` (${formatHotkey(first)})` : ""}`;
62
+ return (_jsx(ToolbarButton, { title: title, active: active, disabled: !enabled, onClick: () => { if (editor)
63
+ defaultActionRegistry.dispatch(id, { editor }); }, children: Icon ? _jsx(Icon, { ...iconProps }) : (action.label ?? id) }));
64
+ };
65
+ /**
66
+ * Platform-correct zoom hotkey labels — ⌘ glyphs on macOS, "Ctrl+…"
67
+ * elsewhere. Descriptors mirror the bound zoom hotkeys; display uses the
68
+ * minus/plus glyphs.
69
+ */
70
+ const HK_ZOOM_OUT = formatHotkey({ meta: true, key: "−" });
71
+ const HK_ZOOM_IN = formatHotkey({ meta: true, key: "+" });
72
+ const HK_ZOOM_RESET = formatHotkey({ meta: true, key: "0" });
73
+ const HK_ZOOM_FIT = formatHotkey({ meta: true, key: "1" });
74
+ /**
75
+ * Open an OS file picker for image(s) and insert them at the viewport
76
+ * centre via the editor's file-drop pipeline (same path as drag-and-drop,
77
+ * so sizing / GIF animation / Scene.files registration all apply).
78
+ * Multi-select supported — each file dispatched independently.
79
+ *
80
+ * Lives in the UI layer rather than the L2 `state` package because it
81
+ * touches the DOM (`<input type=file>`). Exported so hosts can wire it to
82
+ * a hotkey or a custom button.
83
+ */
84
+ export const openImageFilePicker = (editor) => {
85
+ if (typeof document === "undefined")
86
+ return;
87
+ const input = document.createElement("input");
88
+ input.type = "file";
89
+ input.accept = "image/*";
90
+ input.multiple = true;
91
+ input.addEventListener("change", () => {
92
+ const files = input.files;
93
+ if (!files || files.length === 0)
94
+ return;
95
+ // Toolbar / hotkey invocation has no cursor position — land the
96
+ // image(s) at the viewport centre in world coords.
97
+ const vp = editor.scene.viewport;
98
+ const world = editor.screenToWorld({
99
+ x: vp.size.width / 2,
100
+ y: vp.size.height / 2,
101
+ });
102
+ for (const file of Array.from(files)) {
103
+ void editor.dispatchFileDrop(file, world);
104
+ }
105
+ });
106
+ input.click();
107
+ };
108
+ /** Convenience default — modes + tool-lock + undo/redo + zoom widget. */
109
+ // Built from the action registry: modes / undo / redo / tool-lock are
110
+ // `action-ref` (label·icon·hotkey·pressed·disabled sourced from the
111
+ // action). Insert-image stays an inline `action` — it's host-registered at
112
+ // runtime, so the default toolbar wires the file picker directly to be
113
+ // robust even when the action isn't present.
114
+ export const DEFAULT_TOOLBAR = [
115
+ { kind: "action-ref", id: "mode-select" },
116
+ { kind: "action-ref", id: "mode-hand" },
117
+ { kind: "action-ref", id: "mode-rect" },
118
+ { kind: "action-ref", id: "mode-ellipse" },
119
+ { kind: "action-ref", id: "mode-text" },
120
+ { kind: "action-ref", id: "mode-edge" },
121
+ { kind: "action-ref", id: "mode-brush" },
122
+ { kind: "action-ref", id: "mode-frame" },
123
+ {
124
+ kind: "action",
125
+ id: "insert-image",
126
+ label: _jsx(ImageIcon, { ...iconProps }),
127
+ title: "Insert image (I)",
128
+ onClick: (editor) => { openImageFilePicker(editor); },
129
+ },
130
+ { kind: "action-ref", id: "toggle-tool-lock" },
131
+ { kind: "divider" },
132
+ { kind: "action-ref", id: "undo" },
133
+ { kind: "action-ref", id: "redo" },
134
+ { kind: "divider" },
135
+ ];
136
+ /**
137
+ * Creation-tool set for the vertical left dock. Just the creation tools +
138
+ * the tool-lock toggle — no undo/redo/zoom (those live in the menu /
139
+ * bottom-left). Hosts prepend their own leading items (e.g. a
140
+ * templates-library toggle) and render with
141
+ * `<Toolbar orientation="vertical" />`.
142
+ */
143
+ export const DEFAULT_VERTICAL_TOOLBAR = [
144
+ { kind: "action-ref", id: "mode-select" },
145
+ { kind: "action-ref", id: "mode-hand" },
146
+ { kind: "divider" },
147
+ { kind: "action-ref", id: "mode-rect" },
148
+ { kind: "action-ref", id: "mode-ellipse" },
149
+ { kind: "action-ref", id: "mode-text" },
150
+ { kind: "action-ref", id: "mode-edge" },
151
+ { kind: "action-ref", id: "mode-brush" },
152
+ { kind: "action-ref", id: "mode-frame" },
153
+ {
154
+ kind: "action",
155
+ id: "insert-image",
156
+ label: _jsx(ImageIcon, { ...iconProps }),
157
+ title: "Insert image (I)",
158
+ onClick: (editor) => { openImageFilePicker(editor); },
159
+ },
160
+ { kind: "divider" },
161
+ { kind: "action-ref", id: "toggle-tool-lock" },
162
+ ];
163
+ export const Toolbar = ({ items = DEFAULT_TOOLBAR, style, className, orientation = "horizontal", }) => {
164
+ const editor = useDiagramOptional();
165
+ const mode = useMode();
166
+ const { canUndo, canRedo, undo, redo } = useHistory();
167
+ const vertical = orientation === "vertical";
168
+ return (_jsx("div", { role: "toolbar", "aria-orientation": orientation, className: `du-button-group${vertical ? " du-button-group-vertical" : ""} ${className ?? ""}`.trim(), style: style, children: items.map((item, i) => {
169
+ switch (item.kind) {
170
+ case "divider":
171
+ return _jsx(ToolbarDivider, { vertical: vertical }, i);
172
+ case "action-ref":
173
+ return _jsx(ActionRefButton, { id: item.id }, i);
174
+ case "mode": {
175
+ const active = mode === item.mode;
176
+ return (_jsx(ToolbarButton, { ...(item.title !== undefined ? { title: item.title } : {}), disabled: !editor, active: active, onClick: () => editor?.setMode(item.mode), children: item.label }, i));
177
+ }
178
+ case "action":
179
+ return (_jsx(ToolbarButton, { ...(item.title !== undefined ? { title: item.title } : {}), disabled: item.disabled ?? !editor, active: item.active, onClick: () => {
180
+ if (editor)
181
+ item.onClick(editor);
182
+ }, children: item.label }, i));
183
+ case "undo":
184
+ return (_jsx(ToolbarButton, { disabled: !canUndo, onClick: undo, children: item.label ?? "Undo" }, i));
185
+ case "redo":
186
+ return (_jsx(ToolbarButton, { disabled: !canRedo, onClick: redo, children: item.label ?? "Redo" }, i));
187
+ case "tool-lock":
188
+ return (_jsx(ToolLockButton, { ...(item.label !== undefined ? { label: item.label } : {}), ...(item.title !== undefined ? { title: item.title } : {}) }, i));
189
+ }
190
+ }) }));
191
+ };
192
+ /**
193
+ * Pressable tool-lock affordance. Reads `editor.toolLocked` reactively so
194
+ * the active state stays in sync when the user toggles via hotkey or
195
+ * context menu.
196
+ */
197
+ export const ToolLockButton = ({ label = "🔒", title = "Lock current tool", }) => {
198
+ const editor = useDiagramOptional();
199
+ const locked = useEditorSelector((e) => e.toolLocked, false);
200
+ return (_jsx(ToolbarButton, { disabled: !editor, title: title, active: locked, onClick: () => editor?.setToolLocked(!locked), children: label }));
201
+ };
202
+ /** "−" — calls `editor.zoomOut()`. */
203
+ export const ZoomOutButton = ({ label = "−", title = `Zoom out (${HK_ZOOM_OUT})`, className, style, }) => {
204
+ const editor = useDiagramOptional();
205
+ return (_jsx(ToolbarButton, { disabled: !editor, title: title, className: className, style: style, onClick: () => editor?.zoomOut(), children: label }));
206
+ };
207
+ /** "+" — calls `editor.zoomIn()`. */
208
+ export const ZoomInButton = ({ label = "+", title = `Zoom in (${HK_ZOOM_IN})`, className, style, }) => {
209
+ const editor = useDiagramOptional();
210
+ return (_jsx(ToolbarButton, { disabled: !editor, title: title, className: className, style: style, onClick: () => editor?.zoomIn(), children: label }));
211
+ };
212
+ /** "100%" / "Reset" — calls `editor.resetZoom()`. */
213
+ export const ResetZoomButton = ({ label = "100%", title = `Reset zoom to 100% (${HK_ZOOM_RESET})`, className, style, }) => {
214
+ const editor = useDiagramOptional();
215
+ return (_jsx(ToolbarButton, { disabled: !editor, title: title, className: className, style: style, onClick: () => editor?.resetZoom(), children: label }));
216
+ };
217
+ /** "Fit" — calls `editor.zoomToFit()`. */
218
+ export const ZoomToFitButton = ({ label = "Fit", title = `Fit content to viewport (${HK_ZOOM_FIT})`, className, style, }) => {
219
+ const editor = useDiagramOptional();
220
+ return (_jsx(ToolbarButton, { disabled: !editor, title: title, className: className, style: style, onClick: () => editor?.zoomToFit(), children: label }));
221
+ };
222
+ /**
223
+ * Live zoom percent. Clicks reset zoom to 100% — same UX as the percent
224
+ * button in `ZoomWidget`.
225
+ */
226
+ export const ZoomDisplay = ({ className, style }) => {
227
+ const editor = useDiagramOptional();
228
+ const zoom = useEditorSelector((e) => e.scene.viewport.zoom, 1);
229
+ const percent = `${Math.round(zoom * 100)}%`;
230
+ return (_jsx(ToolbarButton, { disabled: !editor, title: `Reset zoom to 100% (${HK_ZOOM_RESET})`, className: className, style: style, onClick: () => editor?.resetZoom(), children: _jsx("span", { style: { minWidth: 40, display: "inline-block", textAlign: "center" }, children: percent }) }));
231
+ };
232
+ /**
233
+ * Pre-composed inline zoom widget: − / current % / + / Fit. Equivalent
234
+ * to laying the four standalone buttons + display in a row.
235
+ */
236
+ export const ZoomWidget = ({ className, style }) => (_jsxs("span", { className: className, style: { display: "inline-flex", alignItems: "center", gap: 2, ...style }, children: [_jsx(ZoomOutButton, {}), _jsx(ZoomDisplay, {}), _jsx(ZoomInButton, {}), _jsx(ZoomToFitButton, {})] }));
237
+ /**
238
+ * Floating zoom controls — bottom-right cluster with rounded shadow
239
+ * chrome. Drops the widget into a corner so the toolbar stays free for
240
+ * tools. Hosts that need a different position pass `style`.
241
+ */
242
+ export const FloatingZoomControls = ({ className, style, }) => (_jsxs("div", { className: className, style: {
243
+ position: "absolute",
244
+ bottom: 16,
245
+ right: 16,
246
+ display: "inline-flex",
247
+ alignItems: "center",
248
+ gap: 2,
249
+ padding: "4px 6px",
250
+ background: "var(--toolbar-bg, #1a1a1a)",
251
+ border: "1px solid var(--border, #2a2a2a)",
252
+ borderRadius: 6,
253
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.18)",
254
+ zIndex: 50,
255
+ ...style,
256
+ }, children: [_jsx(ZoomOutButton, {}), _jsx(ZoomDisplay, {}), _jsx(ZoomInButton, {}), _jsx(ZoomToFitButton, {})] }));
257
+ const ToolbarButton = ({ children, onClick, active, disabled, title, className, style, }) => {
258
+ const btn = (_jsx("button", { type: "button", onClick: onClick, disabled: disabled, "aria-label": title, "aria-pressed": active, className: `du-icon-button${active ? " is-active" : ""}${className ? ` ${className}` : ""}`, style: {
259
+ // Toolbar items are wider than square — labels can be 1-2
260
+ // characters or short words. Match the IconButton height but
261
+ // let the width grow with the content.
262
+ width: "auto",
263
+ minWidth: "var(--du-button-size, 36px)",
264
+ padding: "0 8px",
265
+ ...style,
266
+ }, children: children }));
267
+ // Wrap in Tooltip when there's text to show. Disabled / empty labels go
268
+ // raw — the shared-state tooltip would otherwise flash an empty box.
269
+ return title ? _jsx(Tooltip, { content: title, children: btn }) : btn;
270
+ };
271
+ const ToolbarDivider = ({ vertical = false }) => vertical ? (_jsx("span", { style: {
272
+ height: 1,
273
+ width: "100%",
274
+ background: "var(--du-ui-border, #333)",
275
+ margin: "4px 0",
276
+ } })) : (_jsx("span", { style: {
277
+ width: 1,
278
+ height: TOOLBAR_SEPARATOR_HEIGHT,
279
+ background: "var(--du-ui-border, #333)",
280
+ margin: "0 4px",
281
+ } }));
282
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../src/toolbar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ export type TooltipSide = "top" | "bottom" | "left" | "right";
3
+ /** Provider — install once near the app root. Renders the portal. */
4
+ export declare const TooltipProvider: ({ children }: {
5
+ readonly children: ReactNode;
6
+ }) => import("react/jsx-runtime").JSX.Element;
7
+ export interface TooltipProps {
8
+ readonly content: ReactNode;
9
+ /** Side relative to the trigger. Default `"bottom"`. */
10
+ readonly side?: TooltipSide;
11
+ /** Disable the tooltip without changing the tree. */
12
+ readonly disabled?: boolean;
13
+ readonly children: ReactElement;
14
+ }
15
+ /**
16
+ * Wrap a single element to attach a shared-state tooltip. Returns the
17
+ * child with mouse / focus handlers spliced in — the trigger's existing
18
+ * handlers are preserved.
19
+ */
20
+ export declare const Tooltip: ({ content, side, disabled, children }: TooltipProps) => ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
21
+ //# sourceMappingURL=tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../src/tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA0Cf,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAkF9D,qEAAqE;AACrE,eAAO,MAAM,eAAe,GAAI,cAAc;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,4CA8B7E,CAAC;AAmEF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC;AAED;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,uCAAkD,YAAY,+EA2DrF,CAAC"}
@@ -0,0 +1,217 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cloneElement, createContext, isValidElement, useContext, useEffect, useId, useLayoutEffect, useRef, useState, } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import { TOOLTIP_HIDE_GRACE_MS, TOOLTIP_OFFSET_PX, TOOLTIP_OPEN_DELAY_MS, TOOLTIP_SKIP_DELAY_MS, } from "./constants.js";
5
+ const listeners = new Set();
6
+ let currentTarget = null;
7
+ let openTimer = null;
8
+ let hideTimer = null;
9
+ let lastClosedAt = 0;
10
+ let pointerDown = false;
11
+ const notify = () => {
12
+ for (const l of listeners)
13
+ l(currentTarget);
14
+ };
15
+ const setTarget = (next) => {
16
+ currentTarget = next;
17
+ notify();
18
+ };
19
+ const subscribe = (l) => {
20
+ listeners.add(l);
21
+ return () => {
22
+ listeners.delete(l);
23
+ };
24
+ };
25
+ /** Open request — schedules the show (with delay or skip). */
26
+ const requestOpen = (target) => {
27
+ if (pointerDown)
28
+ return;
29
+ if (hideTimer) {
30
+ clearTimeout(hideTimer);
31
+ hideTimer = null;
32
+ }
33
+ if (openTimer)
34
+ clearTimeout(openTimer);
35
+ const elapsedSinceLastClose = Date.now() - lastClosedAt;
36
+ const skipDelay = currentTarget !== null
37
+ || elapsedSinceLastClose < TOOLTIP_SKIP_DELAY_MS;
38
+ if (skipDelay) {
39
+ setTarget(target);
40
+ return;
41
+ }
42
+ openTimer = setTimeout(() => {
43
+ openTimer = null;
44
+ setTarget(target);
45
+ }, TOOLTIP_OPEN_DELAY_MS);
46
+ };
47
+ /** Close request — only acts if the leaving target matches the open one. */
48
+ const requestClose = (id) => {
49
+ if (openTimer) {
50
+ clearTimeout(openTimer);
51
+ openTimer = null;
52
+ }
53
+ if (currentTarget?.id === id) {
54
+ if (hideTimer)
55
+ clearTimeout(hideTimer);
56
+ hideTimer = setTimeout(() => {
57
+ hideTimer = null;
58
+ lastClosedAt = Date.now();
59
+ setTarget(null);
60
+ }, TOOLTIP_HIDE_GRACE_MS);
61
+ }
62
+ };
63
+ /** Hard-close — used for pointerdown / Escape / unmount. */
64
+ const forceClose = () => {
65
+ if (openTimer) {
66
+ clearTimeout(openTimer);
67
+ openTimer = null;
68
+ }
69
+ if (hideTimer) {
70
+ clearTimeout(hideTimer);
71
+ hideTimer = null;
72
+ }
73
+ if (currentTarget) {
74
+ lastClosedAt = Date.now();
75
+ setTarget(null);
76
+ }
77
+ };
78
+ /** Provider — install once near the app root. Renders the portal. */
79
+ export const TooltipProvider = ({ children }) => {
80
+ // pointerdown anywhere closes. Capture phase so we beat the rest of the
81
+ // app to the event.
82
+ useEffect(() => {
83
+ const onDown = () => {
84
+ pointerDown = true;
85
+ forceClose();
86
+ };
87
+ const onUp = () => {
88
+ pointerDown = false;
89
+ };
90
+ const onKey = (ev) => {
91
+ if (ev.key === "Escape")
92
+ forceClose();
93
+ };
94
+ document.addEventListener("pointerdown", onDown, { capture: true });
95
+ document.addEventListener("pointerup", onUp, { capture: true });
96
+ document.addEventListener("keydown", onKey, { capture: true });
97
+ return () => {
98
+ document.removeEventListener("pointerdown", onDown, { capture: true });
99
+ document.removeEventListener("pointerup", onUp, { capture: true });
100
+ document.removeEventListener("keydown", onKey, { capture: true });
101
+ };
102
+ }, []);
103
+ return (_jsxs(TooltipProviderCtx.Provider, { value: true, children: [children, _jsx(TooltipPortal, {})] }));
104
+ };
105
+ const TooltipProviderCtx = createContext(false);
106
+ const useHasProvider = () => useContext(TooltipProviderCtx);
107
+ /**
108
+ * The singleton tooltip surface. Renders via portal into `document.body`
109
+ * so it can sit above modal overlays.
110
+ */
111
+ const TooltipPortal = () => {
112
+ const [target, setTargetState] = useState(null);
113
+ useEffect(() => subscribe(setTargetState), []);
114
+ if (!target)
115
+ return null;
116
+ if (typeof document === "undefined")
117
+ return null;
118
+ return createPortal(_jsx(TooltipSurface, { target: target }), document.body);
119
+ };
120
+ const TooltipSurface = ({ target }) => {
121
+ const ref = useRef(null);
122
+ const [pos, setPos] = useState(null);
123
+ useLayoutEffect(() => {
124
+ const el = ref.current;
125
+ if (!el)
126
+ return;
127
+ const tipRect = el.getBoundingClientRect();
128
+ const { rect, side } = target;
129
+ let left = rect.left + rect.width / 2 - tipRect.width / 2;
130
+ let top = rect.top + rect.height / 2 - tipRect.height / 2;
131
+ switch (side) {
132
+ case "top":
133
+ top = rect.top - tipRect.height - TOOLTIP_OFFSET_PX;
134
+ break;
135
+ case "bottom":
136
+ top = rect.bottom + TOOLTIP_OFFSET_PX;
137
+ break;
138
+ case "left":
139
+ left = rect.left - tipRect.width - TOOLTIP_OFFSET_PX;
140
+ break;
141
+ case "right":
142
+ left = rect.right + TOOLTIP_OFFSET_PX;
143
+ break;
144
+ }
145
+ // Clamp to viewport — keep the tooltip on-screen at edges.
146
+ const pad = 4;
147
+ left = Math.max(pad, Math.min(left, window.innerWidth - tipRect.width - pad));
148
+ top = Math.max(pad, Math.min(top, window.innerHeight - tipRect.height - pad));
149
+ setPos({ left, top });
150
+ }, [target]);
151
+ const style = {
152
+ position: "fixed",
153
+ left: pos?.left ?? -9999,
154
+ top: pos?.top ?? -9999,
155
+ pointerEvents: "none",
156
+ zIndex: 10000,
157
+ visibility: pos ? "visible" : "hidden",
158
+ };
159
+ return (_jsx("div", { ref: ref, role: "tooltip", className: "du-tooltip", style: style, children: target.content }));
160
+ };
161
+ /**
162
+ * Wrap a single element to attach a shared-state tooltip. Returns the
163
+ * child with mouse / focus handlers spliced in — the trigger's existing
164
+ * handlers are preserved.
165
+ */
166
+ export const Tooltip = ({ content, side = "bottom", disabled, children }) => {
167
+ const id = useId();
168
+ const hasProvider = useHasProvider();
169
+ // Fall back to native title= when there's no provider (degraded but
170
+ // functional — keeps stories / isolated tests working).
171
+ if (!hasProvider || disabled || content === undefined || content === null) {
172
+ if (!isValidElement(children))
173
+ return children;
174
+ if (typeof content === "string" && !disabled) {
175
+ return cloneElement(children, { title: content });
176
+ }
177
+ return children;
178
+ }
179
+ if (!isValidElement(children))
180
+ return children;
181
+ const child = children;
182
+ const open = (el) => {
183
+ requestOpen({
184
+ id,
185
+ content,
186
+ side,
187
+ rect: el.getBoundingClientRect(),
188
+ });
189
+ };
190
+ const onPointerEnter = (ev) => {
191
+ child.props.onPointerEnter?.(ev);
192
+ if (ev.pointerType === "touch")
193
+ return;
194
+ open(ev.currentTarget);
195
+ };
196
+ const onPointerLeave = (ev) => {
197
+ child.props.onPointerLeave?.(ev);
198
+ requestClose(id);
199
+ };
200
+ const onFocus = (ev) => {
201
+ child.props.onFocus?.(ev);
202
+ open(ev.currentTarget);
203
+ };
204
+ const onBlur = (ev) => {
205
+ child.props.onBlur?.(ev);
206
+ requestClose(id);
207
+ };
208
+ return cloneElement(child, {
209
+ onPointerEnter,
210
+ onPointerLeave,
211
+ onFocus,
212
+ onBlur,
213
+ // Strip the native title — it would race the custom tooltip.
214
+ title: undefined,
215
+ });
216
+ };
217
+ //# sourceMappingURL=tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../src/tooltip.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { CSSProperties, ReactNode } from "react";
2
+ /**
3
+ * Absolute-positioned overlay that sits above the canvas surface and
4
+ * hosts every floating piece of UI (top bar, bottom bar, side panels,
5
+ * floating toolbars). The wrapper has `pointer-events: none` so pointer
6
+ * events fall through to the canvas everywhere the UI isn't drawn;
7
+ * individual children re-enable events on themselves.
8
+ *
9
+ * UI is layered, not laid out: the canvas occupies the full surface and
10
+ * the `<UILayer>` floats on top.
11
+ *
12
+ * Hosts can pass a `style` override (e.g. `{ right: 240 }`) when a docked
13
+ * side panel takes up part of the surface, so bars stop before the docked
14
+ * column's edge.
15
+ */
16
+ export interface UILayerProps {
17
+ readonly children: ReactNode;
18
+ readonly className?: string;
19
+ readonly style?: CSSProperties;
20
+ }
21
+ export declare const UILayer: ({ children, className, style }: UILayerProps) => import("react/jsx-runtime").JSX.Element;
22
+ //# sourceMappingURL=ui-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-layer.d.ts","sourceRoot":"","sources":["../src/ui-layer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,eAAO,MAAM,OAAO,GAAI,gCAAgC,YAAY,4CAInE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const UILayer = ({ children, className, style }) => (_jsx("div", { className: `du-ui-layer ${className ?? ""}`.trim(), style: style, children: children }));
3
+ //# sourceMappingURL=ui-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-layer.js","sourceRoot":"","sources":["../src/ui-layer.tsx"],"names":[],"mappings":";AAsBA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAgB,EAAE,EAAE,CAAC,CACvE,cAAK,SAAS,EAAE,eAAe,SAAS,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,YAClE,QAAQ,GACL,CACP,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { type CSSProperties } from "react";
2
+ import { type Branch, type Snapshot, type SnapshotStore } from "@oh-just-another/versioning";
3
+ interface StoreSnapshot {
4
+ readonly branches: readonly Branch[];
5
+ readonly snapshots: readonly Snapshot[];
6
+ readonly currentBranchId: Branch["id"];
7
+ }
8
+ /**
9
+ * Subscribe to a `SnapshotStore` and return reactive lists of branches +
10
+ * snapshots + the currently-active branch. Pass `null` for hosts that
11
+ * haven't wired versioning — the hook returns empty arrays.
12
+ */
13
+ export declare const useSnapshotStore: (store: SnapshotStore | null) => StoreSnapshot;
14
+ export interface VersionPanelProps {
15
+ /** Required — host owns the store's lifecycle. */
16
+ readonly store: SnapshotStore;
17
+ /** Author identity used when capturing snapshots. */
18
+ readonly author: {
19
+ id: string;
20
+ name: string;
21
+ };
22
+ readonly style?: CSSProperties;
23
+ readonly className?: string;
24
+ }
25
+ /**
26
+ * Side-panel with a tree of branches + snapshots and capture / restore /
27
+ * branch actions. Branches are flat, snapshots nested inside each branch
28
+ * (no DAG view).
29
+ */
30
+ export declare const VersionPanel: ({ store, author, style, className }: VersionPanelProps) => import("react/jsx-runtime").JSX.Element;
31
+ export {};
32
+ //# sourceMappingURL=versioning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../src/versioning.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7E,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,aAAa,EAEnB,MAAM,6BAA6B,CAAC;AAIrC,UAAU,aAAa;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,aAAa,GAAG,IAAI,KAAG,aA6B9D,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,qCAAqC,iBAAiB,4CAgRlF,CAAC"}