@ctrl-ui/react 0.8.5 → 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.
Files changed (152) hide show
  1. package/dist/action-bar.js +1 -1
  2. package/dist/activity.js +1 -1
  3. package/dist/blocks/coding-agent.js +16 -19
  4. package/dist/blocks/design-canvas-data.d.ts +32 -0
  5. package/dist/blocks/design-canvas-data.js +100 -0
  6. package/dist/blocks/design-canvas-inspector.d.ts +8 -0
  7. package/dist/blocks/design-canvas-inspector.js +238 -0
  8. package/dist/blocks/design-canvas.d.ts +17 -0
  9. package/dist/blocks/design-canvas.js +346 -0
  10. package/dist/blocks/file-explorer.js +2 -2
  11. package/dist/blocks/settings.js +2 -2
  12. package/dist/chat-composer-attachment.d.ts +9 -3
  13. package/dist/chat-composer-attachment.js +27 -10
  14. package/dist/chat-composer-editor.js +20 -4
  15. package/dist/chat-composer.d.ts +1 -1
  16. package/dist/chat-composer.js +4 -3
  17. package/dist/chat-layout.js +32 -19
  18. package/dist/context.js +1 -1
  19. package/dist/dynamic-notification.js +1 -1
  20. package/dist/environment-variables.js +1 -1
  21. package/dist/filter-bar/context.d.ts +32 -0
  22. package/dist/filter-bar/context.js +11 -0
  23. package/dist/filter-bar/editor.d.ts +14 -0
  24. package/dist/filter-bar/editor.js +204 -0
  25. package/dist/filter-bar/model.d.ts +9 -0
  26. package/dist/filter-bar/model.js +48 -0
  27. package/dist/filter-bar/motion.d.ts +10 -0
  28. package/dist/filter-bar/motion.js +84 -0
  29. package/dist/filter-bar/parts.d.ts +19 -0
  30. package/dist/filter-bar/parts.js +233 -0
  31. package/dist/filter-bar/types.d.ts +53 -0
  32. package/dist/filter-bar/types.js +0 -0
  33. package/dist/filter-bar.d.ts +27 -0
  34. package/dist/filter-bar.js +304 -0
  35. package/dist/hooks/use-chat-composer.d.ts +3 -1
  36. package/dist/hooks/use-chat-composer.js +2 -2
  37. package/dist/hooks/use-dropzone.d.ts +7 -4
  38. package/dist/hooks/use-dropzone.js +34 -3
  39. package/dist/inline-attachment.js +8 -14
  40. package/dist/inline-citation.js +1 -1
  41. package/dist/knob-contracts/chat-layout-knobs.d.ts +1 -1
  42. package/dist/knob-contracts/chat-layout-knobs.js +2 -1
  43. package/dist/knob-contracts/choice-knobs.d.ts +1 -1
  44. package/dist/knob-contracts/choice-knobs.js +1 -0
  45. package/dist/knob-contracts/collapsible-knobs.d.ts +1 -1
  46. package/dist/knob-contracts/collapsible-knobs.js +1 -1
  47. package/dist/knob-contracts/filter-bar-knobs.d.ts +4 -0
  48. package/dist/knob-contracts/filter-bar-knobs.js +16 -0
  49. package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
  50. package/dist/knob-contracts/infinite-canvas-knobs.js +3 -0
  51. package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
  52. package/dist/knob-contracts/page-layout-knobs.js +4 -1
  53. package/dist/knob-contracts/popup-knobs.d.ts +1 -1
  54. package/dist/knob-contracts/popup-knobs.js +1 -0
  55. package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
  56. package/dist/knob-contracts/table-of-contents-knobs.js +3 -5
  57. package/dist/lib/phone-input-format.js +1 -1
  58. package/dist/markdown-block.js +11 -7
  59. package/dist/scripts/contrast-eval.js +5 -4
  60. package/dist/styles/index.css +5 -4
  61. package/dist/styles/recipes/button-group.css +1 -1
  62. package/dist/styles/recipes/button.css +2 -2
  63. package/dist/styles/recipes/chat-composer.css +14 -6
  64. package/dist/styles/recipes/chat-layout.css +29 -2
  65. package/dist/styles/recipes/choice.css +10 -3
  66. package/dist/styles/recipes/code-diff.css +16 -4
  67. package/dist/styles/recipes/code.css +11 -5
  68. package/dist/styles/recipes/collapsible.css +37 -0
  69. package/dist/styles/recipes/color-picker.css +12 -2
  70. package/dist/styles/recipes/dockable-panel.css +11 -3
  71. package/dist/styles/recipes/field-parts.css +62 -0
  72. package/dist/styles/recipes/field.css +28 -6
  73. package/dist/styles/recipes/filter-bar.css +174 -0
  74. package/dist/styles/recipes/infinite-canvas.css +51 -3
  75. package/dist/styles/recipes/inline-attachment.css +6 -1
  76. package/dist/styles/recipes/page-layout.css +36 -2
  77. package/dist/styles/recipes/pagination.css +1 -1
  78. package/dist/styles/recipes/popup-controls.css +16 -0
  79. package/dist/styles/recipes/popup-drawer.css +34 -32
  80. package/dist/styles/recipes/popup-lists.css +11 -2
  81. package/dist/styles/recipes/popup.css +10 -12
  82. package/dist/styles/recipes/range.css +1 -1
  83. package/dist/styles/recipes/resizable.css +34 -0
  84. package/dist/styles/recipes/spinner.css +4 -0
  85. package/dist/styles/recipes/table-of-contents.css +42 -42
  86. package/dist/styles/recipes/tabs.css +21 -0
  87. package/dist/styles/recipes/track-highlight.css +2 -1
  88. package/dist/styles/recipes/transcript-divider.css +2 -2
  89. package/dist/styles/theme.css +250 -91
  90. package/dist/ui/alert-dialog.js +1 -1
  91. package/dist/ui/autocomplete.js +5 -1
  92. package/dist/ui/button.js +2 -2
  93. package/dist/ui/checkbox-group.js +1 -1
  94. package/dist/ui/code-diff.js +1 -1
  95. package/dist/ui/code.js +3 -3
  96. package/dist/ui/collapsible.js +1 -1
  97. package/dist/ui/color-picker.js +2 -2
  98. package/dist/ui/combobox-disabled-selection.d.ts +1 -1
  99. package/dist/ui/combobox-disabled-selection.js +2 -1
  100. package/dist/ui/combobox.d.ts +5 -23
  101. package/dist/ui/combobox.js +26 -14
  102. package/dist/ui/command.js +9 -1
  103. package/dist/ui/context-menu.js +1 -1
  104. package/dist/ui/dialog.js +1 -1
  105. package/dist/ui/dockable-panel.js +18 -10
  106. package/dist/ui/drawer.d.ts +7 -4
  107. package/dist/ui/drawer.js +36 -23
  108. package/dist/ui/dropdown-menu.js +1 -1
  109. package/dist/ui/dropzone.d.ts +3 -1
  110. package/dist/ui/dropzone.js +3 -1
  111. package/dist/ui/field.js +1 -1
  112. package/dist/ui/hover-card.js +1 -1
  113. package/dist/ui/infinite-canvas.d.ts +11 -0
  114. package/dist/ui/infinite-canvas.js +82 -7
  115. package/dist/ui/input-group.d.ts +2 -1
  116. package/dist/ui/input-group.js +12 -3
  117. package/dist/ui/input.js +9 -0
  118. package/dist/ui/item.js +1 -1
  119. package/dist/ui/markdown-elements.js +11 -8
  120. package/dist/ui/menubar.js +1 -1
  121. package/dist/ui/morphing-panel.js +1 -1
  122. package/dist/ui/navigation-menu.js +1 -1
  123. package/dist/ui/number-field.d.ts +1 -1
  124. package/dist/ui/number-field.js +13 -2
  125. package/dist/ui/phone-input.js +2 -2
  126. package/dist/ui/popover.js +1 -1
  127. package/dist/ui/radio-group.d.ts +1 -0
  128. package/dist/ui/radio-group.js +11 -1
  129. package/dist/ui/resizable.d.ts +18 -1
  130. package/dist/ui/resizable.js +127 -7
  131. package/dist/ui/responsive-dialog.js +6 -3
  132. package/dist/ui/rich-tooltip.js +1 -1
  133. package/dist/ui/scroll-area.d.ts +4 -1
  134. package/dist/ui/scroll-area.js +2 -1
  135. package/dist/ui/select.d.ts +2 -1
  136. package/dist/ui/select.js +58 -33
  137. package/dist/ui/sheet.js +1 -1
  138. package/dist/ui/sidebar-menu.js +1 -1
  139. package/dist/ui/sidebar-provider.js +2 -2
  140. package/dist/ui/sidebar-resize-rail.js +1 -1
  141. package/dist/ui/sidebar.js +1 -1
  142. package/dist/ui/table-of-contents.d.ts +4 -3
  143. package/dist/ui/table-of-contents.js +126 -47
  144. package/dist/ui/table.js +11 -7
  145. package/dist/ui/toast.js +1 -1
  146. package/dist/ui/toggle.d.ts +1 -1
  147. package/dist/ui/toggle.js +2 -1
  148. package/dist/ui/tooltip.js +1 -1
  149. package/dist/ui/tree.js +1 -1
  150. package/dist/ui/trigger-menu.js +7 -3
  151. package/dist/user-ask.js +1 -1
  152. package/package.json +1 -1
@@ -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
- className: "flex h-[var(--control-h-sm)] w-full items-center gap-2 rounded-[var(--radius-popup-item)] px-2 text-caption font-medium hover:bg-foreground/6",
137
- children: [
138
- /* @__PURE__ */ jsx(ChevronRightIcon, {
139
- className: "size-3.5 shrink-0 text-muted-foreground",
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
- }), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenu, {
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: cn("h-full min-h-0 max-w-none", 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 };