@ankhorage/zora 25.8.15 → 25.8.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/capabilities/index.js +34 -59
  4. package/dist/capabilities/index.js.map +3 -3
  5. package/dist/features/date-picker/composition/DatePickerContent.d.ts.map +1 -1
  6. package/dist/features/date-picker/composition/DatePickerContent.js +1 -11
  7. package/dist/features/date-picker/composition/DatePickerContent.js.map +1 -1
  8. package/dist/features/date-picker/composition/DatePickerField.d.ts.map +1 -1
  9. package/dist/features/date-picker/composition/DatePickerField.js +2 -17
  10. package/dist/features/date-picker/composition/DatePickerField.js.map +1 -1
  11. package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.js +7 -19
  12. package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.js.map +1 -1
  13. package/dist/features/picker/composition/PickerField.d.ts +14 -0
  14. package/dist/features/picker/composition/PickerField.d.ts.map +1 -0
  15. package/dist/features/picker/composition/PickerField.js +21 -0
  16. package/dist/features/picker/composition/PickerField.js.map +1 -0
  17. package/dist/features/picker/composition/PickerHeader.d.ts +9 -0
  18. package/dist/features/picker/composition/PickerHeader.d.ts.map +1 -0
  19. package/dist/features/picker/composition/PickerHeader.js +14 -0
  20. package/dist/features/picker/composition/PickerHeader.js.map +1 -0
  21. package/dist/features/tabletop/meta.d.ts +46 -46
  22. package/dist/features/tabletop/meta.d.ts.map +1 -1
  23. package/dist/features/tabletop/meta.js +33 -58
  24. package/dist/features/tabletop/meta.js.map +1 -1
  25. package/dist/features/time-picker/composition/TimePickerContent.js +1 -12
  26. package/dist/features/time-picker/composition/TimePickerContent.js.map +1 -1
  27. package/dist/features/time-picker/composition/TimePickerField.d.ts.map +1 -1
  28. package/dist/features/time-picker/composition/TimePickerField.js +2 -17
  29. package/dist/features/time-picker/composition/TimePickerField.js.map +1 -1
  30. package/dist/features/typography/utils/headingThemeRecipeMeta.d.ts +5 -5
  31. package/dist/features/typography/utils/headingThemeRecipeMeta.d.ts.map +1 -1
  32. package/dist/features/typography/utils/headingThemeRecipeMeta.js +2 -19
  33. package/dist/features/typography/utils/headingThemeRecipeMeta.js.map +1 -1
  34. package/dist/features/typography/utils/resolveHeadingRecipe.d.ts.map +1 -1
  35. package/dist/features/typography/utils/resolveHeadingRecipe.js +11 -68
  36. package/dist/features/typography/utils/resolveHeadingRecipe.js.map +1 -1
  37. package/dist/features/typography/utils/resolveHeadingThemeRecipe.d.ts +4 -4
  38. package/dist/features/typography/utils/resolveHeadingThemeRecipe.d.ts.map +1 -1
  39. package/dist/features/typography/utils/resolveHeadingThemeRecipe.js +2 -33
  40. package/dist/features/typography/utils/resolveHeadingThemeRecipe.js.map +1 -1
  41. package/dist/features/typography/utils/resolveTextStyle.d.ts.map +1 -1
  42. package/dist/features/typography/utils/resolveTextStyle.js +11 -76
  43. package/dist/features/typography/utils/resolveTextStyle.js.map +1 -1
  44. package/dist/features/typography/utils/resolveTextThemeRecipe.d.ts +4 -4
  45. package/dist/features/typography/utils/resolveTextThemeRecipe.d.ts.map +1 -1
  46. package/dist/features/typography/utils/resolveTextThemeRecipe.js +2 -33
  47. package/dist/features/typography/utils/resolveTextThemeRecipe.js.map +1 -1
  48. package/dist/features/typography/utils/resolveTypographyStyleTokens.d.ts +21 -0
  49. package/dist/features/typography/utils/resolveTypographyStyleTokens.d.ts.map +1 -0
  50. package/dist/features/typography/utils/resolveTypographyStyleTokens.js +75 -0
  51. package/dist/features/typography/utils/resolveTypographyStyleTokens.js.map +1 -0
  52. package/dist/features/typography/utils/resolveTypographyThemeRecipeFields.d.ts +10 -0
  53. package/dist/features/typography/utils/resolveTypographyThemeRecipeFields.d.ts.map +1 -0
  54. package/dist/features/typography/utils/resolveTypographyThemeRecipeFields.js +19 -0
  55. package/dist/features/typography/utils/resolveTypographyThemeRecipeFields.js.map +1 -0
  56. package/dist/features/typography/utils/textThemeRecipeMeta.d.ts +6 -6
  57. package/dist/features/typography/utils/textThemeRecipeMeta.d.ts.map +1 -1
  58. package/dist/features/typography/utils/textThemeRecipeMeta.js +2 -19
  59. package/dist/features/typography/utils/textThemeRecipeMeta.js.map +1 -1
  60. package/dist/features/typography/utils/typographyThemeRecipeFields.d.ts +30 -0
  61. package/dist/features/typography/utils/typographyThemeRecipeFields.d.ts.map +1 -0
  62. package/dist/features/typography/utils/typographyThemeRecipeFields.js +23 -0
  63. package/dist/features/typography/utils/typographyThemeRecipeFields.js.map +1 -0
  64. package/dist/features/uploader/adapters/inbound/Uploader.d.ts.map +1 -1
  65. package/dist/features/uploader/adapters/inbound/Uploader.js +1 -16
  66. package/dist/features/uploader/adapters/inbound/Uploader.js.map +1 -1
  67. package/dist/features/uploader/application/use-cases/validateUploadAsset.d.ts.map +1 -1
  68. package/dist/features/uploader/application/use-cases/validateUploadAsset.js +1 -16
  69. package/dist/features/uploader/application/use-cases/validateUploadAsset.js.map +1 -1
  70. package/dist/features/web-component-artifact/composition/createWebDesiredStateWithNodeAsync.d.ts.map +1 -1
  71. package/dist/features/web-component-artifact/composition/createWebDesiredStateWithNodeAsync.js +3 -4
  72. package/dist/features/web-component-artifact/composition/createWebDesiredStateWithNodeAsync.js.map +1 -1
  73. package/dist/features/web-component-artifact/composition/readWebComponentPackageMetadataAsync.d.ts +8 -0
  74. package/dist/features/web-component-artifact/composition/readWebComponentPackageMetadataAsync.d.ts.map +1 -0
  75. package/dist/features/web-component-artifact/composition/readWebComponentPackageMetadataAsync.js +10 -0
  76. package/dist/features/web-component-artifact/composition/readWebComponentPackageMetadataAsync.js.map +1 -0
  77. package/dist/features/web-component-artifact/composition/synchronizeDeclaredWebComponentsWithNodeAsync.d.ts.map +1 -1
  78. package/dist/features/web-component-artifact/composition/synchronizeDeclaredWebComponentsWithNodeAsync.js +4 -6
  79. package/dist/features/web-component-artifact/composition/synchronizeDeclaredWebComponentsWithNodeAsync.js.map +1 -1
  80. package/package.json +14 -14
  81. package/src/expo57Migration.test.ts +50 -0
  82. package/src/features/date-picker/composition/DatePickerContent.tsx +1 -22
  83. package/src/features/date-picker/composition/DatePickerField.tsx +2 -31
  84. package/src/features/matrix-grid/application/getMatrixGridNextFocusId.ts +11 -22
  85. package/src/features/picker/composition/PickerField.tsx +61 -0
  86. package/src/features/picker/composition/PickerHeader.tsx +25 -0
  87. package/src/features/tabletop/meta.ts +34 -58
  88. package/src/features/time-picker/composition/TimePickerContent.tsx +1 -23
  89. package/src/features/time-picker/composition/TimePickerField.tsx +2 -31
  90. package/src/features/typography/utils/headingThemeRecipeMeta.ts +2 -19
  91. package/src/features/typography/utils/resolveHeadingRecipe.ts +12 -88
  92. package/src/features/typography/utils/resolveHeadingThemeRecipe.ts +3 -39
  93. package/src/features/typography/utils/resolveTextStyle.ts +10 -98
  94. package/src/features/typography/utils/resolveTextThemeRecipe.ts +3 -39
  95. package/src/features/typography/utils/resolveTypographyStyleTokens.ts +113 -0
  96. package/src/features/typography/utils/resolveTypographyThemeRecipeFields.ts +27 -0
  97. package/src/features/typography/utils/textThemeRecipeMeta.ts +2 -19
  98. package/src/features/typography/utils/typographyThemeRecipeFields.ts +23 -0
  99. package/src/features/uploader/adapters/inbound/Uploader.tsx +1 -20
  100. package/src/features/uploader/application/use-cases/validateUploadAsset.test.ts +2 -2
  101. package/src/features/uploader/application/use-cases/validateUploadAsset.ts +2 -20
  102. package/src/features/web-component-artifact/composition/createWebDesiredStateWithNodeAsync.ts +3 -6
  103. package/src/features/web-component-artifact/composition/readWebComponentPackageMetadataAsync.ts +18 -0
  104. package/src/features/web-component-artifact/composition/synchronizeDeclaredWebComponentsWithNodeAsync.ts +4 -8
  105. package/web-dist/chunks/{Accordion-rqr10gn4.js → Accordion-1495be5z.js} +2 -2
  106. package/web-dist/chunks/{Accordion-m2hcc8g4.js → Accordion-3qphhsb4.js} +1 -1
  107. package/web-dist/chunks/{Accordion-gn8ptzwb.js → Accordion-4x8gdqqs.js} +1 -1
  108. package/web-dist/chunks/{Accordion-9aczb0k2.js → Accordion-58bpmzdj.js} +2 -2
  109. package/web-dist/chunks/{Accordion-2jy53kzk.js → Accordion-69c4pfz2.js} +2 -2
  110. package/web-dist/chunks/{Accordion-rqhh2m5b.js → Accordion-7n93d7fa.js} +1 -1
  111. package/web-dist/chunks/{Accordion-m6mp8aea.js → Accordion-a42brn0p.js} +1 -1
  112. package/web-dist/chunks/{Accordion-g08740h4.js → Accordion-c912kzs0.js} +1 -1
  113. package/web-dist/chunks/{Accordion-tyh8jj9d.js → Accordion-cbbafww1.js} +1 -1
  114. package/web-dist/chunks/{Accordion-11ej93t5.js → Accordion-cjjg81ry.js} +2 -2
  115. package/web-dist/chunks/{Accordion-vkd002gw.js → Accordion-d0bebw9j.js} +3 -3
  116. package/web-dist/chunks/{Accordion-vjcd5kxc.js → Accordion-gntmfcmz.js} +1 -1
  117. package/web-dist/chunks/{Accordion-wqyrrptg.js → Accordion-jyemxzat.js} +1 -1
  118. package/web-dist/chunks/{Accordion-p7d5svfq.js → Accordion-kmwhjw1k.js} +1 -1
  119. package/web-dist/chunks/{Accordion-26prtnm7.js → Accordion-ptxa6trg.js} +1 -1
  120. package/web-dist/chunks/{Accordion-4yq92mxp.js → Accordion-ve81xazy.js} +1 -1
  121. package/web-dist/chunks/Accordion-vnb3vntm.js +79 -0
  122. package/web-dist/chunks/{Accordion-9rnsg9pk.js → Accordion-vqx3exsq.js} +129 -243
  123. package/web-dist/chunks/{Accordion-1hbt9k69.js → Accordion-w95t2pr3.js} +1 -1
  124. package/web-dist/chunks/{Accordion-g2aqhct0.js → Accordion-z5dpzw3g.js} +2 -2
  125. package/web-dist/chunks/{Accordion-a4pz3vjj.js → Accordion-zf1g5422.js} +1 -1
  126. package/web-dist/components/accordion/Accordion.js +2 -2
  127. package/web-dist/components/accordion-item/AccordionItem.js +2 -2
  128. package/web-dist/components/app-bar/AppBar.js +2 -2
  129. package/web-dist/components/app-header/AppHeader.js +2 -2
  130. package/web-dist/components/auth-screen/AuthScreen.js +4 -4
  131. package/web-dist/components/avatar/Avatar.js +2 -2
  132. package/web-dist/components/avatar-group/AvatarGroup.js +2 -2
  133. package/web-dist/components/barcode-scanner-view/BarcodeScannerView.js +4 -4
  134. package/web-dist/components/breadcrumbs/Breadcrumbs.js +1 -1
  135. package/web-dist/components/camera-permission-view/CameraPermissionView.js +4 -4
  136. package/web-dist/components/card/Card.js +3 -3
  137. package/web-dist/components/chat-list-item/ChatListItem.js +3 -3
  138. package/web-dist/components/checkbox/Checkbox.js +2 -2
  139. package/web-dist/components/checkbox-group/CheckboxGroup.js +2 -2
  140. package/web-dist/components/chip/Chip.js +2 -2
  141. package/web-dist/components/chip-group/ChipGroup.js +2 -2
  142. package/web-dist/components/collection-editor/CollectionEditor.js +3 -3
  143. package/web-dist/components/content-rail/ContentRail.js +1 -1
  144. package/web-dist/components/data-table/DataTable.js +7 -7
  145. package/web-dist/components/date-picker/DatePicker.js +12 -49
  146. package/web-dist/components/dialog/Dialog.js +2 -2
  147. package/web-dist/components/empty-state/EmptyState.js +4 -4
  148. package/web-dist/components/explorer/Explorer.js +2 -2
  149. package/web-dist/components/field/Field.js +2 -2
  150. package/web-dist/components/file-explorer/FileExplorer.js +2 -2
  151. package/web-dist/components/flat-list/FlatList.js +3 -3
  152. package/web-dist/components/forgot-password-form/ForgotPasswordForm.js +4 -4
  153. package/web-dist/components/form/Form.js +3 -3
  154. package/web-dist/components/form-actions/FormActions.js +3 -3
  155. package/web-dist/components/form-error/FormError.js +3 -3
  156. package/web-dist/components/heading/Heading.js +1 -1
  157. package/web-dist/components/hero/Hero.js +3 -3
  158. package/web-dist/components/list/List.js +3 -3
  159. package/web-dist/components/list-item/ListItem.js +3 -3
  160. package/web-dist/components/list-section/ListSection.js +3 -3
  161. package/web-dist/components/matrix-grid/MatrixGrid.js +5 -17
  162. package/web-dist/components/media-card/MediaCard.js +3 -3
  163. package/web-dist/components/media-explorer/MediaExplorer.js +2 -2
  164. package/web-dist/components/message-bubble/MessageBubble.js +3 -3
  165. package/web-dist/components/metric-card/MetricCard.js +3 -3
  166. package/web-dist/components/missing-element/MissingElement.js +1 -1
  167. package/web-dist/components/o-auth-provider-button/OAuthProviderButton.js +4 -4
  168. package/web-dist/components/o-auth-provider-list/OAuthProviderList.js +4 -4
  169. package/web-dist/components/otp-form/OtpForm.js +4 -4
  170. package/web-dist/components/pagination/Pagination.js +1 -1
  171. package/web-dist/components/palette-item/PaletteItem.js +3 -3
  172. package/web-dist/components/post-card/PostCard.js +3 -3
  173. package/web-dist/components/product-card/ProductCard.js +3 -3
  174. package/web-dist/components/progress/Progress.js +2 -2
  175. package/web-dist/components/progress-ring/ProgressRing.js +2 -2
  176. package/web-dist/components/radio/Radio.js +2 -2
  177. package/web-dist/components/radio-group/RadioGroup.js +2 -2
  178. package/web-dist/components/reader/Reader.js +4 -4
  179. package/web-dist/components/scan-overlay/ScanOverlay.js +4 -4
  180. package/web-dist/components/screen-section/ScreenSection.js +2 -2
  181. package/web-dist/components/section-header/SectionHeader.js +2 -2
  182. package/web-dist/components/section-list/SectionList.js +3 -3
  183. package/web-dist/components/sign-in-form/SignInForm.js +4 -4
  184. package/web-dist/components/sign-up-form/SignUpForm.js +4 -4
  185. package/web-dist/components/skeleton/Skeleton.js +6 -6
  186. package/web-dist/components/skeleton-card/SkeletonCard.js +6 -6
  187. package/web-dist/components/skeleton-list/SkeletonList.js +6 -6
  188. package/web-dist/components/skeleton-text/SkeletonText.js +6 -6
  189. package/web-dist/components/text/Text.js +1 -1
  190. package/web-dist/components/time-picker/TimePicker.js +12 -51
  191. package/web-dist/components/timeline/Timeline.js +1 -1
  192. package/web-dist/components/toolbar/Toolbar.js +3 -3
  193. package/web-dist/components/tree-item/TreeItem.js +3 -3
  194. package/web-dist/components/uploader/Uploader.js +21 -37
  195. package/web-dist/manifest.json +204 -202
