@elevasis/ui 2.9.1 → 2.10.1

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 (74) hide show
  1. package/dist/app/index.css +137 -0
  2. package/dist/app/index.d.ts +223 -0
  3. package/dist/app/index.js +95 -0
  4. package/dist/charts/index.js +3 -2
  5. package/dist/{chunk-NYMKWGKN.js → chunk-4BF74JVD.js} +110 -7
  6. package/dist/{chunk-47YILFON.js → chunk-6PNHW4X2.js} +159 -144
  7. package/dist/chunk-ADSSLKKP.js +10 -0
  8. package/dist/chunk-AEBKE4IX.js +13 -0
  9. package/dist/{chunk-C2OFFC7J.js → chunk-AL23U6C3.js} +3 -2
  10. package/dist/{chunk-27COZ5AH.js → chunk-CEWTOKE7.js} +3 -50
  11. package/dist/{chunk-AQQYVAFK.js → chunk-CLXMNMIS.js} +8 -7
  12. package/dist/{chunk-4PHPENKX.js → chunk-E3IFHX6A.js} +27 -377
  13. package/dist/{chunk-CYXZHBP4.js → chunk-F4TPY6YL.js} +14 -3
  14. package/dist/chunk-G2TDX3W6.js +5 -0
  15. package/dist/{chunk-CTWYIRKW.js → chunk-GJVGV7QZ.js} +24 -34
  16. package/dist/chunk-IIMU5YAJ.js +53 -0
  17. package/dist/{chunk-VNUOQQNY.js → chunk-KYOF6NYW.js} +2 -2
  18. package/dist/{chunk-W4VYXIN7.js → chunk-L4XXM55J.js} +3 -142
  19. package/dist/{chunk-YCHZ4U5V.js → chunk-LPSBID5V.js} +5 -13
  20. package/dist/{chunk-F5QSLYUB.js → chunk-LW5NKRI7.js} +1189 -1300
  21. package/dist/{chunk-KGEYEUR5.js → chunk-M6ZZ2FW5.js} +7 -6
  22. package/dist/{chunk-OPT74SGF.js → chunk-N5CLIRBS.js} +31 -176
  23. package/dist/chunk-R7WLWGPO.js +126 -0
  24. package/dist/{chunk-Y3D3WFJG.js → chunk-SQQGLGHW.js} +2 -11
  25. package/dist/{chunk-KFICYU6S.js → chunk-STZJ7SY5.js} +1 -1
  26. package/dist/chunk-SZHARWKU.js +15 -0
  27. package/dist/{chunk-7PDDPNQS.js → chunk-TSX4I3NW.js} +3 -3
  28. package/dist/chunk-V7XHGJQZ.js +145 -0
  29. package/dist/{chunk-UE5QQDCR.js → chunk-WHQXDETX.js} +5 -5
  30. package/dist/{chunk-4JPW5U5I.js → chunk-XB4NWSI3.js} +53 -54
  31. package/dist/{chunk-ZZ35VSNF.js → chunk-YQLE5HR5.js} +4 -4
  32. package/dist/components/index.d.ts +6 -253
  33. package/dist/components/index.js +31 -25
  34. package/dist/features/auth/index.d.ts +0 -107
  35. package/dist/features/auth/index.js +0 -1
  36. package/dist/features/crm/index.d.ts +3 -136
  37. package/dist/features/crm/index.js +14 -9
  38. package/dist/features/dashboard/index.js +13 -9
  39. package/dist/features/delivery/index.d.ts +3 -137
  40. package/dist/features/delivery/index.js +15 -9
  41. package/dist/features/lead-gen/index.d.ts +3 -29
  42. package/dist/features/lead-gen/index.js +20 -14
  43. package/dist/features/monitoring/index.d.ts +3 -30
  44. package/dist/features/monitoring/index.js +14 -10
  45. package/dist/features/operations/index.d.ts +18 -1324
  46. package/dist/features/operations/index.js +18 -13
  47. package/dist/features/seo/index.d.ts +3 -30
  48. package/dist/features/seo/index.js +3 -2
  49. package/dist/features/settings/index.d.ts +6 -146
  50. package/dist/features/settings/index.js +13 -9
  51. package/dist/hooks/index.d.ts +10 -1403
  52. package/dist/hooks/index.js +11 -7
  53. package/dist/hooks/published.d.ts +10 -1403
  54. package/dist/hooks/published.js +11 -7
  55. package/dist/index.d.ts +97 -1510
  56. package/dist/index.js +12 -8
  57. package/dist/initialization/index.d.ts +3 -117
  58. package/dist/layout/index.d.ts +12 -2
  59. package/dist/layout/index.js +5 -4
  60. package/dist/organization/index.d.ts +3 -10
  61. package/dist/organization/index.js +2 -1
  62. package/dist/profile/index.d.ts +0 -107
  63. package/dist/provider/index.d.ts +45 -65
  64. package/dist/provider/index.js +10 -6
  65. package/dist/provider/published.d.ts +45 -65
  66. package/dist/provider/published.js +6 -3
  67. package/dist/supabase/index.d.ts +0 -209
  68. package/dist/theme/index.d.ts +1 -1
  69. package/dist/theme/index.js +3 -3
  70. package/dist/typeform/index.js +10 -10
  71. package/dist/types/index.d.ts +68 -1738
  72. package/package.json +20 -4
  73. package/src/app/README.md +24 -0
  74. package/dist/chunk-IDACMRGQ.js +0 -115
