@tenorlab/vue-dashboard 1.4.903 → 1.5.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.
package/README.md CHANGED
@@ -135,9 +135,9 @@ import {
135
135
  TWidgetFactory,
136
136
  } from '@tenorlab/vue-dashboard'
137
137
  import {
138
- createStaticEntry as _createStaticEntry,
138
+ createStaticEntry,
139
139
  localWidgetDiscovery,
140
- remoteWidgetDiscovery as _remoteWidgetDiscovery,
140
+ remoteWidgetDiscovery,
141
141
  } from '@tenorlab/vue-dashboard/core'
142
142
 
143
143
  import WidgetRecentPaymentInfo from './other-widgets/WidgetRecentPaymentInfo.vue'
@@ -146,9 +146,6 @@ import WidgetRecentPaymentInfo from './other-widgets/WidgetRecentPaymentInfo.vue
146
146
  const bundledWidgetsSrcPath = '/src/bundled-widgets'
147
147
  const asyncWidgetsSrcPath = '/src/async-widgets'
148
148
 
149
- import { markRaw } from 'vue'
150
- import type { Component as VueComponent } from 'vue'
151
-
152
149
  // Use Vite's Glob Import
153
150
  // This creates an object where the keys are file paths, and the values are the TWidgetFactory functions.
154
151
  // We target the 'index.ts' files within the widgets subdirectories.