@@ -1,5 +1,37 @@
1
1
  import type { ZoraComponentMeta } from '../../types/authoring';
2
2
 
3
+ const tabletopPresentationProps = {
4
+ shape: {
5
+ type: 'enum',
6
+ category: 'Table',
7
+ label: 'Shape',
8
+ enum: ['circle', 'oval', 'rounded'],
9
+ default: 'oval',
10
+ authoring: { authority: 'instance' },
11
+ },
12
+ cardSize: {
13
+ type: 'enum',
14
+ category: 'Cards',
15
+ label: 'Card size',
16
+ enum: ['small', 'medium', 'large'],
17
+ default: 'small',
18
+ authoring: { authority: 'instance' },
19
+ },
20
+ disabled: {
21
+ type: 'boolean',
22
+ category: 'State',
23
+ label: 'Disabled',
24
+ default: false,
25
+ authoring: { authority: 'instance' },
26
+ },
27
+ accessibilityLabel: {
28
+ type: 'string',
29
+ category: 'Accessibility',
30
+ label: 'Accessibility label',
31
+ authoring: { authority: 'instance' },
32
+ },
33
+ } as const;
34
+
3
35
  export const cardBackMeta = {
4
36
  name: 'CardBack',
5
37
  category: 'component',
@@ -163,14 +195,6 @@ export const tabletopTableMeta = {
163
195
  label: 'Center sublabel',
164
196
  authoring: { authority: 'instance' },
165
197
  },
166
- shape: {
167
- type: 'enum',
168
- category: 'Table',
169
- label: 'Shape',
170
- enum: ['circle', 'oval', 'rounded'],
171
- default: 'oval',
172
- authoring: { authority: 'instance' },
173
- },
174
198
  seatCount: {
175
199
  type: 'enum',
176
200
  category: 'Players',
@@ -178,27 +202,7 @@ export const tabletopTableMeta = {
178
202
  enum: [2, 3, 4, 5, 6, 7, 8, 9, 10],
179
203
  authoring: { authority: 'instance' },
180
204
  },
181
- cardSize: {
182
- type: 'enum',
183
- category: 'Cards',
184
- label: 'Card size',
185
- enum: ['small', 'medium', 'large'],
186
- default: 'small',
187
- authoring: { authority: 'instance' },
188
- },
189
- disabled: {
190
- type: 'boolean',
191
- category: 'State',
192
- label: 'Disabled',
193
- default: false,
194
- authoring: { authority: 'instance' },
195
- },
196
- accessibilityLabel: {
197
- type: 'string',
198
- category: 'Accessibility',
199
- label: 'Accessibility label',
200
- authoring: { authority: 'instance' },
201
- },
205
+ ...tabletopPresentationProps,
202
206
  },
203
207
  } as const satisfies ZoraComponentMeta;
