@saasicat/ui-vue 0.22.2 → 0.23.0

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 (108) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-LY52T4N4.js → chunk-TQQMKWN6.js} +58 -1
  3. package/dist/index.cjs +213 -159
  4. package/dist/index.d.cts +2 -2
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.js +7 -1
  7. package/dist/quasar/index.cjs +116 -20
  8. package/dist/quasar/index.d.cts +48 -3
  9. package/dist/quasar/index.d.ts +48 -3
  10. package/dist/quasar/index.js +58 -3
  11. package/dist/{use-super-admin-i18n-CgTuNi8h.d.cts → use-sa-theme-B5t7oXph.d.cts} +51 -1
  12. package/dist/{use-super-admin-i18n-CHNdsSlm.d.ts → use-sa-theme-OUBlaqgl.d.ts} +51 -1
  13. package/package.json +5 -2
  14. package/src/components/BundleVersionPublishDialog.vue +17 -17
  15. package/src/components/KvBlock.vue +6 -6
  16. package/src/components/MarketingPromotionsTab.vue +78 -78
  17. package/src/components/MfaPromptDialog.vue +2 -2
  18. package/src/components/TenantActionConfirmDialog.vue +5 -5
  19. package/src/components/VersionDiffPreview.vue +18 -18
  20. package/src/components/bundle-editor/BundleCreatePanel.vue +52 -52
  21. package/src/components/bundle-editor/BundleFeaturesEditor.vue +20 -20
  22. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +33 -33
  23. package/src/components/bundle-editor/BundleQuotasEditor.vue +26 -26
  24. package/src/components/bundle-editor/BundleStatusBanner.vue +21 -21
  25. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +48 -48
  26. package/src/components/bundle-editor/BundleVersionStrip.vue +30 -30
  27. package/src/components/dialogs/PilotCreateDialog.vue +20 -20
  28. package/src/components/dialogs/PilotEditDialog.vue +6 -6
  29. package/src/components/dialogs/PromoCodeCreateDialog.vue +9 -9
  30. package/src/components/dialogs/PromoCodeDialogFields.vue +61 -61
  31. package/src/components/dialogs/PromoCodeEditDialog.vue +11 -11
  32. package/src/components/dialogs/pilot-dialog.css +48 -48
  33. package/src/components/plan/PlanCycleToggle.vue +9 -16
  34. package/src/components/plan/PlanGrid.vue +30 -34
  35. package/src/components/plan/PriceSummary.vue +35 -35
  36. package/src/components/plan/PromoCodeInput.vue +26 -26
  37. package/src/components/plan/PublicBundleGrid.vue +32 -28
  38. package/src/components/plan-create-dialog/PlanCreateDialog.vue +49 -49
  39. package/src/components/plan-detail/PlanDetail.vue +172 -156
  40. package/src/components/plan-detail/PlanTitleEdit.vue +11 -11
  41. package/src/components/plan-list/PlanList.vue +98 -77
  42. package/src/components/plan-matrix/PlanMatrix.vue +89 -89
  43. package/src/components/plan-review/PlanReview.vue +60 -56
  44. package/src/components/plan-version-editor/PlanVersionEditor.vue +224 -200
  45. package/src/components/wizard-stepper/WizardStepper.vue +17 -17
  46. package/src/index.ts +1 -0
  47. package/src/pages-standard/AdminLayout.vue +58 -37
  48. package/src/pages-standard/AdminManifestErrorPage.vue +6 -6
  49. package/src/pages-standard/AuditPage.vue +3 -3
  50. package/src/pages-standard/BundlesPage.vue +36 -36
  51. package/src/pages-standard/DashboardPage.vue +17 -17
  52. package/src/pages-standard/DiscoveryPage.vue +55 -49
  53. package/src/pages-standard/EmailHistoryPage.vue +53 -71
  54. package/src/pages-standard/MarketingCatalogPage.vue +226 -218
  55. package/src/pages-standard/PilotsPage.vue +7 -6
  56. package/src/pages-standard/PlatformEmailPage.vue +18 -18
  57. package/src/pages-standard/PromoCodeDetailPage.vue +3 -3
  58. package/src/pages-standard/PromoCodesPage.vue +7 -6
  59. package/src/pages-standard/SuperAdminLoginPage.vue +39 -25
  60. package/src/pages-standard/SuperAdminSetupWizard.vue +44 -33
  61. package/src/pages-standard/TenantDetailPage.vue +7 -7
  62. package/src/pages-standard/TenantsPage.vue +11 -46
  63. package/src/pages-standard/bundles-page/BundleAccordionList.vue +13 -13
  64. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +24 -24
  65. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +22 -22
  66. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +39 -39
  67. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +26 -26
  68. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +1 -1
  69. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -16
  70. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +21 -15
  71. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +45 -45
  72. package/src/pages-standard/plans-page/PlanBundleOverview.vue +21 -15
  73. package/src/pages-standard/plans-page/PlanPublishDialog.vue +4 -4
  74. package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
  75. package/src/pages-standard/sa-theme.css +9 -687
  76. package/src/pages-standard/tenants/StatusPill.vue +13 -13
  77. package/src/pages-tenant/LimitsRow.vue +4 -4
  78. package/src/pages-tenant/MySubscriptionBundlesPage.vue +61 -61
  79. package/src/pages-tenant/OnboardingConfigurator.vue +24 -24
  80. package/src/pages-tenant/PackageSnapshotPanel.vue +10 -16
  81. package/src/pages-tenant/PendingVersionBanner.vue +12 -12
  82. package/src/pages-tenant/PlanChangeWizard.vue +20 -27
  83. package/src/pages-tenant/TenantPlanSection.vue +13 -21
  84. package/src/pages-tenant/UsageBar.vue +7 -7
  85. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +14 -14
  86. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +10 -10
  87. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +2 -2
  88. package/src/quasar/create-super-admin-app.ts +96 -1
  89. package/src/quasar/dark-bridge.ts +66 -0
  90. package/src/quasar/index.ts +1 -0
  91. package/src/ui/theme/_breakpoints.scss +28 -0
  92. package/src/ui/theme/base.css +50 -0
  93. package/src/ui/theme/components/body.css +23 -0
  94. package/src/ui/theme/components/button.css +158 -0
  95. package/src/ui/theme/components/card.css +48 -0
  96. package/src/ui/theme/components/field.css +38 -0
  97. package/src/ui/theme/components/hero.css +46 -0
  98. package/src/ui/theme/components/paginator.css +63 -0
  99. package/src/ui/theme/components/section.css +67 -0
  100. package/src/ui/theme/components/statistics.css +189 -0
  101. package/src/ui/theme/components/table.css +60 -0
  102. package/src/ui/theme/index.css +42 -0
  103. package/src/ui/theme/tokens.legacy.css +147 -0
  104. package/src/ui/theme/tokens.primitive.css +108 -0
  105. package/src/ui/theme/tokens.scale.css +103 -0
  106. package/src/ui/theme/tokens.semantic.dark.css +173 -0
  107. package/src/ui/theme/tokens.semantic.light.css +212 -0
  108. package/src/vue/use-sa-theme.ts +154 -0