@@ -0,0 +1,137 @@
1
+ /* src/theme/custom.css */
2
+ .mantine-Button-root[data-variant=default] {
3
+ background-color: var(--color-surface);
4
+ backdrop-filter: var(--glass-blur);
5
+ -webkit-backdrop-filter: var(--glass-blur);
6
+ border: 1px solid var(--color-border);
7
+ color: var(--color-text);
8
+ }
9
+ .mantine-Button-root[data-variant=default]:hover {
10
+ background-color: var(--color-surface-hover);
11
+ }
12
+ .mantine-Accordion-control:hover {
13
+ background-color: var(--color-surface-hover);
14
+ }
15
+ .mantine-Menu-item:hover:not([data-disabled]) {
16
+ background-color: var(--color-surface-hover);
17
+ }
18
+ .mantine-Select-option:hover {
19
+ background-color: var(--color-surface-hover) !important;
20
+ }
21
+ [data-mantine-color-scheme=dark] .mantine-Tabs-root {
22
+ --tab-border-color: var(--color-border);
23
+ }
24
+ .mantine-Tabs-tab:hover {
25
+ background-color: var(--color-surface-hover);
26
+ }
27
+ .mantine-Pagination-control:not([data-active]) {
28
+ background: var(--color-surface);
29
+ }
30
+ ::-webkit-scrollbar {
31
+ width: 5px;
32
+ height: 5px;
33
+ }
34
+ ::-webkit-scrollbar-track {
35
+ background: transparent;
36
+ }
37
+ ::-webkit-scrollbar-thumb {
38
+ background: color-mix(in srgb, var(--color-text-subtle) 50%, var(--color-border));
39
+ border-radius: 4px;
40
+ }
41
+ ::-webkit-scrollbar-thumb:hover {
42
+ background: var(--color-text-subtle);
43
+ }
44
+ .mantine-Checkbox-input {
45
+ background-color: var(--color-surface);
46
+ border-color: var(--color-border);
47
+ }
48
+ .mantine-Checkbox-input:checked {
49
+ background-color: var(--color-primary);
50
+ border-color: var(--color-primary);
51
+ }
52
+ .mantine-Switch-root:has(input:not(:checked)) .mantine-Switch-track {
53
+ background-color: var(--color-surface-hover);
54
+ border-color: var(--color-border);
55
+ }
56
+ .mantine-Timeline-root {
57
+ --tl-color: var(--color-primary);
58
+ }
59
+ .mantine-Timeline-item {
60
+ --item-border-color: var(--color-border);
61
+ }
62
+ .mantine-Timeline-itemBullet {
63
+ border-color: var(--color-border);
64
+ }
65
+ .mantine-Timeline-itemBullet:where([data-with-child]) {
66
+ background-color: var(--color-primary);
67
+ border-color: var(--color-primary);
68
+ }
69
+ .recharts-surface:focus {
70
+ outline: none;
71
+ }
72
+ .hide-scrollbar {
73
+ scrollbar-width: none;
74
+ -ms-overflow-style: none;
75
+ }
76
+ .hide-scrollbar::-webkit-scrollbar {
77
+ display: none;
78
+ }
79
+
80
+ /* src/components/display/ElevasisLoader.module.css */
81
+ .wrapper {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ width: var(--loader-size);
86
+ height: var(--loader-size);
87
+ overflow: visible;
88
+ }
89
+ .loader {
90
+ width: 100%;
91
+ height: 100%;
92
+ display: block;
93
+ overflow: visible;
94
+ }
95
+ .chevron {
96
+ stroke: var(--loader-color);
97
+ stroke-width: 2;
98
+ stroke-linecap: square;
99
+ stroke-linejoin: miter;
100
+ fill: none;
101
+ opacity: 0.15;
102
+ animation: chevronPulse 2s ease-in-out infinite;
103
+ filter: drop-shadow(0 0 1.5px var(--loader-color));
104
+ }
105
+ [data-mantine-color-scheme=light] .chevron {
106
+ filter: none;
107
+ }
108
+ .c1 {
109
+ animation-delay: 0s;
110
+ }
111
+ .c2 {
112
+ animation-delay: 0.2s;
113
+ }
114
+ .c3 {
115
+ animation-delay: 0.4s;
116
+ }
117
+ @keyframes chevronPulse {
118
+ 0%, 100% {
119
+ opacity: 0.12;
120
+ filter: drop-shadow(0 0 1px var(--loader-color));
121
+ }
122
+ 40%, 60% {
123
+ opacity: 1;
124
+ filter: drop-shadow(0 0 3px var(--loader-color));
125
+ }
126
+ }
127
+ [data-mantine-color-scheme=light] .chevron {
128
+ animation-name: chevronPulseLight;
129
+ }
130
+ @keyframes chevronPulseLight {
131
+ 0%, 100% {
132
+ opacity: 0.2;
133
+ }
134
+ 40%, 60% {
135
+ opacity: 1;
136
+ }
137
+ }
@@ -0,0 +1,223 @@
1
+ import { ReactNode, ComponentType } from 'react';
2
+ import { AnyRouter } from '@tanstack/react-router';
3
+ import { QueryClient } from '@tanstack/react-query';
4
+ import { MantineThemeOverride } from '@mantine/core';
5
+
6
+ interface ApiErrorDetails {
7
+ method: string;
8
+ statusCode: number;
9
+ requestId?: string;
10
+ }
11
+
12
+ /** Framework-agnostic theme overrides bundled with a preset (fonts, radius, component styles). */
13
+ interface FrameworkThemeOverrides {
14
+ fontFamily?: string;
15
+ defaultRadius?: string;
16
+ headings?: {
17
+ fontFamily?: string;
18
+ fontWeight?: string;
19
+ };
20
+ components?: Record<string, unknown>;
21
+ }
22
+ /** Tokens every preset must define. `elevatedSurface` is progressively adopted and stays optional. */
23
+ type PresetTokens = Required<Omit<ElevasisTokenOverrides, 'elevatedSurface'>> & Pick<ElevasisTokenOverrides, 'elevatedSurface'>;
24
+ interface ThemePreset {
25
+ light: PresetTokens;
26
+ dark: PresetTokens;
27
+ /** Optional framework theme overrides bundled with this preset (fonts, radius, etc.). */
28
+ framework?: FrameworkThemeOverrides;
29
+ /**
30
+ * Subtitle font family — used for card names, section labels, and nav items.
31
+ * Sits between heading and body in the typographic hierarchy.
32
+ */
33
+ subtitleFontFamily?: string;
34
+ /** Google Fonts URLs to load when this preset is active. */
35
+ fontImports?: string[];
36
+ /** Display label for settings UI (e.g. "Tactical"). Built-in presets define this; custom presets must provide it. */
37
+ label?: string;
38
+ /** Short description for settings UI (e.g. "Tactical command center aesthetic"). */
39
+ description?: string;
40
+ /** Three representative hex colors for swatch display: [primary, dark-bg, light-bg]. */
41
+ colors?: [string, string, string];
42
+ /**
43
+ * Background layers rendered behind app content when this preset is active.
44
+ * Overridden by `theme.background` on the provider if both are set.
45
+ */
46
+ background?: ReactNode;
47
+ /**
48
+ * Loader element used in loading states when this preset is active.
49
+ * Overridden by `theme.loader` on the provider if both are set.
50
+ */
51
+ loader?: ReactNode;
52
+ }
53
+ type PresetName = 'default' | 'tactical' | 'regal' | 'cyber-volt' | 'aurora' | 'rose-gold' | 'midnight' | 'titanium' | 'canopy' | 'slate' | 'cyber-strike' | 'cyber-chrome' | 'cyber-void' | 'nirvana' | 'wave' | 'synapse' | 'cortex' | 'helios' | 'graphite' | 'quarry';
54
+
55
+ /** Flat + per-scheme override pattern. Flat values apply to both; `light`/`dark` win over flat. */
56
+ type WithSchemes<T> = T & {
57
+ light?: T;
58
+ dark?: T;
59
+ };
60
+ /**
61
+ * Theme token overrides. Each key maps 1:1 to a CSS variable.
62
+ * All optional — defaults come from Elevasis design system.
63
+ */
64
+ interface ElevasisTokenOverrides {
65
+ primary?: string;
66
+ /** Text color that contrasts with `primary`. Defaults to '#fff'. */
67
+ primaryContrast?: string;
68
+ background?: string;
69
+ surface?: string;
70
+ surfaceHover?: string;
71
+ /** Opaque surface for floating overlays (modals, menus, popovers) — guarantees readable contrast against decorative backgrounds. */
72
+ elevatedSurface?: string;
73
+ text?: string;
74
+ textDimmed?: string;
75
+ textSubtle?: string;
76
+ border?: string;
77
+ error?: string;
78
+ warning?: string;
79
+ success?: string;
80
+ glassBackground?: string;
81
+ glassBlur?: string;
82
+ shadow?: string;
83
+ cardShadow?: string;
84
+ durationFast?: string;
85
+ durationNormal?: string;
86
+ easing?: string;
87
+ /** Foreground text color for destructive/error buttons. Defaults to '#fff'. */
88
+ destructiveFg?: string;
89
+ /** Heading font family — used for titles, section headers. */
90
+ fontHeading?: string;
91
+ /** Body font family — used for general text. */
92
+ fontSans?: string;
93
+ }
94
+ /**
95
+ * Core theme config — Mantine-free.
96
+ * Used by ElevasisCoreProvider and as the base for ElevasisThemeConfig.
97
+ */
98
+ interface ElevasisCoreThemeConfig {
99
+ /** Color scheme: 'light', 'dark', or 'auto'. Defaults to 'dark'. */
100
+ colorScheme?: 'light' | 'dark' | 'auto';
101
+ /** Named preset — bundles light/dark token defaults. Defaults to 'default'. Accepts built-in PresetName or custom preset key. */
102
+ preset?: PresetName | (string & {});
103
+ /**
104
+ * Semantic token overrides fed into CSS variables.
105
+ * Flat values apply to both schemes. `light`/`dark` nested values win over flat.
106
+ */
107
+ tokens?: WithSchemes<ElevasisTokenOverrides>;
108
+ /** Custom presets map — when provided, used instead of built-in presets. Typically `{ ...presets, ...customPresets }`. */
109
+ presets?: Record<string, ThemePreset>;
110
+ }
111
+
112
+ /**
113
+ * Mantine-specific theme config — extends the headless core config with
114
+ * visual appearance and a full Mantine theme override escape hatch.
115
+ */
116
+ interface ElevasisThemeConfig extends ElevasisCoreThemeConfig {
117
+ /** Full Mantine theme override — merged on top of Elevasis defaults. */
118
+ mantine?: MantineThemeOverride;
119
+ /** Background layers rendered behind app content. Defaults to Elevasis background (PerspectiveGrid + RadiantGlow + FloatingOrbs + FilmGrain). */
120
+ background?: ReactNode;
121
+ /** Loader element rendered during loading states. Defaults to Elevasis chevron loader (xl). */
122
+ loader?: ReactNode;
123
+ }
124
+
125
+ /**
126
+ * Store integration hooks for reading and writing theme state.
127
+ * Pass functions that read from your Zustand store (or equivalent).
128
+ */
129
+ interface ElevasisAppStoreConfig {
130
+ /** Returns the active preset name (e.g. 'default', 'ocean') */
131
+ useThemePreset: () => string;
132
+ /** Returns the active color scheme ('light' | 'dark' | 'auto') */
133
+ useThemeColorScheme: () => string;
134
+ /** Returns the setTheme action from the store */
135
+ useSetTheme: () => (theme: Record<string, unknown>) => void;
136
+ }
137
+ /**
138
+ * Configuration for createElevasisApp.
139
+ *
140
+ * NOTE: CSS imports are NOT handled by this factory — consumers must import
141
+ * the required CSS in their entry point:
142
+ * ```ts
143
+ * import './style.css'
144
+ * import '@elevasis/ui/components/index.css'
145
+ * import '@elevasis/ui/graph/index.css'
146
+ * import '@elevasis/ui/provider/index.css'
147
+ * ```
148
+ *
149
+ * Module-level side effects (initializeBetterStack, suppressKnownWarnings) also
150
+ * remain in the consumer's main.tsx — call them before invoking createElevasisApp.
151
+ */
152
+ interface ElevasisAppConfig {
153
+ /** TanStack Router instance (from createRouter) */
154
+ router: AnyRouter;
155
+ /** Elevasis API base URL */
156
+ apiUrl: string;
157
+ /** WorkOS AuthKit configuration */
158
+ auth: {
159
+ clientId: string;
160
+ redirectUri?: string;
161
+ apiHostname?: string;
162
+ devMode?: boolean;
163
+ };
164
+ /**
165
+ * Zustand store hooks for theme state.
166
+ * When omitted, uses static defaults ('default' preset, 'dark' scheme, no sync).
167
+ */
168
+ store?: ElevasisAppStoreConfig;
169
+ /** Extra theme configuration (presets map, background, loader) */
170
+ theme?: {
171
+ presets?: ElevasisThemeConfig['presets'];
172
+ background?: ReactNode;
173
+ loader?: ReactNode;
174
+ };
175
+ /** Custom QueryClient. A default is created internally when omitted. */
176
+ queryClient?: QueryClient;
177
+ /** Callback for API errors (status >= 500) */
178
+ onApiError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
179
+ /**
180
+ * Component to render when VITE_WORKOS_CLIENT_ID (or auth.clientId) is missing.
181
+ * When omitted and clientId is falsy, renders null.
182
+ */
183
+ MissingEnvNotice?: ComponentType;
184
+ /**
185
+ * Called with the current access token whenever the auth user changes.
186
+ * Use this to sync the token to a debug logger or external service.
187
+ */
188
+ onAuthTokenChange?: (token: string | undefined) => void;
189
+ }
190
+ /**
191
+ * Creates a root App component from a declarative config.
192
+ *
193
+ * Absorbs the boilerplate common to every template's main.tsx:
194
+ * - Theme preset/colorScheme reading from a Zustand store
195
+ * - Missing env var guard
196
+ * - ElevasisUIProvider assembly
197
+ * - Auth token sync
198
+ * - Profile theme sync
199
+ * - Notifications + RouterProvider rendering
200
+ *
201
+ * @example
202
+ * ```tsx
203
+ * const App = createElevasisApp({
204
+ * router,
205
+ * apiUrl: import.meta.env.VITE_API_URL,
206
+ * auth: { clientId: import.meta.env.VITE_WORKOS_CLIENT_ID, devMode: true },
207
+ * store: {
208
+ * useThemePreset: () => useAppStore(s => s.theme.preset),
209
+ * useThemeColorScheme: () => useAppStore(s => s.theme.colorScheme),
210
+ * useSetTheme: () => useAppStore(s => s.setTheme),
211
+ * },
212
+ * MissingEnvNotice,
213
+ * onAuthTokenChange: (token) => uiLogger.setAuthToken(token),
214
+ * onApiError: (endpoint, error, details) => bslogAPIError(endpoint, error, details),
215
+ * })
216
+ *
217
+ * createRoot(document.getElementById('root')!).render(<App />)
218
+ * ```
219
+ */
220
+ declare function createElevasisApp(config: ElevasisAppConfig): ComponentType;
221
+
222
+ export { createElevasisApp };
223
+ export type { ElevasisAppConfig, ElevasisAppStoreConfig };
@@ -0,0 +1,95 @@
1
+ import { ElevasisUIProvider } from '../chunk-LPSBID5V.js';
2
+ import '../chunk-6PNHW4X2.js';
3
+ import '../chunk-F4TPY6YL.js';
4
+ import '../chunk-R7WLWGPO.js';
5
+ import '../chunk-SZHARWKU.js';
6
+ import '../chunk-NVOCKXUQ.js';
7
+ import '../chunk-V7XHGJQZ.js';
8
+ import '../chunk-QJ2KCHKX.js';
9
+ import '../chunk-IOKL7BKE.js';
10
+ import { useInitialization } from '../chunk-TUXTSEAF.js';
11
+ import '../chunk-DD3CCMCZ.js';
12
+ import '../chunk-QEPXAWE2.js';
13
+ import '../chunk-BRJ3QZ4E.js';
14
+ import { useCallback, useEffect } from 'react';
15
+ import { RouterProvider } from '@tanstack/react-router';
16
+ import { Notifications } from '@mantine/notifications';
17
+ import { useAuth } from '@workos-inc/authkit-react';
18
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
19
+
20
+ var DEFAULT_PRESET = "default";
21
+ var DEFAULT_COLOR_SCHEME = "dark";
22
+ function AppWithStore({ config }) {
23
+ const themePreset = config.store?.useThemePreset() ?? DEFAULT_PRESET;
24
+ const themeColorScheme = config.store?.useThemeColorScheme() ?? DEFAULT_COLOR_SCHEME;
25
+ const handleApiError = useCallback(
26
+ (endpoint, error, details) => {
27
+ config.onApiError?.(endpoint, error, details);
28
+ },
29
+ [config.onApiError]
30
+ );
31
+ if (!config.auth.clientId) {
32
+ if (config.MissingEnvNotice) {
33
+ return /* @__PURE__ */ jsx(config.MissingEnvNotice, {});
34
+ }
35
+ return null;
36
+ }
37
+ const assembledTheme = {
38
+ preset: themePreset,
39
+ colorScheme: themeColorScheme,
40
+ ...config.theme?.presets ? { presets: config.theme.presets } : {},
41
+ ...config.theme?.background !== void 0 ? { background: config.theme.background } : {},
42
+ ...config.theme?.loader !== void 0 ? { loader: config.theme.loader } : {}
43
+ };
44
+ return /* @__PURE__ */ jsx(
45
+ ElevasisUIProvider,
46
+ {
47
+ theme: assembledTheme,
48
+ auth: {
49
+ mode: "authkit",
50
+ clientId: config.auth.clientId,
51
+ redirectUri: config.auth.redirectUri,
52
+ apiHostname: config.auth.apiHostname,
53
+ devMode: config.auth.devMode
54
+ },
55
+ queryClient: config.queryClient,
56
+ apiUrl: config.apiUrl,
57
+ onError: config.onApiError ? handleApiError : void 0,
58
+ children: /* @__PURE__ */ jsx(AuthenticatedApp, { config })
59
+ }
60
+ );
61
+ }
62
+ function AuthenticatedApp({ config }) {
63
+ const { user, getAccessToken } = useAuth();
64
+ const setTheme = config.store?.useSetTheme();
65
+ const { profile } = useInitialization();
66
+ useEffect(() => {
67
+ if (!config.onAuthTokenChange) return;
68
+ if (user) {
69
+ getAccessToken().then((token) => config.onAuthTokenChange(token)).catch(() => {
70
+ });
71
+ } else {
72
+ config.onAuthTokenChange(void 0);
73
+ }
74
+ }, [user, getAccessToken, config.onAuthTokenChange]);
75
+ useEffect(() => {
76
+ if (!setTheme || !profile?.config) return;
77
+ const cfg = profile.config;
78
+ if (cfg.theme) {
79
+ setTheme(cfg.theme);
80
+ }
81
+ }, [profile, setTheme]);
82
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
83
+ /* @__PURE__ */ jsx(Notifications, {}),
84
+ /* @__PURE__ */ jsx(RouterProvider, { router: config.router })
85
+ ] });
86
+ }
87
+ function createElevasisApp(config) {
88
+ function ElevasisApp() {
89
+ return /* @__PURE__ */ jsx(AppWithStore, { config });
90
+ }
91
+ ElevasisApp.displayName = "ElevasisApp";
92
+ return ElevasisApp;
93
+ }
94
+
95
+ export { createElevasisApp };
@@ -1,8 +1,9 @@
1
- export { ActivityTrendChart, ChartFrame, CombinedTrendChart, CostTrendChart, CyberAreaChart, CyberDonut, CyberDonutTooltip, CyberLegendItem, HeroStatsRow, getSeriesColor, useCyberColors } from '../chunk-KFICYU6S.js';
1
+ export { ActivityTrendChart, ChartFrame, CombinedTrendChart, CostTrendChart, CyberAreaChart, CyberDonut, CyberDonutTooltip, CyberLegendItem, HeroStatsRow, getSeriesColor, useCyberColors } from '../chunk-STZJ7SY5.js';
2
2
  import '../chunk-LXHZYSMQ.js';