204
208
  export const pokerTrainingTableMeta = {
@@ -245,34 +249,6 @@ export const pokerTrainingTableMeta = {
245
249
  default: 100,
246
250
  authoring: { authority: 'instance' },
247
251
  },
248
- shape: {
249
- type: 'enum',
250
- category: 'Table',
251
- label: 'Shape',
252
- enum: ['circle', 'oval', 'rounded'],
253
- default: 'oval',
254
- authoring: { authority: 'instance' },
255
- },
256
- cardSize: {
257
- type: 'enum',
258
- category: 'Cards',
259
- label: 'Card size',
260
- enum: ['small', 'medium', 'large'],
261
- default: 'small',
262
- authoring: { authority: 'instance' },
263
- },
264
- disabled: {
265
- type: 'boolean',
266
- category: 'State',
267
- label: 'Disabled',
268
- default: false,
269
- authoring: { authority: 'instance' },
270
- },
271
- accessibilityLabel: {
272
- type: 'string',
273
- category: 'Accessibility',
274
- label: 'Accessibility label',
275
- authoring: { authority: 'instance' },
276
- },
252
+ ...tabletopPresentationProps,
277
253
  },
278
254
  } as const satisfies ZoraComponentMeta;
@@ -4,7 +4,7 @@ import { ScrollView, StyleSheet } from 'react-native';
4
4
  import type { TimePickerProps } from '../../../types/time-picker';