package/dist/index.d.cts CHANGED
@@ -2,8 +2,8 @@ import { BootLoaderOptions, ManifestLoaderOptions, BuildRouteEntry, SidebarSecti
2
2
  export { ADMIN_UI_VERSION, AdminPromoListFilter, AdminPromoListRow, AdminResourceClientOptions, BatchColumnDriftError, BatchColumnFetcher, BatchColumnRow, BatchColumnValue, BootLoadError, CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpJsonError, LoginBootProject, LoginBrandFallback, LoginBranding, ManifestLoadError, MessageParams, ParamStyle, PlanCounts, PlanRowLike, PlanVersionLike, ResolvePlansInput, ResolvedPlan, SidebarItem, buildRoutes, buildSidebar, countPlans, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isCurrentlyValid, isExpired, isFutureScheduled, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, resolvePlans, todayIsoDate, trimTrailingSlashes } from './client/index.cjs';
3
3
  import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-DJcfm5N2.cjs';
4
4
  export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-DJcfm5N2.cjs';
5
- import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-CgTuNi8h.cjs';
6
- export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY, p as SUPER_ADMIN_MANIFEST_KEY, q as SUPER_ADMIN_NOTIFY_KEY, r as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, s as SuperAdminLoginResult, t as SuperAdminManifestGuardOptions, U as UiNotify, u as UiNotifyKind, v as UiNotifyOptions, w as buildNavigationGuard, x as createSuperAdminI18n, y as useSaMessages, z as useSuperAdminI18n } from './use-super-admin-i18n-CgTuNi8h.cjs';
5
+ import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-sa-theme-B5t7oXph.cjs';
6
+ export { h as ExtensionLoader, I as InstallPlugin, i as SA_LOCALE_STORAGE_KEY, j as SA_THEME_KEY, k as SUPER_ADMIN_ACTIONS_KEY, l as SUPER_ADMIN_BRAND_KEY, m as SUPER_ADMIN_ENDPOINTS_KEY, n as SUPER_ADMIN_EXTENSIONS_KEY, o as SUPER_ADMIN_HTTP_KEY, p as SUPER_ADMIN_I18N_KEY, q as SUPER_ADMIN_LOGIN_ADAPTER_KEY, r as SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY, s as SUPER_ADMIN_MANIFEST_KEY, t as SUPER_ADMIN_NOTIFY_KEY, u as SaColorScheme, v as SaResolvedScheme, g as SaTheme, e as SaThemeOptions, w as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, f as SuperAdminI18n, d as SuperAdminI18nOptions, x as SuperAdminLoginResult, y as SuperAdminManifestGuardOptions, U as UiNotify, z as UiNotifyKind, B as UiNotifyOptions, C as buildNavigationGuard, D as createSaTheme, F as createSuperAdminI18n, G as useSaMessages, H as useSaTheme, J as useSuperAdminI18n } from './use-sa-theme-B5t7oXph.cjs';
7
7
  import { AdminManifest, TenantListFilter, TenantDto, AuditQuery, AuditEntry, FeatureUiRegistry, PromoPreviewResponse, OnboardingSelectionRequest, PublicMarketingBundle, FeatureDef, FeatureKey, PublicBootResponse, DiscoverySnapshot, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, ReviewCatalogEntryData, CatalogEntryI18n, UpdateCatalogEntryBaseData, SyncDiscoveryResult, BundleVersionRow, CreateBundleVersionDraftData, BundleVersionMutationResult, UpdateBundleVersionDraftData, BundleRow, CreateBundleData, UpdateBundleData, SubscriptionBundleRecord, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, PromotionRow, CreatePromotionData, UpdatePromotionData, PlanVersionRow, CreatePlanVersionDraftData, PlanVersionMutationResult, UpdatePlanVersionDraftData, PlanRow, CreatePlanData, UpdatePlanData, TenantActionDef } from '@saasicat/types';
8
8
  import { RouteRecordRaw, NavigationGuardWithThis } from 'vue-router';
