@ankhorage/zora 0.6.0 → 0.6.2

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 (103) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +44 -1
  3. package/dist/components/card/Card.d.ts.map +1 -1
  4. package/dist/components/card/Card.js +2 -1
  5. package/dist/components/card/Card.js.map +1 -1
  6. package/dist/components/checkbox/CheckboxGroup.d.ts.map +1 -1
  7. package/dist/components/checkbox/CheckboxGroup.js +2 -1
  8. package/dist/components/checkbox/CheckboxGroup.js.map +1 -1
  9. package/dist/components/drawer/Drawer.d.ts.map +1 -1
  10. package/dist/components/drawer/Drawer.js +2 -1
  11. package/dist/components/drawer/Drawer.js.map +1 -1
  12. package/dist/components/form/FormError.d.ts.map +1 -1
  13. package/dist/components/form/FormError.js +3 -2
  14. package/dist/components/form/FormError.js.map +1 -1
  15. package/dist/components/form/FormField.d.ts.map +1 -1
  16. package/dist/components/form/FormField.js +2 -1
  17. package/dist/components/form/FormField.js.map +1 -1
  18. package/dist/components/input/Input.js +3 -3
  19. package/dist/components/input/Input.js.map +1 -1
  20. package/dist/components/input/types.d.ts +4 -4
  21. package/dist/components/input/types.d.ts.map +1 -1
  22. package/dist/components/input/types.js.map +1 -1
  23. package/dist/components/modal/Modal.d.ts.map +1 -1
  24. package/dist/components/modal/Modal.js +2 -1
  25. package/dist/components/modal/Modal.js.map +1 -1
  26. package/dist/components/radio/RadioGroup.d.ts.map +1 -1
  27. package/dist/components/radio/RadioGroup.js +2 -1
  28. package/dist/components/radio/RadioGroup.js.map +1 -1
  29. package/dist/components/tabs/Tabs.d.ts.map +1 -1
  30. package/dist/components/tabs/Tabs.js +3 -2
  31. package/dist/components/tabs/Tabs.js.map +1 -1
  32. package/dist/components/text/Text.d.ts +4 -0
  33. package/dist/components/text/Text.d.ts.map +1 -0
  34. package/dist/components/text/Text.js +47 -0
  35. package/dist/components/text/Text.js.map +1 -0
  36. package/dist/components/text/index.d.ts +3 -0
  37. package/dist/components/text/index.d.ts.map +1 -0
  38. package/dist/components/text/index.js +2 -0
  39. package/dist/components/text/index.js.map +1 -0
  40. package/dist/components/text/resolveTextRecipe.d.ts +15 -0
  41. package/dist/components/text/resolveTextRecipe.d.ts.map +1 -0
  42. package/dist/components/text/resolveTextRecipe.js +110 -0
  43. package/dist/components/text/resolveTextRecipe.js.map +1 -0
  44. package/dist/components/text/types.d.ts +26 -0
  45. package/dist/components/text/types.d.ts.map +1 -0
  46. package/dist/components/text/types.js +2 -0
  47. package/dist/components/text/types.js.map +1 -0
  48. package/dist/components/textarea/Textarea.js +3 -3
  49. package/dist/components/textarea/Textarea.js.map +1 -1
  50. package/dist/components/textarea/types.d.ts +4 -4
  51. package/dist/components/textarea/types.d.ts.map +1 -1
  52. package/dist/components/textarea/types.js.map +1 -1
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +1 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/layout/page-header/PageHeader.d.ts.map +1 -1
  58. package/dist/layout/page-header/PageHeader.js +2 -1
  59. package/dist/layout/page-header/PageHeader.js.map +1 -1
  60. package/dist/patterns/collection-editor/CollectionEditor.d.ts.map +1 -1
  61. package/dist/patterns/collection-editor/CollectionEditor.js +2 -1
  62. package/dist/patterns/collection-editor/CollectionEditor.js.map +1 -1
  63. package/dist/patterns/form-field/FormField.d.ts.map +1 -1
  64. package/dist/patterns/form-field/FormField.js +2 -1
  65. package/dist/patterns/form-field/FormField.js.map +1 -1
  66. package/dist/patterns/form-field/index.d.ts +0 -1
  67. package/dist/patterns/form-field/index.d.ts.map +1 -1
  68. package/dist/patterns/form-field/index.js.map +1 -1
  69. package/dist/patterns/section-header/SectionHeader.d.ts.map +1 -1
  70. package/dist/patterns/section-header/SectionHeader.js +2 -1
  71. package/dist/patterns/section-header/SectionHeader.js.map +1 -1
  72. package/dist/patterns/settings-row/SettingsRow.d.ts.map +1 -1
  73. package/dist/patterns/settings-row/SettingsRow.js +2 -1
  74. package/dist/patterns/settings-row/SettingsRow.js.map +1 -1
  75. package/dist/patterns/tile-grid/PaletteItem.d.ts.map +1 -1
  76. package/dist/patterns/tile-grid/PaletteItem.js +2 -1
  77. package/dist/patterns/tile-grid/PaletteItem.js.map +1 -1
  78. package/package.json +2 -2
  79. package/src/components/card/Card.tsx +2 -1
  80. package/src/components/checkbox/CheckboxGroup.tsx +2 -1
  81. package/src/components/drawer/Drawer.tsx +2 -1
  82. package/src/components/form/FormError.tsx +3 -2
  83. package/src/components/form/FormField.tsx +2 -1
  84. package/src/components/input/Input.tsx +5 -5
  85. package/src/components/input/types.ts +4 -4
  86. package/src/components/modal/Modal.tsx +2 -1
  87. package/src/components/radio/RadioGroup.tsx +2 -1
  88. package/src/components/tabs/Tabs.tsx +3 -6
  89. package/src/components/text/Text.tsx +93 -0
  90. package/src/components/text/index.ts +2 -0
  91. package/src/components/text/resolveTextRecipe.test.ts +333 -0
  92. package/src/components/text/resolveTextRecipe.ts +169 -0
  93. package/src/components/text/types.ts +38 -0
  94. package/src/components/textarea/Textarea.tsx +5 -5
  95. package/src/components/textarea/types.ts +4 -4
  96. package/src/index.ts +2 -0
  97. package/src/layout/page-header/PageHeader.tsx +2 -1
  98. package/src/patterns/collection-editor/CollectionEditor.tsx +2 -1
  99. package/src/patterns/form-field/FormField.tsx +2 -1
  100. package/src/patterns/form-field/index.ts +0 -1
  101. package/src/patterns/section-header/SectionHeader.tsx +2 -1
  102. package/src/patterns/settings-row/SettingsRow.tsx +2 -1
  103. package/src/patterns/tile-grid/PaletteItem.tsx +2 -1
