@ankhorage/zora 0.8.0 → 0.9.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 (54) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +53 -46
  3. package/dist/components/heading/Heading.d.ts.map +1 -1
  4. package/dist/components/heading/Heading.js +4 -12
  5. package/dist/components/heading/Heading.js.map +1 -1
  6. package/dist/components/text/Text.d.ts.map +1 -1
  7. package/dist/components/text/Text.js +4 -12
  8. package/dist/components/text/Text.js.map +1 -1
  9. package/dist/theme/ZoraProvider.d.ts +4 -4
  10. package/dist/theme/ZoraProvider.d.ts.map +1 -1
  11. package/dist/theme/ZoraProvider.js +4 -3
  12. package/dist/theme/ZoraProvider.js.map +1 -1
  13. package/dist/theme/createZoraThemeConfig.d.ts +4 -0
  14. package/dist/theme/createZoraThemeConfig.d.ts.map +1 -0
  15. package/dist/theme/createZoraThemeConfig.js +23 -0
  16. package/dist/theme/createZoraThemeConfig.js.map +1 -0
  17. package/dist/theme/index.d.ts +3 -3
  18. package/dist/theme/index.d.ts.map +1 -1
  19. package/dist/theme/index.js +2 -2
  20. package/dist/theme/index.js.map +1 -1
  21. package/dist/theme/types.d.ts +21 -0
  22. package/dist/theme/types.d.ts.map +1 -0
  23. package/dist/theme/types.js +2 -0
  24. package/dist/theme/types.js.map +1 -0
  25. package/dist/theme/zoraDefaultTheme.d.ts +3 -0
  26. package/dist/theme/zoraDefaultTheme.d.ts.map +1 -0
  27. package/dist/theme/zoraDefaultTheme.js +8 -0
  28. package/dist/theme/zoraDefaultTheme.js.map +1 -0
  29. package/package.json +1 -1
  30. package/src/components/contentFallback.test.ts +23 -0
  31. package/src/components/heading/Heading.tsx +3 -12
  32. package/src/components/text/Text.tsx +3 -12
  33. package/src/theme/ZoraProvider.tsx +7 -5
  34. package/src/theme/createZoraThemeConfig.test.ts +36 -0
  35. package/src/theme/createZoraThemeConfig.ts +27 -0
  36. package/src/theme/index.ts +11 -3
  37. package/src/theme/types.ts +33 -0
  38. package/src/theme/zoraDefaultTheme.ts +9 -0
  39. package/dist/internal/deepMerge.d.ts +0 -2
  40. package/dist/internal/deepMerge.d.ts.map +0 -1
  41. package/dist/internal/deepMerge.js +0 -20
  42. package/dist/internal/deepMerge.js.map +0 -1
  43. package/dist/theme/createZoraTheme.d.ts +0 -4
  44. package/dist/theme/createZoraTheme.d.ts.map +0 -1
  45. package/dist/theme/createZoraTheme.js +0 -6
  46. package/dist/theme/createZoraTheme.js.map +0 -1
  47. package/dist/theme/zoraTheme.d.ts +0 -3
  48. package/dist/theme/zoraTheme.d.ts.map +0 -1
  49. package/dist/theme/zoraTheme.js +0 -15
  50. package/dist/theme/zoraTheme.js.map +0 -1
  51. package/src/internal/deepMerge.ts +0 -23
  52. package/src/theme/createZoraTheme.test.ts +0 -25
  53. package/src/theme/createZoraTheme.ts +0 -10
  54. package/src/theme/zoraTheme.ts +0 -16
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3745d82: Introduces the ZORA theme seed model with `ZoraTheme`, `ZoraComputedTheme`, and
8
+ `zoraDefaultTheme`, replacing public override/config terminology with app-facing
9
+ theme terminology.
10
+
11
+ ## 0.8.1
12
+
13
+ ### Patch Changes
14
+
15
+ - f7e5fdc: Stop resolving localization internally in Text and Heading. Localization keys now remain passive fallback content so runtime integrations can resolve localized display props before rendering.
16
+
3
17
  ## 0.8.0
4
18
 
5
19
  ### Minor Changes
package/README.md CHANGED
@@ -122,21 +122,21 @@ responsive for mobile and web layouts.
122
122
 
123
123
  ZORA props:
124
124
 
125
- | Prop | Type | Default | Notes |
126
- | --------------- | ------------------------------------------- | ----------- | ------------------------------------------ |
127
- | `children` | `React.ReactNode` | - | Primary content. |
128
- | `text` | `string` | - | Manifest-friendly content prop. |
129
- | `i18nKey` | `string` | - | Translation key fallback. |
130
- | `level` | `HeadingLevel` | `2` | Semantic heading level from `1` through `6`. |
131
- | `size` | `Responsive<HeadingSize>` | level size | Visual scale: `display`, `h1` through `h6`. |
132
- | `tone` | `Responsive<HeadingTone>` | `'default'` | Semantic text color. |
133
- | `align` | `Responsive<HeadingAlign>` | - | Text alignment. |
134
- | `weight` | `Responsive<HeadingWeight>` | recipe | Optional structured weight override. |
135
- | `italic` | `boolean` | `false` | Italic style. |
136
- | `numberOfLines` | `number` | - | Native/web truncation line count. |
137
- | `ellipsizeMode` | `'head' \| 'middle' \| 'tail' \| 'clip'` | - | Truncation behavior. |
138
- | `selectable` | `boolean` | - | Allows text selection where supported. |
139
- | `testID` | `string` | - | Test id. |
125
+ | Prop | Type | Default | Notes |
126
+ | --------------- | ---------------------------------------- | ----------- | -------------------------------------------- |
127
+ | `children` | `React.ReactNode` | - | Primary content. |
128
+ | `text` | `string` | - | Manifest-friendly content prop. |
129
+ | `i18nKey` | `string` | - | Runtime-resolved fallback key when no content prop is provided. |
130
+ | `level` | `HeadingLevel` | `2` | Semantic heading level from `1` through `6`. |
131
+ | `size` | `Responsive<HeadingSize>` | level size | Visual scale: `display`, `h1` through `h6`. |
132
+ | `tone` | `Responsive<HeadingTone>` | `'default'` | Semantic text color. |
133
+ | `align` | `Responsive<HeadingAlign>` | - | Text alignment. |
134
+ | `weight` | `Responsive<HeadingWeight>` | recipe | Optional structured weight override. |
135
+ | `italic` | `boolean` | `false` | Italic style. |
136
+ | `numberOfLines` | `number` | - | Native/web truncation line count. |
137
+ | `ellipsizeMode` | `'head' \| 'middle' \| 'tail' \| 'clip'` | - | Truncation behavior. |
138
+ | `selectable` | `boolean` | - | Allows text selection where supported. |
139
+ | `testID` | `string` | - | Test id. |
140
140
 
141
141
  No inherited props. `HeadingProps` is declared directly by ZORA to keep heading
142
142
  usage structured and template-safe.
@@ -167,7 +167,7 @@ ZORA props:
167
167
  | --------------- | ---------------------------------------- | ----------- | -------------------------------------- |
168
168
  | `children` | `React.ReactNode` | - | Primary content. |
169
169
  | `text` | `string` | - | Manifest-friendly content prop. |
170
- | `i18nKey` | `string` | - | Translation key fallback. |
170
+ | `i18nKey` | `string` | - | Runtime-resolved fallback key when no content prop is provided. |
171
171
  | `variant` | `Responsive<TextVariant>` | `'body'` | Typography recipe. |
172
172
  | `tone` | `Responsive<TextTone>` | `'default'` | Semantic text color. |
173
173
  | `align` | `Responsive<TextAlign>` | - | Text alignment. |
