@almadar/ui 4.50.16 → 4.50.17

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.
@@ -58405,6 +58405,74 @@ function ServerBridgeProvider({
58405
58405
  return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeContext.Provider, { value: { connected, sendEvent }, children });
58406
58406
  }
58407
58407
 
58408
+ // context/OrbitalThemeProvider.tsx
58409
+ init_ThemeContext();
58410
+
58411
+ // context/themeTokens.ts
58412
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
58413
+ const vars = {};
58414
+ const isDark = mode === "dark";
58415
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
58416
+ if (pickColors) {
58417
+ for (const [key, value] of Object.entries(pickColors)) {
58418
+ vars[`--color-${key}`] = value;
58419
+ }
58420
+ if (isDark && darkVariant?.colors && tokens.colors) {
58421
+ for (const [key, value] of Object.entries(tokens.colors)) {
58422
+ const varName = `--color-${key}`;
58423
+ if (!(varName in vars)) vars[varName] = value;
58424
+ }
58425
+ }
58426
+ }
58427
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
58428
+ if (pickRadii) {
58429
+ for (const [key, value] of Object.entries(pickRadii)) {
58430
+ vars[`--radius-${key}`] = value;
58431
+ }
58432
+ }
58433
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
58434
+ if (pickSpacing) {
58435
+ for (const [key, value] of Object.entries(pickSpacing)) {
58436
+ vars[`--space-${key}`] = value;
58437
+ }
58438
+ }
58439
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
58440
+ if (pickTypography) {
58441
+ for (const [key, value] of Object.entries(pickTypography)) {
58442
+ vars[`--${key}`] = value;
58443
+ }
58444
+ }
58445
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
58446
+ if (pickShadows) {
58447
+ for (const [key, value] of Object.entries(pickShadows)) {
58448
+ vars[`--shadow-${key}`] = value;
58449
+ }
58450
+ }
58451
+ return vars;
58452
+ }
58453
+ function resolveThemeForRuntime(theme) {
58454
+ if (theme === void 0) return void 0;
58455
+ if (typeof theme === "string") return void 0;
58456
+ return theme;
58457
+ }
58458
+ function OrbitalThemeProvider({ theme, children }) {
58459
+ const resolved = resolveThemeForRuntime(theme);
58460
+ const { resolvedMode } = useTheme();
58461
+ if (!resolved) {
58462
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
58463
+ }
58464
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
58465
+ return /* @__PURE__ */ jsxRuntime.jsx(
58466
+ "div",
58467
+ {
58468
+ "data-orbital-theme": resolved.name,
58469
+ style: { display: "contents", ...vars },
58470
+ children
58471
+ }
58472
+ );
58473
+ }
58474
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
58475
+
58408
58476
  // runtime/OrbPreview.tsx
58409
58477
  init_navigation();
58410
58478
  init_verificationRegistry();
@@ -58816,6 +58884,19 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
58816
58884
  });
58817
58885
  return set;
58818
58886
  }, [schema, pageName]);
58887
+ const activeOrbitalTheme = React93.useMemo(() => {
58888
+ const parsed = schema;
58889
+ if (!parsed?.orbitals?.length) return void 0;
58890
+ if (pageName) {
58891
+ for (const orb of parsed.orbitals) {
58892
+ for (const pageRef of orb.pages ?? []) {
58893
+ const name = typeof pageRef === "object" && pageRef !== null ? pageRef.name : void 0;
58894
+ if (name === pageName) return orb.theme;
58895
+ }
58896
+ }
58897
+ }
58898
+ return parsed.orbitals[0]?.theme;
58899
+ }, [schema, pageName]);
58819
58900
  const inner = /* @__PURE__ */ jsxRuntime.jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
58820
58901
  EntitySchemaProvider,
58821
58902
  {
@@ -58836,7 +58917,7 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
58836
58917
  persistence
58837
58918
  }
58838
58919
  ),
