@ctrl-ui/react 0.8.6 → 0.8.7
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/action-bar.js +1 -1
- package/dist/activity.js +1 -1
- package/dist/blocks/coding-agent.js +16 -19
- package/dist/blocks/design-canvas-data.d.ts +32 -0
- package/dist/blocks/design-canvas-data.js +100 -0
- package/dist/blocks/design-canvas-inspector.d.ts +8 -0
- package/dist/blocks/design-canvas-inspector.js +238 -0
- package/dist/blocks/design-canvas.d.ts +17 -0
- package/dist/blocks/design-canvas.js +346 -0
- package/dist/blocks/file-explorer.js +2 -2
- package/dist/blocks/settings.js +2 -2
- package/dist/chat-composer-attachment.d.ts +9 -3
- package/dist/chat-composer-attachment.js +27 -10
- package/dist/chat-composer-editor.js +20 -4
- package/dist/chat-composer.d.ts +1 -1
- package/dist/chat-composer.js +4 -3
- package/dist/chat-layout.js +32 -19
- package/dist/context.js +1 -1
- package/dist/dynamic-notification.js +1 -1
- package/dist/environment-variables.js +1 -1
- package/dist/filter-bar/context.d.ts +32 -0
- package/dist/filter-bar/context.js +11 -0
- package/dist/filter-bar/editor.d.ts +14 -0
- package/dist/filter-bar/editor.js +204 -0
- package/dist/filter-bar/model.d.ts +9 -0
- package/dist/filter-bar/model.js +48 -0
- package/dist/filter-bar/motion.d.ts +10 -0
- package/dist/filter-bar/motion.js +84 -0
- package/dist/filter-bar/parts.d.ts +19 -0
- package/dist/filter-bar/parts.js +233 -0
- package/dist/filter-bar/types.d.ts +53 -0
- package/dist/filter-bar/types.js +0 -0
- package/dist/filter-bar.d.ts +27 -0
- package/dist/filter-bar.js +304 -0
- package/dist/hooks/use-chat-composer.d.ts +3 -1
- package/dist/hooks/use-chat-composer.js +2 -2
- package/dist/hooks/use-dropzone.d.ts +7 -4
- package/dist/hooks/use-dropzone.js +34 -3
- package/dist/inline-attachment.js +8 -14
- package/dist/inline-citation.js +1 -1
- package/dist/knob-contracts/chat-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/chat-layout-knobs.js +2 -1
- package/dist/knob-contracts/choice-knobs.d.ts +1 -1
- package/dist/knob-contracts/choice-knobs.js +1 -0
- package/dist/knob-contracts/collapsible-knobs.d.ts +1 -1
- package/dist/knob-contracts/collapsible-knobs.js +1 -1
- package/dist/knob-contracts/filter-bar-knobs.d.ts +4 -0
- package/dist/knob-contracts/filter-bar-knobs.js +16 -0
- package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
- package/dist/knob-contracts/infinite-canvas-knobs.js +3 -0
- package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
- package/dist/knob-contracts/page-layout-knobs.js +3 -1
- package/dist/knob-contracts/popup-knobs.d.ts +1 -1
- package/dist/knob-contracts/popup-knobs.js +1 -0
- package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
- package/dist/knob-contracts/table-of-contents-knobs.js +3 -5
- package/dist/lib/phone-input-format.js +1 -1
- package/dist/markdown-block.js +11 -7
- package/dist/scripts/contrast-eval.js +5 -4
- package/dist/styles/index.css +5 -4
- package/dist/styles/recipes/button-group.css +1 -1
- package/dist/styles/recipes/button.css +2 -2
- package/dist/styles/recipes/chat-composer.css +14 -6
- package/dist/styles/recipes/chat-layout.css +29 -2
- package/dist/styles/recipes/choice.css +10 -3
- package/dist/styles/recipes/code-diff.css +16 -4
- package/dist/styles/recipes/code.css +11 -5
- package/dist/styles/recipes/collapsible.css +37 -0
- package/dist/styles/recipes/color-picker.css +12 -2
- package/dist/styles/recipes/dockable-panel.css +11 -3
- package/dist/styles/recipes/field-parts.css +62 -0
- package/dist/styles/recipes/field.css +28 -6
- package/dist/styles/recipes/filter-bar.css +174 -0
- package/dist/styles/recipes/infinite-canvas.css +51 -3
- package/dist/styles/recipes/inline-attachment.css +6 -1
- package/dist/styles/recipes/page-layout.css +18 -0
- package/dist/styles/recipes/pagination.css +1 -1
- package/dist/styles/recipes/popup-controls.css +16 -0
- package/dist/styles/recipes/popup-drawer.css +34 -32
- package/dist/styles/recipes/popup-lists.css +11 -2
- package/dist/styles/recipes/popup.css +10 -12
- package/dist/styles/recipes/range.css +1 -1
- package/dist/styles/recipes/resizable.css +34 -0
- package/dist/styles/recipes/spinner.css +4 -0
- package/dist/styles/recipes/table-of-contents.css +42 -42
- package/dist/styles/recipes/tabs.css +21 -0
- package/dist/styles/recipes/track-highlight.css +2 -1
- package/dist/styles/recipes/transcript-divider.css +2 -2
- package/dist/styles/theme.css +250 -91
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/autocomplete.js +5 -1
- package/dist/ui/button.js +2 -2
- package/dist/ui/checkbox-group.js +1 -1
- package/dist/ui/code-diff.js +1 -1
- package/dist/ui/code.js +3 -3
- package/dist/ui/collapsible.js +1 -1
- package/dist/ui/color-picker.js +1 -1
- package/dist/ui/combobox-disabled-selection.d.ts +1 -1
- package/dist/ui/combobox-disabled-selection.js +2 -1
- package/dist/ui/combobox.d.ts +5 -23
- package/dist/ui/combobox.js +26 -14
- package/dist/ui/command.js +9 -1
- package/dist/ui/context-menu.js +1 -1
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dockable-panel.js +18 -10
- package/dist/ui/drawer.d.ts +7 -4
- package/dist/ui/drawer.js +36 -23
- package/dist/ui/dropdown-menu.js +1 -1
- package/dist/ui/dropzone.d.ts +3 -1
- package/dist/ui/dropzone.js +3 -1
- package/dist/ui/field.js +1 -1
- package/dist/ui/hover-card.js +1 -1
- package/dist/ui/infinite-canvas.d.ts +11 -0
- package/dist/ui/infinite-canvas.js +82 -7
- package/dist/ui/input-group.d.ts +2 -1
- package/dist/ui/input-group.js +12 -3
- package/dist/ui/input.js +9 -0
- package/dist/ui/item.js +1 -1
- package/dist/ui/markdown-elements.js +11 -8
- package/dist/ui/menubar.js +1 -1
- package/dist/ui/morphing-panel.js +1 -1
- package/dist/ui/navigation-menu.js +1 -1
- package/dist/ui/number-field.d.ts +1 -1
- package/dist/ui/number-field.js +13 -2
- package/dist/ui/phone-input.js +2 -2
- package/dist/ui/popover.js +1 -1
- package/dist/ui/radio-group.d.ts +1 -0
- package/dist/ui/radio-group.js +11 -1
- package/dist/ui/resizable.d.ts +18 -1
- package/dist/ui/resizable.js +127 -7
- package/dist/ui/responsive-dialog.js +6 -3
- package/dist/ui/rich-tooltip.js +1 -1
- package/dist/ui/scroll-area.d.ts +4 -1
- package/dist/ui/scroll-area.js +2 -1
- package/dist/ui/select.d.ts +2 -1
- package/dist/ui/select.js +58 -33
- package/dist/ui/sheet.js +1 -1
- package/dist/ui/sidebar-menu.js +1 -1
- package/dist/ui/sidebar-provider.js +2 -2
- package/dist/ui/sidebar-resize-rail.js +1 -1
- package/dist/ui/sidebar.js +1 -1
- package/dist/ui/table-of-contents.d.ts +4 -3
- package/dist/ui/table-of-contents.js +126 -47
- package/dist/ui/table.js +11 -7
- package/dist/ui/toast.js +1 -1
- package/dist/ui/toggle.d.ts +1 -1
- package/dist/ui/toggle.js +2 -1
- package/dist/ui/tooltip.js +1 -1
- package/dist/ui/tree.js +1 -1
- package/dist/ui/trigger-menu.js +7 -3
- package/dist/user-ask.js +1 -1
- package/package.json +1 -1
package/dist/action-bar.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useCopyToClipboard } from "./hooks/use-copy-to-clipboard.js";
|
|
3
2
|
import { cn } from "./lib/cn.js";
|
|
4
3
|
import { Button } from "./ui/button.js";
|
|
4
|
+
import { useCopyToClipboard } from "./hooks/use-copy-to-clipboard.js";
|
|
5
5
|
import { createContext, useContext } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/action-bar.tsx
|
package/dist/activity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "./lib/cn.js";
|
|
3
|
-
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible.js";
|
|
4
3
|
import { ScrollArea } from "./ui/scroll-area.js";
|
|
4
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible.js";
|
|
5
5
|
import { createContext, useContext } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { Check, ChevronRight, CircleAlert, CircleDashed, LoaderCircle } from "lucide-react";
|
|
@@ -132,26 +132,23 @@ function CodingAgentSidebar({ appName, brand, sidebarTop, navigation, projects,
|
|
|
132
132
|
children: projects.map((project) => /* @__PURE__ */ jsxs(Collapsible, {
|
|
133
133
|
defaultOpen: project.open ?? true,
|
|
134
134
|
className: "min-w-0",
|
|
135
|
-
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, { children: [
|
|
136
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {
|
|
137
|
+
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
138
|
+
"aria-hidden": "true"
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ jsx("span", {
|
|
141
|
+
className: "flex shrink-0 items-center text-muted-foreground",
|
|
142
|
+
children: project.icon ?? /* @__PURE__ */ jsx(FolderIcon, {
|
|
143
|
+
className: "size-4",
|
|
140
144
|
"aria-hidden": "true"
|
|
141
|
-
}),
|
|
142
|
-
/* @__PURE__ */ jsx("span", {
|
|
143
|
-
className: "flex shrink-0 items-center text-muted-foreground",
|
|
144
|
-
children: project.icon ?? /* @__PURE__ */ jsx(FolderIcon, {
|
|
145
|
-
className: "size-4",
|
|
146
|
-
"aria-hidden": "true"
|
|
147
|
-
})
|
|
148
|
-
}),
|
|
149
|
-
/* @__PURE__ */ jsx("span", {
|
|
150
|
-
className: "truncate",
|
|
151
|
-
children: project.name
|
|
152
145
|
})
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
}),
|
|
147
|
+
/* @__PURE__ */ jsx("span", {
|
|
148
|
+
className: "truncate",
|
|
149
|
+
children: project.name
|
|
150
|
+
})
|
|
151
|
+
] }), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenu, {
|
|
155
152
|
className: "mt-1 pl-5",
|
|
156
153
|
children: project.tasks.map((task) => {
|
|
157
154
|
const isActive = task.id === activeTaskId;
|
|
@@ -191,7 +188,7 @@ function CodingAgentSidebar({ appName, brand, sidebarTop, navigation, projects,
|
|
|
191
188
|
function CodingAgentConversation({ children, composer, className, ...props }) {
|
|
192
189
|
return /* @__PURE__ */ jsx(ChatLayout, {
|
|
193
190
|
chrome: "embedded",
|
|
194
|
-
className
|
|
191
|
+
className,
|
|
195
192
|
...props,
|
|
196
193
|
children: /* @__PURE__ */ jsx(ChatThread, {
|
|
197
194
|
composer: /* @__PURE__ */ jsx("div", {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/blocks/design-canvas-data.d.ts
|
|
2
|
+
export type DesignCanvasLayerKind = "frame" | "rectangle" | "ellipse" | "text";
|
|
3
|
+
export type DesignCanvasTool = "move" | DesignCanvasLayerKind;
|
|
4
|
+
export type DesignCanvasFill = {
|
|
5
|
+
color: string;
|
|
6
|
+
opacity: number;
|
|
7
|
+
visible: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type DesignCanvasLayer = {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
kind: DesignCanvasLayerKind;
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
rotation: number;
|
|
18
|
+
opacity: number;
|
|
19
|
+
cornerRadius: number;
|
|
20
|
+
fill: DesignCanvasFill | null;
|
|
21
|
+
text?: string;
|
|
22
|
+
};
|
|
23
|
+
export type DesignCanvasPoint = {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
};
|
|
27
|
+
export type DesignCanvasBounds = Pick<DesignCanvasLayer, "x" | "y" | "width" | "height">;
|
|
28
|
+
export declare function drawnDesignCanvasBounds(kind: DesignCanvasLayerKind, start: DesignCanvasPoint, end: DesignCanvasPoint, clickTolerance: number): DesignCanvasBounds;
|
|
29
|
+
export declare function createDesignCanvasLayer(kind: DesignCanvasLayerKind, bounds: DesignCanvasBounds, id: string): DesignCanvasLayer;
|
|
30
|
+
export declare function resizeDesignCanvasLayer(layer: DesignCanvasLayer, size: Partial<Pick<DesignCanvasLayer, "width" | "height">>, aspectRatioLocked: boolean): DesignCanvasLayer;
|
|
31
|
+
export declare function designCanvasFillColor(fill: DesignCanvasFill | null): string;
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//#region src/blocks/design-canvas-data.ts
|
|
2
|
+
const NEW_LAYER_DEFAULTS = {
|
|
3
|
+
frame: {
|
|
4
|
+
name: "Frame",
|
|
5
|
+
width: 320,
|
|
6
|
+
height: 200,
|
|
7
|
+
fill: {
|
|
8
|
+
color: "#FFFFFF",
|
|
9
|
+
opacity: 100,
|
|
10
|
+
visible: true
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
rectangle: {
|
|
14
|
+
name: "Rectangle",
|
|
15
|
+
width: 120,
|
|
16
|
+
height: 120,
|
|
17
|
+
fill: {
|
|
18
|
+
color: "#D9D9D9",
|
|
19
|
+
opacity: 100,
|
|
20
|
+
visible: true
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
ellipse: {
|
|
24
|
+
name: "Ellipse",
|
|
25
|
+
width: 120,
|
|
26
|
+
height: 120,
|
|
27
|
+
fill: {
|
|
28
|
+
color: "#D9D9D9",
|
|
29
|
+
opacity: 100,
|
|
30
|
+
visible: true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
text: {
|
|
34
|
+
name: "Text",
|
|
35
|
+
width: 160,
|
|
36
|
+
height: 32,
|
|
37
|
+
fill: {
|
|
38
|
+
color: "#000000",
|
|
39
|
+
opacity: 100,
|
|
40
|
+
visible: true
|
|
41
|
+
},
|
|
42
|
+
text: "Text"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function drawnDesignCanvasBounds(kind, start, end, clickTolerance) {
|
|
46
|
+
const width = Math.abs(end.x - start.x);
|
|
47
|
+
const height = Math.abs(end.y - start.y);
|
|
48
|
+
if (Math.max(width, height) < clickTolerance) {
|
|
49
|
+
const defaults = NEW_LAYER_DEFAULTS[kind];
|
|
50
|
+
return {
|
|
51
|
+
x: Math.round(start.x - defaults.width / 2),
|
|
52
|
+
y: Math.round(start.y - defaults.height / 2),
|
|
53
|
+
width: defaults.width,
|
|
54
|
+
height: defaults.height
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
x: Math.round(Math.min(start.x, end.x)),
|
|
59
|
+
y: Math.round(Math.min(start.y, end.y)),
|
|
60
|
+
width: Math.max(1, Math.round(width)),
|
|
61
|
+
height: Math.max(1, Math.round(height))
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function createDesignCanvasLayer(kind, bounds, id) {
|
|
65
|
+
return {
|
|
66
|
+
...NEW_LAYER_DEFAULTS[kind],
|
|
67
|
+
...bounds,
|
|
68
|
+
id,
|
|
69
|
+
kind,
|
|
70
|
+
rotation: 0,
|
|
71
|
+
opacity: 100,
|
|
72
|
+
cornerRadius: 0
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function resizeDesignCanvasLayer(layer, size, aspectRatioLocked) {
|
|
76
|
+
const aspectRatio = layer.width / layer.height;
|
|
77
|
+
if (size.width !== void 0) {
|
|
78
|
+
const height = aspectRatioLocked ? Math.round(size.width / aspectRatio) : layer.height;
|
|
79
|
+
return {
|
|
80
|
+
...layer,
|
|
81
|
+
width: size.width,
|
|
82
|
+
height
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (size.height !== void 0) {
|
|
86
|
+
const width = aspectRatioLocked ? Math.round(size.height * aspectRatio) : layer.width;
|
|
87
|
+
return {
|
|
88
|
+
...layer,
|
|
89
|
+
width,
|
|
90
|
+
height: size.height
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return layer;
|
|
94
|
+
}
|
|
95
|
+
function designCanvasFillColor(fill) {
|
|
96
|
+
if (!fill?.visible) return "transparent";
|
|
97
|
+
return `color-mix(in srgb, ${fill.color} ${fill.opacity}%, transparent)`;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { createDesignCanvasLayer, designCanvasFillColor, drawnDesignCanvasBounds, resizeDesignCanvasLayer };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DesignCanvasLayer } from "./design-canvas-data.js";
|
|
2
|
+
//#region src/blocks/design-canvas-inspector.d.ts
|
|
3
|
+
export type DesignCanvasInspectorProps = {
|
|
4
|
+
layer: DesignCanvasLayer | undefined;
|
|
5
|
+
onLayerChange: (layer: DesignCanvasLayer) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function DesignCanvasInspector({ layer, onLayerChange }: DesignCanvasInspectorProps): import("react").JSX.Element;
|
|
8
|
+
//#endregion
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "../ui/button.js";
|
|
3
|
+
import { InputGroup, InputGroupAddon } from "../ui/input-group.js";
|
|
4
|
+
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from "../ui/empty.js";
|
|
5
|
+
import { Separator } from "../ui/separator.js";
|
|
6
|
+
import { resizeDesignCanvasLayer } from "./design-canvas-data.js";
|
|
7
|
+
import { NumberField, NumberFieldGroup, NumberFieldInput, NumberFieldScrubArea } from "../ui/number-field.js";
|
|
8
|
+
import { ColorPicker, ColorPickerArea, ColorPickerContent, ColorPickerEyeDropper, ColorPickerHue, ColorPickerInput, ColorPickerTrigger } from "../ui/color-picker.js";
|
|
9
|
+
import { Toggle } from "../ui/toggle.js";
|
|
10
|
+
import { useState } from "react";
|
|
11
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { BlendIcon, EyeIcon, EyeOffIcon, Link2Icon, MinusIcon, PlusIcon, RotateCwIcon, SquareRoundCornerIcon, Unlink2Icon } from "lucide-react";
|
|
13
|
+
//#region src/blocks/design-canvas-inspector.tsx
|
|
14
|
+
const WHOLE_NUMBER_FORMAT = {
|
|
15
|
+
useGrouping: false,
|
|
16
|
+
maximumFractionDigits: 0
|
|
17
|
+
};
|
|
18
|
+
const DEFAULT_FILL = {
|
|
19
|
+
color: "#D9D9D9",
|
|
20
|
+
opacity: 100,
|
|
21
|
+
visible: true
|
|
22
|
+
};
|
|
23
|
+
function DesignCanvasInspector({ layer, onLayerChange }) {
|
|
24
|
+
const [aspectRatioLocked, setAspectRatioLocked] = useState(false);
|
|
25
|
+
if (!layer) return /* @__PURE__ */ jsx(Empty, {
|
|
26
|
+
className: "h-full",
|
|
27
|
+
children: /* @__PURE__ */ jsxs(EmptyHeader, { children: [/* @__PURE__ */ jsx(EmptyTitle, { children: "Nothing selected" }), /* @__PURE__ */ jsx(EmptyDescription, { children: "Select a layer to edit its position, size, and fill." })] })
|
|
28
|
+
});
|
|
29
|
+
const update = (patch) => onLayerChange({
|
|
30
|
+
...layer,
|
|
31
|
+
...patch
|
|
32
|
+
});
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "flex flex-col",
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ jsxs(InspectorSection, {
|
|
37
|
+
title: "Position",
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsx(ScrubField, {
|
|
40
|
+
label: "X position",
|
|
41
|
+
prefix: "X",
|
|
42
|
+
value: layer.x,
|
|
43
|
+
onValueChange: (x) => update({ x })
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ jsx(ScrubField, {
|
|
46
|
+
label: "Y position",
|
|
47
|
+
prefix: "Y",
|
|
48
|
+
value: layer.y,
|
|
49
|
+
onValueChange: (y) => update({ y })
|
|
50
|
+
}),
|
|
51
|
+
/* @__PURE__ */ jsx(ScrubField, {
|
|
52
|
+
label: "Rotation",
|
|
53
|
+
className: "col-start-1",
|
|
54
|
+
prefix: /* @__PURE__ */ jsx(RotateCwIcon, {}),
|
|
55
|
+
value: layer.rotation,
|
|
56
|
+
min: -360,
|
|
57
|
+
max: 360,
|
|
58
|
+
format: {
|
|
59
|
+
...WHOLE_NUMBER_FORMAT,
|
|
60
|
+
style: "unit",
|
|
61
|
+
unit: "degree",
|
|
62
|
+
unitDisplay: "narrow"
|
|
63
|
+
},
|
|
64
|
+
onValueChange: (rotation) => update({ rotation })
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ jsxs(InspectorSection, {
|
|
69
|
+
title: "Layout",
|
|
70
|
+
children: [
|
|
71
|
+
/* @__PURE__ */ jsx(ScrubField, {
|
|
72
|
+
label: "Width",
|
|
73
|
+
prefix: "W",
|
|
74
|
+
value: layer.width,
|
|
75
|
+
min: 1,
|
|
76
|
+
onValueChange: (width) => onLayerChange(resizeDesignCanvasLayer(layer, { width }, aspectRatioLocked))
|
|
77
|
+
}),
|
|
78
|
+
/* @__PURE__ */ jsx(ScrubField, {
|
|
79
|
+
label: "Height",
|
|
80
|
+
prefix: "H",
|
|
81
|
+
value: layer.height,
|
|
82
|
+
min: 1,
|
|
83
|
+
onValueChange: (height) => onLayerChange(resizeDesignCanvasLayer(layer, { height }, aspectRatioLocked))
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ jsx(Toggle, {
|
|
86
|
+
size: "sm",
|
|
87
|
+
variant: "ghost",
|
|
88
|
+
iconOnly: true,
|
|
89
|
+
"aria-label": "Lock aspect ratio",
|
|
90
|
+
pressed: aspectRatioLocked,
|
|
91
|
+
onPressedChange: setAspectRatioLocked,
|
|
92
|
+
children: aspectRatioLocked ? /* @__PURE__ */ jsx(Link2Icon, {}) : /* @__PURE__ */ jsx(Unlink2Icon, {})
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ jsxs(InspectorSection, {
|
|
97
|
+
title: "Appearance",
|
|
98
|
+
children: [/* @__PURE__ */ jsx(ScrubField, {
|
|
99
|
+
label: "Layer opacity",
|
|
100
|
+
prefix: /* @__PURE__ */ jsx(BlendIcon, {}),
|
|
101
|
+
suffix: "%",
|
|
102
|
+
value: layer.opacity,
|
|
103
|
+
min: 0,
|
|
104
|
+
max: 100,
|
|
105
|
+
onValueChange: (opacity) => update({ opacity })
|
|
106
|
+
}), /* @__PURE__ */ jsx(ScrubField, {
|
|
107
|
+
label: "Corner radius",
|
|
108
|
+
prefix: /* @__PURE__ */ jsx(SquareRoundCornerIcon, {}),
|
|
109
|
+
value: layer.cornerRadius,
|
|
110
|
+
min: 0,
|
|
111
|
+
onValueChange: (cornerRadius) => update({ cornerRadius })
|
|
112
|
+
})]
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ jsx(InspectorSection, {
|
|
115
|
+
title: "Fill",
|
|
116
|
+
action: layer.fill ? null : /* @__PURE__ */ jsx(Button, {
|
|
117
|
+
size: "xs",
|
|
118
|
+
variant: "ghost",
|
|
119
|
+
iconOnly: true,
|
|
120
|
+
"aria-label": "Add fill",
|
|
121
|
+
onClick: () => update({ fill: DEFAULT_FILL }),
|
|
122
|
+
children: /* @__PURE__ */ jsx(PlusIcon, {})
|
|
123
|
+
}),
|
|
124
|
+
children: layer.fill ? /* @__PURE__ */ jsx(FillRow, {
|
|
125
|
+
fill: layer.fill,
|
|
126
|
+
onFillChange: (fill) => update({ fill }),
|
|
127
|
+
onRemove: () => update({ fill: null })
|
|
128
|
+
}) : null
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function InspectorSection({ title, action, children }) {
|
|
134
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
135
|
+
"aria-label": title,
|
|
136
|
+
className: "flex flex-col gap-2 border-b px-3 py-3",
|
|
137
|
+
children: [/* @__PURE__ */ jsxs("header", {
|
|
138
|
+
className: "flex h-6 items-center justify-between",
|
|
139
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
140
|
+
className: "text-caption font-medium",
|
|
141
|
+
children: title
|
|
142
|
+
}), action]
|
|
143
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
144
|
+
className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] items-center gap-2 empty:hidden",
|
|
145
|
+
children
|
|
146
|
+
})]
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function ScrubField({ label, className, prefix, suffix, value, onValueChange, min, max, format = WHOLE_NUMBER_FORMAT }) {
|
|
150
|
+
return /* @__PURE__ */ jsx(NumberField, {
|
|
151
|
+
size: "sm",
|
|
152
|
+
className,
|
|
153
|
+
value,
|
|
154
|
+
min,
|
|
155
|
+
max,
|
|
156
|
+
format,
|
|
157
|
+
onValueChange: (next) => {
|
|
158
|
+
if (next !== null) onValueChange(next);
|
|
159
|
+
},
|
|
160
|
+
children: /* @__PURE__ */ jsxs(NumberFieldGroup, {
|
|
161
|
+
className: "w-full",
|
|
162
|
+
children: [
|
|
163
|
+
prefix ? /* @__PURE__ */ jsx(NumberFieldScrubArea, { children: prefix }) : null,
|
|
164
|
+
/* @__PURE__ */ jsx(NumberFieldInput, { "aria-label": label }),
|
|
165
|
+
suffix ? /* @__PURE__ */ jsx(NumberFieldScrubArea, { children: suffix }) : null
|
|
166
|
+
]
|
|
167
|
+
})
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function FillRow({ fill, onFillChange, onRemove }) {
|
|
171
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(ColorPicker, {
|
|
172
|
+
value: fill.color,
|
|
173
|
+
alpha: false,
|
|
174
|
+
onValueChange: (color) => onFillChange({
|
|
175
|
+
...fill,
|
|
176
|
+
color
|
|
177
|
+
}),
|
|
178
|
+
children: [/* @__PURE__ */ jsxs(InputGroup, {
|
|
179
|
+
size: "sm",
|
|
180
|
+
className: "col-span-2",
|
|
181
|
+
children: [
|
|
182
|
+
/* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(ColorPickerTrigger, { "aria-label": "Choose fill color" }) }),
|
|
183
|
+
/* @__PURE__ */ jsx(ColorPickerInput, { "aria-label": "Fill color" }),
|
|
184
|
+
/* @__PURE__ */ jsx(Separator, {
|
|
185
|
+
orientation: "vertical",
|
|
186
|
+
className: "h-4"
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ jsx(NumberField, {
|
|
189
|
+
value: fill.opacity,
|
|
190
|
+
min: 0,
|
|
191
|
+
max: 100,
|
|
192
|
+
format: WHOLE_NUMBER_FORMAT,
|
|
193
|
+
className: "shrink-0",
|
|
194
|
+
onValueChange: (opacity) => {
|
|
195
|
+
if (opacity !== null) onFillChange({
|
|
196
|
+
...fill,
|
|
197
|
+
opacity
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
children: /* @__PURE__ */ jsxs(NumberFieldGroup, {
|
|
201
|
+
className: "w-full",
|
|
202
|
+
children: [/* @__PURE__ */ jsx(NumberFieldInput, { "aria-label": "Fill opacity" }), /* @__PURE__ */ jsx(NumberFieldScrubArea, { children: "%" })]
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
}), /* @__PURE__ */ jsxs(ColorPickerContent, {
|
|
207
|
+
side: "left",
|
|
208
|
+
align: "start",
|
|
209
|
+
children: [/* @__PURE__ */ jsx(ColorPickerArea, {}), /* @__PURE__ */ jsxs("div", {
|
|
210
|
+
className: "flex items-center gap-2",
|
|
211
|
+
children: [/* @__PURE__ */ jsx(ColorPickerEyeDropper, {}), /* @__PURE__ */ jsx(ColorPickerHue, { className: "flex-1" })]
|
|
212
|
+
})]
|
|
213
|
+
})]
|
|
214
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
215
|
+
className: "flex",
|
|
216
|
+
children: [/* @__PURE__ */ jsx(Toggle, {
|
|
217
|
+
size: "sm",
|
|
218
|
+
variant: "ghost",
|
|
219
|
+
iconOnly: true,
|
|
220
|
+
"aria-label": "Show fill",
|
|
221
|
+
pressed: fill.visible,
|
|
222
|
+
onPressedChange: (visible) => onFillChange({
|
|
223
|
+
...fill,
|
|
224
|
+
visible
|
|
225
|
+
}),
|
|
226
|
+
children: fill.visible ? /* @__PURE__ */ jsx(EyeIcon, {}) : /* @__PURE__ */ jsx(EyeOffIcon, {})
|
|
227
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
228
|
+
size: "sm",
|
|
229
|
+
variant: "ghost",
|
|
230
|
+
iconOnly: true,
|
|
231
|
+
"aria-label": "Remove fill",
|
|
232
|
+
onClick: onRemove,
|
|
233
|
+
children: /* @__PURE__ */ jsx(MinusIcon, {})
|
|
234
|
+
})]
|
|
235
|
+
})] });
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
export { DesignCanvasInspector };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DesignCanvasFill, DesignCanvasLayer, DesignCanvasLayerKind, DesignCanvasTool } from "./design-canvas-data.js";
|
|
2
|
+
import { InfiniteCanvasTransform } from "../ui/infinite-canvas.js";
|
|
3
|
+
import { ComponentProps } from "react";
|
|
4
|
+
//#region src/blocks/design-canvas.d.ts
|
|
5
|
+
export type DesignCanvasBlockProps = Omit<ComponentProps<"div">, "children" | "defaultValue" | "onChange"> & {
|
|
6
|
+
layers?: readonly DesignCanvasLayer[];
|
|
7
|
+
defaultLayers?: readonly DesignCanvasLayer[];
|
|
8
|
+
onLayersChange?: (layers: DesignCanvasLayer[]) => void;
|
|
9
|
+
selectedLayerId?: string | null;
|
|
10
|
+
defaultSelectedLayerId?: string | null;
|
|
11
|
+
onSelectedLayerIdChange?: (layerId: string | null) => void;
|
|
12
|
+
defaultTransform?: InfiniteCanvasTransform;
|
|
13
|
+
layout?: "viewport" | "contained";
|
|
14
|
+
};
|
|
15
|
+
export declare function DesignCanvasBlock({ layers, defaultLayers, onLayersChange, selectedLayerId, defaultSelectedLayerId, onSelectedLayerIdChange, defaultTransform, layout, className, ...props }: DesignCanvasBlockProps): import("react").JSX.Element;
|
|
16
|
+
//#endregion
|
|
17
|
+
export type { DesignCanvasFill, DesignCanvasLayer, DesignCanvasLayerKind, DesignCanvasTool };
|