@hilum/designer 3.8.5 → 3.10.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/dist/index.d.ts +70 -4
- package/dist/index.js +162 -53
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Dispatch, SetStateAction, ReactNode, ComponentPropsWithoutRef, ComponentType, CSSProperties } from 'react';
|
|
4
|
+
import { Density, IconComponent } from '@hilum/ui';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The minimal contract a designer shell needs from the engine beneath it.
|
|
@@ -47,6 +48,12 @@ declare function ShellProvider({ initialSelectedIds, initialTool, readOnly, reso
|
|
|
47
48
|
|
|
48
49
|
interface DesignerShellProps {
|
|
49
50
|
className?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Control density for everything inside the shell. Editor chrome defaults
|
|
53
|
+
* to `"compact"` (24px controls, 28px rows, 12px text); pass `"default"` to
|
|
54
|
+
* keep standard Hilum sizing.
|
|
55
|
+
*/
|
|
56
|
+
density?: Density;
|
|
50
57
|
children: ReactNode;
|
|
51
58
|
}
|
|
52
59
|
/**
|
|
@@ -54,7 +61,7 @@ interface DesignerShellProps {
|
|
|
54
61
|
* Place a <DesignerHeader>, <DesignerSidebar>, <DesignerPanel>, and the
|
|
55
62
|
* canvas content as children.
|
|
56
63
|
*/
|
|
57
|
-
declare function DesignerShell({ className, children }: DesignerShellProps): react_jsx_runtime.JSX.Element;
|
|
64
|
+
declare function DesignerShell({ className, density, children }: DesignerShellProps): react_jsx_runtime.JSX.Element;
|
|
58
65
|
|
|
59
66
|
type DesignerWorkspaceInsetValue = number | string;
|
|
60
67
|
interface DesignerWorkspaceInsets {
|
|
@@ -161,6 +168,11 @@ interface DesignerPanelProps {
|
|
|
161
168
|
/** Sheet edge. Defaults to `bottom` for mobile editor panels. */
|
|
162
169
|
sheetSide?: "left" | "right" | "top" | "bottom";
|
|
163
170
|
sheetClassName?: string;
|
|
171
|
+
/**
|
|
172
|
+
* Control density inside the panel. Inspector / layer panels default to
|
|
173
|
+
* `"compact"` editor sizing; pass `"default"` for standard Hilum sizing.
|
|
174
|
+
*/
|
|
175
|
+
density?: Density;
|
|
164
176
|
className?: string;
|
|
165
177
|
style?: CSSProperties;
|
|
166
178
|
children?: ReactNode;
|
|
@@ -170,7 +182,54 @@ interface DesignerPanelProps {
|
|
|
170
182
|
* inspector / properties, history, comments, etc. Static-width for v1.
|
|
171
183
|
* (Resize handles arrive in a later iteration if needed.)
|
|
172
184
|
*/
|
|
173
|
-
declare function DesignerPanel({ side, variant, width, bordered, floatingInset, open, onOpenChange, sheetTitle, sheetDescription, sheetSide, sheetClassName, className, style, children, }: DesignerPanelProps): react_jsx_runtime.JSX.Element;
|
|
185
|
+
declare function DesignerPanel({ side, variant, width, bordered, floatingInset, open, onOpenChange, sheetTitle, sheetDescription, sheetSide, sheetClassName, density, className, style, children, }: DesignerPanelProps): react_jsx_runtime.JSX.Element;
|
|
186
|
+
|
|
187
|
+
interface DesignerPanelHeaderProps {
|
|
188
|
+
/** Panel title ("Sections", "Theme settings"). */
|
|
189
|
+
title?: ReactNode;
|
|
190
|
+
/** Muted line under the title (template name, selection summary). */
|
|
191
|
+
description?: ReactNode;
|
|
192
|
+
/** Trailing icon buttons (DesignerToolbarButton / Button size="icon-sm"). */
|
|
193
|
+
actions?: ReactNode;
|
|
194
|
+
/** Second row — DesignerPanelTabs, a SearchInput, or filters. */
|
|
195
|
+
children?: ReactNode;
|
|
196
|
+
/** Stick to the top of the panel's scroll area. Default: true. */
|
|
197
|
+
sticky?: boolean;
|
|
198
|
+
className?: string;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Header for a DesignerPanel: a title/actions row plus an optional second row
|
|
202
|
+
* for tabs or search. Replaces hand-built panel headers with arbitrary sizes.
|
|
203
|
+
*/
|
|
204
|
+
declare function DesignerPanelHeader({ title, description, actions, children, sticky, className, }: DesignerPanelHeaderProps): react_jsx_runtime.JSX.Element;
|
|
205
|
+
interface DesignerPanelTab<V extends string = string> {
|
|
206
|
+
value: V;
|
|
207
|
+
label: string;
|
|
208
|
+
icon?: IconComponent;
|
|
209
|
+
disabled?: boolean;
|
|
210
|
+
}
|
|
211
|
+
interface DesignerPanelTabsProps<V extends string = string> {
|
|
212
|
+
tabs: ReadonlyArray<DesignerPanelTab<V>>;
|
|
213
|
+
value: V;
|
|
214
|
+
onValueChange: (value: V) => void;
|
|
215
|
+
/**
|
|
216
|
+
* Show only the active tab's label (icons for the rest) — for narrow
|
|
217
|
+
* panels. Requires icons. Default: false.
|
|
218
|
+
*/
|
|
219
|
+
iconsOnly?: boolean;
|
|
220
|
+
/** Stretch tabs to share the full width when they fit. Default: false. */
|
|
221
|
+
fill?: boolean;
|
|
222
|
+
/** Accessible name for the tablist. */
|
|
223
|
+
"aria-label"?: string;
|
|
224
|
+
idPrefix?: string;
|
|
225
|
+
className?: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Panel tab strip that never clips: it scrolls horizontally with edge fades
|
|
229
|
+
* and keeps the active tab in view. Value-based wrapper over TabsSubtle —
|
|
230
|
+
* render the matching content yourself (`{value === "sections" && …}`).
|
|
231
|
+
*/
|
|
232
|
+
declare function DesignerPanelTabs<V extends string = string>({ tabs, value, onValueChange, iconsOnly, fill, "aria-label": ariaLabel, idPrefix, className, }: DesignerPanelTabsProps<V>): react_jsx_runtime.JSX.Element;
|
|
174
233
|
|
|
175
234
|
interface DesignerPaneProps {
|
|
176
235
|
/**
|
|
@@ -216,6 +275,13 @@ interface DesignerPropertyRowProps extends ComponentPropsWithoutRef<"div"> {
|
|
|
216
275
|
labelFor?: string;
|
|
217
276
|
/** Class name for the generated controls container when label is provided. */
|
|
218
277
|
controlsClassName?: string;
|
|
278
|
+
/**
|
|
279
|
+
* `stacked` (default) puts the label above the controls; `inline` puts it
|
|
280
|
+
* in a fixed-width column to the left — the dense Figma-style inspector row.
|
|
281
|
+
*/
|
|
282
|
+
layout?: "stacked" | "inline";
|
|
283
|
+
/** Label column width when `layout="inline"`. Default: 64px. */
|
|
284
|
+
labelWidth?: number | string;
|
|
219
285
|
children: ReactNode;
|
|
220
286
|
}
|
|
221
287
|
interface DesignerPropertyLabelProps extends ComponentPropsWithoutRef<"label"> {
|
|
@@ -228,7 +294,7 @@ interface DesignerPropertyGroupProps extends Omit<ComponentPropsWithoutRef<"div"
|
|
|
228
294
|
title?: ReactNode;
|
|
229
295
|
children: ReactNode;
|
|
230
296
|
}
|
|
231
|
-
declare function DesignerPropertyRow({ label, labelFor, controlsClassName, className, children, ...rest }: DesignerPropertyRowProps): react_jsx_runtime.JSX.Element;
|
|
297
|
+
declare function DesignerPropertyRow({ label, labelFor, controlsClassName, layout, labelWidth, className, children, ...rest }: DesignerPropertyRowProps): react_jsx_runtime.JSX.Element;
|
|
232
298
|
declare function DesignerPropertyLabel({ className, children, ...rest }: DesignerPropertyLabelProps): react_jsx_runtime.JSX.Element;
|
|
233
299
|
declare function DesignerPropertyControls({ className, children, ...rest }: DesignerPropertyControlsProps): react_jsx_runtime.JSX.Element;
|
|
234
300
|
declare function DesignerPropertyGroup({ title, className, children, ...rest }: DesignerPropertyGroupProps): react_jsx_runtime.JSX.Element;
|
|
@@ -406,4 +472,4 @@ interface UseKeybindingsOptions {
|
|
|
406
472
|
*/
|
|
407
473
|
declare function useKeybindings(bindings: KeybindingConfig[], { disabled, target }?: UseKeybindingsOptions): void;
|
|
408
474
|
|
|
409
|
-
export { CornerRadiusControl, type CornerRadiusControlProps, type CornerSide, type DesignerControlValue, DesignerHeader, type DesignerHeaderProps, DesignerPane, DesignerPaneContent, type DesignerPaneContentProps, type DesignerPaneProps, DesignerPaneTitle, type DesignerPaneTitleProps, DesignerPanel, type DesignerPanelProps, DesignerPropertyControls, type DesignerPropertyControlsProps, DesignerPropertyGroup, type DesignerPropertyGroupProps, DesignerPropertyLabel, type DesignerPropertyLabelProps, DesignerPropertyRow, type DesignerPropertyRowProps, DesignerShell, type DesignerShellProps, DesignerSidebar, type DesignerSidebarProps, DesignerToolbar, DesignerToolbarButton, type DesignerToolbarButtonProps, DesignerToolbarGroup, type DesignerToolbarGroupProps, type DesignerToolbarProps, DesignerToolbarSeparator, type DesignerToolbarSeparatorProps, type DesignerValueItem, DesignerWorkspace, type DesignerWorkspaceInsetValue, type DesignerWorkspaceInsets, type DesignerWorkspaceInsetsInput, type DesignerWorkspaceProps, DesignerWorkspaceViewport, type DesignerWorkspaceViewportProps, FourValueControl, type FourValueControlProps, type KeybindingConfig, type ShellContextValue, ShellProvider, type SidebarItem, SpacingControl, type SpacingControlProps, type SpacingSide, TwoValueControl, type TwoValueControlProps, useHistory, useKeybindings, useShellContext };
|
|
475
|
+
export { CornerRadiusControl, type CornerRadiusControlProps, type CornerSide, type DesignerControlValue, DesignerHeader, type DesignerHeaderProps, DesignerPane, DesignerPaneContent, type DesignerPaneContentProps, type DesignerPaneProps, DesignerPaneTitle, type DesignerPaneTitleProps, DesignerPanel, DesignerPanelHeader, type DesignerPanelHeaderProps, type DesignerPanelProps, type DesignerPanelTab, DesignerPanelTabs, type DesignerPanelTabsProps, DesignerPropertyControls, type DesignerPropertyControlsProps, DesignerPropertyGroup, type DesignerPropertyGroupProps, DesignerPropertyLabel, type DesignerPropertyLabelProps, DesignerPropertyRow, type DesignerPropertyRowProps, DesignerShell, type DesignerShellProps, DesignerSidebar, type DesignerSidebarProps, DesignerToolbar, DesignerToolbarButton, type DesignerToolbarButtonProps, DesignerToolbarGroup, type DesignerToolbarGroupProps, type DesignerToolbarProps, DesignerToolbarSeparator, type DesignerToolbarSeparatorProps, type DesignerValueItem, DesignerWorkspace, type DesignerWorkspaceInsetValue, type DesignerWorkspaceInsets, type DesignerWorkspaceInsetsInput, type DesignerWorkspaceProps, DesignerWorkspaceViewport, type DesignerWorkspaceViewportProps, FourValueControl, type FourValueControlProps, type KeybindingConfig, type ShellContextValue, ShellProvider, type SidebarItem, SpacingControl, type SpacingControlProps, type SpacingSide, TwoValueControl, type TwoValueControlProps, useHistory, useKeybindings, useShellContext };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { createContext, useContext, useState, useMemo, useCallback, useEffect } from 'react';
|
|
2
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { cn, TooltipProvider, Tooltip, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, Button, InputNumber } from '@hilum/ui';
|
|
4
|
+
import { DensityProvider, cn, TooltipProvider, Tooltip, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, TabsSubtle, TabsSubtleItem, Button, InputNumber } from '@hilum/ui';
|
|
4
5
|
import { ChevronDown, Link2, Unlink2 } from 'lucide-react';
|
|
5
6
|
|
|
6
7
|
// src/shell/ShellContext.tsx
|
|
@@ -41,17 +42,19 @@ function ShellProvider({
|
|
|
41
42
|
);
|
|
42
43
|
return /* @__PURE__ */ jsx(ShellContext.Provider, { value, children });
|
|
43
44
|
}
|
|
44
|
-
function DesignerShell({ className, children }) {
|
|
45
|
-
return /* @__PURE__ */ jsx(
|
|
45
|
+
function DesignerShell({ className, density = "compact", children }) {
|
|
46
|
+
return /* @__PURE__ */ jsx(DensityProvider, { density, wrap: false, children: /* @__PURE__ */ jsx(
|
|
46
47
|
"div",
|
|
47
48
|
{
|
|
49
|
+
"data-designer-shell": true,
|
|
50
|
+
"data-density": density,
|
|
48
51
|
className: cn(
|
|
49
|
-
"flex flex-col h-screen w-screen overflow-hidden bg-
|
|
52
|
+
"flex flex-col h-screen w-screen overflow-hidden bg-canvas text-foreground",
|
|
50
53
|
className
|
|
51
54
|
),
|
|
52
55
|
children
|
|
53
56
|
}
|
|
54
|
-
);
|
|
57
|
+
) });
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
// src/components/designer-workspace-insets.ts
|
|
@@ -94,7 +97,7 @@ function DesignerWorkspace({
|
|
|
94
97
|
{
|
|
95
98
|
"data-designer-workspace": true,
|
|
96
99
|
className: cn(
|
|
97
|
-
"relative isolate flex min-h-0 min-w-0 flex-1 overflow-hidden bg-
|
|
100
|
+
"relative isolate flex min-h-0 min-w-0 flex-1 overflow-hidden bg-canvas",
|
|
98
101
|
className
|
|
99
102
|
),
|
|
100
103
|
style: workspaceStyle,
|
|
@@ -139,7 +142,7 @@ function DesignerHeader({
|
|
|
139
142
|
{
|
|
140
143
|
"data-designer-header": true,
|
|
141
144
|
className: cn(
|
|
142
|
-
"grid h-12 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3
|
|
145
|
+
"grid h-12 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 bg-card px-3",
|
|
143
146
|
className
|
|
144
147
|
),
|
|
145
148
|
...props,
|
|
@@ -191,7 +194,7 @@ function DesignerSidebar({
|
|
|
191
194
|
"aria-label": "Editor tools",
|
|
192
195
|
className: cn(
|
|
193
196
|
"fixed inset-x-3 bottom-[max(0.75rem,env(safe-area-inset-bottom))] z-40",
|
|
194
|
-
"rounded-xl border border-border bg-card p-1 shadow-
|
|
197
|
+
"rounded-xl border border-border bg-card p-1 shadow-surface-3",
|
|
195
198
|
className
|
|
196
199
|
),
|
|
197
200
|
style,
|
|
@@ -240,7 +243,7 @@ function DesignerSidebar({
|
|
|
240
243
|
"data-side": side,
|
|
241
244
|
"data-variant": variant,
|
|
242
245
|
className: cn(
|
|
243
|
-
"absolute z-30 flex w-12 flex-col overflow-hidden rounded-lg bg-card shadow-
|
|
246
|
+
"absolute z-30 flex w-12 flex-col overflow-hidden rounded-lg bg-card shadow-surface-3 compact:w-11",
|
|
244
247
|
"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none",
|
|
245
248
|
className
|
|
246
249
|
),
|
|
@@ -295,9 +298,11 @@ function SidebarButton({
|
|
|
295
298
|
"aria-pressed": item.active,
|
|
296
299
|
className: cn(
|
|
297
300
|
"relative flex size-9 items-center justify-center rounded-md transition-[background-color,color,opacity,scale] active:scale-[0.96]",
|
|
301
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
302
|
+
"compact:size-8 compact:rounded-[6px]",
|
|
298
303
|
"[@media(pointer:coarse)]:size-11",
|
|
299
304
|
touchTarget && "size-11 shrink-0",
|
|
300
|
-
item.active ? "bg-foreground text-background" : "text-muted-foreground hover:bg-
|
|
305
|
+
item.active ? "bg-foreground text-background" : "text-muted-foreground hover:bg-hover hover:text-foreground active:bg-active",
|
|
301
306
|
item.disabled && "opacity-50 cursor-not-allowed"
|
|
302
307
|
),
|
|
303
308
|
children: [
|
|
@@ -321,6 +326,7 @@ function DesignerPanel({
|
|
|
321
326
|
sheetDescription,
|
|
322
327
|
sheetSide = "bottom",
|
|
323
328
|
sheetClassName,
|
|
329
|
+
density = "compact",
|
|
324
330
|
className,
|
|
325
331
|
style,
|
|
326
332
|
children
|
|
@@ -331,9 +337,10 @@ function DesignerPanel({
|
|
|
331
337
|
...onOpenChange ? { onOpenChange } : {}
|
|
332
338
|
};
|
|
333
339
|
const resolvedSheetDescription = sheetDescription ?? "Editor panel controls";
|
|
334
|
-
return /* @__PURE__ */ jsx(Sheet, { ...sheetProps, children: /* @__PURE__ */ jsxs(
|
|
340
|
+
return /* @__PURE__ */ jsx(DensityProvider, { density, wrap: false, children: /* @__PURE__ */ jsx(Sheet, { ...sheetProps, children: /* @__PURE__ */ jsxs(
|
|
335
341
|
SheetContent,
|
|
336
342
|
{
|
|
343
|
+
"data-density": density,
|
|
337
344
|
side: sheetSide,
|
|
338
345
|
className: cn(
|
|
339
346
|
"flex max-h-[min(86svh,44rem)] flex-col overflow-hidden p-0",
|
|
@@ -354,7 +361,7 @@ function DesignerPanel({
|
|
|
354
361
|
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto", children })
|
|
355
362
|
]
|
|
356
363
|
}
|
|
357
|
-
) });
|
|
364
|
+
) }) });
|
|
358
365
|
}
|
|
359
366
|
const floatingInsets = resolveDesignerWorkspaceInsets(floatingInset, 16);
|
|
360
367
|
const floatingStyle = variant === "floating" ? {
|
|
@@ -366,17 +373,18 @@ function DesignerPanel({
|
|
|
366
373
|
maxWidth: "calc(100% - 2rem)",
|
|
367
374
|
...style
|
|
368
375
|
} : { width, maxWidth: "100%", ...style };
|
|
369
|
-
return /* @__PURE__ */ jsx(
|
|
376
|
+
return /* @__PURE__ */ jsx(DensityProvider, { density, wrap: false, children: /* @__PURE__ */ jsx(
|
|
370
377
|
"aside",
|
|
371
378
|
{
|
|
372
379
|
"data-side": side,
|
|
373
380
|
"data-variant": variant,
|
|
381
|
+
"data-density": density,
|
|
374
382
|
className: cn(
|
|
375
|
-
"flex min-w-0 max-w-full shrink-0 flex-col overflow-hidden bg-card",
|
|
383
|
+
"flex min-w-0 max-w-full shrink-0 flex-col overflow-hidden bg-card text-foreground",
|
|
376
384
|
variant === "inline" && bordered && (side === "left" ? "border-r" : "border-l"),
|
|
377
385
|
variant === "inline" && bordered && "border-border",
|
|
378
386
|
variant === "floating" && [
|
|
379
|
-
"absolute z-20 rounded-lg shadow-
|
|
387
|
+
"absolute z-20 rounded-lg shadow-surface-3",
|
|
380
388
|
"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none"
|
|
381
389
|
],
|
|
382
390
|
className
|
|
@@ -384,6 +392,76 @@ function DesignerPanel({
|
|
|
384
392
|
style: floatingStyle,
|
|
385
393
|
children: /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto", children })
|
|
386
394
|
}
|
|
395
|
+
) });
|
|
396
|
+
}
|
|
397
|
+
function DesignerPanelHeader({
|
|
398
|
+
title,
|
|
399
|
+
description,
|
|
400
|
+
actions,
|
|
401
|
+
children,
|
|
402
|
+
sticky = true,
|
|
403
|
+
className
|
|
404
|
+
}) {
|
|
405
|
+
return /* @__PURE__ */ jsxs(
|
|
406
|
+
"div",
|
|
407
|
+
{
|
|
408
|
+
"data-slot": "designer-panel-header",
|
|
409
|
+
className: cn(
|
|
410
|
+
"flex min-w-0 shrink-0 flex-col gap-2 border-b border-border bg-card px-3 py-2.5",
|
|
411
|
+
sticky && "sticky top-0 z-10",
|
|
412
|
+
className
|
|
413
|
+
),
|
|
414
|
+
children: [
|
|
415
|
+
(title || actions) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
416
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
417
|
+
title && /* @__PURE__ */ jsx("div", { className: "body-sm truncate font-semibold text-foreground", children: title }),
|
|
418
|
+
description && /* @__PURE__ */ jsx("div", { className: "caption-sm truncate text-muted-foreground", children: description })
|
|
419
|
+
] }),
|
|
420
|
+
actions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1", children: actions })
|
|
421
|
+
] }),
|
|
422
|
+
children
|
|
423
|
+
]
|
|
424
|
+
}
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
function DesignerPanelTabs({
|
|
428
|
+
tabs,
|
|
429
|
+
value,
|
|
430
|
+
onValueChange,
|
|
431
|
+
iconsOnly = false,
|
|
432
|
+
fill = false,
|
|
433
|
+
"aria-label": ariaLabel,
|
|
434
|
+
idPrefix,
|
|
435
|
+
className
|
|
436
|
+
}) {
|
|
437
|
+
const selectedIndex = Math.max(
|
|
438
|
+
0,
|
|
439
|
+
tabs.findIndex((tab) => tab.value === value)
|
|
440
|
+
);
|
|
441
|
+
return /* @__PURE__ */ jsx(
|
|
442
|
+
TabsSubtle,
|
|
443
|
+
{
|
|
444
|
+
selectedIndex,
|
|
445
|
+
onSelect: (index) => {
|
|
446
|
+
const tab = tabs[index];
|
|
447
|
+
if (tab && !tab.disabled) onValueChange(tab.value);
|
|
448
|
+
},
|
|
449
|
+
activeLabel: iconsOnly,
|
|
450
|
+
...idPrefix ? { idPrefix } : {},
|
|
451
|
+
...ariaLabel ? { "aria-label": ariaLabel } : {},
|
|
452
|
+
className: cn("w-full", className),
|
|
453
|
+
children: tabs.map((tab, index) => /* @__PURE__ */ jsx(
|
|
454
|
+
TabsSubtleItem,
|
|
455
|
+
{
|
|
456
|
+
index,
|
|
457
|
+
label: tab.label,
|
|
458
|
+
...tab.icon ? { icon: tab.icon } : {},
|
|
459
|
+
...tab.disabled ? { "aria-disabled": true } : {},
|
|
460
|
+
className: cn("justify-center px-2.5 py-1.5", fill && "flex-1")
|
|
461
|
+
},
|
|
462
|
+
tab.value
|
|
463
|
+
))
|
|
464
|
+
}
|
|
387
465
|
);
|
|
388
466
|
}
|
|
389
467
|
function DesignerPane({
|
|
@@ -431,7 +509,8 @@ function DesignerPaneTitle({ className, children, action }) {
|
|
|
431
509
|
className: cn(
|
|
432
510
|
"flex min-h-10 w-full items-center justify-between gap-2 px-3 py-2 text-left",
|
|
433
511
|
"caption-xs uppercase tracking-wider font-semibold text-muted-foreground",
|
|
434
|
-
|
|
512
|
+
"compact:min-h-8 compact:py-1.5 compact:text-[10px]",
|
|
513
|
+
collapsible && "hover:text-foreground transition-colors outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
435
514
|
className
|
|
436
515
|
),
|
|
437
516
|
children: [
|
|
@@ -457,7 +536,7 @@ function DesignerPaneContent({ className, children }) {
|
|
|
457
536
|
"div",
|
|
458
537
|
{
|
|
459
538
|
className: cn(
|
|
460
|
-
"flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden px-3 pb-3",
|
|
539
|
+
"flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden px-3 pb-3 compact:gap-1.5",
|
|
461
540
|
className
|
|
462
541
|
),
|
|
463
542
|
children
|
|
@@ -473,20 +552,33 @@ function DesignerPropertyRow({
|
|
|
473
552
|
label,
|
|
474
553
|
labelFor,
|
|
475
554
|
controlsClassName,
|
|
555
|
+
layout = "stacked",
|
|
556
|
+
labelWidth = 64,
|
|
476
557
|
className,
|
|
477
558
|
children,
|
|
478
559
|
...rest
|
|
479
560
|
}) {
|
|
561
|
+
const inline = layout === "inline";
|
|
480
562
|
return /* @__PURE__ */ jsx(
|
|
481
563
|
"div",
|
|
482
564
|
{
|
|
565
|
+
"data-layout": layout,
|
|
483
566
|
className: cn(
|
|
484
|
-
"flex w-full min-w-0 max-w-full
|
|
567
|
+
"flex w-full min-w-0 max-w-full py-1.5 compact:py-0.5",
|
|
568
|
+
inline ? "flex-row items-center gap-2 compact:min-h-7" : "flex-col items-stretch gap-1.5 compact:gap-1",
|
|
485
569
|
className
|
|
486
570
|
),
|
|
487
571
|
...rest,
|
|
488
572
|
children: label === void 0 ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
489
|
-
/* @__PURE__ */ jsx(
|
|
573
|
+
/* @__PURE__ */ jsx(
|
|
574
|
+
DesignerPropertyLabel,
|
|
575
|
+
{
|
|
576
|
+
htmlFor: labelFor,
|
|
577
|
+
className: inline ? "w-auto shrink-0 truncate" : void 0,
|
|
578
|
+
style: inline ? { width: typeof labelWidth === "number" ? `${labelWidth}px` : labelWidth } : void 0,
|
|
579
|
+
children: label
|
|
580
|
+
}
|
|
581
|
+
),
|
|
490
582
|
/* @__PURE__ */ jsx(DesignerPropertyControls, { className: controlsClassName, children })
|
|
491
583
|
] })
|
|
492
584
|
}
|
|
@@ -497,7 +589,7 @@ function DesignerPropertyLabel({ className, children, ...rest }) {
|
|
|
497
589
|
"label",
|
|
498
590
|
{
|
|
499
591
|
className: cn(
|
|
500
|
-
"caption w-full min-w-0 max-w-full select-none text-muted-foreground",
|
|
592
|
+
"caption w-full min-w-0 max-w-full select-none text-muted-foreground compact:text-[11px] compact:leading-4",
|
|
501
593
|
className
|
|
502
594
|
),
|
|
503
595
|
...rest,
|
|
@@ -524,7 +616,7 @@ function DesignerPropertyGroup({
|
|
|
524
616
|
children,
|
|
525
617
|
...rest
|
|
526
618
|
}) {
|
|
527
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 max-w-full flex-col gap-3", className), ...rest, children: [
|
|
619
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 max-w-full flex-col gap-3 compact:gap-2", className), ...rest, children: [
|
|
528
620
|
title && /* @__PURE__ */ jsx("div", { className: "caption-xs min-w-0 max-w-full select-none overflow-hidden text-ellipsis uppercase tracking-wider text-muted-foreground", children: title }),
|
|
529
621
|
children
|
|
530
622
|
] });
|
|
@@ -546,7 +638,7 @@ function DesignerToolbar({
|
|
|
546
638
|
{
|
|
547
639
|
role: "toolbar",
|
|
548
640
|
className: cn(
|
|
549
|
-
"flex items-center gap-0.5 rounded-lg bg-card p-1 shadow-
|
|
641
|
+
"flex items-center gap-0.5 rounded-lg bg-card p-1 shadow-surface-3",
|
|
550
642
|
"transition-[opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none",
|
|
551
643
|
variant === "floating" && positioned,
|
|
552
644
|
variant === "floating" && "bottom-4 -translate-x-1/2 z-30",
|
|
@@ -567,7 +659,14 @@ function DesignerToolbarGroup({ className, children }) {
|
|
|
567
659
|
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children });
|
|
568
660
|
}
|
|
569
661
|
function DesignerToolbarSeparator({ className }) {
|
|
570
|
-
return /* @__PURE__ */ jsx(
|
|
662
|
+
return /* @__PURE__ */ jsx(
|
|
663
|
+
"div",
|
|
664
|
+
{
|
|
665
|
+
className: cn("mx-1 h-5 w-px bg-border compact:h-4", className),
|
|
666
|
+
role: "separator",
|
|
667
|
+
"aria-orientation": "vertical"
|
|
668
|
+
}
|
|
669
|
+
);
|
|
571
670
|
}
|
|
572
671
|
function DesignerToolbarButton({
|
|
573
672
|
label,
|
|
@@ -600,10 +699,12 @@ function DesignerToolbarButton({
|
|
|
600
699
|
"aria-label": label,
|
|
601
700
|
"aria-pressed": active,
|
|
602
701
|
className: cn(
|
|
603
|
-
"flex h-9 min-w-9 items-center justify-center gap-1 rounded-md px-2 caption transition-[background-color,color,opacity,scale] active:scale-[0.96]",
|
|
702
|
+
"flex h-9 min-w-9 items-center justify-center gap-1 rounded-md px-2 caption tabular-nums transition-[background-color,color,opacity,scale] active:scale-[0.96]",
|
|
703
|
+
"outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
704
|
+
"compact:h-8 compact:min-w-8 compact:rounded-[6px] compact:px-1.5 compact:text-[12px]",
|
|
604
705
|
"[@media(pointer:coarse)]:h-11 [@media(pointer:coarse)]:min-w-11",
|
|
605
706
|
size === "touch" && "h-11 min-w-11",
|
|
606
|
-
active ? "bg-foreground text-background" : "text-muted-foreground hover:bg-
|
|
707
|
+
active ? "bg-foreground text-background" : "text-muted-foreground hover:bg-hover hover:text-foreground active:bg-active",
|
|
607
708
|
disabled && "opacity-50 cursor-not-allowed",
|
|
608
709
|
className
|
|
609
710
|
),
|
|
@@ -637,30 +738,29 @@ function DesignerValueField({
|
|
|
637
738
|
onChange,
|
|
638
739
|
onCommit
|
|
639
740
|
}) {
|
|
640
|
-
return /* @__PURE__ */
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
] });
|
|
741
|
+
return /* @__PURE__ */ jsx("div", { className: "relative min-w-0", children: /* @__PURE__ */ jsx(
|
|
742
|
+
InputNumber,
|
|
743
|
+
{
|
|
744
|
+
label: /* @__PURE__ */ jsx("span", { className: "uppercase", children: item.label }),
|
|
745
|
+
scrubLabel: item.ariaLabel,
|
|
746
|
+
value,
|
|
747
|
+
onChange,
|
|
748
|
+
min: item.min ?? min,
|
|
749
|
+
max: item.max ?? max,
|
|
750
|
+
step: item.step ?? step,
|
|
751
|
+
precision: item.precision ?? precision,
|
|
752
|
+
unit: item.unit ?? unit,
|
|
753
|
+
mixedLabel,
|
|
754
|
+
commitOnChange: true,
|
|
755
|
+
hideSteppers,
|
|
756
|
+
disabled: disabled || item.disabled,
|
|
757
|
+
readOnly,
|
|
758
|
+
"aria-label": item.ariaLabel ?? (typeof item.label === "string" ? item.label : void 0),
|
|
759
|
+
onBlur: onCommit,
|
|
760
|
+
className: cn("h-8 w-full compact:h-6", inputClassName),
|
|
761
|
+
inputMode: "decimal"
|
|
762
|
+
}
|
|
763
|
+
) });
|
|
664
764
|
}
|
|
665
765
|
function DesignerValueControl({
|
|
666
766
|
label,
|
|
@@ -703,9 +803,18 @@ function DesignerValueControl({
|
|
|
703
803
|
}
|
|
704
804
|
onChange(key, value);
|
|
705
805
|
};
|
|
706
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col gap-1.5", className), children: [
|
|
806
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col gap-1.5 compact:gap-1", className), children: [
|
|
707
807
|
(label || hasLinkControl) && /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
|
|
708
|
-
label && /* @__PURE__ */ jsx(
|
|
808
|
+
label && /* @__PURE__ */ jsx(
|
|
809
|
+
"div",
|
|
810
|
+
{
|
|
811
|
+
className: cn(
|
|
812
|
+
"caption select-none text-muted-foreground compact:text-[11px]",
|
|
813
|
+
labelClassName
|
|
814
|
+
),
|
|
815
|
+
children: label
|
|
816
|
+
}
|
|
817
|
+
),
|
|
709
818
|
hasLinkControl && /* @__PURE__ */ jsx(
|
|
710
819
|
Button,
|
|
711
820
|
{
|
|
@@ -744,7 +853,7 @@ function DesignerValueControl({
|
|
|
744
853
|
"div",
|
|
745
854
|
{
|
|
746
855
|
className: cn(
|
|
747
|
-
"grid min-w-0 gap-2",
|
|
856
|
+
"grid min-w-0 gap-2 compact:gap-1.5",
|
|
748
857
|
items.length === 2 ? "grid-cols-2" : "grid-cols-2",
|
|
749
858
|
controlsClassName
|
|
750
859
|
),
|
|
@@ -892,6 +1001,6 @@ function useKeybindings(bindings, { disabled, target } = {}) {
|
|
|
892
1001
|
}, [bindings, disabled, target]);
|
|
893
1002
|
}
|
|
894
1003
|
|
|
895
|
-
export { CornerRadiusControl, DesignerHeader, DesignerPane, DesignerPaneContent, DesignerPaneTitle, DesignerPanel, DesignerPropertyControls, DesignerPropertyGroup, DesignerPropertyLabel, DesignerPropertyRow, DesignerShell, DesignerSidebar, DesignerToolbar, DesignerToolbarButton, DesignerToolbarGroup, DesignerToolbarSeparator, DesignerWorkspace, DesignerWorkspaceViewport, FourValueControl, ShellProvider, SpacingControl, TwoValueControl, useHistory, useKeybindings, useShellContext };
|
|
1004
|
+
export { CornerRadiusControl, DesignerHeader, DesignerPane, DesignerPaneContent, DesignerPaneTitle, DesignerPanel, DesignerPanelHeader, DesignerPanelTabs, DesignerPropertyControls, DesignerPropertyGroup, DesignerPropertyLabel, DesignerPropertyRow, DesignerShell, DesignerSidebar, DesignerToolbar, DesignerToolbarButton, DesignerToolbarGroup, DesignerToolbarSeparator, DesignerWorkspace, DesignerWorkspaceViewport, FourValueControl, ShellProvider, SpacingControl, TwoValueControl, useHistory, useKeybindings, useShellContext };
|
|
896
1005
|
//# sourceMappingURL=index.js.map
|
|
897
1006
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell/ShellContext.tsx","../src/components/DesignerShell.tsx","../src/components/designer-workspace-insets.ts","../src/components/DesignerWorkspace.tsx","../src/components/DesignerHeader.tsx","../src/components/DesignerSidebar.tsx","../src/components/DesignerPanel.tsx","../src/components/DesignerPane.tsx","../src/components/DesignerPropertyRow.tsx","../src/components/DesignerToolbar.tsx","../src/components/DesignerValueControls.tsx","../src/hooks/useHistory.ts","../src/hooks/useKeybindings.ts"],"names":["jsx","cn","jsxs","useState","createContext","useContext","TooltipProvider","Tooltip"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext, useMemo, useState } from \"react\";\nimport type { Dispatch, ReactNode, SetStateAction } from \"react\";\n\n/**\n * The minimal contract a designer shell needs from the engine beneath it.\n *\n * The chrome (toolbar, panel, pane, sidebar) reads from this context.\n * It does NOT know what is being edited — selection IDs are opaque strings\n * (layer IDs, field IDs, node IDs — whatever the engine uses), and active\n * tool is an open string the app defines (`select`, `hand`, `text`, …).\n *\n * @hilum/designer-canvas wires this up for canvas apps. A form-builder app\n * could wire its own engine to ShellContext with the same primitives.\n */\nexport interface ShellContextValue {\n /** IDs of currently-selected items. Engine-defined meaning. */\n selectedIds: string[];\n setSelectedIds: Dispatch<SetStateAction<string[]>>;\n\n /** Active tool. App-defined enum (e.g. 'select' | 'hand' | 'text'). */\n activeTool: string;\n setActiveTool: Dispatch<SetStateAction<string>>;\n\n /** When true, mutating actions should no-op. Used for previews. */\n readOnly: boolean;\n\n /**\n * Optional resolver: given a `selectedId`, return its engine-defined \"kind\"\n * (e.g. 'text', 'image'). DesignerPane.showFor uses this to decide whether\n * to render. Apps that don't have typed selections can leave this undefined.\n */\n resolveKind?: (id: string) => string | undefined;\n}\n\nconst noop = () => {};\n\nconst DEFAULT: ShellContextValue = {\n selectedIds: [],\n setSelectedIds: noop as Dispatch<SetStateAction<string[]>>,\n activeTool: \"select\",\n setActiveTool: noop as Dispatch<SetStateAction<string>>,\n readOnly: false,\n};\n\nconst ShellContext = createContext<ShellContextValue>(DEFAULT);\n\nexport function useShellContext(): ShellContextValue {\n return useContext(ShellContext);\n}\n\ninterface ShellProviderProps {\n /** Initial selected IDs. Default: []. */\n initialSelectedIds?: string[];\n /** Initial active tool. Default: 'select'. */\n initialTool?: string;\n /** Read-only flag. */\n readOnly?: boolean;\n /** Kind resolver — see ShellContextValue.resolveKind. */\n resolveKind?: (id: string) => string | undefined;\n /** Controlled override — pass a value to lift state out of the provider. */\n value?: Partial<ShellContextValue>;\n children: ReactNode;\n}\n\nexport function ShellProvider({\n initialSelectedIds = [],\n initialTool = \"select\",\n readOnly = false,\n resolveKind,\n value: controlled,\n children,\n}: ShellProviderProps) {\n const [selectedIds, setSelectedIds] = useState<string[]>(initialSelectedIds);\n const [activeTool, setActiveTool] = useState<string>(initialTool);\n\n const resolvedKind = controlled?.resolveKind ?? resolveKind;\n\n const value = useMemo<ShellContextValue>(\n () => ({\n selectedIds: controlled?.selectedIds ?? selectedIds,\n setSelectedIds: controlled?.setSelectedIds ?? setSelectedIds,\n activeTool: controlled?.activeTool ?? activeTool,\n setActiveTool: controlled?.setActiveTool ?? setActiveTool,\n readOnly: controlled?.readOnly ?? readOnly,\n ...(resolvedKind !== undefined && { resolveKind: resolvedKind }),\n }),\n [selectedIds, activeTool, readOnly, resolvedKind, controlled],\n );\n\n return <ShellContext.Provider value={value}>{children}</ShellContext.Provider>;\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\n\ninterface DesignerShellProps {\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Root layout for an editor app — full viewport, themed surface.\n * Place a <DesignerHeader>, <DesignerSidebar>, <DesignerPanel>, and the\n * canvas content as children.\n */\nfunction DesignerShell({ className, children }: DesignerShellProps) {\n return (\n <div\n className={cn(\n \"flex flex-col h-screen w-screen overflow-hidden bg-muted text-foreground\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nexport { DesignerShell };\nexport type { DesignerShellProps };\n","export type DesignerWorkspaceInsetValue = number | string;\n\nexport interface DesignerWorkspaceInsets {\n top: DesignerWorkspaceInsetValue;\n right: DesignerWorkspaceInsetValue;\n bottom: DesignerWorkspaceInsetValue;\n left: DesignerWorkspaceInsetValue;\n}\n\nexport type DesignerWorkspaceInsetsInput =\n | DesignerWorkspaceInsetValue\n | Partial<DesignerWorkspaceInsets>;\n\nfunction toCssLength(value: DesignerWorkspaceInsetValue): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\nexport function resolveDesignerWorkspaceInsets(\n input: DesignerWorkspaceInsetsInput | undefined,\n fallback: DesignerWorkspaceInsetValue = 0,\n): Record<keyof DesignerWorkspaceInsets, string> {\n const fallbackValue = toCssLength(fallback);\n\n if (typeof input === \"number\" || typeof input === \"string\") {\n const value = toCssLength(input);\n return { top: value, right: value, bottom: value, left: value };\n }\n\n return {\n top: input?.top === undefined ? fallbackValue : toCssLength(input.top),\n right: input?.right === undefined ? fallbackValue : toCssLength(input.right),\n bottom: input?.bottom === undefined ? fallbackValue : toCssLength(input.bottom),\n left: input?.left === undefined ? fallbackValue : toCssLength(input.left),\n };\n}\n\nexport function getDesignerFloatingMaxHeight(insets: {\n top: string;\n bottom: string;\n}): string {\n return `calc(100% - ${insets.top} - ${insets.bottom})`;\n}\n","import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\nimport {\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n type DesignerWorkspaceInsetValue,\n} from \"./designer-workspace-insets\";\n\ninterface DesignerWorkspaceProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * Insets that describe the unobscured canvas area between floating chrome.\n * Numbers are interpreted as pixels; CSS lengths and calc() expressions are\n * accepted for responsive shells.\n */\n safeInsets?: DesignerWorkspaceInsetsInput;\n children: ReactNode;\n}\n\ninterface DesignerWorkspaceViewportProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n children: ReactNode;\n}\n\ntype WorkspaceStyle = CSSProperties & {\n \"--designer-workspace-inset-top\": string;\n \"--designer-workspace-inset-right\": string;\n \"--designer-workspace-inset-bottom\": string;\n \"--designer-workspace-inset-left\": string;\n};\n\n/**\n * Positioning boundary for a canvas editor. Floating rails, panels, and\n * toolbars are layered over this surface while DesignerWorkspaceViewport uses\n * the configured safe insets to keep document content unobscured.\n */\nfunction DesignerWorkspace({\n safeInsets,\n className,\n style,\n children,\n ...props\n}: DesignerWorkspaceProps) {\n const insets = resolveDesignerWorkspaceInsets(safeInsets);\n const workspaceStyle = {\n \"--designer-workspace-inset-top\": insets.top,\n \"--designer-workspace-inset-right\": insets.right,\n \"--designer-workspace-inset-bottom\": insets.bottom,\n \"--designer-workspace-inset-left\": insets.left,\n ...style,\n } as WorkspaceStyle;\n\n return (\n <div\n data-designer-workspace\n className={cn(\n \"relative isolate flex min-h-0 min-w-0 flex-1 overflow-hidden bg-muted\",\n className,\n )}\n style={workspaceStyle}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Safe, canvas-sized region within DesignerWorkspace. Its bounds are derived\n * from the workspace's safeInsets so fit/center calculations use the visible\n * area between floating editor chrome.\n */\nfunction DesignerWorkspaceViewport({\n className,\n style,\n children,\n ...props\n}: DesignerWorkspaceViewportProps) {\n return (\n <div\n data-designer-workspace-viewport\n className={cn(\"absolute z-0 flex min-h-0 min-w-0 overflow-hidden\", className)}\n style={{\n top: \"var(--designer-workspace-inset-top)\",\n right: \"var(--designer-workspace-inset-right)\",\n bottom: \"var(--designer-workspace-inset-bottom)\",\n left: \"var(--designer-workspace-inset-left)\",\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport { DesignerWorkspace, DesignerWorkspaceViewport };\nexport type {\n DesignerWorkspaceProps,\n DesignerWorkspaceViewportProps,\n DesignerWorkspaceInsets,\n DesignerWorkspaceInsetsInput,\n DesignerWorkspaceInsetValue,\n};\n","import type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\n\ninterface DesignerHeaderProps extends Omit<ComponentPropsWithoutRef<\"header\">, \"children\"> {\n /** Left-aligned content — file name, breadcrumbs, project switcher. */\n left?: ReactNode;\n /** Center content — typically the active document title. */\n center?: ReactNode;\n /** Right-aligned content — share, export, presence, account. */\n right?: ReactNode;\n className?: string;\n children?: ReactNode;\n}\n\n/**\n * Top bar of an editor app. Slot-driven — the chrome doesn't know what\n * goes in each region. Use <DesignerHeader left={...} center={...} right={...} />.\n */\nfunction DesignerHeader({\n left,\n center,\n right,\n className,\n children,\n ...props\n}: DesignerHeaderProps) {\n return (\n <header\n data-designer-header\n className={cn(\n \"grid h-12 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card px-3\",\n className,\n )}\n {...props}\n >\n <div\n data-designer-header-slot=\"left\"\n className=\"flex min-w-0 items-center gap-2 justify-self-start\"\n >\n {left}\n </div>\n <div\n data-designer-header-slot=\"center\"\n className=\"flex min-w-0 items-center gap-2 justify-self-center\"\n >\n {center}\n </div>\n <div\n data-designer-header-slot=\"right\"\n className=\"flex min-w-0 items-center gap-2 justify-self-end\"\n >\n {right}\n </div>\n {children}\n </header>\n );\n}\n\nexport { DesignerHeader };\nexport type { DesignerHeaderProps };\n","import type { ComponentType, CSSProperties, ReactNode } from \"react\";\nimport { cn, Tooltip, TooltipProvider } from \"@hilum/ui\";\nimport {\n getDesignerFloatingMaxHeight,\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n} from \"./designer-workspace-insets\";\n\ninterface SidebarItem {\n id: string;\n label: string;\n icon: ComponentType<{ size?: number; className?: string }>;\n onClick?: () => void;\n /** Caller-computed active flag. */\n active?: boolean;\n disabled?: boolean;\n badge?: ReactNode;\n}\n\ninterface DesignerSidebarProps {\n /** Top group of icon buttons. */\n items: SidebarItem[];\n /** Optional bottom group (settings, help, account). */\n bottomItems?: SidebarItem[];\n /** Layout variant. `rail` preserves the inline desktop vertical rail. */\n variant?: \"rail\" | \"floating\" | \"bottom\";\n side?: \"left\" | \"right\";\n /** Insets used to position a floating rail within DesignerWorkspace. Default: 16px. */\n floatingInset?: DesignerWorkspaceInsetsInput;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\n/**\n * Vertical icon rail used as the primary tool / navigation column in an\n * editor. Driven by an `items` array — no engine coupling. Each item gets\n * a tooltip showing its label.\n */\nfunction DesignerSidebar({\n items,\n bottomItems,\n variant = \"rail\",\n side = \"left\",\n floatingInset,\n className,\n style,\n children,\n}: DesignerSidebarProps) {\n if (variant === \"bottom\") {\n const allItems = [...items, ...(bottomItems ?? [])];\n\n return (\n <nav\n aria-label=\"Editor tools\"\n className={cn(\n \"fixed inset-x-3 bottom-[max(0.75rem,env(safe-area-inset-bottom))] z-40\",\n \"rounded-xl border border-border bg-card p-1 shadow-natural\",\n className,\n )}\n style={style}\n >\n <TooltipProvider>\n <div className=\"flex min-w-0 items-center gap-1 overflow-x-auto overscroll-x-contain\">\n {allItems.map((item) => (\n <SidebarButton key={item.id} item={item} tooltipSide=\"top\" touchTarget />\n ))}\n </div>\n {children}\n </TooltipProvider>\n </nav>\n );\n }\n\n const content = (\n <TooltipProvider>\n <div\n data-designer-sidebar-items\n className={cn(\n \"flex min-h-0 flex-col items-center gap-0.5 overflow-y-auto overscroll-contain p-1.5\",\n variant === \"floating\" ? \"flex-initial\" : \"flex-1\",\n )}\n >\n {items.map((item) => (\n <SidebarButton\n key={item.id}\n item={item}\n tooltipSide={side === \"left\" ? \"right\" : \"left\"}\n />\n ))}\n </div>\n\n {children}\n\n {bottomItems && bottomItems.length > 0 && (\n <div className=\"flex shrink-0 flex-col items-center gap-0.5 p-1.5\">\n {bottomItems.map((item) => (\n <SidebarButton\n key={item.id}\n item={item}\n tooltipSide={side === \"left\" ? \"right\" : \"left\"}\n />\n ))}\n </div>\n )}\n </TooltipProvider>\n );\n\n if (variant === \"floating\") {\n const insets = resolveDesignerWorkspaceInsets(floatingInset, 16);\n\n return (\n <nav\n aria-label=\"Editor tools\"\n data-side={side}\n data-variant={variant}\n className={cn(\n \"absolute z-30 flex w-12 flex-col overflow-hidden rounded-lg bg-card shadow-natural\",\n \"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n className,\n )}\n style={{\n top: insets.top,\n [side]: insets[side],\n height: \"fit-content\",\n maxHeight: getDesignerFloatingMaxHeight(insets),\n ...style,\n }}\n >\n {content}\n </nav>\n );\n }\n\n return (\n <aside\n data-side={side}\n data-variant={variant}\n className={cn(\n \"flex flex-col w-12 bg-card shrink-0\",\n side === \"left\" ? \"border-r\" : \"border-l\",\n \"border-border\",\n className,\n )}\n style={style}\n >\n {content}\n </aside>\n );\n}\n\nfunction SidebarButton({\n item,\n tooltipSide,\n touchTarget = false,\n}: {\n item: SidebarItem;\n tooltipSide: \"top\" | \"right\" | \"left\";\n touchTarget?: boolean;\n}) {\n const Icon = item.icon;\n return (\n <Tooltip\n content={<span className=\"block whitespace-nowrap\">{item.label}</span>}\n side={tooltipSide}\n sideOffset={10}\n delayDuration={120}\n className=\"max-w-56 rounded-lg bg-foreground px-2.5 py-1.5 text-[12px] font-medium leading-none tracking-[0.01em] text-background shadow-natural\"\n >\n <button\n type=\"button\"\n onClick={item.onClick}\n disabled={item.disabled}\n aria-label={item.label}\n aria-pressed={item.active}\n className={cn(\n \"relative flex size-9 items-center justify-center rounded-md transition-[background-color,color,opacity,scale] active:scale-[0.96]\",\n \"[@media(pointer:coarse)]:size-11\",\n touchTarget && \"size-11 shrink-0\",\n item.active\n ? \"bg-foreground text-background\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n item.disabled && \"opacity-50 cursor-not-allowed\",\n )}\n >\n <Icon size={touchTarget ? 18 : 16} />\n {item.badge != null && (\n <span className=\"absolute -top-0.5 -right-0.5 caption-xs\">{item.badge}</span>\n )}\n </button>\n </Tooltip>\n );\n}\n\nexport { DesignerSidebar };\nexport type { DesignerSidebarProps, SidebarItem };\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { cn, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from \"@hilum/ui\";\nimport {\n getDesignerFloatingMaxHeight,\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n} from \"./designer-workspace-insets\";\n\ninterface DesignerPanelProps {\n side: \"left\" | \"right\";\n /** Presentation mode. `inline` preserves the desktop side-panel behavior. */\n variant?: \"inline\" | \"floating\" | \"sheet\";\n /** Width in pixels. Default: 240. */\n width?: number;\n /** Add a separator border on the inner edge. Default: true. */\n bordered?: boolean;\n /** Insets used to position a floating panel within DesignerWorkspace. Default: 16px. */\n floatingInset?: DesignerWorkspaceInsetsInput;\n /** Controlled open state when `variant=\"sheet\"`. */\n open?: boolean;\n /** Controlled open-state handler when `variant=\"sheet\"`. */\n onOpenChange?: (open: boolean) => void;\n /** Accessible sheet title when `variant=\"sheet\"`. */\n sheetTitle?: ReactNode;\n /** Optional sheet description. */\n sheetDescription?: ReactNode;\n /** Sheet edge. Defaults to `bottom` for mobile editor panels. */\n sheetSide?: \"left\" | \"right\" | \"top\" | \"bottom\";\n sheetClassName?: string;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\n/**\n * Left or right side panel of an editor — typically holds layer lists,\n * inspector / properties, history, comments, etc. Static-width for v1.\n * (Resize handles arrive in a later iteration if needed.)\n */\nfunction DesignerPanel({\n side,\n variant = \"inline\",\n width = 240,\n bordered = true,\n floatingInset,\n open,\n onOpenChange,\n sheetTitle,\n sheetDescription,\n sheetSide = \"bottom\",\n sheetClassName,\n className,\n style,\n children,\n}: DesignerPanelProps) {\n if (variant === \"sheet\") {\n const sheetProps = {\n ...(open !== undefined ? { open } : {}),\n ...(onOpenChange ? { onOpenChange } : {}),\n };\n const resolvedSheetDescription = sheetDescription ?? \"Editor panel controls\";\n\n return (\n <Sheet {...sheetProps}>\n <SheetContent\n side={sheetSide}\n className={cn(\n \"flex max-h-[min(86svh,44rem)] flex-col overflow-hidden p-0\",\n sheetSide === \"bottom\" && \"rounded-t-2xl\",\n sheetClassName,\n )}\n >\n <SheetHeader\n className={cn(sheetTitle ? \"mb-0 border-b border-border px-4 py-3\" : \"sr-only\")}\n >\n <SheetTitle>{sheetTitle ?? `${side} panel`}</SheetTitle>\n <SheetDescription className={sheetDescription ? undefined : \"sr-only\"}>\n {resolvedSheetDescription}\n </SheetDescription>\n </SheetHeader>\n <div className=\"flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto\">\n {children}\n </div>\n </SheetContent>\n </Sheet>\n );\n }\n\n const floatingInsets = resolveDesignerWorkspaceInsets(floatingInset, 16);\n const floatingStyle: CSSProperties | undefined =\n variant === \"floating\"\n ? {\n top: floatingInsets.top,\n [side]: floatingInsets[side],\n width,\n height: \"fit-content\",\n maxHeight: getDesignerFloatingMaxHeight(floatingInsets),\n maxWidth: \"calc(100% - 2rem)\",\n ...style,\n }\n : { width, maxWidth: \"100%\", ...style };\n\n return (\n <aside\n data-side={side}\n data-variant={variant}\n className={cn(\n \"flex min-w-0 max-w-full shrink-0 flex-col overflow-hidden bg-card\",\n variant === \"inline\" && bordered && (side === \"left\" ? \"border-r\" : \"border-l\"),\n variant === \"inline\" && bordered && \"border-border\",\n variant === \"floating\" && [\n \"absolute z-20 rounded-lg shadow-natural\",\n \"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n ],\n className,\n )}\n style={floatingStyle}\n >\n <div className=\"flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto\">\n {children}\n </div>\n </aside>\n );\n}\n\nexport { DesignerPanel };\nexport type { DesignerPanelProps };\n","import { useState, type ReactNode } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"@hilum/ui\";\nimport { useShellContext } from \"../shell/ShellContext\";\n\ninterface DesignerPaneProps {\n /**\n * Predicate or list of allowed kinds. The pane renders only when matched.\n *\n * - `string[]`: render when at least one selected ID resolves to one of\n * these kinds (requires `ShellContext.resolveKind`).\n * - `(selectedIds: string[]) => boolean`: full predicate.\n * - omitted: always render.\n */\n showFor?: string[] | ((selectedIds: string[]) => boolean);\n collapsible?: boolean;\n defaultOpen?: boolean;\n className?: string;\n children: ReactNode;\n}\n\ninterface DesignerPaneTitleProps {\n className?: string;\n children: ReactNode;\n /** Right-aligned action / control. */\n action?: ReactNode;\n}\n\ninterface DesignerPaneContentProps {\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Collapsible inspector section. Use inside a <DesignerPanel>.\n *\n * <DesignerPane showFor={[\"text\"]} collapsible>\n * <DesignerPaneTitle>Typography</DesignerPaneTitle>\n * <DesignerPaneContent>...</DesignerPaneContent>\n * </DesignerPane>\n */\nfunction DesignerPane({\n showFor,\n collapsible = false,\n defaultOpen = true,\n className,\n children,\n}: DesignerPaneProps) {\n const { selectedIds, resolveKind } = useShellContext();\n const [open, setOpen] = useState(defaultOpen);\n\n // Visibility check.\n let visible = true;\n if (typeof showFor === \"function\") {\n visible = showFor(selectedIds);\n } else if (Array.isArray(showFor)) {\n if (!resolveKind) {\n // No resolver: best effort — show only if any IDs are selected.\n visible = selectedIds.length > 0;\n } else {\n visible = selectedIds.some((id) => {\n const kind = resolveKind(id);\n return kind != null && showFor.includes(kind);\n });\n }\n }\n if (!visible) return null;\n\n return (\n <PaneContext.Provider value={{ open, toggle: () => setOpen((v) => !v), collapsible }}>\n <section\n className={cn(\n \"flex min-w-0 max-w-full flex-col overflow-x-hidden border-b border-border last:border-b-0\",\n className,\n )}\n >\n {children}\n </section>\n </PaneContext.Provider>\n );\n}\n\nfunction DesignerPaneTitle({ className, children, action }: DesignerPaneTitleProps) {\n const { open, toggle, collapsible } = usePaneContext();\n\n const Tag = collapsible ? \"button\" : \"div\";\n return (\n <Tag\n type={collapsible ? \"button\" : undefined}\n onClick={collapsible ? toggle : undefined}\n className={cn(\n \"flex min-h-10 w-full items-center justify-between gap-2 px-3 py-2 text-left\",\n \"caption-xs uppercase tracking-wider font-semibold text-muted-foreground\",\n collapsible && \"hover:text-foreground transition-colors\",\n className,\n )}\n >\n <span className=\"flex items-center gap-1.5\">\n {collapsible && (\n <ChevronDown\n size={12}\n className={cn(\"transition-transform duration-150\", !open && \"-rotate-90\")}\n />\n )}\n {children}\n </span>\n {action && <span className=\"ml-auto\">{action}</span>}\n </Tag>\n );\n}\n\nfunction DesignerPaneContent({ className, children }: DesignerPaneContentProps) {\n const { open } = usePaneContext();\n if (!open) return null;\n return (\n <div\n className={cn(\n \"flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden px-3 pb-3\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\n// --- internal pane context (so title and content stay in sync) ---\n\nimport { createContext, useContext } from \"react\";\n\ninterface PaneCtx {\n open: boolean;\n toggle: () => void;\n collapsible: boolean;\n}\nconst PaneContext = createContext<PaneCtx>({ open: true, toggle: () => {}, collapsible: false });\nfunction usePaneContext() {\n return useContext(PaneContext);\n}\n\nexport { DesignerPane, DesignerPaneTitle, DesignerPaneContent };\nexport type { DesignerPaneProps, DesignerPaneTitleProps, DesignerPaneContentProps };\n","import type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\n\ninterface DesignerPropertyRowProps extends ComponentPropsWithoutRef<\"div\"> {\n /** Optional label for direct row usage. Compound usage can use DesignerPropertyLabel. */\n label?: ReactNode;\n /** htmlFor forwarded to the generated label when label is provided. */\n labelFor?: string;\n /** Class name for the generated controls container when label is provided. */\n controlsClassName?: string;\n children: ReactNode;\n}\n\ninterface DesignerPropertyLabelProps extends ComponentPropsWithoutRef<\"label\"> {\n children: ReactNode;\n}\n\ninterface DesignerPropertyControlsProps extends ComponentPropsWithoutRef<\"div\"> {\n children: ReactNode;\n}\n\ninterface DesignerPropertyGroupProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"title\"> {\n title?: ReactNode;\n children: ReactNode;\n}\n\nfunction DesignerPropertyRow({\n label,\n labelFor,\n controlsClassName,\n className,\n children,\n ...rest\n}: DesignerPropertyRowProps) {\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 max-w-full flex-col items-stretch gap-1.5 py-1.5\",\n className,\n )}\n {...rest}\n >\n {label === undefined ? (\n children\n ) : (\n <>\n <DesignerPropertyLabel htmlFor={labelFor}>{label}</DesignerPropertyLabel>\n <DesignerPropertyControls className={controlsClassName}>\n {children}\n </DesignerPropertyControls>\n </>\n )}\n </div>\n );\n}\n\nfunction DesignerPropertyLabel({ className, children, ...rest }: DesignerPropertyLabelProps) {\n return (\n <label\n className={cn(\n \"caption w-full min-w-0 max-w-full select-none text-muted-foreground\",\n className,\n )}\n {...rest}\n >\n {children}\n </label>\n );\n}\n\nfunction DesignerPropertyControls({ className, children, ...rest }: DesignerPropertyControlsProps) {\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 max-w-full flex-1 items-center gap-2 overflow-visible\",\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nfunction DesignerPropertyGroup({\n title,\n className,\n children,\n ...rest\n}: DesignerPropertyGroupProps) {\n return (\n <div className={cn(\"flex min-w-0 max-w-full flex-col gap-3\", className)} {...rest}>\n {title && (\n <div className=\"caption-xs min-w-0 max-w-full select-none overflow-hidden text-ellipsis uppercase tracking-wider text-muted-foreground\">\n {title}\n </div>\n )}\n {children}\n </div>\n );\n}\n\nexport {\n DesignerPropertyRow,\n DesignerPropertyLabel,\n DesignerPropertyControls,\n DesignerPropertyGroup,\n};\nexport type {\n DesignerPropertyRowProps,\n DesignerPropertyLabelProps,\n DesignerPropertyControlsProps,\n DesignerPropertyGroupProps,\n};\n","import type { ComponentType, CSSProperties, ReactNode } from \"react\";\nimport { cn, Tooltip, TooltipProvider } from \"@hilum/ui\";\n\n/* ============================================================== *\n * Toolbar — outer container *\n * ============================================================== */\n\ninterface DesignerToolbarProps {\n className?: string;\n /** Position. Default: 'floating' (centered, floating above content). */\n variant?: \"floating\" | \"inline\" | \"dock\";\n /**\n * Position floating chrome against the viewport or the nearest positioned\n * workspace ancestor. Default: 'viewport'.\n */\n boundary?: \"viewport\" | \"workspace\";\n /** Center against the full boundary or its configured workspace safe area. */\n center?: \"boundary\" | \"safe-area\";\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction DesignerToolbar({\n className,\n variant = \"floating\",\n boundary = \"viewport\",\n center = \"boundary\",\n style,\n children,\n}: DesignerToolbarProps) {\n const positioned = boundary === \"workspace\" ? \"absolute\" : \"fixed\";\n const safeAreaStyle: CSSProperties | undefined =\n variant === \"floating\" && boundary === \"workspace\" && center === \"safe-area\"\n ? {\n left: \"calc(var(--designer-workspace-inset-left) + (100% - var(--designer-workspace-inset-left) - var(--designer-workspace-inset-right)) / 2)\",\n }\n : undefined;\n\n return (\n <TooltipProvider>\n <div\n role=\"toolbar\"\n className={cn(\n \"flex items-center gap-0.5 rounded-lg bg-card p-1 shadow-natural\",\n \"transition-[opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n variant === \"floating\" && positioned,\n variant === \"floating\" && \"bottom-4 -translate-x-1/2 z-30\",\n variant === \"floating\" && center === \"boundary\" && \"left-1/2\",\n variant === \"dock\" && [\n positioned,\n \"inset-x-3 bottom-[max(0.75rem,env(safe-area-inset-bottom))] z-30\",\n \"overflow-x-auto overscroll-x-contain rounded-xl\",\n ],\n className,\n )}\n style={{ ...safeAreaStyle, ...style }}\n >\n {children}\n </div>\n </TooltipProvider>\n );\n}\n\n/* ============================================================== *\n * ToolbarGroup — visual group of buttons *\n * ============================================================== */\n\ninterface DesignerToolbarGroupProps {\n className?: string;\n children: ReactNode;\n}\n\nfunction DesignerToolbarGroup({ className, children }: DesignerToolbarGroupProps) {\n return <div className={cn(\"flex items-center gap-0.5\", className)}>{children}</div>;\n}\n\n/* ============================================================== *\n * ToolbarSeparator *\n * ============================================================== */\n\ninterface DesignerToolbarSeparatorProps {\n className?: string;\n}\n\nfunction DesignerToolbarSeparator({ className }: DesignerToolbarSeparatorProps) {\n return <div className={cn(\"mx-1 h-5 w-px bg-muted\", className)} role=\"separator\" />;\n}\n\n/* ============================================================== *\n * ToolbarButton — single tool / action *\n * ============================================================== */\n\ninterface DesignerToolbarButtonProps {\n label: string;\n icon?: ComponentType<{ size?: number; className?: string }>;\n onClick?: () => void;\n active?: boolean;\n disabled?: boolean;\n /** Optional keyboard shortcut shown in the tooltip (e.g. 'V', 'Cmd+Z'). */\n shortcut?: string;\n size?: \"default\" | \"touch\";\n className?: string;\n children?: ReactNode;\n}\n\nfunction DesignerToolbarButton({\n label,\n icon: Icon,\n onClick,\n active,\n disabled,\n shortcut,\n size = \"default\",\n className,\n children,\n}: DesignerToolbarButtonProps) {\n return (\n <Tooltip\n content={(\n <span className=\"flex items-center whitespace-nowrap\">\n <span>{label}</span>\n {shortcut && <span className=\"ml-2 text-[11px] text-background/65\">{shortcut}</span>}\n </span>\n )}\n side=\"top\"\n sideOffset={10}\n delayDuration={120}\n className=\"max-w-56 rounded-lg bg-foreground px-2.5 py-1.5 text-[12px] font-medium leading-none tracking-[0.01em] text-background shadow-natural\"\n >\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n aria-label={label}\n aria-pressed={active}\n className={cn(\n \"flex h-9 min-w-9 items-center justify-center gap-1 rounded-md px-2 caption transition-[background-color,color,opacity,scale] active:scale-[0.96]\",\n \"[@media(pointer:coarse)]:h-11 [@media(pointer:coarse)]:min-w-11\",\n size === \"touch\" && \"h-11 min-w-11\",\n active\n ? \"bg-foreground text-background\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {Icon && <Icon size={16} />}\n {children}\n </button>\n </Tooltip>\n );\n}\n\nexport { DesignerToolbar, DesignerToolbarGroup, DesignerToolbarSeparator, DesignerToolbarButton };\nexport type {\n DesignerToolbarProps,\n DesignerToolbarGroupProps,\n DesignerToolbarSeparatorProps,\n DesignerToolbarButtonProps,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Link2, Unlink2 } from \"lucide-react\";\nimport { Button, InputNumber, cn } from \"@hilum/ui\";\n\ntype DesignerControlValue = number | null;\n\ninterface DesignerValueItem<K extends string> {\n key: K;\n label: React.ReactNode;\n ariaLabel?: string;\n min?: number;\n max?: number;\n step?: number;\n precision?: number;\n unit?: string;\n disabled?: boolean;\n}\n\ninterface DesignerValueControlBaseProps<K extends string> {\n label?: React.ReactNode;\n values: Record<K, DesignerControlValue>;\n items: readonly DesignerValueItem<K>[];\n onChange: (key: K, value: number) => void;\n onChangeAll?: (value: number) => void;\n onCommit?: () => void;\n linked?: boolean;\n onLinkedChange?: (linked: boolean) => void;\n unit?: string;\n min?: number;\n max?: number;\n step?: number;\n precision?: number;\n disabled?: boolean;\n readOnly?: boolean;\n mixedLabel?: string;\n hideSteppers?: boolean;\n className?: string;\n labelClassName?: string;\n inputClassName?: string;\n controlsClassName?: string;\n linkButtonClassName?: string;\n linkLabel?: string;\n unlinkLabel?: string;\n}\n\ninterface TwoValueControlProps<K extends string = string>\n extends DesignerValueControlBaseProps<K> {\n items: readonly [DesignerValueItem<K>, DesignerValueItem<K>];\n}\n\ninterface FourValueControlProps<K extends string = string>\n extends DesignerValueControlBaseProps<K> {\n items: readonly [\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n ];\n layout?: \"grid\" | \"single-when-linked\";\n}\n\ntype SpacingSide = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype CornerSide = \"topLeft\" | \"topRight\" | \"bottomLeft\" | \"bottomRight\";\n\ntype SpacingControlProps = Omit<\n FourValueControlProps<SpacingSide>,\n \"items\" | \"values\" | \"onChange\" | \"onChangeAll\"\n> & {\n values: Record<SpacingSide, DesignerControlValue>;\n onChange: (side: SpacingSide, value: number) => void;\n onChangeAll?: (value: number) => void;\n};\n\ntype CornerRadiusControlProps = Omit<\n FourValueControlProps<CornerSide>,\n \"items\" | \"values\" | \"onChange\" | \"onChangeAll\"\n> & {\n values: Record<CornerSide, DesignerControlValue>;\n onChange: (side: CornerSide, value: number) => void;\n onChangeAll?: (value: number) => void;\n};\n\nfunction getSharedValue<K extends string>(\n items: readonly DesignerValueItem<K>[],\n values: Record<K, DesignerControlValue>,\n) {\n const first = values[items[0].key];\n if (first === null) return null;\n return items.every((item) => values[item.key] === first) ? first : null;\n}\n\nfunction DesignerValueField<K extends string>({\n item,\n value,\n unit,\n min,\n max,\n step,\n precision,\n disabled,\n readOnly,\n mixedLabel,\n hideSteppers,\n inputClassName,\n onChange,\n onCommit,\n}: {\n item: DesignerValueItem<K>;\n value: DesignerControlValue;\n unit?: string | undefined;\n min?: number | undefined;\n max?: number | undefined;\n step?: number | undefined;\n precision?: number | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n mixedLabel?: string | undefined;\n hideSteppers?: boolean | undefined;\n inputClassName?: string | undefined;\n onChange: (value: number) => void;\n onCommit?: (() => void) | undefined;\n}) {\n return (\n <div className=\"relative min-w-0\">\n <span className=\"caption-xs pointer-events-none absolute left-2 top-1/2 z-10 -translate-y-1/2 select-none font-semibold uppercase text-muted-foreground\">\n {item.label}\n </span>\n <InputNumber\n value={value}\n onChange={onChange}\n min={item.min ?? min}\n max={item.max ?? max}\n step={item.step ?? step}\n precision={item.precision ?? precision}\n unit={item.unit ?? unit}\n mixedLabel={mixedLabel}\n commitOnChange\n hideSteppers={hideSteppers}\n disabled={disabled || item.disabled}\n readOnly={readOnly}\n aria-label={item.ariaLabel}\n onBlur={onCommit}\n className={cn(\"h-9 w-full bg-muted/60\", inputClassName)}\n inputMode=\"decimal\"\n />\n </div>\n );\n}\n\nfunction DesignerValueControl<K extends string>({\n label,\n values,\n items,\n onChange,\n onChangeAll,\n onCommit,\n linked,\n onLinkedChange,\n unit,\n min = -Infinity,\n max = Infinity,\n step = 1,\n precision = 0,\n disabled = false,\n readOnly = false,\n mixedLabel = \"Mixed\",\n hideSteppers = true,\n className,\n labelClassName,\n inputClassName,\n controlsClassName,\n linkButtonClassName,\n linkLabel = \"Link values\",\n unlinkLabel = \"Unlink values\",\n singleWhenLinked = false,\n}: DesignerValueControlBaseProps<K> & { singleWhenLinked?: boolean }) {\n const hasLinkControl = typeof linked === \"boolean\" && Boolean(onLinkedChange);\n const sharedValue = getSharedValue(items, values);\n const showSingleInput = singleWhenLinked && linked;\n\n const handleChange = (key: K, value: number) => {\n if (linked) {\n if (onChangeAll) {\n onChangeAll(value);\n } else {\n items.forEach((item) => onChange(item.key, value));\n }\n return;\n }\n\n onChange(key, value);\n };\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1.5\", className)}>\n {(label || hasLinkControl) && (\n <div className=\"flex min-w-0 items-center justify-between gap-2\">\n {label && (\n <div className={cn(\"caption select-none text-muted-foreground\", labelClassName)}>\n {label}\n </div>\n )}\n {hasLinkControl && (\n <Button\n type=\"button\"\n variant={linked ? \"secondary\" : \"ghost\"}\n size=\"icon-xs\"\n aria-label={linked ? unlinkLabel : linkLabel}\n title={linked ? unlinkLabel : linkLabel}\n aria-pressed={linked}\n disabled={disabled || readOnly}\n onClick={() => onLinkedChange?.(!linked)}\n className={linkButtonClassName}\n >\n {linked ? <Link2 size={12} /> : <Unlink2 size={12} />}\n </Button>\n )}\n </div>\n )}\n\n {showSingleInput ? (\n <DesignerValueField\n item={{ ...items[0], label: \"All\", ariaLabel: \"All values\" }}\n value={sharedValue}\n unit={unit}\n min={min}\n max={max}\n step={step}\n precision={precision}\n disabled={disabled}\n readOnly={readOnly}\n mixedLabel={mixedLabel}\n hideSteppers={hideSteppers}\n inputClassName={inputClassName}\n onChange={(value) => handleChange(items[0].key, value)}\n onCommit={onCommit}\n />\n ) : (\n <div\n className={cn(\n \"grid min-w-0 gap-2\",\n items.length === 2 ? \"grid-cols-2\" : \"grid-cols-2\",\n controlsClassName,\n )}\n >\n {items.map((item) => (\n <DesignerValueField\n key={item.key}\n item={item}\n value={values[item.key]}\n unit={unit}\n min={min}\n max={max}\n step={step}\n precision={precision}\n disabled={disabled}\n readOnly={readOnly}\n mixedLabel={mixedLabel}\n hideSteppers={hideSteppers}\n inputClassName={inputClassName}\n onChange={(value) => handleChange(item.key, value)}\n onCommit={onCommit}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction TwoValueControl<K extends string = string>(props: TwoValueControlProps<K>) {\n return <DesignerValueControl {...props} />;\n}\n\nfunction FourValueControl<K extends string = string>({\n layout = \"single-when-linked\",\n ...props\n}: FourValueControlProps<K>) {\n return <DesignerValueControl {...props} singleWhenLinked={layout === \"single-when-linked\"} />;\n}\n\nconst spacingItems = [\n { key: \"top\", label: \"T\", ariaLabel: \"Top\" },\n { key: \"right\", label: \"R\", ariaLabel: \"Right\" },\n { key: \"bottom\", label: \"B\", ariaLabel: \"Bottom\" },\n { key: \"left\", label: \"L\", ariaLabel: \"Left\" },\n] as const satisfies readonly [\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n];\n\nconst cornerItems = [\n { key: \"topLeft\", label: \"TL\", ariaLabel: \"Top left radius\" },\n { key: \"topRight\", label: \"TR\", ariaLabel: \"Top right radius\" },\n { key: \"bottomLeft\", label: \"BL\", ariaLabel: \"Bottom left radius\" },\n { key: \"bottomRight\", label: \"BR\", ariaLabel: \"Bottom right radius\" },\n] as const satisfies readonly [\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n];\n\nfunction SpacingControl(props: SpacingControlProps) {\n return <FourValueControl {...props} items={spacingItems} />;\n}\n\nfunction CornerRadiusControl(props: CornerRadiusControlProps) {\n return <FourValueControl {...props} items={cornerItems} min={props.min ?? 0} />;\n}\n\nexport {\n CornerRadiusControl,\n FourValueControl,\n SpacingControl,\n TwoValueControl,\n};\nexport type {\n CornerRadiusControlProps,\n CornerSide,\n DesignerControlValue,\n DesignerValueItem,\n FourValueControlProps,\n SpacingControlProps,\n SpacingSide,\n TwoValueControlProps,\n};\n","import { useCallback, useState } from \"react\";\n\ninterface HistoryState<T> {\n past: T[];\n present: T;\n future: T[];\n}\n\ninterface UseHistoryReturn<T> {\n state: T;\n /**\n * Record a new state. Use when the user makes a logical edit. Pushes the\n * current `state` into `past` and clears `future`. Pass `{ skipHistory: true }`\n * (via a separate setter) to overwrite without pushing — apps that need that\n * can set state directly via a wrapper.\n */\n setState: (next: T | ((prev: T) => T)) => void;\n /** Replace `state` without pushing onto the history stack. */\n replaceState: (next: T | ((prev: T) => T)) => void;\n undo: () => void;\n redo: () => void;\n reset: (next: T) => void;\n canUndo: boolean;\n canRedo: boolean;\n /** Number of past entries (undo depth). */\n pastSize: number;\n /** Number of future entries (redo depth). */\n futureSize: number;\n}\n\n/**\n * Generic, engine-agnostic undo/redo stack.\n *\n * @hilum/designer-canvas wires this with `useHistory<Layer[]>(layers)`.\n * A form-builder app could wire `useHistory<FormSchema>(schema)`.\n */\nexport function useHistory<T>(initial: T): UseHistoryReturn<T> {\n const [history, setHistory] = useState<HistoryState<T>>({\n past: [],\n present: initial,\n future: [],\n });\n\n const setState = useCallback((next: T | ((prev: T) => T)) => {\n setHistory((prev) => {\n const value = typeof next === \"function\" ? (next as (p: T) => T)(prev.present) : next;\n if (Object.is(value, prev.present)) return prev;\n return {\n past: [...prev.past, prev.present],\n present: value,\n future: [],\n };\n });\n }, []);\n\n const replaceState = useCallback((next: T | ((prev: T) => T)) => {\n setHistory((prev) => {\n const value = typeof next === \"function\" ? (next as (p: T) => T)(prev.present) : next;\n return { ...prev, present: value };\n });\n }, []);\n\n const undo = useCallback(() => {\n setHistory((prev) => {\n if (prev.past.length === 0) return prev;\n const past = prev.past.slice(0, -1);\n const previous = prev.past[prev.past.length - 1]!;\n return {\n past,\n present: previous,\n future: [prev.present, ...prev.future],\n };\n });\n }, []);\n\n const redo = useCallback(() => {\n setHistory((prev) => {\n if (prev.future.length === 0) return prev;\n const [next, ...rest] = prev.future;\n return {\n past: [...prev.past, prev.present],\n present: next!,\n future: rest,\n };\n });\n }, []);\n\n const reset = useCallback((next: T) => {\n setHistory({ past: [], present: next, future: [] });\n }, []);\n\n return {\n state: history.present,\n setState,\n replaceState,\n undo,\n redo,\n reset,\n canUndo: history.past.length > 0,\n canRedo: history.future.length > 0,\n pastSize: history.past.length,\n futureSize: history.future.length,\n };\n}\n","import { useEffect } from \"react\";\n\nexport interface KeybindingConfig {\n /** Lower-case key (e.g. 'z', 'arrowup', 'escape', '+', '-'). */\n key: string;\n ctrl?: boolean;\n /** Cmd on macOS. Use both `meta` and `ctrl: true` if you want both. */\n meta?: boolean;\n shift?: boolean;\n alt?: boolean;\n /**\n * Treat both ctrl and meta as the same modifier (for cross-platform\n * shortcuts like Cmd+Z / Ctrl+Z). Default: false. Set to true to match\n * either modifier.\n */\n mod?: boolean;\n action: (event: KeyboardEvent) => void;\n /** Don't run when target is an input / textarea / contenteditable. Default: true. */\n skipInputs?: boolean;\n /** Call event.preventDefault() before action. Default: true. */\n preventDefault?: boolean;\n}\n\ninterface UseKeybindingsOptions {\n /** Skip all bindings entirely. */\n disabled?: boolean;\n /** Element to attach the listener to. Default: window. */\n target?: Window | HTMLElement | null;\n}\n\n/**\n * Generic keyboard shortcut registry. Engine-agnostic — the package doesn't\n * know what an action does. Pass an array of bindings; the hook attaches\n * a single keydown listener and dispatches on match.\n *\n * @hilum/designer-canvas wires its standard editor shortcuts (Cmd+Z, V, T,\n * arrow nudge, etc.) on top of this hook.\n */\nexport function useKeybindings(\n bindings: KeybindingConfig[],\n { disabled, target }: UseKeybindingsOptions = {},\n) {\n useEffect(() => {\n if (disabled) return;\n const node = target ?? (typeof window !== \"undefined\" ? window : null);\n if (!node) return;\n\n const handler = (rawEvent: Event) => {\n const e = rawEvent as KeyboardEvent;\n\n const tgt = e.target as HTMLElement | null;\n const isInput =\n tgt instanceof HTMLInputElement ||\n tgt instanceof HTMLTextAreaElement ||\n tgt instanceof HTMLSelectElement ||\n tgt?.isContentEditable === true;\n\n const key = e.key.toLowerCase();\n\n for (const b of bindings) {\n if (b.key.toLowerCase() !== key) continue;\n if (b.skipInputs !== false && isInput) continue;\n\n const ctrlMatches = b.ctrl ? e.ctrlKey : !e.ctrlKey || b.mod;\n const metaMatches = b.meta ? e.metaKey : !e.metaKey || b.mod;\n const modMatches = b.mod ? e.ctrlKey || e.metaKey : true;\n const shiftMatches = b.shift ? e.shiftKey : !e.shiftKey;\n const altMatches = b.alt ? e.altKey : !e.altKey;\n\n if (!modMatches) continue;\n if (!b.mod && (!ctrlMatches || !metaMatches)) continue;\n if (!shiftMatches || !altMatches) continue;\n\n if (b.preventDefault !== false) e.preventDefault();\n b.action(e);\n return;\n }\n };\n\n (node as Window).addEventListener(\"keydown\", handler);\n return () => (node as Window).removeEventListener(\"keydown\", handler);\n }, [bindings, disabled, target]);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shell/ShellContext.tsx","../src/components/DesignerShell.tsx","../src/components/designer-workspace-insets.ts","../src/components/DesignerWorkspace.tsx","../src/components/DesignerHeader.tsx","../src/components/DesignerSidebar.tsx","../src/components/DesignerPanel.tsx","../src/components/DesignerPanelHeader.tsx","../src/components/DesignerPane.tsx","../src/components/DesignerPropertyRow.tsx","../src/components/DesignerToolbar.tsx","../src/components/DesignerValueControls.tsx","../src/hooks/useHistory.ts","../src/hooks/useKeybindings.ts"],"names":["jsx","cn","jsxs","DensityProvider","useState","createContext","useContext","TooltipProvider","Tooltip"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext, useMemo, useState } from \"react\";\nimport type { Dispatch, ReactNode, SetStateAction } from \"react\";\n\n/**\n * The minimal contract a designer shell needs from the engine beneath it.\n *\n * The chrome (toolbar, panel, pane, sidebar) reads from this context.\n * It does NOT know what is being edited — selection IDs are opaque strings\n * (layer IDs, field IDs, node IDs — whatever the engine uses), and active\n * tool is an open string the app defines (`select`, `hand`, `text`, …).\n *\n * @hilum/designer-canvas wires this up for canvas apps. A form-builder app\n * could wire its own engine to ShellContext with the same primitives.\n */\nexport interface ShellContextValue {\n /** IDs of currently-selected items. Engine-defined meaning. */\n selectedIds: string[];\n setSelectedIds: Dispatch<SetStateAction<string[]>>;\n\n /** Active tool. App-defined enum (e.g. 'select' | 'hand' | 'text'). */\n activeTool: string;\n setActiveTool: Dispatch<SetStateAction<string>>;\n\n /** When true, mutating actions should no-op. Used for previews. */\n readOnly: boolean;\n\n /**\n * Optional resolver: given a `selectedId`, return its engine-defined \"kind\"\n * (e.g. 'text', 'image'). DesignerPane.showFor uses this to decide whether\n * to render. Apps that don't have typed selections can leave this undefined.\n */\n resolveKind?: (id: string) => string | undefined;\n}\n\nconst noop = () => {};\n\nconst DEFAULT: ShellContextValue = {\n selectedIds: [],\n setSelectedIds: noop as Dispatch<SetStateAction<string[]>>,\n activeTool: \"select\",\n setActiveTool: noop as Dispatch<SetStateAction<string>>,\n readOnly: false,\n};\n\nconst ShellContext = createContext<ShellContextValue>(DEFAULT);\n\nexport function useShellContext(): ShellContextValue {\n return useContext(ShellContext);\n}\n\ninterface ShellProviderProps {\n /** Initial selected IDs. Default: []. */\n initialSelectedIds?: string[];\n /** Initial active tool. Default: 'select'. */\n initialTool?: string;\n /** Read-only flag. */\n readOnly?: boolean;\n /** Kind resolver — see ShellContextValue.resolveKind. */\n resolveKind?: (id: string) => string | undefined;\n /** Controlled override — pass a value to lift state out of the provider. */\n value?: Partial<ShellContextValue>;\n children: ReactNode;\n}\n\nexport function ShellProvider({\n initialSelectedIds = [],\n initialTool = \"select\",\n readOnly = false,\n resolveKind,\n value: controlled,\n children,\n}: ShellProviderProps) {\n const [selectedIds, setSelectedIds] = useState<string[]>(initialSelectedIds);\n const [activeTool, setActiveTool] = useState<string>(initialTool);\n\n const resolvedKind = controlled?.resolveKind ?? resolveKind;\n\n const value = useMemo<ShellContextValue>(\n () => ({\n selectedIds: controlled?.selectedIds ?? selectedIds,\n setSelectedIds: controlled?.setSelectedIds ?? setSelectedIds,\n activeTool: controlled?.activeTool ?? activeTool,\n setActiveTool: controlled?.setActiveTool ?? setActiveTool,\n readOnly: controlled?.readOnly ?? readOnly,\n ...(resolvedKind !== undefined && { resolveKind: resolvedKind }),\n }),\n [selectedIds, activeTool, readOnly, resolvedKind, controlled],\n );\n\n return <ShellContext.Provider value={value}>{children}</ShellContext.Provider>;\n}\n","import type { ReactNode } from \"react\";\nimport { cn, DensityProvider, type Density } from \"@hilum/ui\";\n\ninterface DesignerShellProps {\n className?: string;\n /**\n * Control density for everything inside the shell. Editor chrome defaults\n * to `\"compact\"` (24px controls, 28px rows, 12px text); pass `\"default\"` to\n * keep standard Hilum sizing.\n */\n density?: Density;\n children: ReactNode;\n}\n\n/**\n * Root layout for an editor app — full viewport, themed surface.\n * Place a <DesignerHeader>, <DesignerSidebar>, <DesignerPanel>, and the\n * canvas content as children.\n */\nfunction DesignerShell({ className, density = \"compact\", children }: DesignerShellProps) {\n return (\n <DensityProvider density={density} wrap={false}>\n <div\n data-designer-shell\n data-density={density}\n className={cn(\n \"flex flex-col h-screen w-screen overflow-hidden bg-canvas text-foreground\",\n className,\n )}\n >\n {children}\n </div>\n </DensityProvider>\n );\n}\n\nexport { DesignerShell };\nexport type { DesignerShellProps };\n","export type DesignerWorkspaceInsetValue = number | string;\n\nexport interface DesignerWorkspaceInsets {\n top: DesignerWorkspaceInsetValue;\n right: DesignerWorkspaceInsetValue;\n bottom: DesignerWorkspaceInsetValue;\n left: DesignerWorkspaceInsetValue;\n}\n\nexport type DesignerWorkspaceInsetsInput =\n | DesignerWorkspaceInsetValue\n | Partial<DesignerWorkspaceInsets>;\n\nfunction toCssLength(value: DesignerWorkspaceInsetValue): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\nexport function resolveDesignerWorkspaceInsets(\n input: DesignerWorkspaceInsetsInput | undefined,\n fallback: DesignerWorkspaceInsetValue = 0,\n): Record<keyof DesignerWorkspaceInsets, string> {\n const fallbackValue = toCssLength(fallback);\n\n if (typeof input === \"number\" || typeof input === \"string\") {\n const value = toCssLength(input);\n return { top: value, right: value, bottom: value, left: value };\n }\n\n return {\n top: input?.top === undefined ? fallbackValue : toCssLength(input.top),\n right: input?.right === undefined ? fallbackValue : toCssLength(input.right),\n bottom: input?.bottom === undefined ? fallbackValue : toCssLength(input.bottom),\n left: input?.left === undefined ? fallbackValue : toCssLength(input.left),\n };\n}\n\nexport function getDesignerFloatingMaxHeight(insets: {\n top: string;\n bottom: string;\n}): string {\n return `calc(100% - ${insets.top} - ${insets.bottom})`;\n}\n","import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\nimport {\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n type DesignerWorkspaceInsetValue,\n} from \"./designer-workspace-insets\";\n\ninterface DesignerWorkspaceProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * Insets that describe the unobscured canvas area between floating chrome.\n * Numbers are interpreted as pixels; CSS lengths and calc() expressions are\n * accepted for responsive shells.\n */\n safeInsets?: DesignerWorkspaceInsetsInput;\n children: ReactNode;\n}\n\ninterface DesignerWorkspaceViewportProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n children: ReactNode;\n}\n\ntype WorkspaceStyle = CSSProperties & {\n \"--designer-workspace-inset-top\": string;\n \"--designer-workspace-inset-right\": string;\n \"--designer-workspace-inset-bottom\": string;\n \"--designer-workspace-inset-left\": string;\n};\n\n/**\n * Positioning boundary for a canvas editor. Floating rails, panels, and\n * toolbars are layered over this surface while DesignerWorkspaceViewport uses\n * the configured safe insets to keep document content unobscured.\n */\nfunction DesignerWorkspace({\n safeInsets,\n className,\n style,\n children,\n ...props\n}: DesignerWorkspaceProps) {\n const insets = resolveDesignerWorkspaceInsets(safeInsets);\n const workspaceStyle = {\n \"--designer-workspace-inset-top\": insets.top,\n \"--designer-workspace-inset-right\": insets.right,\n \"--designer-workspace-inset-bottom\": insets.bottom,\n \"--designer-workspace-inset-left\": insets.left,\n ...style,\n } as WorkspaceStyle;\n\n return (\n <div\n data-designer-workspace\n className={cn(\n \"relative isolate flex min-h-0 min-w-0 flex-1 overflow-hidden bg-canvas\",\n className,\n )}\n style={workspaceStyle}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Safe, canvas-sized region within DesignerWorkspace. Its bounds are derived\n * from the workspace's safeInsets so fit/center calculations use the visible\n * area between floating editor chrome.\n */\nfunction DesignerWorkspaceViewport({\n className,\n style,\n children,\n ...props\n}: DesignerWorkspaceViewportProps) {\n return (\n <div\n data-designer-workspace-viewport\n className={cn(\"absolute z-0 flex min-h-0 min-w-0 overflow-hidden\", className)}\n style={{\n top: \"var(--designer-workspace-inset-top)\",\n right: \"var(--designer-workspace-inset-right)\",\n bottom: \"var(--designer-workspace-inset-bottom)\",\n left: \"var(--designer-workspace-inset-left)\",\n ...style,\n }}\n {...props}\n >\n {children}\n </div>\n );\n}\n\nexport { DesignerWorkspace, DesignerWorkspaceViewport };\nexport type {\n DesignerWorkspaceProps,\n DesignerWorkspaceViewportProps,\n DesignerWorkspaceInsets,\n DesignerWorkspaceInsetsInput,\n DesignerWorkspaceInsetValue,\n};\n","import type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\n\ninterface DesignerHeaderProps extends Omit<ComponentPropsWithoutRef<\"header\">, \"children\"> {\n /** Left-aligned content — file name, breadcrumbs, project switcher. */\n left?: ReactNode;\n /** Center content — typically the active document title. */\n center?: ReactNode;\n /** Right-aligned content — share, export, presence, account. */\n right?: ReactNode;\n className?: string;\n children?: ReactNode;\n}\n\n/**\n * Top bar of an editor app. Slot-driven — the chrome doesn't know what\n * goes in each region. Use <DesignerHeader left={...} center={...} right={...} />.\n */\nfunction DesignerHeader({\n left,\n center,\n right,\n className,\n children,\n ...props\n}: DesignerHeaderProps) {\n return (\n <header\n data-designer-header\n className={cn(\n \"grid h-12 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 bg-card px-3\",\n className,\n )}\n {...props}\n >\n <div\n data-designer-header-slot=\"left\"\n className=\"flex min-w-0 items-center gap-2 justify-self-start\"\n >\n {left}\n </div>\n <div\n data-designer-header-slot=\"center\"\n className=\"flex min-w-0 items-center gap-2 justify-self-center\"\n >\n {center}\n </div>\n <div\n data-designer-header-slot=\"right\"\n className=\"flex min-w-0 items-center gap-2 justify-self-end\"\n >\n {right}\n </div>\n {children}\n </header>\n );\n}\n\nexport { DesignerHeader };\nexport type { DesignerHeaderProps };\n","import type { ComponentType, CSSProperties, ReactNode } from \"react\";\nimport { cn, Tooltip, TooltipProvider } from \"@hilum/ui\";\nimport {\n getDesignerFloatingMaxHeight,\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n} from \"./designer-workspace-insets\";\n\ninterface SidebarItem {\n id: string;\n label: string;\n icon: ComponentType<{ size?: number; className?: string }>;\n onClick?: () => void;\n /** Caller-computed active flag. */\n active?: boolean;\n disabled?: boolean;\n badge?: ReactNode;\n}\n\ninterface DesignerSidebarProps {\n /** Top group of icon buttons. */\n items: SidebarItem[];\n /** Optional bottom group (settings, help, account). */\n bottomItems?: SidebarItem[];\n /** Layout variant. `rail` preserves the inline desktop vertical rail. */\n variant?: \"rail\" | \"floating\" | \"bottom\";\n side?: \"left\" | \"right\";\n /** Insets used to position a floating rail within DesignerWorkspace. Default: 16px. */\n floatingInset?: DesignerWorkspaceInsetsInput;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\n/**\n * Vertical icon rail used as the primary tool / navigation column in an\n * editor. Driven by an `items` array — no engine coupling. Each item gets\n * a tooltip showing its label.\n */\nfunction DesignerSidebar({\n items,\n bottomItems,\n variant = \"rail\",\n side = \"left\",\n floatingInset,\n className,\n style,\n children,\n}: DesignerSidebarProps) {\n if (variant === \"bottom\") {\n const allItems = [...items, ...(bottomItems ?? [])];\n\n return (\n <nav\n aria-label=\"Editor tools\"\n className={cn(\n \"fixed inset-x-3 bottom-[max(0.75rem,env(safe-area-inset-bottom))] z-40\",\n \"rounded-xl border border-border bg-card p-1 shadow-surface-3\",\n className,\n )}\n style={style}\n >\n <TooltipProvider>\n <div className=\"flex min-w-0 items-center gap-1 overflow-x-auto overscroll-x-contain\">\n {allItems.map((item) => (\n <SidebarButton key={item.id} item={item} tooltipSide=\"top\" touchTarget />\n ))}\n </div>\n {children}\n </TooltipProvider>\n </nav>\n );\n }\n\n const content = (\n <TooltipProvider>\n <div\n data-designer-sidebar-items\n className={cn(\n \"flex min-h-0 flex-col items-center gap-0.5 overflow-y-auto overscroll-contain p-1.5\",\n variant === \"floating\" ? \"flex-initial\" : \"flex-1\",\n )}\n >\n {items.map((item) => (\n <SidebarButton\n key={item.id}\n item={item}\n tooltipSide={side === \"left\" ? \"right\" : \"left\"}\n />\n ))}\n </div>\n\n {children}\n\n {bottomItems && bottomItems.length > 0 && (\n <div className=\"flex shrink-0 flex-col items-center gap-0.5 p-1.5\">\n {bottomItems.map((item) => (\n <SidebarButton\n key={item.id}\n item={item}\n tooltipSide={side === \"left\" ? \"right\" : \"left\"}\n />\n ))}\n </div>\n )}\n </TooltipProvider>\n );\n\n if (variant === \"floating\") {\n const insets = resolveDesignerWorkspaceInsets(floatingInset, 16);\n\n return (\n <nav\n aria-label=\"Editor tools\"\n data-side={side}\n data-variant={variant}\n className={cn(\n \"absolute z-30 flex w-12 flex-col overflow-hidden rounded-lg bg-card shadow-surface-3 compact:w-11\",\n \"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n className,\n )}\n style={{\n top: insets.top,\n [side]: insets[side],\n height: \"fit-content\",\n maxHeight: getDesignerFloatingMaxHeight(insets),\n ...style,\n }}\n >\n {content}\n </nav>\n );\n }\n\n return (\n <aside\n data-side={side}\n data-variant={variant}\n className={cn(\n \"flex flex-col w-12 bg-card shrink-0\",\n side === \"left\" ? \"border-r\" : \"border-l\",\n \"border-border\",\n className,\n )}\n style={style}\n >\n {content}\n </aside>\n );\n}\n\nfunction SidebarButton({\n item,\n tooltipSide,\n touchTarget = false,\n}: {\n item: SidebarItem;\n tooltipSide: \"top\" | \"right\" | \"left\";\n touchTarget?: boolean;\n}) {\n const Icon = item.icon;\n return (\n <Tooltip\n content={<span className=\"block whitespace-nowrap\">{item.label}</span>}\n side={tooltipSide}\n sideOffset={10}\n delayDuration={120}\n className=\"max-w-56 rounded-lg bg-foreground px-2.5 py-1.5 text-[12px] font-medium leading-none tracking-[0.01em] text-background shadow-natural\"\n >\n <button\n type=\"button\"\n onClick={item.onClick}\n disabled={item.disabled}\n aria-label={item.label}\n aria-pressed={item.active}\n className={cn(\n \"relative flex size-9 items-center justify-center rounded-md transition-[background-color,color,opacity,scale] active:scale-[0.96]\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"compact:size-8 compact:rounded-[6px]\",\n \"[@media(pointer:coarse)]:size-11\",\n touchTarget && \"size-11 shrink-0\",\n item.active\n ? \"bg-foreground text-background\"\n : \"text-muted-foreground hover:bg-hover hover:text-foreground active:bg-active\",\n item.disabled && \"opacity-50 cursor-not-allowed\",\n )}\n >\n <Icon size={touchTarget ? 18 : 16} />\n {item.badge != null && (\n <span className=\"absolute -top-0.5 -right-0.5 caption-xs\">{item.badge}</span>\n )}\n </button>\n </Tooltip>\n );\n}\n\nexport { DesignerSidebar };\nexport type { DesignerSidebarProps, SidebarItem };\n","import type { CSSProperties, ReactNode } from \"react\";\nimport {\n cn,\n DensityProvider,\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n type Density,\n} from \"@hilum/ui\";\nimport {\n getDesignerFloatingMaxHeight,\n resolveDesignerWorkspaceInsets,\n type DesignerWorkspaceInsetsInput,\n} from \"./designer-workspace-insets\";\n\ninterface DesignerPanelProps {\n side: \"left\" | \"right\";\n /** Presentation mode. `inline` preserves the desktop side-panel behavior. */\n variant?: \"inline\" | \"floating\" | \"sheet\";\n /** Width in pixels. Default: 240. */\n width?: number;\n /** Add a separator border on the inner edge. Default: true. */\n bordered?: boolean;\n /** Insets used to position a floating panel within DesignerWorkspace. Default: 16px. */\n floatingInset?: DesignerWorkspaceInsetsInput;\n /** Controlled open state when `variant=\"sheet\"`. */\n open?: boolean;\n /** Controlled open-state handler when `variant=\"sheet\"`. */\n onOpenChange?: (open: boolean) => void;\n /** Accessible sheet title when `variant=\"sheet\"`. */\n sheetTitle?: ReactNode;\n /** Optional sheet description. */\n sheetDescription?: ReactNode;\n /** Sheet edge. Defaults to `bottom` for mobile editor panels. */\n sheetSide?: \"left\" | \"right\" | \"top\" | \"bottom\";\n sheetClassName?: string;\n /**\n * Control density inside the panel. Inspector / layer panels default to\n * `\"compact\"` editor sizing; pass `\"default\"` for standard Hilum sizing.\n */\n density?: Density;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\n/**\n * Left or right side panel of an editor — typically holds layer lists,\n * inspector / properties, history, comments, etc. Static-width for v1.\n * (Resize handles arrive in a later iteration if needed.)\n */\nfunction DesignerPanel({\n side,\n variant = \"inline\",\n width = 240,\n bordered = true,\n floatingInset,\n open,\n onOpenChange,\n sheetTitle,\n sheetDescription,\n sheetSide = \"bottom\",\n sheetClassName,\n density = \"compact\",\n className,\n style,\n children,\n}: DesignerPanelProps) {\n if (variant === \"sheet\") {\n const sheetProps = {\n ...(open !== undefined ? { open } : {}),\n ...(onOpenChange ? { onOpenChange } : {}),\n };\n const resolvedSheetDescription = sheetDescription ?? \"Editor panel controls\";\n\n return (\n <DensityProvider density={density} wrap={false}>\n <Sheet {...sheetProps}>\n <SheetContent\n data-density={density}\n side={sheetSide}\n className={cn(\n \"flex max-h-[min(86svh,44rem)] flex-col overflow-hidden p-0\",\n sheetSide === \"bottom\" && \"rounded-t-2xl\",\n sheetClassName,\n )}\n >\n <SheetHeader\n className={cn(sheetTitle ? \"mb-0 border-b border-border px-4 py-3\" : \"sr-only\")}\n >\n <SheetTitle>{sheetTitle ?? `${side} panel`}</SheetTitle>\n <SheetDescription className={sheetDescription ? undefined : \"sr-only\"}>\n {resolvedSheetDescription}\n </SheetDescription>\n </SheetHeader>\n <div className=\"flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto\">\n {children}\n </div>\n </SheetContent>\n </Sheet>\n </DensityProvider>\n );\n }\n\n const floatingInsets = resolveDesignerWorkspaceInsets(floatingInset, 16);\n const floatingStyle: CSSProperties | undefined =\n variant === \"floating\"\n ? {\n top: floatingInsets.top,\n [side]: floatingInsets[side],\n width,\n height: \"fit-content\",\n maxHeight: getDesignerFloatingMaxHeight(floatingInsets),\n maxWidth: \"calc(100% - 2rem)\",\n ...style,\n }\n : { width, maxWidth: \"100%\", ...style };\n\n return (\n <DensityProvider density={density} wrap={false}>\n <aside\n data-side={side}\n data-variant={variant}\n data-density={density}\n className={cn(\n \"flex min-w-0 max-w-full shrink-0 flex-col overflow-hidden bg-card text-foreground\",\n variant === \"inline\" && bordered && (side === \"left\" ? \"border-r\" : \"border-l\"),\n variant === \"inline\" && bordered && \"border-border\",\n variant === \"floating\" && [\n \"absolute z-20 rounded-lg shadow-surface-3\",\n \"[interpolate-size:allow-keywords] transition-[height,max-height,opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n ],\n className,\n )}\n style={floatingStyle}\n >\n <div className=\"flex min-w-0 flex-1 flex-col overflow-x-hidden overflow-y-auto\">\n {children}\n </div>\n </aside>\n </DensityProvider>\n );\n}\n\nexport { DesignerPanel };\nexport type { DesignerPanelProps };\n","import type { ReactNode } from \"react\";\nimport { cn, TabsSubtle, TabsSubtleItem, type IconComponent } from \"@hilum/ui\";\n\n/* ============================================================== *\n * DesignerPanelHeader — title row + optional tabs/search row *\n * ============================================================== */\n\ninterface DesignerPanelHeaderProps {\n /** Panel title (\"Sections\", \"Theme settings\"). */\n title?: ReactNode;\n /** Muted line under the title (template name, selection summary). */\n description?: ReactNode;\n /** Trailing icon buttons (DesignerToolbarButton / Button size=\"icon-sm\"). */\n actions?: ReactNode;\n /** Second row — DesignerPanelTabs, a SearchInput, or filters. */\n children?: ReactNode;\n /** Stick to the top of the panel's scroll area. Default: true. */\n sticky?: boolean;\n className?: string;\n}\n\n/**\n * Header for a DesignerPanel: a title/actions row plus an optional second row\n * for tabs or search. Replaces hand-built panel headers with arbitrary sizes.\n */\nfunction DesignerPanelHeader({\n title,\n description,\n actions,\n children,\n sticky = true,\n className,\n}: DesignerPanelHeaderProps) {\n return (\n <div\n data-slot=\"designer-panel-header\"\n className={cn(\n \"flex min-w-0 shrink-0 flex-col gap-2 border-b border-border bg-card px-3 py-2.5\",\n sticky && \"sticky top-0 z-10\",\n className,\n )}\n >\n {(title || actions) && (\n <div className=\"flex min-w-0 items-center gap-2\">\n <div className=\"min-w-0 flex-1\">\n {title && (\n <div className=\"body-sm truncate font-semibold text-foreground\">{title}</div>\n )}\n {description && (\n <div className=\"caption-sm truncate text-muted-foreground\">{description}</div>\n )}\n </div>\n {actions && <div className=\"flex shrink-0 items-center gap-1\">{actions}</div>}\n </div>\n )}\n {children}\n </div>\n );\n}\n\n/* ============================================================== *\n * DesignerPanelTabs — value-based, overflow-safe panel tabs *\n * ============================================================== */\n\ninterface DesignerPanelTab<V extends string = string> {\n value: V;\n label: string;\n icon?: IconComponent;\n disabled?: boolean;\n}\n\ninterface DesignerPanelTabsProps<V extends string = string> {\n tabs: ReadonlyArray<DesignerPanelTab<V>>;\n value: V;\n onValueChange: (value: V) => void;\n /**\n * Show only the active tab's label (icons for the rest) — for narrow\n * panels. Requires icons. Default: false.\n */\n iconsOnly?: boolean;\n /** Stretch tabs to share the full width when they fit. Default: false. */\n fill?: boolean;\n /** Accessible name for the tablist. */\n \"aria-label\"?: string;\n idPrefix?: string;\n className?: string;\n}\n\n/**\n * Panel tab strip that never clips: it scrolls horizontally with edge fades\n * and keeps the active tab in view. Value-based wrapper over TabsSubtle —\n * render the matching content yourself (`{value === \"sections\" && …}`).\n */\nfunction DesignerPanelTabs<V extends string = string>({\n tabs,\n value,\n onValueChange,\n iconsOnly = false,\n fill = false,\n \"aria-label\": ariaLabel,\n idPrefix,\n className,\n}: DesignerPanelTabsProps<V>) {\n const selectedIndex = Math.max(\n 0,\n tabs.findIndex((tab) => tab.value === value),\n );\n return (\n <TabsSubtle\n selectedIndex={selectedIndex}\n onSelect={(index) => {\n const tab = tabs[index];\n if (tab && !tab.disabled) onValueChange(tab.value);\n }}\n activeLabel={iconsOnly}\n {...(idPrefix ? { idPrefix } : {})}\n {...(ariaLabel ? { \"aria-label\": ariaLabel } : {})}\n className={cn(\"w-full\", className)}\n >\n {tabs.map((tab, index) => (\n <TabsSubtleItem\n key={tab.value}\n index={index}\n label={tab.label}\n {...(tab.icon ? { icon: tab.icon } : {})}\n {...(tab.disabled ? { \"aria-disabled\": true } : {})}\n className={cn(\"justify-center px-2.5 py-1.5\", fill && \"flex-1\")}\n />\n ))}\n </TabsSubtle>\n );\n}\n\nexport { DesignerPanelHeader, DesignerPanelTabs };\nexport type { DesignerPanelHeaderProps, DesignerPanelTabsProps, DesignerPanelTab };\n","import { useState, type ReactNode } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"@hilum/ui\";\nimport { useShellContext } from \"../shell/ShellContext\";\n\ninterface DesignerPaneProps {\n /**\n * Predicate or list of allowed kinds. The pane renders only when matched.\n *\n * - `string[]`: render when at least one selected ID resolves to one of\n * these kinds (requires `ShellContext.resolveKind`).\n * - `(selectedIds: string[]) => boolean`: full predicate.\n * - omitted: always render.\n */\n showFor?: string[] | ((selectedIds: string[]) => boolean);\n collapsible?: boolean;\n defaultOpen?: boolean;\n className?: string;\n children: ReactNode;\n}\n\ninterface DesignerPaneTitleProps {\n className?: string;\n children: ReactNode;\n /** Right-aligned action / control. */\n action?: ReactNode;\n}\n\ninterface DesignerPaneContentProps {\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Collapsible inspector section. Use inside a <DesignerPanel>.\n *\n * <DesignerPane showFor={[\"text\"]} collapsible>\n * <DesignerPaneTitle>Typography</DesignerPaneTitle>\n * <DesignerPaneContent>...</DesignerPaneContent>\n * </DesignerPane>\n */\nfunction DesignerPane({\n showFor,\n collapsible = false,\n defaultOpen = true,\n className,\n children,\n}: DesignerPaneProps) {\n const { selectedIds, resolveKind } = useShellContext();\n const [open, setOpen] = useState(defaultOpen);\n\n // Visibility check.\n let visible = true;\n if (typeof showFor === \"function\") {\n visible = showFor(selectedIds);\n } else if (Array.isArray(showFor)) {\n if (!resolveKind) {\n // No resolver: best effort — show only if any IDs are selected.\n visible = selectedIds.length > 0;\n } else {\n visible = selectedIds.some((id) => {\n const kind = resolveKind(id);\n return kind != null && showFor.includes(kind);\n });\n }\n }\n if (!visible) return null;\n\n return (\n <PaneContext.Provider value={{ open, toggle: () => setOpen((v) => !v), collapsible }}>\n <section\n className={cn(\n \"flex min-w-0 max-w-full flex-col overflow-x-hidden border-b border-border last:border-b-0\",\n className,\n )}\n >\n {children}\n </section>\n </PaneContext.Provider>\n );\n}\n\nfunction DesignerPaneTitle({ className, children, action }: DesignerPaneTitleProps) {\n const { open, toggle, collapsible } = usePaneContext();\n\n const Tag = collapsible ? \"button\" : \"div\";\n return (\n <Tag\n type={collapsible ? \"button\" : undefined}\n onClick={collapsible ? toggle : undefined}\n className={cn(\n \"flex min-h-10 w-full items-center justify-between gap-2 px-3 py-2 text-left\",\n \"caption-xs uppercase tracking-wider font-semibold text-muted-foreground\",\n \"compact:min-h-8 compact:py-1.5 compact:text-[10px]\",\n collapsible &&\n \"hover:text-foreground transition-colors outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\",\n className,\n )}\n >\n <span className=\"flex items-center gap-1.5\">\n {collapsible && (\n <ChevronDown\n size={12}\n className={cn(\"transition-transform duration-150\", !open && \"-rotate-90\")}\n />\n )}\n {children}\n </span>\n {action && <span className=\"ml-auto\">{action}</span>}\n </Tag>\n );\n}\n\nfunction DesignerPaneContent({ className, children }: DesignerPaneContentProps) {\n const { open } = usePaneContext();\n if (!open) return null;\n return (\n <div\n className={cn(\n \"flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden px-3 pb-3 compact:gap-1.5\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\n// --- internal pane context (so title and content stay in sync) ---\n\nimport { createContext, useContext } from \"react\";\n\ninterface PaneCtx {\n open: boolean;\n toggle: () => void;\n collapsible: boolean;\n}\nconst PaneContext = createContext<PaneCtx>({ open: true, toggle: () => {}, collapsible: false });\nfunction usePaneContext() {\n return useContext(PaneContext);\n}\n\nexport { DesignerPane, DesignerPaneTitle, DesignerPaneContent };\nexport type { DesignerPaneProps, DesignerPaneTitleProps, DesignerPaneContentProps };\n","import type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"@hilum/ui\";\n\ninterface DesignerPropertyRowProps extends ComponentPropsWithoutRef<\"div\"> {\n /** Optional label for direct row usage. Compound usage can use DesignerPropertyLabel. */\n label?: ReactNode;\n /** htmlFor forwarded to the generated label when label is provided. */\n labelFor?: string;\n /** Class name for the generated controls container when label is provided. */\n controlsClassName?: string;\n /**\n * `stacked` (default) puts the label above the controls; `inline` puts it\n * in a fixed-width column to the left — the dense Figma-style inspector row.\n */\n layout?: \"stacked\" | \"inline\";\n /** Label column width when `layout=\"inline\"`. Default: 64px. */\n labelWidth?: number | string;\n children: ReactNode;\n}\n\ninterface DesignerPropertyLabelProps extends ComponentPropsWithoutRef<\"label\"> {\n children: ReactNode;\n}\n\ninterface DesignerPropertyControlsProps extends ComponentPropsWithoutRef<\"div\"> {\n children: ReactNode;\n}\n\ninterface DesignerPropertyGroupProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"title\"> {\n title?: ReactNode;\n children: ReactNode;\n}\n\nfunction DesignerPropertyRow({\n label,\n labelFor,\n controlsClassName,\n layout = \"stacked\",\n labelWidth = 64,\n className,\n children,\n ...rest\n}: DesignerPropertyRowProps) {\n const inline = layout === \"inline\";\n return (\n <div\n data-layout={layout}\n className={cn(\n \"flex w-full min-w-0 max-w-full py-1.5 compact:py-0.5\",\n inline\n ? \"flex-row items-center gap-2 compact:min-h-7\"\n : \"flex-col items-stretch gap-1.5 compact:gap-1\",\n className,\n )}\n {...rest}\n >\n {label === undefined ? (\n children\n ) : (\n <>\n <DesignerPropertyLabel\n htmlFor={labelFor}\n className={inline ? \"w-auto shrink-0 truncate\" : undefined}\n style={\n inline\n ? { width: typeof labelWidth === \"number\" ? `${labelWidth}px` : labelWidth }\n : undefined\n }\n >\n {label}\n </DesignerPropertyLabel>\n <DesignerPropertyControls className={controlsClassName}>\n {children}\n </DesignerPropertyControls>\n </>\n )}\n </div>\n );\n}\n\nfunction DesignerPropertyLabel({ className, children, ...rest }: DesignerPropertyLabelProps) {\n return (\n <label\n className={cn(\n \"caption w-full min-w-0 max-w-full select-none text-muted-foreground compact:text-[11px] compact:leading-4\",\n className,\n )}\n {...rest}\n >\n {children}\n </label>\n );\n}\n\nfunction DesignerPropertyControls({ className, children, ...rest }: DesignerPropertyControlsProps) {\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 max-w-full flex-1 items-center gap-2 overflow-visible\",\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nfunction DesignerPropertyGroup({\n title,\n className,\n children,\n ...rest\n}: DesignerPropertyGroupProps) {\n return (\n <div className={cn(\"flex min-w-0 max-w-full flex-col gap-3 compact:gap-2\", className)} {...rest}>\n {title && (\n <div className=\"caption-xs min-w-0 max-w-full select-none overflow-hidden text-ellipsis uppercase tracking-wider text-muted-foreground\">\n {title}\n </div>\n )}\n {children}\n </div>\n );\n}\n\nexport {\n DesignerPropertyRow,\n DesignerPropertyLabel,\n DesignerPropertyControls,\n DesignerPropertyGroup,\n};\nexport type {\n DesignerPropertyRowProps,\n DesignerPropertyLabelProps,\n DesignerPropertyControlsProps,\n DesignerPropertyGroupProps,\n};\n","import type { ComponentType, CSSProperties, ReactNode } from \"react\";\nimport { cn, Tooltip, TooltipProvider } from \"@hilum/ui\";\n\n/* ============================================================== *\n * Toolbar — outer container *\n * ============================================================== */\n\ninterface DesignerToolbarProps {\n className?: string;\n /** Position. Default: 'floating' (centered, floating above content). */\n variant?: \"floating\" | \"inline\" | \"dock\";\n /**\n * Position floating chrome against the viewport or the nearest positioned\n * workspace ancestor. Default: 'viewport'.\n */\n boundary?: \"viewport\" | \"workspace\";\n /** Center against the full boundary or its configured workspace safe area. */\n center?: \"boundary\" | \"safe-area\";\n style?: CSSProperties;\n children: ReactNode;\n}\n\nfunction DesignerToolbar({\n className,\n variant = \"floating\",\n boundary = \"viewport\",\n center = \"boundary\",\n style,\n children,\n}: DesignerToolbarProps) {\n const positioned = boundary === \"workspace\" ? \"absolute\" : \"fixed\";\n const safeAreaStyle: CSSProperties | undefined =\n variant === \"floating\" && boundary === \"workspace\" && center === \"safe-area\"\n ? {\n left: \"calc(var(--designer-workspace-inset-left) + (100% - var(--designer-workspace-inset-left) - var(--designer-workspace-inset-right)) / 2)\",\n }\n : undefined;\n\n return (\n <TooltipProvider>\n <div\n role=\"toolbar\"\n className={cn(\n \"flex items-center gap-0.5 rounded-lg bg-card p-1 shadow-surface-3\",\n \"transition-[opacity,transform,box-shadow] duration-200 ease-out motion-reduce:transition-none\",\n variant === \"floating\" && positioned,\n variant === \"floating\" && \"bottom-4 -translate-x-1/2 z-30\",\n variant === \"floating\" && center === \"boundary\" && \"left-1/2\",\n variant === \"dock\" && [\n positioned,\n \"inset-x-3 bottom-[max(0.75rem,env(safe-area-inset-bottom))] z-30\",\n \"overflow-x-auto overscroll-x-contain rounded-xl\",\n ],\n className,\n )}\n style={{ ...safeAreaStyle, ...style }}\n >\n {children}\n </div>\n </TooltipProvider>\n );\n}\n\n/* ============================================================== *\n * ToolbarGroup — visual group of buttons *\n * ============================================================== */\n\ninterface DesignerToolbarGroupProps {\n className?: string;\n children: ReactNode;\n}\n\nfunction DesignerToolbarGroup({ className, children }: DesignerToolbarGroupProps) {\n return <div className={cn(\"flex items-center gap-0.5\", className)}>{children}</div>;\n}\n\n/* ============================================================== *\n * ToolbarSeparator *\n * ============================================================== */\n\ninterface DesignerToolbarSeparatorProps {\n className?: string;\n}\n\nfunction DesignerToolbarSeparator({ className }: DesignerToolbarSeparatorProps) {\n return (\n <div\n className={cn(\"mx-1 h-5 w-px bg-border compact:h-4\", className)}\n role=\"separator\"\n aria-orientation=\"vertical\"\n />\n );\n}\n\n/* ============================================================== *\n * ToolbarButton — single tool / action *\n * ============================================================== */\n\ninterface DesignerToolbarButtonProps {\n label: string;\n icon?: ComponentType<{ size?: number; className?: string }>;\n onClick?: () => void;\n active?: boolean;\n disabled?: boolean;\n /** Optional keyboard shortcut shown in the tooltip (e.g. 'V', 'Cmd+Z'). */\n shortcut?: string;\n size?: \"default\" | \"touch\";\n className?: string;\n children?: ReactNode;\n}\n\nfunction DesignerToolbarButton({\n label,\n icon: Icon,\n onClick,\n active,\n disabled,\n shortcut,\n size = \"default\",\n className,\n children,\n}: DesignerToolbarButtonProps) {\n return (\n <Tooltip\n content={(\n <span className=\"flex items-center whitespace-nowrap\">\n <span>{label}</span>\n {shortcut && <span className=\"ml-2 text-[11px] text-background/65\">{shortcut}</span>}\n </span>\n )}\n side=\"top\"\n sideOffset={10}\n delayDuration={120}\n className=\"max-w-56 rounded-lg bg-foreground px-2.5 py-1.5 text-[12px] font-medium leading-none tracking-[0.01em] text-background shadow-natural\"\n >\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n aria-label={label}\n aria-pressed={active}\n className={cn(\n \"flex h-9 min-w-9 items-center justify-center gap-1 rounded-md px-2 caption tabular-nums transition-[background-color,color,opacity,scale] active:scale-[0.96]\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"compact:h-8 compact:min-w-8 compact:rounded-[6px] compact:px-1.5 compact:text-[12px]\",\n \"[@media(pointer:coarse)]:h-11 [@media(pointer:coarse)]:min-w-11\",\n size === \"touch\" && \"h-11 min-w-11\",\n active\n ? \"bg-foreground text-background\"\n : \"text-muted-foreground hover:bg-hover hover:text-foreground active:bg-active\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {Icon && <Icon size={16} />}\n {children}\n </button>\n </Tooltip>\n );\n}\n\nexport { DesignerToolbar, DesignerToolbarGroup, DesignerToolbarSeparator, DesignerToolbarButton };\nexport type {\n DesignerToolbarProps,\n DesignerToolbarGroupProps,\n DesignerToolbarSeparatorProps,\n DesignerToolbarButtonProps,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Link2, Unlink2 } from \"lucide-react\";\nimport { Button, InputNumber, cn } from \"@hilum/ui\";\n\ntype DesignerControlValue = number | null;\n\ninterface DesignerValueItem<K extends string> {\n key: K;\n label: React.ReactNode;\n ariaLabel?: string;\n min?: number;\n max?: number;\n step?: number;\n precision?: number;\n unit?: string;\n disabled?: boolean;\n}\n\ninterface DesignerValueControlBaseProps<K extends string> {\n label?: React.ReactNode;\n values: Record<K, DesignerControlValue>;\n items: readonly DesignerValueItem<K>[];\n onChange: (key: K, value: number) => void;\n onChangeAll?: (value: number) => void;\n onCommit?: () => void;\n linked?: boolean;\n onLinkedChange?: (linked: boolean) => void;\n unit?: string;\n min?: number;\n max?: number;\n step?: number;\n precision?: number;\n disabled?: boolean;\n readOnly?: boolean;\n mixedLabel?: string;\n hideSteppers?: boolean;\n className?: string;\n labelClassName?: string;\n inputClassName?: string;\n controlsClassName?: string;\n linkButtonClassName?: string;\n linkLabel?: string;\n unlinkLabel?: string;\n}\n\ninterface TwoValueControlProps<K extends string = string>\n extends DesignerValueControlBaseProps<K> {\n items: readonly [DesignerValueItem<K>, DesignerValueItem<K>];\n}\n\ninterface FourValueControlProps<K extends string = string>\n extends DesignerValueControlBaseProps<K> {\n items: readonly [\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n DesignerValueItem<K>,\n ];\n layout?: \"grid\" | \"single-when-linked\";\n}\n\ntype SpacingSide = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype CornerSide = \"topLeft\" | \"topRight\" | \"bottomLeft\" | \"bottomRight\";\n\ntype SpacingControlProps = Omit<\n FourValueControlProps<SpacingSide>,\n \"items\" | \"values\" | \"onChange\" | \"onChangeAll\"\n> & {\n values: Record<SpacingSide, DesignerControlValue>;\n onChange: (side: SpacingSide, value: number) => void;\n onChangeAll?: (value: number) => void;\n};\n\ntype CornerRadiusControlProps = Omit<\n FourValueControlProps<CornerSide>,\n \"items\" | \"values\" | \"onChange\" | \"onChangeAll\"\n> & {\n values: Record<CornerSide, DesignerControlValue>;\n onChange: (side: CornerSide, value: number) => void;\n onChangeAll?: (value: number) => void;\n};\n\nfunction getSharedValue<K extends string>(\n items: readonly DesignerValueItem<K>[],\n values: Record<K, DesignerControlValue>,\n) {\n const first = values[items[0].key];\n if (first === null) return null;\n return items.every((item) => values[item.key] === first) ? first : null;\n}\n\nfunction DesignerValueField<K extends string>({\n item,\n value,\n unit,\n min,\n max,\n step,\n precision,\n disabled,\n readOnly,\n mixedLabel,\n hideSteppers,\n inputClassName,\n onChange,\n onCommit,\n}: {\n item: DesignerValueItem<K>;\n value: DesignerControlValue;\n unit?: string | undefined;\n min?: number | undefined;\n max?: number | undefined;\n step?: number | undefined;\n precision?: number | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n mixedLabel?: string | undefined;\n hideSteppers?: boolean | undefined;\n inputClassName?: string | undefined;\n onChange: (value: number) => void;\n onCommit?: (() => void) | undefined;\n}) {\n return (\n <div className=\"relative min-w-0\">\n {/* Label-in-field prefix doubles as a scrub handle (drag to change). */}\n <InputNumber\n label={<span className=\"uppercase\">{item.label}</span>}\n scrubLabel={item.ariaLabel}\n value={value}\n onChange={onChange}\n min={item.min ?? min}\n max={item.max ?? max}\n step={item.step ?? step}\n precision={item.precision ?? precision}\n unit={item.unit ?? unit}\n mixedLabel={mixedLabel}\n commitOnChange\n hideSteppers={hideSteppers}\n disabled={disabled || item.disabled}\n readOnly={readOnly}\n aria-label={item.ariaLabel ?? (typeof item.label === \"string\" ? item.label : undefined)}\n onBlur={onCommit}\n className={cn(\"h-8 w-full compact:h-6\", inputClassName)}\n inputMode=\"decimal\"\n />\n </div>\n );\n}\n\nfunction DesignerValueControl<K extends string>({\n label,\n values,\n items,\n onChange,\n onChangeAll,\n onCommit,\n linked,\n onLinkedChange,\n unit,\n min = -Infinity,\n max = Infinity,\n step = 1,\n precision = 0,\n disabled = false,\n readOnly = false,\n mixedLabel = \"Mixed\",\n hideSteppers = true,\n className,\n labelClassName,\n inputClassName,\n controlsClassName,\n linkButtonClassName,\n linkLabel = \"Link values\",\n unlinkLabel = \"Unlink values\",\n singleWhenLinked = false,\n}: DesignerValueControlBaseProps<K> & { singleWhenLinked?: boolean }) {\n const hasLinkControl = typeof linked === \"boolean\" && Boolean(onLinkedChange);\n const sharedValue = getSharedValue(items, values);\n const showSingleInput = singleWhenLinked && linked;\n\n const handleChange = (key: K, value: number) => {\n if (linked) {\n if (onChangeAll) {\n onChangeAll(value);\n } else {\n items.forEach((item) => onChange(item.key, value));\n }\n return;\n }\n\n onChange(key, value);\n };\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1.5 compact:gap-1\", className)}>\n {(label || hasLinkControl) && (\n <div className=\"flex min-w-0 items-center justify-between gap-2\">\n {label && (\n <div\n className={cn(\n \"caption select-none text-muted-foreground compact:text-[11px]\",\n labelClassName,\n )}\n >\n {label}\n </div>\n )}\n {hasLinkControl && (\n <Button\n type=\"button\"\n variant={linked ? \"secondary\" : \"ghost\"}\n size=\"icon-xs\"\n aria-label={linked ? unlinkLabel : linkLabel}\n title={linked ? unlinkLabel : linkLabel}\n aria-pressed={linked}\n disabled={disabled || readOnly}\n onClick={() => onLinkedChange?.(!linked)}\n className={linkButtonClassName}\n >\n {linked ? <Link2 size={12} /> : <Unlink2 size={12} />}\n </Button>\n )}\n </div>\n )}\n\n {showSingleInput ? (\n <DesignerValueField\n item={{ ...items[0], label: \"All\", ariaLabel: \"All values\" }}\n value={sharedValue}\n unit={unit}\n min={min}\n max={max}\n step={step}\n precision={precision}\n disabled={disabled}\n readOnly={readOnly}\n mixedLabel={mixedLabel}\n hideSteppers={hideSteppers}\n inputClassName={inputClassName}\n onChange={(value) => handleChange(items[0].key, value)}\n onCommit={onCommit}\n />\n ) : (\n <div\n className={cn(\n \"grid min-w-0 gap-2 compact:gap-1.5\",\n items.length === 2 ? \"grid-cols-2\" : \"grid-cols-2\",\n controlsClassName,\n )}\n >\n {items.map((item) => (\n <DesignerValueField\n key={item.key}\n item={item}\n value={values[item.key]}\n unit={unit}\n min={min}\n max={max}\n step={step}\n precision={precision}\n disabled={disabled}\n readOnly={readOnly}\n mixedLabel={mixedLabel}\n hideSteppers={hideSteppers}\n inputClassName={inputClassName}\n onChange={(value) => handleChange(item.key, value)}\n onCommit={onCommit}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction TwoValueControl<K extends string = string>(props: TwoValueControlProps<K>) {\n return <DesignerValueControl {...props} />;\n}\n\nfunction FourValueControl<K extends string = string>({\n layout = \"single-when-linked\",\n ...props\n}: FourValueControlProps<K>) {\n return <DesignerValueControl {...props} singleWhenLinked={layout === \"single-when-linked\"} />;\n}\n\nconst spacingItems = [\n { key: \"top\", label: \"T\", ariaLabel: \"Top\" },\n { key: \"right\", label: \"R\", ariaLabel: \"Right\" },\n { key: \"bottom\", label: \"B\", ariaLabel: \"Bottom\" },\n { key: \"left\", label: \"L\", ariaLabel: \"Left\" },\n] as const satisfies readonly [\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n DesignerValueItem<SpacingSide>,\n];\n\nconst cornerItems = [\n { key: \"topLeft\", label: \"TL\", ariaLabel: \"Top left radius\" },\n { key: \"topRight\", label: \"TR\", ariaLabel: \"Top right radius\" },\n { key: \"bottomLeft\", label: \"BL\", ariaLabel: \"Bottom left radius\" },\n { key: \"bottomRight\", label: \"BR\", ariaLabel: \"Bottom right radius\" },\n] as const satisfies readonly [\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n DesignerValueItem<CornerSide>,\n];\n\nfunction SpacingControl(props: SpacingControlProps) {\n return <FourValueControl {...props} items={spacingItems} />;\n}\n\nfunction CornerRadiusControl(props: CornerRadiusControlProps) {\n return <FourValueControl {...props} items={cornerItems} min={props.min ?? 0} />;\n}\n\nexport {\n CornerRadiusControl,\n FourValueControl,\n SpacingControl,\n TwoValueControl,\n};\nexport type {\n CornerRadiusControlProps,\n CornerSide,\n DesignerControlValue,\n DesignerValueItem,\n FourValueControlProps,\n SpacingControlProps,\n SpacingSide,\n TwoValueControlProps,\n};\n","import { useCallback, useState } from \"react\";\n\ninterface HistoryState<T> {\n past: T[];\n present: T;\n future: T[];\n}\n\ninterface UseHistoryReturn<T> {\n state: T;\n /**\n * Record a new state. Use when the user makes a logical edit. Pushes the\n * current `state` into `past` and clears `future`. Pass `{ skipHistory: true }`\n * (via a separate setter) to overwrite without pushing — apps that need that\n * can set state directly via a wrapper.\n */\n setState: (next: T | ((prev: T) => T)) => void;\n /** Replace `state` without pushing onto the history stack. */\n replaceState: (next: T | ((prev: T) => T)) => void;\n undo: () => void;\n redo: () => void;\n reset: (next: T) => void;\n canUndo: boolean;\n canRedo: boolean;\n /** Number of past entries (undo depth). */\n pastSize: number;\n /** Number of future entries (redo depth). */\n futureSize: number;\n}\n\n/**\n * Generic, engine-agnostic undo/redo stack.\n *\n * @hilum/designer-canvas wires this with `useHistory<Layer[]>(layers)`.\n * A form-builder app could wire `useHistory<FormSchema>(schema)`.\n */\nexport function useHistory<T>(initial: T): UseHistoryReturn<T> {\n const [history, setHistory] = useState<HistoryState<T>>({\n past: [],\n present: initial,\n future: [],\n });\n\n const setState = useCallback((next: T | ((prev: T) => T)) => {\n setHistory((prev) => {\n const value = typeof next === \"function\" ? (next as (p: T) => T)(prev.present) : next;\n if (Object.is(value, prev.present)) return prev;\n return {\n past: [...prev.past, prev.present],\n present: value,\n future: [],\n };\n });\n }, []);\n\n const replaceState = useCallback((next: T | ((prev: T) => T)) => {\n setHistory((prev) => {\n const value = typeof next === \"function\" ? (next as (p: T) => T)(prev.present) : next;\n return { ...prev, present: value };\n });\n }, []);\n\n const undo = useCallback(() => {\n setHistory((prev) => {\n if (prev.past.length === 0) return prev;\n const past = prev.past.slice(0, -1);\n const previous = prev.past[prev.past.length - 1]!;\n return {\n past,\n present: previous,\n future: [prev.present, ...prev.future],\n };\n });\n }, []);\n\n const redo = useCallback(() => {\n setHistory((prev) => {\n if (prev.future.length === 0) return prev;\n const [next, ...rest] = prev.future;\n return {\n past: [...prev.past, prev.present],\n present: next!,\n future: rest,\n };\n });\n }, []);\n\n const reset = useCallback((next: T) => {\n setHistory({ past: [], present: next, future: [] });\n }, []);\n\n return {\n state: history.present,\n setState,\n replaceState,\n undo,\n redo,\n reset,\n canUndo: history.past.length > 0,\n canRedo: history.future.length > 0,\n pastSize: history.past.length,\n futureSize: history.future.length,\n };\n}\n","import { useEffect } from \"react\";\n\nexport interface KeybindingConfig {\n /** Lower-case key (e.g. 'z', 'arrowup', 'escape', '+', '-'). */\n key: string;\n ctrl?: boolean;\n /** Cmd on macOS. Use both `meta` and `ctrl: true` if you want both. */\n meta?: boolean;\n shift?: boolean;\n alt?: boolean;\n /**\n * Treat both ctrl and meta as the same modifier (for cross-platform\n * shortcuts like Cmd+Z / Ctrl+Z). Default: false. Set to true to match\n * either modifier.\n */\n mod?: boolean;\n action: (event: KeyboardEvent) => void;\n /** Don't run when target is an input / textarea / contenteditable. Default: true. */\n skipInputs?: boolean;\n /** Call event.preventDefault() before action. Default: true. */\n preventDefault?: boolean;\n}\n\ninterface UseKeybindingsOptions {\n /** Skip all bindings entirely. */\n disabled?: boolean;\n /** Element to attach the listener to. Default: window. */\n target?: Window | HTMLElement | null;\n}\n\n/**\n * Generic keyboard shortcut registry. Engine-agnostic — the package doesn't\n * know what an action does. Pass an array of bindings; the hook attaches\n * a single keydown listener and dispatches on match.\n *\n * @hilum/designer-canvas wires its standard editor shortcuts (Cmd+Z, V, T,\n * arrow nudge, etc.) on top of this hook.\n */\nexport function useKeybindings(\n bindings: KeybindingConfig[],\n { disabled, target }: UseKeybindingsOptions = {},\n) {\n useEffect(() => {\n if (disabled) return;\n const node = target ?? (typeof window !== \"undefined\" ? window : null);\n if (!node) return;\n\n const handler = (rawEvent: Event) => {\n const e = rawEvent as KeyboardEvent;\n\n const tgt = e.target as HTMLElement | null;\n const isInput =\n tgt instanceof HTMLInputElement ||\n tgt instanceof HTMLTextAreaElement ||\n tgt instanceof HTMLSelectElement ||\n tgt?.isContentEditable === true;\n\n const key = e.key.toLowerCase();\n\n for (const b of bindings) {\n if (b.key.toLowerCase() !== key) continue;\n if (b.skipInputs !== false && isInput) continue;\n\n const ctrlMatches = b.ctrl ? e.ctrlKey : !e.ctrlKey || b.mod;\n const metaMatches = b.meta ? e.metaKey : !e.metaKey || b.mod;\n const modMatches = b.mod ? e.ctrlKey || e.metaKey : true;\n const shiftMatches = b.shift ? e.shiftKey : !e.shiftKey;\n const altMatches = b.alt ? e.altKey : !e.altKey;\n\n if (!modMatches) continue;\n if (!b.mod && (!ctrlMatches || !metaMatches)) continue;\n if (!shiftMatches || !altMatches) continue;\n\n if (b.preventDefault !== false) e.preventDefault();\n b.action(e);\n return;\n }\n };\n\n (node as Window).addEventListener(\"keydown\", handler);\n return () => (node as Window).removeEventListener(\"keydown\", handler);\n }, [bindings, disabled, target]);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hilum/designer",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Engine-agnostic canvas-editor chrome — DesignerShell, Toolbar, Panel, Pane + generic useHistory and useKeybindings hooks",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,11 +13,13 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
|
+
"sideEffects": false,
|
|
16
17
|
"exports": {
|
|
17
18
|
".": {
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
}
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
21
23
|
},
|
|
22
24
|
"files": [
|
|
23
25
|
"dist",
|
|
@@ -39,7 +41,7 @@
|
|
|
39
41
|
"tailwindcss": "^4.2.0",
|
|
40
42
|
"tsup": "^8.3.0",
|
|
41
43
|
"typescript": "^5.7.0",
|
|
42
|
-
"@hilum/ui": "3.
|
|
44
|
+
"@hilum/ui": "3.10.0"
|
|
43
45
|
},
|
|
44
46
|
"scripts": {
|
|
45
47
|
"build": "tsup",
|