@dashadmin/dash-boilerplate 1.3.45 → 1.3.46

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.cjs +215 -161
  2. package/dist/index.js +203 -151
  3. package/package.json +2 -1
package/dist/index.cjs CHANGED
@@ -83,6 +83,7 @@ __export(index_exports, {
83
83
  AppWrapperLight: () => AppWrapperLight,
84
84
  CustomErrorBoundary: () => CustomErrorBoundary,
85
85
  DEFAULT_LAYOUT_DIMENSIONS: () => DEFAULT_LAYOUT_DIMENSIONS,
86
+ DarkToggleModeLight: () => DarkToggleModeLight,
86
87
  DashThemeContext: () => DashThemeContext,
87
88
  DashThemeProviderLight: () => DashThemeProviderLight,
88
89
  DefaultAppLoadErrorFallback: () => DefaultAppLoadErrorFallback,
@@ -102,6 +103,7 @@ __export(index_exports, {
102
103
  injectCriticalStyles: () => injectCriticalStyles,
103
104
  isElectron: () => isElectron,
104
105
  setElectronStoreValue: () => setElectronStoreValue,
106
+ setGlobalLoaderIcon: () => setGlobalLoaderIcon,
105
107
  syncElectronStore: () => syncElectronStore,
106
108
  syncElectronStoreToLocalStorage: () => syncElectronStoreToLocalStorage,
107
109
  useAppInitialization: () => useAppInitialization,
@@ -296,25 +298,27 @@ var useTranslateLight = () => {
296
298
 
297
299
  // src/components/GlobalSmallLoader.tsx
298
300
  var import_jsx_runtime2 = require("react/jsx-runtime");
299
- var loaderSvgMarkup = `<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>`;
300
- var KTIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { dangerouslySetInnerHTML: { __html: loaderSvgMarkup } });
301
+ var DEFAULT_LOADER_ICON_MARKUP = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><rect x="1" y="1" width="14" height="14" rx="2" fill="currentColor"/></svg>`;
302
+ var loaderIconMarkup = DEFAULT_LOADER_ICON_MARKUP;
303
+ var setGlobalLoaderIcon = (svgMarkup) => {
304
+ loaderIconMarkup = svgMarkup;
305
+ };
306
+ var LoaderIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { dangerouslySetInnerHTML: { __html: loaderIconMarkup } });
301
307
  var GlobalSmallLoader = ({
302
308
  message,
303
309
  showMessage = false
304
- }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
305
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "initial-loader", children: [
306
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "initial-loader-spinner" }),
307
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "initial-loader-icon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(KTIcon, {}) })
308
- ] }),
309
- showMessage && message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "initial-loader-text", children: message })
310
- ] });
311
- var GlobalLoaderHtmlMarkup = `<div class="initial-loader">
310
+ }) => {
311
+ injectCriticalStyles();
312
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "initial-loader", children: [
313
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "initial-loader-spinner", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "initial-loader-icon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoaderIcon, {}) }) }),
314
+ showMessage && message && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "initial-loader-text", children: message })
315
+ ] });
316
+ };
317
+ var GlobalLoaderHtmlMarkup = (message = "") => `<div class="initial-loader">
312
318
  <div class="initial-loader-spinner">
313
- <span class="initial-loader-icon">
314
- ${loaderSvgMarkup}
315
- </span>
319
+ <span class="initial-loader-icon">${loaderIconMarkup}</span>
316
320
  </div>
317
- <div class="initial-loader-text"></div>
321
+ ${message ? `<div class="initial-loader-text">${message}</div>` : ""}
318
322
  </div>`;