9
9
  import * as vue from 'vue';
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import { BootLoaderOptions, ManifestLoaderOptions, BuildRouteEntry, SidebarSecti
2
2
  export { ADMIN_UI_VERSION, AdminPromoListFilter, AdminPromoListRow, AdminResourceClientOptions, BatchColumnDriftError, BatchColumnFetcher, BatchColumnRow, BatchColumnValue, BootLoadError, CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpJsonError, LoginBootProject, LoginBrandFallback, LoginBranding, ManifestLoadError, MessageParams, ParamStyle, PlanCounts, PlanRowLike, PlanVersionLike, ResolvePlansInput, ResolvedPlan, SidebarItem, buildRoutes, buildSidebar, countPlans, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isCurrentlyValid, isExpired, isFutureScheduled, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, resolvePlans, todayIsoDate, trimTrailingSlashes } from './client/index.js';
3
3
  import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-DJcfm5N2.js';
4
4
  export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-DJcfm5N2.js';
5
- import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-CHNdsSlm.js';
6
- export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY, p as SUPER_ADMIN_MANIFEST_KEY, q as SUPER_ADMIN_NOTIFY_KEY, r as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, s as SuperAdminLoginResult, t as SuperAdminManifestGuardOptions, U as UiNotify, u as UiNotifyKind, v as UiNotifyOptions, w as buildNavigationGuard, x as createSuperAdminI18n, y as useSaMessages, z as useSuperAdminI18n } from './use-super-admin-i18n-CHNdsSlm.js';
5
+ import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-sa-theme-OUBlaqgl.js';
6
+ export { h as ExtensionLoader, I as InstallPlugin, i as SA_LOCALE_STORAGE_KEY, j as SA_THEME_KEY, k as SUPER_ADMIN_ACTIONS_KEY, l as SUPER_ADMIN_BRAND_KEY, m as SUPER_ADMIN_ENDPOINTS_KEY, n as SUPER_ADMIN_EXTENSIONS_KEY, o as SUPER_ADMIN_HTTP_KEY, p as SUPER_ADMIN_I18N_KEY, q as SUPER_ADMIN_LOGIN_ADAPTER_KEY, r as SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY, s as SUPER_ADMIN_MANIFEST_KEY, t as SUPER_ADMIN_NOTIFY_KEY, u as SaColorScheme, v as SaResolvedScheme, g as SaTheme, e as SaThemeOptions, w as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, f as SuperAdminI18n, d as SuperAdminI18nOptions, x as SuperAdminLoginResult, y as SuperAdminManifestGuardOptions, U as UiNotify, z as UiNotifyKind, B as UiNotifyOptions, C as buildNavigationGuard, D as createSaTheme, F as createSuperAdminI18n, G as useSaMessages, H as useSaTheme, J as useSuperAdminI18n } from './use-sa-theme-OUBlaqgl.js';
7
7
  import { AdminManifest, TenantListFilter, TenantDto, AuditQuery, AuditEntry, FeatureUiRegistry, PromoPreviewResponse, OnboardingSelectionRequest, PublicMarketingBundle, FeatureDef, FeatureKey, PublicBootResponse, DiscoverySnapshot, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, ReviewCatalogEntryData, CatalogEntryI18n, UpdateCatalogEntryBaseData, SyncDiscoveryResult, BundleVersionRow, CreateBundleVersionDraftData, BundleVersionMutationResult, UpdateBundleVersionDraftData, BundleRow, CreateBundleData, UpdateBundleData, SubscriptionBundleRecord, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, PromotionRow, CreatePromotionData, UpdatePromotionData, PlanVersionRow, CreatePlanVersionDraftData, PlanVersionMutationResult, UpdatePlanVersionDraftData, PlanRow, CreatePlanData, UpdatePlanData, TenantActionDef } from '@saasicat/types';
8
8
  import { RouteRecordRaw, NavigationGuardWithThis } from 'vue-router';
