@ankhorage/zora 2.10.0 → 2.12.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 (180) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -2
  3. package/dist/components/button/Button.d.ts.map +1 -1
  4. package/dist/components/button/Button.js +4 -2
  5. package/dist/components/button/Button.js.map +1 -1
  6. package/dist/components/button/meta.d.ts +3 -6
  7. package/dist/components/button/meta.d.ts.map +1 -1
  8. package/dist/components/button/meta.js +9 -15
  9. package/dist/components/button/meta.js.map +1 -1
  10. package/dist/components/button/resolveButtonThemeRecipe.d.ts +9 -0
  11. package/dist/components/button/resolveButtonThemeRecipe.d.ts.map +1 -0
  12. package/dist/components/button/resolveButtonThemeRecipe.js +30 -0
  13. package/dist/components/button/resolveButtonThemeRecipe.js.map +1 -0
  14. package/dist/components/button/themeRecipeMeta.d.ts +4 -10
  15. package/dist/components/button/themeRecipeMeta.d.ts.map +1 -1
  16. package/dist/components/button/themeRecipeMeta.js +5 -10
  17. package/dist/components/button/themeRecipeMeta.js.map +1 -1
  18. package/dist/components/card/Card.d.ts.map +1 -1
  19. package/dist/components/card/Card.js +8 -4
  20. package/dist/components/card/Card.js.map +1 -1
  21. package/dist/components/card/meta.d.ts +23 -4
  22. package/dist/components/card/meta.d.ts.map +1 -1
  23. package/dist/components/card/meta.js +14 -15
  24. package/dist/components/card/meta.js.map +1 -1
  25. package/dist/components/card/resolveCardThemeRecipe.d.ts +15 -0
  26. package/dist/components/card/resolveCardThemeRecipe.d.ts.map +1 -0
  27. package/dist/components/card/resolveCardThemeRecipe.js +22 -0
  28. package/dist/components/card/resolveCardThemeRecipe.js.map +1 -0
  29. package/dist/components/card/themeRecipeMeta.d.ts +1 -1
  30. package/dist/components/card/themeRecipeMeta.js +1 -1
  31. package/dist/components/card/themeRecipeMeta.js.map +1 -1
  32. package/dist/components/card/types.d.ts +2 -0
  33. package/dist/components/card/types.d.ts.map +1 -1
  34. package/dist/components/card/types.js.map +1 -1
  35. package/dist/components/heading/Heading.d.ts.map +1 -1
  36. package/dist/components/heading/Heading.js +14 -15
  37. package/dist/components/heading/Heading.js.map +1 -1
  38. package/dist/components/heading/meta.d.ts +6 -1
  39. package/dist/components/heading/meta.d.ts.map +1 -1
  40. package/dist/components/heading/meta.js +13 -22
  41. package/dist/components/heading/meta.js.map +1 -1
  42. package/dist/components/heading/resolveHeadingThemeRecipe.d.ts +11 -0
  43. package/dist/components/heading/resolveHeadingThemeRecipe.d.ts.map +1 -0
  44. package/dist/components/heading/resolveHeadingThemeRecipe.js +46 -0
  45. package/dist/components/heading/resolveHeadingThemeRecipe.js.map +1 -0
  46. package/dist/components/heading/themeRecipeMeta.d.ts +39 -0
  47. package/dist/components/heading/themeRecipeMeta.d.ts.map +1 -0
  48. package/dist/components/heading/themeRecipeMeta.js +32 -0
  49. package/dist/components/heading/themeRecipeMeta.js.map +1 -0
  50. package/dist/components/text/Text.d.ts +0 -1
  51. package/dist/components/text/Text.d.ts.map +1 -1
  52. package/dist/components/text/Text.js +14 -16
  53. package/dist/components/text/Text.js.map +1 -1
  54. package/dist/components/text/meta.d.ts +6 -5
  55. package/dist/components/text/meta.d.ts.map +1 -1
  56. package/dist/components/text/meta.js +13 -25
  57. package/dist/components/text/meta.js.map +1 -1
  58. package/dist/components/text/resolveTextThemeRecipe.d.ts +11 -0
  59. package/dist/components/text/resolveTextThemeRecipe.d.ts.map +1 -0
  60. package/dist/components/text/resolveTextThemeRecipe.js +46 -0
  61. package/dist/components/text/resolveTextThemeRecipe.js.map +1 -0
  62. package/dist/components/text/themeRecipeMeta.d.ts +15 -7
  63. package/dist/components/text/themeRecipeMeta.d.ts.map +1 -1
  64. package/dist/components/text/themeRecipeMeta.js +12 -11
  65. package/dist/components/text/themeRecipeMeta.js.map +1 -1
  66. package/dist/foundation/meta.d.ts +4 -4
  67. package/dist/layout/screen/meta.d.ts +1 -1
  68. package/dist/layout/screen-section/meta.d.ts +1 -1
  69. package/dist/metadata/allowedChildren.d.ts +3 -3
  70. package/dist/metadata/allowedChildren.d.ts.map +1 -1
  71. package/dist/metadata/allowedChildren.js +1 -0
  72. package/dist/metadata/allowedChildren.js.map +1 -1
  73. package/dist/metadata/componentMeta.d.ts.map +1 -1
  74. package/dist/metadata/componentMeta.js +2 -0
  75. package/dist/metadata/componentMeta.js.map +1 -1
  76. package/dist/metadata/themeRecipeMeta.d.ts.map +1 -1
  77. package/dist/metadata/themeRecipeMeta.js +2 -0
  78. package/dist/metadata/themeRecipeMeta.js.map +1 -1
  79. package/dist/metadata/themeRecipeTypes.d.ts +3 -3
  80. package/dist/metadata/themeRecipeTypes.d.ts.map +1 -1
  81. package/dist/metadata/themeRecipeTypes.js.map +1 -1
  82. package/dist/metadata/types.d.ts +1 -0
  83. package/dist/metadata/types.d.ts.map +1 -1
  84. package/dist/metadata/types.js.map +1 -1
  85. package/dist/patterns/message-bubble/meta.d.ts +1 -1
  86. package/dist/patterns/notice/meta.d.ts +1 -1
  87. package/dist/patterns/panel/Panel.d.ts +0 -2
  88. package/dist/patterns/panel/Panel.d.ts.map +1 -1
  89. package/dist/patterns/panel/Panel.js +6 -4
  90. package/dist/patterns/panel/Panel.js.map +1 -1
  91. package/dist/patterns/panel/meta.d.ts +23 -4
  92. package/dist/patterns/panel/meta.d.ts.map +1 -1
  93. package/dist/patterns/panel/meta.js +14 -15
  94. package/dist/patterns/panel/meta.js.map +1 -1
  95. package/dist/patterns/panel/themeRecipeMeta.d.ts +1 -1
  96. package/dist/patterns/panel/themeRecipeMeta.js +1 -1
  97. package/dist/patterns/panel/themeRecipeMeta.js.map +1 -1
  98. package/dist/patterns/panel/types.d.ts +2 -0
  99. package/dist/patterns/panel/types.d.ts.map +1 -1
  100. package/dist/patterns/panel/types.js.map +1 -1
  101. package/dist/patterns/post-card/meta.d.ts +1 -1
  102. package/dist/patterns/scanner/meta.d.ts +2 -2
  103. package/dist/registry.d.ts.map +1 -1
  104. package/dist/registry.js +2 -0
  105. package/dist/registry.js.map +1 -1
  106. package/dist/theme/ThemeModeToggle.d.ts +1 -1
  107. package/dist/theme/ThemeModeToggle.d.ts.map +1 -1
  108. package/dist/theme/ThemeModeToggle.js +2 -2
  109. package/dist/theme/ThemeModeToggle.js.map +1 -1
  110. package/dist/theme/ThemeModeToggle.meta.d.ts +28 -0
  111. package/dist/theme/ThemeModeToggle.meta.d.ts.map +1 -0
  112. package/dist/theme/ThemeModeToggle.meta.js +28 -0
  113. package/dist/theme/ThemeModeToggle.meta.js.map +1 -0
  114. package/dist/theme/ThemeModeToggleProps.d.ts +1 -1
  115. package/dist/theme/ThemeModeToggleProps.d.ts.map +1 -1
  116. package/dist/theme/ThemeModeToggleProps.js.map +1 -1
  117. package/dist/theme/ZoraProvider.d.ts +4 -12
  118. package/dist/theme/ZoraProvider.d.ts.map +1 -1
  119. package/dist/theme/ZoraProvider.js +5 -14
  120. package/dist/theme/ZoraProvider.js.map +1 -1
  121. package/dist/theme/ZoraThemeRuntimeContext.d.ts +1 -2
  122. package/dist/theme/ZoraThemeRuntimeContext.d.ts.map +1 -1
  123. package/dist/theme/ZoraThemeRuntimeContext.js +0 -1
  124. package/dist/theme/ZoraThemeRuntimeContext.js.map +1 -1
  125. package/dist/theme/ZoraThemeScope.d.ts.map +1 -1
  126. package/dist/theme/ZoraThemeScope.js +4 -10
  127. package/dist/theme/ZoraThemeScope.js.map +1 -1
  128. package/dist/theme/resolveZoraThemeRecipe.d.ts +16 -0
  129. package/dist/theme/resolveZoraThemeRecipe.d.ts.map +1 -0
  130. package/dist/theme/resolveZoraThemeRecipe.js +56 -0
  131. package/dist/theme/resolveZoraThemeRecipe.js.map +1 -0
  132. package/dist/theme/useZoraThemeRecipe.d.ts +2 -0
  133. package/dist/theme/useZoraThemeRecipe.d.ts.map +1 -0
  134. package/dist/theme/useZoraThemeRecipe.js +7 -0
  135. package/dist/theme/useZoraThemeRecipe.js.map +1 -0
  136. package/package.json +4 -4
  137. package/src/components/button/Button.tsx +4 -2
  138. package/src/components/button/meta.ts +10 -15
  139. package/src/components/button/resolveButtonThemeRecipe.test.ts +25 -0
  140. package/src/components/button/resolveButtonThemeRecipe.ts +41 -0
  141. package/src/components/button/themeRecipeMeta.ts +5 -10
  142. package/src/components/card/Card.tsx +13 -7
  143. package/src/components/card/meta.ts +15 -15
  144. package/src/components/card/resolveCardThemeRecipe.test.ts +28 -0
  145. package/src/components/card/resolveCardThemeRecipe.ts +33 -0
  146. package/src/components/card/themeRecipeMeta.ts +1 -1
  147. package/src/components/card/types.ts +2 -0
  148. package/src/components/contentFallback.test.ts +4 -4
  149. package/src/components/heading/Heading.tsx +18 -28
  150. package/src/components/heading/meta.ts +14 -22
  151. package/src/components/heading/resolveHeadingThemeRecipe.ts +55 -0
  152. package/src/components/heading/themeRecipeMeta.ts +33 -0
  153. package/src/components/text/Text.tsx +16 -25
  154. package/src/components/text/meta.ts +14 -25
  155. package/src/components/text/resolveTextThemeRecipe.ts +48 -0
  156. package/src/components/text/themeRecipeMeta.ts +12 -11
  157. package/src/metadata/allowedChildren.ts +1 -0
  158. package/src/metadata/authoringMeta.test.ts +18 -44
  159. package/src/metadata/componentMeta.test.ts +8 -0
  160. package/src/metadata/componentMeta.ts +2 -0
  161. package/src/metadata/themeRecipeMeta.test.ts +41 -39
  162. package/src/metadata/themeRecipeMeta.ts +2 -0
  163. package/src/metadata/themeRecipeTypes.ts +3 -3
  164. package/src/metadata/types.ts +3 -9
  165. package/src/patterns/panel/Panel.tsx +14 -4
  166. package/src/patterns/panel/meta.ts +15 -15
  167. package/src/patterns/panel/themeRecipeMeta.ts +1 -1
  168. package/src/patterns/panel/types.ts +2 -0
  169. package/src/registry.test.ts +5 -3
  170. package/src/registry.ts +2 -0
  171. package/src/theme/ThemeModeToggle.meta.ts +29 -0
  172. package/src/theme/ThemeModeToggle.tsx +7 -1
  173. package/src/theme/ThemeModeToggleProps.ts +4 -1
  174. package/src/theme/ZoraProvider.tsx +10 -13
  175. package/src/theme/ZoraThemeRuntimeContext.tsx +1 -3
  176. package/src/theme/ZoraThemeScope.tsx +5 -25
  177. package/src/theme/resolveZoraThemeRecipe.test.ts +72 -0
  178. package/src/theme/resolveZoraThemeRecipe.ts +91 -0
  179. package/src/theme/themeConfigScope.test.ts +25 -0
  180. package/src/theme/useZoraThemeRecipe.ts +7 -0
