declarative-ui-core 1.0.0 → 1.0.2

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 (2) hide show
  1. package/dist/index.js +652 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,655 @@
1
- import { bD as s, bE as t, bF as b, bG as o } from "./index-CqZ75MN0.js";
1
+ import { jsxs as v, jsx as r } from "react/jsx-runtime";
2
+ import { useRef as P, useState as D, useEffect as M, useMemo as C } from "react";
3
+ import $ from "maplibre-gl";
4
+ import J from "react-markdown";
5
+ import F from "mermaid";
6
+ import { VegaLite as G } from "react-vega";
7
+ const o = {
8
+ canvas: {
9
+ display: "grid",
10
+ width: "100%",
11
+ borderRadius: 16,
12
+ border: "1px solid #eee",
13
+ background: "white",
14
+ minWidth: 0
15
+ },
16
+ panel: {
17
+ height: "100%",
18
+ display: "flex",
19
+ flexDirection: "column",
20
+ border: "1px solid #eaeaea",
21
+ borderRadius: 16,
22
+ boxShadow: "0 1px 3px rgba(0,0,0,0.06)",
23
+ overflow: "hidden",
24
+ background: "#fff"
25
+ },
26
+ panelHeader: { padding: "10px 12px", borderBottom: "1px solid #f0f0f0", display: "flex", gap: 10, alignItems: "baseline" },
27
+ panelTitle: { fontSize: 13, fontWeight: 800, flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
28
+ panelBody: { padding: 12, minHeight: 0, overflow: "auto", flex: 1 },
29
+ tableWrap: { overflow: "auto" },
30
+ table: { width: "100%", borderCollapse: "collapse", fontSize: 12 },
31
+ th: { textAlign: "left", padding: "6px 8px", borderBottom: "1px solid #eee", position: "sticky", top: 0, background: "#fff" },
32
+ td: { padding: "6px 8px", borderBottom: "1px solid #f2f2f2" },
33
+ kvList: { display: "flex", flexDirection: "column", gap: 8 },
34
+ kvRow: { display: "flex", gap: 10, alignItems: "baseline" },
35
+ kvKey: { width: 140, fontSize: 12, fontWeight: 700, color: "#444" },
36
+ kvValue: { fontSize: 12, color: "#111" },
37
+ listCards: { display: "flex", flexDirection: "column", gap: 10 },
38
+ listCard: { padding: 10, border: "1px solid #eee", borderRadius: 10, background: "#fafafa" },
39
+ listCardRow: { display: "flex", gap: 10, alignItems: "baseline", padding: "4px 0" },
40
+ listCardLabel: { fontSize: 11, fontWeight: 700, color: "#666", textTransform: "capitalize", minWidth: 80 },
41
+ listCardValue: { fontSize: 12, color: "#111", flex: 1 },
42
+ formRow: { display: "grid", gridTemplateColumns: "140px 1fr", gap: 10, alignItems: "center" },
43
+ formLabel: { fontSize: 12, fontWeight: 700, color: "#444" },
44
+ input: { padding: "8px 10px", borderRadius: 10, border: "1px solid #e6e6e6", fontSize: 12 },
45
+ pre: {
46
+ background: "#fafafa",
47
+ border: "1px solid #eee",
48
+ borderRadius: 12,
49
+ padding: 10,
50
+ overflow: "auto",
51
+ fontSize: 12,
52
+ lineHeight: 1.4
53
+ },
54
+ muted: { fontSize: 13, color: "#666" },
55
+ error: { padding: 10, border: "1px solid #f2c", borderRadius: 12, background: "#fff7fb", fontSize: 12 }
56
+ };
57
+ function K({ componentId: i, component: t }) {
58
+ const e = t.config?.columns;
59
+ return /* @__PURE__ */ v("div", { style: o.panel, children: [
60
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: t.title ?? i }) }),
61
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ v("div", { style: o.kvList, children: [
62
+ (e ?? []).map((n) => /* @__PURE__ */ v("label", { style: o.formRow, children: [
63
+ /* @__PURE__ */ r("div", { style: o.formLabel, children: n.label }),
64
+ /* @__PURE__ */ r("input", { style: o.input, placeholder: n.key })
65
+ ] }, n.key)),
66
+ e?.length ? null : /* @__PURE__ */ r("div", { style: o.muted, children: "No columns provided." })
67
+ ] }) })
68
+ ] });
69
+ }
70
+ function T(i, t) {
71
+ if (!t) return;
72
+ const e = t.startsWith("data.") ? t.slice(5) : t, n = i.data?.[e];
73
+ if (!(!n || n.source !== "inline"))
74
+ return n.rows;
75
+ }
76
+ function X({ page: i, componentId: t, component: e }) {
77
+ const n = T(i, e.dataRef) ?? [], l = e.config?.mode, s = e.config?.displayFields, f = s && s.length > 0 ? s : n.length > 0 ? Object.keys(n[0]) : [];
78
+ return /* @__PURE__ */ v("div", { style: o.panel, children: [
79
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: e.title ?? t }) }),
80
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: l === "kv" && n.length === 1 ? /* @__PURE__ */ r("div", { style: o.kvList, children: Object.entries(n[0]).map(([y, m]) => /* @__PURE__ */ v("div", { style: o.kvRow, children: [
81
+ /* @__PURE__ */ r("div", { style: o.kvKey, children: y }),
82
+ /* @__PURE__ */ r("div", { style: o.kvValue, children: String(m) })
83
+ ] }, y)) }) : f.length > 0 ? /* @__PURE__ */ r("div", { style: o.listCards, children: n.map((y, m) => /* @__PURE__ */ r("div", { style: o.listCard, children: f.map((b) => /* @__PURE__ */ v("div", { style: o.listCardRow, children: [
84
+ /* @__PURE__ */ r("div", { style: o.listCardLabel, children: b }),
85
+ /* @__PURE__ */ r("div", { style: o.listCardValue, children: String(y[b] ?? "") })
86
+ ] }, b)) }, m)) }) : /* @__PURE__ */ r("pre", { style: o.pre, children: JSON.stringify(n, null, 2) }) })
87
+ ] });
88
+ }
89
+ function H() {
90
+ const i = P(null), [t, e] = D({ width: 0, height: 0 });
91
+ return M(() => {
92
+ const n = i.current;
93
+ if (!n) return;
94
+ const l = new ResizeObserver((s) => {
95
+ const f = s[0];
96
+ if (!f) return;
97
+ const y = f.contentRect, m = { width: Math.round(y.width), height: Math.round(y.height) };
98
+ e((b) => Math.abs(b.width - m.width) <= 1 && Math.abs(b.height - m.height) <= 1 ? b : m);
99
+ });
100
+ return l.observe(n), () => l.disconnect();
101
+ }, []), { ref: i, size: t };
102
+ }
103
+ function B(i, t) {
104
+ if (!t) return;
105
+ const e = i.setProjection;
106
+ if (typeof e != "function") return;
107
+ const n = typeof t == "string" ? t : t && typeof t == "object" && typeof t.name == "string" ? t.name : t && typeof t == "object" && typeof t.type == "string" ? t.type : void 0;
108
+ if (n)
109
+ try {
110
+ e.call(i, n);
111
+ return;
112
+ } catch {
113
+ }
114
+ }
115
+ function Y(i) {
116
+ if (!i || typeof i != "object") return {};
117
+ const t = i, e = Array.isArray(t.markers) ? t.markers : void 0, n = e ? e.map((l) => {
118
+ if (!l) return null;
119
+ if ("lngLat" in l) {
120
+ const s = l, f = s.lngLat;
121
+ if (Array.isArray(f) && f.length === 2)
122
+ return {
123
+ name: typeof s.name == "string" ? s.name : void 0,
124
+ lngLat: [Number(f[0]), Number(f[1])],
125
+ popup: typeof s.popup == "string" ? s.popup : void 0,
126
+ shape: typeof s.shape == "string" ? s.shape : void 0,
127
+ color: typeof s.color == "string" ? s.color : void 0,
128
+ radius: typeof s.radius == "number" ? s.radius : void 0
129
+ };
130
+ }
131
+ if ("longitude" in l && "latitude" in l) {
132
+ const s = l;
133
+ if (typeof s.longitude == "number" && typeof s.latitude == "number") {
134
+ const f = typeof s.title == "string" ? s.title : void 0, y = typeof s.description == "string" ? s.description : void 0;
135
+ return {
136
+ name: f,
137
+ lngLat: [Number(s.longitude), Number(s.latitude)],
138
+ popup: y,
139
+ shape: typeof s.shape == "string" ? s.shape : void 0,
140
+ color: typeof s.color == "string" ? s.color : void 0,
141
+ radius: typeof s.radius == "number" ? s.radius : void 0
142
+ };
143
+ }
144
+ }
145
+ return null;
146
+ }).filter((l) => l !== null) : void 0;
147
+ if (typeof t.style == "string" || t.style && typeof t.style == "object")
148
+ return { style: t.style, options: t.options, markers: n };
149
+ if (t.version && t.sources && t.layers)
150
+ return { style: t, options: {}, markers: n };
151
+ if (t.style) {
152
+ const { style: l, ...s } = t;
153
+ return { style: l, options: s, markers: n };
154
+ }
155
+ return {};
156
+ }
157
+ function W(i) {
158
+ return { type: "FeatureCollection", features: i.map((e) => {
159
+ const n = typeof e.longitude == "number" ? e.longitude : typeof e.lng == "number" ? e.lng : typeof e.lon == "number" ? e.lon : void 0, l = typeof e.latitude == "number" ? e.latitude : typeof e.lat == "number" ? e.lat : void 0;
160
+ if (typeof n != "number" || typeof l != "number" || !Number.isFinite(n) || !Number.isFinite(l)) return null;
161
+ const s = { ...e };
162
+ return {
163
+ type: "Feature",
164
+ geometry: { type: "Point", coordinates: [n, l] },
165
+ properties: s
166
+ };
167
+ }).filter((e) => e !== null) };
168
+ }
169
+ function V(i, t) {
170
+ return (Array.isArray(i?.layers) ? i.layers : []).some((n) => n && typeof n == "object" && n.source === t);
171
+ }
172
+ function A(i, t) {
173
+ const e = "data", n = "circle-data", l = W(t), s = { ...i.sources ?? {} };
174
+ s[e] = {
175
+ type: "geojson",
176
+ data: l
177
+ };
178
+ const f = Array.isArray(i.layers) ? [...i.layers] : [], y = !V(i, e), m = f.filter((b) => b && typeof b == "object" && b.id !== n);
179
+ return y && m.push({
180
+ id: n,
181
+ type: "circle",
182
+ source: e,
183
+ paint: {
184
+ "circle-radius": ["coalesce", ["get", "radius"], 8],
185
+ "circle-color": ["coalesce", ["get", "color"], "#2563eb"],
186
+ "circle-stroke-color": "#ffffff",
187
+ "circle-stroke-width": 2,
188
+ "circle-opacity": 1
189
+ }
190
+ }), {
191
+ ...i,
192
+ sources: s,
193
+ layers: m
194
+ };
195
+ }
196
+ function q(i, t) {
197
+ const e = "data", n = "circle-data", l = W(t);
198
+ try {
199
+ const s = i.getSource(e) ?? null;
200
+ s && typeof s.setData == "function" ? s.setData(l) : i.addSource(e, { type: "geojson", data: l });
201
+ } catch {
202
+ }
203
+ try {
204
+ const s = i.getStyle();
205
+ !V(s, e) && !i.getLayer(n) && i.addLayer({
206
+ id: n,
207
+ type: "circle",
208
+ source: e,
209
+ paint: {
210
+ "circle-radius": ["coalesce", ["get", "radius"], 8],
211
+ "circle-color": ["coalesce", ["get", "color"], "#2563eb"],
212
+ "circle-stroke-color": "#ffffff",
213
+ "circle-stroke-width": 2,
214
+ "circle-opacity": 1
215
+ }
216
+ });
217
+ } catch {
218
+ }
219
+ }
220
+ function _({ page: i, componentId: t, component: e }) {
221
+ const n = e.title ?? t, l = "circle-data", { ref: s, size: f } = H(), y = P(null), m = P([]), b = P(/* @__PURE__ */ new Map()), c = C(() => Y(e.config), [e.config]), u = C(() => T(i, e.dataRef), [i, e.dataRef]), w = C(() => {
222
+ if (!u || u.length === 0) return null;
223
+ let d = 1 / 0, a = 1 / 0, k = -1 / 0, p = -1 / 0;
224
+ for (const h of u) {
225
+ const L = typeof h.longitude == "number" ? h.longitude : typeof h.lng == "number" ? h.lng : typeof h.lon == "number" ? h.lon : void 0, j = typeof h.latitude == "number" ? h.latitude : typeof h.lat == "number" ? h.lat : void 0;
226
+ typeof L != "number" || typeof j != "number" || !Number.isFinite(L) || !Number.isFinite(j) || (d = Math.min(d, L), a = Math.min(a, j), k = Math.max(k, L), p = Math.max(p, j));
227
+ }
228
+ return !Number.isFinite(d) || !Number.isFinite(a) || !Number.isFinite(k) || !Number.isFinite(p) ? null : [
229
+ [d, a],
230
+ [k, p]
231
+ ];
232
+ }, [u]), g = C(() => {
233
+ if (!c.options) return;
234
+ const { projection: d, ...a } = c.options;
235
+ return a;
236
+ }, [c.options]), x = C(() => {
237
+ const d = c.options?.projection;
238
+ if (typeof d == "string") return d;
239
+ if (d && typeof d == "object" && typeof d.name == "string") return d.name;
240
+ if (d && typeof d == "object" && typeof d.type == "string") return d.type;
241
+ const a = typeof c.style == "object" && c.style ? c.style.projection : void 0;
242
+ if (typeof a == "string") return a;
243
+ if (a && typeof a == "object" && typeof a.name == "string") return a.name;
244
+ if (a && typeof a == "object" && typeof a.type == "string") return a.type;
245
+ }, [c.options, c.style]), S = typeof c.style == "string" && typeof x == "string", R = typeof c.style == "string" && Array.isArray(u) && u.length > 0, Z = C(
246
+ () => ({
247
+ version: 8,
248
+ sources: {},
249
+ layers: []
250
+ }),
251
+ []
252
+ ), I = (d) => {
253
+ if (!S && !R) return;
254
+ const a = c.style, k = b.current.get(a);
255
+ if (k) {
256
+ try {
257
+ let p = k;
258
+ S && (p = { ...p ?? {}, projection: { type: x } }), R && e.dataRef && u && (p = A(p, u) ?? p), d.setStyle(p);
259
+ } catch {
260
+ }
261
+ return;
262
+ }
263
+ fetch(a).then((p) => p.json()).then((p) => {
264
+ b.current.set(a, p);
265
+ let h = p ?? {};
266
+ S && (h = { ...h, projection: { type: x } }), R && e.dataRef && u && (h = A(h, u) ?? h);
267
+ try {
268
+ d.setStyle(h);
269
+ } catch {
270
+ }
271
+ }).catch(() => {
272
+ });
273
+ }, z = C(() => {
274
+ if (c.style)
275
+ return typeof c.style == "object" && c.style && e.dataRef && Array.isArray(u) && u.length > 0 ? A(c.style, u) ?? c.style : c.style;
276
+ }, [c.style, e.dataRef, u]);
277
+ return M(() => {
278
+ const d = s.current;
279
+ if (!d || !z) return;
280
+ if (!y.current) {
281
+ const k = {
282
+ container: d,
283
+ style: typeof z == "string" && (S || R) ? Z : z,
284
+ attributionControl: {},
285
+ ...g ?? {}
286
+ }, p = new $.Map(k);
287
+ I(p);
288
+ const h = () => B(p, x);
289
+ p.once("load", h), p.once("style.load", h), p.addControl(new $.NavigationControl({ visualizePitch: !0 }), "top-right");
290
+ const L = () => {
291
+ if (u && u.length > 0 && (q(p, u), !c.options?.center && c.options?.zoom === void 0 && w))
292
+ try {
293
+ p.fitBounds(w, { padding: 30, duration: 0, maxZoom: 12 });
294
+ } catch {
295
+ }
296
+ };
297
+ return p.once("style.load", L), y.current = p, () => {
298
+ m.current.forEach((j) => j.remove()), m.current = [], y.current = null, p.remove();
299
+ };
300
+ }
301
+ const a = y.current;
302
+ if (S || R)
303
+ I(a);
304
+ else
305
+ try {
306
+ a.setStyle(z);
307
+ } catch {
308
+ }
309
+ if (x) {
310
+ const k = () => B(a, x);
311
+ a.once("style.load", k), a.once("render", k);
312
+ }
313
+ if (c.options?.center && c.options?.zoom !== void 0)
314
+ try {
315
+ a.jumpTo({ center: c.options.center, zoom: c.options.zoom });
316
+ } catch {
317
+ }
318
+ }, [z, g, s, x, R, S, u, w, c.options?.center, c.options?.zoom]), M(() => {
319
+ const d = y.current;
320
+ if (!d || !u || u.length === 0) return;
321
+ const a = () => {
322
+ if (q(d, u), !c.options?.center && c.options?.zoom === void 0 && w)
323
+ try {
324
+ d.fitBounds(w, { padding: 30, duration: 0, maxZoom: 12 });
325
+ } catch {
326
+ }
327
+ };
328
+ d.once("style.load", a), d.once("load", a);
329
+ }, [u, w, c.options?.center, c.options?.zoom]), M(() => {
330
+ const d = y.current;
331
+ d && (f.width <= 0 || f.height <= 0 || d.resize());
332
+ }, [f.width, f.height]), M(() => {
333
+ const d = y.current;
334
+ if (!d || !u || u.length === 0) return;
335
+ const a = new $.Popup({
336
+ closeButton: !1,
337
+ closeOnClick: !1
338
+ }), k = (L) => {
339
+ if (!L.features || L.features.length === 0) return;
340
+ const j = L.features[0], N = j.properties?.name;
341
+ if (N) {
342
+ d.getCanvas().style.cursor = "pointer";
343
+ const U = j.geometry.coordinates.slice();
344
+ a.setLngLat(U).setHTML(`<div style="padding: 4px 8px; font-size: 13px;">${N}</div>`).addTo(d);
345
+ }
346
+ }, p = () => {
347
+ d.getCanvas().style.cursor = "", a.remove();
348
+ }, h = () => {
349
+ d.getLayer(l) ? (d.on("mouseenter", l, k), d.on("mouseleave", l, p)) : d.once("styledata", h);
350
+ };
351
+ return h(), () => {
352
+ a.remove(), d && !d._removed && d.getLayer(l) && (d.off("mouseenter", l, k), d.off("mouseleave", l, p));
353
+ };
354
+ }, [u, l]), M(() => {
355
+ const d = y.current;
356
+ d && (m.current.forEach((a) => a.remove()), m.current = [], (c.markers ?? []).forEach((a) => {
357
+ const p = a.shape === "circle" || typeof a.radius == "number" || typeof a.color == "string" ? document.createElement("div") : null;
358
+ if (p) {
359
+ const L = typeof a.radius == "number" && Number.isFinite(a.radius) ? Math.max(2, a.radius) : 8;
360
+ p.style.width = `${L * 2}px`, p.style.height = `${L * 2}px`, p.style.borderRadius = "999px", p.style.background = typeof a.color == "string" ? a.color : "#2563eb", p.style.border = "2px solid #ffffff", p.style.boxShadow = "0 2px 10px rgba(0,0,0,0.25)";
361
+ }
362
+ const h = new $.Marker(p ? { element: p } : void 0).setLngLat(a.lngLat);
363
+ if (a.popup || a.name) {
364
+ const L = a.popup ?? `<div style="font-size:12px"><strong>${a.name ?? ""}</strong></div>`;
365
+ h.setPopup(new $.Popup({ offset: 20 }).setHTML(L));
366
+ }
367
+ h.addTo(d), m.current.push(h);
368
+ }));
369
+ }, [c.markers]), /* @__PURE__ */ v("div", { style: o.panel, children: [
370
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: n }) }),
371
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: c.style ? /* @__PURE__ */ r("div", { ref: s, style: { width: "100%", height: "100%", minHeight: 420 } }) : /* @__PURE__ */ v("div", { style: o.muted, children: [
372
+ "MapLibre requires a style in component.config. Provide either:",
373
+ /* @__PURE__ */ r("pre", { style: o.pre, children: JSON.stringify({ style: "https://.../style.json", options: { center: [12.5, 41.9], zoom: 4 } }, null, 2) })
374
+ ] }) })
375
+ ] });
376
+ }
377
+ function Q({ page: i, componentId: t, component: e }) {
378
+ const n = e.title ?? t, l = typeof e.config?.md == "string" ? e.config.md : "";
379
+ return l ? /* @__PURE__ */ v("div", { style: o.panel, children: [
380
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: n }) }),
381
+ /* @__PURE__ */ r("div", { style: { ...o.panelBody, overflow: "auto" }, children: /* @__PURE__ */ r("div", { style: {
382
+ padding: "8px",
383
+ lineHeight: "1.6",
384
+ fontSize: "14px"
385
+ }, children: /* @__PURE__ */ r(J, { children: l }) }) })
386
+ ] }) : /* @__PURE__ */ v("div", { style: o.panel, children: [
387
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: n }) }),
388
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ r("div", { style: o.muted, children: 'No markdown content provided. Add an "md" field to config.' }) })
389
+ ] });
390
+ }
391
+ F.initialize({
392
+ startOnLoad: !1,
393
+ theme: "default",
394
+ securityLevel: "loose"
395
+ });
396
+ function ee({ page: i, componentId: t, component: e }) {
397
+ const n = e.title ?? t, l = typeof e.config?.mermaid == "string" ? e.config.mermaid : "", s = P(null), [f, y] = D(1);
398
+ M(() => {
399
+ if (!l || !s.current) return;
400
+ (async () => {
401
+ try {
402
+ const w = `mermaid-${t}-${Date.now()}`, { svg: g } = await F.render(w, l);
403
+ if (s.current) {
404
+ s.current.innerHTML = g;
405
+ const x = s.current.querySelector("svg");
406
+ x && (x.style.maxWidth = "100%", x.style.height = "auto");
407
+ }
408
+ } catch (w) {
409
+ s.current && (s.current.innerHTML = `<div style="color: #dc2626; padding: 8px;">Error rendering diagram: ${w instanceof Error ? w.message : String(w)}</div>`);
410
+ }
411
+ })();
412
+ }, [l, t]);
413
+ const m = () => y((u) => Math.min(u + 0.2, 3)), b = () => y((u) => Math.max(u - 0.2, 0.5)), c = () => y(1);
414
+ return l ? /* @__PURE__ */ v("div", { style: o.panel, children: [
415
+ /* @__PURE__ */ v("div", { style: o.panelHeader, children: [
416
+ /* @__PURE__ */ r("div", { style: o.panelTitle, children: n }),
417
+ /* @__PURE__ */ v("div", { style: { display: "flex", gap: "4px", marginLeft: "auto" }, children: [
418
+ /* @__PURE__ */ r(
419
+ "button",
420
+ {
421
+ onClick: b,
422
+ style: {
423
+ padding: "4px 8px",
424
+ fontSize: "12px",
425
+ border: "1px solid #ddd",
426
+ borderRadius: "4px",
427
+ background: "#fff",
428
+ cursor: "pointer"
429
+ },
430
+ title: "Zoom out",
431
+ children: "−"
432
+ }
433
+ ),
434
+ /* @__PURE__ */ v(
435
+ "button",
436
+ {
437
+ onClick: c,
438
+ style: {
439
+ padding: "4px 8px",
440
+ fontSize: "12px",
441
+ border: "1px solid #ddd",
442
+ borderRadius: "4px",
443
+ background: "#fff",
444
+ cursor: "pointer"
445
+ },
446
+ title: "Reset zoom",
447
+ children: [
448
+ Math.round(f * 100),
449
+ "%"
450
+ ]
451
+ }
452
+ ),
453
+ /* @__PURE__ */ r(
454
+ "button",
455
+ {
456
+ onClick: m,
457
+ style: {
458
+ padding: "4px 8px",
459
+ fontSize: "12px",
460
+ border: "1px solid #ddd",
461
+ borderRadius: "4px",
462
+ background: "#fff",
463
+ cursor: "pointer"
464
+ },
465
+ title: "Zoom in",
466
+ children: "+"
467
+ }
468
+ )
469
+ ] })
470
+ ] }),
471
+ /* @__PURE__ */ r("div", { style: { ...o.panelBody, overflow: "auto", position: "relative" }, children: /* @__PURE__ */ r("div", { style: {
472
+ padding: "50px",
473
+ display: "flex",
474
+ justifyContent: "center",
475
+ alignItems: "center"
476
+ }, children: /* @__PURE__ */ r(
477
+ "div",
478
+ {
479
+ ref: s,
480
+ style: {
481
+ transform: `scale(${f})`,
482
+ transformOrigin: "center center",
483
+ transition: "transform 0.2s ease"
484
+ }
485
+ }
486
+ ) }) })
487
+ ] }) : /* @__PURE__ */ v("div", { style: o.panel, children: [
488
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: n }) }),
489
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ r("div", { style: o.muted, children: 'No mermaid diagram provided. Add a "mermaid" field to config.' }) })
490
+ ] });
491
+ }
492
+ function te({ page: i, componentId: t, component: e }) {
493
+ const n = T(i, e.dataRef) ?? [], l = e.config?.columns, s = l && l.length ? l : Object.keys(n[0] ?? {}).map((f) => ({ key: f, label: f }));
494
+ return /* @__PURE__ */ v("div", { style: o.panel, children: [
495
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: e.title ?? t }) }),
496
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ r("div", { style: o.tableWrap, children: /* @__PURE__ */ v("table", { style: o.table, children: [
497
+ /* @__PURE__ */ r("thead", { children: /* @__PURE__ */ r("tr", { children: s.map((f) => /* @__PURE__ */ r("th", { style: o.th, children: f.label }, f.key)) }) }),
498
+ /* @__PURE__ */ r("tbody", { children: n.map((f, y) => /* @__PURE__ */ r("tr", { children: s.map((m) => /* @__PURE__ */ r("td", { style: o.td, children: String(f[m.key] ?? "") }, m.key)) }, y)) })
499
+ ] }) }) })
500
+ ] });
501
+ }
502
+ function re({ componentId: i, component: t }) {
503
+ return /* @__PURE__ */ v("div", { style: o.panel, children: [
504
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: t.title ?? i }) }),
505
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ r("pre", { style: o.pre, children: JSON.stringify(t, null, 2) }) })
506
+ ] });
507
+ }
508
+ function ie(i) {
509
+ if (!i || typeof i != "object") return !1;
510
+ const t = (e) => {
511
+ if (!e || typeof e != "object") return !1;
512
+ const n = e.mark, l = n === "text" || n && typeof n == "object" && n.type === "text", s = !!(e.encoding?.text && typeof e.encoding.text == "object" && "value" in e.encoding.text);
513
+ return l && s ? !0 : Array.isArray(e.layer) ? e.layer.some(t) : e.spec ? t(e.spec) : !1;
514
+ };
515
+ return t(i);
516
+ }
517
+ function ne({ page: i, componentId: t, component: e }) {
518
+ const n = T(i, e.dataRef), { ref: l, size: s } = H(), f = e.spec ?? {}, y = f.config ?? {}, m = {
519
+ ...y,
520
+ axis: { ...y.axis, grid: !1 },
521
+ axisX: { ...y.axisX, grid: !1 },
522
+ axisY: { ...y.axisY, grid: !1 },
523
+ view: { ...y.view, stroke: null }
524
+ }, b = { ...f, config: m }, c = s.width > 0 && s.height > 0 ? {
525
+ ...b,
526
+ autosize: { type: "fit", contains: "padding" },
527
+ width: Math.floor(s.width),
528
+ height: Math.floor(s.height)
529
+ } : b, u = n ? { ...c, data: { values: n } } : ie(c) ? { ...c, data: { values: [{}] } } : c, w = e.title === "" ? "" : e.title ?? t;
530
+ return /* @__PURE__ */ v("div", { style: o.panel, children: [
531
+ w ? /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: w }) }) : null,
532
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ r("div", { ref: l, style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ r(G, { spec: u, actions: !1 }) }) })
533
+ ] });
534
+ }
535
+ function E({ page: i, componentId: t, component: e }) {
536
+ switch (e.type) {
537
+ case "vegalite5":
538
+ return /* @__PURE__ */ r(ne, { page: i, componentId: t, component: e });
539
+ case "table":
540
+ return /* @__PURE__ */ r(te, { page: i, componentId: t, component: e });
541
+ case "form":
542
+ return /* @__PURE__ */ r(K, { page: i, componentId: t, component: e });
543
+ case "list":
544
+ return /* @__PURE__ */ r(X, { page: i, componentId: t, component: e });
545
+ case "map":
546
+ return /* @__PURE__ */ r(_, { page: i, componentId: t, component: e });
547
+ case "markdown":
548
+ return /* @__PURE__ */ r(Q, { page: i, componentId: t, component: e });
549
+ case "mermaid":
550
+ return /* @__PURE__ */ r(ee, { page: i, componentId: t, component: e });
551
+ default:
552
+ return /* @__PURE__ */ r(re, { page: i, componentId: t, component: e });
553
+ }
554
+ }
555
+ function O(i, t, e) {
556
+ return Math.min(e, Math.max(t, i));
557
+ }
558
+ function oe(i) {
559
+ const t = i.reduce((n, l) => Math.max(n, l.y + l.h), 0), e = i.reduce((n, l) => Math.max(n, l.x + l.w), 0);
560
+ return { maxBottom: t, maxRight: e };
561
+ }
562
+ function xe({ page: i }) {
563
+ const { ref: t, size: e } = H(), n = i.layout.cols ?? 24, l = i.layout.rowHeight ?? 30, s = i.layout.margin?.[0] ?? 10, f = i.layout.margin?.[1] ?? 10, y = i.layout.containerPadding?.[0] ?? 0, m = i.layout.containerPadding?.[1] ?? 0, { maxBottom: b } = oe(i.layout.items), c = b * l + Math.max(0, b - 1) * f + m * 2, u = e.width > 0 ? e.width < 768 : !1, w = [...i.layout.items].sort((g, x) => g.y - x.y || g.x - x.x);
564
+ return /* @__PURE__ */ r("div", { ref: t, children: u ? /* @__PURE__ */ r(
565
+ "div",
566
+ {
567
+ style: {
568
+ display: "flex",
569
+ flexDirection: "column",
570
+ gap: f,
571
+ padding: `${m}px ${y}px`
572
+ },
573
+ children: w.map((g) => {
574
+ const x = i.components[g.i], S = g.h * l + Math.max(0, g.h - 1) * f;
575
+ return /* @__PURE__ */ r("div", { style: { width: "100%", height: S }, children: x ? /* @__PURE__ */ r(E, { page: i, componentId: g.i, component: x }) : /* @__PURE__ */ v("div", { style: o.panel, children: [
576
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: g.i }) }),
577
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ v("div", { style: o.error, children: [
578
+ "No entry in components for id: ",
579
+ g.i
580
+ ] }) })
581
+ ] }) }, g.i);
582
+ })
583
+ }
584
+ ) : /* @__PURE__ */ r(
585
+ "div",
586
+ {
587
+ style: {
588
+ ...o.canvas,
589
+ padding: `${m}px ${y}px`,
590
+ gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))`,
591
+ gridAutoRows: `${l}px`,
592
+ gap: `${f}px ${s}px`,
593
+ minHeight: c
594
+ },
595
+ children: i.layout.items.map((g) => {
596
+ const x = i.components[g.i];
597
+ return /* @__PURE__ */ r(
598
+ "div",
599
+ {
600
+ style: {
601
+ gridColumnStart: O(g.x + 1, 1, n + 1),
602
+ gridColumnEnd: `span ${O(g.w, 1, n)}`,
603
+ gridRowStart: Math.max(1, g.y + 1),
604
+ gridRowEnd: `span ${Math.max(1, g.h)}`
605
+ },
606
+ children: x ? /* @__PURE__ */ r(E, { page: i, componentId: g.i, component: x }) : /* @__PURE__ */ v("div", { style: o.panel, children: [
607
+ /* @__PURE__ */ r("div", { style: o.panelHeader, children: /* @__PURE__ */ r("div", { style: o.panelTitle, children: g.i }) }),
608
+ /* @__PURE__ */ r("div", { style: o.panelBody, children: /* @__PURE__ */ v("div", { style: o.error, children: [
609
+ "No entry in components for id: ",
610
+ g.i
611
+ ] }) })
612
+ ] })
613
+ },
614
+ g.i
615
+ );
616
+ })
617
+ }
618
+ ) });
619
+ }
620
+ const se = "https://json-schema.org/draft/2020-12/schema", le = "https://example.com/ai-canvas/page.schema.json", ae = "AI Canvas Page", de = "object", ce = !1, pe = ["layout", "components", "data"], fe = { meta: { $ref: "#/$defs/Meta" }, layout: { $ref: "#/$defs/Layout" }, components: { $ref: "#/$defs/Components" }, data: { $ref: "#/$defs/Data" } }, ye = { Meta: { type: "object", additionalProperties: !1, properties: { title: { type: "string", minLength: 1 }, description: { type: "string" }, version: { type: "string" } } }, Layout: { type: "object", additionalProperties: !1, required: ["engine", "items"], properties: { engine: { type: "string", enum: ["rgl"] }, cols: { type: "integer", minimum: 1, default: 24 }, rowHeight: { type: "integer", minimum: 1, default: 30 }, margin: { type: "array", items: { type: "integer", minimum: 0 }, minItems: 2, maxItems: 2, default: [10, 10] }, containerPadding: { type: "array", items: { type: "integer", minimum: 0 }, minItems: 2, maxItems: 2, default: [0, 0] }, items: { type: "array", minItems: 1, items: { $ref: "#/$defs/RglItem" } } } }, RglItem: { type: "object", additionalProperties: !1, required: ["i", "x", "y", "w", "h"], properties: { i: { type: "string", minLength: 1 }, x: { type: "integer", minimum: 0 }, y: { type: "integer", minimum: 0 }, w: { type: "integer", minimum: 1 }, h: { type: "integer", minimum: 1 }, static: { type: "boolean", default: !1 } } }, Components: { type: "object", description: "Map of componentId -> component config. Keys should match layout.items[*].i.", additionalProperties: { $ref: "#/$defs/Component" } }, Component: { type: "object", additionalProperties: !1, required: ["type"], properties: { type: { type: "string", enum: ["vegalite5", "map", "list", "form", "table", "markdown", "mermaid"] }, title: { type: "string" }, dataRef: { type: "string", minLength: 1 }, config: { type: "object", description: "Component-specific configuration (non-Vega-Lite components). Keep flexible for now.", additionalProperties: !0, default: {} }, spec: { type: "object", description: "Vega-Lite spec (only for type=vegalite5).", additionalProperties: !0 } }, allOf: [{ if: { properties: { type: { const: "vegalite5" } }, required: ["type"] }, then: { required: ["spec"] }, else: { properties: { spec: !1 } } }, { if: { properties: { type: { const: "map" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0, description: "MapLibre GL JS configuration. Provide either a MapLibre Style Specification object (Mapbox style spec v8) directly, or an object like { style: <style-spec-or-url>, options: <map options> }." } } } }, { if: { properties: { type: { const: "table" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0, required: ["columns"], properties: { columns: { type: "array", minItems: 1, items: { $ref: "#/$defs/Column" } } } } } } }, { if: { properties: { type: { const: "form" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0, required: ["columns"], properties: { columns: { type: "array", minItems: 1, items: { $ref: "#/$defs/Column" } } } } } } }, { if: { properties: { type: { const: "list" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0 } } } }, { if: { properties: { type: { const: "markdown" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0, required: ["md"], properties: { md: { type: "string", minLength: 1, description: "Markdown content to render" } } } } } }, { if: { properties: { type: { const: "mermaid" } }, required: ["type"] }, then: { properties: { config: { type: "object", additionalProperties: !0, required: ["mermaid"], properties: { mermaid: { type: "string", minLength: 1, description: "Mermaid diagram definition" } } } } } }] }, Column: { type: "object", additionalProperties: !1, required: ["key", "label"], properties: { key: { type: "string", minLength: 1 }, label: { type: "string", minLength: 1 } } }, Data: { type: "object", description: "Map of datasetName -> inline dataset.", additionalProperties: { $ref: "#/$defs/InlineDataset" } }, InlineDataset: { type: "object", additionalProperties: !1, required: ["source", "rows"], properties: { source: { type: "string", enum: ["inline"] }, rows: { type: "array", items: { type: "object", additionalProperties: !0 } } } } }, we = {
621
+ $schema: se,
622
+ $id: le,
623
+ title: ae,
624
+ type: de,
625
+ additionalProperties: ce,
626
+ required: pe,
627
+ properties: fe,
628
+ $defs: ye
629
+ };
630
+ function ke(i) {
631
+ const t = JSON.parse(JSON.stringify(i));
632
+ t && typeof t == "object" && delete t.$id;
633
+ try {
634
+ const n = t?.$defs?.Layout?.properties?.items;
635
+ n && typeof n == "object" && (n.minItems = 0);
636
+ } catch {
637
+ }
638
+ const e = (n) => {
639
+ if (!(!n || typeof n != "object")) {
640
+ if (n.$ref === "https://vega.github.io/schema/vega-lite/v5.json") {
641
+ delete n.$ref, n.type = "object", n.additionalProperties = !0;
642
+ return;
643
+ }
644
+ for (const l of Object.values(n))
645
+ Array.isArray(l) ? l.forEach(e) : e(l);
646
+ }
647
+ };
648
+ return e(t), t;
649
+ }
2
650
  export {
3
- s as CanvasRenderer,
4
- t as PAGE_SCHEMA,
5
- b as schemaWithoutRemoteVegaLiteRef,
651
+ xe as CanvasRenderer,
652
+ we as PAGE_SCHEMA,
653
+ ke as schemaWithoutRemoteVegaLiteRef,
6
654
  o as styles
7
655
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "declarative-ui-core",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",