9
9
  import * as vue from 'vue';
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  } from "./chunk-XMMFN2WJ.js";
31
31
  import {
32
32
  SA_LOCALE_STORAGE_KEY,
33
+ SA_THEME_KEY,
33
34
  SUPER_ADMIN_ACTIONS_KEY,
34
35
  SUPER_ADMIN_BRAND_KEY,
35
36
  SUPER_ADMIN_ENDPOINTS_KEY,
@@ -41,10 +42,12 @@ import {
41
42
  SUPER_ADMIN_MANIFEST_KEY,
42
43
  SUPER_ADMIN_NOTIFY_KEY,
43
44
  buildNavigationGuard,
45
+ createSaTheme,
44
46
  createSuperAdminI18n,
45
47
  useSaMessages,
48
+ useSaTheme,
46
49
  useSuperAdminI18n
47
- } from "./chunk-LY52T4N4.js";
50
+ } from "./chunk-TQQMKWN6.js";
48
51
  import {
49
52
  DEFAULT_SA_LOCALE,
50
53
  SA_INTL_LOCALES,
@@ -2858,6 +2861,7 @@ export {
2858
2861
  SA_LOCALE_LABELS,
2859
2862
  SA_LOCALE_STORAGE_KEY,
2860
2863
  SA_MESSAGES,
2864
+ SA_THEME_KEY,
2861
2865
  SERVER_PAGE_SIZE_OPTIONS,
2862
2866
  SUPER_ADMIN_ACTIONS_KEY,
2863
2867
  SUPER_ADMIN_BRAND_KEY,
@@ -2883,6 +2887,7 @@ export {
2883
2887
  createPlatformLoaders,
2884
2888
  createProjectPageHostRoute,
2885
2889
  createSaCatalog,
2890
+ createSaTheme,
2886
2891
  createSuperAdminI18n,
2887
2892
  defaultHttpClient,
2888
2893
  defaultIconForActionKey,
@@ -2932,6 +2937,7 @@ export {
2932
2937
  usePromotions,
2933
2938
  usePublicBoot,
2934
2939
  useSaMessages,
2940
+ useSaTheme,
2935
2941
  useSubscriptionDraft,
2936
2942
  useSuperAdminActions,
2937
2943
  useSuperAdminBrand,
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/quasar/index.ts
21
21
  var quasar_exports = {};
22
22
  __export(quasar_exports, {
23
+ SA_PORTAL_CLASS: () => SA_PORTAL_CLASS,
24
+ bindSaThemeToDocument: () => bindSaThemeToDocument,
23
25
  createSuperAdminApp: () => createSuperAdminApp,
24
26
  quasarNotify: () => quasarNotify,
25
27
  useSuperAdminNotify: () => useSuperAdminNotify
@@ -27,8 +29,8 @@ __export(quasar_exports, {
27
29
  module.exports = __toCommonJS(quasar_exports);
28
30
 
29
31
  // src/quasar/create-super-admin-app.ts
30
- var import_vue3 = require("vue");
31
- var import_quasar2 = require("quasar");
32
+ var import_vue5 = require("vue");
33
+ var import_quasar3 = require("quasar");
32
34
  var import_pinia = require("pinia");
33
35
  var import_vue_router = require("vue-router");
34
36
 
@@ -146,8 +148,49 @@ var SUPER_ADMIN_NOTIFY_KEY = /* @__PURE__ */ Symbol.for(
146
148
  "@saasicat/ui-vue/SUPER_ADMIN_NOTIFY"
147
149
  );
148
150
 
149
- // src/vue/use-super-admin-i18n.ts
151
+ // src/vue/use-sa-theme.ts
150
152
  var import_vue = require("vue");
153
+ var SCHEMES = ["light", "dark", "system"];
154
+ var STORAGE_KEY = "saasicat.theme.scheme";
155
+ function isScheme(value) {
156
+ return typeof value === "string" && SCHEMES.includes(value);
157
+ }
158
+ function systemScheme() {
159
+ const value = (0, import_vue.ref)("light");
160
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
161
+ return { value, unsubscribe: () => {
162
+ } };
163
+ }
164
+ const query = window.matchMedia("(prefers-color-scheme: dark)");
165
+ value.value = query.matches ? "dark" : "light";
166
+ const onChange = (event) => {
167
+ value.value = event.matches ? "dark" : "light";
168
+ };
169
+ query.addEventListener("change", onChange);
170
+ return { value, unsubscribe: () => query.removeEventListener("change", onChange) };
171
+ }
172
+ function createSaTheme(options = {}) {
173
+ const storage = options.storage ?? defaultKvStore();
174
+ const persist = options.persist !== false;
175
+ const provided = options.scheme;
176
+ const appOwnsIt = (0, import_vue.isRef)(provided);
177
+ const stored = persist && !appOwnsIt ? storage.get(STORAGE_KEY) : null;
178
+ const scheme = (0, import_vue.isRef)(provided) ? provided : (0, import_vue.ref)(isScheme(stored) ? stored : provided ?? "system");
179
+ const { value: system, unsubscribe } = systemScheme();
180
+ const stopPersisting = persist && !appOwnsIt ? (0, import_vue.watch)(scheme, (next) => storage.set(STORAGE_KEY, next)) : null;
181
+ return {
182
+ scheme,
183
+ resolved: (0, import_vue.computed)(() => scheme.value === "system" ? system.value : scheme.value),
184
+ dispose: () => {
185
+ unsubscribe();
186
+ stopPersisting?.();
187
+ }
188
+ };
189
+ }
190
+ var SA_THEME_KEY = /* @__PURE__ */ Symbol.for("@saasicat/ui-vue/SA_THEME");
191
+
192
+ // src/vue/use-super-admin-i18n.ts
193
+ var import_vue2 = require("vue");
151
194
 
152
195
  // src/client/i18n/locale.ts
153
196
  var SA_LOCALES = ["de", "en"];
@@ -186,7 +229,7 @@ function mergeMessages(base, overrides) {
186
229
  }
187
230
 
188
231
  // src/client/i18n/format.ts
189
- var import_types = require("@saasicat/types");
232
+ var import_types2 = require("@saasicat/types");
190
233
 
191
234
  // src/client/i18n/messages/audit.ts
192
235
  var auditMessages = defineMessages(
@@ -3250,13 +3293,13 @@ var SUPER_ADMIN_I18N_KEY = /* @__PURE__ */ Symbol.for(
3250
3293
  );
3251
3294
  function createSuperAdminI18n(options = {}) {
3252
3295
  const catalog = createSaCatalog(options);
3253
- const locale = (0, import_vue.isRef)(options.locale) ? options.locale : createOwnedLocale(options, catalog);
3254
- const active = (0, import_vue.computed)(
3296
+ const locale = (0, import_vue2.isRef)(options.locale) ? options.locale : createOwnedLocale(options, catalog);
3297
+ const active = (0, import_vue2.computed)(
3255
3298
  () => catalog.has(locale.value) ? locale.value : catalog.defaultLocale
3256
3299
  );
3257
- const messages = (0, import_vue.computed)(() => catalog.messagesFor(active.value));
3258
- const intlLocale = (0, import_vue.computed)(() => catalog.intlLocaleFor(active.value));
3259
- const writable = !(0, import_vue.isReadonly)(locale);
3300
+ const messages = (0, import_vue2.computed)(() => catalog.messagesFor(active.value));
3301
+ const intlLocale = (0, import_vue2.computed)(() => catalog.intlLocaleFor(active.value));
3302
+ const writable = !(0, import_vue2.isReadonly)(locale);
3260
3303
  return {
3261
3304
  locale,
3262
3305
  messages,
@@ -3267,20 +3310,47 @@ function createSuperAdminI18n(options = {}) {
3267
3310
  }
3268
3311
  function createOwnedLocale(options, catalog) {
3269
3312
  const initial = options.locale ?? catalog.defaultLocale;
3270
- if (options.persist === false) return (0, import_vue.ref)(initial);
3313
+ if (options.persist === false) return (0, import_vue2.ref)(initial);
3271
3314
  const storage = options.storage ?? defaultKvStore();
3272
3315
  const key = `${options.storageKeyPrefix ?? ""}${SA_LOCALE_STORAGE_KEY}`;
3273
3316
  const stored = storage.get(key);
3274
- const locale = (0, import_vue.ref)(stored && catalog.has(stored) ? stored : initial);
3275
- (0, import_vue.watch)(locale, (next) => storage.set(key, next));
3317
+ const locale = (0, import_vue2.ref)(stored && catalog.has(stored) ? stored : initial);
3318
+ (0, import_vue2.watch)(locale, (next) => storage.set(key, next));
3276
3319
  return locale;
3277
3320
  }
3278
3321
 
3279
- // src/quasar/notify.ts
3280
- var import_vue2 = require("vue");
3322
+ // src/quasar/dark-bridge.ts
3281
3323
  var import_quasar = require("quasar");
3324
+ var import_vue3 = require("vue");
3325
+ function bindSaThemeToDocument(theme) {
3326
+ const toQuasar = (0, import_vue3.watch)(
3327
+ theme.resolved,
3328
+ (resolved) => {
3329
+ if (typeof document !== "undefined") {
3330
+ document.documentElement.setAttribute("data-sa-theme", resolved);
3331
+ }
3332
+ import_quasar.Dark.set(resolved === "dark");
3333
+ },
3334
+ { immediate: true }
3335
+ );
3336
+ const fromQuasar = (0, import_vue3.watch)(
3337
+ () => import_quasar.Dark.isActive,
3338
+ (isDark) => {
3339
+ const asScheme = isDark ? "dark" : "light";
3340
+ if (theme.resolved.value !== asScheme) theme.scheme.value = asScheme;
3341
+ }
3342
+ );
3343
+ return () => {
3344
+ toQuasar();
3345
+ fromQuasar();
3346
+ };
3347
+ }
3348
+
3349
+ // src/quasar/notify.ts
3350
+ var import_vue4 = require("vue");
3351
+ var import_quasar2 = require("quasar");
3282
3352
  var quasarNotify = (kind, message, options) => {
3283
- import_quasar.Notify.create({
3353
+ import_quasar2.Notify.create({
3284
3354
  type: kind,
3285
3355
  message,
3286
3356
  position: "top",
@@ -3289,17 +3359,29 @@ var quasarNotify = (kind, message, options) => {
3289
3359
  });
3290
3360
  };
3291
3361
  function useSuperAdminNotify() {
3292
- return (0, import_vue2.inject)(SUPER_ADMIN_NOTIFY_KEY, quasarNotify);
3362
+ return (0, import_vue4.inject)(SUPER_ADMIN_NOTIFY_KEY, quasarNotify);
3293
3363
  }
3294
3364
 
3295
3365
  // src/quasar/create-super-admin-app.ts
3366
+ var SA_PORTAL_CLASS = "sa-portal";
3296
3367
  var DEFAULT_QUASAR_OPTIONS = {
3297
- plugins: { Notify: import_quasar2.Notify, Dialog: import_quasar2.Dialog, Loading: import_quasar2.Loading },
3368
+ plugins: { Notify: import_quasar3.Notify, Dialog: import_quasar3.Dialog, Loading: import_quasar3.Loading },
3298
3369
  config: { notify: { position: "top-right", timeout: 3e3 } }
3299
3370
  };
3300
3371
  function createSuperAdminApp(options) {
3301
- const app = (0, import_vue3.createApp)(options.rootComponent);
3302
- app.use(import_quasar2.Quasar, options.quasarOptions ?? DEFAULT_QUASAR_OPTIONS);
3372
+ const app = (0, import_vue5.createApp)(options.rootComponent);
3373
+ const quasarOptions = options.quasarOptions ?? DEFAULT_QUASAR_OPTIONS;
3374
+ const config = quasarOptions.config;
3375
+ const existingPortalClass = config?.globalNodes?.class;
3376
+ app.use(import_quasar3.Quasar, {
3377
+ ...quasarOptions,
3378
+ config: {
3379
+ ...quasarOptions.config,
3380
+ globalNodes: {
3381
+ class: [existingPortalClass, SA_PORTAL_CLASS].filter(Boolean).join(" ")
3382
+ }
3383
+ }
3384
+ });
3303
3385
  const pinia = (0, import_pinia.createPinia)();
3304
3386
  app.use(pinia);
3305
3387
  const router = (0, import_vue_router.createRouter)({
@@ -3317,8 +3399,15 @@ function createSuperAdminApp(options) {
3317
3399
  manifestEndpoint: options.endpoints.manifestEndpoint ?? `${options.endpoints.apiBase}/manifest`
3318
3400
  };
3319
3401
  const i18n = createSuperAdminI18n(options.i18n);
3402
+ const configuredDark = options.quasarOptions?.config?.dark;
3403
+ const theme = createSaTheme({
3404
+ ...options.theme,
3405
+ scheme: options.theme?.scheme ?? (typeof configuredDark === "boolean" ? configuredDark ? "dark" : "light" : void 0)
3406
+ });
3407
+ const stopThemeBridge = bindSaThemeToDocument(theme);
3320
3408
  app.provide(SUPER_ADMIN_BRAND_KEY, { tag: "SuperAdmin", ...options.brand });
3321
3409
  app.provide(SUPER_ADMIN_I18N_KEY, i18n);
3410
+ app.provide(SA_THEME_KEY, theme);
3322
3411
  app.provide(SUPER_ADMIN_ENDPOINTS_KEY, endpoints);
3323
3412
  app.provide(SUPER_ADMIN_EXTENSIONS_KEY, options.extensions ?? {});
3324
3413
  app.provide(SUPER_ADMIN_ACTIONS_KEY, options.actions ?? {});
@@ -3341,11 +3430,18 @@ function createSuperAdminApp(options) {
3341
3430
  router,
3342
3431
  pinia,
3343
3432
  i18n,
3344
- mount: (selector) => app.mount(selector)
3433
+ theme,
3434
+ mount: (selector) => app.mount(selector),
3435
+ dispose: () => {
3436
+ stopThemeBridge();
3437
+ theme.dispose();
3438
+ }
3345
3439
  };
3346
3440
  }
3347
3441
  // Annotate the CommonJS export names for ESM import in node:
3348
3442
  0 && (module.exports = {
3443
+ SA_PORTAL_CLASS,
3444
+ bindSaThemeToDocument,
3349
3445
  createSuperAdminApp,
3350
3446
  quasarNotify,
3351
3447
  useSuperAdminNotify
@@ -1,9 +1,9 @@
1
- import { Component, App } from 'vue';
1
+ import { Component, App, WatchStopHandle } from 'vue';
2
2
  import { QuasarPluginOptions } from 'quasar';
3
3
  import { Pinia } from 'pinia';
4
4
  import { RouteRecordRaw, RouterHistory, Router } from 'vue-router';
5
5
  import { H as HttpClient } from '../catalog-DJcfm5N2.cjs';
6
- import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-CgTuNi8h.cjs';
6
+ import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SaThemeOptions, f as SuperAdminI18n, g as SaTheme } from '../use-sa-theme-B5t7oXph.cjs';
7
7
  import '@saasicat/types';
8
8
 
9
9
  interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
@@ -66,6 +66,17 @@ interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
66
66
  * runtime. Consumed via `useSuperAdminI18n()` / `useSaMessages()`.
67
67
  */
68
68
  i18n?: SuperAdminI18nOptions;
69
+ /**
70
+ * Optional: colour scheme. Default follows the operating system and
71
+ * remembers an explicit pick. The context is returned on the handle
72
+ * (`handle.theme`) — set `handle.theme.scheme.value = 'dark'` to switch at
73
+ * runtime, and read it anywhere via `useSaTheme()`.
74
+ *
75
+ * Whatever it resolves to is mirrored onto `<html data-sa-theme>` AND into
76
+ * Quasar's `Dark`, so the platform's surfaces and Quasar's own components
77
+ * never disagree.
78
+ */
79
+ theme?: SaThemeOptions;
69
80
  }
70
81
  interface SuperAdminAppHandle {
71
82
  app: App;
@@ -73,9 +84,27 @@ interface SuperAdminAppHandle {
73
84
  pinia: Pinia;
74
85
  /** i18n context of the shell — switch locale via `i18n.locale.value`. */
75
86
  i18n: SuperAdminI18n;
87
+ /** Colour scheme of the shell — switch via `theme.scheme.value`. */
88
+ theme: SaTheme;
76
89
  /** Mounts the app on a selector. Returns the root component instance. */
77
90
  mount: (selector: string | Element) => ReturnType<App['mount']>;
91
+ /**
92
+ * Releases what this helper attached to the DOCUMENT — the theme's
93
+ * `prefers-color-scheme` subscription and the bridge that mirrors it onto
94
+ * `data-sa-theme` and Quasar's `Dark`. Idempotent; it does not unmount the
95
+ * app, which is `handle.app.unmount()`.
96
+ *
97
+ * Only matters where a shell is torn down while the document survives: hot
98
+ * reload, a micro-frontend, a second shell in one page. Skip it and the old
99
+ * bridge keeps writing to the one document on the next OS theme change, and
100
+ * can overrule the scheme the new shell was given.
101
+ */
102
+ dispose: () => void;
78
103
  }
104
+ /** Marks Quasar's teleported nodes so the theme can reach them. Exported so a
105
+ * test fixture can install the same config a real app gets — without it the
106
+ * `.sa-portal` rules are exercised by nothing. */
107
+ declare const SA_PORTAL_CLASS = "sa-portal";
79
108
  /**
80
109
  * Universal bootstrap function for SuperAdmin apps. Replaces the `main.ts`
81
110
  * boilerplate duplicated per app today (Quasar + Pinia + Router + manifest
@@ -84,6 +113,22 @@ interface SuperAdminAppHandle {
84
113
  */
85
114
  declare function createSuperAdminApp(options: CreateSuperAdminAppOptions): SuperAdminAppHandle;
86
115
 
116
+ /**
117
+ * Mirrors a theme context onto the document and Quasar. Returns the stop
118
+ * handle; `createSuperAdminApp()` wires this up for you.
119
+ *
120
+ * `immediate` is not optional: at bootstrap the stored pick is already resolved
121
+ * and nothing has painted yet, so a first-change-only watcher would render one
122
+ * frame in the wrong theme on every reload.
123
+ *
124
+ * That first tick MIRRORS, it does not negotiate — whatever `theme.resolved`
125
+ * says is written to Quasar, including `Dark.set(false)`. So a caller that
126
+ * bootstraps with Quasar already dark has to say so when it builds the theme,
127
+ * or its own choice is erased one line after it was applied.
128
+ * `createSuperAdminApp` does exactly that, seeding from `Dark.isActive`.
129
+ */
130
+ declare function bindSaThemeToDocument(theme: SaTheme): WatchStopHandle;
131
+
87
132
  /**
88
133
  * Quasar-backed notify port: `position: 'top'` matches the convention the
89
134
  * standard pages used with their previous direct `$q.notify` calls.
@@ -92,4 +137,4 @@ declare const quasarNotify: UiNotify;
92
137
  /** Returns the app-provided notify port, falling back to the Quasar default. */
93
138
  declare function useSuperAdminNotify(): UiNotify;
94
139
 
95
- export { type CreateSuperAdminAppOptions, type SuperAdminAppHandle, createSuperAdminApp, quasarNotify, useSuperAdminNotify };
140
+ export { type CreateSuperAdminAppOptions, SA_PORTAL_CLASS, type SuperAdminAppHandle, bindSaThemeToDocument, createSuperAdminApp, quasarNotify, useSuperAdminNotify };
@@ -1,9 +1,9 @@
1
- import { Component, App } from 'vue';
1
+ import { Component, App, WatchStopHandle } from 'vue';
2
2
  import { QuasarPluginOptions } from 'quasar';
3
3
  import { Pinia } from 'pinia';
4
4
  import { RouteRecordRaw, RouterHistory, Router } from 'vue-router';
5
5
  import { H as HttpClient } from '../catalog-DJcfm5N2.js';
6
- import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-CHNdsSlm.js';
6
+ import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SaThemeOptions, f as SuperAdminI18n, g as SaTheme } from '../use-sa-theme-OUBlaqgl.js';
7
7
  import '@saasicat/types';
8
8
 
9
9
  interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
@@ -66,6 +66,17 @@ interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
66
66
  * runtime. Consumed via `useSuperAdminI18n()` / `useSaMessages()`.
67
67
  */
68
68
  i18n?: SuperAdminI18nOptions;
69
+ /**
70
+ * Optional: colour scheme. Default follows the operating system and
71
+ * remembers an explicit pick. The context is returned on the handle
72
+ * (`handle.theme`) — set `handle.theme.scheme.value = 'dark'` to switch at
73
+ * runtime, and read it anywhere via `useSaTheme()`.
74
+ *
75
+ * Whatever it resolves to is mirrored onto `<html data-sa-theme>` AND into
76
+ * Quasar's `Dark`, so the platform's surfaces and Quasar's own components
77
+ * never disagree.
78
+ */
79
+ theme?: SaThemeOptions;
69
80
  }
70
81
  interface SuperAdminAppHandle {
71
82
  app: App;
@@ -73,9 +84,27 @@ interface SuperAdminAppHandle {
73
84
  pinia: Pinia;
74
85
  /** i18n context of the shell — switch locale via `i18n.locale.value`. */
75
86
  i18n: SuperAdminI18n;
87
+ /** Colour scheme of the shell — switch via `theme.scheme.value`. */
88
+ theme: SaTheme;
76
89
  /** Mounts the app on a selector. Returns the root component instance. */
77
90
  mount: (selector: string | Element) => ReturnType<App['mount']>;
91
+ /**
92
+ * Releases what this helper attached to the DOCUMENT — the theme's
93
+ * `prefers-color-scheme` subscription and the bridge that mirrors it onto
94
+ * `data-sa-theme` and Quasar's `Dark`. Idempotent; it does not unmount the
95
+ * app, which is `handle.app.unmount()`.
96
+ *
97
+ * Only matters where a shell is torn down while the document survives: hot
98
+ * reload, a micro-frontend, a second shell in one page. Skip it and the old
99
+ * bridge keeps writing to the one document on the next OS theme change, and
100
+ * can overrule the scheme the new shell was given.
101
+ */
102
+ dispose: () => void;
78
103
  }
104
+ /** Marks Quasar's teleported nodes so the theme can reach them. Exported so a
105
+ * test fixture can install the same config a real app gets — without it the
106
+ * `.sa-portal` rules are exercised by nothing. */
107
+ declare const SA_PORTAL_CLASS = "sa-portal";
79
108
  /**
80
109
  * Universal bootstrap function for SuperAdmin apps. Replaces the `main.ts`
81
110
  * boilerplate duplicated per app today (Quasar + Pinia + Router + manifest
@@ -84,6 +113,22 @@ interface SuperAdminAppHandle {
84
113
  */
85
114
  declare function createSuperAdminApp(options: CreateSuperAdminAppOptions): SuperAdminAppHandle;
86
115
 
116
+ /**
117
+ * Mirrors a theme context onto the document and Quasar. Returns the stop
118
+ * handle; `createSuperAdminApp()` wires this up for you.
119
+ *
120
+ * `immediate` is not optional: at bootstrap the stored pick is already resolved
121
+ * and nothing has painted yet, so a first-change-only watcher would render one
122
+ * frame in the wrong theme on every reload.
123
+ *
124
+ * That first tick MIRRORS, it does not negotiate — whatever `theme.resolved`
125
+ * says is written to Quasar, including `Dark.set(false)`. So a caller that
126
+ * bootstraps with Quasar already dark has to say so when it builds the theme,
127
+ * or its own choice is erased one line after it was applied.
128
+ * `createSuperAdminApp` does exactly that, seeding from `Dark.isActive`.
129
+ */
130
+ declare function bindSaThemeToDocument(theme: SaTheme): WatchStopHandle;
131
+
87
132
  /**
88
133
  * Quasar-backed notify port: `position: 'top'` matches the convention the
89
134
  * standard pages used with their previous direct `$q.notify` calls.
@@ -92,4 +137,4 @@ declare const quasarNotify: UiNotify;
92
137
  /** Returns the app-provided notify port, falling back to the Quasar default. */
93
138
  declare function useSuperAdminNotify(): UiNotify;
94
139
 
95
- export { type CreateSuperAdminAppOptions, type SuperAdminAppHandle, createSuperAdminApp, quasarNotify, useSuperAdminNotify };
140
+ export { type CreateSuperAdminAppOptions, SA_PORTAL_CLASS, type SuperAdminAppHandle, bindSaThemeToDocument, createSuperAdminApp, quasarNotify, useSuperAdminNotify };
@@ -1,4 +1,5 @@
1
1
  import {
2
+ SA_THEME_KEY,
2
3
  SUPER_ADMIN_ACTIONS_KEY,
3
4
  SUPER_ADMIN_BRAND_KEY,
4
5
  SUPER_ADMIN_ENDPOINTS_KEY,
@@ -10,8 +11,9 @@ import {
10
11
  SUPER_ADMIN_MANIFEST_KEY,
11
12
  SUPER_ADMIN_NOTIFY_KEY,
12
13
  buildNavigationGuard,
14
+ createSaTheme,
13
15
  createSuperAdminI18n
14
- } from "../chunk-LY52T4N4.js";
16
+ } from "../chunk-TQQMKWN6.js";
15
17
  import {
16
18
  defaultHttpClient
17
19
  } from "../chunk-F7NRM6KI.js";
@@ -25,6 +27,33 @@ import {
25
27
  createWebHistory
26
28
  } from "vue-router";
27
29
 
30
+ // src/quasar/dark-bridge.ts
31
+ import { Dark } from "quasar";
32
+ import { watch } from "vue";
33
+ function bindSaThemeToDocument(theme) {
34
+ const toQuasar = watch(
35
+ theme.resolved,
36
+ (resolved) => {
37
+ if (typeof document !== "undefined") {
38
+ document.documentElement.setAttribute("data-sa-theme", resolved);
39
+ }
40
+ Dark.set(resolved === "dark");
41
+ },
42
+ { immediate: true }
43
+ );
44
+ const fromQuasar = watch(
45
+ () => Dark.isActive,
46
+ (isDark) => {
47
+ const asScheme = isDark ? "dark" : "light";
48
+ if (theme.resolved.value !== asScheme) theme.scheme.value = asScheme;
49
+ }
50
+ );
51
+ return () => {
52
+ toQuasar();
53
+ fromQuasar();
54
+ };
55
+ }
56
+
28
57
  // src/quasar/notify.ts
29
58
  import { inject } from "vue";
30
59
  import { Notify } from "quasar";
@@ -42,13 +71,25 @@ function useSuperAdminNotify() {
42
71
  }
43
72
 
44
73
  // src/quasar/create-super-admin-app.ts
74
+ var SA_PORTAL_CLASS = "sa-portal";
45
75
  var DEFAULT_QUASAR_OPTIONS = {
46
76
  plugins: { Notify: Notify2, Dialog, Loading },
47
77
  config: { notify: { position: "top-right", timeout: 3e3 } }
48
78
  };
49
79
  function createSuperAdminApp(options) {
50
80
  const app = createApp(options.rootComponent);
51
- app.use(Quasar, options.quasarOptions ?? DEFAULT_QUASAR_OPTIONS);
81
+ const quasarOptions = options.quasarOptions ?? DEFAULT_QUASAR_OPTIONS;
82
+ const config = quasarOptions.config;
83
+ const existingPortalClass = config?.globalNodes?.class;
84
+ app.use(Quasar, {
85
+ ...quasarOptions,
86
+ config: {
87
+ ...quasarOptions.config,
88
+ globalNodes: {
89
+ class: [existingPortalClass, SA_PORTAL_CLASS].filter(Boolean).join(" ")
90
+ }
91
+ }
92
+ });
52
93
  const pinia = createPinia();
53
94
  app.use(pinia);
54
95
  const router = createRouter({
@@ -66,8 +107,15 @@ function createSuperAdminApp(options) {
66
107
  manifestEndpoint: options.endpoints.manifestEndpoint ?? `${options.endpoints.apiBase}/manifest`
67
108
  };
68
109
  const i18n = createSuperAdminI18n(options.i18n);
110
+ const configuredDark = options.quasarOptions?.config?.dark;
111
+ const theme = createSaTheme({
112
+ ...options.theme,
113
+ scheme: options.theme?.scheme ?? (typeof configuredDark === "boolean" ? configuredDark ? "dark" : "light" : void 0)
114
+ });
115
+ const stopThemeBridge = bindSaThemeToDocument(theme);
69
116
  app.provide(SUPER_ADMIN_BRAND_KEY, { tag: "SuperAdmin", ...options.brand });
70
117
  app.provide(SUPER_ADMIN_I18N_KEY, i18n);
118
+ app.provide(SA_THEME_KEY, theme);
71
119
  app.provide(SUPER_ADMIN_ENDPOINTS_KEY, endpoints);
72
120
  app.provide(SUPER_ADMIN_EXTENSIONS_KEY, options.extensions ?? {});
73
121
  app.provide(SUPER_ADMIN_ACTIONS_KEY, options.actions ?? {});
@@ -90,10 +138,17 @@ function createSuperAdminApp(options) {
90
138
  router,
91
139
  pinia,
92
140
  i18n,
93
- mount: (selector) => app.mount(selector)
141
+ theme,
142
+ mount: (selector) => app.mount(selector),
143
+ dispose: () => {
144
+ stopThemeBridge();
145
+ theme.dispose();
146
+ }
94
147
  };
95
148
  }
96
149
  export {
150
+ SA_PORTAL_CLASS,
151
+ bindSaThemeToDocument,
97
152
  createSuperAdminApp,
98
153
  quasarNotify,
99
154
  useSuperAdminNotify
@@ -280,4 +280,54 @@ declare function useSuperAdminI18n(): SuperAdminI18n;
280
280
  */
281
281
  declare function useSaMessages<K extends keyof SaMessages>(namespace: K): ComputedRef<SaMessages[K]>;
282
282
 
283
- export { type ActionsMap as A, type ExtensionsMap as E, type InstallPlugin as I, type SuperAdminGuardOptions as S, type UiNotify as U, type SuperAdminBrand as a, type SuperAdminEndpoints as b, type SuperAdminLoginAdapter as c, type SuperAdminI18nOptions as d, type SuperAdminI18n as e, type ExtensionLoader as f, SA_LOCALE_STORAGE_KEY as g, SUPER_ADMIN_ACTIONS_KEY as h, SUPER_ADMIN_BRAND_KEY as i, SUPER_ADMIN_ENDPOINTS_KEY as j, SUPER_ADMIN_EXTENSIONS_KEY as k, SUPER_ADMIN_HTTP_KEY as l, SUPER_ADMIN_I18N_KEY as m, SUPER_ADMIN_LOGIN_ADAPTER_KEY as n, SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY as o, SUPER_ADMIN_MANIFEST_KEY as p, SUPER_ADMIN_NOTIFY_KEY as q, type SuperAdminAuthGuardOptions as r, type SuperAdminLoginResult as s, type SuperAdminManifestGuardOptions as t, type UiNotifyKind as u, type UiNotifyOptions as v, buildNavigationGuard as w, createSuperAdminI18n as x, useSaMessages as y, useSuperAdminI18n as z };
283
+ type SaColorScheme = 'light' | 'dark' | 'system';
284
+ type SaResolvedScheme = 'light' | 'dark';
285
+ interface SaTheme {
286
+ /** What the operator picked. Writable — assigning switches the theme. */
287
+ scheme: Ref<SaColorScheme>;
288
+ /** What that means right now: `'system'` resolved against the OS. */
289
+ resolved: ComputedRef<SaResolvedScheme>;
290
+ /**
291
+ * Releases the `prefers-color-scheme` subscription and the persistence
292
+ * watcher. Idempotent.
293
+ *
294
+ * Needed because this context outlives no component — nothing unmounts it.
295
+ * A second shell in the same document (hot reload, a micro-frontend, a
296
+ * second test file) would otherwise leave the first one subscribed, and the
297
+ * next change of the operating system's theme would drive TWO bridges, both
298
+ * writing `data-sa-theme` and Quasar's `Dark` onto the one document. The
299
+ * stale one can win, and then the new shell's explicit scheme is overruled
300
+ * by a context nobody holds a reference to any more.
301
+ */
302
+ dispose: () => void;
303
+ }
304
+ interface SaThemeOptions {
305
+ /** Starting scheme. Pass a `Ref` to keep the value in your own store. */
306
+ scheme?: SaColorScheme | Ref<SaColorScheme>;
307
+ /**
308
+ * Remember the operator's pick across reloads, default `true`. Ignored when
309
+ * `scheme` is a `Ref`: the app owns that value and persists it where it
310
+ * belongs. Same rule as the locale in `createSuperAdminI18n`.
311
+ */
312
+ persist?: boolean;
313
+ /** Injection seam for tests. */
314
+ storage?: KvStore;
315
+ }
316
+ /**
317
+ * Creates the theme context. `createSuperAdminApp()` makes one and the Quasar
318
+ * bridge mirrors it onto the document; call it directly only when bootstrapping
319
+ * by hand.
320
+ */
321
+ declare function createSaTheme(options?: SaThemeOptions): SaTheme;
322
+ declare const SA_THEME_KEY: InjectionKey<SaTheme>;
323
+ /**
324
+ * The shell's theme context, or a shared unpersisted one outside a shell.
325
+ *
326
+ * Same shape as `useSuperAdminI18n()`, and for the same reason: a component
327
+ * mounted in isolation must render rather than throw, and the fallback must not
328
+ * write to real storage or two tests in one process would decide each other's
329
+ * outcome.
330
+ */
331
+ declare function useSaTheme(): SaTheme;
332
+
333
+ export { type ActionsMap as A, type UiNotifyOptions as B, buildNavigationGuard as C, createSaTheme as D, type ExtensionsMap as E, createSuperAdminI18n as F, useSaMessages as G, useSaTheme as H, type InstallPlugin as I, useSuperAdminI18n as J, type SuperAdminGuardOptions as S, type UiNotify as U, type SuperAdminBrand as a, type SuperAdminEndpoints as b, type SuperAdminLoginAdapter as c, type SuperAdminI18nOptions as d, type SaThemeOptions as e, type SuperAdminI18n as f, type SaTheme as g, type ExtensionLoader as h, SA_LOCALE_STORAGE_KEY as i, SA_THEME_KEY as j, SUPER_ADMIN_ACTIONS_KEY as k, SUPER_ADMIN_BRAND_KEY as l, SUPER_ADMIN_ENDPOINTS_KEY as m, SUPER_ADMIN_EXTENSIONS_KEY as n, SUPER_ADMIN_HTTP_KEY as o, SUPER_ADMIN_I18N_KEY as p, SUPER_ADMIN_LOGIN_ADAPTER_KEY as q, SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY as r, SUPER_ADMIN_MANIFEST_KEY as s, SUPER_ADMIN_NOTIFY_KEY as t, type SaColorScheme as u, type SaResolvedScheme as v, type SuperAdminAuthGuardOptions as w, type SuperAdminLoginResult as x, type SuperAdminManifestGuardOptions as y, type UiNotifyKind as z };