58839
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
58920
+ /* @__PURE__ */ jsxRuntime.jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
58840
58921
  ]
58841
58922
  }
58842
58923
  ) });
package/dist/avl/index.js CHANGED
@@ -58359,6 +58359,74 @@ function ServerBridgeProvider({
58359
58359
  return /* @__PURE__ */ jsx(ServerBridgeContext.Provider, { value: { connected, sendEvent }, children });
58360
58360
  }
58361
58361
 
58362
+ // context/OrbitalThemeProvider.tsx
58363
+ init_ThemeContext();
58364
+
58365
+ // context/themeTokens.ts
58366
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
58367
+ const vars = {};
58368
+ const isDark = mode === "dark";
58369
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
58370
+ if (pickColors) {
58371
+ for (const [key, value] of Object.entries(pickColors)) {
58372
+ vars[`--color-${key}`] = value;
58373
+ }
58374
+ if (isDark && darkVariant?.colors && tokens.colors) {
58375
+ for (const [key, value] of Object.entries(tokens.colors)) {
58376
+ const varName = `--color-${key}`;
58377
+ if (!(varName in vars)) vars[varName] = value;
58378
+ }
58379
+ }
58380
+ }
58381
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
58382
+ if (pickRadii) {
58383
+ for (const [key, value] of Object.entries(pickRadii)) {
58384
+ vars[`--radius-${key}`] = value;
58385
+ }
58386
+ }
58387
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
58388
+ if (pickSpacing) {
58389
+ for (const [key, value] of Object.entries(pickSpacing)) {
58390
+ vars[`--space-${key}`] = value;
58391
+ }
58392
+ }
58393
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
58394
+ if (pickTypography) {
58395
+ for (const [key, value] of Object.entries(pickTypography)) {
58396
+ vars[`--${key}`] = value;
58397
+ }
58398
+ }
58399
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
58400
+ if (pickShadows) {
58401
+ for (const [key, value] of Object.entries(pickShadows)) {
58402
+ vars[`--shadow-${key}`] = value;
58403
+ }
58404
+ }
58405
+ return vars;
58406
+ }
58407
+ function resolveThemeForRuntime(theme) {
58408
+ if (theme === void 0) return void 0;
58409
+ if (typeof theme === "string") return void 0;
58410
+ return theme;
58411
+ }
58412
+ function OrbitalThemeProvider({ theme, children }) {
58413
+ const resolved = resolveThemeForRuntime(theme);
58414
+ const { resolvedMode } = useTheme();
58415
+ if (!resolved) {
58416
+ return /* @__PURE__ */ jsx(Fragment, { children });
58417
+ }
58418
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
58419
+ return /* @__PURE__ */ jsx(
58420
+ "div",
58421
+ {
58422
+ "data-orbital-theme": resolved.name,
58423
+ style: { display: "contents", ...vars },
58424
+ children
58425
+ }
58426
+ );
58427
+ }
58428
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
58429
+
58362
58430
  // runtime/OrbPreview.tsx
58363
58431
  init_navigation();
58364
58432
  init_verificationRegistry();
@@ -58770,6 +58838,19 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
58770
58838
  });
58771
58839
  return set;
58772
58840
  }, [schema, pageName]);
58841
+ const activeOrbitalTheme = useMemo(() => {
58842
+ const parsed = schema;
58843
+ if (!parsed?.orbitals?.length) return void 0;
58844
+ if (pageName) {
58845
+ for (const orb of parsed.orbitals) {
58846
+ for (const pageRef of orb.pages ?? []) {
58847
+ const name = typeof pageRef === "object" && pageRef !== null ? pageRef.name : void 0;
58848
+ if (name === pageName) return orb.theme;
58849
+ }
58850
+ }
58851
+ }
58852
+ return parsed.orbitals[0]?.theme;
58853
+ }, [schema, pageName]);
58773
58854
  const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxs(
58774
58855
  EntitySchemaProvider,
58775
58856
  {
@@ -58790,7 +58871,7 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
58790
58871
  persistence
58791
58872
  }
58792
58873
  ),