@@ -1,20 +1,12 @@
1
+ import type { ThemeConfig } from '@ankhorage/contracts';
1
2
  import React from 'react';
2
3
  import type { ZoraTheme, ZoraThemeMode } from './types';
3
4
  export interface ZoraProviderProps {
4
5
  children: React.ReactNode;
5
6
  theme?: ZoraTheme;
7
+ themeConfig?: ThemeConfig;
6
8
  initialMode?: ZoraThemeMode;
7
9
  }
8
- /***
9
- * Installs the ZORA theme runtime and underlying Surface theme provider.
10
- *
11
- * Wrap an app with `ZoraProvider` once near the root so components, patterns,
12
- * layouts, and theme hooks resolve the same design tokens and color mode.
13
- *
14
- * @example App provider
15
- * ```tsx
16
- * <ZoraProvider initialMode="light"><App /></ZoraProvider>
17
- * ```
18
- */
19
- export declare function ZoraProvider({ children, theme, initialMode, }: ZoraProviderProps): React.JSX.Element;
10
+ /** Installs the ZORA theme runtime and underlying Surface theme provider. */
11
+ export declare function ZoraProvider({ children, theme, themeConfig, initialMode, }: ZoraProviderProps): React.JSX.Element;
20
12
  //# sourceMappingURL=ZoraProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAwB,EACxB,WAAqB,GACtB,EAAE,iBAAiB,qBAUnB"}
