@btst/stack 1.10.0 → 1.11.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/packages/ui/src/components/minimal-tiptap/utils.cjs +15 -11
- package/dist/packages/ui/src/components/minimal-tiptap/utils.mjs +15 -11
- package/dist/packages/ui/src/components/ui-builder/index.cjs +9 -7
- package/dist/packages/ui/src/components/ui-builder/index.mjs +9 -7
- package/dist/packages/ui/src/components/ui-builder/internal/canvas/auto-frame.cjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/canvas/auto-frame.mjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/components/add-component-popover.cjs +228 -48
- package/dist/packages/ui/src/components/ui-builder/internal/components/add-component-popover.mjs +228 -48
- package/dist/packages/ui/src/components/ui-builder/internal/components/element-selector.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/components/element-selector.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/components/error-fallback.cjs +4 -2
- package/dist/packages/ui/src/components/ui-builder/internal/components/error-fallback.mjs +4 -2
- package/dist/packages/ui/src/components/ui-builder/internal/components/multi-select.cjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/components/multi-select.mjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/draggable-new-component.cjs +67 -0
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/draggable-new-component.mjs +62 -0
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/drop-zone.cjs +181 -37
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/drop-zone.mjs +181 -38
- package/dist/packages/ui/src/components/ui-builder/internal/editor-panel.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/editor-panel.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-group-control.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-group-control.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-item-control.cjs +9 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-item-control.mjs +9 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/iconname-field.cjs +3 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/iconname-field.mjs +3 -2
- package/dist/packages/ui/src/components/ui-builder/internal/layers-panel.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/layers-panel.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/props-panel.cjs +17 -5
- package/dist/packages/ui/src/components/ui-builder/internal/props-panel.mjs +17 -5
- package/dist/packages/ui/src/components/ui-builder/internal/utils/render-utils.cjs +70 -16
- package/dist/packages/ui/src/components/ui-builder/internal/utils/render-utils.mjs +73 -20
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context-colission-utils.cjs +14 -9
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context-colission-utils.mjs +14 -9
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context.cjs +38 -10
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context.mjs +35 -11
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-contexts.cjs +1 -0
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-contexts.mjs +1 -0
- package/dist/packages/ui/src/lib/ui-builder/context/drag-overlay.cjs +7 -4
- package/dist/packages/ui/src/lib/ui-builder/context/drag-overlay.mjs +7 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-auto-scroll.cjs +4 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-auto-scroll.mjs +4 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-dnd-event-handlers.cjs +53 -16
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-dnd-event-handlers.mjs +53 -16
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-drop-validation.cjs +23 -7
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-drop-validation.mjs +23 -7
- package/dist/packages/ui/src/lib/ui-builder/registry/form-field-overrides.cjs +110 -11
- package/dist/packages/ui/src/lib/ui-builder/registry/form-field-overrides.mjs +111 -13
- package/dist/packages/ui/src/lib/ui-builder/store/editor-store.cjs +3 -2
- package/dist/packages/ui/src/lib/ui-builder/store/editor-store.mjs +3 -2
- package/dist/packages/ui/src/lib/ui-builder/store/layer-store.cjs +53 -7
- package/dist/packages/ui/src/lib/ui-builder/store/layer-store.mjs +54 -8
- package/dist/packages/ui/src/lib/ui-builder/store/layer-utils.cjs +4 -3
- package/dist/packages/ui/src/lib/ui-builder/store/layer-utils.mjs +4 -3
- package/dist/packages/ui/src/lib/ui-builder/utils/variable-resolver.cjs +12 -0
- package/dist/packages/ui/src/lib/ui-builder/utils/variable-resolver.mjs +12 -1
- package/dist/plugins/ui-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.cts +2 -2
- package/dist/plugins/ui-builder/client/hooks/index.d.mts +2 -2
- package/dist/plugins/ui-builder/client/hooks/index.d.ts +2 -2
- package/dist/plugins/ui-builder/client/index.d.cts +17 -7
- package/dist/plugins/ui-builder/client/index.d.mts +17 -7
- package/dist/plugins/ui-builder/client/index.d.ts +17 -7
- package/dist/plugins/ui-builder/index.d.cts +2 -2
- package/dist/plugins/ui-builder/index.d.mts +2 -2
- package/dist/plugins/ui-builder/index.d.ts +2 -2
- package/dist/shared/{stack.BSM2cgoq.d.cts → stack.BYysGdHl.d.cts} +1 -1
- package/dist/shared/{stack.CqfZWfjJ.d.cts → stack.BdJFrdyt.d.cts} +8 -2
- package/dist/shared/{stack.e1FN86dE.d.mts → stack.ChVuHi5e.d.mts} +8 -2
- package/dist/shared/{stack.CLtOoAqF.d.mts → stack.DYCFcnkL.d.mts} +1 -1
- package/dist/shared/{stack.MMntCVZZ.d.ts → stack.EhM4pmtN.d.ts} +8 -2
- package/dist/shared/{stack.BD1m-4yB.d.ts → stack.kFbDspnF.d.ts} +1 -1
- package/package.json +1 -1
package/dist/packages/ui/src/components/ui-builder/internal/components/add-component-popover.mjs
CHANGED
|
@@ -8,25 +8,48 @@ import { useEditorStore } from '../../../../lib/ui-builder/store/editor-store.mj
|
|
|
8
8
|
import { cn } from '../../../../lib/utils.mjs';
|
|
9
9
|
import LayerRenderer from '../../layer-renderer.mjs';
|
|
10
10
|
import { createComponentLayer } from '../../../../lib/ui-builder/store/layer-utils.mjs';
|
|
11
|
+
import { DraggableNewComponent } from '../dnd/draggable-new-component.mjs';
|
|
11
12
|
|
|
12
13
|
const fallback = /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-muted rounded border animate-pulse" });
|
|
13
14
|
const previewLayerCache = /* @__PURE__ */ new Map();
|
|
15
|
+
function isValidChildOfParent(componentRegistry, componentType, parentType) {
|
|
16
|
+
const def = componentRegistry[componentType];
|
|
17
|
+
if (!def?.childOf) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (!parentType) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return def.childOf.includes(parentType);
|
|
24
|
+
}
|
|
25
|
+
function isChildOnlyComponent(componentRegistry, componentType) {
|
|
26
|
+
const def = componentRegistry[componentType];
|
|
27
|
+
return Boolean(def?.childOf);
|
|
28
|
+
}
|
|
14
29
|
function AddComponentsPopover({
|
|
15
30
|
className,
|
|
16
31
|
children,
|
|
17
32
|
addPosition,
|
|
18
33
|
parentLayerId,
|
|
19
34
|
onOpenChange,
|
|
35
|
+
enableDragToCanvas = false,
|
|
20
36
|
onChange
|
|
21
37
|
}) {
|
|
22
38
|
const [open, setOpen] = React__default.useState(false);
|
|
39
|
+
const [activeView, setActiveView] = React__default.useState("components");
|
|
23
40
|
const componentRegistry = useEditorStore((state) => state.registry);
|
|
41
|
+
const blocks = useEditorStore((state) => state.blocks);
|
|
42
|
+
const findLayerById = useLayerStore((state) => state.findLayerById);
|
|
43
|
+
const parentLayerType = useMemo(() => {
|
|
44
|
+
const parentLayer = findLayerById(parentLayerId);
|
|
45
|
+
return parentLayer?.type;
|
|
46
|
+
}, [findLayerById, parentLayerId]);
|
|
24
47
|
const groupedOptions = useMemo(() => {
|
|
25
|
-
const componentOptions = Object.keys(componentRegistry).map((name) => ({
|
|
48
|
+
const componentOptions = Object.keys(componentRegistry).filter((name) => isValidChildOfParent(componentRegistry, name, parentLayerType)).map((name) => ({
|
|
26
49
|
value: name,
|
|
27
50
|
label: name,
|
|
28
51
|
type: "component",
|
|
29
|
-
from: componentRegistry[name]
|
|
52
|
+
from: componentRegistry[name]?.from
|
|
30
53
|
}));
|
|
31
54
|
return componentOptions.reduce(
|
|
32
55
|
(acc, option) => {
|
|
@@ -35,16 +58,34 @@ function AddComponentsPopover({
|
|
|
35
58
|
if (!acc[group]) {
|
|
36
59
|
acc[group] = [];
|
|
37
60
|
}
|
|
38
|
-
acc[group]
|
|
61
|
+
acc[group]?.push(option);
|
|
39
62
|
return acc;
|
|
40
63
|
},
|
|
41
64
|
{}
|
|
42
65
|
);
|
|
43
|
-
}, [componentRegistry]);
|
|
66
|
+
}, [componentRegistry, parentLayerType]);
|
|
44
67
|
const categories = useMemo(() => {
|
|
45
68
|
return Object.keys(groupedOptions);
|
|
46
69
|
}, [groupedOptions]);
|
|
70
|
+
const groupedBlocks = useMemo(() => {
|
|
71
|
+
if (!blocks) return {};
|
|
72
|
+
return Object.values(blocks).reduce(
|
|
73
|
+
(acc, block) => {
|
|
74
|
+
if (!acc[block.category]) {
|
|
75
|
+
acc[block.category] = [];
|
|
76
|
+
}
|
|
77
|
+
acc[block.category]?.push(block);
|
|
78
|
+
return acc;
|
|
79
|
+
},
|
|
80
|
+
{}
|
|
81
|
+
);
|
|
82
|
+
}, [blocks]);
|
|
83
|
+
const blockCategories = useMemo(() => {
|
|
84
|
+
return Object.keys(groupedBlocks);
|
|
85
|
+
}, [groupedBlocks]);
|
|
86
|
+
const hasBlocks = blocks && Object.keys(blocks).length > 0;
|
|
47
87
|
const addComponentLayer = useLayerStore((state) => state.addComponentLayer);
|
|
88
|
+
const addLayerDirect = useLayerStore((state) => state.addLayerDirect);
|
|
48
89
|
const handleSelect = React__default.useCallback(
|
|
49
90
|
(currentValue) => {
|
|
50
91
|
if (onChange) {
|
|
@@ -69,6 +110,15 @@ function AddComponentsPopover({
|
|
|
69
110
|
onChange
|
|
70
111
|
]
|
|
71
112
|
);
|
|
113
|
+
const handleBlockSelect = React__default.useCallback(
|
|
114
|
+
(block) => {
|
|
115
|
+
const clonedTemplate = cloneLayerWithNewIds(block.template);
|
|
116
|
+
addLayerDirect(clonedTemplate, parentLayerId, addPosition);
|
|
117
|
+
setOpen(false);
|
|
118
|
+
onOpenChange?.(false);
|
|
119
|
+
},
|
|
120
|
+
[addLayerDirect, parentLayerId, addPosition, onOpenChange]
|
|
121
|
+
);
|
|
72
122
|
const handleOpenChange = useCallback(
|
|
73
123
|
(open2) => {
|
|
74
124
|
setOpen(open2);
|
|
@@ -76,63 +126,180 @@ function AddComponentsPopover({
|
|
|
76
126
|
},
|
|
77
127
|
[onOpenChange]
|
|
78
128
|
);
|
|
129
|
+
const handleDragStart = useCallback(() => {
|
|
130
|
+
setOpen(false);
|
|
131
|
+
onOpenChange?.(false);
|
|
132
|
+
}, [onOpenChange]);
|
|
79
133
|
const defaultTab = categories[0] || "";
|
|
134
|
+
const defaultBlockCategory = blockCategories[0] || "";
|
|
80
135
|
return /* @__PURE__ */ jsx("div", { className: cn("relative flex justify-center", className), children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
|
|
81
136
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children }),
|
|
82
|
-
/* @__PURE__ */
|
|
83
|
-
|
|
84
|
-
/* @__PURE__ */ jsx(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
137
|
+
/* @__PURE__ */ jsxs(PopoverContent, { className: "w-[320px] p-0", align: "start", children: [
|
|
138
|
+
hasBlocks && /* @__PURE__ */ jsxs("div", { className: "flex border-b", children: [
|
|
139
|
+
/* @__PURE__ */ jsx(
|
|
140
|
+
"button",
|
|
141
|
+
{
|
|
142
|
+
className: cn(
|
|
143
|
+
"flex-1 px-4 py-2 text-sm font-medium transition-colors",
|
|
144
|
+
activeView === "components" ? "bg-background border-b-2 border-primary" : "bg-muted/50 text-muted-foreground hover:text-foreground"
|
|
145
|
+
),
|
|
146
|
+
onClick: () => setActiveView("components"),
|
|
147
|
+
children: "Components"
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
/* @__PURE__ */ jsx(
|
|
151
|
+
"button",
|
|
90
152
|
{
|
|
91
|
-
|
|
92
|
-
|
|
153
|
+
className: cn(
|
|
154
|
+
"flex-1 px-4 py-2 text-sm font-medium transition-colors",
|
|
155
|
+
activeView === "blocks" ? "bg-background border-b-2 border-primary" : "bg-muted/50 text-muted-foreground hover:text-foreground"
|
|
156
|
+
),
|
|
157
|
+
onClick: () => setActiveView("blocks"),
|
|
158
|
+
children: "Blocks"
|
|
93
159
|
}
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
160
|
+
)
|
|
161
|
+
] }),
|
|
162
|
+
activeView === "components" && categories.length > 0 ? /* @__PURE__ */ jsxs(Tabs, { defaultValue: defaultTab, className: "w-full", children: [
|
|
163
|
+
/* @__PURE__ */ jsx(TabsList, { className: cn(categories.length > 1 ? "h-14 w-full rounded-none border-b flex flex-row overflow-x-scroll justify-start" : "hidden"), children: categories.map((category) => /* @__PURE__ */ jsxs(TabsTrigger, { value: category, className: "flex flex-col justify-start items-start overflow-hidden px-2 py-1 min-w-24 min-h-11 shrink-0", children: [
|
|
164
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm", children: formatCategoryName(category) }),
|
|
165
|
+
/* @__PURE__ */ jsx("div", { className: "w-full min-h-[12px] text-[8px] leading-[9px] text-left text-muted-foreground text-wrap", children: category })
|
|
166
|
+
] }, category)) }),
|
|
167
|
+
categories.map((category) => /* @__PURE__ */ jsx(TabsContent, { value: category, className: "m-0", children: /* @__PURE__ */ jsxs(Command, { className: "border-0", children: [
|
|
168
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center px-3 w-full [&>div:first-child]:w-full", children: /* @__PURE__ */ jsx(
|
|
169
|
+
CommandInput,
|
|
99
170
|
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
171
|
+
placeholder: "Find components",
|
|
172
|
+
className: "border-0 focus:ring-0 w-full"
|
|
173
|
+
}
|
|
174
|
+
) }),
|
|
175
|
+
/* @__PURE__ */ jsxs(CommandList, { className: "max-h-[250px]", children: [
|
|
176
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: "No components found" }),
|
|
177
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: groupedOptions[category]?.map((component) => /* @__PURE__ */ jsx(
|
|
178
|
+
GroupedComponentItem,
|
|
179
|
+
{
|
|
180
|
+
component,
|
|
181
|
+
onClick: handleSelect,
|
|
182
|
+
onDragStart: handleDragStart,
|
|
183
|
+
enableDrag: enableDragToCanvas
|
|
184
|
+
},
|
|
185
|
+
component.value
|
|
186
|
+
)) })
|
|
187
|
+
] })
|
|
188
|
+
] }) }, category))
|
|
189
|
+
] }) : activeView === "components" ? /* @__PURE__ */ jsxs(Command, { children: [
|
|
190
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Add component" }),
|
|
191
|
+
/* @__PURE__ */ jsx(CommandList, { children: /* @__PURE__ */ jsx(CommandEmpty, { children: "No components found" }) })
|
|
192
|
+
] }) : null,
|
|
193
|
+
activeView === "blocks" && hasBlocks && /* @__PURE__ */ jsxs(Tabs, { defaultValue: defaultBlockCategory, className: "w-full", children: [
|
|
194
|
+
/* @__PURE__ */ jsx(TabsList, { className: "h-14 w-full rounded-none border-b flex flex-row overflow-x-scroll justify-start", children: blockCategories.map((category) => /* @__PURE__ */ jsxs(TabsTrigger, { value: category, className: "flex flex-col justify-start items-start overflow-hidden px-2 py-1 min-w-24 min-h-11 shrink-0", children: [
|
|
195
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm", children: formatCategoryName(category) }),
|
|
196
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full min-h-[12px] text-[8px] leading-[9px] text-left text-muted-foreground", children: [
|
|
197
|
+
groupedBlocks[category]?.length,
|
|
198
|
+
" blocks"
|
|
199
|
+
] })
|
|
200
|
+
] }, category)) }),
|
|
201
|
+
blockCategories.map((category) => /* @__PURE__ */ jsx(TabsContent, { value: category, className: "m-0", children: /* @__PURE__ */ jsxs(Command, { className: "border-0", children: [
|
|
202
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center px-3 w-full [&>div:first-child]:w-full", children: /* @__PURE__ */ jsx(
|
|
203
|
+
CommandInput,
|
|
204
|
+
{
|
|
205
|
+
placeholder: "Find blocks",
|
|
206
|
+
className: "border-0 focus:ring-0 w-full"
|
|
207
|
+
}
|
|
208
|
+
) }),
|
|
209
|
+
/* @__PURE__ */ jsxs(CommandList, { className: "max-h-[250px]", children: [
|
|
210
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: "No blocks found" }),
|
|
211
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: groupedBlocks[category]?.map((block) => /* @__PURE__ */ jsx(
|
|
212
|
+
BlockItem,
|
|
213
|
+
{
|
|
214
|
+
block,
|
|
215
|
+
onClick: handleBlockSelect
|
|
216
|
+
},
|
|
217
|
+
block.name
|
|
218
|
+
)) })
|
|
219
|
+
] })
|
|
220
|
+
] }) }, category))
|
|
221
|
+
] })
|
|
222
|
+
] })
|
|
111
223
|
] }) });
|
|
112
224
|
}
|
|
225
|
+
function cloneLayerWithNewIds(layer) {
|
|
226
|
+
const newId = generateUniqueId();
|
|
227
|
+
let newChildren;
|
|
228
|
+
if (Array.isArray(layer.children)) {
|
|
229
|
+
newChildren = layer.children.map((child) => cloneLayerWithNewIds(child));
|
|
230
|
+
} else if (typeof layer.children === "string") {
|
|
231
|
+
newChildren = layer.children;
|
|
232
|
+
} else if (layer.children && typeof layer.children === "object" && "__variableRef" in layer.children) {
|
|
233
|
+
newChildren = layer.children;
|
|
234
|
+
} else {
|
|
235
|
+
newChildren = layer.children;
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
...layer,
|
|
239
|
+
id: newId,
|
|
240
|
+
children: newChildren
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function generateUniqueId() {
|
|
244
|
+
return Math.random().toString(36).substring(2, 9);
|
|
245
|
+
}
|
|
246
|
+
const BlockItem = memo(({
|
|
247
|
+
block,
|
|
248
|
+
onClick
|
|
249
|
+
}) => {
|
|
250
|
+
const handleSelect = useCallback(() => {
|
|
251
|
+
onClick(block);
|
|
252
|
+
}, [onClick, block]);
|
|
253
|
+
return /* @__PURE__ */ jsxs(
|
|
254
|
+
CommandItem,
|
|
255
|
+
{
|
|
256
|
+
onSelect: handleSelect,
|
|
257
|
+
className: "cursor-pointer flex flex-col items-start gap-1 py-3",
|
|
258
|
+
children: [
|
|
259
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium", children: formatBlockName(block.name) }),
|
|
260
|
+
block.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground line-clamp-2", children: block.description })
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
BlockItem.displayName = "BlockItem";
|
|
266
|
+
function formatBlockName(name) {
|
|
267
|
+
return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
268
|
+
}
|
|
113
269
|
const GroupedComponentItem = memo(({
|
|
114
270
|
component,
|
|
115
|
-
onClick
|
|
271
|
+
onClick,
|
|
272
|
+
onDragStart,
|
|
273
|
+
enableDrag = false
|
|
116
274
|
}) => {
|
|
117
275
|
const handleSelect = useCallback(() => {
|
|
118
276
|
onClick(component.value);
|
|
119
277
|
}, [onClick, component.value]);
|
|
120
278
|
const componentRegistry = useEditorStore((state) => state.registry);
|
|
121
|
-
|
|
279
|
+
const content = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
280
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 w-10 h-6 overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
281
|
+
LazyComponentPreview,
|
|
282
|
+
{
|
|
283
|
+
componentType: component.value,
|
|
284
|
+
componentRegistry
|
|
285
|
+
}
|
|
286
|
+
) }),
|
|
287
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center flex-1 min-w-0", children: /* @__PURE__ */ jsx("span", { className: "truncate", children: component.label }) })
|
|
288
|
+
] });
|
|
289
|
+
return /* @__PURE__ */ jsx(
|
|
122
290
|
CommandItem,
|
|
123
291
|
{
|
|
124
292
|
onSelect: handleSelect,
|
|
125
|
-
className: "cursor-pointer flex items-center gap-
|
|
126
|
-
children:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
]
|
|
293
|
+
className: "cursor-pointer flex items-center gap-2 py-2",
|
|
294
|
+
children: enableDrag ? /* @__PURE__ */ jsx(
|
|
295
|
+
DraggableNewComponent,
|
|
296
|
+
{
|
|
297
|
+
componentType: component.value,
|
|
298
|
+
onDragStart,
|
|
299
|
+
className: "flex-1",
|
|
300
|
+
children: content
|
|
301
|
+
}
|
|
302
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex-1", children: content })
|
|
136
303
|
},
|
|
137
304
|
component.value
|
|
138
305
|
);
|
|
@@ -150,7 +317,7 @@ const LazyComponentPreview = memo(({
|
|
|
150
317
|
let timeoutId = null;
|
|
151
318
|
const observer = new IntersectionObserver(
|
|
152
319
|
([entry]) => {
|
|
153
|
-
if (entry
|
|
320
|
+
if (entry?.isIntersecting) {
|
|
154
321
|
timeoutId = setTimeout(() => setShouldLoad(true), 50);
|
|
155
322
|
}
|
|
156
323
|
},
|
|
@@ -173,12 +340,20 @@ const LazyComponentPreview = memo(({
|
|
|
173
340
|
) }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-muted rounded border" }) });
|
|
174
341
|
});
|
|
175
342
|
LazyComponentPreview.displayName = "LazyComponentPreview";
|
|
343
|
+
const ChildOnlyPlaceholder = memo(({ componentType }) => {
|
|
344
|
+
const initials = componentType.replace(/([A-Z])/g, " $1").trim().split(" ").map((word) => word[0]).slice(0, 2).join("");
|
|
345
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-muted/50 rounded border border-dashed flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-[8px] font-medium text-muted-foreground", children: initials }) });
|
|
346
|
+
});
|
|
347
|
+
ChildOnlyPlaceholder.displayName = "ChildOnlyPlaceholder";
|
|
176
348
|
const ComponentPreview = memo(({
|
|
177
349
|
componentType,
|
|
178
350
|
componentRegistry
|
|
179
351
|
}) => {
|
|
180
|
-
const
|
|
352
|
+
const isChildOnly = isChildOnlyComponent(componentRegistry, componentType);
|
|
181
353
|
const previewLayer = useMemo(() => {
|
|
354
|
+
if (isChildOnly) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
182
357
|
const cacheKey = `${componentType}-${JSON.stringify(componentRegistry[componentType]?.schema)}`;
|
|
183
358
|
if (previewLayerCache.has(cacheKey)) {
|
|
184
359
|
return previewLayerCache.get(cacheKey);
|
|
@@ -194,15 +369,20 @@ const ComponentPreview = memo(({
|
|
|
194
369
|
console.warn(`Failed to create preview for component ${componentType}:`, error);
|
|
195
370
|
return null;
|
|
196
371
|
}
|
|
197
|
-
}, [componentType, componentRegistry]);
|
|
372
|
+
}, [componentType, componentRegistry, isChildOnly]);
|
|
373
|
+
if (isChildOnly) {
|
|
374
|
+
return /* @__PURE__ */ jsx(ChildOnlyPlaceholder, { componentType });
|
|
375
|
+
}
|
|
198
376
|
if (!previewLayer) {
|
|
199
377
|
return /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-muted rounded border" });
|
|
200
378
|
}
|
|
379
|
+
const style = { width: "200%", height: "200%" };
|
|
201
380
|
return /* @__PURE__ */ jsx(
|
|
202
381
|
"div",
|
|
203
382
|
{
|
|
204
|
-
className: "w-full h-full bg-background rounded border overflow-hidden transform scale-50 origin-top-left",
|
|
383
|
+
className: "w-full h-full bg-background rounded border overflow-hidden transform scale-50 origin-top-left pointer-events-none",
|
|
205
384
|
style,
|
|
385
|
+
inert: true,
|
|
206
386
|
children: /* @__PURE__ */ jsx(
|
|
207
387
|
LayerRenderer,
|
|
208
388
|
{
|
|
@@ -218,7 +398,7 @@ ComponentPreview.displayName = "ComponentPreview";
|
|
|
218
398
|
function formatCategoryName(name) {
|
|
219
399
|
const words = name.split("/");
|
|
220
400
|
const lastWord = words[words.length - 1];
|
|
221
|
-
return lastWord
|
|
401
|
+
return lastWord?.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase()) ?? "";
|
|
222
402
|
}
|
|
223
403
|
|
|
224
404
|
export { AddComponentsPopover };
|
|
@@ -96,7 +96,7 @@ const ElementSelector = ({
|
|
|
96
96
|
ref: refs.setReference,
|
|
97
97
|
className: utils.cn(
|
|
98
98
|
"fixed box-border hover:border-blue-300 hover:border-2 hover:bg-blue-300/20 hover:shadow-md hover:shadow-blue-500/20 cursor-default",
|
|
99
|
-
isBeingDragged ? "border-2 border-
|
|
99
|
+
isBeingDragged ? "border-2 border-green-500 border-dashed shadow-lg opacity-70 bg-orange-50/20" : isSelected ? "border-2 border-blue-500 hover:border-blue-500 hover:bg-transparent hover:shadow-none" : ""
|
|
100
100
|
),
|
|
101
101
|
style: overlayStyle
|
|
102
102
|
}
|
|
@@ -94,7 +94,7 @@ const ElementSelector = ({
|
|
|
94
94
|
ref: refs.setReference,
|
|
95
95
|
className: cn(
|
|
96
96
|
"fixed box-border hover:border-blue-300 hover:border-2 hover:bg-blue-300/20 hover:shadow-md hover:shadow-blue-500/20 cursor-default",
|
|
97
|
-
isBeingDragged ? "border-2 border-
|
|
97
|
+
isBeingDragged ? "border-2 border-green-500 border-dashed shadow-lg opacity-70 bg-orange-50/20" : isSelected ? "border-2 border-blue-500 hover:border-blue-500 hover:bg-transparent hover:shadow-none" : ""
|
|
98
98
|
),
|
|
99
99
|
style: overlayStyle
|
|
100
100
|
}
|
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
const jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
|
|
5
5
|
function ErrorFallback({ error }) {
|
|
6
|
+
const errorMessage = error == null ? void 0 : error instanceof Error ? error.message : String(error);
|
|
7
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
6
8
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border border-red-500 bg-red-100 text-red-700 rounded flex-grow w-full", children: [
|
|
7
9
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-bold mb-2", children: "Component Error" }),
|
|
8
10
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
9
11
|
"Error: ",
|
|
10
|
-
|
|
12
|
+
errorMessage || "Unknown error"
|
|
11
13
|
] }),
|
|
12
14
|
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "mt-2", children: [
|
|
13
15
|
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer", children: "Stack trace" }),
|
|
14
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-2 text-xs whitespace-pre-wrap", children:
|
|
16
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-2 text-xs whitespace-pre-wrap", children: errorStack })
|
|
15
17
|
] })
|
|
16
18
|
] });
|
|
17
19
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
3
|
function ErrorFallback({ error }) {
|
|
4
|
+
const errorMessage = error == null ? void 0 : error instanceof Error ? error.message : String(error);
|
|
5
|
+
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
4
6
|
return /* @__PURE__ */ jsxs("div", { className: "p-4 border border-red-500 bg-red-100 text-red-700 rounded flex-grow w-full", children: [
|
|
5
7
|
/* @__PURE__ */ jsx("h3", { className: "font-bold mb-2", children: "Component Error" }),
|
|
6
8
|
/* @__PURE__ */ jsxs("p", { children: [
|
|
7
9
|
"Error: ",
|
|
8
|
-
|
|
10
|
+
errorMessage || "Unknown error"
|
|
9
11
|
] }),
|
|
10
12
|
/* @__PURE__ */ jsxs("details", { className: "mt-2", children: [
|
|
11
13
|
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer", children: "Stack trace" }),
|
|
12
|
-
/* @__PURE__ */ jsx("pre", { className: "mt-2 text-xs whitespace-pre-wrap", children:
|
|
14
|
+
/* @__PURE__ */ jsx("pre", { className: "mt-2 text-xs whitespace-pre-wrap", children: errorStack })
|
|
13
15
|
] })
|
|
14
16
|
] });
|
|
15
17
|
}
|
|
@@ -40,7 +40,10 @@ function transToGroupOption(options, groupBy) {
|
|
|
40
40
|
if (!groupOption[key]) {
|
|
41
41
|
groupOption[key] = [];
|
|
42
42
|
}
|
|
43
|
-
groupOption[key]
|
|
43
|
+
const group = groupOption[key];
|
|
44
|
+
if (group) {
|
|
45
|
+
group.push(option);
|
|
46
|
+
}
|
|
44
47
|
});
|
|
45
48
|
return groupOption;
|
|
46
49
|
}
|
|
@@ -145,8 +148,8 @@ const MultipleSelector = React__namespace.forwardRef(
|
|
|
145
148
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
146
149
|
if (input.value === "" && selected.length > 0) {
|
|
147
150
|
const lastSelectOption = selected[selected.length - 1];
|
|
148
|
-
if (!lastSelectOption.fixed) {
|
|
149
|
-
handleUnselect(
|
|
151
|
+
if (lastSelectOption && !lastSelectOption.fixed) {
|
|
152
|
+
handleUnselect(lastSelectOption);
|
|
150
153
|
}
|
|
151
154
|
}
|
|
152
155
|
}
|
|
@@ -25,7 +25,10 @@ function transToGroupOption(options, groupBy) {
|
|
|
25
25
|
if (!groupOption[key]) {
|
|
26
26
|
groupOption[key] = [];
|
|
27
27
|
}
|
|
28
|
-
groupOption[key]
|
|
28
|
+
const group = groupOption[key];
|
|
29
|
+
if (group) {
|
|
30
|
+
group.push(option);
|
|
31
|
+
}
|
|
29
32
|
});
|
|
30
33
|
return groupOption;
|
|
31
34
|
}
|
|
@@ -130,8 +133,8 @@ const MultipleSelector = React.forwardRef(
|
|
|
130
133
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
131
134
|
if (input.value === "" && selected.length > 0) {
|
|
132
135
|
const lastSelectOption = selected[selected.length - 1];
|
|
133
|
-
if (!lastSelectOption.fixed) {
|
|
134
|
-
handleUnselect(
|
|
136
|
+
if (lastSelectOption && !lastSelectOption.fixed) {
|
|
137
|
+
handleUnselect(lastSelectOption);
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
const React = require('react');
|
|
7
|
+
const core_esm = require('../../../../../../../node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.cjs');
|
|
8
|
+
const LucideIcons = require('lucide-react');
|
|
9
|
+
const utils = require('../../../../lib/utils.cjs');
|
|
10
|
+
|
|
11
|
+
const DraggableNewComponent = ({
|
|
12
|
+
componentType,
|
|
13
|
+
children,
|
|
14
|
+
onDragStart,
|
|
15
|
+
className
|
|
16
|
+
}) => {
|
|
17
|
+
const {
|
|
18
|
+
attributes,
|
|
19
|
+
listeners,
|
|
20
|
+
setNodeRef,
|
|
21
|
+
setActivatorNodeRef,
|
|
22
|
+
isDragging
|
|
23
|
+
} = core_esm.useDraggable({
|
|
24
|
+
id: `new-component-${componentType}`,
|
|
25
|
+
data: {
|
|
26
|
+
type: "new-component",
|
|
27
|
+
componentType
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
if (isDragging && onDragStart) {
|
|
32
|
+
onDragStart();
|
|
33
|
+
}
|
|
34
|
+
}, [isDragging, onDragStart]);
|
|
35
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36
|
+
"div",
|
|
37
|
+
{
|
|
38
|
+
ref: setNodeRef,
|
|
39
|
+
className: utils.cn(
|
|
40
|
+
"flex items-center gap-1",
|
|
41
|
+
isDragging && "opacity-50",
|
|
42
|
+
className
|
|
43
|
+
),
|
|
44
|
+
...attributes,
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
ref: setActivatorNodeRef,
|
|
50
|
+
...listeners,
|
|
51
|
+
className: utils.cn(
|
|
52
|
+
"flex-shrink-0 cursor-grab active:cursor-grabbing p-1 -ml-1",
|
|
53
|
+
"text-muted-foreground hover:text-foreground transition-colors",
|
|
54
|
+
"rounded hover:bg-muted/50"
|
|
55
|
+
),
|
|
56
|
+
"aria-label": `Drag ${componentType} to canvas`,
|
|
57
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.GripVertical, { className: "h-4 w-4" })
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children })
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
exports.DraggableNewComponent = DraggableNewComponent;
|
|
67
|
+
exports.default = DraggableNewComponent;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useDraggable } from '../../../../../../../node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.mjs';
|
|
4
|
+
import { GripVertical } from 'lucide-react';
|
|
5
|
+
import { cn } from '../../../../lib/utils.mjs';
|
|
6
|
+
|
|
7
|
+
const DraggableNewComponent = ({
|
|
8
|
+
componentType,
|
|
9
|
+
children,
|
|
10
|
+
onDragStart,
|
|
11
|
+
className
|
|
12
|
+
}) => {
|
|
13
|
+
const {
|
|
14
|
+
attributes,
|
|
15
|
+
listeners,
|
|
16
|
+
setNodeRef,
|
|
17
|
+
setActivatorNodeRef,
|
|
18
|
+
isDragging
|
|
19
|
+
} = useDraggable({
|
|
20
|
+
id: `new-component-${componentType}`,
|
|
21
|
+
data: {
|
|
22
|
+
type: "new-component",
|
|
23
|
+
componentType
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (isDragging && onDragStart) {
|
|
28
|
+
onDragStart();
|
|
29
|
+
}
|
|
30
|
+
}, [isDragging, onDragStart]);
|
|
31
|
+
return /* @__PURE__ */ jsxs(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
ref: setNodeRef,
|
|
35
|
+
className: cn(
|
|
36
|
+
"flex items-center gap-1",
|
|
37
|
+
isDragging && "opacity-50",
|
|
38
|
+
className
|
|
39
|
+
),
|
|
40
|
+
...attributes,
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ jsx(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
ref: setActivatorNodeRef,
|
|
46
|
+
...listeners,
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex-shrink-0 cursor-grab active:cursor-grabbing p-1 -ml-1",
|
|
49
|
+
"text-muted-foreground hover:text-foreground transition-colors",
|
|
50
|
+
"rounded hover:bg-muted/50"
|
|
51
|
+
),
|
|
52
|
+
"aria-label": `Drag ${componentType} to canvas`,
|
|
53
|
+
children: /* @__PURE__ */ jsx(GripVertical, { className: "h-4 w-4" })
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { DraggableNewComponent, DraggableNewComponent as default };
|