58793
- /* @__PURE__ */ jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
58874
+ /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
58794
58875
  ]
58795
58876
  }
58796
58877
  ) });
@@ -0,0 +1,37 @@
1
+ /**
2
+ * OrbitalThemeProvider — runtime application of `OrbitalDefinition.theme`.
3
+ *
4
+ * Wraps an orbital's rendered subtree in a wrapping `<div>` that sets the
5
+ * CSS variables derived from `theme.tokens` (and `variants.dark` when the
6
+ * resolved color mode is dark). Inline custom-property declarations on the
7
+ * wrapper override any `[data-theme]` selector rule for the same variable
8
+ * within the subtree, while letting unset variables cascade from the parent.
9
+ *
10
+ * Mapping is delegated to `themeTokensToCssVars`, which mirrors the Rust
11
+ * compiler's `generate_tokens_css`. Compile-time and runtime produce the
12
+ * same CSS variable map for the same `ThemeDefinition` input, so a Studio
13
+ * Design System edit and an `orbital compile` of the same schema render
14
+ * identically.
15
+ *
16
+ * No-op when:
17
+ * - `theme` is `undefined` (orbital declares no theme — parent cascades)
18
+ * - `theme` is a string ref that didn't get inlined upstream
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * <OrbitalThemeProvider theme={orbital.theme}>
23
+ * <UISlotRenderer />
24
+ * </OrbitalThemeProvider>
25
+ * ```
26
+ */
27
+ import { type ReactElement, type ReactNode } from 'react';
28
+ import type { ThemeRef } from '@almadar/core';
29
+ export interface OrbitalThemeProviderProps {
30
+ /** The `OrbitalDefinition.theme` value (inline definition or string ref). */
31
+ theme?: ThemeRef;
32
+ children: ReactNode;
33
+ }
34
+ export declare function OrbitalThemeProvider({ theme, children }: OrbitalThemeProviderProps): ReactElement;
35
+ export declare namespace OrbitalThemeProvider {
36
+ var displayName: string;
37
+ }
@@ -622,6 +622,71 @@ function useTheme() {
622
622
  }
623
623
  var ThemeContext_default = ThemeContext;
624
624
 
625
+ // context/themeTokens.ts
626
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
627
+ const vars = {};
628
+ const isDark = mode === "dark";
629
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
630
+ if (pickColors) {
631
+ for (const [key, value] of Object.entries(pickColors)) {
632
+ vars[`--color-${key}`] = value;
633
+ }
634
+ if (isDark && darkVariant?.colors && tokens.colors) {
635
+ for (const [key, value] of Object.entries(tokens.colors)) {
636
+ const varName = `--color-${key}`;
637
+ if (!(varName in vars)) vars[varName] = value;
638
+ }
639
+ }
640
+ }
641
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
642
+ if (pickRadii) {
643
+ for (const [key, value] of Object.entries(pickRadii)) {
644
+ vars[`--radius-${key}`] = value;
645
+ }
646
+ }
647
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
648
+ if (pickSpacing) {
649
+ for (const [key, value] of Object.entries(pickSpacing)) {
650
+ vars[`--space-${key}`] = value;
651
+ }
652
+ }
653
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
654
+ if (pickTypography) {
655
+ for (const [key, value] of Object.entries(pickTypography)) {
656
+ vars[`--${key}`] = value;
657
+ }
658
+ }
659
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
660
+ if (pickShadows) {
661
+ for (const [key, value] of Object.entries(pickShadows)) {
662
+ vars[`--shadow-${key}`] = value;
663
+ }
664
+ }
665
+ return vars;
666
+ }
667
+ function resolveThemeForRuntime(theme) {
668
+ if (theme === void 0) return void 0;
669
+ if (typeof theme === "string") return void 0;
670
+ return theme;
671
+ }
672
+ function OrbitalThemeProvider({ theme, children }) {
673
+ const resolved = resolveThemeForRuntime(theme);
674
+ const { resolvedMode } = useTheme();
675
+ if (!resolved) {
676
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
677
+ }
678
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
679
+ return /* @__PURE__ */ jsxRuntime.jsx(
680
+ "div",
681
+ {
682
+ "data-orbital-theme": resolved.name,
683
+ style: { display: "contents", ...vars },
684
+ children
685
+ }
686
+ );
687
+ }
688
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
689
+
625
690
  // context/DesignThemeContext.tsx