@@ -1310,16 +1310,33 @@ Theme provider that creates the ZORA theme and passes it to Surface
1310
1310
  </ZoraProvider>
1311
1311
  ```
1312
1312
 
1313
+ Pass a theme seed to define your app theme:
1314
+
1315
+ ```tsx
1316
+ <ZoraProvider
1317
+ initialMode="dark"
1318
+ theme={{
1319
+ id: 'studio',
1320
+ name: 'Studio',
1321
+ primaryColor: '#0f766e',
1322
+ harmony: 'analogous',
1323
+ tone: 'jewel',
1324
+ }}
1325
+ >
1326
+ <App />
1327
+ </ZoraProvider>
1328
+ ```
1329
+
1313
1330
  <details>
1314
1331
  <summary>Props</summary>
1315
1332
 
1316
1333
  ZORA props:
1317
1334
 
1318
- | Prop | Type | Default | Notes |
1319
- | --------------- | ------------------- | --------- | --------------------------------------------------------------- |
1320
- | `children` | `React.ReactNode` | - | Required app content. |
1321
- | `initialConfig` | `ZoraThemeOverride` | - | Partial Surface `ThemeConfig` override merged into `zoraTheme`. |
1322
- | `initialMode` | `'light' \| 'dark'` | `'light'` | Initial theme mode passed to Surface. |
1335
+ | Prop | Type | Default | Notes |
1336
+ | ------------- | -------------------- | ------------------ | -------------------------------------- |
1337
+ | `children` | `React.ReactNode` | - | Required app content. |
1338
+ | `theme` | `ZoraTheme` | `zoraDefaultTheme` | App-facing theme seed for ZORA. |
1339
+ | `initialMode` | `'light' \| 'dark'` | `'light'` | Initial theme mode passed to Surface. |
1323
1340
 
1324
1341
  Inherited props:
1325
1342
 
@@ -1327,15 +1344,17 @@ No inherited props. `ZoraProviderProps` is declared directly by ZORA.
1327
1344
 
1328
1345
  </details>
1329
1346
 
1330
- ### `createZoraTheme`
1347
+ ### `createZoraThemeConfig`
1331
1348
 
1332
- Creates a Surface `ThemeConfig` by deep-merging overrides into `zoraTheme`.
1349
+ Creates a Surface-compatible `ThemeConfig` from a ZORA theme seed.
1333
1350
 
1334
1351
  ```tsx