319
323
  var injectCriticalStyles = () => {
320
324
  if (typeof document === "undefined") return;
@@ -339,15 +343,23 @@ var injectCriticalStyles = () => {
339
343
  .initial-loader-spinner {
340
344
  width: 40px;
341
345
  height: 40px;
342
- border: 3px solid rgba(255,255,255,0.1);
343
- border-top-color: var(--primary-color, #3f51b5);
344
- border-radius: 50%;
345
- animation: spin 1s linear infinite;
346
346
  position: relative;
347
347
  display: flex;
348
348
  justify-content: center;
349
349
  align-items: center;
350
350
  }
351
+ /* The ring lives on a pseudo-element (not the container itself) so its
352
+ rotation never touches .initial-loader-icon \u2014 a real DOM child would
353
+ inherit a parent's animated transform and spin along with the ring. */
354
+ .initial-loader-spinner::before {
355
+ content: '';
356
+ position: absolute;
357
+ inset: 0;
358
+ border: 3px solid var(--border-color, rgba(128,128,128,0.25));
359
+ border-top-color: var(--highlight-color, #49a000);
360
+ border-radius: 50%;
361
+ animation: spin 1s linear infinite;
362
+ }
351
363
  .initial-loader-icon {
352
364
  position: absolute;
353
365
  top: 50%;
@@ -536,129 +548,18 @@ var AppWrapperLight = ({
536
548
  ] });
537
549
  };
538
550
 
539
- // src/components/DefaultFallbacks.tsx
540
- var import_react4 = __toESM(require("react"), 1);
541
- var import_jsx_runtime5 = require("react/jsx-runtime");
542
- var defaultContainerStyle = {
543
- display: "flex",
544
- flexDirection: "column",
545
- justifyContent: "center",
546
- alignItems: "center",
547
- minHeight: "100vh",
548
- gap: "16px",
549
- color: "var(--text-color, #333)",
550
- backgroundColor: "var(--background-color, #fff)"
551
- };
552
- var defaultErrorMessageStyle = {
553
- margin: 0,
554
- fontSize: "1.25rem",
555
- fontWeight: 500,
556
- color: "#f44336"
557
- };
558
- var defaultButtonStyle = {
559
- marginTop: "16px",
560
- padding: "8px 16px",
561
- backgroundColor: "#1976d2",
562
- color: "white",
563
- border: "none",
564
- borderRadius: "4px",
565
- cursor: "pointer",
566
- fontSize: "14px",
567
- fontWeight: 500
568
- };
569
- var DefaultInitializationErrorFallback = ({
570
- error,
571
- message = "Failed to initialize application",
572
- onRetry = () => window.location.reload(),
573
- retryLabel = "Retry",
574
- containerStyle,
575
- messageStyle,
576
- buttonStyle
577
- }) => {
578
- const errorMessage = error instanceof Error ? error.message : error || message;
579
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: __spreadValues(__spreadValues({}, defaultContainerStyle), containerStyle), children: [
580
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h6", { style: __spreadValues(__spreadValues({}, defaultErrorMessageStyle), messageStyle), children: errorMessage }),
581
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
582
- "button",
583
- {
584
- onClick: onRetry,
585
- style: __spreadValues(__spreadValues({}, defaultButtonStyle), buttonStyle),
586
- children: retryLabel
587
- }
588
- )
589
- ] });
590
- };
591
- var DefaultAppLoadErrorFallback = ({
592
- message = "Failed to load application",
593
- onRetry = () => window.location.reload(),
594
- retryLabel = "Retry",
595
- containerStyle,
596
- messageStyle,
597
- buttonStyle
598
- }) => {
599
- const appLoadContainerStyle = {
600
- display: "flex",
601
- flexDirection: "column",
602
- justifyContent: "center",
603
- alignItems: "center",
604
- height: "100vh",
605
- color: "#000000",
606
- gap: "12px"
607
- };
608
- const appLoadButtonStyle = {
609
- padding: "8px 24px",
610
- backgroundColor: "#57005aff",
611
- color: "#fff",
612
- border: "none",
613
- borderRadius: "4px",
614
- cursor: "pointer"
615
- };
616
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: __spreadValues(__spreadValues({}, appLoadContainerStyle), containerStyle), children: [
617
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { style: messageStyle, children: message }),
618
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
619
- "button",
620
- {
621
- onClick: onRetry,
622
- style: __spreadValues(__spreadValues({}, appLoadButtonStyle), buttonStyle),
623
- children: retryLabel
624
- }
625
- )
626
- ] });
627
- };
628
- var createLazyAppLoader = ({
629
- importFn,
630
- delay = 100,
631
- ErrorFallback: ErrorFallback2 = DefaultAppLoadErrorFallback,
632
- errorMessage = "Failed to load application"
633
- }) => {
634
- return import_react4.default.lazy(() => {
635
- return new Promise((resolve) => {
636
- setTimeout(() => {
637
- importFn().then((mod) => {
638
- resolve({ default: mod.default });
639
- }).catch((error) => {
640
- console.error("Failed to load application:", error);
641
- resolve({
642
- default: () => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
643
- ErrorFallback2,
644
- {
645
- error,
646
- message: errorMessage
647
- }
648
- )
649
- });
650
- });
651
- }, delay);
652
- });
653
- });
654
- };
551
+ // src/components/DarkToggleModeLight.tsx
552
+ var import_react_redux = require("react-redux");
553
+ var import_icons_material = require("@mui/icons-material");
554
+ var import_dash_admin_state = require("dash-admin-state");
555
+ var import_material2 = require("@mui/material");
655
556
 
656
557
  // src/theme/DashThemeProviderLight.tsx
657
- var import_react5 = require("react");
558
+ var import_react4 = require("react");
658
559
  var import_CssBaseline = __toESM(require("@mui/material/CssBaseline"), 1);
659
560
  var import_material = require("@mui/material");
660
561
  var import_dash_utils = require("dash-utils");
661
- var import_jsx_runtime6 = require("react/jsx-runtime");
562
+ var import_jsx_runtime5 = require("react/jsx-runtime");
662
563
  var getCssVariableNumber = (varName, defaultValue) => {
663
564
  if (typeof document === "undefined") return defaultValue;
664
565
  const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
@@ -710,8 +611,14 @@ var createMinimalTheme = (mode, extendedOptions) => {
710
611
  palette: {
711
612
  mode,
712
613
  primary: {
713
- main: colors.primaryColor,
714
- contrastText: colors.primaryContrast
614
+ main: colors.primaryColor
615
+ // No explicit contrastText: MUI's palette augmentation derives it via
616
+ // getContrastText(main) (picks black/white text by contrast ratio) when
617
+ // omitted. Trusting --primary-contrast here caused illegible button text
618
+ // whenever an app picked a --primary-contrast too close in tone to
619
+ // --primary-color (e.g. vanexa-system's near-identical blues, 2026-08-03) —
620
+ // --primary-contrast is also used standalone as a gradient stop elsewhere,
621
+ // so it was never guaranteed to double as a legible foreground color.
715
622
  },
716
623
  secondary: {
717
624
  main: colors.secondaryColor
@@ -760,9 +667,9 @@ var createMinimalTheme = (mode, extendedOptions) => {
760
667
  }
761
668
  }, safeExtendedOptions));
762
669
  };