3
- import '../chunk-Y3D3WFJG.js';
3
+ import '../chunk-SQQGLGHW.js';
4
4
  import '../chunk-3KMDHCAR.js';
5
5
  import '../chunk-NYBEU5TE.js';
6
+ import '../chunk-SZHARWKU.js';
6
7
  import '../chunk-2IFYDILW.js';
7
8
  import '../chunk-ELJIFLCB.js';
8
9
  import '../chunk-DT3QYZVU.js';
@@ -1,12 +1,12 @@
1
- import { SubshellNavItem } from './chunk-27COZ5AH.js';
1
+ import { SubshellNavItem } from './chunk-CEWTOKE7.js';
2
2
  import { NavigationButton } from './chunk-NYBEU5TE.js';
3
3
  import { useAppearance } from './chunk-QJ2KCHKX.js';
4
- import { sidebarItemGap, sidebarSubLinkPaddingY, sidebarSubLinkPaddingX, sidebarSubLinkIndent, sidebarHoverDelay, sidebarTransitionDuration, sidebarCollapsedWidth, sidebarWidth, topbarHeight, sidebarToggleIconSize, sidebarSectionPadding } from './chunk-DT3QYZVU.js';
4
+ import { sidebarItemGap, sidebarSubLinkPaddingY, sidebarSubLinkPaddingX, sidebarSubLinkIndent, sidebarHoverDelay, sidebarTransitionDuration, sidebarCollapsedWidth, sidebarWidth, topbarHeight, sidebarToggleIconSize, sidebarSectionPadding, sidebarGroupChevronSize, sidebarIconInnerSize } from './chunk-DT3QYZVU.js';
5
5
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { createContext, memo, useEffect, createElement, useContext, useRef, useLayoutEffect, useState } from 'react';
8
- import { Collapse, HoverCard, Stack, Group, Text, UnstyledButton, Tooltip, ScrollArea, Menu, Avatar, useMantineColorScheme, Switch, Code } from '@mantine/core';
9
- import { IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconUser, IconLogout, IconMoonStars, IconSun } from '@tabler/icons-react';
8
+ import { Collapse, HoverCard, Stack, Group, Text, UnstyledButton, Tooltip, ScrollArea, Menu, Avatar, Box, useMantineColorScheme, Switch, Code } from '@mantine/core';
9
+ import { IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconUser, IconLogout, IconChevronDown, IconChevronRight, IconMoonStars, IconSun } from '@tabler/icons-react';
10
10
 