1
+ {"version":3,"file":"ZoraProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAwB,EACxB,WAAW,EACX,WAAqB,GACtB,EAAE,iBAAiB,qBAcnB"}
@@ -3,21 +3,12 @@ import React from 'react';
3
3
  import { createZoraThemeConfig } from './createZoraThemeConfig';
4
4
  import { zoraDefaultTheme } from './zoraDefaultTheme';
5
5
  import { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';
6
- /***
7
- * Installs the ZORA theme runtime and underlying Surface theme provider.
8
- *
9
- * Wrap an app with `ZoraProvider` once near the root so components, patterns,
10
- * layouts, and theme hooks resolve the same design tokens and color mode.
11
- *
12
- * @example App provider
13
- * ```tsx
14
- * <ZoraProvider initialMode="light"><App /></ZoraProvider>
15
- * ```
16
- */
17
- export function ZoraProvider({ children, theme = zoraDefaultTheme, initialMode = 'light', }) {
18
- const runtimeValue = React.useMemo(() => ({ sourceTheme: theme, themeId: theme.id }), [theme]);
6
+ /** Installs the ZORA theme runtime and underlying Surface theme provider. */
7
+ export function ZoraProvider({ children, theme = zoraDefaultTheme, themeConfig, initialMode = 'light', }) {
8
+ const resolvedConfig = React.useMemo(() => themeConfig ?? createZoraThemeConfig(theme), [theme, themeConfig]);
9
+ const runtimeValue = React.useMemo(() => ({ themeId: resolvedConfig.id }), [resolvedConfig.id]);
19
10
  return (<ZoraThemeRuntimeContext.Provider value={runtimeValue}>
20
- <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>
11
+ <ThemeProvider initialConfig={resolvedConfig} initialMode={initialMode}>
21
12
  {children}
22
13
  </ThemeProvider>
23
14
  </ZoraThemeRuntimeContext.Provider>);
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQpE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,GAAG,gBAAgB,EACxB,WAAW,GAAG,OAAO,GACH;IAClB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/F,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACpD;MAAA,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACnF;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,aAAa,CACjB;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC","sourcesContent":["import { ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport type { ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\nimport { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n theme?: ZoraTheme;\n initialMode?: ZoraThemeMode;\n}\n\n/***\n * Installs the ZORA theme runtime and underlying Surface theme provider.\n *\n * Wrap an app with `ZoraProvider` once near the root so components, patterns,\n * layouts, and theme hooks resolve the same design tokens and color mode.\n *\n * @example App provider\n * ```tsx\n * <ZoraProvider initialMode=\"light\"><App /></ZoraProvider>\n * ```\n */\nexport function ZoraProvider({\n children,\n theme = zoraDefaultTheme,\n initialMode = 'light',\n}: ZoraProviderProps) {\n const runtimeValue = React.useMemo(() => ({ sourceTheme: theme, themeId: theme.id }), [theme]);\n\n return (\n <ZoraThemeRuntimeContext.Provider value={runtimeValue}>\n <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>\n {children}\n </ThemeProvider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n"]}
1
+ {"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AASpE,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,GAAG,gBAAgB,EACxB,WAAW,EACX,WAAW,GAAG,OAAO,GACH;IAClB,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAClC,GAAG,EAAE,CAAC,WAAW,IAAI,qBAAqB,CAAC,KAAK,CAAC,EACjD,CAAC,KAAK,EAAE,WAAW,CAAC,CACrB,CAAC;IACF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhG,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACpD;MAAA,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACrE;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,aAAa,CACjB;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/contracts';\nimport { ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport type { ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\nimport { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n theme?: ZoraTheme;\n themeConfig?: ThemeConfig;\n initialMode?: ZoraThemeMode;\n}\n\n/** Installs the ZORA theme runtime and underlying Surface theme provider. */\nexport function ZoraProvider({\n children,\n theme = zoraDefaultTheme,\n themeConfig,\n initialMode = 'light',\n}: ZoraProviderProps) {\n const resolvedConfig = React.useMemo(\n () => themeConfig ?? createZoraThemeConfig(theme),\n [theme, themeConfig],\n );\n const runtimeValue = React.useMemo(() => ({ themeId: resolvedConfig.id }), [resolvedConfig.id]);\n\n return (\n <ZoraThemeRuntimeContext.Provider value={runtimeValue}>\n <ThemeProvider initialConfig={resolvedConfig} initialMode={initialMode}>\n {children}\n </ThemeProvider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n"]}
@@ -1,6 +1,5 @@
1
- import type { ZoraTheme, ZoraThemeId } from './types';
1
+ import type { ZoraThemeId } from './types';
2
2
  interface ZoraThemeRuntime {
3
- sourceTheme: ZoraTheme;
4
3
  themeId: ZoraThemeId;
5
4
  }
6
5
  export declare const ZoraThemeRuntimeContext: import("react").Context<ZoraThemeRuntime>;
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraThemeRuntimeContext.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraThemeRuntimeContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGtD,UAAU,gBAAgB;IACxB,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB,2CAGlC,CAAC;AAEH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD"}
1
+ {"version":3,"file":"ZoraThemeRuntimeContext.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraThemeRuntimeContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,UAAU,gBAAgB;IACxB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB,2CAElC,CAAC;AAEH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD"}
@@ -1,7 +1,6 @@
1
1
  import { createContext, useContext } from 'react';
2
2
  import { zoraDefaultTheme } from './zoraDefaultTheme';
3
3
  export const ZoraThemeRuntimeContext = createContext({
4
- sourceTheme: zoraDefaultTheme,
5
4
  themeId: zoraDefaultTheme.id,
6
5
  });
7
6
  export function useZoraThemeRuntime() {
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraThemeRuntimeContext.js","sourceRoot":"","sources":["../../src/theme/ZoraThemeRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAOtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAmB;IACrE,WAAW,EAAE,gBAAgB;IAC7B,OAAO,EAAE,gBAAgB,CAAC,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { createContext, useContext } from 'react';\n\nimport type { ZoraTheme, ZoraThemeId } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\n\ninterface ZoraThemeRuntime {\n sourceTheme: ZoraTheme;\n themeId: ZoraThemeId;\n}\n\nexport const ZoraThemeRuntimeContext = createContext<ZoraThemeRuntime>({\n sourceTheme: zoraDefaultTheme,\n themeId: zoraDefaultTheme.id,\n});\n\nexport function useZoraThemeRuntime(): ZoraThemeRuntime {\n return useContext(ZoraThemeRuntimeContext);\n}\n"]}
1
+ {"version":3,"file":"ZoraThemeRuntimeContext.js","sourceRoot":"","sources":["../../src/theme/ZoraThemeRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAmB;IACrE,OAAO,EAAE,gBAAgB,CAAC,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { createContext, useContext } from 'react';\n\nimport type { ZoraThemeId } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\n\ninterface ZoraThemeRuntime {\n themeId: ZoraThemeId;\n}\n\nexport const ZoraThemeRuntimeContext = createContext<ZoraThemeRuntime>({\n themeId: zoraDefaultTheme.id,\n});\n\nexport function useZoraThemeRuntime(): ZoraThemeRuntime {\n return useContext(ZoraThemeRuntimeContext);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraThemeScope.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraThemeScope.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAmDD,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,mBAAmB,mSAU9E"}
1
+ {"version":3,"file":"ZoraThemeScope.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraThemeScope.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAmCD,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,mBAAmB,mSAO9E"}
@@ -1,6 +1,5 @@
1
1
  import { createTheme, ThemeContext, useFontContext, useTheme } from '@ankhorage/surface';
2
2
  import React, { useMemo } from 'react';
3
- import { createZoraThemeConfig } from './createZoraThemeConfig';
4
3
  import { resolveZoraScopedThemeId } from './resolveZoraScopedThemeId';
5
4
  import { useZoraThemeRuntime, ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';
6
5
  function ZoraThemeScopeInner({ children, themeId, mode }) {
@@ -12,9 +11,8 @@ function ZoraThemeScopeInner({ children, themeId, mode }) {
12
11
  inheritedThemeId: parentRuntime.themeId,
13
12
  });
14
13
  const scopedMode = mode ?? parentSurface.mode;
15
- // Plan 2: there is no multi-theme registry yet. Keep the active theme seed inherited.
16
- const surfaceConfig = useMemo(() => createZoraThemeConfig(parentRuntime.sourceTheme), [parentRuntime.sourceTheme]);
17
- const scopedTheme = useMemo(() => createTheme(surfaceConfig, scopedMode, activeFontId), [surfaceConfig, scopedMode, activeFontId]);
14
+ const sourceConfig = parentSurface.theme.config;
15
+ const scopedTheme = useMemo(() => createTheme(sourceConfig, scopedMode, activeFontId), [sourceConfig, scopedMode, activeFontId]);
18
16
  const scopedSurfaceValue = useMemo(() => ({
19
17
  theme: scopedTheme,
20
18
  mode: scopedMode,
@@ -22,18 +20,14 @@ function ZoraThemeScopeInner({ children, themeId, mode }) {
22
20
  setThemeConfig: parentSurface.setThemeConfig,
23
21
  _hasProvider: true,
24
22
  }), [parentSurface.setMode, parentSurface.setThemeConfig, scopedMode, scopedTheme]);
25
- const scopedRuntimeValue = useMemo(() => ({
26
- sourceTheme: parentRuntime.sourceTheme,
27
- themeId: scopedThemeId,
28
- }), [parentRuntime.sourceTheme, scopedThemeId]);
23
+ const scopedRuntimeValue = useMemo(() => ({ themeId: scopedThemeId }), [scopedThemeId]);
29
24
  return (<ZoraThemeRuntimeContext.Provider value={scopedRuntimeValue}>
30
25
  <ThemeContext.Provider value={scopedSurfaceValue}>{children}</ThemeContext.Provider>
31
26
  </ZoraThemeRuntimeContext.Provider>);
32
27
  }
33
28
  export function ZoraThemeScope({ children, themeId, mode }) {
34
- if (mode === undefined && themeId === undefined) {
29
+ if (mode === undefined && themeId === undefined)
35
30
  return children;
36
- }
37
31
  return (<ZoraThemeScopeInner mode={mode} themeId={themeId}>
38
32
  {children}
39
33
  </ZoraThemeScopeInner>);
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraThemeScope.js","sourceRoot":"","sources":["../../src/theme/ZoraThemeScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzF,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQzF,SAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAuB;IAC3E,MAAM,aAAa,GAAG,QAAQ,EAAE,CAAC;IACjC,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAE1C,MAAM,aAAa,GAAG,wBAAwB,CAAC;QAC7C,cAAc,EAAE,OAAO;QACvB,gBAAgB,EAAE,aAAa,CAAC,OAAO;KACxC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC;IAE9C,sFAAsF;IACtF,MAAM,aAAa,GAAG,OAAO,CAC3B,GAAG,EAAE,CAAC,qBAAqB,CAAC,aAAa,CAAC,WAAW,CAAC,EACtD,CAAC,aAAa,CAAC,WAAW,CAAC,CAC5B,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,CACzB,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,EAC1D,CAAC,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,CAC1C,CAAC;IAEF,MAAM,kBAAkB,GAAG,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC;QACL,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,aAAa,CAAC,OAAO;QAC9B,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,YAAY,EAAE,IAAI;KACnB,CAAC,EACF,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAC/E,CAAC;IAEF,MAAM,kBAAkB,GAAG,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC;QACL,WAAW,EAAE,aAAa,CAAC,WAAW;QACtC,OAAO,EAAE,aAAa;KACvB,CAAC,EACF,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,CAC3C,CAAC;IAEF,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAC1D;MAAA,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,QAAQ,CACrF;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAuB;IAC7E,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAChD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,CACL,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAChD;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAmB,CAAC,CACvB,CAAC;AACJ,CAAC","sourcesContent":["import { createTheme, ThemeContext, useFontContext, useTheme } from '@ankhorage/surface';\nimport React, { useMemo } from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport { resolveZoraScopedThemeId } from './resolveZoraScopedThemeId';\nimport type { ZoraThemeId, ZoraThemeMode } from './types';\nimport { useZoraThemeRuntime, ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraThemeScopeProps {\n children: React.ReactNode;\n themeId?: ZoraThemeId;\n mode?: ZoraThemeMode;\n}\n\nfunction ZoraThemeScopeInner({ children, themeId, mode }: ZoraThemeScopeProps) {\n const parentSurface = useTheme();\n const parentRuntime = useZoraThemeRuntime();\n const { activeFontId } = useFontContext();\n\n const scopedThemeId = resolveZoraScopedThemeId({\n desiredThemeId: themeId,\n inheritedThemeId: parentRuntime.themeId,\n });\n\n const scopedMode = mode ?? parentSurface.mode;\n\n // Plan 2: there is no multi-theme registry yet. Keep the active theme seed inherited.\n const surfaceConfig = useMemo(\n () => createZoraThemeConfig(parentRuntime.sourceTheme),\n [parentRuntime.sourceTheme],\n );\n\n const scopedTheme = useMemo(\n () => createTheme(surfaceConfig, scopedMode, activeFontId),\n [surfaceConfig, scopedMode, activeFontId],\n );\n\n const scopedSurfaceValue = useMemo(\n () => ({\n theme: scopedTheme,\n mode: scopedMode,\n setMode: parentSurface.setMode,\n setThemeConfig: parentSurface.setThemeConfig,\n _hasProvider: true,\n }),\n [parentSurface.setMode, parentSurface.setThemeConfig, scopedMode, scopedTheme],\n );\n\n const scopedRuntimeValue = useMemo(\n () => ({\n sourceTheme: parentRuntime.sourceTheme,\n themeId: scopedThemeId,\n }),\n [parentRuntime.sourceTheme, scopedThemeId],\n );\n\n return (\n <ZoraThemeRuntimeContext.Provider value={scopedRuntimeValue}>\n <ThemeContext.Provider value={scopedSurfaceValue}>{children}</ThemeContext.Provider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n\nexport function ZoraThemeScope({ children, themeId, mode }: ZoraThemeScopeProps) {\n if (mode === undefined && themeId === undefined) {\n return children;\n }\n\n return (\n <ZoraThemeScopeInner mode={mode} themeId={themeId}>\n {children}\n </ZoraThemeScopeInner>\n );\n}\n"]}
1
+ {"version":3,"file":"ZoraThemeScope.js","sourceRoot":"","sources":["../../src/theme/ZoraThemeScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzF,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQzF,SAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAuB;IAC3E,MAAM,aAAa,GAAG,QAAQ,EAAE,CAAC;IACjC,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1C,MAAM,aAAa,GAAG,wBAAwB,CAAC;QAC7C,cAAc,EAAE,OAAO;QACvB,gBAAgB,EAAE,aAAa,CAAC,OAAO;KACxC,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC;IAC9C,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CACzB,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,EACzD,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CACzC,CAAC;IACF,MAAM,kBAAkB,GAAG,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC;QACL,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,aAAa,CAAC,OAAO;QAC9B,cAAc,EAAE,aAAa,CAAC,cAAc;QAC5C,YAAY,EAAE,IAAI;KACnB,CAAC,EACF,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAC/E,CAAC;IACF,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAExF,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAC1D;MAAA,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,QAAQ,CACrF;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAuB;IAC7E,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACjE,OAAO,CACL,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAChD;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAmB,CAAC,CACvB,CAAC;AACJ,CAAC","sourcesContent":["import { createTheme, ThemeContext, useFontContext, useTheme } from '@ankhorage/surface';\nimport React, { useMemo } from 'react';\n\nimport { resolveZoraScopedThemeId } from './resolveZoraScopedThemeId';\nimport type { ZoraThemeId, ZoraThemeMode } from './types';\nimport { useZoraThemeRuntime, ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraThemeScopeProps {\n children: React.ReactNode;\n themeId?: ZoraThemeId;\n mode?: ZoraThemeMode;\n}\n\nfunction ZoraThemeScopeInner({ children, themeId, mode }: ZoraThemeScopeProps) {\n const parentSurface = useTheme();\n const parentRuntime = useZoraThemeRuntime();\n const { activeFontId } = useFontContext();\n const scopedThemeId = resolveZoraScopedThemeId({\n desiredThemeId: themeId,\n inheritedThemeId: parentRuntime.themeId,\n });\n const scopedMode = mode ?? parentSurface.mode;\n const sourceConfig = parentSurface.theme.config;\n const scopedTheme = useMemo(\n () => createTheme(sourceConfig, scopedMode, activeFontId),\n [sourceConfig, scopedMode, activeFontId],\n );\n const scopedSurfaceValue = useMemo(\n () => ({\n theme: scopedTheme,\n mode: scopedMode,\n setMode: parentSurface.setMode,\n setThemeConfig: parentSurface.setThemeConfig,\n _hasProvider: true,\n }),\n [parentSurface.setMode, parentSurface.setThemeConfig, scopedMode, scopedTheme],\n );\n const scopedRuntimeValue = useMemo(() => ({ themeId: scopedThemeId }), [scopedThemeId]);\n\n return (\n <ZoraThemeRuntimeContext.Provider value={scopedRuntimeValue}>\n <ThemeContext.Provider value={scopedSurfaceValue}>{children}</ThemeContext.Provider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n\nexport function ZoraThemeScope({ children, themeId, mode }: ZoraThemeScopeProps) {\n if (mode === undefined && themeId === undefined) return children;\n return (\n <ZoraThemeScopeInner mode={mode} themeId={themeId}>\n {children}\n </ZoraThemeScopeInner>\n );\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import type { ThemeConfig, ThemeRecipeOverrideValue } from '@ankhorage/contracts';
2
+ interface ZoraThemeRecipeRuntimeTheme {
3
+ readonly config: ThemeConfig;
4
+ readonly colors: object;
5
+ readonly spacing: object;
6
+ readonly radii: object;
7
+ readonly shadows: object;
8
+ readonly typography: {
9
+ readonly sizes: object;
10
+ readonly weights: object;
11
+ readonly headings: object;
12
+ };
13
+ }
14
+ export declare function resolveZoraThemeRecipe(theme: ZoraThemeRecipeRuntimeTheme, recipeName: string): Readonly<Record<string, ThemeRecipeOverrideValue>>;
15
+ export {};
16
+ //# sourceMappingURL=resolveZoraThemeRecipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveZoraThemeRecipe.d.ts","sourceRoot":"","sources":["../../src/theme/resolveZoraThemeRecipe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAKlF,UAAU,2BAA2B;IACnC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE;QACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAID,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,2BAA2B,EAClC,UAAU,EAAE,MAAM,GACjB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAqBpD"}
@@ -0,0 +1,56 @@
1
+ import { ZORA_THEME_RECIPE_META } from '../metadata/themeRecipeMeta';
2
+ const recipeMetaByName = new Map(Object.entries(ZORA_THEME_RECIPE_META));
3
+ export function resolveZoraThemeRecipe(theme, recipeName) {
4
+ const meta = recipeMetaByName.get(recipeName);
5
+ if (!meta)
6
+ throw new RangeError(`Unknown ZORA theme recipe: ${recipeName}.`);
7
+ const recipes = meta.kind === 'component' ? theme.config.recipes?.components : theme.config.recipes?.patterns;
8
+ const overrides = new Map(Object.entries(recipes ?? {})).get(recipeName);
9
+ const overrideByField = new Map(Object.entries(overrides ?? {}));
10
+ const resolved = [];
11
+ for (const [fieldName, fieldMeta] of Object.entries(meta.fields)) {
12
+ const override = overrideByField.get(fieldName);
13
+ if (override !== undefined) {
14
+ validateFieldValue(theme, recipeName, fieldName, fieldMeta, override);
15
+ resolved.push([fieldName, override]);
16
+ }
17
+ else if (fieldMeta.default !== undefined) {
18
+ resolved.push([fieldName, fieldMeta.default]);
19
+ }
20
+ }
21
+ return Object.fromEntries(resolved);
22
+ }
23
+ function validateFieldValue(theme, recipeName, fieldName, meta, value) {
24
+ if (meta.type === 'boolean') {
25
+ if (typeof value !== 'boolean') {
26
+ throw new TypeError(`Theme recipe ${recipeName}.${fieldName} must be boolean.`);
27
+ }
28
+ return;
29
+ }
30
+ if (typeof value !== 'string') {
31
+ throw new TypeError(`Theme recipe ${recipeName}.${fieldName} must be a string.`);
32
+ }
33
+ if (meta.type === 'choice' && !meta.options.includes(value)) {
34
+ throw new RangeError(`Invalid theme recipe choice for ${recipeName}.${fieldName}: ${value}.`);
35
+ }
36
+ if (meta.type === 'token' && !hasThemeToken(theme, meta.tokenFamily, value)) {
37
+ throw new RangeError(`Unknown ${meta.tokenFamily} token for ${recipeName}.${fieldName}: ${value}.`);
38
+ }
39
+ }
40
+ function hasThemeToken(theme, family, token) {
41
+ if (family === 'colors')
42
+ return hasOwn(theme.colors, token);
43
+ if (family === 'spacing')
44
+ return hasOwn(theme.spacing, token);
45
+ if (family === 'radii')
46
+ return hasOwn(theme.radii, token);
47
+ if (family === 'shadows')
48
+ return hasOwn(theme.shadows, token);
49
+ return (hasOwn(theme.typography.sizes, token) ||
50
+ hasOwn(theme.typography.weights, token) ||
51
+ hasOwn(theme.typography.headings, token));
52
+ }
53
+ function hasOwn(value, key) {
54
+ return Object.prototype.hasOwnProperty.call(value, key);
55
+ }
56
+ //# sourceMappingURL=resolveZoraThemeRecipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveZoraThemeRecipe.js","sourceRoot":"","sources":["../../src/theme/resolveZoraThemeRecipe.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThemeConfig, ThemeRecipeOverrideValue } from '@ankhorage/contracts';\n\nimport { ZORA_THEME_RECIPE_META } from '../metadata/themeRecipeMeta';\nimport type { ZoraThemeRecipeFieldMeta, ZoraThemeTokenFamily } from '../metadata/themeRecipeTypes';\n\ninterface ZoraThemeRecipeRuntimeTheme {\n readonly config: ThemeConfig;\n readonly colors: object;\n readonly spacing: object;\n readonly radii: object;\n readonly shadows: object;\n readonly typography: {\n readonly sizes: object;\n readonly weights: object;\n readonly headings: object;\n };\n}\n\nconst recipeMetaByName = new Map(Object.entries(ZORA_THEME_RECIPE_META));\n\nexport function resolveZoraThemeRecipe(\n theme: ZoraThemeRecipeRuntimeTheme,\n recipeName: string,\n): Readonly<Record<string, ThemeRecipeOverrideValue>> {\n const meta = recipeMetaByName.get(recipeName);\n if (!meta) throw new RangeError(`Unknown ZORA theme recipe: ${recipeName}.`);\n\n const recipes =\n meta.kind === 'component' ? theme.config.recipes?.components : theme.config.recipes?.patterns;\n const overrides = new Map(Object.entries(recipes ?? {})).get(recipeName);\n const overrideByField = new Map(Object.entries(overrides ?? {}));\n const resolved: [string, ThemeRecipeOverrideValue][] = [];\n\n for (const [fieldName, fieldMeta] of Object.entries(meta.fields)) {\n const override = overrideByField.get(fieldName);\n if (override !== undefined) {\n validateFieldValue(theme, recipeName, fieldName, fieldMeta, override);\n resolved.push([fieldName, override]);\n } else if (fieldMeta.default !== undefined) {\n resolved.push([fieldName, fieldMeta.default]);\n }\n }\n\n return Object.fromEntries(resolved);\n}\n\nfunction validateFieldValue(\n theme: ZoraThemeRecipeRuntimeTheme,\n recipeName: string,\n fieldName: string,\n meta: ZoraThemeRecipeFieldMeta,\n value: ThemeRecipeOverrideValue,\n): void {\n if (meta.type === 'boolean') {\n if (typeof value !== 'boolean') {\n throw new TypeError(`Theme recipe ${recipeName}.${fieldName} must be boolean.`);\n }\n return;\n }\n if (typeof value !== 'string') {\n throw new TypeError(`Theme recipe ${recipeName}.${fieldName} must be a string.`);\n }\n if (meta.type === 'choice' && !meta.options.includes(value)) {\n throw new RangeError(`Invalid theme recipe choice for ${recipeName}.${fieldName}: ${value}.`);\n }\n if (meta.type === 'token' && !hasThemeToken(theme, meta.tokenFamily, value)) {\n throw new RangeError(\n `Unknown ${meta.tokenFamily} token for ${recipeName}.${fieldName}: ${value}.`,\n );\n }\n}\n\nfunction hasThemeToken(\n theme: ZoraThemeRecipeRuntimeTheme,\n family: ZoraThemeTokenFamily,\n token: string,\n): boolean {\n if (family === 'colors') return hasOwn(theme.colors, token);\n if (family === 'spacing') return hasOwn(theme.spacing, token);\n if (family === 'radii') return hasOwn(theme.radii, token);\n if (family === 'shadows') return hasOwn(theme.shadows, token);\n return (\n hasOwn(theme.typography.sizes, token) ||\n hasOwn(theme.typography.weights, token) ||\n hasOwn(theme.typography.headings, token)\n );\n}\n\nfunction hasOwn(value: object, key: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function useZoraThemeRecipe(recipeName: string): Readonly<Record<string, import("@ankhorage/contracts").ThemeRecipeOverrideValue>>;
2
+ //# sourceMappingURL=useZoraThemeRecipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useZoraThemeRecipe.d.ts","sourceRoot":"","sources":["../../src/theme/useZoraThemeRecipe.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,qFAGpD"}
@@ -0,0 +1,7 @@
1
+ import { resolveZoraThemeRecipe } from './resolveZoraThemeRecipe';
2
+ import { useZoraTheme } from './useZoraTheme';
3
+ export function useZoraThemeRecipe(recipeName) {
4
+ const { theme } = useZoraTheme();
5
+ return resolveZoraThemeRecipe(theme, recipeName);
6
+ }
7
+ //# sourceMappingURL=useZoraThemeRecipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useZoraThemeRecipe.js","sourceRoot":"","sources":["../../src/theme/useZoraThemeRecipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,OAAO,sBAAsB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { resolveZoraThemeRecipe } from './resolveZoraThemeRecipe';\nimport { useZoraTheme } from './useZoraTheme';\n\nexport function useZoraThemeRecipe(recipeName: string) {\n const { theme } = useZoraTheme();\n return resolveZoraThemeRecipe(theme, recipeName);\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "2.10.0",
4
+ "version": "2.12.0",
5
5
  "description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
6
6
  "homepage": "https://github.com/ankhorage/zora#readme",
7
7
  "bugs": {
@@ -42,8 +42,8 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@ankhorage/color-theory": "^0.0.8",
45
- "@ankhorage/contracts": "^4.0.1",
46
- "@ankhorage/surface": "^2.1.1"
45
+ "@ankhorage/contracts": "^7.2.0",
46
+ "@ankhorage/surface": "^2.2.0"
47
47
  },
48
48
  "files": [
49
49
  "dist",
@@ -90,7 +90,7 @@
90
90
  },
91
91
  "devDependencies": {
92
92
  "@ankhorage/devtools": "^1.3.4",
93
- "@ankhorage/paradox": "^0.1.10",
93
+ "@ankhorage/paradox": "^0.1.21",
94
94
  "@changesets/cli": "^2.31.0",
95
95
  "@expo/vector-icons": "^15.1.1",
96
96
  "@react-native-picker/picker": "^2.11.4",
@@ -1,8 +1,9 @@
1
1
  import { Button as SurfaceButton } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
- import { resolveButtonRecipe } from '../../internal/recipes';
4
+ import { useZoraThemeRecipe } from '../../theme/useZoraThemeRecipe';
5
5
  import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
6
+ import { resolveButtonThemeRecipe } from './resolveButtonThemeRecipe';
6
7
  import type { ButtonProps } from './types';
7
8
 
8
9
  function ButtonInner({
@@ -14,7 +15,8 @@ function ButtonInner({
14
15
  interactionPolicy,
15
16
  ...props
16
17
  }: ButtonProps) {
17
- const recipe = resolveButtonRecipe({ color, variant, size });
18
+ const themeFields = useZoraThemeRecipe('Button');
19
+ const recipe = resolveButtonThemeRecipe({ color, variant, size, themeFields });
18
20
 
19
21
  return (
20
22
  <SurfaceButton
@@ -1,20 +1,18 @@
1
1
  import { ZORA_COLORS } from '../../internal/colorModel';
2
2
  import type { ZoraComponentMeta } from '../../metadata';
3
3
 
4
+ const themeAuthoring = {
5
+ authority: 'theme',
6
+ scope: 'component',
7
+ allowInstanceOverride: true,
8
+ } as const;
9
+
4
10
  export const buttonMeta = {
5
11
  name: 'Button',
6
12
  category: 'component',
7
13
  directManifestNode: true,
8
14
  allowedChildren: [],
9
- blueprint: {
10
- label: 'Button',
11
- defaultProps: {
12
- children: 'Continue',
13
- color: 'primary',
14
- variant: 'solid',
15
- size: 'm',
16
- },
17
- },
15
+ blueprint: { label: 'Button', defaultProps: { children: 'Continue' } },
18
16
  events: {
19
17
  press: {
20
18
  label: 'Press',
@@ -36,24 +34,21 @@ export const buttonMeta = {
36
34
  category: 'Style',
37
35
  label: 'Color',
38
36
  enum: [...ZORA_COLORS],
39
- default: 'primary',
40
- authoring: { authority: 'theme', scope: 'component' },
37
+ authoring: themeAuthoring,
41
38
  },
42
39
  variant: {
43
40
  type: 'enum',
44
41
  category: 'Style',
45
42
  label: 'Variant',
46
43
  enum: ['solid', 'outline', 'ghost', 'soft'],
47
- default: 'solid',
48
- authoring: { authority: 'theme', scope: 'component' },
44
+ authoring: themeAuthoring,
49
45
  },
50
46
  size: {
51
47
  type: 'enum',
52
48
  category: 'Style',
53
49
  label: 'Size',
54
50
  enum: ['s', 'm', 'l'],
55
- default: 'm',
56
- authoring: { authority: 'theme', scope: 'component' },
51
+ authoring: themeAuthoring,
57
52
  },
58
53
  },
59
54
  } as const satisfies ZoraComponentMeta;
@@ -0,0 +1,25 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+
3
+ import { resolveButtonThemeRecipe } from './resolveButtonThemeRecipe';
4
+
5
+ describe('resolveButtonThemeRecipe', () => {
6
+ test('uses theme defaults without changing the existing hard default', () => {
7
+ expect(
8
+ resolveButtonThemeRecipe({ themeFields: { color: 'primary', variant: 'solid', size: 'l' } }),
9
+ ).toEqual({
10
+ color: 'primary',
11
+ variant: 'solid',
12
+ size: 'l',
13
+ });
14
+ });
15
+
16
+ test('lets explicit instance props override theme recipe values', () => {
17
+ expect(
18
+ resolveButtonThemeRecipe({
19
+ color: 'danger',
20
+ size: 's',
21
+ themeFields: { color: 'primary', variant: 'soft', size: 'l' },
22
+ }),
23
+ ).toEqual({ color: 'danger', variant: 'soft', size: 's' });
24
+ });
25
+ });
@@ -0,0 +1,41 @@
1
+ import type { ThemeRecipeOverrideValue } from '@ankhorage/contracts';
2
+
3
+ import {
4
+ resolveButtonRecipe,
5
+ type ZoraButtonVariant,
6
+ type ZoraColor,
7
+ type ZoraControlSize,
8
+ } from '../../internal/recipes';
9
+
10
+ export function resolveButtonThemeRecipe(input: {
11
+ readonly color?: ZoraColor;
12
+ readonly variant?: ZoraButtonVariant;
13
+ readonly size?: ZoraControlSize;
14
+ readonly themeFields: Readonly<Record<string, ThemeRecipeOverrideValue>>;
15
+ }) {
16
+ return resolveButtonRecipe({
17
+ color: input.color ?? readColor(input.themeFields.color),
18
+ variant: input.variant ?? readVariant(input.themeFields.variant),
19
+ size: input.size ?? readSize(input.themeFields.size),
20
+ });
21
+ }
22
+
23
+ function readColor(value: ThemeRecipeOverrideValue | undefined): ZoraColor | undefined {
24
+ if (typeof value !== 'string') return undefined;
25
+ if (value === 'primary' || value === 'secondary' || value === 'tertiary') return value;
26
+ if (value === 'quaternary' || value === 'neutral' || value === 'danger') return value;
27
+ if (value === 'success' || value === 'warning' || value === 'error' || value === 'info')
28
+ return value;
29
+ return undefined;
30
+ }
31
+
32
+ function readVariant(value: ThemeRecipeOverrideValue | undefined): ZoraButtonVariant | undefined {
33
+ if (value === 'solid' || value === 'outline' || value === 'ghost' || value === 'soft')
34
+ return value;
35
+ return undefined;
36
+ }
37
+
38
+ function readSize(value: ThemeRecipeOverrideValue | undefined): ZoraControlSize | undefined {
39
+ if (value === 's' || value === 'm' || value === 'l') return value;
40
+ return undefined;
41
+ }
@@ -1,14 +1,15 @@
1
+ import { ZORA_COLORS } from '../../internal/colorModel';
1
2
  import type { ZoraThemeRecipeMeta } from '../../metadata/themeRecipeTypes';
2
3
 
3
4
  export const buttonThemeRecipeMeta = {
4
5
  name: 'Button',
5
6
  kind: 'component',
6
- description: 'Maps shared theme tokens and semantic choices into Button presentation.',
7
+ description: 'Maps shared semantic choices into Button presentation defaults.',
7
8
  fields: {
8
9
  color: {
9
- type: 'token',
10
- tokenFamily: 'colors',
10
+ type: 'choice',
11
11
  label: 'Color',
12
+ options: ZORA_COLORS,
12
13
  default: 'primary',
13
14
  },
14
15
  variant: {
@@ -22,13 +23,7 @@ export const buttonThemeRecipeMeta = {
22
23
  label: 'Size',
23
24
  description: 'A Button-specific semantic scale, not a universal pixel size.',
24
25
  options: ['s', 'm', 'l'],
25
- default: 'm',
26
- },
27
- radius: {
28
- type: 'token',
29
- tokenFamily: 'radii',
30
- label: 'Corner radius',
31
- default: 'm',
26
+ default: 'l',
32
27
  },
33
28
  },
34
29
  } as const satisfies ZoraThemeRecipeMeta;
@@ -3,9 +3,11 @@ import React from 'react';
3
3
 
4
4
  import { Box, Stack } from '../../foundation';
5
5
  import { resolveCardVariant } from '../../internal/recipes';
6
+ import { useZoraThemeRecipe } from '../../theme/useZoraThemeRecipe';
6
7
  import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
7
8
  import { Heading } from '../heading';
8
9
  import { Text } from '../text';
10
+ import { resolveCardThemeRecipe } from './resolveCardThemeRecipe';
9
11
  import type { CardProps } from './types';
10
12
 
11
13
  function CardInner({
@@ -17,15 +19,19 @@ function CardInner({
17
19
  eyebrow,
18
20
  actions,
19
21
  footer,
20
- tone = 'default',
21
- compact = false,
22
+ tone,
23
+ compact,
24
+ padding,
25
+ radius,
22
26
  onPress,
23
27
  interactionPolicy,
24
28
  ...props
25
29
  }: CardProps) {
30
+ const themeFields = useZoraThemeRecipe('Card');
31
+ const recipe = resolveCardThemeRecipe({ tone, compact, padding, radius, themeFields });
26
32
  const hasHeader = [eyebrow, title, description, actions].some((item) => item != null);
27
33
  const hasFooter = footer !== undefined;
28
- const gap = compact ? 's' : 'm';
34
+ const gap = recipe.compact ? 's' : 'm';
29
35
  const isInteractive = Boolean(onPress) && !actions;
30
36
  const passive = interactionPolicy === 'passive';
31
37
 
@@ -33,9 +39,9 @@ function CardInner({
33
39
  <SurfaceCard
34
40
  {...props}
35
41
  onPress={isInteractive && !passive ? onPress : undefined}
36
- p={compact ? 'm' : 'l'}
37
- radius="l"
38
- variant={resolveCardVariant(tone)}
42
+ p={recipe.padding}
43
+ radius={recipe.radius}
44
+ variant={resolveCardVariant(recipe.tone)}
39
45
  >
40
46
  <Stack gap={gap}>
41
47
  {hasHeader ? (
@@ -52,7 +58,7 @@ function CardInner({
52
58
  {eyebrow}
53
59
  </Text>
54
60
  ) : null}
55
- {title ? <Heading level={compact ? 4 : 3}>{title}</Heading> : null}
61
+ {title ? <Heading level={recipe.compact ? 4 : 3}>{title}</Heading> : null}
56
62
  {description ? (
57
63
  <Text emphasis="muted" variant="bodySmall">
58
64
  {description}
@@ -1,18 +1,18 @@
1
1
  import type { ZoraComponentMeta } from '../../metadata';
2
2
  import { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';
3
3
 
4
+ const themeAuthoring = {
5
+ authority: 'theme',
6
+ scope: 'component',
7
+ allowInstanceOverride: true,
8
+ } as const;
9
+
4
10
  export const cardMeta = {
5
11
  name: 'Card',
6
12
  category: 'component',
7
13
  directManifestNode: true,
8
14
  allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
9
- blueprint: {
10
- label: 'Card',
11
- defaultProps: {
12
- title: 'Card',
13
- tone: 'default',
14
- },
15
- },
15
+ blueprint: { label: 'Card', defaultProps: { title: 'Card' } },
16
16
  props: {
17
17
  title: {
18
18
  type: 'string',
@@ -37,15 +37,15 @@ export const cardMeta = {
37
37
  category: 'Style',
38
38
  label: 'Tone',
39
39
  enum: ['default', 'subtle', 'outline'],
40
- default: 'default',
41
- authoring: { authority: 'theme', scope: 'component' },
40
+ authoring: themeAuthoring,
42
41
  },
43
- compact: {
44
- type: 'boolean',
45
- category: 'Layout',
46
- label: 'Compact',
47
- default: false,
48
- authoring: { authority: 'theme', scope: 'component' },
42
+ compact: { type: 'boolean', category: 'Layout', label: 'Compact', authoring: themeAuthoring },
43
+ padding: { type: 'spacing', category: 'Layout', label: 'Padding', authoring: themeAuthoring },
44
+ radius: {
45
+ type: 'radius',
46
+ category: 'Style',
47
+ label: 'Corner radius',
48
+ authoring: themeAuthoring,
49
49
  },
50
50
  },
51
51
  } as const satisfies ZoraComponentMeta;