@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.
- package/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +54 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/bottom-sheet.d.ts +26 -0
- package/dist/bottom-sheet.d.ts.map +1 -0
- package/dist/bottom-sheet.js +87 -0
- package/dist/bottom-sheet.js.map +1 -0
- package/dist/button-group.d.ts +14 -0
- package/dist/button-group.d.ts.map +1 -0
- package/dist/button-group.js +3 -0
- package/dist/button-group.js.map +1 -0
- package/dist/color-palette.d.ts +34 -0
- package/dist/color-palette.d.ts.map +1 -0
- package/dist/color-palette.js +77 -0
- package/dist/color-palette.js.map +1 -0
- package/dist/color-swatch-picker.d.ts +29 -0
- package/dist/color-swatch-picker.d.ts.map +1 -0
- package/dist/color-swatch-picker.js +56 -0
- package/dist/color-swatch-picker.js.map +1 -0
- package/dist/command-palette.d.ts +13 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +146 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/comments-panel.d.ts +27 -0
- package/dist/comments-panel.d.ts.map +1 -0
- package/dist/comments-panel.js +139 -0
- package/dist/comments-panel.js.map +1 -0
- package/dist/constants.d.ts +112 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +119 -0
- package/dist/constants.js.map +1 -0
- package/dist/context-menu-controller.d.ts +41 -0
- package/dist/context-menu-controller.d.ts.map +1 -0
- package/dist/context-menu-controller.js +26 -0
- package/dist/context-menu-controller.js.map +1 -0
- package/dist/context-menu.d.ts +53 -0
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +333 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/context.d.ts +44 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +95 -0
- package/dist/context.js.map +1 -0
- package/dist/diagram-bars.d.ts +21 -0
- package/dist/diagram-bars.d.ts.map +1 -0
- package/dist/diagram-bars.js +4 -0
- package/dist/diagram-bars.js.map +1 -0
- package/dist/diagram-canvas.d.ts +39 -0
- package/dist/diagram-canvas.d.ts.map +1 -0
- package/dist/diagram-canvas.js +9 -0
- package/dist/diagram-canvas.js.map +1 -0
- package/dist/diagram-root.d.ts +70 -0
- package/dist/diagram-root.d.ts.map +1 -0
- package/dist/diagram-root.js +180 -0
- package/dist/diagram-root.js.map +1 -0
- package/dist/diff-panel.d.ts +25 -0
- package/dist/diff-panel.d.ts.map +1 -0
- package/dist/diff-panel.js +77 -0
- package/dist/diff-panel.js.map +1 -0
- package/dist/edge-style-panel.d.ts +19 -0
- package/dist/edge-style-panel.d.ts.map +1 -0
- package/dist/edge-style-panel.js +120 -0
- package/dist/edge-style-panel.js.map +1 -0
- package/dist/frame-name-editor-overlay.d.ts +13 -0
- package/dist/frame-name-editor-overlay.d.ts.map +1 -0
- package/dist/frame-name-editor-overlay.js +84 -0
- package/dist/frame-name-editor-overlay.js.map +1 -0
- package/dist/frame-panel.d.ts +19 -0
- package/dist/frame-panel.d.ts.map +1 -0
- package/dist/frame-panel.js +66 -0
- package/dist/frame-panel.js.map +1 -0
- package/dist/help-button.d.ts +16 -0
- package/dist/help-button.d.ts.map +1 -0
- package/dist/help-button.js +14 -0
- package/dist/help-button.js.map +1 -0
- package/dist/help-dialog.d.ts +56 -0
- package/dist/help-dialog.d.ts.map +1 -0
- package/dist/help-dialog.js +142 -0
- package/dist/help-dialog.js.map +1 -0
- package/dist/hooks.d.ts +54 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +85 -0
- package/dist/hooks.js.map +1 -0
- package/dist/icon-button.d.ts +28 -0
- package/dist/icon-button.d.ts.map +1 -0
- package/dist/icon-button.js +14 -0
- package/dist/icon-button.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/layer-panel.d.ts +13 -0
- package/dist/layer-panel.d.ts.map +1 -0
- package/dist/layer-panel.js +109 -0
- package/dist/layer-panel.js.map +1 -0
- package/dist/library-panel.d.ts +33 -0
- package/dist/library-panel.d.ts.map +1 -0
- package/dist/library-panel.js +37 -0
- package/dist/library-panel.js.map +1 -0
- package/dist/link-caption-editor.d.ts +8 -0
- package/dist/link-caption-editor.d.ts.map +1 -0
- package/dist/link-caption-editor.js +65 -0
- package/dist/link-caption-editor.js.map +1 -0
- package/dist/link-drop-shape-menu.d.ts +12 -0
- package/dist/link-drop-shape-menu.d.ts.map +1 -0
- package/dist/link-drop-shape-menu.js +55 -0
- package/dist/link-drop-shape-menu.js.map +1 -0
- package/dist/link-hover-popup.d.ts +2 -0
- package/dist/link-hover-popup.d.ts.map +1 -0
- package/dist/link-hover-popup.js +96 -0
- package/dist/link-hover-popup.js.map +1 -0
- package/dist/main-menu.d.ts +67 -0
- package/dist/main-menu.d.ts.map +1 -0
- package/dist/main-menu.js +243 -0
- package/dist/main-menu.js.map +1 -0
- package/dist/markdown.d.ts +10 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +131 -0
- package/dist/markdown.js.map +1 -0
- package/dist/merge-dialog.d.ts +22 -0
- package/dist/merge-dialog.d.ts.map +1 -0
- package/dist/merge-dialog.js +46 -0
- package/dist/merge-dialog.js.map +1 -0
- package/dist/modal.d.ts +19 -0
- package/dist/modal.d.ts.map +1 -0
- package/dist/modal.js +87 -0
- package/dist/modal.js.map +1 -0
- package/dist/palette.d.ts +73 -0
- package/dist/palette.d.ts.map +1 -0
- package/dist/palette.js +330 -0
- package/dist/palette.js.map +1 -0
- package/dist/popover.d.ts +33 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +107 -0
- package/dist/popover.js.map +1 -0
- package/dist/property-panel.d.ts +32 -0
- package/dist/property-panel.d.ts.map +1 -0
- package/dist/property-panel.js +728 -0
- package/dist/property-panel.js.map +1 -0
- package/dist/reset-to-content-button.d.ts +10 -0
- package/dist/reset-to-content-button.d.ts.map +1 -0
- package/dist/reset-to-content-button.js +62 -0
- package/dist/reset-to-content-button.js.map +1 -0
- package/dist/segmented-control.d.ts +23 -0
- package/dist/segmented-control.d.ts.map +1 -0
- package/dist/segmented-control.js +5 -0
- package/dist/segmented-control.js.map +1 -0
- package/dist/selection-floating-panel.d.ts +56 -0
- package/dist/selection-floating-panel.d.ts.map +1 -0
- package/dist/selection-floating-panel.js +251 -0
- package/dist/selection-floating-panel.js.map +1 -0
- package/dist/sidebar.d.ts +31 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +66 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/slider.d.ts +20 -0
- package/dist/slider.d.ts.map +1 -0
- package/dist/slider.js +9 -0
- package/dist/slider.js.map +1 -0
- package/dist/text-editor-overlay.d.ts +16 -0
- package/dist/text-editor-overlay.d.ts.map +1 -0
- package/dist/text-editor-overlay.js +112 -0
- package/dist/text-editor-overlay.js.map +1 -0
- package/dist/toast.d.ts +34 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +89 -0
- package/dist/toast.js.map +1 -0
- package/dist/toolbar.d.ts +149 -0
- package/dist/toolbar.d.ts.map +1 -0
- package/dist/toolbar.js +282 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/tooltip.d.ts +21 -0
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +217 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/ui-layer.d.ts +22 -0
- package/dist/ui-layer.d.ts.map +1 -0
- package/dist/ui-layer.js +3 -0
- package/dist/ui-layer.js.map +1 -0
- package/dist/versioning.d.ts +32 -0
- package/dist/versioning.d.ts.map +1 -0
- package/dist/versioning.js +206 -0
- package/dist/versioning.js.map +1 -0
- package/package.json +81 -0
- package/src/styles.css +1502 -0
package/dist/sidebar.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo, useState, } from "react";
|
|
3
|
+
const Ctx = createContext(null);
|
|
4
|
+
const useSidebar = () => {
|
|
5
|
+
const ctx = useContext(Ctx);
|
|
6
|
+
if (!ctx)
|
|
7
|
+
throw new Error("Sidebar sub-component must be inside <Sidebar>");
|
|
8
|
+
return ctx;
|
|
9
|
+
};
|
|
10
|
+
export const Sidebar = ({ children, defaultTab = "", docked = "right", width = 280, className, style, }) => {
|
|
11
|
+
const [active, setActive] = useState(defaultTab);
|
|
12
|
+
const ctx = useMemo(() => ({ active, setActive }), [active]);
|
|
13
|
+
const wrapper = {
|
|
14
|
+
width,
|
|
15
|
+
background: "var(--panel, #161616)",
|
|
16
|
+
color: "var(--text, #ddd)",
|
|
17
|
+
display: "flex",
|
|
18
|
+
flexDirection: "column",
|
|
19
|
+
minHeight: 0,
|
|
20
|
+
borderLeft: docked === "right" ? "1px solid var(--border, #2a2a2a)" : "none",
|
|
21
|
+
borderRight: docked === "left" ? "1px solid var(--border, #2a2a2a)" : "none",
|
|
22
|
+
...style,
|
|
23
|
+
};
|
|
24
|
+
return (_jsx(Ctx.Provider, { value: ctx, children: _jsx("aside", { className: className, style: wrapper, children: children }) }));
|
|
25
|
+
};
|
|
26
|
+
const Header = ({ children }) => (_jsx("header", { style: {
|
|
27
|
+
padding: "12px 14px",
|
|
28
|
+
fontSize: 13,
|
|
29
|
+
fontWeight: 600,
|
|
30
|
+
color: "var(--text-strong, #fff)",
|
|
31
|
+
borderBottom: "1px solid var(--border, #2a2a2a)",
|
|
32
|
+
}, children: children }));
|
|
33
|
+
const TabTriggers = ({ children }) => (_jsx("div", { style: {
|
|
34
|
+
display: "flex",
|
|
35
|
+
gap: 4,
|
|
36
|
+
padding: "8px 10px",
|
|
37
|
+
borderBottom: "1px solid var(--border, #2a2a2a)",
|
|
38
|
+
}, children: children }));
|
|
39
|
+
const Trigger = ({ tab, children }) => {
|
|
40
|
+
const { active, setActive } = useSidebar();
|
|
41
|
+
const isActive = active === tab;
|
|
42
|
+
return (_jsx("button", { type: "button", "aria-pressed": isActive, onClick: () => { setActive(tab); }, style: {
|
|
43
|
+
background: isActive ? "var(--accent, #1a73e8)" : "transparent",
|
|
44
|
+
color: isActive ? "var(--surface, #fff)" : "var(--text, #ddd)",
|
|
45
|
+
border: `1px solid ${isActive ? "var(--accent, #1a73e8)" : "var(--border, #2a2a2a)"}`,
|
|
46
|
+
borderRadius: 4,
|
|
47
|
+
padding: "4px 10px",
|
|
48
|
+
fontSize: 12,
|
|
49
|
+
cursor: "pointer",
|
|
50
|
+
font: "inherit",
|
|
51
|
+
}, children: children }));
|
|
52
|
+
};
|
|
53
|
+
const Tab = ({ tab, children }) => {
|
|
54
|
+
const { active } = useSidebar();
|
|
55
|
+
if (active !== tab)
|
|
56
|
+
return null;
|
|
57
|
+
return (_jsx("div", { style: { flex: "1 1 auto", overflowY: "auto", padding: "10px 12px" }, children: children }));
|
|
58
|
+
};
|
|
59
|
+
/** Plain section (no tab gating) — for content that's always visible. */
|
|
60
|
+
const Section = ({ children }) => (_jsx("div", { style: { padding: "10px 12px", borderBottom: "1px solid var(--border, #2a2a2a)" }, children: children }));
|
|
61
|
+
Sidebar.Header = Header;
|
|
62
|
+
Sidebar.TabTriggers = TabTriggers;
|
|
63
|
+
Sidebar.Trigger = Trigger;
|
|
64
|
+
Sidebar.Tab = Tab;
|
|
65
|
+
Sidebar.Section = Section;
|
|
66
|
+
//# sourceMappingURL=sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../src/sidebar.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EACb,UAAU,EACV,OAAO,EACP,QAAQ,GAGT,MAAM,OAAO,CAAC;AAyBf,MAAM,GAAG,GAAG,aAAa,CAAwB,IAAI,CAAC,CAAC;AACvD,MAAM,UAAU,GAAG,GAAmB,EAAE;IACtC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAYF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EACtB,QAAQ,EACR,UAAU,GAAG,EAAE,EACf,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,GAAG,EACX,SAAS,EACT,KAAK,GACQ,EAAE,EAAE;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,OAAO,CAAiB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAkB;QAC7B,KAAK;QACL,UAAU,EAAE,uBAAuB;QACnC,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,MAAM;QAC5E,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,MAAM;QAC5E,GAAG,KAAK;KACT,CAAC;IACF,OAAO,CACL,KAAC,GAAG,CAAC,QAAQ,IAAC,KAAK,EAAE,GAAG,YACtB,gBAAO,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,YACxC,QAAQ,GACH,GACK,CAChB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE,CAAC,CACxD,iBACE,KAAK,EAAE;QACL,OAAO,EAAE,WAAW;QACpB,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,0BAA0B;QACjC,YAAY,EAAE,kCAAkC;KACjD,YAEA,QAAQ,GACF,CACV,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE,CAAC,CAC7D,cACE,KAAK,EAAE;QACL,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,UAAU;QACnB,YAAY,EAAE,kCAAkC;KACjD,YAEA,QAAQ,GACL,CACP,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAwC,EAAE,EAAE;IAC1E,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,KAAK,GAAG,CAAC;IAChC,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,kBACC,QAAQ,EACtB,OAAO,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAClC,KAAK,EAAE;YACL,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,aAAa;YAC/D,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,mBAAmB;YAC9D,MAAM,EAAE,aAAa,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,wBAAwB,EAAE;YACrF,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,SAAS;SAChB,YAEA,QAAQ,GACF,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAwC,EAAE,EAAE;IACtE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IAChC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,YACtE,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,yEAAyE;AACzE,MAAM,OAAO,GAAG,CAAC,EAAE,QAAQ,EAA2B,EAAE,EAAE,CAAC,CACzD,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,kCAAkC,EAAE,YACnF,QAAQ,GACL,CACP,CAAC;AAEF,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;AACxB,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;AAClC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;AAC1B,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAClB,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC"}
|
package/dist/slider.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native `<input type=range>` wrapped in a styled track. Drives
|
|
3
|
+
* continuous numeric properties (opacity, blur, …). Optional
|
|
4
|
+
* `valueLabel` shows the formatted current value alongside the track —
|
|
5
|
+
* the host owns the formatter (e.g. `${Math.round(v * 100)}%`).
|
|
6
|
+
*
|
|
7
|
+
* `value === null` (mixed multi-selection) leaves the thumb at the
|
|
8
|
+
* midpoint of the range and renders a "—" label until the user moves it.
|
|
9
|
+
*/
|
|
10
|
+
export interface SliderProps {
|
|
11
|
+
readonly value: number | null;
|
|
12
|
+
readonly min: number;
|
|
13
|
+
readonly max: number;
|
|
14
|
+
readonly step?: number;
|
|
15
|
+
readonly onChange: (value: number) => void;
|
|
16
|
+
readonly ariaLabel?: string;
|
|
17
|
+
readonly valueLabel?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const Slider: ({ value, min, max, step, onChange, ariaLabel, valueLabel, }: SliderProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=slider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../src/slider.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,MAAM,GAAI,6DAQpB,WAAW,4CAoBb,CAAC"}
|
package/dist/slider.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export const Slider = ({ value, min, max, step = 1, onChange, ariaLabel, valueLabel, }) => {
|
|
3
|
+
const handle = (ev) => {
|
|
4
|
+
onChange(Number(ev.target.value));
|
|
5
|
+
};
|
|
6
|
+
const thumbValue = value ?? (min + max) / 2;
|
|
7
|
+
return (_jsxs("div", { className: "du-slider", children: [_jsx("input", { type: "range", min: min, max: max, step: step, value: thumbValue, onChange: handle, "aria-label": ariaLabel, className: "du-slider-track" }), _jsx("span", { className: "du-slider-value", children: value === null ? "—" : valueLabel ?? value })] }));
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slider.js","sourceRoot":"","sources":["../src/slider.tsx"],"names":[],"mappings":";AAqBA,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EACrB,KAAK,EACL,GAAG,EACH,GAAG,EACH,IAAI,GAAG,CAAC,EACR,QAAQ,EACR,SAAS,EACT,UAAU,GACE,EAAE,EAAE;IAChB,MAAM,MAAM,GAAG,CAAC,EAAiC,EAAQ,EAAE;QACzD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,KAAK,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5C,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACxB,gBACE,IAAI,EAAC,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,gBACJ,SAAS,EACrB,SAAS,EAAC,iBAAiB,GAC3B,EACF,eAAM,SAAS,EAAC,iBAAiB,YAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,KAAK,GAAQ,IACjF,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invisible keystroke/IME sink for in-canvas text editing. The caret and
|
|
3
|
+
* selection are drawn on the canvas by the renderer (the editor's
|
|
4
|
+
* overlay pass); this component is not a visible editor — it is a 1×1,
|
|
5
|
+
* fully-transparent `<textarea>` that holds keyboard focus so the
|
|
6
|
+
* browser delivers typing, IME composition, clipboard and native
|
|
7
|
+
* caret/selection navigation. Each change is mirrored into the editor
|
|
8
|
+
* (`setEditingText` / `setEditingSelection`), which mutates the shape's
|
|
9
|
+
* text live and owns the on-canvas caret.
|
|
10
|
+
*
|
|
11
|
+
* Wiring: drop as a sibling of `<DiagramSurface>` inside `<DiagramRoot>`.
|
|
12
|
+
* Editing opens via `editor.beginTextEdit(id)` / the text tool; it
|
|
13
|
+
* commits on Escape, on a click outside the shape, or on a tool change.
|
|
14
|
+
*/
|
|
15
|
+
export declare const TextEditorOverlay: () => import("react/jsx-runtime").JSX.Element | null;
|
|
16
|
+
//# sourceMappingURL=text-editor-overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor-overlay.d.ts","sourceRoot":"","sources":["../src/text-editor-overlay.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,sDA4G7B,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useLayoutEffect, useReducer, useRef } from "react";
|
|
3
|
+
import { getElement } from "@oh-just-another/scene";
|
|
4
|
+
import { useDiagramOptional } from "./hooks.js";
|
|
5
|
+
/**
|
|
6
|
+
* Invisible keystroke/IME sink for in-canvas text editing. The caret and
|
|
7
|
+
* selection are drawn on the canvas by the renderer (the editor's
|
|
8
|
+
* overlay pass); this component is not a visible editor — it is a 1×1,
|
|
9
|
+
* fully-transparent `<textarea>` that holds keyboard focus so the
|
|
10
|
+
* browser delivers typing, IME composition, clipboard and native
|
|
11
|
+
* caret/selection navigation. Each change is mirrored into the editor
|
|
12
|
+
* (`setEditingText` / `setEditingSelection`), which mutates the shape's
|
|
13
|
+
* text live and owns the on-canvas caret.
|
|
14
|
+
*
|
|
15
|
+
* Wiring: drop as a sibling of `<DiagramSurface>` inside `<DiagramRoot>`.
|
|
16
|
+
* Editing opens via `editor.beginTextEdit(id)` / the text tool; it
|
|
17
|
+
* commits on Escape, on a click outside the shape, or on a tool change.
|
|
18
|
+
*/
|
|
19
|
+
export const TextEditorOverlay = () => {
|
|
20
|
+
const editor = useDiagramOptional();
|
|
21
|
+
const ref = useRef(null);
|
|
22
|
+
const [, force] = useReducer((x) => x + 1, 0);
|
|
23
|
+
// Re-render on any editor change so value/selection stay mirrored.
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!editor)
|
|
26
|
+
return undefined;
|
|
27
|
+
return editor.on("change", force);
|
|
28
|
+
}, [editor]);
|
|
29
|
+
const editingId = editor?.editingTextElement ?? null;
|
|
30
|
+
// Focus the sink whenever an edit starts.
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!editingId)
|
|
33
|
+
return;
|
|
34
|
+
ref.current?.focus();
|
|
35
|
+
}, [editingId]);
|
|
36
|
+
// Mirror the editor's text + selection INTO the textarea so native
|
|
37
|
+
// navigation, IME and typing all operate on the live content. Guarded
|
|
38
|
+
// so it never fights the user's own caret.
|
|
39
|
+
useLayoutEffect(() => {
|
|
40
|
+
const ta = ref.current;
|
|
41
|
+
if (!editor || !editingId || !ta)
|
|
42
|
+
return;
|
|
43
|
+
const shape = getElement(editor.scene, editingId);
|
|
44
|
+
const text = shape?.type === "text" ? shape.text : "";
|
|
45
|
+
if (ta.value !== text)
|
|
46
|
+
ta.value = text;
|
|
47
|
+
const sel = editor.editingTextSelection;
|
|
48
|
+
if (sel && (ta.selectionStart !== sel.start || ta.selectionEnd !== sel.end)) {
|
|
49
|
+
ta.setSelectionRange(sel.start, sel.end, sel.dir);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (!editor || !editingId)
|
|
53
|
+
return null;
|
|
54
|
+
const shape = getElement(editor.scene, editingId);
|
|
55
|
+
if (shape?.type !== "text")
|
|
56
|
+
return null;
|
|
57
|
+
// Park the sink at the text's screen position so the IME candidate
|
|
58
|
+
// window appears near the caret. It's invisible and click-through.
|
|
59
|
+
const vp = editor.scene.viewport;
|
|
60
|
+
const left = (shape.position.x - vp.pan.x) * vp.zoom;
|
|
61
|
+
const top = (shape.position.y - vp.pan.y) * vp.zoom;
|
|
62
|
+
const dirOf = (ta) => ta.selectionDirection === "backward" ? "backward" : "forward";
|
|
63
|
+
return (_jsx("textarea", { ref: ref, defaultValue: shape.text,
|
|
64
|
+
// `onInput` covers typing, paste, cut, delete and IME end — read
|
|
65
|
+
// the textarea's authoritative value + caret and push them live.
|
|
66
|
+
onInput: (ev) => {
|
|
67
|
+
const t = ev.currentTarget;
|
|
68
|
+
editor.setEditingText(t.value, t.selectionStart, t.selectionEnd, dirOf(t));
|
|
69
|
+
}, onSelect: (ev) => {
|
|
70
|
+
const t = ev.currentTarget;
|
|
71
|
+
editor.setEditingSelection(t.selectionStart, t.selectionEnd, dirOf(t));
|
|
72
|
+
}, onKeyDown: (ev) => {
|
|
73
|
+
// Escape (and Cmd/Ctrl+Enter) commit and exit; plain Enter is a
|
|
74
|
+
// newline (native textarea behaviour, mirrored via onInput).
|
|
75
|
+
if (ev.key === "Escape" || (ev.key === "Enter" && (ev.metaKey || ev.ctrlKey))) {
|
|
76
|
+
ev.preventDefault();
|
|
77
|
+
ev.stopPropagation();
|
|
78
|
+
editor.commitTextEdit();
|
|
79
|
+
}
|
|
80
|
+
}, onBlur: () => {
|
|
81
|
+
// A click inside the text repositions the caret (canvas handles
|
|
82
|
+
// it) and must NOT end editing — keep focus if still in an edit
|
|
83
|
+
// after the click resolves. A real exit (commit) clears
|
|
84
|
+
// `editingTextElement`, so it won't refocus then.
|
|
85
|
+
const id = editingId;
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
const ta = ref.current;
|
|
88
|
+
if (ta && editor.editingTextElement === id && document.activeElement !== ta) {
|
|
89
|
+
ta.focus();
|
|
90
|
+
}
|
|
91
|
+
}, 0);
|
|
92
|
+
}, spellCheck: false, autoCapitalize: "off", autoCorrect: "off", "aria-label": "Text editor", style: {
|
|
93
|
+
position: "absolute",
|
|
94
|
+
top,
|
|
95
|
+
left,
|
|
96
|
+
width: 1,
|
|
97
|
+
height: 1,
|
|
98
|
+
padding: 0,
|
|
99
|
+
margin: 0,
|
|
100
|
+
border: 0,
|
|
101
|
+
outline: "none",
|
|
102
|
+
opacity: 0,
|
|
103
|
+
resize: "none",
|
|
104
|
+
overflow: "hidden",
|
|
105
|
+
whiteSpace: "pre",
|
|
106
|
+
// Click-through so canvas pointer handling (caret placement /
|
|
107
|
+
// drag-select / commit-outside) receives the events.
|
|
108
|
+
pointerEvents: "none",
|
|
109
|
+
zIndex: 100,
|
|
110
|
+
} }));
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=text-editor-overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor-overlay.js","sourceRoot":"","sources":["../src/text-editor-overlay.tsx"],"names":[],"mappings":"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"}
|
package/dist/toast.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* In-process toast bus. Hosts mount `<ToastHost>` once at the root;
|
|
4
|
+
* descendants call `useToast()` to push messages. Each toast dismisses
|
|
5
|
+
* itself after `duration` ms; the × button closes it manually.
|
|
6
|
+
*/
|
|
7
|
+
export type ToastKind = "info" | "success" | "warn" | "error";
|
|
8
|
+
export interface Toast {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly kind: ToastKind;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
/** ms before auto-dismiss; 0 / Infinity keeps it open. */
|
|
13
|
+
readonly duration?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ToastApi {
|
|
16
|
+
push(message: string, kind?: ToastKind, duration?: number): string;
|
|
17
|
+
dismiss(id: string): void;
|
|
18
|
+
}
|
|
19
|
+
export declare const useToast: () => ToastApi;
|
|
20
|
+
/** Like `useToast` but returns null instead of throwing. */
|
|
21
|
+
export declare const useToastOptional: () => ToastApi | null;
|
|
22
|
+
export interface ToastHostProps {
|
|
23
|
+
readonly children?: ReactNode;
|
|
24
|
+
/** Default duration for `push` calls that omit the argument. */
|
|
25
|
+
readonly defaultDuration?: number;
|
|
26
|
+
readonly style?: CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
export declare const ToastHost: ({ children, defaultDuration, style, }: ToastHostProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
/**
|
|
30
|
+
* Auto-mount helper for hosts that want a single ToastHost at the top
|
|
31
|
+
* of their component tree without writing the JSX themselves.
|
|
32
|
+
*/
|
|
33
|
+
export declare const useEphemeralToast: (message: string, kind?: ToastKind) => void;
|
|
34
|
+
//# sourceMappingURL=toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf;;;;GAIG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,eAAO,MAAM,QAAQ,QAAO,QAI3B,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,QAAO,QAAQ,GAAG,IAAgC,CAAC;AAEhF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED,eAAO,MAAM,SAAS,GAAI,uCAIvB,cAAc,4CA6BhB,CAAC;AAoFF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,OAAM,SAAkB,KAAG,IAK7E,CAAC"}
|
package/dist/toast.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
3
|
+
import { TOAST_DEFAULT_DURATION_MS } from "./constants.js";
|
|
4
|
+
const ToastContext = createContext(null);
|
|
5
|
+
export const useToast = () => {
|
|
6
|
+
const ctx = useContext(ToastContext);
|
|
7
|
+
if (!ctx)
|
|
8
|
+
throw new Error("useToast: must be wrapped in <ToastHost>");
|
|
9
|
+
return ctx;
|
|
10
|
+
};
|
|
11
|
+
/** Like `useToast` but returns null instead of throwing. */
|
|
12
|
+
export const useToastOptional = () => useContext(ToastContext);
|
|
13
|
+
export const ToastHost = ({ children, defaultDuration = TOAST_DEFAULT_DURATION_MS, style, }) => {
|
|
14
|
+
const [items, setItems] = useState([]);
|
|
15
|
+
const counter = useRef(0);
|
|
16
|
+
const dismiss = useCallback((id) => {
|
|
17
|
+
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
18
|
+
}, []);
|
|
19
|
+
const push = useCallback((message, kind = "info", duration) => {
|
|
20
|
+
const id = `toast-${++counter.current}`;
|
|
21
|
+
const ttl = duration ?? defaultDuration;
|
|
22
|
+
setItems((prev) => [...prev, { id, kind, message, duration: ttl }]);
|
|
23
|
+
if (ttl > 0 && Number.isFinite(ttl)) {
|
|
24
|
+
window.setTimeout(() => { dismiss(id); }, ttl);
|
|
25
|
+
}
|
|
26
|
+
return id;
|
|
27
|
+
}, [defaultDuration, dismiss]);
|
|
28
|
+
const api = useMemo(() => ({ push, dismiss }), [push, dismiss]);
|
|
29
|
+
return (_jsxs(ToastContext.Provider, { value: api, children: [children, _jsx(ToastStack, { toasts: items, onDismiss: dismiss, ...(style ? { style } : {}) })] }));
|
|
30
|
+
};
|
|
31
|
+
const ToastStack = ({ toasts, onDismiss, style, }) => {
|
|
32
|
+
const stackStyle = {
|
|
33
|
+
position: "fixed",
|
|
34
|
+
top: 16,
|
|
35
|
+
right: 16,
|
|
36
|
+
zIndex: 1100,
|
|
37
|
+
display: "flex",
|
|
38
|
+
flexDirection: "column",
|
|
39
|
+
gap: 8,
|
|
40
|
+
pointerEvents: "none",
|
|
41
|
+
...style,
|
|
42
|
+
};
|
|
43
|
+
return (_jsx("div", { style: stackStyle, "aria-live": "polite", "aria-atomic": "false", children: toasts.map((t) => (_jsx(ToastItem, { toast: t, onDismiss: onDismiss }, t.id))) }));
|
|
44
|
+
};
|
|
45
|
+
const KIND_ACCENT = {
|
|
46
|
+
info: "var(--accent, #1a73e8)",
|
|
47
|
+
success: "#2e8b57",
|
|
48
|
+
warn: "#c79100",
|
|
49
|
+
error: "#c83232",
|
|
50
|
+
};
|
|
51
|
+
const ToastItem = ({ toast, onDismiss, }) => {
|
|
52
|
+
const itemStyle = {
|
|
53
|
+
pointerEvents: "auto",
|
|
54
|
+
minWidth: 240,
|
|
55
|
+
maxWidth: 360,
|
|
56
|
+
padding: "10px 12px",
|
|
57
|
+
background: "var(--panel, #1a1a1a)",
|
|
58
|
+
color: "var(--text, #ddd)",
|
|
59
|
+
border: "1px solid var(--border, #2a2a2a)",
|
|
60
|
+
borderLeft: `4px solid ${KIND_ACCENT[toast.kind]}`,
|
|
61
|
+
borderRadius: 4,
|
|
62
|
+
boxShadow: "0 4px 14px rgba(0, 0, 0, 0.3)",
|
|
63
|
+
fontSize: 13,
|
|
64
|
+
display: "flex",
|
|
65
|
+
alignItems: "flex-start",
|
|
66
|
+
gap: 12,
|
|
67
|
+
};
|
|
68
|
+
return (_jsxs("div", { role: "status", style: itemStyle, children: [_jsx("span", { style: { flex: 1, lineHeight: 1.35 }, children: toast.message }), _jsx("button", { type: "button", "aria-label": "Dismiss", onClick: () => { onDismiss(toast.id); }, style: {
|
|
69
|
+
background: "transparent",
|
|
70
|
+
border: "none",
|
|
71
|
+
color: "var(--muted, #888)",
|
|
72
|
+
cursor: "pointer",
|
|
73
|
+
fontSize: 16,
|
|
74
|
+
lineHeight: 1,
|
|
75
|
+
padding: 0,
|
|
76
|
+
}, children: "\u00D7" })] }));
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Auto-mount helper for hosts that want a single ToastHost at the top
|
|
80
|
+
* of their component tree without writing the JSX themselves.
|
|
81
|
+
*/
|
|
82
|
+
export const useEphemeralToast = (message, kind = "info") => {
|
|
83
|
+
const toast = useToastOptional();
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (toast && message)
|
|
86
|
+
toast.push(message, kind);
|
|
87
|
+
}, [toast, message, kind]);
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.js","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
import type { Editor, Mode } from "@oh-just-another/state";
|
|
3
|
+
/**
|
|
4
|
+
* Single toolbar item. Builtin `mode` items wire to `editor.setMode`;
|
|
5
|
+
* `action` items receive the live editor and decide what to do; `divider`
|
|
6
|
+
* draws a thin vertical separator. The `zoom-*` kinds let hosts place
|
|
7
|
+
* individual zoom controls anywhere in the toolbar; `zoom` packs all
|
|
8
|
+
* four into a single compact widget (− / % / + / Fit).
|
|
9
|
+
*/
|
|
10
|
+
export type ToolbarItem = {
|
|
11
|
+
readonly kind: "mode";
|
|
12
|
+
readonly mode: Mode;
|
|
13
|
+
readonly label: ReactNode;
|
|
14
|
+
readonly title?: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "action";
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly label: ReactNode;
|
|
19
|
+
readonly title?: string;
|
|
20
|
+
readonly disabled?: boolean;
|
|
21
|
+
/** Render the button in its pressed/active state (e.g. a toggle). */
|
|
22
|
+
readonly active?: boolean;
|
|
23
|
+
readonly onClick: (editor: Editor) => void;
|
|
24
|
+
} | {
|
|
25
|
+
/**
|
|
26
|
+
* Button sourced from a registered action by id — label / icon /
|
|
27
|
+
* hotkey / pressed (`checked`) / disabled (`predicate`) all come from
|
|
28
|
+
* `defaultActionRegistry`. The registry-driven way to place a built-in
|
|
29
|
+
* (mode-*, undo, redo, tool-lock, …) on the toolbar.
|
|
30
|
+
*/
|
|
31
|
+
readonly kind: "action-ref";
|
|
32
|
+
readonly id: string;
|
|
33
|
+
} | {
|
|
34
|
+
readonly kind: "divider";
|
|
35
|
+
} | {
|
|
36
|
+
readonly kind: "undo";
|
|
37
|
+
readonly label?: ReactNode;
|
|
38
|
+
} | {
|
|
39
|
+
readonly kind: "redo";
|
|
40
|
+
readonly label?: ReactNode;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: "zoom";
|
|
43
|
+
} | {
|
|
44
|
+
readonly kind: "zoom-in";
|
|
45
|
+
readonly label?: ReactNode;
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: "zoom-out";
|
|
48
|
+
readonly label?: ReactNode;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: "zoom-reset";
|
|
51
|
+
readonly label?: ReactNode;
|
|
52
|
+
} | {
|
|
53
|
+
readonly kind: "zoom-fit";
|
|
54
|
+
readonly label?: ReactNode;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "zoom-display";
|
|
57
|
+
} | {
|
|
58
|
+
/**
|
|
59
|
+
* Tool-lock toggle. Renders a pressed-when-locked button; click flips
|
|
60
|
+
* `editor.toolLocked`. When locked, draw modes (rectangle / ellipse /
|
|
61
|
+
* edge / brush) persist after each create instead of reverting to
|
|
62
|
+
* select.
|
|
63
|
+
*/
|
|
64
|
+
readonly kind: "tool-lock";
|
|
65
|
+
readonly label?: ReactNode;
|
|
66
|
+
readonly title?: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Open an OS file picker for image(s) and insert them at the viewport
|
|
70
|
+
* centre via the editor's file-drop pipeline (same path as drag-and-drop,
|
|
71
|
+
* so sizing / GIF animation / Scene.files registration all apply).
|
|
72
|
+
* Multi-select supported — each file dispatched independently.
|
|
73
|
+
*
|
|
74
|
+
* Lives in the UI layer rather than the L2 `state` package because it
|
|
75
|
+
* touches the DOM (`<input type=file>`). Exported so hosts can wire it to
|
|
76
|
+
* a hotkey or a custom button.
|
|
77
|
+
*/
|
|
78
|
+
export declare const openImageFilePicker: (editor: Editor) => void;
|
|
79
|
+
/** Convenience default — modes + tool-lock + undo/redo + zoom widget. */
|
|
80
|
+
export declare const DEFAULT_TOOLBAR: readonly ToolbarItem[];
|
|
81
|
+
/**
|
|
82
|
+
* Creation-tool set for the vertical left dock. Just the creation tools +
|
|
83
|
+
* the tool-lock toggle — no undo/redo/zoom (those live in the menu /
|
|
84
|
+
* bottom-left). Hosts prepend their own leading items (e.g. a
|
|
85
|
+
* templates-library toggle) and render with
|
|
86
|
+
* `<Toolbar orientation="vertical" />`.
|
|
87
|
+
*/
|
|
88
|
+
export declare const DEFAULT_VERTICAL_TOOLBAR: readonly ToolbarItem[];
|
|
89
|
+
export interface ToolbarProps {
|
|
90
|
+
readonly items?: readonly ToolbarItem[];
|
|
91
|
+
readonly style?: CSSProperties;
|
|
92
|
+
readonly className?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Lay the toolbar out as a horizontal row (default) or a vertical
|
|
95
|
+
* column (the left creation dock). Vertical flips the button-group
|
|
96
|
+
* flex direction and draws horizontal dividers.
|
|
97
|
+
*/
|
|
98
|
+
readonly orientation?: "horizontal" | "vertical";
|
|
99
|
+
}
|
|
100
|
+
export declare const Toolbar: ({ items, style, className, orientation, }: ToolbarProps) => import("react/jsx-runtime").JSX.Element;
|
|
101
|
+
/**
|
|
102
|
+
* Pressable tool-lock affordance. Reads `editor.toolLocked` reactively so
|
|
103
|
+
* the active state stays in sync when the user toggles via hotkey or
|
|
104
|
+
* context menu.
|
|
105
|
+
*/
|
|
106
|
+
export declare const ToolLockButton: ({ label, title, }: {
|
|
107
|
+
readonly label?: ReactNode;
|
|
108
|
+
readonly title?: string;
|
|
109
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
110
|
+
export interface ZoomButtonProps {
|
|
111
|
+
readonly label?: ReactNode;
|
|
112
|
+
readonly title?: string;
|
|
113
|
+
readonly className?: string;
|
|
114
|
+
readonly style?: CSSProperties;
|
|
115
|
+
}
|
|
116
|
+
/** "−" — calls `editor.zoomOut()`. */
|
|
117
|
+
export declare const ZoomOutButton: ({ label, title, className, style, }: ZoomButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
118
|
+
/** "+" — calls `editor.zoomIn()`. */
|
|
119
|
+
export declare const ZoomInButton: ({ label, title, className, style, }: ZoomButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
120
|
+
/** "100%" / "Reset" — calls `editor.resetZoom()`. */
|
|
121
|
+
export declare const ResetZoomButton: ({ label, title, className, style, }: ZoomButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
122
|
+
/** "Fit" — calls `editor.zoomToFit()`. */
|
|
123
|
+
export declare const ZoomToFitButton: ({ label, title, className, style, }: ZoomButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
124
|
+
/**
|
|
125
|
+
* Live zoom percent. Clicks reset zoom to 100% — same UX as the percent
|
|
126
|
+
* button in `ZoomWidget`.
|
|
127
|
+
*/
|
|
128
|
+
export declare const ZoomDisplay: ({ className, style }: {
|
|
129
|
+
readonly className?: string;
|
|
130
|
+
readonly style?: CSSProperties;
|
|
131
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
132
|
+
/**
|
|
133
|
+
* Pre-composed inline zoom widget: − / current % / + / Fit. Equivalent
|
|
134
|
+
* to laying the four standalone buttons + display in a row.
|
|
135
|
+
*/
|
|
136
|
+
export declare const ZoomWidget: ({ className, style }: {
|
|
137
|
+
readonly className?: string;
|
|
138
|
+
readonly style?: CSSProperties;
|
|
139
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
140
|
+
/**
|
|
141
|
+
* Floating zoom controls — bottom-right cluster with rounded shadow
|
|
142
|
+
* chrome. Drops the widget into a corner so the toolbar stays free for
|
|
143
|
+
* tools. Hosts that need a different position pass `style`.
|
|
144
|
+
*/
|
|
145
|
+
export declare const FloatingZoomControls: ({ className, style, }: {
|
|
146
|
+
readonly className?: string;
|
|
147
|
+
readonly style?: CSSProperties;
|
|
148
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
149
|
+
//# sourceMappingURL=toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../src/toolbar.tsx"],"names":[],"mappings":"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"}
|