@@ -169,18 +166,6 @@ const allMetaModules = import.meta.glob('/src/**/widget-*/meta.ts', {
169
166
 
170
167
  const hasPermission = (_user: any, _permission: string) => true
171
168
 
172
- /**
173
- * @name createStaticEntry
174
- * Wraps around createStaticEntry from npm package to ensure the component added is marked raw (using markRaw)
175
- */
176
- export const createStaticEntry = (
177
- key: string,
178
- component: VueComponent,
179
- metaData?: TWidgetMetaInfoBase,
180
- ): [string, IDynamicWidgetCatalogEntry] => {
181
- return _createStaticEntry(key, markRaw(component), metaData)
182
- }
183
-
184
169
  /**
185
170
  * @name getWidgetCatalog
186
171
  * @description Dynamically builds the widgets catalog based on user type and operations/permissions.
package/dist/core.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Component } from 'vue';
2
-
3
1
  export declare const blankDashboardConfig: IDashboardConfig;
4
2
 
5
3
  /**
@@ -11,10 +9,10 @@ export declare const createDynamicEntry: (key: string, loader: TWidgetFactoryBas
11
9
 
12
10
  /**
13
11
  * @name createStaticEntry
14
- * Wraps around (and shadows) the @tenorlab/dashboard-core createStaticEntry to ensure
15
- * the component added is marked raw (using markRaw)
12
+ * Helper function to create static entries
13
+ * This helps keep the catalog registration clean
16
14
  */
17
- export declare const createStaticEntry: (key: string, component: Component, metaData?: TWidgetMetaInfoBase) => [string, IDynamicWidgetCatalogEntry];
15
+ export declare const createStaticEntry: <TFrameworkComponentType = any>(key: string, component: TFrameworkComponentType, metaData?: TWidgetMetaInfoBase) => [string, IDynamicWidgetCatalogEntryBase];
18
16
 
19
17
  /**
20
18
  * @name cssSettingsCatalog
@@ -226,17 +224,6 @@ export declare interface IDashboardWidgetPropsBase<TExtraProps = any> {
226
224
  extraProps?: TExtraProps;
227
225
  }
228
226
 
229
- /**
230
- * @name IDynamicWidgetCatalogEntry
231
- * @description Represents a dynamic widget catalog entry for Vue components.
232
- * @interface IDynamicWidgetCatalogEntry
233
- * @extends IDynamicWidgetCatalogEntryBase
234
- * @template TFrameworkElementType - The type representing a Vue component instance.
235
- * @template TFrameworkComponentType - The type representing a Vue component.
236
- */
237
- declare interface IDynamicWidgetCatalogEntry extends IDynamicWidgetCatalogEntryBase<TFrameworkElementType, TFrameworkComponentType> {
238
- }
239
-
240
227
  /**
241
228
  * @name IDynamicWidgetCatalogEntryBase
242
229
  * @description Catalog entry describing how to create or load a widget.
@@ -268,8 +255,8 @@ export declare interface IDynamicWidgetCatalogEntryBase<TFrameworkElementType =
268
255
 
269
256
  /**
270
257
  * @name localWidgetDiscovery
271
- * Wraps around (and shadows) the @tenorlab/dashboard-core localWidgetDiscovery to ensure
272
- * the component added is marked raw (using markRaw)
258
+ * @description Scans local directories for widgets.
259
+ * If lazy is true, it registers loaders. If false, it registers static components.
273
260
  */
274
261
  export declare const localWidgetDiscovery: (baseSrcPath: string, // e.g., "/src/async-widgets" or "/src/bundled-widgets"
275
262
  widgetModules: Record<string, any>, widgetMetaModules: Record<string, any>, lazy?: boolean) => [string, IDynamicWidgetCatalogEntryBase][];
@@ -279,13 +266,14 @@ export declare const parseContainerTitle: (containerWidgetKey: TDashboardWidgetK
279
266
  /**
280
267
  * Enhanced helper to derive key and title from widget file paths.
281
268
  * Handles:
269
+ * - widget-total-orders -> WidgetTotalOrders
282
270
  * - widget-revenue-trends1 -> WidgetRevenueTrends1
283
271
  * - widget-with-extraprops -> WidgetWithExtraprops
284
272
  * - widget-revenue-trends-async -> WidgetRevenueTrendsAsync
285
273
  */
286
274
  export declare const parseKeyAndTitleFromFilePath: (path: string) => {
287
275
  key: TDashboardWidgetKey;
288
- title: string;
276
+ name: string;
289
277
  folder: string;
290
278
  } | null;
291
279
 
@@ -339,18 +327,6 @@ export declare type TDashboardWidgetCatalogBase<TFrameworkElementType = any, TFr
339
327
  */
340
328
  export declare type TDashboardWidgetKey = string;
341
329
 
342
- /**
343
- * @name TFrameworkComponentType
344
- * @description Represents a Vue component type.
345
- */
346
- declare type TFrameworkComponentType = Component;
347
-
348
- /**
349
- * @name TFrameworkElementType
350
- * @description Represents a Vue component instance.
351
- */
352
- declare type TFrameworkElementType = Component;
353
-
354
330
  /**
355
331
  * @name TGetDefaultWidgetMetaFromKey
356
332
  * @description Function that returns default `TWidgetMetaInfoBase` metadata for a widget key.
@@ -369,7 +345,7 @@ export declare type TGetDefaultWidgetMetaFromKey = (widgetKey: TDashboardWidgetK
369
345
  * and/or `description`.
370
346
  */
371
347
  export declare type TGetDefaultWidgetMetaFromKeyOptions = {
372
- title?: string;
348
+ name?: string;
373
349
  description?: string;
374
350
  };
375
351
 
package/dist/core.es.js CHANGED
@@ -1,10 +1,370 @@
1
- import { markRaw as n } from "vue";
2
- import { createStaticEntry as a, localWidgetDiscovery as i } from "@tenorlab/vue-dashboard/core";
3
- export * from "@tenorlab/vue-dashboard/core";
4
- const E = (t, r, c) => a(t, n(r), c), f = (t, r, c, e = !0) => e ? i(t, r, c, e) : i(t, r, c, e).map(
5
- (o) => a(o[0], n(o[1].component), o[1].meta)
6
- );
1
+ const w = [
2
+ {
3
+ key: "grid-gap",
4
+ name: "Gap",
5
+ description: "Set the gap between widgets in the dashboard grid",
6
+ cssProperty: "--bwj-dashboard-gap",
7
+ step: 0.1,
8
+ defaultUnit: "rem",
9
+ minValue: 0,
10
+ defaultValue: "1.25rem",
11
+ value: "1.25rem"
12
+ },
13
+ {
14
+ key: "widget-width",
15
+ name: "Widget Width",
16
+ description: "Set the min width for the widgets",
17
+ cssProperty: "--bwj-widget-width",
18
+ step: 0.1,
19
+ defaultUnit: "rem",
20
+ minValue: 6,
21
+ defaultValue: "21rem",
22
+ value: "21rem"
23
+ },
24
+ {
25
+ key: "widget-border-radius",
26
+ name: "Widget Border Radius",
27
+ description: "Set the border radius for the widgets",
28
+ cssProperty: "--bwj-widget-border-radius",
29
+ step: 0.1,
30
+ defaultUnit: "rem",
31
+ minValue: 0,
32
+ defaultValue: "0.33rem",
33
+ value: "0.33rem"
34
+ },
35
+ {
36
+ key: "widget-inner-padding-x",
37
+ name: "Widget Horiz Padding",
38
+ description: "Set the horizontal padding for the widgets",
39
+ cssProperty: "--bwj-widget-inner-px",
40
+ step: 0.1,
41
+ defaultUnit: "rem",
42
+ minValue: 0,
43
+ defaultValue: "1.0rem",
44
+ value: "1.0rem"
45
+ },
46
+ {
47
+ key: "widget-inner-padding-y",
48
+ name: "Widget Vertical Padding",
49
+ description: "Set the vertical padding for the widgets",
50
+ cssProperty: "--bwj-widget-inner-py",
51
+ step: 0.1,
52
+ defaultUnit: "rem",
53
+ minValue: 0,
54
+ defaultValue: "0.75rem",
55
+ value: "0.75rem"
56
+ },
57
+ {
58
+ key: "widget-header-padding-y",
59
+ name: "Widget Header Vertical Padding",
60
+ description: "Set the vertical padding for the widget headers",
61
+ cssProperty: "--bwj-widget-header-py",
62
+ step: 0.1,
63
+ defaultUnit: "rem",
64
+ minValue: 0,
65
+ defaultValue: "1.0rem",
66
+ value: "1.0rem"
67
+ },
68
+ {
69
+ key: "widget-title-font-size",
70
+ name: "Widget Title Font Size",
71
+ description: "Set the font size for the widget titles",
72
+ cssProperty: "--bwj-widget-title-size",
73
+ step: 0.1,
74
+ defaultUnit: "rem",
75
+ minValue: 0,
76
+ defaultValue: "1.0rem",
77
+ value: "1.0rem"
78
+ }
79
+ ], S = ["rem", "pc", "cm", "in", "em", "vh", "vw", "%"], b = (e, t) => S.includes(e) ? t : 1, E = {
80
+ /**
81
+ * @name incrementOrDecrementValue
82
+ * @description Increments or decrement a value based on the direction parameter
83
+ * @param item: an instance of IDashboardSettingEntry
84
+ * @param direction: -1 (for decrement) or 1 (for increment)
85
+ * @returns the update item
86
+ */
87
+ incrementOrDecrementValue: (e, t) => {
88
+ const a = e.value.match(/([\d.]+)/), i = a ? parseFloat(a[1]) : 0, s = e.value.match(/([^\d.]+)/), n = s ? s[1] : e.defaultUnit, r = b(n, e.step) * t, c = `${Math.max(i + r, e.minValue).toFixed(1)}${n}`;
89
+ return {
90
+ ...e,
91
+ value: c
92
+ };
93
+ }
94
+ }, f = (e, t) => `dashboards_${t}_${e}`, v = async (e, t, a, i) => {
95
+ const s = localStorage.getItem(f(e, t));
96
+ if (s)
97
+ try {
98
+ const n = JSON.parse(s);
99
+ return n.length < 1 ? [i] : (n.forEach((r) => {
100
+ r.dashboardId || (r.dashboardId = "default"), r.dashboardName || (r.dashboardName = `Dashboard ${r.dashboardId}`), r.responsiveGrid = r.responsiveGrid ?? !1, (r.widgets || []).length < 1 && (r.widgets = i.widgets);
101
+ const c = (r.cssSettings || []).filter(
102
+ (o) => i.cssSettings.some((d) => d.key === o.key)
103
+ );
104
+ if (c.length < 1)
105
+ r.cssSettings = [...i.cssSettings];
106
+ else {
107
+ c.forEach((d) => {
108
+ d.value = (d.value || "").replace(/NaN/g, "");
109
+ const l = i.cssSettings.find(
110
+ (g) => g.key === d.key
111
+ );
112
+ l && (Object.keys(l).forEach((g) => {
113
+ g in d || (d[g] = l[g]);
114
+ }), d.step = l.step, d.minValue = l.minValue, d.defaultValue = l.defaultValue, d.defaultUnit = l.defaultUnit, /\d+/g.test(d.value) === !1 && (d.value = l ? l.value : "1.0rem"));
115
+ });
116
+ const o = i.cssSettings.filter((d) => !c.some(
117
+ (l) => l.key === d.key
118
+ ));
119
+ r.cssSettings = [...c, ...o];
120
+ }
121
+ r.widgets = r.widgets.filter(
122
+ (o) => o.includes("WidgetContainer") || a.has(o)
123
+ ), r.childWidgetsConfig = r.childWidgetsConfig.filter(
124
+ (o) => a.has(o.widgetKey)
125
+ ), r.zoomScale ? r.zoomScale < 0.7 && (r.zoomScale = 0.7) : r.zoomScale = 1;
126
+ }), n);
127
+ } catch (n) {
128
+ console.warn("Error parsing saved dashboard config:", n);
129
+ }
130
+ return [i];
131
+ }, C = async (e, t, a, i) => {
132
+ a.forEach((n) => {
133
+ if (n.userID = e, n.clientAppKey = t, n.responsiveGrid = n.responsiveGrid ?? !1, typeof n != "object")
134
+ throw new Error("Invalid dashboard configuration");
135
+ n.widgets = n.widgets.filter(
136
+ (r) => r.includes("WidgetContainer") || i.has(r)
137
+ ), n.childWidgetsConfig = n.childWidgetsConfig.filter(
138
+ (r) => i.has(r.widgetKey)
139
+ ), n.zoomScale ? n.zoomScale < 0.7 && (n.zoomScale = 0.7) : n.zoomScale = 1;
140
+ });
141
+ const s = JSON.stringify(a);
142
+ return localStorage.setItem(f(e, t), s), !0;
143
+ }, W = {
144
+ getSavedDashboards: v,
145
+ saveDashboards: C
146
+ }, P = () => W, z = {
147
+ userID: 0,
148
+ clientAppKey: "",
149
+ dashboardId: "default",
150
+ dashboardName: "Default",
151
+ zoomScale: 1,
152
+ responsiveGrid: !1,
153
+ widgets: [],
154
+ childWidgetsConfig: [],
155
+ cssSettings: [...w]
156
+ }, U = (e) => {
157
+ const t = `${e}`.split("_");
158
+ return t.length > 1 ? t[1].replace(/(\D)(\d+)/, "$1 $2") : "Container";
159
+ }, u = 0.7, p = 1, V = 0.05, D = (e) => {
160
+ let t = Number(e || 0);
161
+ return t < u && (t = u), t > p && (t = p), t;
162
+ }, j = (e, t) => {
163
+ let a = Number(Number((V * t).toFixed(2)).toFixed(2)), i = Number((Number(e) + a).toFixed(2));
164
+ return D(i);
165
+ }, N = (e) => {
166
+ let t = {
167
+ ...e
168
+ };
169
+ return t.widgets = t.widgets.filter((a) => {
170
+ if (`${a}`.includes("WidgetContainer")) {
171
+ const i = t.childWidgetsConfig.filter(
172
+ (s) => s.parentWidgetKey === a
173
+ );
174
+ if (!i || i.length === 0)
175
+ return t.widgets = t.widgets.filter(
176
+ (s) => s !== a
177
+ ), !1;
178
+ }
179
+ return !0;
180
+ }), t;
181
+ }, x = (e) => {
182
+ const t = e.widgets.filter(
183
+ (i) => i.includes("WidgetContainer")
184
+ ), a = {};
185
+ return t.forEach((i, s) => {
186
+ const n = `${i.split("_container")[0]}_container${s + 1}`;
187
+ a[i] = n;
188
+ }), e.widgets = e.widgets.map((i) => a[i] || i), e.childWidgetsConfig = e.childWidgetsConfig.map((i) => {
189
+ const s = i.parentWidgetKey, n = a[s];
190
+ return {
191
+ ...i,
192
+ // If a new key exists, use it. If not, keep the original key.
193
+ parentWidgetKey: n || s
194
+ };
195
+ }), e;
196
+ }, m = (e, t) => {
197
+ const a = `${e}`.includes("Container"), i = a ? ["Container"] : ["Widget"], s = t?.name || e, n = t?.description || (a ? "Container" : "Unknown");
198
+ return {
199
+ name: s,
200
+ description: n,
201
+ categories: i,
202
+ noDuplicatedWidgets: !0,
203
+ icon: void 0,
204
+ externalDependencies: []
205
+ };
206
+ }, I = (e, t, a) => t[e] || m(e, a), M = (e, t) => t.get(e)?.meta || m(e), k = (e, t, a) => {
207
+ const i = a || m(e);
208
+ return [
209
+ e,
210
+ {
211
+ key: e,
212
+ title: i.name,
213
+ isContainer: `${e}`.includes("Container"),
214
+ isRemote: !1,
215
+ meta: i,
216
+ component: t
217
+ }
218
+ ];
219
+ }, h = (e, t, a, i) => {
220
+ const s = i || m(e);
221
+ return [
222
+ e,
223
+ {
224
+ key: e,
225
+ title: s.name,
226
+ isContainer: !1,
227
+ isRemote: a,
228
+ meta: s,
229
+ loader: t
230
+ }
231
+ ];
232
+ }, F = (e) => {
233
+ const t = e.match(/\/widget-([a-zA-Z0-9-]+)\/index\.ts$/);
234
+ if (t && t[1]) {
235
+ const a = t[1], i = a.split("-"), s = `Widget${i.map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join("")}`, n = i.map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join(" ");
236
+ return {
237
+ key: s,
238
+ name: n,
239
+ folder: a
240
+ };
241
+ }
242
+ return null;
243
+ }, $ = (e, t, a, i) => {
244
+ const s = `${t}/widget-${a}/meta.ts`, n = e[s];
245
+ if (!n)
246
+ return;
247
+ const r = `${i}Meta`;
248
+ return n[r] || void 0;
249
+ }, A = async (e) => new Promise(async (t, a) => {
250
+ const i = [];
251
+ try {
252
+ const s = await (await fetch(`${e}?${Math.random()}`)).json();
253
+ for (const n in s) {
254
+ const r = s[n], c = () => import(
255
+ /* @vite-ignore */
256
+ r.url
257
+ ), o = {
258
+ name: r.meta?.name || "Unknown",
259
+ description: r.meta?.description || "Remote Plugin",
260
+ categories: r.meta?.categories || ["Widget"],
261
+ noDuplicatedWidgets: r.meta?.noDuplicatedWidgets ?? !0,
262
+ icon: void 0,
263
+ // Or a logic to map a string name to a Lucide component
264
+ externalDependencies: r.meta?.externalDependencies || []
265
+ };
266
+ i.push(h(n, c, !0, o));
267
+ }
268
+ t({
269
+ entries: i,
270
+ message: "",
271
+ details: ""
272
+ });
273
+ } catch (s) {
274
+ console.error("Remote plugin discovery failed:", s), a({
275
+ entries: [],
276
+ message: "Remote plugin discovery failed:",
277
+ details: typeof s == "object" ? JSON.stringify(s) : s
278
+ });
279
+ }
280
+ }), K = (e, t, a, i = !0) => {
281
+ const s = [];
282
+ for (const n in t) {
283
+ const r = t[n], c = F(n);
284
+ if (c && r) {
285
+ const { key: o, name: d, folder: l } = c;
286
+ let g = $(a, e, l, o);
287
+ if (g || (g = m(o, {
288
+ name: d,
289
+ description: `Local ${i ? "dynamic" : "static"} widget`
290
+ })), i)
291
+ s.push(
292
+ h(o, r, !1, g)
293
+ );
294
+ else {
295
+ const y = r.default || r;
296
+ s.push(k(o, y, g));
297
+ }
298
+ }
299
+ }
300
+ return s;
301
+ }, R = (e, t = "color") => {
302
+ if (typeof window > "u") return "#FFFFFF";
303
+ const a = document.createElement("div");
304
+ Array.isArray(e) ? e.forEach((s) => a.classList.add(s)) : e.split(" ").forEach((s) => a.classList.add(s)), a.style.display = "none", document.body.appendChild(a);
305
+ const i = window.getComputedStyle(a)[t];
306
+ return document.body.removeChild(a), i;
307
+ }, G = {
308
+ /**
309
+ * @name getCssVariableValue
310
+ * @description Return the value of a CSS custom property from the current HTML document
311
+ * @param cssPropertyName
312
+ * @returns
313
+ */
314
+ getCssVariableValue: (e) => {
315
+ const t = document.documentElement;
316
+ return getComputedStyle(t).getPropertyValue(e).trim() || null;
317
+ },
318
+ /**
319
+ * @name setCssVariableValue
320
+ * @description Sets the value of a CSS custom property on the current HTML document
321
+ * @param cssPropertyName
322
+ * @param value
323
+ */
324
+ setCssVariableValue: (e, t) => {
325
+ document.documentElement.style.setProperty(e, t);
326
+ },
327
+ /**
328
+ * @name restoreCssVarsFromSettings
329
+ * @description
330
+ * Sets the values of many CSS custom properties on the current HTML document
331
+ * from the list of dashboard settings provided
332
+ * @param settings, an array of IDashboardSettingEntry
333
+ */
334
+ restoreCssVarsFromSettings: (e) => {
335
+ const t = document.documentElement;
336
+ e.forEach((a) => {
337
+ t.style.setProperty(a.cssProperty, a.value);
338
+ });
339
+ }
340
+ }, Z = (e, ...t) => [
341
+ ...new Set(
342
+ [e || "", ...t].join(" ").trim().replace(/\n+/gi, " ").replace(/\s+/gi, " ").split(" ")
343
+ )
344
+ ].join(" ").trim();
7
345
  export {
8
- E as createStaticEntry,
9
- f as localWidgetDiscovery
346
+ p as DashboardMaxZoomScale,
347
+ u as DashboardMinZoomScale,
348
+ V as DashboardZoomStep,
349
+ z as blankDashboardConfig,
350
+ h as createDynamicEntry,
351
+ k as createStaticEntry,
352
+ w as cssSettingsCatalog,
353
+ G as cssVarsUtils,
354
+ E as dashboardSettingsUtils,
355
+ x as ensureContainersSequence,
356
+ D as ensureZoomScaleIsWithinRange,
357
+ m as getDefaultWidgetMetaFromKey,
358
+ I as getDefaultWidgetMetaFromMap,
359
+ Z as getDistinctCssClasses,
360
+ $ as getMetaInfoFromFile,
361
+ j as getNewZoomScaleWithinRange,
362
+ M as getWidgetMetaFromCatalog,
363
+ K as localWidgetDiscovery,
364
+ U as parseContainerTitle,
365
+ F as parseKeyAndTitleFromFilePath,
366
+ A as remoteWidgetDiscovery,
367
+ N as removeEmptyContainers,
368
+ R as resolveColorFromClass,
369
+ P as useDashboardStorageService
10
370
  };
@@ -1,5 +1,5 @@
1
- import { reactive as de, computed as v, readonly as we, defineComponent as b, createElementBlock as f, openBlock as l, normalizeClass as C, createElementVNode as o, createStaticVNode as se, withModifiers as z, normalizeStyle as oe, renderSlot as V, mergeProps as q, createBlock as E, withCtx as K, unref as x, toDisplayString as B, ref as j, onMounted as xe, onUnmounted as ye, createVNode as I, Fragment as U, renderList as P, shallowRef as ne, watchEffect as be, markRaw as Q, defineAsyncComponent as _e, resolveComponent as ke, Suspense as $e, resolveDynamicComponent as le, createSlots as Ie, createTextVNode as ce, withKeys as ie, watch as De, createCommentVNode as Y } from "vue";
2
- import { blankDashboardConfig as te, ensureContainersSequence as We, getDistinctCssClasses as T, ensureZoomScaleIsWithinRange as Ke, parseContainerTitle as ue, dashboardSettingsUtils as Be, getWidgetMetaFromCatalog as Me } from "@tenorlab/vue-dashboard/core";
1
+ import { reactive as de, computed as v, readonly as we, defineComponent as b, createElementBlock as f, openBlock as l, normalizeClass as C, createElementVNode as o, createStaticVNode as se, withModifiers as z, normalizeStyle as oe, renderSlot as H, mergeProps as q, createBlock as E, withCtx as K, unref as x, toDisplayString as B, ref as R, onMounted as xe, onUnmounted as ye, createVNode as I, Fragment as U, renderList as P, shallowRef as ne, watchEffect as be, markRaw as Q, defineAsyncComponent as _e, resolveComponent as ke, Suspense as $e, resolveDynamicComponent as le, createSlots as Ie, createTextVNode as ce, withKeys as ie, watch as De, createCommentVNode as Y } from "vue";
2
+ import { blankDashboardConfig as te, ensureContainersSequence as We, getDistinctCssClasses as T, ensureZoomScaleIsWithinRange as Ke, parseContainerTitle as ue, dashboardSettingsUtils as Be, getWidgetMetaFromCatalog as Me } from "./core.es.js";
3
3
  const Ee = (t) => {
4
4
  const s = t.widgets.filter((n) => n.includes("WidgetContainer")).map((n) => Number(n.split("_")[1].replace("container", "")));
5
5
  return `container${s.length > 0 ? Math.max(...s) + 1 : 1}`;
@@ -205,13 +205,13 @@ const Ee = (t) => {
205
205
  addWidget: (t) => N.addWidget(t),
206
206
  removeWidget: (t, s) => N.removeWidget(t, s),
207
207
  moveWidget: (t, s, e) => N.moveWidget(t, s, e)
208
- }, He = {
208
+ }, je = {
209
209
  getNextContainerKey: (t) => Se(y.currentDashboardConfig, t),
210
210
  getCurrentDashboardConfig: () => y.currentDashboardConfig,
211
211
  getCurrentDashboardId: () => y.currentDashboardConfig.dashboardId,
212
212
  getIsResponsive: () => y.currentDashboardConfig.responsiveGrid || !1,
213
213
  getTargetContainerKey: () => y.targetContainerKey
214
- }, Ve = {
214
+ }, He = {
215
215
  isLoading: v(() => y.isLoading),
216
216
  isEditing: v(() => y.isEditing),
217
217
  targetContainerKey: v(() => y.targetContainerKey),
@@ -220,18 +220,18 @@ const Ee = (t) => {
220
220
  const e = t.dashboardId === "default", n = s.dashboardId === "default";
221
221
  return e && !n ? -1 : n && !e ? 1 : t.dashboardId.localeCompare(s.dashboardId);
222
222
  }))
223
- }, je = {
223
+ }, Re = {
224
224
  ...re,
225
225
  actions: re,
226
- getters: He,
227
- computed: Ve
228
- }, gs = () => je, S = de({
226
+ getters: je,
227
+ computed: He
228
+ }, gs = () => Re, S = de({
229
229
  currentDashboardId: "",
230
230
  undoHistory: {},
231
231
  historyIndex: {}
232
232
  }), G = (t) => S.undoHistory[t] || [], Z = (t) => S.historyIndex[t] ?? -1, X = (t, s) => {
233
233
  S.historyIndex[t] = s;
234
- }, Re = (t) => {
234
+ }, Ve = (t) => {
235
235
  const s = t.dashboardId;
236
236
  if (S.currentDashboardId !== s) {
237
237
  S.currentDashboardId = s;
@@ -267,7 +267,7 @@ const Ee = (t) => {
267
267
  _historyLength: e
268
268
  };
269
269
  }, Oe = v(() => ge()), ps = () => ({
270
- initializeHistoryForDashboard: Re,
270
+ initializeHistoryForDashboard: Ve,
271
271
  resetAllHistory: () => {
272
272
  S.undoHistory = {}, S.historyIndex = {};
273
273
  },
@@ -900,7 +900,7 @@ const hs = /* @__PURE__ */ b({
900
900
  o("path", { d: "M12 17h.01" }, null, -1)
901
901
  ])], 2));
902
902
  }
903
- }), tt = ["title", "disabled"], H = /* @__PURE__ */ b({
903
+ }), tt = ["title", "disabled"], j = /* @__PURE__ */ b({
904
904
  __name: "Button",
905
905
  props: {
906
906
  disabled: { type: Boolean, default: !1 },
@@ -935,7 +935,7 @@ const hs = /* @__PURE__ */ b({
935
935
  const d = e.isIconButton || !1, p = e.category || "primary", c = e.type || "normal", m = e.disabled || !1, _ = e.className || "", k = e.font || "", W = Number((e.border || 0) > 0 ? e.border : 0);
936
936
  let M = (e.borderColor || "").trim();
937
937
  M = M.length > 0 ? M : "";
938
- const L = Number((e.borderHover || 0) > 0 ? e.borderHover : 0), R = e.shadow || "sm", $ = e.shadowHover || "md", D = (e.addCss || "").trim(), h = e.justifyCss || "justify-center";
938
+ const L = Number((e.borderHover || 0) > 0 ? e.borderHover : 0), V = e.shadow || "sm", $ = e.shadowHover || "md", D = (e.addCss || "").trim(), h = e.justifyCss || "justify-center";
939
939
  if (d)
940
940
  return T(
941
941
  "flex flex-row items-center",
@@ -958,7 +958,7 @@ const hs = /* @__PURE__ */ b({
958
958
  const A = u.replaceAll("[category]", p).trim();
959
959
  a.push(A);
960
960
  }
961
- return W > 0 ? (a.push(`border-[${W}px]`), a.push(`border-${M}`)) : (a.push("border-[1px]"), a.push("border-transparent")), L > 0 ? (a.push(`hover:border-[${L}px] group-hover:border-[${L}px]`), a.push(`hover:border-${M} group-hover:border-${M}`)) : a.push("hover:border-[1px] group-hover:border-[1px]"), a.push(`shadow-${R}`), a.push(`hover:shadow-${$} group-hover:shadow-${$}`), D.length > 0 && a.push(D), D.indexOf("hidden") === -1 && a.push("inline-flex"), a.push(h), a.join(" ").trim();
961
+ return W > 0 ? (a.push(`border-[${W}px]`), a.push(`border-${M}`)) : (a.push("border-[1px]"), a.push("border-transparent")), L > 0 ? (a.push(`hover:border-[${L}px] group-hover:border-[${L}px]`), a.push(`hover:border-${M} group-hover:border-${M}`)) : a.push("hover:border-[1px] group-hover:border-[1px]"), a.push(`shadow-${V}`), a.push(`hover:shadow-${$} group-hover:shadow-${$}`), D.length > 0 && a.push(D), D.indexOf("hidden") === -1 && a.push("inline-flex"), a.push(h), a.join(" ").trim();
962
962
  }), g = v(() => ({
963
963
  padding: e.isIconButton ? 0 : `${e.py}rem ${e.px}rem `
964
964
  })), w = (d) => {
@@ -976,7 +976,7 @@ const hs = /* @__PURE__ */ b({
976
976
  disabled: t.disabled,
977
977
  onClick: z(w, ["stop"])
978
978
  }, [
979
- V(d.$slots, "default")
979
+ H(d.$slots, "default")
980
980
  ], 14, tt));
981
981
  }
982
982
  }), st = ["data-testid"], ot = /* @__PURE__ */ b({
@@ -996,7 +996,7 @@ const hs = /* @__PURE__ */ b({
996
996
  "data-testid": t.testId || "not-set",
997
997
  class: n.value
998
998
  }, e.value), [
999
- V(i.$slots, "default")
999
+ H(i.$slots, "default")
1000
1000
  ], 16, st));
1001
1001
  }
1002
1002
  }), ks = /* @__PURE__ */ b({
@@ -1025,7 +1025,7 @@ const hs = /* @__PURE__ */ b({
1025
1025
  o("div", {
1026
1026
  class: C(x(i))
1027
1027
  }, [
1028
- V(r.$slots, "default")
1028
+ H(r.$slots, "default")
1029
1029
  ], 2)
1030
1030
  ]),
1031
1031
  _: 3
@@ -1080,7 +1080,7 @@ const hs = /* @__PURE__ */ b({
1080
1080
  },
1081
1081
  emits: ["draggingChange"],
1082
1082
  setup(t, { emit: s }) {
1083
- const e = t, n = s, i = j(null), r = j({ x: 0, y: 0 }), g = j({ x: 0, y: 0 }), w = j({ x: 0, y: 0 }), d = {
1083
+ const e = t, n = s, i = R(null), r = R({ x: 0, y: 0 }), g = R({ x: 0, y: 0 }), w = R({ x: 0, y: 0 }), d = {
1084
1084
  // 1. Take it out of the document flow
1085
1085
  position: "fixed",
1086
1086
  // 2. Set initial viewport position (e.g., top right)
@@ -1127,7 +1127,7 @@ const hs = /* @__PURE__ */ b({
1127
1127
  class: C(e.className),
1128
1128
  style: oe(p.value)
1129
1129
  }, [
1130
- V(k.$slots, "default")
1130
+ H(k.$slots, "default")
1131
1131
  ], 14, at));
1132
1132
  }
1133
1133
  }), Ce = (t, s) => {
@@ -1141,13 +1141,13 @@ const hs = /* @__PURE__ */ b({
1141
1141
  };
1142
1142
  function ut(t, s) {
1143
1143
  return l(), f("div", ct, [
1144
- V(t.$slots, "default")
1144
+ H(t.$slots, "default")
1145
1145
  ]);
1146
1146
  }
1147
1147
  const $s = /* @__PURE__ */ Ce(lt, [["render", ut]]), gt = {}, pt = { className: "w-full flex flex-col items-end" };
1148
1148
  function ht(t, s) {
1149
1149
  return l(), f("div", pt, [
1150
- V(t.$slots, "default")
1150
+ H(t.$slots, "default")
1151
1151
  ]);
1152
1152
  }
1153
1153
  const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
@@ -1176,7 +1176,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1176
1176
  class: C(i.value),
1177
1177
  style: oe(n.value)
1178
1178
  }, [
1179
- V(r.$slots, "default")
1179
+ H(r.$slots, "default")
1180
1180
  ], 6));
1181
1181
  }