@@ -0,0 +1,169 @@
1
+ import {
2
+ type AnkhTheme,
3
+ type Breakpoint,
4
+ type FontWeight,
5
+ resolveResponsive,
6
+ type Responsive,
7
+ } from '@ankhorage/surface';
8
+ import type { TextStyle } from 'react-native';
9
+
10
+ import type { TextAlign, TextTone, TextVariant, TextWeight } from './types';
11
+
12
+ interface VariantRecipe {
13
+ fontSize: number;
14
+ lineHeight: number;
15
+ weight: TextWeight;
16
+ textTransform?: TextStyle['textTransform'];
17
+ letterSpacing?: number;
18
+ }
19
+
20
+ interface ResolveTextStyleOptions {
21
+ theme: AnkhTheme;
22
+ breakpoint: Breakpoint;
23
+ variant?: Responsive<TextVariant>;
24
+ tone?: Responsive<TextTone>;
25
+ weight?: Responsive<TextWeight>;
26
+ align?: Responsive<TextAlign>;
27
+ italic?: boolean;
28
+ }
29
+
30
+ function isMediumBreakpointOrLarger(breakpoint: Breakpoint): boolean {
31
+ return breakpoint === 'md' || breakpoint === 'lg' || breakpoint === 'xl';
32
+ }
33
+
34
+ function resolveWeight(theme: AnkhTheme, weight: TextWeight): FontWeight {
35
+ return theme.typography.weights[weight];
36
+ }
37
+
38
+ function resolveFontFamily({
39
+ theme,
40
+ variant,
41
+ weight,
42
+ italic,
43
+ }: {
44
+ theme: AnkhTheme;
45
+ variant: TextVariant;
46
+ weight: FontWeight;
47
+ italic: boolean;
48
+ }): string | undefined {
49
+ if (variant === 'code') {
50
+ return 'monospace';
51
+ }
52
+
53
+ return theme.typography.fonts[italic ? 'italic' : 'normal'][weight];
54
+ }
55
+
56
+ function resolveVariantRecipe(
57
+ theme: AnkhTheme,
58
+ variant: TextVariant,
59
+ breakpoint: Breakpoint,
60
+ ): VariantRecipe {
61
+ switch (variant) {
62
+ case 'lead':
63
+ return {
64
+ fontSize: isMediumBreakpointOrLarger(breakpoint)
65
+ ? theme.typography.sizes.l
66
+ : theme.typography.sizes.m,
67
+ lineHeight: isMediumBreakpointOrLarger(breakpoint) ? 28 : 24,
68
+ weight: 'regular',
69
+ };
70
+ case 'bodySmall':
71
+ return {
72
+ fontSize: theme.typography.sizes.s,
73
+ lineHeight: 20,
74
+ weight: 'regular',
75
+ };
76
+ case 'caption':
77
+ return {
78
+ fontSize: theme.typography.sizes.xs,
79
+ lineHeight: 16,
80
+ weight: 'regular',
81
+ };
82
+ case 'label':
83
+ return {
84
+ fontSize: theme.typography.sizes.s,
85
+ lineHeight: 18,
86
+ weight: 'medium',
87
+ };
88
+ case 'eyebrow':
89
+ return {
90
+ fontSize: theme.typography.sizes.xs,
91
+ lineHeight: 16,
92
+ weight: 'semiBold',
93
+ textTransform: 'uppercase',
94
+ letterSpacing: 0.8,
95
+ };
96
+ case 'code':
97
+ return {
98
+ fontSize: theme.typography.sizes.s,
99
+ lineHeight: 20,
100
+ weight: 'regular',
101
+ };
102
+ case 'body':
103
+ default:
104
+ return {
105
+ fontSize: theme.typography.sizes.m,
106
+ lineHeight: 24,
107
+ weight: 'regular',
108
+ };
109
+ }
110
+ }
111
+
112
+ function resolveToneColor(theme: AnkhTheme, tone: TextTone): string {
113
+ switch (tone) {
114
+ case 'muted':
115
+ return theme.semantics.content.muted;
116
+ case 'subtle':
117
+ return theme.semantics.content.subtle;
118
+ case 'inverse':
119
+ return theme.semantics.content.inverse;
120
+ case 'primary':
121
+ return theme.semantics.brand.base;
122
+ case 'danger':
123
+ return theme.semantics.danger.base;
124
+ case 'success':
125
+ return theme.semantics.success.base;
126
+ case 'warning':
127
+ return theme.semantics.warning.base;
128
+ case 'default':
129
+ default:
130
+ return theme.semantics.content.default;
131
+ }
132
+ }
133
+
134
+ export function resolveTextStyle({
135
+ theme,
136
+ breakpoint,
137
+ variant,
138
+ tone,
139
+ weight,
140
+ align,
141
+ italic = false,
142
+ }: ResolveTextStyleOptions): TextStyle {
143
+ const resolvedVariant = resolveResponsive(variant, breakpoint) ?? 'body';
144
+ const resolvedTone = resolveResponsive(tone, breakpoint) ?? 'default';
145
+ const resolvedAlign = resolveResponsive(align, breakpoint);
146
+ const recipe = resolveVariantRecipe(theme, resolvedVariant, breakpoint);
147
+ const resolvedWeight = resolveWeight(
148
+ theme,
149
+ resolveResponsive(weight, breakpoint) ?? recipe.weight,
150
+ );
151
+
152
+ return {
153
+ color: resolveToneColor(theme, resolvedTone),
154
+ elevation: 0,
155
+ fontFamily: resolveFontFamily({
156
+ theme,
157
+ variant: resolvedVariant,
158
+ weight: resolvedWeight,
159
+ italic,
160
+ }),
161
+ fontSize: recipe.fontSize,
162
+ fontStyle: italic ? 'italic' : 'normal',
163
+ fontWeight: resolvedWeight,
164
+ letterSpacing: recipe.letterSpacing,
165
+ lineHeight: recipe.lineHeight,
166
+ textAlign: resolvedAlign,
167
+ textTransform: recipe.textTransform,
168
+ };
169
+ }
@@ -0,0 +1,38 @@
1
+ import type { Responsive } from '@ankhorage/surface';
2
+ import type React from 'react';
3
+ import type { AccessibilityRole, TextStyle } from 'react-native';
4
+
5
+ export type TextVariant = 'body' | 'lead' | 'bodySmall' | 'caption' | 'label' | 'eyebrow' | 'code';
6
+
7
+ export type TextTone =
8
+ | 'default'
9
+ | 'muted'
10
+ | 'subtle'
11
+ | 'inverse'
12
+ | 'primary'
13
+ | 'danger'
14
+ | 'success'
15
+ | 'warning';
16
+
17
+ export type TextWeight = 'regular' | 'medium' | 'semiBold' | 'bold';
18
+
19
+ export type TextAlign = NonNullable<TextStyle['textAlign']>;
20
+
21
+ export interface TextProps {
22
+ children?: React.ReactNode;
23
+ text?: string;
24
+ i18nKey?: string;
25
+ variant?: Responsive<TextVariant>;
26
+ tone?: Responsive<TextTone>;
27
+ align?: Responsive<TextAlign>;
28
+ weight?: Responsive<TextWeight>;
29
+ italic?: boolean;
30
+ numberOfLines?: number;
31
+ ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
32
+ selectable?: boolean;
33
+ accessibilityLabel?: string;
34
+ accessibilityHint?: string;
35
+ accessibilityRole?: AccessibilityRole;
36
+ nativeID?: string;
37
+ testID?: string;
38
+ }
@@ -1,20 +1,20 @@
1
- import { Icon, Textarea as SurfaceTextarea, useTheme } from '@ankhorage/surface';
1
+ import * as Surface from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
4
  import { resolveIconSize } from '../../internal/recipes';
