@dashadmin/dash-boilerplate 1.3.16

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 (3) hide show
  1. package/dist/index.js +827 -0
  2. package/package.json +56 -0
  3. package/src/index.ts +84 -0
package/dist/index.js ADDED
@@ -0,0 +1,827 @@
1
+ import { jsx as c, jsxs as y, Fragment as U } from "react/jsx-runtime";
2
+ import A, { createContext as $, useState as v, useCallback as T, useEffect as p, useMemo as E, useContext as V, useTransition as _, Suspense as J } from "react";
3
+ import { ErrorBoundary as G } from "react-error-boundary";
4
+ import K from "@mui/material/CssBaseline";
5
+ import { ThemeProvider as Q, createTheme as X } from "@mui/material";
6
+ import { updateDomCssVariables as I, dashStorage as Y } from "@dashadmin/dash-utils";
7
+ import { useDispatch as B } from "react-redux";
8
+ import { syncDeviceStoreToLocalStorage as Z, syncLocalStorageToDeviceStore as D, AuthPersistenceService as f } from "@dashadmin/dash-auth";
9
+ import { DASH_REDUX_ACTIONS as S } from "@dashadmin/dash-admin-state";
10
+ import { ACTION_UPDATE_AUTH as P } from "@dashadmin/dash-admin-state/src/redux/reducers/Auth";
11
+ import z from "@dashadmin/dash-admin/src/contexts/auth/DASHAuthenticationService";
12
+ const M = (t, e) => e.split(".").reduce((o, r) => o ? o[r] : null, t), N = (t, e) => !e || !t ? t : Object.keys(e).reduce((o, r) => o.replace(new RegExp(`%\\{${r}\\}`, "g"), String(e[r])), t), ee = [
13
+ { locale: "en", name: "English" },
14
+ { locale: "es", name: "EspaΓ±ol" }
15
+ ], Ce = (t) => {
16
+ const {
17
+ translations: e,
18
+ initialLocale: o = "es",
19
+ fallbackLocale: r = "en",
20
+ locales: a = ee,
21
+ onLocaleChange: s
22
+ } = t;
23
+ let n = o;
24
+ return {
25
+ translate: (i, b) => {
26
+ const C = e[n] || e[r] || {}, x = M(C, i);
27
+ if (typeof x == "string")
28
+ return N(x, b);
29
+ if (n !== r) {
30
+ const j = e[r] || {}, R = M(j, i);
31
+ if (typeof R == "string")
32
+ return N(R, b);
33
+ }
34
+ return i;
35
+ },
36
+ changeLocale: async (i) => e[i] ? (n = i, localStorage.setItem("dash-user-locale", i), s?.(i), Promise.resolve()) : Promise.reject(new Error(`Locale '${i}' not found`)),
37
+ getLocale: () => n,
38
+ getLocales: () => a,
39
+ getMessages: (i) => e[i] || {}
40
+ };
41
+ }, H = "dash:locale-change", te = {
42
+ i18nProvider: null,
43
+ locale: "es",
44
+ setI18nProvider: () => {
45
+ },
46
+ setLocale: () => {
47
+ }
48
+ }, q = $(te), Ee = ({
49
+ children: t,
50
+ defaultLocale: e = "es"
51
+ }) => {
52
+ const [o, r] = v(null), [a, s] = v(() => typeof window < "u" && localStorage.getItem("dash-user-locale") || e), n = T(async (l) => {
53
+ console.log("🌐 I18nBridgeProviderLight: Setting bridged i18nProvider", {
54
+ providerLocale: l?.getLocale?.(),
55
+ desiredLocale: a
56
+ }), r(l);
57
+ const u = l?.getLocale?.();
58
+ if (u && u !== a && l?.changeLocale) {
59
+ console.log(`🌐 I18nBridgeProviderLight: Provider locale (${u}) differs from desired (${a}), switching...`);
60
+ try {
61
+ await l.changeLocale(a), console.log(`🌐 I18nBridgeProviderLight: Successfully switched provider to ${a}`);
62
+ } catch (m) {
63
+ console.warn("🌐 I18nBridgeProviderLight: Failed to switch provider locale:", m);
64
+ }
65
+ } else l?.getLocale && s(l.getLocale());
66
+ }, [a]);
67
+ p(() => {
68
+ const l = async (u) => {
69
+ const g = u.detail?.locale;
70
+ if (g && g !== a) {
71
+ if (console.log("🌐 I18nBridgeProviderLight: Received locale change event:", g), o?.changeLocale)
72
+ try {
73
+ await o.changeLocale(g);
74
+ } catch (i) {
75
+ console.warn("Failed to change provider locale:", i);
76
+ }
77
+ s(g);
78
+ }
79
+ };
80
+ return window.addEventListener(H, l), () => {
81
+ window.removeEventListener(H, l);
82
+ };
83
+ }, [o, a]);
84
+ const d = E(() => ({
85
+ i18nProvider: o,
86
+ locale: a,
87
+ setI18nProvider: n,
88
+ setLocale: s
89
+ }), [o, a, n]);
90
+ return /* @__PURE__ */ c(q.Provider, { value: d, children: t });
91
+ }, k = () => V(q), Pe = () => {
92
+ const { i18nProvider: t } = k();
93
+ return E(() => t?.getLocales ? t.getLocales() : [], [t]);
94
+ }, Be = () => {
95
+ const { i18nProvider: t, setLocale: e } = k();
96
+ return T(async (r) => {
97
+ t?.changeLocale && (await t.changeLocale(r), e(r));
98
+ }, [t, e]);
99
+ }, ke = () => {
100
+ const { locale: t } = k();
101
+ return t;
102
+ }, Ie = () => {
103
+ const { i18nProvider: t } = k();
104
+ return T((o, r) => t?.translate ? t.translate(o, r) : o, [t]);
105
+ }, O = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32px" height="32px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" viewBox="0 0 16 16"><g><path style="opacity:1" fill="#FFFFFF" d="M11.506 12.388q0.306 0.011 0.617 0.008v1.281h-0.89a2 2 0 0 1 -0.898 -0.215 1.24 1.24 0 0 1 -0.629 -0.761 2.5 2.5 0 0 1 -0.094 -0.554q-0.006 -1.082 -0.004 -2.163h-0.609q0.002 -0.398 -0.004 -0.796a616 616 0 0 0 -1.676 2.023 657 657 0 0 0 2.069 2.46q-0.935 0.012 -1.874 0.008L6.003 11.61q-0.006 1.035 -0.004 2.069H4.485q0.004 -2.983 -0.008 -5.966 -0.661 -0.21 -0.863 -0.875a2 2 0 0 1 -0.039 -0.258q-0.008 -2.108 0 -4.217 0.12 -0.356 0.48 -0.246 0.153 0.079 0.191 0.246l0.008 3.272q0.05 0.116 0.168 0.066 0.035 -0.027 0.051 -0.066l0.008 -3.264q0.095 -0.329 0.433 -0.269 0.191 0.059 0.238 0.254l0.008 3.272q0.065 0.14 0.195 0.055l0.023 -0.039 0.008 -3.264q0.086 -0.321 0.418 -0.285 0.197 0.057 0.254 0.254a352 352 0 0 1 0.016 3.295q0.062 0.109 0.176 0.051 0.029 -0.028 0.043 -0.066l0.008 -3.28q0.045 -0.17 0.207 -0.238 0.25 -0.074 0.41 0.129a0.5 0.5 0 0 1 0.047 0.109q0.014 1.063 0.012 2.128 0.002 1.088 -0.012 2.175 -0.137 0.844 -0.96 1.078a301 301 0 0 0 0 3.006q0.753 -1.005 1.503 -2.011 1.05 -0.006 2.101 -0.004 0.002 -0.519 -0.004 -1.039a1.82 1.82 0 0 1 -1.281 -1.101q-0.197 -0.504 -0.211 -1.046a4.7 4.7 0 0 1 0.383 -2.03q0.242 -0.547 0.668 -0.964 0.395 -0.364 0.929 -0.445 0.695 -0.056 1.218 0.398 0.476 0.438 0.73 1.035 0.513 1.212 0.32 2.514a2.26 2.26 0 0 1 -0.484 1.07 1.75 1.75 0 0 1 -0.754 0.5v1.109h0.992v1.265h-0.992q-0.002 1.042 0.004 2.085 0.05 0.323 0.379 0.32"/></g></svg>', oe = () => /* @__PURE__ */ c("span", { dangerouslySetInnerHTML: { __html: O } }), ze = ({
106
+ message: t,
107
+ showMessage: e = !1
108
+ }) => /* @__PURE__ */ y("div", { children: [
109
+ /* @__PURE__ */ y("div", { className: "initial-loader", children: [
110
+ /* @__PURE__ */ c("div", { className: "initial-loader-spinner" }),
111
+ /* @__PURE__ */ c("span", { className: "initial-loader-icon", children: /* @__PURE__ */ c(oe, {}) })
112
+ ] }),
113
+ e && t && /* @__PURE__ */ c("div", { className: "initial-loader-text", children: t })
114
+ ] }), Ae = `<div class="initial-loader">
115
+ <div class="initial-loader-spinner">
116
+ <span class="initial-loader-icon">
117
+ ${O}
118
+ </span>
119
+ </div>
120
+ <div class="initial-loader-text"></div>
121
+ </div>`, Te = () => {
122
+ if (typeof document > "u" || document.getElementById("critical-loading-styles")) return;
123
+ const t = document.createElement("style");
124
+ t.id = "critical-loading-styles", t.textContent = `
125
+ .initial-loader {
126
+ position: fixed;
127
+ top: 0;
128
+ left: 0;
129
+ right: 0;
130
+ bottom: 0;
131
+ display: flex;
132
+ flex-direction: column;
133
+ justify-content: center;
134
+ align-items: center;
135
+ color: var(--text-color, #fff);
136
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
137
+ z-index: 9999;
138
+ }
139
+ .initial-loader-spinner {
140
+ width: 40px;
141
+ height: 40px;
142
+ border: 3px solid rgba(255,255,255,0.1);
143
+ border-top-color: var(--primary-color, #3f51b5);
144
+ border-radius: 50%;
145
+ animation: spin 1s linear infinite;
146
+ position: relative;
147
+ display: flex;
148
+ justify-content: center;
149
+ align-items: center;
150
+ }
151
+ .initial-loader-icon {
152
+ position: absolute;
153
+ top: 50%;
154
+ left: 50%;
155
+ width: 16px;
156
+ height: 16px;
157
+ transform: translate(-50%, -50%);
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: center;
161
+ pointer-events: none;
162
+ }
163
+ .initial-loader-text {
164
+ margin-top: 16px;
165
+ font-size: 14px;
166
+ opacity: 0.7;
167
+ }
168
+ @keyframes spin {
169
+ to { transform: rotate(360deg); }
170
+ }
171
+ `, document.head.appendChild(t);
172
+ };
173
+ class Re extends A.Component {
174
+ constructor(e) {
175
+ super(e), this.state = { hasError: !1 };
176
+ }
177
+ static getDerivedStateFromError(e) {
178
+ return { hasError: !0, error: e };
179
+ }
180
+ componentDidCatch(e, o) {
181
+ console.error("CustomErrorBoundary caught error:", e, o), this.props.onError?.(e, o);
182
+ }
183
+ handleReload = () => {
184
+ window.location.reload();
185
+ };
186
+ render() {
187
+ return this.state.hasError ? this.props.fallback ? this.props.fallback : /* @__PURE__ */ y(
188
+ "div",
189
+ {
190
+ style: {
191
+ display: "flex",
192
+ justifyContent: "center",
193
+ alignItems: "center",
194
+ height: "100vh",
195
+ backgroundColor: "var(--bodybg-primary, #121212)",
196
+ color: "var(--text-color, #ffffff)",
197
+ flexDirection: "column",
198
+ gap: "20px"
199
+ },
200
+ children: [
201
+ /* @__PURE__ */ c("h2", { children: "Something went wrong" }),
202
+ /* @__PURE__ */ c("p", { style: { opacity: 0.8 }, children: this.state.error?.message }),
203
+ /* @__PURE__ */ c(
204
+ "button",
205
+ {
206
+ onClick: this.handleReload,
207
+ style: {
208
+ padding: "10px 20px",
209
+ backgroundColor: "var(--primary-color, #007bff)",
210
+ color: "white",
211
+ border: "none",
212
+ borderRadius: "4px",
213
+ cursor: "pointer",
214
+ fontSize: "14px",
215
+ fontWeight: 500
216
+ },
217
+ children: "Reload Page"
218
+ }
219
+ )
220
+ ]
221
+ }
222
+ ) : this.props.children;
223
+ }
224
+ }
225
+ const re = ({ error: t, resetErrorBoundary: e }) => /* @__PURE__ */ y(
226
+ "div",
227
+ {
228
+ style: {
229
+ display: "flex",
230
+ flexDirection: "column",
231
+ alignItems: "center",
232
+ justifyContent: "center",
233
+ height: "100vh",
234
+ gap: "16px",
235
+ color: "var(--text-color)",
236
+ backgroundColor: "var(--bodybg-primary)"
237
+ },
238
+ children: [
239
+ /* @__PURE__ */ c("h1", { style: { margin: 0, fontSize: "1.5rem" }, children: "Something went wrong" }),
240
+ /* @__PURE__ */ c("p", { style: { margin: 0, opacity: 0.8 }, children: t?.message || "Unknown error" }),
241
+ /* @__PURE__ */ c(
242
+ "button",
243
+ {
244
+ onClick: e,
245
+ style: {
246
+ padding: "8px 24px",
247
+ backgroundColor: "var(--primary-color)",
248
+ color: "var(--primary-contrast)",
249
+ border: "none",
250
+ borderRadius: "4px",
251
+ cursor: "pointer",
252
+ fontSize: "14px",
253
+ fontWeight: 500
254
+ },
255
+ children: "Try Again"
256
+ }
257
+ )
258
+ ]
259
+ }
260
+ ), ne = () => /* @__PURE__ */ y(
261
+ "div",
262
+ {
263
+ style: {
264
+ display: "flex",
265
+ justifyContent: "center",
266
+ alignItems: "center",
267
+ height: "100vh",
268
+ backgroundColor: "var(--bodybg-primary)"
269
+ },
270
+ children: [
271
+ /* @__PURE__ */ c(
272
+ "div",
273
+ {
274
+ className: "loading-spinner",
275
+ style: {
276
+ width: "40px",
277
+ height: "40px",
278
+ border: "3px solid rgba(255,255,255,0.1)",
279
+ borderTopColor: "var(--primary-color)",
280
+ borderRadius: "50%",
281
+ animation: "spin 1s linear infinite"
282
+ }
283
+ }
284
+ ),
285
+ /* @__PURE__ */ c("style", { children: `
286
+ @keyframes spin {
287
+ to { transform: rotate(360deg); }
288
+ }
289
+ ` })
290
+ ]
291
+ }
292
+ ), De = ({
293
+ children: t,
294
+ onReset: e,
295
+ showSplash: o = !0
296
+ }) => {
297
+ const [r, a] = _(), [s, n] = v(!0);
298
+ return A.useEffect(() => {
299
+ a(() => {
300
+ n(!1);
301
+ });
302
+ }, []), /* @__PURE__ */ y(U, { children: [
303
+ /* @__PURE__ */ c(G, { FallbackComponent: re, onReset: () => {
304
+ e ? e() : window.location.reload();
305
+ }, children: /* @__PURE__ */ c(J, { fallback: /* @__PURE__ */ c(ne, {}), children: t }) }),
306
+ o && /* @__PURE__ */ c("div", { className: !r && !s ? "dash-splash fade-out" : "dash-splash" })
307
+ ] });
308
+ }, ae = {
309
+ display: "flex",
310
+ flexDirection: "column",
311
+ justifyContent: "center",
312
+ alignItems: "center",
313
+ minHeight: "100vh",
314
+ gap: "16px",
315
+ color: "var(--text-color, #333)",
316
+ backgroundColor: "var(--background-color, #fff)"
317
+ }, ie = {
318
+ margin: 0,
319
+ fontSize: "1.25rem",
320
+ fontWeight: 500,
321
+ color: "#f44336"
322
+ }, se = {
323
+ marginTop: "16px",
324
+ padding: "8px 16px",
325
+ backgroundColor: "#1976d2",
326
+ color: "white",
327
+ border: "none",
328
+ borderRadius: "4px",
329
+ cursor: "pointer",
330
+ fontSize: "14px",
331
+ fontWeight: 500
332
+ }, Me = ({
333
+ error: t,
334
+ message: e = "Failed to initialize application",
335
+ onRetry: o = () => window.location.reload(),
336
+ retryLabel: r = "Retry",
337
+ containerStyle: a,
338
+ messageStyle: s,
339
+ buttonStyle: n
340
+ }) => {
341
+ const d = t instanceof Error ? t.message : t || e;
342
+ return /* @__PURE__ */ y("div", { style: { ...ae, ...a }, children: [
343
+ /* @__PURE__ */ c("h6", { style: { ...ie, ...s }, children: d }),
344
+ /* @__PURE__ */ c(
345
+ "button",
346
+ {
347
+ onClick: o,
348
+ style: { ...se, ...n },
349
+ children: r
350
+ }
351
+ )
352
+ ] });
353
+ }, le = ({
354
+ message: t = "Failed to load application",
355
+ onRetry: e = () => window.location.reload(),
356
+ retryLabel: o = "Retry",
357
+ containerStyle: r,
358
+ messageStyle: a,
359
+ buttonStyle: s
360
+ }) => {
361
+ const n = {
362
+ display: "flex",
363
+ flexDirection: "column",
364
+ justifyContent: "center",
365
+ alignItems: "center",
366
+ height: "100vh",
367
+ color: "#000000",
368
+ gap: "12px"
369
+ }, d = {
370
+ padding: "8px 24px",
371
+ backgroundColor: "#57005aff",
372
+ color: "#fff",
373
+ border: "none",
374
+ borderRadius: "4px",
375
+ cursor: "pointer"
376
+ };
377
+ return /* @__PURE__ */ y("div", { style: { ...n, ...r }, children: [
378
+ /* @__PURE__ */ c("h1", { style: a, children: t }),
379
+ /* @__PURE__ */ c(
380
+ "button",
381
+ {
382
+ onClick: e,
383
+ style: { ...d, ...s },
384
+ children: o
385
+ }
386
+ )
387
+ ] });
388
+ }, Ne = ({
389
+ importFn: t,
390
+ delay: e = 100,
391
+ ErrorFallback: o = le,
392
+ errorMessage: r = "Failed to load application"
393
+ }) => A.lazy(() => new Promise((a) => {
394
+ setTimeout(() => {
395
+ t().then((s) => {
396
+ a({ default: s.default });
397
+ }).catch((s) => {
398
+ console.error("Failed to load application:", s), a({
399
+ default: () => /* @__PURE__ */ c(
400
+ o,
401
+ {
402
+ error: s,
403
+ message: r
404
+ }
405
+ )
406
+ });
407
+ });
408
+ }, e);
409
+ })), F = (t, e) => {
410
+ if (typeof document > "u") return e;
411
+ const o = getComputedStyle(document.documentElement).getPropertyValue(t).trim(), r = parseInt(o, 10);
412
+ return isNaN(r) ? e : r;
413
+ }, h = (t) => typeof document > "u" ? null : getComputedStyle(document.documentElement).getPropertyValue(t).trim() || null, ce = (t) => {
414
+ const e = {}, o = `--${t}`, r = h(`--primary-color${o}`);
415
+ r && (e.primaryColor = r);
416
+ const a = h(`--primary-contrast${o}`);
417
+ a && (e.primaryContrast = a);
418
+ const s = h(`--secondary-color${o}`);
419
+ s && (e.secondaryColor = s);
420
+ const n = h(`--bodybg-primary${o}`);
421
+ n && (e.bodyBgPrimary = n);
422
+ const d = h(`--bodybg-secondary${o}`);
423
+ d && (e.bodyBgSecondary = d);
424
+ const l = h(`--component-bg${o}`);
425
+ l && (e.componentBg = l);
426
+ const u = h(`--text-color${o}`);
427
+ u && (e.textColor = u);
428
+ const m = h(`--text-contrast${o}`);
429
+ m && (e.textContrast = m);
430
+ const g = h(`--heading-color${o}`);
431
+ g && (e.headingColor = g);
432
+ const i = h(`--link-color${o}`);
433
+ i && (e.linkColor = i);
434
+ const b = h(`--border-color${o}`);
435
+ return b && (e.borderColor = b), e;
436
+ }, de = (t, e) => {
437
+ const o = ce(t), r = F("--font-size-base", 14), a = F("--border-radius-base", 6), { palette: s, colorSchemes: n, defaultColorScheme: d, ...l } = e || {};
438
+ return X({
439
+ breakpoints: {
440
+ keys: ["xs", "sm", "md", "lg", "xl"],
441
+ values: { xs: 0, sm: 600, md: 900, lg: 1200, xl: 1536 }
442
+ },
443
+ palette: {
444
+ mode: t,
445
+ primary: {
446
+ main: o.primaryColor,
447
+ contrastText: o.primaryContrast
448
+ },
449
+ secondary: {
450
+ main: o.secondaryColor
451
+ },
452
+ background: {
453
+ default: o.bodyBgPrimary,
454
+ paper: o.componentBg
455
+ },
456
+ text: {
457
+ primary: o.textColor,
458
+ secondary: o.textContrast
459
+ },
460
+ divider: o.borderColor
461
+ },
462
+ typography: {
463
+ fontFamily: '"Montserrat", "Roboto", "Helvetica", "Arial", sans-serif',
464
+ fontSize: r
465
+ },
466
+ shape: {
467
+ borderRadius: a
468
+ },
469
+ components: {
470
+ MuiButton: {
471
+ styleOverrides: {
472
+ root: {
473
+ transition: "all 0.2s ease-in-out",
474
+ textTransform: "none"
475
+ }
476
+ }
477
+ },
478
+ MuiCssBaseline: {
479
+ styleOverrides: {
480
+ body: {
481
+ backgroundColor: o.bodyBgPrimary,
482
+ color: o.textColor
483
+ }
484
+ }
485
+ },
486
+ MuiPaper: {
487
+ styleOverrides: {
488
+ root: {
489
+ backgroundImage: "none"
490
+ }
491
+ }
492
+ }
493
+ },
494
+ ...l
495
+ });
496
+ }, W = $(null), He = () => {
497
+ const t = V(W);
498
+ if (!t)
499
+ throw new Error("useDashThemeContextLight must be used within a DashThemeProviderLight");
500
+ return t;
501
+ }, Fe = ({
502
+ children: t,
503
+ extendedOptions: e,
504
+ defaultMode: o
505
+ }) => {
506
+ const [r, a] = v(() => {
507
+ if (typeof document > "u") return o || "dark";
508
+ const i = document.documentElement.getAttribute("data-theme");
509
+ return i === "light" || i === "dark" ? i : o || "dark";
510
+ }), [s, n] = v(0), d = E(() => de(r, e), [r, e, s]), l = (i) => {
511
+ a(i), typeof document < "u" && (document.documentElement.setAttribute("data-theme", i), localStorage.setItem("theme", i), I(i));
512
+ }, u = () => {
513
+ l(r === "dark" ? "light" : "dark");
514
+ }, m = () => {
515
+ n((i) => i + 1);
516
+ };
517
+ p(() => {
518
+ if (typeof document > "u") return;
519
+ const i = new MutationObserver((b) => {
520
+ b.forEach((C) => {
521
+ if (C.type === "attributes" && C.attributeName === "data-theme") {
522
+ const x = document.documentElement.getAttribute("data-theme");
523
+ (x === "light" || x === "dark") && x !== r && a(x);
524
+ }
525
+ });
526
+ });
527
+ return i.observe(document.documentElement, {
528
+ attributes: !0,
529
+ attributeFilter: ["data-theme"]
530
+ }), () => i.disconnect();
531
+ }, [r]), p(() => {
532
+ typeof document > "u" || I(r);
533
+ }, [r]), p(() => {
534
+ if (typeof window > "u") return;
535
+ const i = () => {
536
+ console.log("DashThemeProviderLight: Refreshing theme from CSS variables"), m();
537
+ };
538
+ return window.addEventListener("DASHTRefreshTheme", i), () => window.removeEventListener("DASHTRefreshTheme", i);
539
+ }, []);
540
+ const g = E(
541
+ () => ({
542
+ theme: d,
543
+ currentMode: r,
544
+ setMode: l,
545
+ toggleMode: u,
546
+ refreshTheme: m
547
+ }),
548
+ [d, r]
549
+ );
550
+ return /* @__PURE__ */ y(Q, { theme: d, children: [
551
+ /* @__PURE__ */ c(K, {}),
552
+ /* @__PURE__ */ c(W.Provider, { value: g, children: t })
553
+ ] });
554
+ }, $e = (t) => {
555
+ const e = B();
556
+ p(() => {
557
+ (() => {
558
+ console.log("πŸ” Bootstrap: Checking for persisted auth data...");
559
+ const r = f.getUser(), a = f.getToken(), s = JSON.parse(Y.getItem("authenticated") || "false"), n = f.getAuth();
560
+ if (console.log("πŸ” Bootstrap: Persisted data check:", {
561
+ hasStoredUser: !!r,
562
+ hasStoredToken: !!a,
563
+ isAuthenticated: s,
564
+ hasPersistedAuth: !!n,
565
+ currentReduxAuth: t
566
+ }), s && r && a && !t) {
567
+ console.log("πŸ”„ Bootstrap: Restoring auth session to Redux from localStorage");
568
+ let d = r;
569
+ if (typeof r == "string") {
570
+ console.error("❌ Bootstrap: Stored user is string, this should not happen");
571
+ try {
572
+ d = JSON.parse(r);
573
+ } catch {
574
+ console.error("❌ Bootstrap: Cannot parse user string, clearing auth data"), f.clearAuth();
575
+ return;
576
+ }
577
+ }
578
+ e(
579
+ S.updateAuth(P, {
580
+ user: d,
581
+ authenticated: !0,
582
+ auth: n?.auth || null
583
+ })
584
+ ), console.log("βœ… Bootstrap: Redux state restored from persisted data");
585
+ }
586
+ })();
587
+ }, [e, t]);
588
+ }, Ve = () => {
589
+ const t = B();
590
+ p(() => {
591
+ const e = (o) => {
592
+ console.log("πŸ” Bootstrap: Received logout event", o.detail), t(
593
+ S.updateAuth(P, {
594
+ user: null,
595
+ authenticated: !1,
596
+ auth: null
597
+ })
598
+ ), f.clearAuth(), localStorage.clear();
599
+ };
600
+ return window.addEventListener("auth:logout", e), () => {
601
+ window.removeEventListener("auth:logout", e);
602
+ };
603
+ }, [t]);
604
+ }, qe = () => {
605
+ const [t, e] = v(!0), [o, r] = v(null), a = B();
606
+ return p(() => {
607
+ t && (async () => {
608
+ try {
609
+ console.log("πŸš€ Bootstrap: Starting app initialization..."), await Z();
610
+ const n = await z.initializeApp(!0);
611
+ if (console.log("πŸ” Bootstrap: Initialization result:", n), n.success) {
612
+ if (console.log("βœ… Bootstrap: Auto-login successful"), a(
613
+ S.updateAuth(P, {
614
+ user: n.user,
615
+ authenticated: !0,
616
+ auth: n.auth || null
617
+ })
618
+ ), window.DashIPCService?.speak(`${n.user?.name}, Bienvenido!`), await D(), r(null), n.redirectAfterLogin) {
619
+ console.log("πŸ”„ Bootstrap: Emitting auth:redirect event", n.redirectAfterLogin);
620
+ const d = new CustomEvent("auth:redirect", {
621
+ detail: { to: n.redirectAfterLogin }
622
+ });
623
+ window.dispatchEvent(d);
624
+ }
625
+ } else {
626
+ console.log("ℹ️ Bootstrap: No valid authentication found");
627
+ const d = f.getAuth();
628
+ if (d && d.auth) {
629
+ console.log("πŸ”„ Bootstrap: Found persisted auth data, attempting token initialization...");
630
+ try {
631
+ const l = await z.initializeFromToken();
632
+ if (l.success) {
633
+ if (console.log("βœ… Bootstrap: Token initialization successful"), a(
634
+ S.updateAuth(P, {
635
+ user: l.user,
636
+ authenticated: !0,
637
+ auth: l.auth || null
638
+ })
639
+ ), await D(), r(null), l.redirectAfterLogin) {
640
+ console.log(
641
+ "πŸ”„ Bootstrap: Emitting auth:redirect event",
642
+ l.redirectAfterLogin
643
+ );
644
+ const u = new CustomEvent("auth:redirect", {
645
+ detail: { to: l.redirectAfterLogin }
646
+ });
647
+ window.dispatchEvent(u);
648
+ }
649
+ } else
650
+ console.log("❌ Bootstrap: Token initialization failed:", l.error), r(null), f.clearAuth();
651
+ } catch (l) {
652
+ console.error("❌ Bootstrap: Token initialization error:", l), r(null), f.clearAuth();
653
+ }
654
+ } else
655
+ console.log("ℹ️ Bootstrap: No persisted auth data found"), f.clearAuth();
656
+ }
657
+ } catch (n) {
658
+ console.error("❌ Bootstrap: App initialization failed:", n), r("Failed to initialize application");
659
+ } finally {
660
+ e(!1);
661
+ }
662
+ })();
663
+ }, [a, t]), { isLoading: t, initializationError: o };
664
+ }, Oe = () => {
665
+ p(() => {
666
+ const e = new URLSearchParams(window.location.search).get("redirect");
667
+ e && e !== "/login" && (console.log("ℹ️ RedirectTO: Setting redirect to by searchParams to:", e), z.setPendingRedirect(e));
668
+ }, []);
669
+ }, ue = "dash:locale-change", We = (t = ["es", "en"], e = "es") => {
670
+ const o = B();
671
+ p(() => {
672
+ if (typeof window > "u") return;
673
+ const a = new URLSearchParams(window.location.search).get("lang"), s = localStorage.getItem("dash-user-locale");
674
+ let n = e;
675
+ a && t.includes(a) ? n = a : s && t.includes(s) && (n = s), s !== n ? (console.log(`🌐 Bootstrap: Locale change detected: ${s} -> ${n}`), localStorage.setItem("dash-user-locale", n)) : console.log(`🌐 Bootstrap: Initializing locale from storage: ${n}`), console.log(`🌐 Bootstrap: Dispatching locale to Redux: ${n}`), o(S.switchLanguage(n)), console.log(`🌐 Bootstrap: Emitting locale change event: ${n}`), window.dispatchEvent(new CustomEvent(ue, {
676
+ detail: { locale: n }
677
+ }));
678
+ }, [o, t, e]);
679
+ }, je = () => {
680
+ const [t, e] = v(
681
+ typeof window < "u" ? window.location.pathname : "/"
682
+ );
683
+ return p(() => {
684
+ if (typeof window > "u") return;
685
+ const o = () => {
686
+ const r = window.location.pathname;
687
+ r !== t && (console.log("πŸ” Bootstrap: URL changed from", t, "to", r), e(r));
688
+ };
689
+ return window.addEventListener("popstate", o), () => window.removeEventListener("popstate", o);
690
+ }, [t]), t;
691
+ }, Ue = (t = "dark") => {
692
+ p(() => {
693
+ if (typeof document > "u") return;
694
+ const e = localStorage.getItem("theme"), o = e === "light" || e === "dark" ? e : t;
695
+ document.documentElement.setAttribute("data-theme", o), e || localStorage.setItem("theme", o);
696
+ }, [t]);
697
+ }, _e = (t) => {
698
+ if (typeof document > "u" || typeof localStorage > "u") return;
699
+ const e = localStorage.getItem("theme"), o = e === "light" || e === "dark" ? e : t;
700
+ document.documentElement.setAttribute("data-theme", o), e || localStorage.setItem("theme", o);
701
+ try {
702
+ I(o), console.log("🎨 Bootstrap: Initialized theme variables for:", o);
703
+ } catch (r) {
704
+ console.warn("Failed to initialize theme variables:", r);
705
+ }
706
+ }, Je = async () => {
707
+ if (typeof window > "u") return;
708
+ const t = window.electronStore;
709
+ if (t) {
710
+ const e = await t.syncToLocalStorage();
711
+ Object.entries(e).forEach(([o, r]) => {
712
+ window.localStorage.setItem(o, JSON.stringify(r));
713
+ });
714
+ }
715
+ }, Ge = async () => {
716
+ if (!(typeof window > "u") && window.electronStore)
717
+ try {
718
+ const t = await window.electronStore.syncToLocalStorage();
719
+ Object.entries(t).forEach(([e, o]) => {
720
+ window.localStorage.setItem(e, JSON.stringify(o));
721
+ }), console.log("βœ… Electron store synced to localStorage");
722
+ } catch (t) {
723
+ console.error("❌ Failed to sync Electron store:", t);
724
+ }
725
+ }, Ke = () => typeof window < "u" && !!window.electronStore, Qe = async (t, e) => {
726
+ if (typeof window > "u") return e;
727
+ if (window.electronStore)
728
+ try {
729
+ return await window.electronStore.get(t);
730
+ } catch {
731
+ return e;
732
+ }
733
+ const o = localStorage.getItem(t);
734
+ if (o)
735
+ try {
736
+ return JSON.parse(o);
737
+ } catch {
738
+ return o;
739
+ }
740
+ return e;
741
+ }, Xe = async (t, e) => {
742
+ if (!(typeof window > "u")) {
743
+ if (window.electronStore)
744
+ try {
745
+ await window.electronStore.set(t, e);
746
+ } catch (o) {
747
+ console.error("Failed to set Electron store value:", o);
748
+ }
749
+ localStorage.setItem(t, JSON.stringify(e));
750
+ }
751
+ }, L = (t, e) => {
752
+ if (typeof document > "u") return e;
753
+ const o = getComputedStyle(document.documentElement).getPropertyValue(t).trim(), r = parseInt(o, 10);
754
+ return isNaN(r) ? e : r;
755
+ }, Ye = (t, e = "") => typeof document > "u" ? e : getComputedStyle(document.documentElement).getPropertyValue(t).trim() || e, w = {
756
+ sidebarLargeWidth: 255,
757
+ sidebarSmallWidth: 64,
758
+ sidebarHorizontalHeight: 120,
759
+ logoVerticalMaxWidth: 130,
760
+ logoVerticalMaxHeight: 130,
761
+ logoHorizontalMaxWidth: 200,
762
+ logoHorizontalMaxHeight: 60
763
+ }, ge = () => ({
764
+ sidebarLargeWidth: L("--sidebar-large-width", w.sidebarLargeWidth),
765
+ sidebarSmallWidth: L("--sidebar-small-width", w.sidebarSmallWidth),
766
+ sidebarHorizontalHeight: L("--sidebar-horizontal-height", w.sidebarHorizontalHeight),
767
+ logoVerticalMaxWidth: L("--logo-vertical-max-width", w.logoVerticalMaxWidth),
768
+ logoVerticalMaxHeight: L("--logo-vertical-max-height", w.logoVerticalMaxHeight),
769
+ logoHorizontalMaxWidth: L("--logo-horizontal-max-width", w.logoHorizontalMaxWidth),
770
+ logoHorizontalMaxHeight: L("--logo-horizontal-max-height", w.logoHorizontalMaxHeight)
771
+ }), Ze = (t = {}) => {
772
+ const e = {
773
+ ...w,
774
+ ...ge(),
775
+ ...t.layoutDimensions
776
+ };
777
+ return {
778
+ appName: t.appName || "Dash App",
779
+ horizontalLogo: t.horizontalLogo,
780
+ squaredLogo: t.squaredLogo,
781
+ loginBackground: t.loginBackground,
782
+ sidebarPosition: t.sidebarPosition || "left",
783
+ ...e,
784
+ // Padding configuration (derived from sidebar sizes)
785
+ paddingHorizontal: e.sidebarLargeWidth,
786
+ paddingVertical: e.sidebarHorizontalHeight
787
+ };
788
+ };
789
+ export {
790
+ De as AppWrapperLight,
791
+ Re as CustomErrorBoundary,
792
+ w as DEFAULT_LAYOUT_DIMENSIONS,
793
+ W as DashThemeContext,
794
+ Fe as DashThemeProviderLight,
795
+ le as DefaultAppLoadErrorFallback,
796
+ Me as DefaultInitializationErrorFallback,
797
+ Ae as GlobalLoaderHtmlMarkup,
798
+ ze as GlobalSmallLoader,
799
+ q as I18nBridgeContext,
800
+ Ee as I18nBridgeProviderLight,
801
+ Ze as createDefaultPanelSettings,
802
+ Ne as createLazyAppLoader,
803
+ Ce as createSimpleI18nProvider,
804
+ L as getCssVariableNumber,
805
+ Ye as getCssVariableString,
806
+ Qe as getElectronStoreValue,
807
+ ge as getLayoutDimensionsFromCss,
808
+ _e as initializeThemeEarly,
809
+ Te as injectCriticalStyles,
810
+ Ke as isElectron,
811
+ Xe as setElectronStoreValue,
812
+ Je as syncElectronStore,
813
+ Ge as syncElectronStoreToLocalStorage,
814
+ qe as useAppInitialization,
815
+ Be as useBridgedChangeLocaleLight,
816
+ ke as useBridgedLocaleLight,
817
+ Pe as useBridgedLocalesLight,
818
+ He as useDashThemeContextLight,
819
+ Ue as useEarlyThemeInit,
820
+ k as useI18nBridgeLight,
821
+ $e as useInitializeReduxFromPersisted,
822
+ Ve as useLogoutEventListener,
823
+ je as usePathnameTracker,
824
+ Oe as usePendingRedirect,
825
+ Ie as useTranslateLight,
826
+ We as useUrlLocaleDetection
827
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@dashadmin/dash-boilerplate",
3
+ "version": "1.3.16",
4
+ "private": false,
5
+ "main": "src/index.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "lint": "eslint --ext .ts,.tsx .",
9
+ "format": "pnpm prettier --write .",
10
+ "typecheck": "tsc --noEmit",
11
+ "build": "vite build"
12
+ },
13
+ "dependencies": {
14
+ "@emotion/react": "latest",
15
+ "@emotion/styled": "latest",
16
+ "@mui/material": "^7.3.10",
17
+ "@dashadmin/dash-admin-state": "workspace:*",
18
+ "@dashadmin/dash-auth": "workspace:*",
19
+ "@dashadmin/dash-auto-admin": "workspace:*",
20
+ "@dashadmin/dash-axios-hook": "workspace:*",
21
+ "@dashadmin/dash-constants": "workspace:*",
22
+ "@dashadmin/dash-utils": "workspace:*",
23
+ "numeral": "^2.0.6",
24
+ "react": "latest",
25
+ "react-admin": "5.14.7",
26
+ "react-dom": "latest",
27
+ "react-error-boundary": "^4.0.0",
28
+ "react-redux": "latest",
29
+ "@dashadmin/dash-admin": "workspace:*"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "latest",
33
+ "@types/numeral": "^2.0.5",
34
+ "@types/react": "latest",
35
+ "@types/react-dom": "latest",
36
+ "@dashadmin/dash-eslint": "workspace:*",
37
+ "@dashadmin/dash-prettier": "workspace:*",
38
+ "@dashadmin/dash-tsconfig": "workspace:*",
39
+ "typescript": "latest",
40
+ "vite": "^5.2.0",
41
+ "rollup": "^4.0.0"
42
+ },
43
+ "publishConfig": {
44
+ "name": "@dashadmin/dash-boilerplate",
45
+ "access": "public",
46
+ "main": "dist/index.js",
47
+ "exports": {
48
+ ".": {
49
+ "import": "./dist/index.js"
50
+ }
51
+ }
52
+ },
53
+ "files": [
54
+ "dist"
55
+ ]
56
+ }
package/src/index.ts ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * dash-boilerplate
3
+ *
4
+ * Shared boilerplate code for Dash lightweight applications.
5
+ * Provides i18n, theming, components, and utilities for both
6
+ * public and private app flows.
7
+ */
8
+
9
+ // i18n module
10
+ export {
11
+ createSimpleI18nProvider,
12
+ I18nBridgeProviderLight,
13
+ useI18nBridgeLight,
14
+ useBridgedLocalesLight,
15
+ useBridgedChangeLocaleLight,
16
+ useBridgedLocaleLight,
17
+ useTranslateLight,
18
+ I18nBridgeContext,
19
+ } from './i18n';
20
+ export type {
21
+ SimpleI18nProvider,
22
+ LocaleDefinition,
23
+ TranslationMessages,
24
+ TranslationsMap,
25
+ I18nBridgeProviderLightProps,
26
+ CreateSimpleI18nProviderOptions,
27
+ } from './i18n';
28
+
29
+ // Components module
30
+ export {
31
+ GlobalSmallLoader,
32
+ GlobalLoaderHtmlMarkup,
33
+ injectCriticalStyles,
34
+ CustomErrorBoundary,
35
+ AppWrapperLight,
36
+ // Default fallback components
37
+ DefaultInitializationErrorFallback,
38
+ DefaultAppLoadErrorFallback,
39
+ createLazyAppLoader,
40
+ } from './components';
41
+ export type {
42
+ GlobalSmallLoaderProps,
43
+ CustomErrorBoundaryProps,
44
+ AppWrapperLightProps,
45
+ DefaultErrorFallbackProps,
46
+ DefaultLoadingFallbackProps,
47
+ CreateLazyAppLoaderOptions,
48
+ } from './components';
49
+
50
+ // Theme module
51
+ export {
52
+ DashThemeProviderLight,
53
+ useDashThemeContextLight,
54
+ DashThemeContext,
55
+ } from './theme';
56
+ export type {
57
+ DashThemeContextType,
58
+ DashThemeProviderLightProps,
59
+ } from './theme';
60
+
61
+ // Utils module
62
+ export {
63
+ useInitializeReduxFromPersisted,
64
+ useLogoutEventListener,
65
+ useAppInitialization,
66
+ usePendingRedirect,
67
+ useUrlLocaleDetection,
68
+ usePathnameTracker,
69
+ useEarlyThemeInit,
70
+ initializeThemeEarly,
71
+ syncElectronStore,
72
+ // Electron store utilities
73
+ syncElectronStoreToLocalStorage,
74
+ isElectron,
75
+ getElectronStoreValue,
76
+ setElectronStoreValue,
77
+ // CSS Variable utilities
78
+ getCssVariableNumber,
79
+ getCssVariableString,
80
+ getLayoutDimensionsFromCss,
81
+ createDefaultPanelSettings,
82
+ DEFAULT_LAYOUT_DIMENSIONS,
83
+ } from './utils';
84
+ export type { AppInitializationResult, LayoutDimensions, PanelSettingsOptions } from './utils';