626
691
  var DesignThemeProvider = ThemeProvider;
627
692
  function useDesignTheme() {
@@ -743,12 +808,15 @@ exports.BUILT_IN_THEMES = BUILT_IN_THEMES;
743
808
  exports.CurrentPagePathContext = CurrentPagePathContext;
744
809
  exports.CurrentPagePathProvider = CurrentPagePathProvider;
745
810
  exports.DesignThemeProvider = DesignThemeProvider;
811
+ exports.OrbitalThemeProvider = OrbitalThemeProvider;
746
812
  exports.ThemeContext = ThemeContext_default;
747
813
  exports.ThemeProvider = ThemeProvider;
748
814
  exports.UISlotContext = UISlotContext;
749
815
  exports.UISlotProvider = UISlotProvider;
750
816
  exports.UserContext = UserContext;
751
817
  exports.UserProvider = UserProvider;
818
+ exports.resolveThemeForRuntime = resolveThemeForRuntime;
819
+ exports.themeTokensToCssVars = themeTokensToCssVars;
752
820
  exports.useCurrentPagePath = useCurrentPagePath;
753
821
  exports.useDesignTheme = useDesignTheme;
754
822
  exports.useHasPermission = useHasPermission;
@@ -4,6 +4,8 @@
4
4
  export { UISlotProvider, useUISlots, useSlotContent, useSlotHasContent, UISlotContext, type UISlotManager, type UISlot, type SlotContent, type RenderUIConfig, type SlotAnimation, type SlotChangeCallback, } from "./UISlotContext";
5
5
  export { ThemeProvider, useTheme, BUILT_IN_THEMES, type ThemeDefinition, type ThemeProviderProps, type ColorMode, type ResolvedMode, type DesignTheme, } from "./ThemeContext";
6
6
  export { default as ThemeContext } from "./ThemeContext";
7
+ export { themeTokensToCssVars, resolveThemeForRuntime, type ThemeMode, } from "./themeTokens";
8
+ export { OrbitalThemeProvider, type OrbitalThemeProviderProps, } from "./OrbitalThemeProvider";
7
9
  export { DesignThemeProvider, useDesignTheme } from "./DesignThemeContext";
8
10
  export { CurrentPagePathProvider, CurrentPagePathContext, useCurrentPagePath, type CurrentPagePathProviderProps, } from "./CurrentPagePathContext";
9
11
  export { UserProvider, UserContext, useUser, useHasRole, useHasPermission, useUserForEvaluation, ANONYMOUS_USER, type UserData, type UserContextValue, type UserProviderProps, } from "./UserContext";
@@ -1,6 +1,6 @@
1
1
  import { createContext, useMemo, useContext, useState, useEffect, useCallback, useRef } from 'react';
2
2
  import { createLogger } from '@almadar/logger';
3
- import { jsx } from 'react/jsx-runtime';
3
+ import { jsx, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  var log = createLogger("almadar:ui:ui-slots");
6
6
  var DEFAULT_SOURCE_KEY = "__default__";
@@ -620,6 +620,71 @@ function useTheme() {
620
620
  }
621
621
  var ThemeContext_default = ThemeContext;
622
622
 
623
+ // context/themeTokens.ts
624
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
625
+ const vars = {};
626
+ const isDark = mode === "dark";
627
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
628
+ if (pickColors) {
629
+ for (const [key, value] of Object.entries(pickColors)) {
630
+ vars[`--color-${key}`] = value;
631
+ }
632
+ if (isDark && darkVariant?.colors && tokens.colors) {
633
+ for (const [key, value] of Object.entries(tokens.colors)) {
634
+ const varName = `--color-${key}`;
635
+ if (!(varName in vars)) vars[varName] = value;
636
+ }
637
+ }
638
+ }
639
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
640
+ if (pickRadii) {
641
+ for (const [key, value] of Object.entries(pickRadii)) {
642
+ vars[`--radius-${key}`] = value;
643
+ }
644
+ }
645
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
646
+ if (pickSpacing) {
647
+ for (const [key, value] of Object.entries(pickSpacing)) {
648
+ vars[`--space-${key}`] = value;
649
+ }
650
+ }
651
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
652
+ if (pickTypography) {
653
+ for (const [key, value] of Object.entries(pickTypography)) {
654
+ vars[`--${key}`] = value;
655
+ }
656
+ }
657
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
658
+ if (pickShadows) {
659
+ for (const [key, value] of Object.entries(pickShadows)) {
660
+ vars[`--shadow-${key}`] = value;
661
+ }
662
+ }
663
+ return vars;
664
+ }
665
+ function resolveThemeForRuntime(theme) {
666
+ if (theme === void 0) return void 0;
667
+ if (typeof theme === "string") return void 0;
668
+ return theme;
669
+ }
670
+ function OrbitalThemeProvider({ theme, children }) {
671
+ const resolved = resolveThemeForRuntime(theme);
672
+ const { resolvedMode } = useTheme();
673
+ if (!resolved) {
674
+ return /* @__PURE__ */ jsx(Fragment, { children });
675
+ }
676
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
677
+ return /* @__PURE__ */ jsx(
678
+ "div",
679
+ {
680
+ "data-orbital-theme": resolved.name,
681
+ style: { display: "contents", ...vars },
682
+ children
683
+ }
684
+ );
685
+ }
686
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
687
+
623
688
  // context/DesignThemeContext.tsx
624
689
  var DesignThemeProvider = ThemeProvider;
625
690
  function useDesignTheme() {
@@ -736,4 +801,4 @@ function useUserForEvaluation() {
736
801
  return isLoggedIn && user ? user : void 0;
737
802
  }
738
803
 
739
- export { ANONYMOUS_USER, BUILT_IN_THEMES, CurrentPagePathContext, CurrentPagePathProvider, DesignThemeProvider, ThemeContext_default as ThemeContext, ThemeProvider, UISlotContext, UISlotProvider, UserContext, UserProvider, useCurrentPagePath, useDesignTheme, useHasPermission, useHasRole, useSlotContent, useSlotHasContent, useTheme, useUISlots, useUser, useUserForEvaluation };
804
+ export { ANONYMOUS_USER, BUILT_IN_THEMES, CurrentPagePathContext, CurrentPagePathProvider, DesignThemeProvider, OrbitalThemeProvider, ThemeContext_default as ThemeContext, ThemeProvider, UISlotContext, UISlotProvider, UserContext, UserProvider, resolveThemeForRuntime, themeTokensToCssVars, useCurrentPagePath, useDesignTheme, useHasPermission, useHasRole, useSlotContent, useSlotHasContent, useTheme, useUISlots, useUser, useUserForEvaluation };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * themeTokens — runtime mirror of the orbital compiler's theme codegen.
3
+ *
4
+ * The compile path (orbital-rust/crates/orbital-shell-typescript/src/codegen/theme.rs)
5
+ * reads `OrbitalDefinition.theme.tokens` and emits CSS custom-property
6
+ * declarations into a `[data-theme="<name>-<mode>"]` block. The runtime
7
+ * does not parse compiled CSS — it reads the same `tokens` object directly
8
+ * and produces the same `{ '--color-primary': '…', '--radius-md': '…' }` map
9
+ * that the compiler emits.
10
+ *
11
+ * Keeping the two paths byte-identical at the variable level is the contract:
12
+ * editing tokens via the Studio Design System tab must produce the exact
13
+ * same rendered result as editing them in source and running `orbital
14
+ * compile`. The mapping rules here mirror `generate_tokens_css` /
15
+ * `generate_tokens_css_dark` (theme.rs:122–351).
16
+ *
17
+ * Compile vs runtime difference (intentional):
18
+ * - Compile emits the FULL set: schema overrides on top of defaults. This is
19
+ * needed because the compiled CSS replaces the theme entirely.
20
+ * - Runtime emits ONLY the keys present in `tokens` (and `variants.dark`).
21
+ * Missing keys cascade from the parent `[data-theme]` rule on the document
22
+ * element. The provider scopes overrides to an orbital subtree without
23
+ * shadowing inherited defaults.
24
+ *
25
+ * @packageDocumentation
26
+ */
27
+ import type { ThemeDefinition, ThemeTokens, ThemeVariant, ThemeRef } from '@almadar/core';
28
+ /** Resolved color mode. Mirrors `ThemeContext.resolvedMode`. */
29
+ export type ThemeMode = 'light' | 'dark';
30
+ /**
31
+ * Convert `ThemeTokens` (+ optional dark variant) into a CSS custom-property
32
+ * map keyed by variable name (e.g. `--color-primary`).
33
+ *
34
+ * Mapping rules (mirror theme.rs):
35
+ * - `tokens.colors.<k>` → `--color-<k>`
36
+ * - `tokens.radii.<k>` → `--radius-<k>`
37
+ * - `tokens.spacing.<k>` → `--space-<k>`
38
+ * - `tokens.typography.<k>` → `--<k>` (keys already include their `font-`/
39
+ * `letter-`/`line-` prefix)
40
+ * - `tokens.shadows.<k>` → `--shadow-<k>` (schema key has no prefix)
41
+ *
42
+ * In `'dark'` mode, the `darkVariant` overrides are merged on top of the
43
+ * base tokens per category — same precedence the Rust compiler uses
44
+ * (`generate_tokens_css_dark`). Categories not present in `darkVariant` fall
45
+ * back to the base tokens.
46
+ */
47
+ export declare function themeTokensToCssVars(tokens: ThemeTokens, mode?: ThemeMode, darkVariant?: ThemeVariant): Record<string, string>;
48
+ /**
49
+ * `ThemeRef` is `ThemeDefinition | string`. When it's a string, it's an
50
+ * unresolved import reference (e.g. `"Ocean.theme"`) that should have been
51
+ * inlined by the compiler's import phase before runtime. If we still see a
52
+ * string here, the upstream resolution path didn't run — return `undefined`
53
+ * rather than guess. `OrbitalThemeProvider` falls through to passthrough.
54
+ */
55
+ export declare function resolveThemeForRuntime(theme: ThemeRef | undefined): ThemeDefinition | undefined;
@@ -46198,6 +46198,74 @@ function ServerBridgeProvider({
46198
46198
  return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeContext.Provider, { value: { connected, sendEvent }, children });
46199
46199
  }
46200
46200
 
46201
+ // context/OrbitalThemeProvider.tsx
46202
+ init_ThemeContext();
46203
+
46204
+ // context/themeTokens.ts
46205
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
46206
+ const vars = {};
46207
+ const isDark = mode === "dark";
46208
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
46209
+ if (pickColors) {
46210
+ for (const [key, value] of Object.entries(pickColors)) {
46211
+ vars[`--color-${key}`] = value;
46212
+ }
46213
+ if (isDark && darkVariant?.colors && tokens.colors) {
46214
+ for (const [key, value] of Object.entries(tokens.colors)) {
46215
+ const varName = `--color-${key}`;
46216
+ if (!(varName in vars)) vars[varName] = value;
46217
+ }
46218
+ }
46219
+ }
46220
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
46221
+ if (pickRadii) {
46222
+ for (const [key, value] of Object.entries(pickRadii)) {
46223
+ vars[`--radius-${key}`] = value;
46224
+ }
46225
+ }
46226
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
46227
+ if (pickSpacing) {
46228
+ for (const [key, value] of Object.entries(pickSpacing)) {
46229
+ vars[`--space-${key}`] = value;
46230
+ }
46231
+ }
46232
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
46233
+ if (pickTypography) {
46234
+ for (const [key, value] of Object.entries(pickTypography)) {
46235
+ vars[`--${key}`] = value;
46236
+ }
46237
+ }
46238
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
46239
+ if (pickShadows) {
46240
+ for (const [key, value] of Object.entries(pickShadows)) {
46241
+ vars[`--shadow-${key}`] = value;
46242
+ }
46243
+ }
46244
+ return vars;
46245
+ }
46246
+ function resolveThemeForRuntime(theme) {
46247
+ if (theme === void 0) return void 0;
46248
+ if (typeof theme === "string") return void 0;
46249
+ return theme;
46250
+ }
46251
+ function OrbitalThemeProvider({ theme, children }) {
46252
+ const resolved = resolveThemeForRuntime(theme);
46253
+ const { resolvedMode } = useTheme();
46254
+ if (!resolved) {
46255
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
46256
+ }
46257
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
46258
+ return /* @__PURE__ */ jsxRuntime.jsx(
46259
+ "div",
46260
+ {
46261
+ "data-orbital-theme": resolved.name,
46262
+ style: { display: "contents", ...vars },
46263
+ children
46264
+ }
46265
+ );
46266
+ }
46267
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
46268
+
46201
46269
  // runtime/OrbPreview.tsx
46202
46270
  init_navigation();
46203
46271
  init_verificationRegistry();
@@ -46646,6 +46714,19 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
46646
46714
  });