5
5
  import type { TextareaProps } from './types';
6
6
 
7
7
  export function Textarea({ size = 'l', leadingIcon, trailingIcon, ...props }: TextareaProps) {
8
- const { theme } = useTheme();
8
+ const { theme } = Surface.useTheme();
9
9
  const iconSize = resolveIconSize(size);
10
10
  const iconColor = theme.semantics.content.muted;
11
11
 
12
12
  return (
13
- <SurfaceTextarea
13
+ <Surface.Textarea
14
14
  {...props}
15
15
  leadingAccessory={
16
16
  leadingIcon ? (
17
- <Icon
17
+ <Surface.Icon
18
18
  color={iconColor}
19
19
  name={leadingIcon.name}
20
20
  provider={leadingIcon.provider}
@@ -25,7 +25,7 @@ export function Textarea({ size = 'l', leadingIcon, trailingIcon, ...props }: Te
25
25
  size={size}
26
26
  trailingAccessory={
27
27
  trailingIcon ? (
28
- <Icon
28
+ <Surface.Icon
29
29
  color={iconColor}
30
30
  name={trailingIcon.name}
31
31
  provider={trailingIcon.provider}
@@ -1,12 +1,12 @@
1
- import type { ButtonIconSpec, TextareaProps as SurfaceTextareaProps } from '@ankhorage/surface';
1
+ import type * as Surface from '@ankhorage/surface';
2
2
 
3
3
  import type { ZoraControlSize } from '../../internal/recipes';
4
4
 
5
5
  export interface TextareaProps extends Omit<
6
- SurfaceTextareaProps,
6
+ Surface.TextareaProps,
7
7
  'leadingAccessory' | 'size' | 'trailingAccessory'
8
8
  > {
9
9
  size?: ZoraControlSize;
10
- leadingIcon?: ButtonIconSpec;
11
- trailingIcon?: ButtonIconSpec;
10
+ leadingIcon?: Surface.ButtonIconSpec;
11
+ trailingIcon?: Surface.ButtonIconSpec;
12
12
  }
package/src/index.ts CHANGED
@@ -51,6 +51,8 @@ export type { SelectOption, SelectProps } from './components/select';
51
51
  export { Select } from './components/select';
52
52
  export type { TabItem, TabsProps } from './components/tabs';
53
53
  export { Tabs } from './components/tabs';
54
+ export type { TextAlign, TextProps, TextTone, TextVariant, TextWeight } from './components/text';
55
+ export { Text } from './components/text';
54
56
  export type { TextareaProps } from './components/textarea';
55
57
  export { Textarea } from './components/textarea';
56
58
  export type { ToolbarActionProps, ToolbarProps } from './components/toolbar';
@@ -1,6 +1,7 @@
1
- import { Box, Heading, Stack, Text } from '@ankhorage/surface';
1
+ import { Box, Heading, Stack } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
+ import { Text } from '../../components/text';
4
5
  import type { PageHeaderProps } from './types';
5
6
 
6
7
  export function PageHeader({
@@ -1,8 +1,9 @@
1
- import { Box, Stack, Text } from '@ankhorage/surface';
1
+ import { Box, Stack } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
4
  import { Button } from '../../components/button';
5
5
  import { IconButton } from '../../components/icon-button';
6
+ import { Text } from '../../components/text';
6
7
  import { Panel } from '../panel';
7
8
  import type { CollectionEditorProps } from './types';
8
9
 
@@ -1,6 +1,7 @@
1
- import { Field, Stack, Text } from '@ankhorage/surface';
1
+ import { Field, Stack } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
+ import { Text } from '../../components/text';
4
5
  import type { FormFieldProps } from './types';
5
6
 
6
7
  export function FormField({ label, description, helperText, children, ...props }: FormFieldProps) {
@@ -1,2 +1 @@
1
1
  export { FormField } from './FormField';
2
- export type { FormFieldProps } from './types';
@@ -1,6 +1,7 @@
1
- import { Box, Heading, Stack, Text } from '@ankhorage/surface';
1
+ import { Box, Heading, Stack } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
+ import { Text } from '../../components/text';
4
5
  import type { SectionHeaderProps } from './types';
5
6
 
6
7
  export function SectionHeader({
@@ -1,7 +1,8 @@
1
- import { Box, Text } from '@ankhorage/surface';
1
+ import { Box } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
4
  import { Card } from '../../components/card';
5
+ import { Text } from '../../components/text';
5
6
  import type { SettingsRowProps } from './types';
6
7
 
7
8
  export function SettingsRow({
@@ -1,7 +1,8 @@
1
- import { Box, Heading, Text, useTheme } from '@ankhorage/surface';
1
+ import { Box, Heading, useTheme } from '@ankhorage/surface';
2
2
  import React from 'react';
3
3
 
4
4
  import { Card } from '../../components/card';
5
+ import { Text } from '../../components/text';
5
6
  import type { PaletteItemProps } from './types';
6
7
 
7
8
  export function PaletteItem({