5
5
  import { Button } from '../../button/public';
6
6
  import { View } from '../../layout/public';
7
- import { Text } from '../../typography/public';
7
+ import { PickerHeader } from '../../picker/composition/PickerHeader';
8
8
 
9
9
  const MINUTES_PER_DAY = 24 * 60;
10
10
  const DEFAULT_STEP_MINUTES = 30;
@@ -69,28 +69,6 @@ interface TimePickerContentProps extends Pick<
69
69
  onSelect: (value: string) => void;
70
70
  }
71
71
 
72
- /*** Renders the shared title block used by picker overlays. */
73
- function PickerHeader({
74
- description,
75
- title,
76
- }: {
77
- description: React.ReactNode | undefined;
78
- title: React.ReactNode;
79
- }) {
80
- return (
81
- <View gap="xxs">
82
- <Text align="center" variant="label" weight="semiBold">
83
- {title}
84
- </Text>
85
- {description ? (
86
- <Text align="center" emphasis="muted" variant="bodySmall">
87
- {description}
88
- </Text>
89
- ) : null}
90
- </View>
91
- );
92
- }
93
-
94
72
  /*** Renders one accessible selectable time option. */
95
73
  function TimePickerOption({
96
74
  formatTime,
@@ -1,9 +1,7 @@
1
- import { Field } from '@ankhorage/surface';
2
1
  import type React from 'react';
3
2
 
4
3
  import type { TimePickerProps } from '../../../types/time-picker';
5
- import { View } from '../../layout/public';
6
- import { Text } from '../../typography/public';
4
+ import { PickerField } from '../../picker/composition/PickerField';
7
5
 
8
6
  /*** Renders the shared TimePicker field frame around a platform-specific trigger. */
9
7
  export function TimePickerField({
@@ -15,18 +13,7 @@ export function TimePickerField({
15
13
  required,
16
14
  testID,
17
15
  }: TimePickerFieldProps) {
18
- return (
19
- <Field
20
- disabled={disabled}
21
- errorText={error}
22
- invalid={Boolean(error)}
23
- label={label ? renderLabel(label, description) : undefined}
24
- required={required}
25
- testID={testID}
26
- >
27
- {children}
28
- </Field>
29
- );
16
+ return <PickerField {...{ children, description, disabled, error, label, required, testID }} />;
30
17
  }
31
18
 
32
19
  interface TimePickerFieldProps extends Pick<
@@ -35,19 +22,3 @@ interface TimePickerFieldProps extends Pick<
35
22
  > {
36
23
  children: React.ReactNode;
37
24
  }
38
-
39
- /*** Renders the picker label and optional supporting description. */
40
- function renderLabel(label: React.ReactNode, description: React.ReactNode | undefined) {
41
- return (
42
- <View gap="xs">
43
- <Text variant="label" weight="semiBold">
44
- {label}
45
- </Text>
46
- {description ? (
47
- <Text emphasis="muted" variant="bodySmall">
48
- {description}
49
- </Text>
50
- ) : null}
51
- </View>
52
- );
53
- }
@@ -1,5 +1,5 @@
1
1
  import type { ZoraThemeRecipeMeta } from '../../../types/theme-recipe';
2
- import { ZORA_COLORS, ZORA_EMPHASES } from '../../theme/colorModel';
2
+ import { typographyThemeRecipeFields } from './typographyThemeRecipeFields';
3
3
 
4
4
  export const headingThemeRecipeMeta = {
5
5
  name: 'Heading',
@@ -11,23 +11,6 @@ export const headingThemeRecipeMeta = {
11
11
  label: 'Size',
12
12
  options: ['display', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
13
13
  },
14
- color: { type: 'choice', label: 'Color', options: ZORA_COLORS },
15
- emphasis: {
16
- type: 'choice',
17
- label: 'Emphasis',
18
- options: ZORA_EMPHASES,
19
- default: 'default',
20
- },
21
- align: {
22
- type: 'choice',
23
- label: 'Align',
24
- options: ['auto', 'left', 'right', 'center', 'justify'],
25
- },
26
- weight: {
27
- type: 'choice',
28
- label: 'Weight',
29
- options: ['regular', 'medium', 'semiBold', 'bold'],
30
- },
31
- italic: { type: 'boolean', label: 'Italic', default: false },
14
+ ...typographyThemeRecipeFields,
32
15
  },
33
16
  } as const satisfies ZoraThemeRecipeMeta;
@@ -1,4 +1,4 @@
1
- import type { FontWeight, RoleSemantics, SurfaceTheme } from '@ankhorage/surface';
1
+ import type { SurfaceTheme } from '@ankhorage/surface';
2
2
  import type { TextStyle } from 'react-native';
3
3
 
4
4
  import type {
@@ -10,6 +10,7 @@ import type {
10
10
  HeadingWeight,
11
11
  } from '../../../types/heading';
12
12
  import { resolveHeadingSizeFromLevel } from './resolveHeadingSizeFromLevel';
13
+ import { resolveTypographyStyleTokens } from './resolveTypographyStyleTokens';
13
14
  export function resolveHeadingRecipe(
14
15
  theme: SurfaceTheme,
15
16
  {
@@ -23,15 +24,21 @@ export function resolveHeadingRecipe(
23
24
  }: ResolveHeadingRecipeOptions,
24
25
  ): TextStyle {
25
26
  const recipe = resolveSizeRecipe(theme, size ?? resolveHeadingSizeFromLevel(level));
26
- const resolvedWeight = resolveWeight(theme, weight ?? recipe.weight);
27
+ const tokens = resolveTypographyStyleTokens({
28
+ theme,
29
+ color,
30
+ emphasis,
31
+ weight: weight ?? recipe.weight,
32
+ italic,
33
+ });
27
34
 
28
35
  return {
29
- color: resolveHeadingColor(theme, emphasis, color),
36
+ color: tokens.color,
30
37
  elevation: 0,
31
- fontFamily: resolveFontFamily({ theme, weight: resolvedWeight, italic }),
38
+ fontFamily: tokens.fontFamily,
32
39
  fontSize: recipe.fontSize,
33
40
  fontStyle: italic ? 'italic' : 'normal',
34
- fontWeight: resolvedWeight,
41
+ fontWeight: tokens.fontWeight,
35
42
  lineHeight: recipe.lineHeight,
36
43
  textAlign: align,
37
44
  };
@@ -89,86 +96,3 @@ function resolveSizeRecipe(theme: SurfaceTheme, size: HeadingSize): HeadingRecip
89
96
  weight: heading.weight,
90
97
  };
91
98
  }
92
-
93
- function resolveRoleSemantics(theme: SurfaceTheme, color: HeadingColor): RoleSemantics {
94
- switch (color) {
95
- case 'secondary':
96
- return theme.semantics.secondary;
97
- case 'tertiary':
98
- return theme.semantics.accent;
99
- case 'quaternary':
100
- return theme.semantics.highlight;
101
- case 'neutral':
102
- return theme.semantics.action.neutral;
103
- case 'error':
104
- return theme.semantics.error;
105
- case 'info':
106
- return theme.semantics.info;
107
- case 'danger':
108
- return theme.semantics.action.danger;
109
- case 'success':
110
- return theme.semantics.success;
111
- case 'warning':
112
- return theme.semantics.warning;
113
- case 'primary':
114
- default:
115
- return theme.semantics.action.primary;
116
- }
117
- }
118
-
119
- function resolveHeadingColor(
120
- theme: SurfaceTheme,
121
- emphasis: HeadingEmphasis,
122
- color?: HeadingColor,
123
- ): string {
124
- if (color) {
125
- const role = resolveRoleSemantics(theme, color);
126
- return emphasis === 'inverse' ? role.onSolidText : role.base;
127
- }
128
-
129
- switch (emphasis) {
130
- case 'muted':
131
- return theme.semantics.content.muted;
132
- case 'subtle':
133
- return theme.semantics.content.subtle;
134
- case 'inverse':
135
- return theme.semantics.content.inverse;
136
- case 'default':
137
- default:
138
- return theme.semantics.content.default;
139
- }
140
- }
141
-
142
- function resolveWeight(theme: SurfaceTheme, weight: HeadingWeight): FontWeight {
143
- switch (weight) {
144
- case 'medium':
145
- return theme.typography.weights.medium;
146
- case 'semiBold':
147
- return theme.typography.weights.semiBold;
148
- case 'bold':
149
- return theme.typography.weights.bold;
150
- case 'regular':
151
- default:
152
- return theme.typography.weights.regular;
153
- }
154
- }
155
-
156
- function resolveFontFamily({
157
- theme,
158
- weight,
159
- italic,
160
- }: {
161
- theme: SurfaceTheme;
162
- weight: FontWeight;
163
- italic: boolean;
164
- }): string | undefined {
165
- const fonts = italic ? theme.typography.fonts.italic : theme.typography.fonts.normal;
166
-
167
- for (const [fontWeight, fontFamily] of Object.entries(fonts)) {
168
- if (fontWeight === weight) {
169
- return fontFamily;
170
- }
171
- }
172
-
173
- return undefined;
174
- }
@@ -1,23 +1,14 @@
1
1
  import type { ThemeRecipeOverrideValue } from '@ankhorage/contracts';
2
2
 
3
- import type {
4
- HeadingAlign,
5
- HeadingColor,
6
- HeadingEmphasis,
7
- HeadingSize,
8
- HeadingWeight,
9
- } from '../../../types/heading';
3
+ import type { HeadingSize } from '../../../types/heading';
4
+ import { resolveTypographyThemeRecipeFields } from './resolveTypographyThemeRecipeFields';
10
5
 
11
6
  export function resolveHeadingThemeRecipe(
12
7
  fields: Readonly<Record<string, ThemeRecipeOverrideValue>>,
13
8
  ) {
14
9
  return {
15
10
  size: readSize(fields.size),
16
- color: readColor(fields.color),
17
- emphasis: readEmphasis(fields.emphasis),
18
- align: readAlign(fields.align),
19
- weight: readWeight(fields.weight),
20
- italic: typeof fields.italic === 'boolean' ? fields.italic : undefined,
11
+ ...resolveTypographyThemeRecipeFields(fields),
21
12
  };
22
13
  }
23
14
 
@@ -26,30 +17,3 @@ function readSize(value: ThemeRecipeOverrideValue | undefined): HeadingSize | un
26
17
  if (value === 'h4' || value === 'h5' || value === 'h6') return value;
27
18
  return undefined;
28
19
  }
29
-
30
- function readColor(value: ThemeRecipeOverrideValue | undefined): HeadingColor | undefined {
31
- if (typeof value !== 'string') return undefined;
32
- if (value === 'primary' || value === 'secondary' || value === 'tertiary') return value;
33
- if (value === 'quaternary' || value === 'neutral' || value === 'danger') return value;
34
- if (value === 'success' || value === 'warning' || value === 'error' || value === 'info')
35
- return value;
36
- return undefined;
37
- }
38
-
39
- function readEmphasis(value: ThemeRecipeOverrideValue | undefined): HeadingEmphasis | undefined {
40
- if (value === 'default' || value === 'muted' || value === 'subtle' || value === 'inverse')
41
- return value;
42
- return undefined;
43
- }
44
-
45
- function readAlign(value: ThemeRecipeOverrideValue | undefined): HeadingAlign | undefined {
46
- if (value === 'auto' || value === 'left' || value === 'right') return value;
47
- if (value === 'center' || value === 'justify') return value;
48
- return undefined;
49
- }
50
-
51
- function readWeight(value: ThemeRecipeOverrideValue | undefined): HeadingWeight | undefined {
52
- if (value === 'regular' || value === 'medium' || value === 'semiBold' || value === 'bold')
53
- return value;
54
- return undefined;
55
- }
@@ -1,9 +1,7 @@
1
1
  import {
2
2
  type Breakpoint,
3
- type FontWeight,
4
3
  resolveResponsive,
5
4
  type Responsive,
6
- type RoleSemantics,
7
5
  type SurfaceTheme,
8
6
  } from '@ankhorage/surface';
9
7
  import type { TextStyle } from 'react-native';
@@ -15,6 +13,7 @@ import type {
15
13
  TextVariant,
16
14
  TextWeight,
17
15
  } from '../../../types/text';
16
+ import { resolveTypographyStyleTokens } from './resolveTypographyStyleTokens';
18
17
  /*** Resolves responsive text variants and theme semantics into a native text style. */
19
18
  export function resolveTextStyle({
20
19
  theme,
@@ -31,23 +30,21 @@ export function resolveTextStyle({
31
30
  const resolvedColor = resolveResponsive(color, breakpoint);
32
31
  const resolvedAlign = resolveResponsive(align, breakpoint);
33
32
  const recipe = resolveVariantRecipe(theme, resolvedVariant, breakpoint);
34
- const resolvedWeight = resolveWeight(
33
+ const tokens = resolveTypographyStyleTokens({
35
34
  theme,
36
- resolveResponsive(weight, breakpoint) ?? recipe.weight,
37
- );
35
+ color: resolvedColor,
36
+ emphasis: resolvedEmphasis,
37
+ weight: resolveResponsive(weight, breakpoint) ?? recipe.weight,
38
+ italic,
39
+ });
38
40
 
39
41
  return {
40
- color: resolveTextColor(theme, resolvedEmphasis, resolvedColor),
42
+ color: tokens.color,
41
43
  elevation: 0,
42
- fontFamily: resolveFontFamily({
43
- theme,
44
- variant: resolvedVariant,
45
- weight: resolvedWeight,
46
- italic,
47
- }),
44
+ fontFamily: resolvedVariant === 'code' ? 'monospace' : tokens.fontFamily,
48
45
  fontSize: recipe.fontSize,
49
46
  fontStyle: italic ? 'italic' : 'normal',
50
- fontWeight: resolvedWeight,
47
+ fontWeight: tokens.fontWeight,
51
48
  letterSpacing: recipe.letterSpacing,
52
49
  lineHeight: recipe.lineHeight,
53
50
  textAlign: resolvedAlign,
@@ -78,46 +75,6 @@ function isMediumBreakpointOrLarger(breakpoint: Breakpoint): boolean {
78
75
  return breakpoint === 'md' || breakpoint === 'lg' || breakpoint === 'xl';
79
76
  }
80
77
 
81
- function resolveWeight(theme: SurfaceTheme, weight: TextWeight): FontWeight {
82
- switch (weight) {
83
- case 'medium':
84
- return theme.typography.weights.medium;
85
- case 'semiBold':
86
- return theme.typography.weights.semiBold;
87
- case 'bold':
88
- return theme.typography.weights.bold;
89
- case 'regular':
90
- default:
91
- return theme.typography.weights.regular;
92
- }
93
- }
94
-
95
- function resolveFontFamily({
96
- theme,
97
- variant,
98
- weight,
99
- italic,
100
- }: {
101
- theme: SurfaceTheme;
102
- variant: TextVariant;
103
- weight: FontWeight;
104
- italic: boolean;
105
- }): string | undefined {
106
- if (variant === 'code') {
107
- return 'monospace';
108
- }
109
-
110
- const fonts = italic ? theme.typography.fonts.italic : theme.typography.fonts.normal;
111
-
112
- for (const [fontWeight, fontFamily] of Object.entries(fonts)) {
113
- if (fontWeight === weight) {
114
- return fontFamily;
115
- }
116
- }
117
-
118
- return undefined;
119
- }
120
-
121
78
  function resolveVariantRecipe(
122
79
  theme: SurfaceTheme,
123
80
  variant: TextVariant,
@@ -173,48 +130,3 @@ function resolveVariantRecipe(
173
130
  };
174
131
  }
175
132
  }
176
-
177
- function resolveRoleSemantics(theme: SurfaceTheme, color: TextColor): RoleSemantics {
178
- switch (color) {
179
- case 'secondary':
180
- return theme.semantics.secondary;
181
- case 'tertiary':
182
- return theme.semantics.accent;
183
- case 'quaternary':
184
- return theme.semantics.highlight;
185
- case 'neutral':
186
- return theme.semantics.action.neutral;
187
- case 'error':
188
- return theme.semantics.error;
189
- case 'info':
190
- return theme.semantics.info;
191
- case 'danger':
192
- return theme.semantics.action.danger;
193
- case 'success':
194
- return theme.semantics.success;
195
- case 'warning':
196
- return theme.semantics.warning;
197
- case 'primary':
198
- default:
199
- return theme.semantics.action.primary;
200
- }
201
- }
202
-
203
- function resolveTextColor(theme: SurfaceTheme, emphasis: TextEmphasis, color?: TextColor): string {
204
- if (color) {
205
- const role = resolveRoleSemantics(theme, color);
206
- return emphasis === 'inverse' ? role.onSolidText : role.base;
207
- }
208
-
209
- switch (emphasis) {
210
- case 'muted':
211
- return theme.semantics.content.muted;
212
- case 'subtle':
213
- return theme.semantics.content.subtle;
214
- case 'inverse':
215
- return theme.semantics.content.inverse;
216
- case 'default':
217
- default:
218
- return theme.semantics.content.default;
219
- }
220
- }
@@ -1,21 +1,12 @@
1
1
  import type { ThemeRecipeOverrideValue } from '@ankhorage/contracts';
2
2
 
3
- import type {
4
- TextAlign,
5
- TextColor,
6
- TextEmphasis,
7
- TextVariant,
8
- TextWeight,
9
- } from '../../../types/text';
3
+ import type { TextVariant } from '../../../types/text';
4
+ import { resolveTypographyThemeRecipeFields } from './resolveTypographyThemeRecipeFields';
10
5
 
11
6
  export function resolveTextThemeRecipe(fields: Readonly<Record<string, ThemeRecipeOverrideValue>>) {
12
7
  return {
13
8
  variant: readVariant(fields.variant),
14
- color: readColor(fields.color),
15
- emphasis: readEmphasis(fields.emphasis),
16
- align: readAlign(fields.align),
17
- weight: readWeight(fields.weight),
18
- italic: typeof fields.italic === 'boolean' ? fields.italic : undefined,
9
+ ...resolveTypographyThemeRecipeFields(fields),
19
10
  };
20
11
  }
21
12
 
@@ -25,30 +16,3 @@ function readVariant(value: ThemeRecipeOverrideValue | undefined): TextVariant |
25
16
  if (value === 'label' || value === 'eyebrow' || value === 'code') return value;
26
17
  return undefined;
27
18
  }
28
-
29
- function readColor(value: ThemeRecipeOverrideValue | undefined): TextColor | undefined {
30
- if (typeof value !== 'string') return undefined;
31
- if (value === 'primary' || value === 'secondary' || value === 'tertiary') return value;
32
- if (value === 'quaternary' || value === 'neutral' || value === 'danger') return value;
33
- if (value === 'success' || value === 'warning' || value === 'error' || value === 'info')
34
- return value;
35
- return undefined;
36
- }
37
-
38
- function readEmphasis(value: ThemeRecipeOverrideValue | undefined): TextEmphasis | undefined {
39
- if (value === 'default' || value === 'muted' || value === 'subtle' || value === 'inverse')
40
- return value;
41
- return undefined;
42
- }
43
-
44
- function readAlign(value: ThemeRecipeOverrideValue | undefined): TextAlign | undefined {
45
- if (value === 'auto' || value === 'left' || value === 'right') return value;
46
- if (value === 'center' || value === 'justify') return value;
47
- return undefined;
48
- }
49
-
50
- function readWeight(value: ThemeRecipeOverrideValue | undefined): TextWeight | undefined {
51
- if (value === 'regular' || value === 'medium' || value === 'semiBold' || value === 'bold')
52
- return value;
53
- return undefined;
54
- }