@bolttech/template-editor 0.0.2 → 0.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/package.json CHANGED
@@ -1,30 +1,28 @@
1
1
  {
2
2
  "name": "@bolttech/template-editor",
3
3
  "private": false,
4
- "version": "0.0.2",
4
+ "version": "0.0.3",
5
5
  "type": "module",
6
- "main": "./dist/template-editor.umd.js",
7
- "module": "./dist/template-editor.es.js",
6
+ "main": "./dist/template-editor.cjs",
7
+ "module": "./dist/template-editor.mjs",
8
8
  "types": "./dist/template-editor.d.ts",
9
9
  "files": [
10
10
  "dist"
11
11
  ],
12
+ "sideEffects": [
13
+ "*.css"
14
+ ],
12
15
  "exports": {
13
16
  ".": {
14
- "import": {
15
- "types": "./dist/template-editor.d.ts",
16
- "default": "./dist/template-editor.es.js"
17
- },
18
- "require": {
19
- "types": "./dist/template-editor.d.ts",
20
- "default": "./dist/template-editor.umd.js"
21
- }
17
+ "types": "./dist/template-editor.d.ts",
18
+ "import": "./dist/template-editor.mjs",
19
+ "require": "./dist/template-editor.cjs"
22
20
  },
23
21
  "./style.css": "./dist/template-editor.css"
24
22
  },
25
23
  "engines": {
26
- "node": ">=22.18",
27
- "npm": ">=10.9"
24
+ "node": ">=18.x",
25
+ "npm": ">=9.x"
28
26
  },
29
27
  "scripts": {
30
28
  "start": "node server",
@@ -47,7 +45,7 @@
47
45
  "prepare": "npx -y husky"
48
46
  },
49
47
  "dependencies": {
50
- "@bolttech/templating-sdk": "^0.1.2",
48
+ "@bolttech/templating-sdk": "^0.1.3",
51
49
  "@craftjs/core": "^0.2.12",
52
50
  "@craftjs/utils": "^0.2.5",
53
51
  "@monaco-editor/react": "^4.7.0",
@@ -56,6 +54,7 @@
56
54
  "htmlparser2": "^10.0.0",
57
55
  "re-resizable": "^6.11.2",
58
56
  "react-icons": "^5.5.0",
57
+ "react-resizable": "^3.0.5",
59
58
  "react-shadow": "^20.6.0",
60
59
  "sirv": "^3.0.2",
61
60
  "vite": "^7.1.7"
@@ -73,6 +72,7 @@
73
72
  "@types/htmlparser2": "^3.10.7",
74
73
  "@types/react": "^19.1.8",
75
74
  "@types/react-dom": "^19.1.9",
75
+ "@types/react-resizable": "^3.0.8",
76
76
  "@vitejs/plugin-react": "^5.0.2",
77
77
  "@vitest/coverage-v8": "^3.2.4",
78
78
  "autoprefixer": "^10.4.21",
@@ -1,433 +0,0 @@
1
- import { j as e } from "./index-_5hb_xRw.js";
2
- import { useState as h, useEffect as L } from "react";
3
- import { FiX as U, FiLink as V, FiUpload as S, FiCode as _, FiCheck as F, FiCopy as P } from "react-icons/fi";
4
- const O = ({
5
- name: p,
6
- value: t,
7
- path: y,
8
- onSelect: i,
9
- isSelected: x
10
- }) => {
11
- const m = typeof t == "object" && t !== null && !Array.isArray(t), g = Array.isArray(t), b = () => t === null ? "null" : t === void 0 ? "undefined" : typeof t == "string" ? `"${t}"` : typeof t == "number" || typeof t == "boolean" ? String(t) : g ? `Array(${t.length})` : m ? `Object(${Object.keys(t).length})` : String(t), u = () => t === null ? "null" : t === void 0 ? "undefined" : typeof t == "string" ? "string" : typeof t == "number" ? "number" : typeof t == "boolean" ? "boolean" : g ? "array" : m ? "object" : typeof t;
12
- return /* @__PURE__ */ e.jsxs(
13
- "button",
14
- {
15
- onClick: () => i(y, t),
16
- className: `flex min-w-[120px] flex-col items-center gap-1 rounded-none border border-[#e8e7ee] p-3 transition-all duration-200 ${x ? "border-[#30aab3] bg-[#170f4f] text-white" : "bg-white text-[#170f4f] hover:border-[#30aab3] hover:bg-gray-50"}`,
17
- children: [
18
- /* @__PURE__ */ e.jsx("div", { className: "text-xs font-medium", children: p }),
19
- /* @__PURE__ */ e.jsx(
20
- "div",
21
- {
22
- className: `text-xs ${u() === "string" ? "text-green-600" : u() === "number" ? "text-blue-600" : u() === "boolean" ? "text-purple-600" : u() === "null" ? "text-gray-500" : "text-orange-600"} ${x ? "text-white" : ""}`,
23
- children: b()
24
- }
25
- ),
26
- /* @__PURE__ */ e.jsxs(
27
- "div",
28
- {
29
- className: `text-xs ${x ? "text-gray-300" : "text-gray-400"}`,
30
- children: [
31
- "(",
32
- u(),
33
- ")"
34
- ]
35
- }
36
- )
37
- ]
38
- }
39
- );
40
- }, E = ({ data: p, onPathSelect: t }) => {
41
- const [y, i] = h([]), [x, m] = h(null), [g, b] = h(!1), u = (r, n) => n.reduce((a, s) => {
42
- if (a != null) {
43
- if (s.startsWith("[") && s.endsWith("]")) {
44
- const l = parseInt(s.slice(1, -1), 10);
45
- return a[l];
46
- }
47
- return a[s];
48
- }
49
- }, r), j = (() => {
50
- const r = [];
51
- let n = [], a = p;
52
- r.push({ path: [], value: p, isRoot: !0 });
53
- for (const s of y)
54
- n = [...n, s], a = u(p, n), a != null && typeof a == "object" && r.push({
55
- path: [...n],
56
- value: a,
57
- isRoot: !1
58
- });
59
- return r;
60
- })(), N = (r, n, a) => {
61
- if (typeof a == "object" && a !== null && (i((s) => [...s.slice(0, r), n]), t)) {
62
- const s = [...j[r].path, n];
63
- t(s.join("."));
64
- }
65
- }, v = (r, n, a) => {
66
- if (typeof a != "object" || a === null) {
67
- if (m({ path: [...j[r].path, n], value: a }), t) {
68
- const s = [...j[r].path, n];
69
- t(s.join("."));
70
- }
71
- } else
72
- m(null);
73
- }, w = (r, n) => {
74
- const a = r.value;
75
- return r.isRoot ? /* @__PURE__ */ e.jsx("div", { className: "flex min-w-[140px] flex-col gap-2", children: Object.entries(p).map(([s, l]) => /* @__PURE__ */ e.jsx(
76
- O,
77
- {
78
- name: s,
79
- value: l,
80
- path: s,
81
- onSelect: (C, c) => typeof c == "object" && c !== null ? N(0, s, c) : v(0, s, c),
82
- isSelected: y.length === 0
83
- },
84
- s
85
- )) }, n) : Array.isArray(a) ? /* @__PURE__ */ e.jsx("div", { className: "flex min-w-[140px] flex-col gap-2", children: a.map((s, l) => /* @__PURE__ */ e.jsx(
86
- O,
87
- {
88
- name: `[${l}]`,
89
- value: s,
90
- path: `[${l}]`,
91
- onSelect: (C, c) => typeof c == "object" && c !== null ? N(n, `[${l}]`, c) : v(n, `[${l}]`, c),
92
- isSelected: !1
93
- },
94
- l
95
- )) }, n) : typeof a == "object" && a !== null ? /* @__PURE__ */ e.jsx("div", { className: "flex min-w-[140px] flex-col gap-2", children: Object.entries(a).map(([s, l]) => /* @__PURE__ */ e.jsx(
96
- O,
97
- {
98
- name: s,
99
- value: l,
100
- path: s,
101
- onSelect: (C, c) => typeof c == "object" && c !== null ? N(n, s, c) : v(n, s, c),
102
- isSelected: !1
103
- },
104
- s
105
- )) }, n) : null;
106
- };
107
- return /* @__PURE__ */ e.jsxs("div", { className: "overflow-x-auto rounded-none border border-[#e8e7ee] bg-white", children: [
108
- /* @__PURE__ */ e.jsx("div", { className: "border-b border-[#e8e7ee] bg-gray-50 px-4 py-2", children: /* @__PURE__ */ e.jsx("h3", { className: "text-sm font-medium text-[#170f4f]", children: "Data Structure" }) }),
109
- /* @__PURE__ */ e.jsxs("div", { className: "flex gap-6 overflow-x-auto p-4", children: [
110
- j.map((r, n) => w(r, n)),
111
- x && /* @__PURE__ */ e.jsx("div", { className: "flex min-w-[180px] flex-col gap-2", children: /* @__PURE__ */ e.jsxs("div", { className: "mt-2 rounded-none border border-[#e8e7ee] bg-gray-50 p-3", children: [
112
- /* @__PURE__ */ e.jsx("h4", { className: "mb-1 text-xs font-medium text-gray-600", children: "Selected Value" }),
113
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
114
- /* @__PURE__ */ e.jsx("span", { className: "font-medium", children: "Path:" }),
115
- " ",
116
- x.path.join("."),
117
- /* @__PURE__ */ e.jsx(
118
- "button",
119
- {
120
- className: "ml-1 text-gray-400 hover:text-gray-600",
121
- onClick: () => {
122
- navigator.clipboard.writeText(
123
- x.path.join(".")
124
- ), b(!0), setTimeout(() => b(!1), 2e3);
125
- },
126
- title: "Copy path",
127
- children: g ? /* @__PURE__ */ e.jsx(F, { size: 14 }) : /* @__PURE__ */ e.jsx(P, { size: 14 })
128
- }
129
- )
130
- ] }),
131
- /* @__PURE__ */ e.jsxs("div", { className: "text-sm", children: [
132
- /* @__PURE__ */ e.jsx("span", { className: "font-medium", children: "Value:" }),
133
- " ",
134
- String(x.value)
135
- ] }),
136
- /* @__PURE__ */ e.jsxs("div", { className: "text-sm", children: [
137
- /* @__PURE__ */ e.jsx("span", { className: "font-medium", children: "Type:" }),
138
- " ",
139
- typeof x.value
140
- ] })
141
- ] }) })
142
- ] })
143
- ] });
144
- }, H = ({
145
- isOpen: p,
146
- onClose: t,
147
- onDataImport: y
148
- }) => {
149
- const [i, x] = h("url"), [m, g] = h(""), [b, u] = h(""), [f, j] = h(""), [N, v] = h(!1), [w, r] = h(""), [n, a] = h(!1), [s, l] = h(null);
150
- L(() => {
151
- if (p) {
152
- const o = localStorage.getItem("bolttech_datasource");
153
- if (o)
154
- try {
155
- const d = JSON.parse(o);
156
- d && typeof d == "object" && d.data && (l(d.data), d.url && u(d.url));
157
- } catch {
158
- }
159
- }
160
- }, [p]);
161
- const C = (o) => {
162
- const d = o.target.files?.[0];
163
- if (!d) return;
164
- if (!d.name.endsWith(".json")) {
165
- r("Please select a JSON file");
166
- return;
167
- }
168
- const J = new FileReader();
169
- J.onload = (D) => {
170
- try {
171
- const k = D.target?.result, R = JSON.parse(k);
172
- g(k), l(R), r("");
173
- } catch {
174
- r("Invalid JSON file"), g(""), l(null);
175
- }
176
- }, J.readAsText(d);
177
- }, c = async () => {
178
- if (!b.trim()) {
179
- r("Please enter a URL");
180
- return;
181
- }
182
- v(!0), r("");
183
- try {
184
- const o = await fetch(b);
185
- if (!o.ok)
186
- throw new Error("Failed to fetch data");
187
- const d = await o.json();
188
- j(JSON.stringify(d, null, 2)), l(d), r("");
189
- } catch {
190
- r("Failed to fetch data from URL");
191
- } finally {
192
- v(!1);
193
- }
194
- }, $ = (o) => {
195
- j(o), r("");
196
- try {
197
- if (o.trim()) {
198
- const d = JSON.parse(o);
199
- l(d);
200
- } else
201
- l(null);
202
- } catch {
203
- r("Invalid JSON format"), l(null);
204
- }
205
- }, z = () => {
206
- let o;
207
- try {
208
- switch (i) {
209
- case "file":
210
- if (!m) {
211
- r("Please select a file");
212
- return;
213
- }
214
- o = JSON.parse(m);
215
- break;
216
- case "url":
217
- if (!f) {
218
- r("Please fetch data from URL first");
219
- return;
220
- }
221
- o = JSON.parse(f);
222
- break;
223
- case "code":
224
- if (!f.trim()) {
225
- r("Please enter JSON data");
226
- return;
227
- }
228
- o = JSON.parse(f);
229
- break;
230
- }
231
- i === "url" ? localStorage.setItem(
232
- "bolttech_datasource",
233
- JSON.stringify({ from: i, data: o, url: b })
234
- ) : localStorage.setItem(
235
- "bolttech_datasource",
236
- JSON.stringify({ from: i, data: o })
237
- ), y(o), t();
238
- } catch {
239
- r("Invalid JSON data");
240
- }
241
- }, A = () => {
242
- navigator.clipboard.writeText(f), a(!0), setTimeout(() => a(!1), 2e3);
243
- }, T = () => {
244
- try {
245
- return f.trim() ? (JSON.parse(f), !0) : !1;
246
- } catch {
247
- return !1;
248
- }
249
- };
250
- return p ? /* @__PURE__ */ e.jsx(
251
- "div",
252
- {
253
- className: "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50",
254
- onClick: (o) => {
255
- o.target === o.currentTarget && t();
256
- },
257
- children: /* @__PURE__ */ e.jsxs("div", { className: "flex h-[90vh] w-full max-w-6xl flex-col rounded-none bg-white shadow-xl", children: [
258
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center justify-between border-b border-[#e8e7ee] bg-white p-6", children: [
259
- /* @__PURE__ */ e.jsx("h2", { className: "text-lg font-bold tracking-wide text-[#170f4f]", children: "DataSource" }),
260
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
261
- /* @__PURE__ */ e.jsx(
262
- "button",
263
- {
264
- onClick: () => {
265
- localStorage.removeItem("bolttech_datasource"), l(null), g(""), u(""), j("");
266
- },
267
- className: "rounded-none p-2 text-gray-400 transition-colors duration-200 hover:bg-red-50 hover:text-red-600",
268
- title: "Clean Data",
269
- children: "🧹"
270
- }
271
- ),
272
- /* @__PURE__ */ e.jsx(
273
- "button",
274
- {
275
- onClick: t,
276
- className: "rounded-none p-2 text-gray-400 transition-colors duration-200 hover:bg-gray-50 hover:text-gray-600",
277
- children: /* @__PURE__ */ e.jsx(U, { size: 18 })
278
- }
279
- )
280
- ] })
281
- ] }),
282
- /* @__PURE__ */ e.jsx("div", { className: "max-h-[42vh] overflow-y-auto border-b border-[#e8e7ee] px-6 py-4", children: /* @__PURE__ */ e.jsx(E, { data: { root: s || {} } }) }),
283
- /* @__PURE__ */ e.jsxs("div", { className: "flex border-b border-[#e8e7ee]", children: [
284
- /* @__PURE__ */ e.jsxs(
285
- "button",
286
- {
287
- onClick: () => x("url"),
288
- className: `flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors duration-200 ${i === "url" ? "border-b-2 border-[#30aab3] text-[#170f4f]" : "text-gray-500 hover:text-[#170f4f]"}`,
289
- children: [
290
- /* @__PURE__ */ e.jsx(V, { size: 16 }),
291
- "URL"
292
- ]
293
- }
294
- ),
295
- /* @__PURE__ */ e.jsxs(
296
- "button",
297
- {
298
- onClick: () => x("file"),
299
- className: `flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors duration-200 ${i === "file" ? "border-b-2 border-[#30aab3] text-[#170f4f]" : "text-gray-500 hover:text-[#170f4f]"}`,
300
- children: [
301
- /* @__PURE__ */ e.jsx(S, { size: 16 }),
302
- "Import File"
303
- ]
304
- }
305
- ),
306
- /* @__PURE__ */ e.jsxs(
307
- "button",
308
- {
309
- onClick: () => x("code"),
310
- className: `flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors duration-200 ${i === "code" ? "border-b-2 border-[#30aab3] text-[#170f4f]" : "text-gray-500 hover:text-[#170f4f]"}`,
311
- children: [
312
- /* @__PURE__ */ e.jsx(_, { size: 16 }),
313
- "Custom Code"
314
- ]
315
- }
316
- )
317
- ] }),
318
- /* @__PURE__ */ e.jsxs("div", { className: "flex-1 overflow-hidden p-6", children: [
319
- i === "code" && /* @__PURE__ */ e.jsxs("div", { className: "flex h-full flex-col", children: [
320
- /* @__PURE__ */ e.jsx("div", { className: "mb-4", children: /* @__PURE__ */ e.jsx("p", { className: "mb-1 text-sm text-gray-500", children: "Enter your JSON data below" }) }),
321
- /* @__PURE__ */ e.jsxs("div", { className: "flex-1 overflow-hidden rounded-none bg-gray-900", children: [
322
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center justify-between border-b border-gray-700 bg-gray-800 px-4 py-2", children: [
323
- /* @__PURE__ */ e.jsx("span", { className: "text-sm font-medium text-gray-300", children: "JSON Editor" }),
324
- f && /* @__PURE__ */ e.jsxs(
325
- "button",
326
- {
327
- onClick: A,
328
- className: "flex items-center gap-1 text-xs text-gray-400 hover:text-gray-300",
329
- children: [
330
- n ? /* @__PURE__ */ e.jsx(F, { size: 12 }) : /* @__PURE__ */ e.jsx(P, { size: 12 }),
331
- n ? "Copied!" : "Copy"
332
- ]
333
- }
334
- )
335
- ] }),
336
- /* @__PURE__ */ e.jsx("div", { className: "h-full overflow-auto pb-8", children: /* @__PURE__ */ e.jsx(
337
- "textarea",
338
- {
339
- value: f,
340
- onChange: (o) => $(o.target.value),
341
- placeholder: '{"name": "John", "age": 30, "city": "New York"}',
342
- className: "h-full w-full resize-none border-none bg-transparent p-4 font-mono text-sm text-gray-300 outline-none"
343
- }
344
- ) })
345
- ] })
346
- ] }),
347
- i === "url" && /* @__PURE__ */ e.jsx("div", { className: "bte:flex bte:h-full bte:flex-col", children: /* @__PURE__ */ e.jsxs("div", { className: "bte:mb-4", children: [
348
- /* @__PURE__ */ e.jsx("label", { className: "mb-2 block text-sm font-medium text-gray-700", children: "JSON URL" }),
349
- /* @__PURE__ */ e.jsxs("div", { className: "flex gap-2", children: [
350
- /* @__PURE__ */ e.jsx(
351
- "input",
352
- {
353
- type: "url",
354
- value: b,
355
- onChange: (o) => u(o.target.value),
356
- placeholder: "https://api.example.com/data.json",
357
- className: "flex-1 rounded-none border border-[#e8e7ee] px-3 py-2 focus:outline-none focus:ring-2 focus:ring-[#30aab3]"
358
- }
359
- ),
360
- /* @__PURE__ */ e.jsx(
361
- "button",
362
- {
363
- onClick: c,
364
- disabled: N || !b.trim(),
365
- className: "rounded-none bg-[#170f4f] px-4 py-2 text-white transition-colors duration-200 hover:bg-[#30aab3] disabled:cursor-not-allowed disabled:opacity-50",
366
- children: N ? "Loading..." : "Fetch"
367
- }
368
- )
369
- ] })
370
- ] }) }),
371
- i === "file" && /* @__PURE__ */ e.jsxs("div", { className: "bte:flex bte:h-full bte:flex-col", children: [
372
- /* @__PURE__ */ e.jsxs("div", { className: "bte:mb-4", children: [
373
- /* @__PURE__ */ e.jsx("label", { className: "mb-2 block text-sm font-medium text-gray-700", children: "Select JSON File" }),
374
- /* @__PURE__ */ e.jsxs("div", { className: "rounded-none border-2 border-dashed border-[#e8e7ee] p-8 text-center transition-colors duration-200 hover:border-[#30aab3]", children: [
375
- /* @__PURE__ */ e.jsx(
376
- "input",
377
- {
378
- type: "file",
379
- accept: ".json",
380
- onChange: C,
381
- className: "hidden",
382
- id: "file-upload"
383
- }
384
- ),
385
- /* @__PURE__ */ e.jsxs(
386
- "label",
387
- {
388
- htmlFor: "file-upload",
389
- className: "flex cursor-pointer flex-col items-center",
390
- children: [
391
- /* @__PURE__ */ e.jsx(S, { size: 48, className: "mb-4 text-gray-400" }),
392
- /* @__PURE__ */ e.jsx(S, { size: 48, className: "mb-4 text-gray-400" }),
393
- /* @__PURE__ */ e.jsx("span", { className: "text-lg font-medium text-gray-700", children: "Click to upload JSON file" }),
394
- /* @__PURE__ */ e.jsx("span", { className: "mt-1 text-sm text-gray-500", children: "or drag and drop" })
395
- ]
396
- }
397
- )
398
- ] })
399
- ] }),
400
- m && /* @__PURE__ */ e.jsxs("div", { className: "flex-1 overflow-hidden rounded-none bg-gray-900", children: [
401
- /* @__PURE__ */ e.jsx("div", { className: "flex items-center justify-between border-b border-gray-700 bg-gray-800 px-4 py-2", children: /* @__PURE__ */ e.jsx("span", { className: "text-sm font-medium text-gray-300", children: "File Preview" }) }),
402
- /* @__PURE__ */ e.jsx("div", { className: "h-32 overflow-auto", children: /* @__PURE__ */ e.jsx("pre", { className: "whitespace-pre-wrap p-4 font-mono text-sm text-gray-300", children: /* @__PURE__ */ e.jsx("code", { children: m }) }) })
403
- ] })
404
- ] }),
405
- w && /* @__PURE__ */ e.jsx("div", { className: "mt-4 rounded-none border border-red-200 bg-red-50 p-3", children: /* @__PURE__ */ e.jsx("p", { className: "text-sm text-red-600", children: w }) })
406
- ] }),
407
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center justify-end gap-3 border-t border-[#e8e7ee] p-6", children: [
408
- /* @__PURE__ */ e.jsx(
409
- "button",
410
- {
411
- onClick: t,
412
- className: "rounded-none bg-gray-100 px-4 py-2 text-gray-700 transition-colors duration-200 hover:bg-gray-200",
413
- children: "Cancel"
414
- }
415
- ),
416
- /* @__PURE__ */ e.jsx(
417
- "button",
418
- {
419
- onClick: z,
420
- disabled: i === "file" && !m || i === "url" && !f || i === "code" && !f || !T(),
421
- className: "rounded-none bg-[#170f4f] px-4 py-2 text-white transition-colors duration-200 hover:bg-[#30aab3] disabled:cursor-not-allowed disabled:opacity-50",
422
- children: "Import Data"
423
- }
424
- )
425
- ] })
426
- ] })
427
- }
428
- ) : null;
429
- };
430
- export {
431
- H as DataSourceModal,
432
- E as HorizontalDataView
433
- };