1182
1182
  }), mt = { class: "widget-title-wrapper w-full flex flex-row gap-2 items-center justify-between" }, ft = { class: "widget-title" }, Ct = { "data-testid": "collapse-and-other-actions" }, vt = { class: "actions-inner" }, wt = { class: "actions-buttons-container" }, xt = { class: "widget-inner" }, J = "size-5", yt = /* @__PURE__ */ b({
@@ -1234,7 +1234,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1234
1234
  o("span", { class: "hidden" }, "Widget")
1235
1235
  ], -1)),
1236
1236
  o("div", wt, [
1237
- I(x(H), {
1237
+ I(x(j), {
1238
1238
  "data-testid": `move-widget-left_${e.title}`,
1239
1239
  isIconButton: !0,
1240
1240
  disabled: e.index < 1,
@@ -1251,7 +1251,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1251
1251
  ]),
1252
1252
  _: 1
1253
1253
  }, 8, ["data-testid", "disabled", "tooltip"]),
1254
- I(x(H), {
1254
+ I(x(j), {
1255
1255
  "data-testid": `move-widget-right_${e.title}`,
1256
1256
  isIconButton: !0,
1257
1257
  disabled: e.index >= e.maxIndex,
@@ -1268,7 +1268,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1268
1268
  ]),
1269
1269
  _: 1
1270
1270
  }, 8, ["data-testid", "disabled", "tooltip"]),
1271
- I(x(H), {
1271
+ I(x(j), {
1272
1272
  "data-testid": `remove-container_${e.title}`,
1273
1273
  isIconButton: !0,
1274
1274
  tooltip: {
@@ -1289,7 +1289,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1289
1289
  ])
1290
1290
  ], 2),
1291
1291
  o("div", xt, [
1292
- V(p.$slots, "default")
1292
+ H(p.$slots, "default")
1293
1293
  ])
1294
1294
  ], 2));