1335
- const theme = createZoraTheme({
1336
- light: {
1337
- primaryColor: '#1d4ed8',
1338
- },
1352
+ const themeConfig = createZoraThemeConfig({
1353
+ id: 'studio',
1354
+ name: 'Studio',
1355
+ primaryColor: '#0f766e',
1356
+ harmony: 'analogous',
1357
+ tone: 'jewel',
1339
1358
  });
1340
1359
  ```
1341
1360
 
@@ -1343,37 +1362,25 @@ const theme = createZoraTheme({
1343
1362
  <summary>API</summary>
1344
1363
 
1345
1364
  ```ts
1346
- type ZoraThemeOverride = Partial<ThemeConfig>;
1347
-
1348
- function createZoraTheme(overrides?: ZoraThemeOverride): ThemeConfig;
1365
+ function createZoraThemeConfig(theme?: ZoraTheme): ThemeConfig;
1349
1366
  ```
1350
1367
 
1351
- The returned theme keeps `id: 'zora'` unless explicitly changed by the merge
1352
- input.
1353
-
1354
1368
  </details>
1355
1369
 
1356
- ### `zoraTheme`
1370
+ ### `zoraDefaultTheme`
1357
1371
 
1358
- Default ZORA Surface theme preset.
1372
+ Default ZORA theme seed.
1359
1373
 
1360
1374
  <details>
1361
1375
  <summary>Value</summary>
1362
1376
 
1363
1377
  ```ts
1364
- const zoraTheme: ThemeConfig = {
1378
+ const zoraDefaultTheme: ZoraTheme = {
1365
1379
  id: 'zora',
1366
1380
  name: 'ZORA',
1367
- light: {
1368
- primaryColor: '#0f766e',
1369
- harmony: 'analogous',
1370
- systemTone: 'jewel',
1371
- },
1372
- dark: {
1373
- primaryColor: '#2dd4bf',
1374
- harmony: 'analogous',
1375
- systemTone: 'jewel',
1376
- },
1381
+ primaryColor: '#0f766e',
1382
+ harmony: 'analogous',
1383
+ tone: 'jewel',
1377
1384
  };
1378
1385
  ```
1379
1386
 
@@ -1 +1 @@
1
- {"version":3,"file":"Heading.d.ts","sourceRoot":"","sources":["../../../src/components/heading/Heading.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAkC5C,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAS,EACT,IAAI,EACJ,IAAgB,EAChB,KAAK,EACL,MAAM,EACN,MAAc,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAA4B,EAC5B,QAAQ,EACR,MAAM,GACP,EAAE,YAAY,4BAoCd"}
1
+ {"version":3,"file":"Heading.d.ts","sourceRoot":"","sources":["../../../src/components/heading/Heading.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0B5C,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAS,EACT,IAAI,EACJ,IAAgB,EAChB,KAAK,EACL,MAAM,EACN,MAAc,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAA4B,EAC5B,QAAQ,EACR,MAAM,GACP,EAAE,YAAY,4BAmCd"}
@@ -1,9 +1,9 @@
1
- import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';
1
+ import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
  import { Text as ReactNativeText } from 'react-native';
4
4
  import { useZoraTheme } from '../../theme/useZoraTheme';
5
5
  import { resolveHeadingRecipe, resolveHeadingSizeFromLevel } from './resolveHeadingRecipe';
6
- function resolveHeadingContent({ children, text, i18nKey, translate, }) {
6
+ function resolveHeadingContent({ children, text, i18nKey, }) {
7
7
  if (children !== undefined) {
8
8
  return children;
9
9
  }
@@ -13,20 +13,12 @@ function resolveHeadingContent({ children, text, i18nKey, translate, }) {
13
13
  if (!i18nKey) {
14
14
  return null;
15
15
  }
16
- try {
17
- const translated = translate(i18nKey);
18
- return translated && translated !== i18nKey ? translated : i18nKey;
19
- }
20
- catch (error) {
21
- console.warn('[ZoraHeading] Translation error:', error);
22
- return i18nKey;
23
- }
16
+ return i18nKey;
24
17
  }
25
18
  export function Heading({ children, text, i18nKey, level = 2, size, tone = 'default', align, weight, italic = false, numberOfLines, ellipsizeMode, selectable, accessibilityLabel, accessibilityHint, accessibilityRole = 'header', nativeID, testID, }) {
26
19
  const { theme } = useZoraTheme();
27
20
  const { breakpoint } = useResponsiveRuntime();
28
- const { t } = useTranslationContext();
29
- const content = resolveHeadingContent({ children, text, i18nKey, translate: t });
21
+ const content = resolveHeadingContent({ children, text, i18nKey });
30
22
  const resolvedSize = resolveResponsive(size, breakpoint) ?? resolveHeadingSizeFromLevel(level);
31
23
  const resolvedTone = resolveResponsive(tone, breakpoint) ?? 'default';
32
24
  const resolvedAlign = resolveResponsive(align, breakpoint);
@@ -1 +1 @@
1
- {"version":3,"file":"Heading.js","sourceRoot":"","sources":["../../../src/components/heading/Heading.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAG3F,SAAS,qBAAqB,CAAC,EAC7B,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,SAAS,GAMV;IACC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,UAAU,IAAI,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EACtB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,GAAG,CAAC,EACT,IAAI,EACJ,IAAI,GAAG,SAAS,EAChB,KAAK,EACL,MAAM,EACN,MAAM,GAAG,KAAK,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAAG,QAAQ,EAC5B,QAAQ,EACR,MAAM,GACO;IACb,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,EAAE,CAAC,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,qBAAqB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IACjF,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAC/F,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC;IACtE,MAAM,aAAa,GAAG,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE7D,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,CAAC,eAAe,CACd,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,KAAK,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE;YACjC,KAAK,EAAE,aAAa;YACpB,MAAM;YACN,KAAK;YACL,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,cAAc;SACvB,CAAC,CAAC,CAEH;MAAA,CAAC,OAAO,CACV;IAAA,EAAE,eAAe,CAAC,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';\nimport React from 'react';\nimport { Text as ReactNativeText } from 'react-native';\n\nimport { useZoraTheme } from '../../theme/useZoraTheme';\nimport { resolveHeadingRecipe, resolveHeadingSizeFromLevel } from './resolveHeadingRecipe';\nimport type { HeadingProps } from './types';\n\nfunction resolveHeadingContent({\n children,\n text,\n i18nKey,\n translate,\n}: {\n children: HeadingProps['children'];\n text: HeadingProps['text'];\n i18nKey: HeadingProps['i18nKey'];\n translate: (key: string) => string;\n}): React.ReactNode {\n if (children !== undefined) {\n return children;\n }\n\n if (text !== undefined) {\n return text;\n }\n\n if (!i18nKey) {\n return null;\n }\n\n try {\n const translated = translate(i18nKey);\n return translated && translated !== i18nKey ? translated : i18nKey;\n } catch (error) {\n console.warn('[ZoraHeading] Translation error:', error);\n return i18nKey;\n }\n}\n\nexport function Heading({\n children,\n text,\n i18nKey,\n level = 2,\n size,\n tone = 'default',\n align,\n weight,\n italic = false,\n numberOfLines,\n ellipsizeMode,\n selectable,\n accessibilityLabel,\n accessibilityHint,\n accessibilityRole = 'header',\n nativeID,\n testID,\n}: HeadingProps) {\n const { theme } = useZoraTheme();\n const { breakpoint } = useResponsiveRuntime();\n const { t } = useTranslationContext();\n const content = resolveHeadingContent({ children, text, i18nKey, translate: t });\n const resolvedSize = resolveResponsive(size, breakpoint) ?? resolveHeadingSizeFromLevel(level);\n const resolvedTone = resolveResponsive(tone, breakpoint) ?? 'default';\n const resolvedAlign = resolveResponsive(align, breakpoint);\n const resolvedWeight = resolveResponsive(weight, breakpoint);\n\n if (content === null || content === undefined) {\n return null;\n }\n\n return (\n <ReactNativeText\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole={accessibilityRole}\n ellipsizeMode={ellipsizeMode}\n nativeID={nativeID}\n numberOfLines={numberOfLines}\n selectable={selectable}\n testID={testID}\n style={resolveHeadingRecipe(theme, {\n align: resolvedAlign,\n italic,\n level,\n size: resolvedSize,\n tone: resolvedTone,\n weight: resolvedWeight,\n })}\n >\n {content}\n </ReactNativeText>\n );\n}\n"]}
1
+ {"version":3,"file":"Heading.js","sourceRoot":"","sources":["../../../src/components/heading/Heading.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAG3F,SAAS,qBAAqB,CAAC,EAC7B,QAAQ,EACR,IAAI,EACJ,OAAO,GAKR;IACC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EACtB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,GAAG,CAAC,EACT,IAAI,EACJ,IAAI,GAAG,SAAS,EAChB,KAAK,EACL,MAAM,EACN,MAAM,GAAG,KAAK,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAAG,QAAQ,EAC5B,QAAQ,EACR,MAAM,GACO;IACb,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,qBAAqB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAC/F,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC;IACtE,MAAM,aAAa,GAAG,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE7D,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,CAAC,eAAe,CACd,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,KAAK,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE;YACjC,KAAK,EAAE,aAAa;YACpB,MAAM;YACN,KAAK;YACL,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,cAAc;SACvB,CAAC,CAAC,CAEH;MAAA,CAAC,OAAO,CACV;IAAA,EAAE,eAAe,CAAC,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';\nimport React from 'react';\nimport { Text as ReactNativeText } from 'react-native';\n\nimport { useZoraTheme } from '../../theme/useZoraTheme';\nimport { resolveHeadingRecipe, resolveHeadingSizeFromLevel } from './resolveHeadingRecipe';\nimport type { HeadingProps } from './types';\n\nfunction resolveHeadingContent({\n children,\n text,\n i18nKey,\n}: {\n children: HeadingProps['children'];\n text: HeadingProps['text'];\n i18nKey: HeadingProps['i18nKey'];\n}): React.ReactNode {\n if (children !== undefined) {\n return children;\n }\n\n if (text !== undefined) {\n return text;\n }\n\n if (!i18nKey) {\n return null;\n }\n\n return i18nKey;\n}\n\nexport function Heading({\n children,\n text,\n i18nKey,\n level = 2,\n size,\n tone = 'default',\n align,\n weight,\n italic = false,\n numberOfLines,\n ellipsizeMode,\n selectable,\n accessibilityLabel,\n accessibilityHint,\n accessibilityRole = 'header',\n nativeID,\n testID,\n}: HeadingProps) {\n const { theme } = useZoraTheme();\n const { breakpoint } = useResponsiveRuntime();\n const content = resolveHeadingContent({ children, text, i18nKey });\n const resolvedSize = resolveResponsive(size, breakpoint) ?? resolveHeadingSizeFromLevel(level);\n const resolvedTone = resolveResponsive(tone, breakpoint) ?? 'default';\n const resolvedAlign = resolveResponsive(align, breakpoint);\n const resolvedWeight = resolveResponsive(weight, breakpoint);\n\n if (content === null || content === undefined) {\n return null;\n }\n\n return (\n <ReactNativeText\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole={accessibilityRole}\n ellipsizeMode={ellipsizeMode}\n nativeID={nativeID}\n numberOfLines={numberOfLines}\n selectable={selectable}\n testID={testID}\n style={resolveHeadingRecipe(theme, {\n align: resolvedAlign,\n italic,\n level,\n size: resolvedSize,\n tone: resolvedTone,\n weight: resolvedWeight,\n })}\n >\n {content}\n </ReactNativeText>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/components/text/Text.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAkCzC,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,OAAgB,EAChB,IAAgB,EAChB,KAAK,EACL,MAAM,EACN,MAAc,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,MAAM,GACP,EAAE,SAAS,4BAmCX"}
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/components/text/Text.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AA0BzC,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,OAAgB,EAChB,IAAgB,EAChB,KAAK,EACL,MAAM,EACN,MAAc,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,MAAM,GACP,EAAE,SAAS,4BAkCX"}
@@ -1,9 +1,9 @@
1
- import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';
1
+ import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
  import { Text as ReactNativeText } from 'react-native';
4
4
  import { useZoraTheme } from '../../theme/useZoraTheme';
5
5
  import { resolveTextStyle } from './resolveTextRecipe';
6
- function resolveTextContent({ children, text, i18nKey, translate, }) {
6
+ function resolveTextContent({ children, text, i18nKey, }) {
7
7
  if (children !== undefined) {
8
8
  return children;
9
9
  }
@@ -13,20 +13,12 @@ function resolveTextContent({ children, text, i18nKey, translate, }) {
13
13
  if (!i18nKey) {
14
14
  return null;
15
15
  }
16
- try {
17
- const translated = translate(i18nKey);
18
- return translated && translated !== i18nKey ? translated : i18nKey;
19
- }
20
- catch (error) {
21
- console.warn('[ZoraText] Translation error:', error);
22
- return i18nKey;
23
- }
16
+ return i18nKey;
24
17
  }
25
18
  export function Text({ children, text, i18nKey, variant = 'body', tone = 'default', align, weight, italic = false, numberOfLines, ellipsizeMode, selectable, accessibilityLabel, accessibilityHint, accessibilityRole, nativeID, testID, }) {
26
19
  const { theme } = useZoraTheme();
27
20
  const { breakpoint } = useResponsiveRuntime();
28
- const { t } = useTranslationContext();
29
- const content = resolveTextContent({ children, text, i18nKey, translate: t });
21
+ const content = resolveTextContent({ children, text, i18nKey });
30
22
  const resolvedVariant = resolveResponsive(variant, breakpoint) ?? 'body';
31
23
  const resolvedStyle = resolveTextStyle({
32
24
  theme,
@@ -1 +1 @@
1
- {"version":3,"file":"Text.js","sourceRoot":"","sources":["../../../src/components/text/Text.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,SAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,SAAS,GAMV;IACC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,UAAU,IAAI,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;IACrE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,OAAO,GAAG,MAAM,EAChB,IAAI,GAAG,SAAS,EAChB,KAAK,EACL,MAAM,EACN,MAAM,GAAG,KAAK,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,MAAM,GACI;IACV,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,EAAE,CAAC,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC;IACzE,MAAM,aAAa,GAAG,gBAAgB,CAAC;QACrC,KAAK;QACL,UAAU;QACV,OAAO,EAAE,eAAe;QACxB,IAAI;QACJ,KAAK;QACL,MAAM;QACN,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,CAAC,eAAe,CACd,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,KAAK,CAAC,CAAC,aAAa,CAAC,CAErB;MAAA,CAAC,OAAO,CACV;IAAA,EAAE,eAAe,CAAC,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';\nimport React from 'react';\nimport { Text as ReactNativeText } from 'react-native';\n\nimport { useZoraTheme } from '../../theme/useZoraTheme';\nimport { resolveTextStyle } from './resolveTextRecipe';\nimport type { TextProps } from './types';\n\nfunction resolveTextContent({\n children,\n text,\n i18nKey,\n translate,\n}: {\n children: TextProps['children'];\n text: TextProps['text'];\n i18nKey: TextProps['i18nKey'];\n translate: (key: string) => string;\n}): React.ReactNode {\n if (children !== undefined) {\n return children;\n }\n\n if (text !== undefined) {\n return text;\n }\n\n if (!i18nKey) {\n return null;\n }\n\n try {\n const translated = translate(i18nKey);\n return translated && translated !== i18nKey ? translated : i18nKey;\n } catch (error) {\n console.warn('[ZoraText] Translation error:', error);\n return i18nKey;\n }\n}\n\nexport function Text({\n children,\n text,\n i18nKey,\n variant = 'body',\n tone = 'default',\n align,\n weight,\n italic = false,\n numberOfLines,\n ellipsizeMode,\n selectable,\n accessibilityLabel,\n accessibilityHint,\n accessibilityRole,\n nativeID,\n testID,\n}: TextProps) {\n const { theme } = useZoraTheme();\n const { breakpoint } = useResponsiveRuntime();\n const { t } = useTranslationContext();\n const content = resolveTextContent({ children, text, i18nKey, translate: t });\n const resolvedVariant = resolveResponsive(variant, breakpoint) ?? 'body';\n const resolvedStyle = resolveTextStyle({\n theme,\n breakpoint,\n variant: resolvedVariant,\n tone,\n align,\n weight,\n italic,\n });\n\n if (content === null || content === undefined) {\n return null;\n }\n\n return (\n <ReactNativeText\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole={accessibilityRole}\n ellipsizeMode={ellipsizeMode}\n nativeID={nativeID}\n numberOfLines={numberOfLines}\n selectable={selectable}\n testID={testID}\n style={resolvedStyle}\n >\n {content}\n </ReactNativeText>\n );\n}\n"]}
1
+ {"version":3,"file":"Text.js","sourceRoot":"","sources":["../../../src/components/text/Text.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,SAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,IAAI,EACJ,OAAO,GAKR;IACC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,OAAO,GAAG,MAAM,EAChB,IAAI,GAAG,SAAS,EAChB,KAAK,EACL,MAAM,EACN,MAAM,GAAG,KAAK,EACd,aAAa,EACb,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,MAAM,GACI;IACV,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC;IACzE,MAAM,aAAa,GAAG,gBAAgB,CAAC;QACrC,KAAK;QACL,UAAU;QACV,OAAO,EAAE,eAAe;QACxB,IAAI;QACJ,KAAK;QACL,MAAM;QACN,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,CAAC,eAAe,CACd,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,KAAK,CAAC,CAAC,aAAa,CAAC,CAErB;MAAA,CAAC,OAAO,CACV;IAAA,EAAE,eAAe,CAAC,CACnB,CAAC;AACJ,CAAC","sourcesContent":["import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';\nimport React from 'react';\nimport { Text as ReactNativeText } from 'react-native';\n\nimport { useZoraTheme } from '../../theme/useZoraTheme';\nimport { resolveTextStyle } from './resolveTextRecipe';\nimport type { TextProps } from './types';\n\nfunction resolveTextContent({\n children,\n text,\n i18nKey,\n}: {\n children: TextProps['children'];\n text: TextProps['text'];\n i18nKey: TextProps['i18nKey'];\n}): React.ReactNode {\n if (children !== undefined) {\n return children;\n }\n\n if (text !== undefined) {\n return text;\n }\n\n if (!i18nKey) {\n return null;\n }\n\n return i18nKey;\n}\n\nexport function Text({\n children,\n text,\n i18nKey,\n variant = 'body',\n tone = 'default',\n align,\n weight,\n italic = false,\n numberOfLines,\n ellipsizeMode,\n selectable,\n accessibilityLabel,\n accessibilityHint,\n accessibilityRole,\n nativeID,\n testID,\n}: TextProps) {\n const { theme } = useZoraTheme();\n const { breakpoint } = useResponsiveRuntime();\n const content = resolveTextContent({ children, text, i18nKey });\n const resolvedVariant = resolveResponsive(variant, breakpoint) ?? 'body';\n const resolvedStyle = resolveTextStyle({\n theme,\n breakpoint,\n variant: resolvedVariant,\n tone,\n align,\n weight,\n italic,\n });\n\n if (content === null || content === undefined) {\n return null;\n }\n\n return (\n <ReactNativeText\n accessibilityHint={accessibilityHint}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole={accessibilityRole}\n ellipsizeMode={ellipsizeMode}\n nativeID={nativeID}\n numberOfLines={numberOfLines}\n selectable={selectable}\n testID={testID}\n style={resolvedStyle}\n >\n {content}\n </ReactNativeText>\n );\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import { type ZoraThemeOverride } from './createZoraTheme';
2
+ import type { ZoraTheme, ZoraThemeMode } from './types';
3
3
  export interface ZoraProviderProps {
4
4
  children: React.ReactNode;
5
- initialConfig?: ZoraThemeOverride;
6
- initialMode?: 'light' | 'dark';
5
+ theme?: ZoraTheme;
6
+ initialMode?: ZoraThemeMode;
7
7
  }
8
- export declare function ZoraProvider({ children, initialConfig, initialMode, }: ZoraProviderProps): React.JSX.Element;
8
+ export declare function ZoraProvider({ children, theme, initialMode, }: ZoraProviderProps): React.JSX.Element;
9
9
  //# 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;AAE1B,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAChC;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,aAAa,EACb,WAAqB,GACtB,EAAE,iBAAiB,qBAMnB"}
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;AAGxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAwB,EACxB,WAAqB,GACtB,EAAE,iBAAiB,qBAMnB"}
@@ -1,8 +1,9 @@
1
1
  import { ResponsiveProvider, ThemeProvider } from '@ankhorage/surface';
2
2
  import React from 'react';
3
- import { createZoraTheme } from './createZoraTheme';
4
- export function ZoraProvider({ children, initialConfig, initialMode = 'light', }) {
5
- return (<ThemeProvider initialConfig={createZoraTheme(initialConfig)} initialMode={initialMode}>
3
+ import { createZoraThemeConfig } from './createZoraThemeConfig';
4
+ import { zoraDefaultTheme } from './zoraDefaultTheme';
5
+ export function ZoraProvider({ children, theme = zoraDefaultTheme, initialMode = 'light', }) {
6
+ return (<ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>
6
7
  <ResponsiveProvider>{children}</ResponsiveProvider>
7
8
  </ThemeProvider>);
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,eAAe,EAA0B,MAAM,mBAAmB,CAAC;AAQ5E,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,aAAa,EACb,WAAW,GAAG,OAAO,GACH;IAClB,OAAO,CACL,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACrF;MAAA,CAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CACpD;IAAA,EAAE,aAAa,CAAC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { ResponsiveProvider, ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraTheme, type ZoraThemeOverride } from './createZoraTheme';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n initialConfig?: ZoraThemeOverride;\n initialMode?: 'light' | 'dark';\n}\n\nexport function ZoraProvider({\n children,\n initialConfig,\n initialMode = 'light',\n}: ZoraProviderProps) {\n return (\n <ThemeProvider initialConfig={createZoraTheme(initialConfig)} initialMode={initialMode}>\n <ResponsiveProvider>{children}</ResponsiveProvider>\n </ThemeProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAQtD,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,GAAG,gBAAgB,EACxB,WAAW,GAAG,OAAO,GACH;IAClB,OAAO,CACL,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACnF;MAAA,CAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CACpD;IAAA,EAAE,aAAa,CAAC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { ResponsiveProvider, ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport type { ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n theme?: ZoraTheme;\n initialMode?: ZoraThemeMode;\n}\n\nexport function ZoraProvider({\n children,\n theme = zoraDefaultTheme,\n initialMode = 'light',\n}: ZoraProviderProps) {\n return (\n <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>\n <ResponsiveProvider>{children}</ResponsiveProvider>\n </ThemeProvider>\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { ThemeConfig } from '@ankhorage/surface';
2
+ import type { ZoraTheme } from './types';
3
+ export declare function createZoraThemeConfig(theme?: ZoraTheme): ThemeConfig;
4
+ //# sourceMappingURL=createZoraThemeConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createZoraThemeConfig.d.ts","sourceRoot":"","sources":["../../src/theme/createZoraThemeConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAgB,SAAS,EAAiB,MAAM,SAAS,CAAC;AAStE,wBAAgB,qBAAqB,CAAC,KAAK,GAAE,SAA4B,GAAG,WAAW,CAetF"}
@@ -0,0 +1,23 @@
1
+ import { zoraDefaultTheme } from './zoraDefaultTheme';
2
+ function resolveModePrimaryColor(primaryColor, _mode) {
3
+ // Intentionally conservative in Plan 1: mode-specific primary derivation
4
+ // (OKLCH/lightness scale, etc.) comes in later theme-engine work.
5
+ return primaryColor;
6
+ }
7
+ export function createZoraThemeConfig(theme = zoraDefaultTheme) {
8
+ return {
9
+ id: theme.id,
10
+ name: theme.name ?? theme.id,
11
+ light: {
12
+ primaryColor: resolveModePrimaryColor(theme.primaryColor, 'light'),
13
+ harmony: theme.harmony,
14
+ systemTone: theme.tone,
15
+ },
16
+ dark: {
17
+ primaryColor: resolveModePrimaryColor(theme.primaryColor, 'dark'),
18
+ harmony: theme.harmony,
19
+ systemTone: theme.tone,
20
+ },
21
+ };
22
+ }
23
+ //# sourceMappingURL=createZoraThemeConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createZoraThemeConfig.js","sourceRoot":"","sources":["../../src/theme/createZoraThemeConfig.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,SAAS,uBAAuB,CAAC,YAA0B,EAAE,KAAoB;IAC/E,yEAAyE;IACzE,kEAAkE;IAClE,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAmB,gBAAgB;IACvE,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE;QAC5B,KAAK,EAAE;YACL,YAAY,EAAE,uBAAuB,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC;YAClE,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,IAAI;SACvB;QACD,IAAI,EAAE;YACJ,YAAY,EAAE,uBAAuB,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC;YACjE,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,IAAI;SACvB;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/surface';\n\nimport type { ZoraHexColor, ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\n\nfunction resolveModePrimaryColor(primaryColor: ZoraHexColor, _mode: ZoraThemeMode): ZoraHexColor {\n // Intentionally conservative in Plan 1: mode-specific primary derivation\n // (OKLCH/lightness scale, etc.) comes in later theme-engine work.\n return primaryColor;\n}\n\nexport function createZoraThemeConfig(theme: ZoraTheme = zoraDefaultTheme): ThemeConfig {\n return {\n id: theme.id,\n name: theme.name ?? theme.id,\n light: {\n primaryColor: resolveModePrimaryColor(theme.primaryColor, 'light'),\n harmony: theme.harmony,\n systemTone: theme.tone,\n },\n dark: {\n primaryColor: resolveModePrimaryColor(theme.primaryColor, 'dark'),\n harmony: theme.harmony,\n systemTone: theme.tone,\n },\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
- export type { ZoraThemeOverride } from './createZoraTheme';
2
- export { createZoraTheme } from './createZoraTheme';
1
+ export { createZoraThemeConfig } from './createZoraThemeConfig';
2
+ export type { ZoraColorHarmony, ZoraColorTone, ZoraComputedTheme, ZoraHexColor, ZoraTheme, ZoraThemeId, ZoraThemeMode, } from './types';
3
3
  export { useZoraTheme } from './useZoraTheme';
4
+ export { zoraDefaultTheme } from './zoraDefaultTheme';
4
5
  export type { ZoraProviderProps } from './ZoraProvider';
5
6
  export { ZoraProvider } from './ZoraProvider';
6
- export { zoraTheme } from './zoraTheme';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,5 +1,5 @@
1
- export { createZoraTheme } from './createZoraTheme';
1
+ export { createZoraThemeConfig } from './createZoraThemeConfig';
2
2
  export { useZoraTheme } from './useZoraTheme';
3
+ export { zoraDefaultTheme } from './zoraDefaultTheme';
3
4
  export { ZoraProvider } from './ZoraProvider';
4
- export { zoraTheme } from './zoraTheme';
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export type { ZoraThemeOverride } from './createZoraTheme';\nexport { createZoraTheme } from './createZoraTheme';\nexport { useZoraTheme } from './useZoraTheme';\nexport type { ZoraProviderProps } from './ZoraProvider';\nexport { ZoraProvider } from './ZoraProvider';\nexport { zoraTheme } from './zoraTheme';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAUhE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { createZoraThemeConfig } from './createZoraThemeConfig';\nexport type {\n ZoraColorHarmony,\n ZoraColorTone,\n ZoraComputedTheme,\n ZoraHexColor,\n ZoraTheme,\n ZoraThemeId,\n ZoraThemeMode,\n} from './types';\nexport { useZoraTheme } from './useZoraTheme';\nexport { zoraDefaultTheme } from './zoraDefaultTheme';\nexport type { ZoraProviderProps } from './ZoraProvider';\nexport { ZoraProvider } from './ZoraProvider';\n"]}
@@ -0,0 +1,21 @@
1
+ import type { ThemeConfig } from '@ankhorage/surface';
2
+ export type ZoraThemeId = string;
3
+ export type ZoraThemeMode = 'light' | 'dark';
4
+ export type ZoraHexColor = `#${string}`;
5
+ export type ZoraColorHarmony = 'monochromatic' | 'analogous' | 'complementary' | 'splitComplementary' | 'triadic' | 'tetradic';
6
+ export type ZoraColorTone = 'neutral' | 'pastel' | 'earth' | 'jewel' | 'fluorescent';
7
+ export interface ZoraTheme {
8
+ id: ZoraThemeId;
9
+ name?: string;
10
+ primaryColor: ZoraHexColor;
11
+ harmony: ZoraColorHarmony;
12
+ tone: ZoraColorTone;
13
+ }
14
+ export interface ZoraComputedTheme {
15
+ id: ZoraThemeId;
16
+ name: string;
17
+ mode: ZoraThemeMode;
18
+ source: ZoraTheme;
19
+ surfaceConfig: ThemeConfig;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,IAAI,MAAM,EAAE,CAAC;AAExC,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,WAAW,GACX,eAAe,GACf,oBAAoB,GACpB,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;AAErF,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,SAAS,CAAC;IAClB,aAAa,EAAE,WAAW,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/theme/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ThemeConfig } from '@ankhorage/surface';\n\nexport type ZoraThemeId = string;\n\nexport type ZoraThemeMode = 'light' | 'dark';\n\nexport type ZoraHexColor = `#${string}`;\n\nexport type ZoraColorHarmony =\n | 'monochromatic'\n | 'analogous'\n | 'complementary'\n | 'splitComplementary'\n | 'triadic'\n | 'tetradic';\n\nexport type ZoraColorTone = 'neutral' | 'pastel' | 'earth' | 'jewel' | 'fluorescent';\n\nexport interface ZoraTheme {\n id: ZoraThemeId;\n name?: string;\n primaryColor: ZoraHexColor;\n harmony: ZoraColorHarmony;\n tone: ZoraColorTone;\n}\n\nexport interface ZoraComputedTheme {\n id: ZoraThemeId;\n name: string;\n mode: ZoraThemeMode;\n source: ZoraTheme;\n surfaceConfig: ThemeConfig;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ZoraTheme } from './types';
2
+ export declare const zoraDefaultTheme: ZoraTheme;
3
+ //# sourceMappingURL=zoraDefaultTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoraDefaultTheme.d.ts","sourceRoot":"","sources":["../../src/theme/zoraDefaultTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,SAM9B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const zoraDefaultTheme = {
2
+ id: 'zora',
3
+ name: 'ZORA',
4
+ primaryColor: '#0f766e',
5
+ harmony: 'analogous',
6
+ tone: 'jewel',
7
+ };
8
+ //# sourceMappingURL=zoraDefaultTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoraDefaultTheme.js","sourceRoot":"","sources":["../../src/theme/zoraDefaultTheme.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAc;IACzC,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,MAAM;IACZ,YAAY,EAAE,SAAS;IACvB,OAAO,EAAE,WAAW;IACpB,IAAI,EAAE,OAAO;CACd,CAAC","sourcesContent":["import type { ZoraTheme } from './types';\n\nexport const zoraDefaultTheme: ZoraTheme = {\n id: 'zora',\n name: 'ZORA',\n primaryColor: '#0f766e',\n harmony: 'analogous',\n tone: 'jewel',\n};\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "0.8.0",
4
+ "version": "0.9.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": {
@@ -0,0 +1,23 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ import { describe, expect, it } from 'bun:test';
5
+
6
+ const textSource = readFileSync(join(import.meta.dir, 'text', 'Text.tsx'), 'utf8');
7
+ const headingSource = readFileSync(join(import.meta.dir, 'heading', 'Heading.tsx'), 'utf8');
8
+
9
+ describe('content fallback ownership', () => {
10
+ it('keeps Text free of translation context coupling', () => {
11
+ expect(textSource).not.toMatch(/useTranslationContext/);
12
+ expect(textSource).toMatch(/if \(children !== undefined\) \{/);
13
+ expect(textSource).toMatch(/if \(text !== undefined\) \{/);
14
+ expect(textSource).toMatch(/return i18nKey;/);
15
+ });
16
+
17
+ it('keeps Heading free of translation context coupling', () => {
18
+ expect(headingSource).not.toMatch(/useTranslationContext/);
19
+ expect(headingSource).toMatch(/if \(children !== undefined\) \{/);
20
+ expect(headingSource).toMatch(/if \(text !== undefined\) \{/);
21
+ expect(headingSource).toMatch(/return i18nKey;/);
22
+ });
23
+ });
@@ -1,4 +1,4 @@
1
- import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';
1
+ import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
  import { Text as ReactNativeText } from 'react-native';
4
4
 
@@ -10,12 +10,10 @@ function resolveHeadingContent({
10
10
  children,
11
11
  text,
12
12
  i18nKey,
13
- translate,
14
13
  }: {
15
14
  children: HeadingProps['children'];
16
15
  text: HeadingProps['text'];
17
16
  i18nKey: HeadingProps['i18nKey'];
18
- translate: (key: string) => string;
19
17
  }): React.ReactNode {
20
18
  if (children !== undefined) {
21
19
  return children;
@@ -29,13 +27,7 @@ function resolveHeadingContent({
29
27
  return null;
30
28
  }
31
29
 
32
- try {
33
- const translated = translate(i18nKey);
34
- return translated && translated !== i18nKey ? translated : i18nKey;
35
- } catch (error) {
36
- console.warn('[ZoraHeading] Translation error:', error);
37
- return i18nKey;
38
- }
30
+ return i18nKey;
39
31
  }
40
32
 
41
33
  export function Heading({
@@ -59,8 +51,7 @@ export function Heading({
59
51
  }: HeadingProps) {
60
52
  const { theme } = useZoraTheme();
61
53
  const { breakpoint } = useResponsiveRuntime();
62
- const { t } = useTranslationContext();
63
- const content = resolveHeadingContent({ children, text, i18nKey, translate: t });
54
+ const content = resolveHeadingContent({ children, text, i18nKey });
64
55
  const resolvedSize = resolveResponsive(size, breakpoint) ?? resolveHeadingSizeFromLevel(level);
65
56
  const resolvedTone = resolveResponsive(tone, breakpoint) ?? 'default';
66
57
  const resolvedAlign = resolveResponsive(align, breakpoint);
@@ -1,4 +1,4 @@
1
- import { resolveResponsive, useResponsiveRuntime, useTranslationContext } from '@ankhorage/surface';
1
+ import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
  import { Text as ReactNativeText } from 'react-native';
4
4
 
@@ -10,12 +10,10 @@ function resolveTextContent({
10
10
  children,
11
11
  text,
12
12
  i18nKey,
13
- translate,
14
13
  }: {
15
14
  children: TextProps['children'];
16
15
  text: TextProps['text'];
17
16
  i18nKey: TextProps['i18nKey'];
18
- translate: (key: string) => string;
19
17
  }): React.ReactNode {
20
18
  if (children !== undefined) {
21
19
  return children;
@@ -29,13 +27,7 @@ function resolveTextContent({
29
27
  return null;
30
28
  }
31
29
 
32
- try {
33
- const translated = translate(i18nKey);
34
- return translated && translated !== i18nKey ? translated : i18nKey;
35
- } catch (error) {
36
- console.warn('[ZoraText] Translation error:', error);
37
- return i18nKey;
38
- }
30
+ return i18nKey;
39
31
  }
40
32
 
41
33
  export function Text({
@@ -58,8 +50,7 @@ export function Text({
58
50
  }: TextProps) {
59
51
  const { theme } = useZoraTheme();
60
52
  const { breakpoint } = useResponsiveRuntime();
61
- const { t } = useTranslationContext();
62
- const content = resolveTextContent({ children, text, i18nKey, translate: t });
53
+ const content = resolveTextContent({ children, text, i18nKey });
63
54
  const resolvedVariant = resolveResponsive(variant, breakpoint) ?? 'body';
64
55
  const resolvedStyle = resolveTextStyle({
65
56
  theme,
@@ -1,21 +1,23 @@
1
1
  import { ResponsiveProvider, ThemeProvider } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
- import { createZoraTheme, type ZoraThemeOverride } from './createZoraTheme';
4
+ import { createZoraThemeConfig } from './createZoraThemeConfig';
5
+ import type { ZoraTheme, ZoraThemeMode } from './types';
6
+ import { zoraDefaultTheme } from './zoraDefaultTheme';
5
7
 
6
8
  export interface ZoraProviderProps {
7
9
  children: React.ReactNode;
8
- initialConfig?: ZoraThemeOverride;
9
- initialMode?: 'light' | 'dark';
10
+ theme?: ZoraTheme;
11
+ initialMode?: ZoraThemeMode;
10
12
  }
11
13
 
12
14
  export function ZoraProvider({
13
15
  children,
14
- initialConfig,
16
+ theme = zoraDefaultTheme,
15
17
  initialMode = 'light',
16
18
  }: ZoraProviderProps) {
17
19
  return (
18
- <ThemeProvider initialConfig={createZoraTheme(initialConfig)} initialMode={initialMode}>
20
+ <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>
19
21
  <ResponsiveProvider>{children}</ResponsiveProvider>
20
22
  </ThemeProvider>
21
23
  );
@@ -0,0 +1,36 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+
3
+ import { createZoraThemeConfig } from './createZoraThemeConfig';
4
+
5
+ describe('createZoraThemeConfig', () => {
6
+ test('converts the default theme seed into a surface config', () => {
7
+ const themeConfig = createZoraThemeConfig();
8
+
9
+ expect(themeConfig.id).toBe('zora');
10
+ expect(themeConfig.name).toBe('ZORA');
11
+ expect(themeConfig.light.primaryColor).toBe('#0f766e');
12
+ expect(themeConfig.light.harmony).toBe('analogous');
13
+ expect(themeConfig.light.systemTone).toBe('jewel');
14
+ expect(themeConfig.dark.primaryColor).toBe('#0f766e');
15
+ expect(themeConfig.dark.harmony).toBe('analogous');
16
+ expect(themeConfig.dark.systemTone).toBe('jewel');
17
+ });
18
+
19
+ test('falls back to id when name is omitted', () => {
20
+ const themeConfig = createZoraThemeConfig({
21
+ id: 'studio',
22
+ primaryColor: '#0f766e',
23
+ harmony: 'analogous',
24
+ tone: 'jewel',
25
+ });
26
+
27
+ expect(themeConfig.id).toBe('studio');
28
+ expect(themeConfig.name).toBe('studio');
29
+ expect(themeConfig.light.primaryColor).toBe('#0f766e');
30
+ expect(themeConfig.light.harmony).toBe('analogous');
31
+ expect(themeConfig.light.systemTone).toBe('jewel');
32
+ expect(themeConfig.dark.primaryColor).toBe('#0f766e');
33
+ expect(themeConfig.dark.harmony).toBe('analogous');
34
+ expect(themeConfig.dark.systemTone).toBe('jewel');
35
+ });
36
+ });
@@ -0,0 +1,27 @@
1
+ import type { ThemeConfig } from '@ankhorage/surface';
2
+
3
+ import type { ZoraHexColor, ZoraTheme, ZoraThemeMode } from './types';
4
+ import { zoraDefaultTheme } from './zoraDefaultTheme';
5
+
6
+ function resolveModePrimaryColor(primaryColor: ZoraHexColor, _mode: ZoraThemeMode): ZoraHexColor {
7
+ // Intentionally conservative in Plan 1: mode-specific primary derivation
8
+ // (OKLCH/lightness scale, etc.) comes in later theme-engine work.
9
+ return primaryColor;
10
+ }
11
+
12
+ export function createZoraThemeConfig(theme: ZoraTheme = zoraDefaultTheme): ThemeConfig {
13
+ return {
14
+ id: theme.id,
15
+ name: theme.name ?? theme.id,
16
+ light: {
17
+ primaryColor: resolveModePrimaryColor(theme.primaryColor, 'light'),
18
+ harmony: theme.harmony,
19
+ systemTone: theme.tone,
20
+ },
21
+ dark: {
22
+ primaryColor: resolveModePrimaryColor(theme.primaryColor, 'dark'),
23
+ harmony: theme.harmony,
24
+ systemTone: theme.tone,
25
+ },
26
+ };
27
+ }
@@ -1,6 +1,14 @@
1
- export type { ZoraThemeOverride } from './createZoraTheme';
2
- export { createZoraTheme } from './createZoraTheme';
1
+ export { createZoraThemeConfig } from './createZoraThemeConfig';
2
+ export type {
3
+ ZoraColorHarmony,
4
+ ZoraColorTone,
5
+ ZoraComputedTheme,
6
+ ZoraHexColor,
7
+ ZoraTheme,
8
+ ZoraThemeId,
9
+ ZoraThemeMode,
10
+ } from './types';
3
11
  export { useZoraTheme } from './useZoraTheme';
12
+ export { zoraDefaultTheme } from './zoraDefaultTheme';
4
13
  export type { ZoraProviderProps } from './ZoraProvider';
5
14
  export { ZoraProvider } from './ZoraProvider';
6
- export { zoraTheme } from './zoraTheme';
@@ -0,0 +1,33 @@
1
+ import type { ThemeConfig } from '@ankhorage/surface';
2
+
3
+ export type ZoraThemeId = string;
4
+
5
+ export type ZoraThemeMode = 'light' | 'dark';
6
+
7
+ export type ZoraHexColor = `#${string}`;
8
+
9
+ export type ZoraColorHarmony =
10
+ | 'monochromatic'
11
+ | 'analogous'
12
+ | 'complementary'
13
+ | 'splitComplementary'
14
+ | 'triadic'
15
+ | 'tetradic';
16
+
17
+ export type ZoraColorTone = 'neutral' | 'pastel' | 'earth' | 'jewel' | 'fluorescent';
18
+
19
+ export interface ZoraTheme {
20
+ id: ZoraThemeId;
21
+ name?: string;
22
+ primaryColor: ZoraHexColor;
23
+ harmony: ZoraColorHarmony;
24
+ tone: ZoraColorTone;
25
+ }
26
+
27
+ export interface ZoraComputedTheme {
28
+ id: ZoraThemeId;
29
+ name: string;
30
+ mode: ZoraThemeMode;
31
+ source: ZoraTheme;
32
+ surfaceConfig: ThemeConfig;
33
+ }
@@ -0,0 +1,9 @@
1
+ import type { ZoraTheme } from './types';
2
+
3
+ export const zoraDefaultTheme: ZoraTheme = {
4
+ id: 'zora',
5
+ name: 'ZORA',
6
+ primaryColor: '#0f766e',
7
+ harmony: 'analogous',
8
+ tone: 'jewel',
9
+ };
@@ -1,2 +0,0 @@
1
- export declare function deepMerge<T extends object>(target: T, source: Partial<T>): T;
2
- //# sourceMappingURL=deepMerge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deepMerge.d.ts","sourceRoot":"","sources":["../../src/internal/deepMerge.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAsB5E"}
@@ -1,20 +0,0 @@
1
- export function deepMerge(target, source) {
2
- const result = { ...target };
3
- Object.keys(source).forEach((key) => {
4
- const sourceValue = source[key];
5
- const targetValue = target[key];
6
- if (sourceValue &&
7
- typeof sourceValue === 'object' &&
8
- !Array.isArray(sourceValue) &&
9
- targetValue &&
10
- typeof targetValue === 'object' &&
11
- !Array.isArray(targetValue)) {
12
- result[key] = deepMerge(targetValue, sourceValue);
13
- }
14
- else if (sourceValue !== undefined) {
15
- result[key] = sourceValue;
16
- }
17
- });
18
- return result;
19
- }
20
- //# sourceMappingURL=deepMerge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deepMerge.js","sourceRoot":"","sources":["../../src/internal/deepMerge.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAmB,MAAS,EAAE,MAAkB;IACvE,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAE5B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAiB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACnD,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAEhC,IACE,WAAW;YACX,OAAO,WAAW,KAAK,QAAQ;YAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAC3B,WAAW;YACX,OAAO,WAAW,KAAK,QAAQ;YAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAC3B,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,WAAqB,EAAE,WAAqB,CAAe,CAAC;QACtF,CAAC;aAAM,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAyB,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["export function deepMerge<T extends object>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n (Object.keys(source) as (keyof T)[]).forEach((key) => {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue as object, sourceValue as object) as T[keyof T];\n } else if (sourceValue !== undefined) {\n result[key] = sourceValue as T[keyof T];\n }\n });\n\n return result;\n}\n"]}
@@ -1,4 +0,0 @@
1
- import type { ThemeConfig } from '@ankhorage/surface';
2
- export type ZoraThemeOverride = Partial<ThemeConfig>;
3
- export declare function createZoraTheme(overrides?: ZoraThemeOverride): ThemeConfig;
4
- //# sourceMappingURL=createZoraTheme.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createZoraTheme.d.ts","sourceRoot":"","sources":["../../src/theme/createZoraTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKtD,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAErD,wBAAgB,eAAe,CAAC,SAAS,GAAE,iBAAsB,GAAG,WAAW,CAE9E"}
@@ -1,6 +0,0 @@
1
- import { deepMerge } from '../internal/deepMerge';
2
- import { zoraTheme } from './zoraTheme';
3
- export function createZoraTheme(overrides = {}) {
4
- return deepMerge(zoraTheme, overrides);
5
- }
6
- //# sourceMappingURL=createZoraTheme.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createZoraTheme.js","sourceRoot":"","sources":["../../src/theme/createZoraTheme.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,MAAM,UAAU,eAAe,CAAC,YAA+B,EAAE;IAC/D,OAAO,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/surface';\n\nimport { deepMerge } from '../internal/deepMerge';\nimport { zoraTheme } from './zoraTheme';\n\nexport type ZoraThemeOverride = Partial<ThemeConfig>;\n\nexport function createZoraTheme(overrides: ZoraThemeOverride = {}): ThemeConfig {\n return deepMerge(zoraTheme, overrides);\n}\n"]}
@@ -1,3 +0,0 @@
1
- import type { ThemeConfig } from '@ankhorage/surface';
2
- export declare const zoraTheme: ThemeConfig;
3
- //# sourceMappingURL=zoraTheme.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoraTheme.d.ts","sourceRoot":"","sources":["../../src/theme/zoraTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,eAAO,MAAM,SAAS,EAAE,WAavB,CAAC"}
@@ -1,15 +0,0 @@
1
- export const zoraTheme = {
2
- id: 'zora',
3
- name: 'ZORA',
4
- light: {
5
- primaryColor: '#0f766e',
6
- harmony: 'analogous',
7
- systemTone: 'jewel',
8
- },
9
- dark: {
10
- primaryColor: '#2dd4bf',
11
- harmony: 'analogous',
12
- systemTone: 'jewel',
13
- },
14
- };
15
- //# sourceMappingURL=zoraTheme.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoraTheme.js","sourceRoot":"","sources":["../../src/theme/zoraTheme.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAgB;IACpC,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE;QACL,YAAY,EAAE,SAAS;QACvB,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,OAAO;KACpB;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,SAAS;QACvB,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,OAAO;KACpB;CACF,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/surface';\n\nexport const zoraTheme: ThemeConfig = {\n id: 'zora',\n name: 'ZORA',\n light: {\n primaryColor: '#0f766e',\n harmony: 'analogous',\n systemTone: 'jewel',\n },\n dark: {\n primaryColor: '#2dd4bf',\n harmony: 'analogous',\n systemTone: 'jewel',\n },\n};\n"]}
@@ -1,23 +0,0 @@
1
- export function deepMerge<T extends object>(target: T, source: Partial<T>): T {
2
- const result = { ...target };
3
-
4
- (Object.keys(source) as (keyof T)[]).forEach((key) => {
5
- const sourceValue = source[key];
6
- const targetValue = target[key];
7
-
8
- if (
9
- sourceValue &&
10
- typeof sourceValue === 'object' &&
11
- !Array.isArray(sourceValue) &&
12
- targetValue &&
13
- typeof targetValue === 'object' &&
14
- !Array.isArray(targetValue)
15
- ) {
16
- result[key] = deepMerge(targetValue as object, sourceValue as object) as T[keyof T];
17
- } else if (sourceValue !== undefined) {
18
- result[key] = sourceValue as T[keyof T];
19
- }
20
- });
21
-
22
- return result;
23
- }
@@ -1,25 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { createZoraTheme } from './createZoraTheme';
4
-
5
- describe('createZoraTheme', () => {
6
- test('keeps the default preset stable', () => {
7
- const theme = createZoraTheme();
8
-
9
- expect(theme.id).toBe('zora');
10
- expect(theme.light.primaryColor).toBe('#0f766e');
11
- expect(theme.dark.primaryColor).toBe('#2dd4bf');
12
- });
13
-
14
- test('merges overrides without dropping the preset identity', () => {
15
- const theme = createZoraTheme({
16
- light: {
17
- primaryColor: '#1d4ed8',
18
- },
19
- });
20
-
21
- expect(theme.id).toBe('zora');
22
- expect(theme.light.primaryColor).toBe('#1d4ed8');
23
- expect(theme.dark.primaryColor).toBe('#2dd4bf');
24
- });
25
- });
@@ -1,10 +0,0 @@
1
- import type { ThemeConfig } from '@ankhorage/surface';
2
-
3
- import { deepMerge } from '../internal/deepMerge';
4
- import { zoraTheme } from './zoraTheme';
5
-
6
- export type ZoraThemeOverride = Partial<ThemeConfig>;
7
-
8
- export function createZoraTheme(overrides: ZoraThemeOverride = {}): ThemeConfig {
9
- return deepMerge(zoraTheme, overrides);
10
- }
@@ -1,16 +0,0 @@
1
- import type { ThemeConfig } from '@ankhorage/surface';
2
-
3
- export const zoraTheme: ThemeConfig = {
4
- id: 'zora',
5
- name: 'ZORA',
6
- light: {
7
- primaryColor: '#0f766e',
8
- harmony: 'analogous',
9
- systemTone: 'jewel',
10
- },
11
- dark: {
12
- primaryColor: '#2dd4bf',
13
- harmony: 'analogous',
14
- systemTone: 'jewel',
15
- },
16
- };