11
11
  var randRange = (min, max) => min + Math.random() * (max - min);
12
12
  var FLUX_SPARKS = Array.from({ length: 30 }, () => {
@@ -381,7 +381,7 @@ var isOverviewLink = (label, link) => {
381
381
  var SubLinkItem = ({ linkItem, currentPath }) => {
382
382
  const { Link } = useRouterContext();
383
383
  const isActive = isOverviewLink(linkItem.label, linkItem.link) ? currentPath === linkItem.link : isPathActive(linkItem.link, currentPath);
384
- const activeColor = "var(--color-primary)";
384
+ const activeColor2 = "var(--color-primary)";
385
385
  const activeColorBg = "color-mix(in srgb, var(--color-primary) 10%, transparent)";
386
386
  const defaultColor = "var(--color-text-subtle)";
387
387
  const hoverColor = "var(--color-text)";
@@ -396,7 +396,7 @@ var SubLinkItem = ({ linkItem, currentPath }) => {
396
396
  textDecoration: "none",
397
397
  fontFamily: "var(--elevasis-font-family-subtitle)",
398
398
  fontSize: "var(--mantine-font-size-sm)",
399
- color: isActive ? activeColor : defaultColor,
399
+ color: isActive ? activeColor2 : defaultColor,
400
400
  backgroundColor: isActive ? activeColorBg : "transparent",
401
401
  padding: `${sidebarSubLinkPaddingY}px ${sidebarSubLinkPaddingX}px ${sidebarSubLinkPaddingY}px ${sidebarSubLinkIndent}px`,
402
402
  borderRadius: "var(--mantine-radius-default)",
@@ -958,6 +958,109 @@ var Sidebar = memo(function Sidebar2({
958
958
  /* @__PURE__ */ jsx(SidebarBottomSection, { user, onLogout, onAccountClick })
959
959
  ] });
960
960
  });
961
+ var activeColor = "var(--color-primary)";
962
+ var defaultTextColor = "var(--color-text)";
963
+ var subtleColor = "var(--color-text-subtle)";
964
+ var activeBg = `color-mix(in srgb, ${activeColor} 10%, transparent)`;
965
+ var CollapsibleSidebarGroup = ({
966
+ icon: Icon,
967
+ label,
968
+ isExpanded,
969
+ onToggle,
970
+ isActive = false,
971
+ badge,
972
+ children,
973
+ onLabelClick,
974
+ emptyMessage = "No items",
975
+ isEmpty = false,
976
+ isLoading = false,
977
+ loadingComponent
978
+ }) => {
979
+ const showActiveStyle = !isExpanded && isActive;
980
+ const iconColor = showActiveStyle ? activeColor : subtleColor;
981
+ const textColor = showActiveStyle ? activeColor : defaultTextColor;
982
+ const fontWeight = showActiveStyle ? 600 : 500;
983
+ const handleLabelClick = (e) => {
984
+ if (onLabelClick) {
985
+ e.stopPropagation();
986
+ onLabelClick();
987
+ }
988
+ };
989
+ return /* @__PURE__ */ jsxs(Box, { children: [
990
+ /* @__PURE__ */ jsx(
991
+ UnstyledButton,
992
+ {
993
+ onClick: onToggle,
994
+ style: {
995
+ display: "flex",
996
+ alignItems: "center",
997
+ width: "100%",
998
+ padding: "var(--mantine-spacing-xs)",
999
+ color: textColor,
1000
+ backgroundColor: showActiveStyle ? activeBg : "transparent",
1001
+ transition: `all var(--duration-fast) var(--easing)`,
1002
+ cursor: "pointer",
1003
+ overflow: "hidden"
1004
+ },
1005
+ onMouseEnter: (e) => {
1006
+ if (!showActiveStyle) {
1007
+ e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
1008
+ }
1009
+ },
1010
+ onMouseLeave: (e) => {
1011
+ if (!showActiveStyle) {
1012
+ e.currentTarget.style.backgroundColor = "transparent";
1013
+ }
1014
+ },
1015
+ children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { width: "100%" }, children: [
1016
+ /* @__PURE__ */ jsx(Box, { style: { flexShrink: 0, color: iconColor }, children: isExpanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: sidebarGroupChevronSize }) : /* @__PURE__ */ jsx(IconChevronRight, { size: sidebarGroupChevronSize }) }),
1017
+ /* @__PURE__ */ jsx(
1018
+ Box,
1019
+ {
1020
+ style: { flexShrink: 0, color: iconColor, cursor: onLabelClick ? "pointer" : "inherit" },
1021
+ onClick: onLabelClick ? handleLabelClick : void 0,
1022
+ children: /* @__PURE__ */ jsx(Icon, { size: sidebarIconInnerSize, color: activeColor })
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ jsx(
1026
+ Text,
1027
+ {
1028
+ size: "sm",
1029
+ fw: fontWeight,
1030
+ style: {
1031
+ fontFamily: "var(--elevasis-font-family-subtitle)",
1032
+ color: textColor,
1033
+ transition: `color var(--duration-fast) var(--easing)`,
1034
+ overflow: "hidden",
1035
+ textOverflow: "ellipsis",
1036
+ whiteSpace: "nowrap",
1037
+ flex: 1,
1038
+ cursor: onLabelClick ? "pointer" : "inherit"
1039
+ },
1040
+ onClick: onLabelClick ? handleLabelClick : void 0,
1041
+ children: label
1042
+ }
1043
+ ),
1044
+ badge && /* @__PURE__ */ jsx(Box, { style: { flexShrink: 0 }, children: badge })
1045
+ ] })
1046
+ }
1047
+ ),
1048
+ /* @__PURE__ */ jsx(Collapse, { in: isExpanded, children: /* @__PURE__ */ jsx(
1049
+ Stack,
1050
+ {
1051
+ gap: 0,
1052
+ mt: "xs",
1053
+ ml: "xs",
1054
+ style: {
1055
+ borderLeft: `1px solid color-mix(in srgb, var(--color-primary) 40%, transparent)`,
1056
+ marginLeft: "calc(var(--mantine-spacing-xs) + 6px)",
1057
+ paddingLeft: "calc(var(--mantine-spacing-xs) - 2px)"
1058
+ },
1059
+ children: isLoading ? loadingComponent : isEmpty ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { padding: "6px 8px" }, children: emptyMessage }) : children
1060
+ }
1061
+ ) })
1062
+ ] });
1063
+ };
961
1064
  var SubshellNavList = ({ items }) => {
962
1065
  const { currentPath, navigate } = useRouterContext();
963
1066
  return /* @__PURE__ */ jsx(Fragment, { children: items.map((item) => {
@@ -1067,4 +1170,4 @@ var Topbar = ({ version, leftContent, children }) => {
1067
1170
  ] });
1068
1171
  };
1069
1172
 
1070
- export { AppShellContainer, AppShellContentContainer, AppShellRightSideContainer, AppShellRightSideOuterContainer, AppTopbarAdjusterWrapper, CyberParticles, LinksGroup, Sidebar, SidebarContext, SidebarProvider, SubshellNavList, Topbar, TopbarContainer, Vignette, subsidebarWidth, useSidebar, useSidebarCollapse };
1173
+ export { AppShellContainer, AppShellContentContainer, AppShellRightSideContainer, AppShellRightSideOuterContainer, AppTopbarAdjusterWrapper, CollapsibleSidebarGroup, CyberParticles, LinksGroup, Sidebar, SidebarContext, SidebarProvider, SubshellNavList, Topbar, TopbarContainer, Vignette, subsidebarWidth, useSidebar, useSidebarCollapse };