@deckedout/visual-editor 1.0.2 → 1.0.3

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/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # @deckedout/visual-editor
2
2
 
3
+ [![CI](https://github.com/EIP-DeckedOut-Orga/eip-visual-editor-package/actions/workflows/ci.yml/badge.svg)](https://github.com/EIP-DeckedOut-Orga/eip-visual-editor-package/actions/workflows/ci.yml)
4
+ [![npm version](https://badge.fury.io/js/@deckedout%2Fvisual-editor.svg)](https://badge.fury.io/js/@deckedout%2Fvisual-editor)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Coverage](https://img.shields.io/badge/coverage-95%25-brightgreen)]()
7
+
3
8
  A flexible, drag-and-drop visual editor built with React and Konva for creating interactive canvases with customizable elements.
4
9
 
5
10
  ## Features
@@ -12,6 +17,7 @@ A flexible, drag-and-drop visual editor built with React and Konva for creating
12
17
  - 🎭 **Multiple Modes**: Edit and preview modes
13
18
  - 📸 **Export Support**: Export canvas to JSON or image formats
14
19
  - 🎨 **Asset Management**: Built-in asset picker for images
20
+ - ✅ **Well Tested**: 95%+ code coverage with comprehensive test suite
15
21
 
16
22
  ## Installation
17
23
 
@@ -219,6 +225,52 @@ function EditorWithCustomElements() {
219
225
  }
220
226
  ```
221
227
 
228
+ ## Development
229
+
230
+ ### Running Tests
231
+
232
+ ```bash
233
+ # Run all tests
234
+ npm test
235
+
236
+ # Run tests in watch mode
237
+ npm run test:watch
238
+
239
+ # Generate coverage report
240
+ npm run test:coverage
241
+ ```
242
+
243
+ ### Building
244
+
245
+ ```bash
246
+ # Build the package
247
+ npm run build
248
+
249
+ # Type check
250
+ npm run type-check
251
+
252
+ # Lint
253
+ npm run lint
254
+ ```
255
+
256
+ ### Testing Coverage
257
+
258
+ This package maintains high test coverage:
259
+ - **95.26%** statements
260
+ - **94.2%** branches
261
+ - **93.05%** functions
262
+ - **95.77%** lines
263
+
264
+ See [TESTING.md](./TESTING.md) for detailed testing documentation.
265
+
266
+ ## Contributing
267
+
268
+ Contributions are welcome! Please ensure:
269
+ 1. All tests pass (`npm test`)
270
+ 2. Code coverage remains above 90%
271
+ 3. Code is properly linted (`npm run lint`)
272
+ 4. Types are correct (`npm run type-check`)
273
+
222
274
  ## License
223
275
 
224
276
  MIT
package/dist/index.js CHANGED
@@ -6,9 +6,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
- };
12
9
  var __export = (target, all) => {
13
10
  for (var name in all)
14
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -31,178 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
28
  ));
32
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
30
 
34
- // src/utils/editorUtils.ts
35
- var editorUtils_exports = {};
36
- __export(editorUtils_exports, {
37
- bringToFront: () => bringToFront,
38
- checkOverlap: () => checkOverlap,
39
- clamp: () => clamp,
40
- cloneElement: () => cloneElement,
41
- constrainToCanvas: () => constrainToCanvas,
42
- createElement: () => createElement,
43
- degToRad: () => degToRad,
44
- distance: () => distance,
45
- duplicateElement: () => duplicateElement,
46
- exportToJSON: () => exportToJSON,
47
- generateElementId: () => generateElementId,
48
- getElementCenter: () => getElementCenter,
49
- getMaxZIndex: () => getMaxZIndex,
50
- getRotatedBoundingBox: () => getRotatedBoundingBox,
51
- importFromJSON: () => importFromJSON,
52
- isValidCanvasExport: () => isValidCanvasExport,
53
- isValidElement: () => isValidElement,
54
- pointInRect: () => pointInRect,
55
- radToDeg: () => radToDeg,
56
- sendToBack: () => sendToBack,
57
- snapPositionToGrid: () => snapPositionToGrid,
58
- snapToGrid: () => snapToGrid,
59
- sortByZIndex: () => sortByZIndex
60
- });
61
- var import_uuid, generateElementId, createElement, cloneElement, duplicateElement, sortByZIndex, getMaxZIndex, bringToFront, sendToBack, checkOverlap, pointInRect, snapToGrid, snapPositionToGrid, clamp, constrainToCanvas, getRotatedBoundingBox, exportToJSON, importFromJSON, getElementCenter, distance, degToRad, radToDeg, isValidElement, isValidCanvasExport;
62
- var init_editorUtils = __esm({
63
- "src/utils/editorUtils.ts"() {
64
- "use strict";
65
- import_uuid = require("uuid");
66
- generateElementId = () => {
67
- return `element-${(0, import_uuid.v4)()}`;
68
- };
69
- createElement = (type, props, options) => {
70
- return {
71
- id: generateElementId(),
72
- type,
73
- position: options?.position || { x: 0, y: 0 },
74
- size: options?.size || { width: 100, height: 100 },
75
- rotation: options?.rotation || 0,
76
- opacity: options?.opacity ?? 1,
77
- zIndex: options?.zIndex || 0,
78
- visible: options?.visible ?? true,
79
- locked: options?.locked ?? false,
80
- displayName: options?.displayName,
81
- props
82
- };
83
- };
84
- cloneElement = (element) => {
85
- return {
86
- ...element,
87
- id: generateElementId(),
88
- // New ID for the clone
89
- props: { ...element.props },
90
- position: { ...element.position },
91
- size: { ...element.size }
92
- };
93
- };
94
- duplicateElement = (element, offset = { x: 20, y: 20 }) => {
95
- const cloned = cloneElement(element);
96
- return {
97
- ...cloned,
98
- position: {
99
- x: element.position.x + offset.x,
100
- y: element.position.y + offset.y
101
- },
102
- zIndex: element.zIndex + 1
103
- // Place on top
104
- };
105
- };
106
- sortByZIndex = (elements) => {
107
- return [...elements].sort((a, b) => a.zIndex - b.zIndex);
108
- };
109
- getMaxZIndex = (elements) => {
110
- if (elements.length === 0) return 0;
111
- return Math.max(...elements.map((el) => el.zIndex));
112
- };
113
- bringToFront = (elements, elementId) => {
114
- const maxZ = getMaxZIndex(elements);
115
- return elements.map((el) => el.id === elementId ? { ...el, zIndex: maxZ + 1 } : el);
116
- };
117
- sendToBack = (elements, elementId) => {
118
- const minZ = Math.min(...elements.map((el) => el.zIndex));
119
- return elements.map((el) => el.id === elementId ? { ...el, zIndex: minZ - 1 } : el);
120
- };
121
- checkOverlap = (rect1, rect2) => {
122
- return !(rect1.x + rect1.width < rect2.x || rect2.x + rect2.width < rect1.x || rect1.y + rect1.height < rect2.y || rect2.y + rect2.height < rect1.y);
123
- };
124
- pointInRect = (point, rect) => {
125
- return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
126
- };
127
- snapToGrid = (value, gridSize) => {
128
- return Math.round(value / gridSize) * gridSize;
129
- };
130
- snapPositionToGrid = (position, gridSize) => {
131
- return {
132
- x: snapToGrid(position.x, gridSize),
133
- y: snapToGrid(position.y, gridSize)
134
- };
135
- };
136
- clamp = (value, min, max) => {
137
- return Math.min(Math.max(value, min), max);
138
- };
139
- constrainToCanvas = (position, size, canvasSize) => {
140
- return {
141
- x: clamp(position.x, 0, canvasSize.width - size.width),
142
- y: clamp(position.y, 0, canvasSize.height - size.height)
143
- };
144
- };
145
- getRotatedBoundingBox = (x, y, width, height, rotation) => {
146
- const rad = rotation * Math.PI / 180;
147
- const cos = Math.abs(Math.cos(rad));
148
- const sin = Math.abs(Math.sin(rad));
149
- const newWidth = width * cos + height * sin;
150
- const newHeight = width * sin + height * cos;
151
- return {
152
- x: x - (newWidth - width) / 2,
153
- y: y - (newHeight - height) / 2,
154
- width: newWidth,
155
- height: newHeight
156
- };
157
- };
158
- exportToJSON = (data) => {
159
- return JSON.stringify(data, null, 2);
160
- };
161
- importFromJSON = (json) => {
162
- try {
163
- const data = JSON.parse(json);
164
- if (!data.width || !data.height || !Array.isArray(data.elements)) {
165
- throw new Error("Invalid canvas data structure");
166
- }
167
- const normalizedElements = data.elements.map((element) => ({
168
- ...element,
169
- visible: element.visible ?? true,
170
- locked: element.locked ?? false
171
- }));
172
- return {
173
- ...data,
174
- elements: normalizedElements
175
- };
176
- } catch (error) {
177
- throw new Error(`Failed to parse canvas data: ${error.message}`);
178
- }
179
- };
180
- getElementCenter = (element) => {
181
- return {
182
- x: element.position.x + element.size.width / 2,
183
- y: element.position.y + element.size.height / 2
184
- };
185
- };
186
- distance = (p1, p2) => {
187
- const dx = p2.x - p1.x;
188
- const dy = p2.y - p1.y;
189
- return Math.sqrt(dx * dx + dy * dy);
190
- };
191
- degToRad = (degrees) => {
192
- return degrees * Math.PI / 180;
193
- };
194
- radToDeg = (radians) => {
195
- return radians * 180 / Math.PI;
196
- };
197
- isValidElement = (element) => {
198
- return element && typeof element.id === "string" && typeof element.type === "string" && element.position && typeof element.position.x === "number" && typeof element.position.y === "number" && element.size && typeof element.size.width === "number" && typeof element.size.height === "number" && typeof element.rotation === "number" && typeof element.zIndex === "number" && element.props !== void 0;
199
- };
200
- isValidCanvasExport = (data) => {
201
- return data && typeof data.width === "number" && typeof data.height === "number" && Array.isArray(data.elements) && data.elements.every(isValidElement);
202
- };
203
- }
204
- });
205
-
206
31
  // src/index.ts
207
32
  var index_exports = {};
208
33
  __export(index_exports, {
@@ -254,6 +79,148 @@ var import_react_konva3 = require("react-konva");
254
79
 
255
80
  // src/core/useEditorState.ts
256
81
  var import_react = require("react");
82
+
83
+ // src/utils/editorUtils.ts
84
+ var import_uuid = require("uuid");
85
+ var generateElementId = () => {
86
+ return `element-${(0, import_uuid.v4)()}`;
87
+ };
88
+ var createElement = (type, props, options) => {
89
+ return {
90
+ id: generateElementId(),
91
+ type,
92
+ position: options?.position || { x: 0, y: 0 },
93
+ size: options?.size || { width: 100, height: 100 },
94
+ rotation: options?.rotation || 0,
95
+ opacity: options?.opacity ?? 1,
96
+ zIndex: options?.zIndex || 0,
97
+ visible: options?.visible ?? true,
98
+ locked: options?.locked ?? false,
99
+ displayName: options?.displayName,
100
+ props
101
+ };
102
+ };
103
+ var cloneElement = (element) => {
104
+ return {
105
+ ...element,
106
+ id: generateElementId(),
107
+ // New ID for the clone
108
+ props: { ...element.props },
109
+ position: { ...element.position },
110
+ size: { ...element.size }
111
+ };
112
+ };
113
+ var duplicateElement = (element, offset = { x: 20, y: 20 }) => {
114
+ const cloned = cloneElement(element);
115
+ return {
116
+ ...cloned,
117
+ position: {
118
+ x: element.position.x + offset.x,
119
+ y: element.position.y + offset.y
120
+ },
121
+ zIndex: element.zIndex + 1
122
+ // Place on top
123
+ };
124
+ };
125
+ var sortByZIndex = (elements) => {
126
+ return [...elements].sort((a, b) => a.zIndex - b.zIndex);
127
+ };
128
+ var getMaxZIndex = (elements) => {
129
+ if (elements.length === 0) return 0;
130
+ return Math.max(...elements.map((el) => el.zIndex));
131
+ };
132
+ var bringToFront = (elements, elementId) => {
133
+ const maxZ = getMaxZIndex(elements);
134
+ return elements.map((el) => el.id === elementId ? { ...el, zIndex: maxZ + 1 } : el);
135
+ };
136
+ var sendToBack = (elements, elementId) => {
137
+ const minZ = Math.min(...elements.map((el) => el.zIndex));
138
+ return elements.map((el) => el.id === elementId ? { ...el, zIndex: minZ - 1 } : el);
139
+ };
140
+ var checkOverlap = (rect1, rect2) => {
141
+ return !(rect1.x + rect1.width < rect2.x || rect2.x + rect2.width < rect1.x || rect1.y + rect1.height < rect2.y || rect2.y + rect2.height < rect1.y);
142
+ };
143
+ var pointInRect = (point, rect) => {
144
+ return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
145
+ };
146
+ var snapToGrid = (value, gridSize) => {
147
+ return Math.round(value / gridSize) * gridSize;
148
+ };
149
+ var snapPositionToGrid = (position, gridSize) => {
150
+ return {
151
+ x: snapToGrid(position.x, gridSize),
152
+ y: snapToGrid(position.y, gridSize)
153
+ };
154
+ };
155
+ var clamp = (value, min, max) => {
156
+ return Math.min(Math.max(value, min), max);
157
+ };
158
+ var constrainToCanvas = (position, size, canvasSize) => {
159
+ return {
160
+ x: clamp(position.x, 0, canvasSize.width - size.width),
161
+ y: clamp(position.y, 0, canvasSize.height - size.height)
162
+ };
163
+ };
164
+ var getRotatedBoundingBox = (x, y, width, height, rotation) => {
165
+ const rad = rotation * Math.PI / 180;
166
+ const cos = Math.abs(Math.cos(rad));
167
+ const sin = Math.abs(Math.sin(rad));
168
+ const newWidth = width * cos + height * sin;
169
+ const newHeight = width * sin + height * cos;
170
+ return {
171
+ x: x - (newWidth - width) / 2,
172
+ y: y - (newHeight - height) / 2,
173
+ width: newWidth,
174
+ height: newHeight
175
+ };
176
+ };
177
+ var exportToJSON = (data) => {
178
+ return JSON.stringify(data, null, 2);
179
+ };
180
+ var importFromJSON = (json) => {
181
+ try {
182
+ const data = JSON.parse(json);
183
+ if (!data.width || !data.height || !Array.isArray(data.elements)) {
184
+ throw new Error("Invalid canvas data structure");
185
+ }
186
+ const normalizedElements = data.elements.map((element) => ({
187
+ ...element,
188
+ visible: element.visible ?? true,
189
+ locked: element.locked ?? false
190
+ }));
191
+ return {
192
+ ...data,
193
+ elements: normalizedElements
194
+ };
195
+ } catch (error) {
196
+ throw new Error(`Failed to parse canvas data: ${error.message}`);
197
+ }
198
+ };
199
+ var getElementCenter = (element) => {
200
+ return {
201
+ x: element.position.x + element.size.width / 2,
202
+ y: element.position.y + element.size.height / 2
203
+ };
204
+ };
205
+ var distance = (p1, p2) => {
206
+ const dx = p2.x - p1.x;
207
+ const dy = p2.y - p1.y;
208
+ return Math.sqrt(dx * dx + dy * dy);
209
+ };
210
+ var degToRad = (degrees) => {
211
+ return degrees * Math.PI / 180;
212
+ };
213
+ var radToDeg = (radians) => {
214
+ return radians * 180 / Math.PI;
215
+ };
216
+ var isValidElement = (element) => {
217
+ return element && typeof element.id === "string" && typeof element.type === "string" && element.position && typeof element.position.x === "number" && typeof element.position.y === "number" && element.size && typeof element.size.width === "number" && typeof element.size.height === "number" && typeof element.rotation === "number" && typeof element.zIndex === "number" && element.props !== void 0;
218
+ };
219
+ var isValidCanvasExport = (data) => {
220
+ return data && typeof data.width === "number" && typeof data.height === "number" && Array.isArray(data.elements) && data.elements.every(isValidElement);
221
+ };
222
+
223
+ // src/core/useEditorState.ts
257
224
  var createInitialState = (mode) => ({
258
225
  elements: [],
259
226
  selectedElementId: null,
@@ -527,8 +494,7 @@ var useEditorState = (initialMode = null) => {
527
494
  (id = null, offset = { x: 20, y: 20 }) => {
528
495
  const elementToDuplicate = id ? state.elements.find((el) => el.id === id) : getSelectedElement();
529
496
  if (!elementToDuplicate) return;
530
- const { duplicateElement: duplicateUtil } = (init_editorUtils(), __toCommonJS(editorUtils_exports));
531
- const duplicated = duplicateUtil(elementToDuplicate, offset);
497
+ const duplicated = duplicateElement(elementToDuplicate, offset);
532
498
  addElement(duplicated);
533
499
  },
534
500
  [state.elements, getSelectedElement, addElement]
@@ -536,10 +502,9 @@ var useEditorState = (initialMode = null) => {
536
502
  const pasteElement = (0, import_react.useCallback)(
537
503
  (copiedElement, offset = { x: 20, y: 20 }) => {
538
504
  if (!copiedElement) return;
539
- const { generateElementId: generateElementId2 } = (init_editorUtils(), __toCommonJS(editorUtils_exports));
540
505
  const pasted = {
541
506
  ...copiedElement,
542
- id: generateElementId2(),
507
+ id: generateElementId(),
543
508
  props: { ...copiedElement.props },
544
509
  position: {
545
510
  x: copiedElement.position.x + offset.x,
@@ -2090,7 +2055,7 @@ var Inspector = ({
2090
2055
  function renderField(field, props, editingValues, onChange, onColorChange, mode) {
2091
2056
  const value = editingValues[field.name] ?? props[field.name] ?? field.defaultValue;
2092
2057
  switch (field.type) {
2093
- case "custom":
2058
+ case "custom": {
2094
2059
  if (!field.customRenderer) {
2095
2060
  console.error(`Custom field "${field.name}" has no customRenderer defined`);
2096
2061
  return null;
@@ -2106,7 +2071,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2106
2071
  mode
2107
2072
  }
2108
2073
  ) }, field.name);
2109
- case "string":
2074
+ }
2075
+ case "string": {
2110
2076
  const isMultiline = field.name === "content" || field.name === "text";
2111
2077
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2112
2078
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: field.name, className: "text-xs", children: field.label }),
@@ -2130,7 +2096,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2130
2096
  ),
2131
2097
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2132
2098
  ] }, field.name);
2133
- case "number":
2099
+ }
2100
+ case "number": {
2134
2101
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2135
2102
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: field.name, className: "text-xs", children: field.label }),
2136
2103
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -2148,7 +2115,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2148
2115
  ),
2149
2116
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2150
2117
  ] }, field.name);
2151
- case "color":
2118
+ }
2119
+ case "color": {
2152
2120
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2153
2121
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: field.name, className: "text-xs", children: field.label }),
2154
2122
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -2163,7 +2131,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2163
2131
  ),
2164
2132
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2165
2133
  ] }, field.name);
2166
- case "select":
2134
+ }
2135
+ case "select": {
2167
2136
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2168
2137
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: field.name, className: "text-xs", children: field.label }),
2169
2138
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
@@ -2179,7 +2148,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2179
2148
  ),
2180
2149
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2181
2150
  ] }, field.name);
2182
- case "boolean":
2151
+ }
2152
+ case "boolean": {
2183
2153
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-start space-x-2", children: [
2184
2154
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2185
2155
  Checkbox,
@@ -2195,7 +2165,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2195
2165
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground", children: field.description })
2196
2166
  ] })
2197
2167
  ] }, field.name);
2198
- case "slider":
2168
+ }
2169
+ case "slider": {
2199
2170
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2200
2171
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between mb-2", children: [
2201
2172
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { className: "text-xs", children: field.label }),
@@ -2214,7 +2185,8 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2214
2185
  ),
2215
2186
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2216
2187
  ] }, field.name);
2217
- case "image":
2188
+ }
2189
+ case "image": {
2218
2190
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2219
2191
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Label, { htmlFor: field.name, className: "text-xs", children: field.label }),
2220
2192
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -2229,6 +2201,7 @@ function renderField(field, props, editingValues, onChange, onColorChange, mode)
2229
2201
  ),
2230
2202
  field.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: field.description })
2231
2203
  ] }, field.name);
2204
+ }
2232
2205
  default:
2233
2206
  return null;
2234
2207
  }
@@ -3571,12 +3544,8 @@ var Canvas = ({
3571
3544
  );
3572
3545
  };
3573
3546
 
3574
- // src/components/VisualEditorWorkspace.tsx
3575
- init_editorUtils();
3576
-
3577
3547
  // src/components/Toolbar.tsx
3578
3548
  var import_lucide_react8 = require("lucide-react");
3579
- init_editorUtils();
3580
3549
  var import_jsx_runtime25 = require("react/jsx-runtime");
3581
3550
  var Toolbar = ({
3582
3551
  api,
@@ -3989,9 +3958,6 @@ var AssetPicker = ({
3989
3958
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScrollArea, { className: "flex-1", children: filteredAssets.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "grid grid-cols-3 gap-2 p-3", children: filteredAssets.map((asset) => assetRenderer(asset)) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex items-center justify-center h-32 text-sm text-muted-foreground", children: searchQuery ? "No assets found" : "No assets available" }) })
3990
3959
  ] });
3991
3960
  };
3992
-
3993
- // src/index.ts
3994
- init_editorUtils();
3995
3961
  // Annotate the CommonJS export names for ESM import in node:
3996
3962
  0 && (module.exports = {
3997
3963
  AssetPicker,