1295
1295
  }
@@ -1432,7 +1432,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1432
1432
  r.removeClick($, D);
1433
1433
  }, L = ($, D, h) => {
1434
1434
  r.moveClick($, D, h);
1435
- }, R = ($) => {
1435
+ }, V = ($) => {
1436
1436
  r.selectContainer($);
1437
1437
  };
1438
1438
  return ($, D) => {
@@ -1452,7 +1452,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1452
1452
  extraProps: k.value,
1453
1453
  onRemoveClick: M,
1454
1454
  onMoveClick: L,
1455
- onSelectContainer: R
1455
+ onSelectContainer: V
1456
1456
  }, Ie({ _: 2 }, [
1457
1457
  w.value ? {
1458
1458
  name: "default",
@@ -1488,7 +1488,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1488
1488
  });
1489
1489
  };
1490
1490
  }
1491
- }), zt = ["data-testid"], Ht = { class: "text-sm font-semibold capitalize" }, Vt = { "data-testid": "collapse-and-other-actions" }, jt = { class: "actions-inner" }, Rt = { class: "actions-buttons-container" }, At = ["data-testid"], O = "size-5", Ut = "border-transparent", Pt = "border-card-invert", ve = /* @__PURE__ */ b({
1491
+ }), zt = ["data-testid"], jt = { class: "text-sm font-semibold capitalize" }, Ht = { "data-testid": "collapse-and-other-actions" }, Rt = { class: "actions-inner" }, Vt = { class: "actions-buttons-container" }, At = ["data-testid"], O = "size-5", Ut = "border-transparent", Pt = "border-card-invert", ve = /* @__PURE__ */ b({
1492
1492
  __name: "WidgetContainer",
1493
1493
  props: {
1494
1494
  index: {},
@@ -1551,12 +1551,12 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1551
1551
  class: "widget-title-wrapper w-full flex whitespace-nowrap",
1552
1552
  onClick: z(m, ["stop"])
1553
1553
  }, [
1554
- o("span", Ht, B(e.title), 1)
1554
+ o("span", jt, B(e.title), 1)
1555
1555
  ]),
1556
- o("div", Vt, [
1557
- o("div", jt, [
1558
- o("div", Rt, [
1559
- I(x(H), {
1556
+ o("div", Ht, [
1557
+ o("div", Rt, [
1558
+ o("div", Vt, [
1559
+ I(x(j), {
1560
1560
  "data-testid": `open-widgets-catalog-from-container_${e.title}`,
1561
1561
  isIconButton: !0,
1562
1562
  class: "whitespace-nowrap",
@@ -1570,7 +1570,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1570
1570
  ]),
1571
1571
  _: 1
1572
1572
  }, 8, ["data-testid"]),
1573
- I(x(H), {
1573
+ I(x(j), {
1574
1574
  "data-testid": `move-container-left_${e.title}`,
1575
1575
  isIconButton: !0,
1576
1576
  disabled: e.index < 1,
@@ -1587,7 +1587,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1587
1587
  ]),
1588
1588
  _: 1
1589
1589
  }, 8, ["data-testid", "disabled", "tooltip"]),
1590
- I(x(H), {
1590
+ I(x(j), {
1591
1591
  "data-testid": `move-container-right_${e.title}`,
1592
1592
  isIconButton: !0,
1593
1593
  disabled: e.index >= e.maxIndex,
@@ -1604,7 +1604,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1604
1604
  ]),
1605
1605
  _: 1
1606
1606
  }, 8, ["data-testid", "disabled", "tooltip"]),
1607
- I(x(H), {
1607
+ I(x(j), {
1608
1608
  "data-testid": `remove-container_${e.title}`,
1609
1609
  isIconButton: !0,
1610
1610
  tooltip: { placement: "top", title: "Remove Container" },
@@ -1625,7 +1625,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1625
1625
  "data-testid": `childrenwrapper_${e.widgetKey}`,
1626
1626
  class: "widget-container-inner"
1627
1627
  }, [
1628
- V(_.$slots, "default")
1628
+ H(_.$slots, "default")
1629
1629
  ], 8, At)
1630
1630
  ], 10, zt));
1631
1631
  }
@@ -1662,7 +1662,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1662
1662
  onSelectContainer: x(g)
1663
1663
  }), {
1664
1664
  default: K(() => [
1665
- V(d.$slots, "default")
1665
+ H(d.$slots, "default")
1666
1666
  ]),
1667
1667
  _: 3
1668
1668
  }, 16, ["onRemoveClick", "onMoveClick", "onSelectContainer"]));
@@ -1700,7 +1700,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1700
1700
  onSelectContainer: x(g)
1701
1701
  }), {
1702
1702
  default: K(() => [
1703
- V(d.$slots, "default")
1703
+ H(d.$slots, "default")
1704
1704
  ]),
1705
1705
  _: 3
1706
1706
  }, 16, ["onRemoveClick", "onMoveClick", "onSelectContainer"]));
@@ -1804,7 +1804,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1804
1804
  const s = t, e = (h, a) => [
1805
1805
  ...a.widgets.filter((A) => A.indexOf("Container") === -1),
1806
1806
  ...a.childWidgetsConfig.map((A) => A.widgetKey)
1807
- ].includes(h), n = j("Editing"), i = j(0), r = j(""), g = j(!1), w = v(() => Array.from(s.widgetsCatalog.keys())), d = v(() => w.value.map((h) => ({
1807
+ ].includes(h), n = R("Editing"), i = R(0), r = R(""), g = R(!1), w = v(() => Array.from(s.widgetsCatalog.keys())), d = v(() => w.value.map((h) => ({
1808
1808
  widgetKey: h,
1809
1809
  metaData: Me(h, s.widgetsCatalog)
1810
1810
  }))), p = v(() => d.value.filter(
@@ -1824,7 +1824,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1824
1824
  }, L = (h) => T(
1825
1825
  "px-4 py-2 font-medium cursor-pointer border-b-2 border-transparent hover:border-primary focus:outline-none",
1826
1826
  h === i.value ? "text-primary border-primary" : ""
1827
- ), R = (h) => {
1827
+ ), V = (h) => {
1828
1828
  _.value ? s.addWidget(h, s.targetContainerKey) : s.addWidget(h);
1829
1829
  }, $ = (h) => {
1830
1830
  const a = (s.currentDashboardConfig.cssSettings || []).map((u) => u.key === h.key ? h : u);
@@ -1872,7 +1872,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1872
1872
  }, B(n.value), 9, ns)
1873
1873
  ]),
1874
1874
  o("div", is, [
1875
- I(x(H), {
1875
+ I(x(j), {
1876
1876
  "data-testid": "undo-dashboard-config-change",
1877
1877
  isIconButton: !0,
1878
1878
  tooltip: {
@@ -1887,7 +1887,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1887
1887
  ]),
1888
1888
  _: 1
1889
1889
  }, 8, ["disabled"]),
1890
- I(x(H), {
1890
+ I(x(j), {
1891
1891
  "data-testid": "redo-dashboard-config-change",
1892
1892
  isIconButton: !0,
1893
1893
  tooltip: {
@@ -1902,7 +1902,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1902
1902
  ]),
1903
1903
  _: 1
1904
1904
  }, 8, ["disabled"]),
1905
- I(x(H), {
1905
+ I(x(j), {
1906
1906
  "data-testid": "reset-dashboard-to-default",
1907
1907
  isIconButton: !0,
1908
1908
  tooltip: {
@@ -1958,13 +1958,13 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1958
1958
  widgetKey: u.widgetKey,
1959
1959
  metaData: u.metaData,
1960
1960
  alreadyAdded: e(u.widgetKey, t.currentDashboardConfig),
1961
- onAddWidget: () => R(u.widgetKey)
1961
+ onAddWidget: () => V(u.widgetKey)
1962
1962
  }, null, 8, ["widgetKey", "metaData", "alreadyAdded", "onAddWidget"]))), 128)) : i.value === 1 ? (l(!0), f(U, { key: 1 }, P(c.value, (u) => (l(), E(ee, {
1963
1963
  key: u.widgetKey,
1964
1964
  widgetKey: u.widgetKey,
1965
1965
  metaData: u.metaData,
1966
1966
  alreadyAdded: e(u.widgetKey, t.currentDashboardConfig),
1967
- onAddWidget: () => R(u.widgetKey)
1967
+ onAddWidget: () => V(u.widgetKey)
1968
1968
  }, null, 8, ["widgetKey", "metaData", "alreadyAdded", "onAddWidget"]))), 128)) : i.value === 2 && !_.value ? (l(!0), f(U, { key: 2 }, P(m.value, (u) => (l(), E(ee, {
1969
1969
  key: u.widgetKey,
1970
1970
  widgetKey: u.widgetKey,
@@ -1980,7 +1980,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
1980
1980
  }, null, 8, ["item"]))), 128)) : Y("", !0)
1981
1981
  ]),
1982
1982
  o("div", ls, [
1983
- I(x(H), {
1983
+ I(x(j), {
1984
1984
  class: "bg-opacity-100",
1985
1985
  tooltip: {
1986
1986
  placement: "bottom",
@@ -2002,7 +2002,7 @@ const Is = /* @__PURE__ */ Ce(gt, [["render", ht]]), Ds = (t) => {
2002
2002
  });
2003
2003
  export {
2004
2004
  hs as AddIcon,
2005
- H as Button,
2005
+ j as Button,
2006
2006
  et as CircleQuestionMarkIcon,
2007
2007
  Je as CrosshairIcon,
2008
2008
  Ws as DashboardGrid,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenorlab/vue-dashboard",
3
- "version": "1.4.903",
3
+ "version": "1.5.2",
4
4
  "description": "Foundation components for creating user-configurable dashboards in Vue",
5
5
  "author": "Damiano Fusco",
6
6
  "type": "module",
@@ -47,7 +47,7 @@
47
47
  "main": "./dist/vue-dashboard.es.js",
48
48
  "module": "./dist/vue-dashboard.es.js",
49
49
  "devDependencies": {
50
- "@tenorlab/dashboard-core": "^1.5.1",
50
+ "@tenorlab/dashboard-core": "^1.5.2",
51
51
  "@types/node": "^24.10.1",
52
52
  "@vitejs/plugin-vue": "^6.0.3",
53
53
  "prettier": "^3.7.4",