763
- var DashThemeContext = (0, import_react5.createContext)(null);
670
+ var DashThemeContext = (0, import_react4.createContext)(null);
764
671
  var useDashThemeContextLight = () => {
765
- const context = (0, import_react5.useContext)(DashThemeContext);
672
+ const context = (0, import_react4.useContext)(DashThemeContext);
766
673
  if (!context) {
767
674
  throw new Error("useDashThemeContextLight must be used within a DashThemeProviderLight");
768
675
  }
@@ -773,13 +680,13 @@ var DashThemeProviderLight = ({
773
680
  extendedOptions,
774
681
  defaultMode
775
682
  }) => {
776
- const [currentMode, setCurrentMode] = (0, import_react5.useState)(() => {
683
+ const [currentMode, setCurrentMode] = (0, import_react4.useState)(() => {
777
684
  if (typeof document === "undefined") return defaultMode || "dark";
778
685
  const stored = document.documentElement.getAttribute("data-theme");
779
686
  return stored === "light" || stored === "dark" ? stored : defaultMode || "dark";
780
687
  });
781
- const [themeVersion, setThemeVersion] = (0, import_react5.useState)(0);
782
- const theme = (0, import_react5.useMemo)(() => {
688
+ const [themeVersion, setThemeVersion] = (0, import_react4.useState)(0);
689
+ const theme = (0, import_react4.useMemo)(() => {
783
690
  return createMinimalTheme(currentMode, extendedOptions);
784
691
  }, [currentMode, extendedOptions, themeVersion]);
785
692
  const setMode = (mode) => {
@@ -796,7 +703,7 @@ var DashThemeProviderLight = ({
796
703
  const refreshTheme = () => {
797
704
  setThemeVersion((v) => v + 1);
798
705
  };
799
- (0, import_react5.useEffect)(() => {
706
+ (0, import_react4.useEffect)(() => {
800
707
  if (typeof document === "undefined") return;
801
708
  const observer = new MutationObserver((mutations) => {
802
709
  mutations.forEach((mutation) => {
@@ -816,11 +723,11 @@ var DashThemeProviderLight = ({
816
723
  });
817
724
  return () => observer.disconnect();
818
725
  }, [currentMode]);
819
- (0, import_react5.useEffect)(() => {
726
+ (0, import_react4.useEffect)(() => {
820
727
  if (typeof document === "undefined") return;
821
728
  (0, import_dash_utils.updateDomCssVariables)(currentMode);
822
729
  }, [currentMode]);
823
- (0, import_react5.useEffect)(() => {
730
+ (0, import_react4.useEffect)(() => {
824
731
  if (typeof window === "undefined") return;
825
732
  const handler = () => {
826
733
  console.log("DashThemeProviderLight: Refreshing theme from CSS variables");
@@ -829,7 +736,7 @@ var DashThemeProviderLight = ({
829
736
  window.addEventListener("DASHTRefreshTheme", handler);
830
737
  return () => window.removeEventListener("DASHTRefreshTheme", handler);
831
738
  }, []);
832
- const contextValue = (0, import_react5.useMemo)(
739
+ const contextValue = (0, import_react4.useMemo)(
833
740
  () => ({
834
741
  theme,
835
742
  currentMode,
@@ -839,22 +746,167 @@ var DashThemeProviderLight = ({
839
746
  }),
840
747
  [theme, currentMode]
841
748
  );
842
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material.ThemeProvider, { theme, children: [
843
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_CssBaseline.default, {}),
844
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DashThemeContext.Provider, { value: contextValue, children })
749
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_material.ThemeProvider, { theme, children: [
750
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_CssBaseline.default, {}),
751
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DashThemeContext.Provider, { value: contextValue, children })
845
752
  ] });
846
753
  };
847
754
 
755
+ // src/components/DarkToggleModeLight.tsx
756
+ var import_jsx_runtime6 = require("react/jsx-runtime");
757
+ var DarkToggleModeLight = () => {
758
+ const { currentMode, setMode } = useDashThemeContextLight();
759
+ const dispatch = (0, import_react_redux.useDispatch)();
760
+ const darkMode = currentMode === "dark";
761
+ const onClick = () => {
762
+ const newMode = darkMode ? "light" : "dark";
763
+ setMode(newMode);
764
+ dispatch(import_dash_admin_state.DASH_REDUX_ACTIONS.toggleThemeType(newMode));
765
+ };
766
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { onClick, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
767
+ import_material2.Avatar,
768
+ {
769
+ sizes: "small",
770
+ sx: { fontSize: "1rem" },
771
+ style: {
772
+ width: "30px",
773
+ height: "30px",
774
+ minHeight: "30px",
775
+ cursor: "pointer"
776
+ },
777
+ className: "dash-icon-button-color dash-icon-button-bg",
778
+ children: darkMode ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons_material.LightMode, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons_material.DarkMode, {})
779
+ }
780
+ ) });
781
+ };
782
+
783
+ // src/components/DefaultFallbacks.tsx
784
+ var import_react5 = __toESM(require("react"), 1);
785
+ var import_jsx_runtime7 = require("react/jsx-runtime");
786
+ var defaultContainerStyle = {
787
+ display: "flex",
788
+ flexDirection: "column",
789
+ justifyContent: "center",
790
+ alignItems: "center",
791
+ minHeight: "100vh",
792
+ gap: "16px",
793
+ color: "var(--text-color, #333)",
794
+ backgroundColor: "var(--background-color, #fff)"
795
+ };
796
+ var defaultErrorMessageStyle = {
797
+ margin: 0,
798
+ fontSize: "1.25rem",
799
+ fontWeight: 500,
800
+ color: "#f44336"
801
+ };
802
+ var defaultButtonStyle = {
803
+ marginTop: "16px",
804
+ padding: "8px 16px",
805
+ backgroundColor: "#1976d2",
806
+ color: "white",
807
+ border: "none",
808
+ borderRadius: "4px",
809
+ cursor: "pointer",
810
+ fontSize: "14px",
811
+ fontWeight: 500
812
+ };
813
+ var DefaultInitializationErrorFallback = ({
814
+ error,
815
+ message = "Failed to initialize application",
816
+ onRetry = () => window.location.reload(),
817
+ retryLabel = "Retry",
818
+ containerStyle,
819
+ messageStyle,
820
+ buttonStyle
821
+ }) => {
822
+ const errorMessage = error instanceof Error ? error.message : error || message;
823
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: __spreadValues(__spreadValues({}, defaultContainerStyle), containerStyle), children: [
824
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h6", { style: __spreadValues(__spreadValues({}, defaultErrorMessageStyle), messageStyle), children: errorMessage }),
825
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
826
+ "button",
827
+ {
828
+ onClick: onRetry,
829
+ style: __spreadValues(__spreadValues({}, defaultButtonStyle), buttonStyle),
830
+ children: retryLabel
831
+ }
832
+ )
833
+ ] });
834
+ };
835
+ var DefaultAppLoadErrorFallback = ({
836
+ message = "Failed to load application",
837
+ onRetry = () => window.location.reload(),
838
+ retryLabel = "Retry",
839
+ containerStyle,
840
+ messageStyle,
841
+ buttonStyle
842
+ }) => {
843
+ const appLoadContainerStyle = {
844
+ display: "flex",
845
+ flexDirection: "column",
846
+ justifyContent: "center",
847
+ alignItems: "center",
848
+ height: "100vh",
849
+ color: "#000000",
850
+ gap: "12px"
851
+ };
852
+ const appLoadButtonStyle = {
853
+ padding: "8px 24px",
854
+ backgroundColor: "#57005aff",
855
+ color: "#fff",
856
+ border: "none",
857
+ borderRadius: "4px",
858
+ cursor: "pointer"
859
+ };
860
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: __spreadValues(__spreadValues({}, appLoadContainerStyle), containerStyle), children: [
861
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: messageStyle, children: message }),
862
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
863
+ "button",
864
+ {
865
+ onClick: onRetry,
866
+ style: __spreadValues(__spreadValues({}, appLoadButtonStyle), buttonStyle),
867
+ children: retryLabel
868
+ }
869
+ )
870
+ ] });
871
+ };
872
+ var createLazyAppLoader = ({
873
+ importFn,
874
+ delay = 100,
875
+ ErrorFallback: ErrorFallback2 = DefaultAppLoadErrorFallback,
876
+ errorMessage = "Failed to load application"
877
+ }) => {
878
+ return import_react5.default.lazy(() => {
879
+ return new Promise((resolve) => {
880
+ setTimeout(() => {
881
+ importFn().then((mod) => {
882
+ resolve({ default: mod.default });
883
+ }).catch((error) => {
884
+ console.error("Failed to load application:", error);
885
+ resolve({
886
+ default: () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
887
+ ErrorFallback2,
888
+ {
889
+ error,
890
+ message: errorMessage
891
+ }
892
+ )
893
+ });
894
+ });
895
+ }, delay);
896
+ });
897
+ });
898
+ };
899
+
848
900
  // src/utils/DashBootstrapUtils.ts
849
901
  var import_react6 = require("react");
850
- var import_react_redux = require("react-redux");
902
+ var import_react_redux2 = require("react-redux");
851
903
  var import_dash_auth = require("dash-auth");
852
- var import_dash_admin_state = require("dash-admin-state");
904
+ var import_dash_admin_state2 = require("dash-admin-state");
853
905
  var import_Auth = require("dash-admin-state/src/redux/reducers/Auth");
854
906
  var import_DASHAuthenticationService = __toESM(require("dash-admin/src/contexts/auth/DASHAuthenticationService"), 1);
855
907
  var import_dash_utils2 = require("dash-utils");
856
908
  var useInitializeReduxFromPersisted = (currentAuthState) => {
857
- const dispatch = (0, import_react_redux.useDispatch)();
909
+ const dispatch = (0, import_react_redux2.useDispatch)();
858
910
  (0, import_react6.useEffect)(() => {
859
911
  const initializeReduxFromPersisted = () => {
860
912
  console.log("\u{1F50D} Bootstrap: Checking for persisted auth data...");
@@ -883,7 +935,7 @@ var useInitializeReduxFromPersisted = (currentAuthState) => {
883
935
  }
884
936
  }
885
937
  dispatch(
886
- import_dash_admin_state.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
938
+ import_dash_admin_state2.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
887
939
  user: userObject,
888
940
  authenticated: true,
889
941
  auth: (persistedAuth == null ? void 0 : persistedAuth.auth) || null
@@ -896,12 +948,12 @@ var useInitializeReduxFromPersisted = (currentAuthState) => {
896
948
  }, [dispatch, currentAuthState]);
897
949
  };
898
950
  var useLogoutEventListener = () => {
899
- const dispatch = (0, import_react_redux.useDispatch)();
951
+ const dispatch = (0, import_react_redux2.useDispatch)();
900
952
  (0, import_react6.useEffect)(() => {
901
953
  const handleLogoutEvent = (event) => {
902
954
  console.log("\u{1F510} Bootstrap: Received logout event", event.detail);
903
955
  dispatch(
904
- import_dash_admin_state.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
956
+ import_dash_admin_state2.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
905
957
  user: null,
906
958
  authenticated: false,
907
959
  auth: null
@@ -919,7 +971,7 @@ var useLogoutEventListener = () => {
919
971
  var useAppInitialization = () => {
920
972
  const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
921
973
  const [initializationError, setInitializationError] = (0, import_react6.useState)(null);
922
- const dispatch = (0, import_react_redux.useDispatch)();
974
+ const dispatch = (0, import_react_redux2.useDispatch)();
923
975
  (0, import_react6.useEffect)(() => {
924
976
  const initializeApp = () => __async(null, null, function* () {
925
977
  var _a, _b;
@@ -931,7 +983,7 @@ var useAppInitialization = () => {
931
983
  if (initResult.success) {
932
984
  console.log("\u2705 Bootstrap: Auto-login successful");
933
985
  dispatch(
934
- import_dash_admin_state.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
986
+ import_dash_admin_state2.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
935
987
  user: initResult.user,
936
988
  authenticated: true,
937
989
  auth: initResult.auth || null
@@ -957,7 +1009,7 @@ var useAppInitialization = () => {
957
1009
  if (tokenInitResult.success) {
958
1010
  console.log("\u2705 Bootstrap: Token initialization successful");
959
1011
  dispatch(
960
- import_dash_admin_state.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
1012
+ import_dash_admin_state2.DASH_REDUX_ACTIONS.updateAuth(import_Auth.ACTION_UPDATE_AUTH, {
961
1013
  user: tokenInitResult.user,
962
1014
  authenticated: true,
963
1015
  auth: tokenInitResult.auth || null
@@ -1015,7 +1067,7 @@ var usePendingRedirect = () => {
1015
1067
  };
1016
1068
  var LOCALE_CHANGE_EVENT2 = "dash:locale-change";
1017
1069
  var useUrlLocaleDetection = (availableLocales = ["es", "en"], defaultLocale = "es") => {
1018
- const dispatch = (0, import_react_redux.useDispatch)();
1070
+ const dispatch = (0, import_react_redux2.useDispatch)();
1019
1071
  (0, import_react6.useEffect)(() => {
1020
1072
  if (typeof window === "undefined") return;
1021
1073
  const searchParams = new URLSearchParams(window.location.search);
@@ -1035,7 +1087,7 @@ var useUrlLocaleDetection = (availableLocales = ["es", "en"], defaultLocale = "e
1035
1087
  console.log(`\u{1F310} Bootstrap: Initializing locale from storage: ${targetLocale}`);
1036
1088
  }
1037
1089
  console.log(`\u{1F310} Bootstrap: Dispatching locale to Redux: ${targetLocale}`);
1038
- dispatch(import_dash_admin_state.DASH_REDUX_ACTIONS.switchLanguage(targetLocale));
1090
+ dispatch(import_dash_admin_state2.DASH_REDUX_ACTIONS.switchLanguage(targetLocale));
1039
1091
  console.log(`\u{1F310} Bootstrap: Emitting locale change event: ${targetLocale}`);
1040
1092
  window.dispatchEvent(new CustomEvent(LOCALE_CHANGE_EVENT2, {
1041
1093
  detail: { locale: targetLocale }
@@ -1197,6 +1249,7 @@ var createDefaultPanelSettings = (options = {}) => {
1197
1249
  AppWrapperLight,
1198
1250
  CustomErrorBoundary,
1199
1251
  DEFAULT_LAYOUT_DIMENSIONS,
1252
+ DarkToggleModeLight,
1200
1253
  DashThemeContext,
1201
1254
  DashThemeProviderLight,
1202
1255
  DefaultAppLoadErrorFallback,
@@ -1216,6 +1269,7 @@ var createDefaultPanelSettings = (options = {}) => {
1216
1269
  injectCriticalStyles,
1217
1270
  isElectron,
1218
1271
  setElectronStoreValue,
1272
+ setGlobalLoaderIcon,
1219
1273
  syncElectronStore,
1220
1274
  syncElectronStoreToLocalStorage,
1221
1275
  useAppInitialization,
package/dist/index.js CHANGED
@@ -227,25 +227,27 @@ var useTranslateLight = () => {
227
227
 
228
228
  // src/components/GlobalSmallLoader.tsx
229
229
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
230
- var loaderSvgMarkup = `<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>`;
231
- var KTIcon = () => /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: loaderSvgMarkup } });
230
+ var DEFAULT_LOADER_ICON_MARKUP = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><rect x="1" y="1" width="14" height="14" rx="2" fill="currentColor"/></svg>`;
231
+ var loaderIconMarkup = DEFAULT_LOADER_ICON_MARKUP;
232
+ var setGlobalLoaderIcon = (svgMarkup) => {
233
+ loaderIconMarkup = svgMarkup;
234
+ };
235
+ var LoaderIcon = () => /* @__PURE__ */ jsx2("span", { dangerouslySetInnerHTML: { __html: loaderIconMarkup } });
232
236
  var GlobalSmallLoader = ({
233
237
  message,
234
238
  showMessage = false
235
- }) => /* @__PURE__ */ jsxs("div", { children: [
236
- /* @__PURE__ */ jsxs("div", { className: "initial-loader", children: [
237
- /* @__PURE__ */ jsx2("div", { className: "initial-loader-spinner" }),
238
- /* @__PURE__ */ jsx2("span", { className: "initial-loader-icon", children: /* @__PURE__ */ jsx2(KTIcon, {}) })
239
- ] }),
240
- showMessage && message && /* @__PURE__ */ jsx2("div", { className: "initial-loader-text", children: message })
241
- ] });
242
- var GlobalLoaderHtmlMarkup = `<div class="initial-loader">
239
+ }) => {
240
+ injectCriticalStyles();
241
+ return /* @__PURE__ */ jsxs("div", { className: "initial-loader", children: [
242
+ /* @__PURE__ */ jsx2("div", { className: "initial-loader-spinner", children: /* @__PURE__ */ jsx2("span", { className: "initial-loader-icon", children: /* @__PURE__ */ jsx2(LoaderIcon, {}) }) }),
243
+ showMessage && message && /* @__PURE__ */ jsx2("div", { className: "initial-loader-text", children: message })
244
+ ] });
245
+ };
246
+ var GlobalLoaderHtmlMarkup = (message = "") => `<div class="initial-loader">
243
247
  <div class="initial-loader-spinner">
244
- <span class="initial-loader-icon">
245
- ${loaderSvgMarkup}
246
- </span>
248
+ <span class="initial-loader-icon">${loaderIconMarkup}</span>
247
249
  </div>
248
- <div class="initial-loader-text"></div>
250
+ ${message ? `<div class="initial-loader-text">${message}</div>` : ""}
249
251
  </div>`;
250
252
  var injectCriticalStyles = () => {
251
253
  if (typeof document === "undefined") return;
@@ -270,15 +272,23 @@ var injectCriticalStyles = () => {
270
272
  .initial-loader-spinner {
271
273
  width: 40px;
272
274
  height: 40px;
273
- border: 3px solid rgba(255,255,255,0.1);
274
- border-top-color: var(--primary-color, #3f51b5);
275
- border-radius: 50%;
276
- animation: spin 1s linear infinite;
277
275
  position: relative;
278
276
  display: flex;
279
277
  justify-content: center;
280
278
  align-items: center;
281
279
  }
280
+ /* The ring lives on a pseudo-element (not the container itself) so its
281
+ rotation never touches .initial-loader-icon \u2014 a real DOM child would
282
+ inherit a parent's animated transform and spin along with the ring. */
283
+ .initial-loader-spinner::before {
284
+ content: '';
285
+ position: absolute;
286
+ inset: 0;
287
+ border: 3px solid var(--border-color, rgba(128,128,128,0.25));
288
+ border-top-color: var(--highlight-color, #49a000);
289
+ border-radius: 50%;
290
+ animation: spin 1s linear infinite;
291
+ }
282
292
  .initial-loader-icon {
283
293
  position: absolute;
284
294
  top: 50%;
@@ -467,129 +477,18 @@ var AppWrapperLight = ({
467
477
  ] });
468
478
  };
469
479
 
470
- // src/components/DefaultFallbacks.tsx
471
- import React4 from "react";
472
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
473
- var defaultContainerStyle = {
474
- display: "flex",
475
- flexDirection: "column",
476
- justifyContent: "center",
477
- alignItems: "center",
478
- minHeight: "100vh",
479
- gap: "16px",
480
- color: "var(--text-color, #333)",
481
- backgroundColor: "var(--background-color, #fff)"
482
- };
483
- var defaultErrorMessageStyle = {
484
- margin: 0,
485
- fontSize: "1.25rem",
486
- fontWeight: 500,
487
- color: "#f44336"
488
- };
489
- var defaultButtonStyle = {
490
- marginTop: "16px",
491
- padding: "8px 16px",
492
- backgroundColor: "#1976d2",
493
- color: "white",
494
- border: "none",
495
- borderRadius: "4px",
496
- cursor: "pointer",
497
- fontSize: "14px",
498
- fontWeight: 500
499
- };
500
- var DefaultInitializationErrorFallback = ({
501
- error,
502
- message = "Failed to initialize application",
503
- onRetry = () => window.location.reload(),
504
- retryLabel = "Retry",
505
- containerStyle,
506
- messageStyle,
507
- buttonStyle
508
- }) => {
509
- const errorMessage = error instanceof Error ? error.message : error || message;
510
- return /* @__PURE__ */ jsxs4("div", { style: __spreadValues(__spreadValues({}, defaultContainerStyle), containerStyle), children: [
511
- /* @__PURE__ */ jsx5("h6", { style: __spreadValues(__spreadValues({}, defaultErrorMessageStyle), messageStyle), children: errorMessage }),
512
- /* @__PURE__ */ jsx5(
513
- "button",
514
- {
515
- onClick: onRetry,
516
- style: __spreadValues(__spreadValues({}, defaultButtonStyle), buttonStyle),
517
- children: retryLabel
518
- }
519
- )
520
- ] });
521
- };
522
- var DefaultAppLoadErrorFallback = ({
523
- message = "Failed to load application",
524
- onRetry = () => window.location.reload(),
525
- retryLabel = "Retry",
526
- containerStyle,
527
- messageStyle,
528
- buttonStyle
529
- }) => {
530
- const appLoadContainerStyle = {
531
- display: "flex",
532
- flexDirection: "column",
533
- justifyContent: "center",
534
- alignItems: "center",
535
- height: "100vh",
536
- color: "#000000",
537
- gap: "12px"
538
- };
539
- const appLoadButtonStyle = {
540
- padding: "8px 24px",
541
- backgroundColor: "#57005aff",
542
- color: "#fff",
543
- border: "none",
544
- borderRadius: "4px",
545
- cursor: "pointer"
546
- };
547
- return /* @__PURE__ */ jsxs4("div", { style: __spreadValues(__spreadValues({}, appLoadContainerStyle), containerStyle), children: [
548
- /* @__PURE__ */ jsx5("h1", { style: messageStyle, children: message }),
549
- /* @__PURE__ */ jsx5(
550
- "button",
551
- {
552
- onClick: onRetry,
553
- style: __spreadValues(__spreadValues({}, appLoadButtonStyle), buttonStyle),
554
- children: retryLabel
555
- }
556
- )
557
- ] });
558
- };
559
- var createLazyAppLoader = ({
560
- importFn,
561
- delay = 100,
562
- ErrorFallback: ErrorFallback2 = DefaultAppLoadErrorFallback,
563
- errorMessage = "Failed to load application"
564
- }) => {
565
- return React4.lazy(() => {
566
- return new Promise((resolve) => {
567
- setTimeout(() => {
568
- importFn().then((mod) => {
569
- resolve({ default: mod.default });
570
- }).catch((error) => {
571
- console.error("Failed to load application:", error);
572
- resolve({
573
- default: () => /* @__PURE__ */ jsx5(
574
- ErrorFallback2,
575
- {
576
- error,
577
- message: errorMessage
578
- }
579
- )
580
- });
581
- });
582
- }, delay);
583
- });
584
- });
585
- };
480
+ // src/components/DarkToggleModeLight.tsx
481
+ import { useDispatch } from "react-redux";
482
+ import { LightMode, DarkMode } from "@mui/icons-material";
483
+ import { DASH_REDUX_ACTIONS } from "dash-admin-state";
484
+ import { Avatar } from "@mui/material";
586
485
 
587
486
  // src/theme/DashThemeProviderLight.tsx
588
487
  import { createContext as createContext2, useContext as useContext2, useState as useState3, useEffect as useEffect2, useMemo as useMemo2 } from "react";
589
488
  import CssBaseline from "@mui/material/CssBaseline";
590
489
  import { createTheme, ThemeProvider } from "@mui/material";
591
490
  import { updateDomCssVariables } from "dash-utils";
592
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
491
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
593
492
  var getCssVariableNumber = (varName, defaultValue) => {
594
493
  if (typeof document === "undefined") return defaultValue;
595
494
  const value = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
@@ -641,8 +540,14 @@ var createMinimalTheme = (mode, extendedOptions) => {
641
540
  palette: {
642
541
  mode,
643
542
  primary: {
644
- main: colors.primaryColor,
645
- contrastText: colors.primaryContrast
543
+ main: colors.primaryColor
544
+ // No explicit contrastText: MUI's palette augmentation derives it via
545
+ // getContrastText(main) (picks black/white text by contrast ratio) when
546
+ // omitted. Trusting --primary-contrast here caused illegible button text
547
+ // whenever an app picked a --primary-contrast too close in tone to
548
+ // --primary-color (e.g. vanexa-system's near-identical blues, 2026-08-03) —
549
+ // --primary-contrast is also used standalone as a gradient stop elsewhere,
550
+ // so it was never guaranteed to double as a legible foreground color.
646
551
  },
647
552
  secondary: {
648
553
  main: colors.secondaryColor
@@ -770,22 +675,167 @@ var DashThemeProviderLight = ({
770
675
  }),
771
676
  [theme, currentMode]
772
677
  );
773
- return /* @__PURE__ */ jsxs5(ThemeProvider, { theme, children: [
774
- /* @__PURE__ */ jsx6(CssBaseline, {}),
775
- /* @__PURE__ */ jsx6(DashThemeContext.Provider, { value: contextValue, children })
678
+ return /* @__PURE__ */ jsxs4(ThemeProvider, { theme, children: [
679
+ /* @__PURE__ */ jsx5(CssBaseline, {}),
680
+ /* @__PURE__ */ jsx5(DashThemeContext.Provider, { value: contextValue, children })
776
681
  ] });
777
682
  };
778
683
 
684
+ // src/components/DarkToggleModeLight.tsx
685
+ import { jsx as jsx6 } from "react/jsx-runtime";
686
+ var DarkToggleModeLight = () => {
687
+ const { currentMode, setMode } = useDashThemeContextLight();
688
+ const dispatch = useDispatch();
689
+ const darkMode = currentMode === "dark";
690
+ const onClick = () => {
691
+ const newMode = darkMode ? "light" : "dark";
692
+ setMode(newMode);
693
+ dispatch(DASH_REDUX_ACTIONS.toggleThemeType(newMode));
694
+ };
695
+ return /* @__PURE__ */ jsx6("div", { onClick, children: /* @__PURE__ */ jsx6(
696
+ Avatar,
697
+ {
698
+ sizes: "small",
699
+ sx: { fontSize: "1rem" },
700
+ style: {
701
+ width: "30px",
702
+ height: "30px",
703
+ minHeight: "30px",
704
+ cursor: "pointer"
705
+ },
706
+ className: "dash-icon-button-color dash-icon-button-bg",
707
+ children: darkMode ? /* @__PURE__ */ jsx6(LightMode, {}) : /* @__PURE__ */ jsx6(DarkMode, {})
708
+ }
709
+ ) });
710
+ };
711
+
712
+ // src/components/DefaultFallbacks.tsx
713
+ import React5 from "react";
714
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
715
+ var defaultContainerStyle = {
716
+ display: "flex",
717
+ flexDirection: "column",
718
+ justifyContent: "center",
719
+ alignItems: "center",
720
+ minHeight: "100vh",
721
+ gap: "16px",
722
+ color: "var(--text-color, #333)",
723
+ backgroundColor: "var(--background-color, #fff)"
724
+ };
725
+ var defaultErrorMessageStyle = {
726
+ margin: 0,
727
+ fontSize: "1.25rem",
728
+ fontWeight: 500,
729
+ color: "#f44336"
730
+ };
731
+ var defaultButtonStyle = {
732
+ marginTop: "16px",
733
+ padding: "8px 16px",
734
+ backgroundColor: "#1976d2",
735
+ color: "white",
736
+ border: "none",
737
+ borderRadius: "4px",
738
+ cursor: "pointer",
739
+ fontSize: "14px",
740
+ fontWeight: 500
741
+ };
742
+ var DefaultInitializationErrorFallback = ({
743
+ error,
744
+ message = "Failed to initialize application",
745
+ onRetry = () => window.location.reload(),
746
+ retryLabel = "Retry",
747
+ containerStyle,
748
+ messageStyle,
749
+ buttonStyle
750
+ }) => {
751
+ const errorMessage = error instanceof Error ? error.message : error || message;
752
+ return /* @__PURE__ */ jsxs5("div", { style: __spreadValues(__spreadValues({}, defaultContainerStyle), containerStyle), children: [
753
+ /* @__PURE__ */ jsx7("h6", { style: __spreadValues(__spreadValues({}, defaultErrorMessageStyle), messageStyle), children: errorMessage }),
754
+ /* @__PURE__ */ jsx7(
755
+ "button",
756
+ {
757
+ onClick: onRetry,
758
+ style: __spreadValues(__spreadValues({}, defaultButtonStyle), buttonStyle),
759
+ children: retryLabel
760
+ }
761
+ )
762
+ ] });
763
+ };
764
+ var DefaultAppLoadErrorFallback = ({
765
+ message = "Failed to load application",
766
+ onRetry = () => window.location.reload(),
767
+ retryLabel = "Retry",
768
+ containerStyle,
769
+ messageStyle,
770
+ buttonStyle
771
+ }) => {
772
+ const appLoadContainerStyle = {
773
+ display: "flex",
774
+ flexDirection: "column",
775
+ justifyContent: "center",
776
+ alignItems: "center",
777
+ height: "100vh",
778
+ color: "#000000",
779
+ gap: "12px"
780
+ };
781
+ const appLoadButtonStyle = {
782
+ padding: "8px 24px",
783
+ backgroundColor: "#57005aff",
784
+ color: "#fff",
785
+ border: "none",
786
+ borderRadius: "4px",
787
+ cursor: "pointer"
788
+ };
789
+ return /* @__PURE__ */ jsxs5("div", { style: __spreadValues(__spreadValues({}, appLoadContainerStyle), containerStyle), children: [
790
+ /* @__PURE__ */ jsx7("h1", { style: messageStyle, children: message }),
791
+ /* @__PURE__ */ jsx7(
792
+ "button",
793
+ {
794
+ onClick: onRetry,
795
+ style: __spreadValues(__spreadValues({}, appLoadButtonStyle), buttonStyle),
796
+ children: retryLabel
797
+ }
798
+ )
799
+ ] });
800
+ };
801
+ var createLazyAppLoader = ({
802
+ importFn,
803
+ delay = 100,
804
+ ErrorFallback: ErrorFallback2 = DefaultAppLoadErrorFallback,
805
+ errorMessage = "Failed to load application"
806
+ }) => {
807
+ return React5.lazy(() => {
808
+ return new Promise((resolve) => {
809
+ setTimeout(() => {
810
+ importFn().then((mod) => {
811
+ resolve({ default: mod.default });
812
+ }).catch((error) => {
813
+ console.error("Failed to load application:", error);
814
+ resolve({
815
+ default: () => /* @__PURE__ */ jsx7(
816
+ ErrorFallback2,
817
+ {
818
+ error,
819
+ message: errorMessage
820
+ }
821
+ )
822
+ });
823
+ });
824
+ }, delay);
825
+ });
826
+ });
827
+ };
828
+
779
829
  // src/utils/DashBootstrapUtils.ts
780
830
  import { useEffect as useEffect3, useState as useState4 } from "react";
781
- import { useDispatch } from "react-redux";
831
+ import { useDispatch as useDispatch2 } from "react-redux";
782
832
  import { AuthPersistenceService, syncDeviceStoreToLocalStorage, syncLocalStorageToDeviceStore } from "dash-auth";
783
- import { DASH_REDUX_ACTIONS } from "dash-admin-state";
833
+ import { DASH_REDUX_ACTIONS as DASH_REDUX_ACTIONS2 } from "dash-admin-state";
784
834
  import { ACTION_UPDATE_AUTH } from "dash-admin-state/src/redux/reducers/Auth";
785
835
  import DASHAuthenticationService from "dash-admin/src/contexts/auth/DASHAuthenticationService";
786
836
  import { dashStorage, updateDomCssVariables as updateDomCssVariables2 } from "dash-utils";
787
837
  var useInitializeReduxFromPersisted = (currentAuthState) => {
788
- const dispatch = useDispatch();
838
+ const dispatch = useDispatch2();
789
839
  useEffect3(() => {
790
840
  const initializeReduxFromPersisted = () => {
791
841
  console.log("\u{1F50D} Bootstrap: Checking for persisted auth data...");
@@ -814,7 +864,7 @@ var useInitializeReduxFromPersisted = (currentAuthState) => {
814
864
  }
815
865
  }
816
866
  dispatch(
817
- DASH_REDUX_ACTIONS.updateAuth(ACTION_UPDATE_AUTH, {
867
+ DASH_REDUX_ACTIONS2.updateAuth(ACTION_UPDATE_AUTH, {
818
868
  user: userObject,
819
869
  authenticated: true,
820
870
  auth: (persistedAuth == null ? void 0 : persistedAuth.auth) || null
@@ -827,12 +877,12 @@ var useInitializeReduxFromPersisted = (currentAuthState) => {
827
877
  }, [dispatch, currentAuthState]);
828
878
  };
829
879
  var useLogoutEventListener = () => {
830
- const dispatch = useDispatch();
880
+ const dispatch = useDispatch2();
831
881
  useEffect3(() => {
832
882
  const handleLogoutEvent = (event) => {
833
883
  console.log("\u{1F510} Bootstrap: Received logout event", event.detail);
834
884
  dispatch(
835
- DASH_REDUX_ACTIONS.updateAuth(ACTION_UPDATE_AUTH, {
885
+ DASH_REDUX_ACTIONS2.updateAuth(ACTION_UPDATE_AUTH, {
836
886
  user: null,
837
887
  authenticated: false,
838
888
  auth: null
@@ -850,7 +900,7 @@ var useLogoutEventListener = () => {
850
900
  var useAppInitialization = () => {
851
901
  const [isLoading, setIsLoading] = useState4(true);
852
902
  const [initializationError, setInitializationError] = useState4(null);
853
- const dispatch = useDispatch();
903
+ const dispatch = useDispatch2();
854
904
  useEffect3(() => {
855
905
  const initializeApp = () => __async(null, null, function* () {
856
906
  var _a, _b;
@@ -862,7 +912,7 @@ var useAppInitialization = () => {
862
912
  if (initResult.success) {
863
913
  console.log("\u2705 Bootstrap: Auto-login successful");
864
914
  dispatch(
865
- DASH_REDUX_ACTIONS.updateAuth(ACTION_UPDATE_AUTH, {
915
+ DASH_REDUX_ACTIONS2.updateAuth(ACTION_UPDATE_AUTH, {
866
916
  user: initResult.user,
867
917
  authenticated: true,
868
918
  auth: initResult.auth || null
@@ -888,7 +938,7 @@ var useAppInitialization = () => {
888
938
  if (tokenInitResult.success) {
889
939
  console.log("\u2705 Bootstrap: Token initialization successful");
890
940
  dispatch(
891
- DASH_REDUX_ACTIONS.updateAuth(ACTION_UPDATE_AUTH, {
941
+ DASH_REDUX_ACTIONS2.updateAuth(ACTION_UPDATE_AUTH, {
892
942
  user: tokenInitResult.user,
893
943
  authenticated: true,
894
944
  auth: tokenInitResult.auth || null
@@ -946,7 +996,7 @@ var usePendingRedirect = () => {
946
996
  };
947
997
  var LOCALE_CHANGE_EVENT2 = "dash:locale-change";
948
998
  var useUrlLocaleDetection = (availableLocales = ["es", "en"], defaultLocale = "es") => {
949
- const dispatch = useDispatch();
999
+ const dispatch = useDispatch2();
950
1000
  useEffect3(() => {
951
1001
  if (typeof window === "undefined") return;
952
1002
  const searchParams = new URLSearchParams(window.location.search);
@@ -966,7 +1016,7 @@ var useUrlLocaleDetection = (availableLocales = ["es", "en"], defaultLocale = "e
966
1016
  console.log(`\u{1F310} Bootstrap: Initializing locale from storage: ${targetLocale}`);
967
1017
  }
968
1018
  console.log(`\u{1F310} Bootstrap: Dispatching locale to Redux: ${targetLocale}`);
969
- dispatch(DASH_REDUX_ACTIONS.switchLanguage(targetLocale));
1019
+ dispatch(DASH_REDUX_ACTIONS2.switchLanguage(targetLocale));
970
1020
  console.log(`\u{1F310} Bootstrap: Emitting locale change event: ${targetLocale}`);
971
1021
  window.dispatchEvent(new CustomEvent(LOCALE_CHANGE_EVENT2, {
972
1022
  detail: { locale: targetLocale }
@@ -1127,6 +1177,7 @@ export {
1127
1177
  AppWrapperLight,
1128
1178
  CustomErrorBoundary,
1129
1179
  DEFAULT_LAYOUT_DIMENSIONS,
1180
+ DarkToggleModeLight,
1130
1181
  DashThemeContext,
1131
1182
  DashThemeProviderLight,
1132
1183
  DefaultAppLoadErrorFallback,
@@ -1146,6 +1197,7 @@ export {
1146
1197
  injectCriticalStyles,
1147
1198
  isElectron,
1148
1199
  setElectronStoreValue,
1200
+ setGlobalLoaderIcon,
1149
1201
  syncElectronStore,
1150
1202
  syncElectronStoreToLocalStorage,
1151
1203
  useAppInitialization,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashadmin/dash-boilerplate",
3
- "version": "1.3.45",
3
+ "version": "1.3.46",
4
4
  "main": "dist/index.cjs",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -12,6 +12,7 @@
12
12
  "dependencies": {
13
13
  "@emotion/react": "latest",
14
14
  "@emotion/styled": "latest",
15
+ "@mui/icons-material": "^7.3.10",
15
16
  "@mui/material": "^7.3.10",
16
17
  "@dashadmin/dash-admin": "workspace:*",
17
18
  "@dashadmin/dash-admin-state": "workspace:*",