46647
46715
  return set;
46648
46716
  }, [schema, pageName]);
46717
+ const activeOrbitalTheme = React80.useMemo(() => {
46718
+ const parsed = schema;
46719
+ if (!parsed?.orbitals?.length) return void 0;
46720
+ if (pageName) {
46721
+ for (const orb of parsed.orbitals) {
46722
+ for (const pageRef of orb.pages ?? []) {
46723
+ const name = typeof pageRef === "object" && pageRef !== null ? pageRef.name : void 0;
46724
+ if (name === pageName) return orb.theme;
46725
+ }
46726
+ }
46727
+ }
46728
+ return parsed.orbitals[0]?.theme;
46729
+ }, [schema, pageName]);
46649
46730
  const inner = /* @__PURE__ */ jsxRuntime.jsx(providers.VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
46650
46731
  EntitySchemaProvider,
46651
46732
  {
@@ -46666,7 +46747,7 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
46666
46747
  persistence
46667
46748
  }
46668
46749
  ),
46669
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
46750
+ /* @__PURE__ */ jsxRuntime.jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
46670
46751
  ]
46671
46752
  }
46672
46753
  ) });
@@ -46152,6 +46152,74 @@ function ServerBridgeProvider({
46152
46152
  return /* @__PURE__ */ jsx(ServerBridgeContext.Provider, { value: { connected, sendEvent }, children });
46153
46153
  }
46154
46154
 
46155
+ // context/OrbitalThemeProvider.tsx
46156
+ init_ThemeContext();
46157
+
46158
+ // context/themeTokens.ts
46159
+ function themeTokensToCssVars(tokens, mode = "light", darkVariant) {
46160
+ const vars = {};
46161
+ const isDark = mode === "dark";
46162
+ const pickColors = isDark && darkVariant?.colors ? darkVariant.colors : tokens.colors;
46163
+ if (pickColors) {
46164
+ for (const [key, value] of Object.entries(pickColors)) {
46165
+ vars[`--color-${key}`] = value;
46166
+ }
46167
+ if (isDark && darkVariant?.colors && tokens.colors) {
46168
+ for (const [key, value] of Object.entries(tokens.colors)) {
46169
+ const varName = `--color-${key}`;
46170
+ if (!(varName in vars)) vars[varName] = value;
46171
+ }
46172
+ }
46173
+ }
46174
+ const pickRadii = isDark && darkVariant?.radii ? darkVariant.radii : tokens.radii;
46175
+ if (pickRadii) {
46176
+ for (const [key, value] of Object.entries(pickRadii)) {
46177
+ vars[`--radius-${key}`] = value;
46178
+ }
46179
+ }
46180
+ const pickSpacing = isDark && darkVariant?.spacing ? darkVariant.spacing : tokens.spacing;
46181
+ if (pickSpacing) {
46182
+ for (const [key, value] of Object.entries(pickSpacing)) {
46183
+ vars[`--space-${key}`] = value;
46184
+ }
46185
+ }
46186
+ const pickTypography = isDark && darkVariant?.typography ? darkVariant.typography : tokens.typography;
46187
+ if (pickTypography) {
46188
+ for (const [key, value] of Object.entries(pickTypography)) {
46189
+ vars[`--${key}`] = value;
46190
+ }
46191
+ }
46192
+ const pickShadows = isDark && darkVariant?.shadows ? darkVariant.shadows : tokens.shadows;
46193
+ if (pickShadows) {
46194
+ for (const [key, value] of Object.entries(pickShadows)) {
46195
+ vars[`--shadow-${key}`] = value;
46196
+ }
46197
+ }
46198
+ return vars;
46199
+ }
46200
+ function resolveThemeForRuntime(theme) {
46201
+ if (theme === void 0) return void 0;
46202
+ if (typeof theme === "string") return void 0;
46203
+ return theme;
46204
+ }
46205
+ function OrbitalThemeProvider({ theme, children }) {
46206
+ const resolved = resolveThemeForRuntime(theme);
46207
+ const { resolvedMode } = useTheme();
46208
+ if (!resolved) {
46209
+ return /* @__PURE__ */ jsx(Fragment, { children });
46210
+ }
46211
+ const vars = themeTokensToCssVars(resolved.tokens, resolvedMode, resolved.variants?.dark);
46212
+ return /* @__PURE__ */ jsx(
46213
+ "div",
46214
+ {
46215
+ "data-orbital-theme": resolved.name,
46216
+ style: { display: "contents", ...vars },
46217
+ children
46218
+ }
46219
+ );
46220
+ }
46221
+ OrbitalThemeProvider.displayName = "OrbitalThemeProvider";
46222
+
46155
46223
  // runtime/OrbPreview.tsx
46156
46224
  init_navigation();
46157
46225
  init_verificationRegistry();
@@ -46600,6 +46668,19 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
46600
46668
  });
46601
46669
  return set;
46602
46670
  }, [schema, pageName]);
46671
+ const activeOrbitalTheme = useMemo(() => {
46672
+ const parsed = schema;
46673
+ if (!parsed?.orbitals?.length) return void 0;
46674
+ if (pageName) {
46675
+ for (const orb of parsed.orbitals) {
46676
+ for (const pageRef of orb.pages ?? []) {
46677
+ const name = typeof pageRef === "object" && pageRef !== null ? pageRef.name : void 0;
46678
+ if (name === pageName) return orb.theme;
46679
+ }
46680
+ }
46681
+ }
46682
+ return parsed.orbitals[0]?.theme;
46683
+ }, [schema, pageName]);
46603
46684
  const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxs(
46604
46685
  EntitySchemaProvider,
46605
46686
  {
@@ -46620,7 +46701,7 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavi
46620
46701
  persistence
46621
46702
  }
46622
46703
  ),
46623
- /* @__PURE__ */ jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
46704
+ /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
46624
46705
  ]
46625
46706
  }
46626
46707
  ) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.50.16",
3
+ "version": "4.50.17",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [