@kanso-labs/react-native-kanso-ui 0.0.0-stage → 0.1.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 (145) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +205 -2
  3. package/dist/button/index.d.ts +56 -0
  4. package/dist/button/index.js +169 -0
  5. package/dist/button/index.js.map +1 -0
  6. package/dist/button/palettes.js +47 -0
  7. package/dist/button/palettes.js.map +1 -0
  8. package/dist/chip/index.js +194 -0
  9. package/dist/chip/index.js.map +1 -0
  10. package/dist/chip/styles.js +36 -0
  11. package/dist/chip/styles.js.map +1 -0
  12. package/dist/clipboard/index.js +58 -0
  13. package/dist/clipboard/index.js.map +1 -0
  14. package/dist/components/avatar/index.d.ts +82 -0
  15. package/dist/components/avatar/index.js +62 -0
  16. package/dist/components/avatar/index.js.map +1 -0
  17. package/dist/components/button/index.d.ts +87 -0
  18. package/dist/components/button/index.js +377 -0
  19. package/dist/components/button/index.js.map +1 -0
  20. package/dist/components/card/index.d.ts +78 -0
  21. package/dist/components/card/index.js +315 -0
  22. package/dist/components/card/index.js.map +1 -0
  23. package/dist/components/checkbox/index.d.ts +76 -0
  24. package/dist/components/checkbox/index.js +360 -0
  25. package/dist/components/checkbox/index.js.map +1 -0
  26. package/dist/components/chip/index.d.ts +84 -0
  27. package/dist/components/chip/index.js +257 -0
  28. package/dist/components/chip/index.js.map +1 -0
  29. package/dist/components/chip-group/index.d.ts +143 -0
  30. package/dist/components/chip-group/index.js +669 -0
  31. package/dist/components/chip-group/index.js.map +1 -0
  32. package/dist/components/copy-field/index.d.ts +60 -0
  33. package/dist/components/copy-field/index.js +277 -0
  34. package/dist/components/copy-field/index.js.map +1 -0
  35. package/dist/components/currency/index.d.ts +69 -0
  36. package/dist/components/currency/index.js +162 -0
  37. package/dist/components/currency/index.js.map +1 -0
  38. package/dist/components/form/index.d.ts +84 -0
  39. package/dist/components/form/index.js +95 -0
  40. package/dist/components/form/index.js.map +1 -0
  41. package/dist/components/icon-button/index.d.ts +68 -0
  42. package/dist/components/icon-button/index.js +289 -0
  43. package/dist/components/icon-button/index.js.map +1 -0
  44. package/dist/components/link/index.d.ts +59 -0
  45. package/dist/components/link/index.js +191 -0
  46. package/dist/components/link/index.js.map +1 -0
  47. package/dist/components/number-field/index.d.ts +151 -0
  48. package/dist/components/number-field/index.js +832 -0
  49. package/dist/components/number-field/index.js.map +1 -0
  50. package/dist/components/product-icon/index.d.ts +70 -0
  51. package/dist/components/product-icon/index.js +60 -0
  52. package/dist/components/product-icon/index.js.map +1 -0
  53. package/dist/components/radio-group/index.d.ts +105 -0
  54. package/dist/components/radio-group/index.js +597 -0
  55. package/dist/components/radio-group/index.js.map +1 -0
  56. package/dist/components/search-field/index.d.ts +98 -0
  57. package/dist/components/search-field/index.js +521 -0
  58. package/dist/components/search-field/index.js.map +1 -0
  59. package/dist/components/segmented-button/index.d.ts +113 -0
  60. package/dist/components/segmented-button/index.js +937 -0
  61. package/dist/components/segmented-button/index.js.map +1 -0
  62. package/dist/components/separator/index.d.ts +45 -0
  63. package/dist/components/separator/index.js +109 -0
  64. package/dist/components/separator/index.js.map +1 -0
  65. package/dist/components/stack/index.d.ts +70 -0
  66. package/dist/components/stack/index.js +107 -0
  67. package/dist/components/stack/index.js.map +1 -0
  68. package/dist/components/switch/index.d.ts +76 -0
  69. package/dist/components/switch/index.js +591 -0
  70. package/dist/components/switch/index.js.map +1 -0
  71. package/dist/components/text/index.d.ts +44 -0
  72. package/dist/components/text/index.js +78 -0
  73. package/dist/components/text/index.js.map +1 -0
  74. package/dist/components/text-field/index.d.ts +146 -0
  75. package/dist/components/text-field/index.js +228 -0
  76. package/dist/components/text-field/index.js.map +1 -0
  77. package/dist/control/index.js +117 -0
  78. package/dist/control/index.js.map +1 -0
  79. package/dist/control/styles.js +36 -0
  80. package/dist/control/styles.js.map +1 -0
  81. package/dist/field/index.d.ts +13 -0
  82. package/dist/field/index.js +1007 -0
  83. package/dist/field/index.js.map +1 -0
  84. package/dist/field/styles.js +131 -0
  85. package/dist/field/styles.js.map +1 -0
  86. package/dist/form/index.d.ts +24 -0
  87. package/dist/form/index.js +209 -0
  88. package/dist/form/index.js.map +1 -0
  89. package/dist/glyphs/icon-style.d.ts +25 -0
  90. package/dist/glyphs/icon-style.js +22 -0
  91. package/dist/glyphs/icon-style.js.map +1 -0
  92. package/dist/glyphs/index.js +170 -0
  93. package/dist/glyphs/index.js.map +1 -0
  94. package/dist/glyphs/styles.js +7 -0
  95. package/dist/glyphs/styles.js.map +1 -0
  96. package/dist/hooks/useWindowSizeClass.d.ts +25 -0
  97. package/dist/hooks/useWindowSizeClass.js +39 -0
  98. package/dist/hooks/useWindowSizeClass.js.map +1 -0
  99. package/dist/index.d.ts +31 -0
  100. package/dist/index.js +27 -0
  101. package/dist/mark/image.js +61 -0
  102. package/dist/mark/image.js.map +1 -0
  103. package/dist/mark/index.d.ts +9 -0
  104. package/dist/mark/index.js +234 -0
  105. package/dist/mark/index.js.map +1 -0
  106. package/dist/mark/initials.js +65 -0
  107. package/dist/mark/initials.js.map +1 -0
  108. package/dist/mark/styles.d.ts +1 -0
  109. package/dist/mark/styles.js +73 -0
  110. package/dist/mark/styles.js.map +1 -0
  111. package/dist/number/parser.js +321 -0
  112. package/dist/number/parser.js.map +1 -0
  113. package/dist/number/state.js +235 -0
  114. package/dist/number/state.js.map +1 -0
  115. package/dist/overlay/host.js +111 -0
  116. package/dist/overlay/host.js.map +1 -0
  117. package/dist/press/index.js +350 -0
  118. package/dist/press/index.js.map +1 -0
  119. package/dist/press/styles.js +31 -0
  120. package/dist/press/styles.js.map +1 -0
  121. package/dist/router/index.d.ts +28 -0
  122. package/dist/router/index.js +82 -0
  123. package/dist/router/index.js.map +1 -0
  124. package/dist/theme/color.js +25 -0
  125. package/dist/theme/color.js.map +1 -0
  126. package/dist/theme/resolve.d.ts +6 -0
  127. package/dist/theme/resolve.js +310 -0
  128. package/dist/theme/resolve.js.map +1 -0
  129. package/dist/theme/scope.d.ts +42 -0
  130. package/dist/theme/scope.js +80 -0
  131. package/dist/theme/scope.js.map +1 -0
  132. package/dist/theme/styles.js +39 -0
  133. package/dist/theme/styles.js.map +1 -0
  134. package/dist/theme-scope.d.ts +56 -0
  135. package/dist/theme-scope.js +127 -0
  136. package/dist/theme-scope.js.map +1 -0
  137. package/dist/tokens/defaults.d.ts +407 -0
  138. package/dist/tokens/defaults.js +403 -0
  139. package/dist/tokens/defaults.js.map +1 -0
  140. package/dist/typography/fonts.js +84 -0
  141. package/dist/typography/fonts.js.map +1 -0
  142. package/dist/typography/roles.d.ts +10 -0
  143. package/dist/typography/roles.js +82 -0
  144. package/dist/typography/roles.js.map +1 -0
  145. package/package.json +132 -4
@@ -0,0 +1,289 @@
1
+ import { IconStyleContext } from "../../glyphs/icon-style.js";
2
+ import { useTheme } from "../../theme/scope.js";
3
+ import { composeStyles, themedStyles } from "../../theme/styles.js";
4
+ import { AnimatedPressable, HEIGHTS, OUTLINE_WIDTHS, PRESSED_CORNERS, buttonStyles, toggleState, useButtonAction, useCorner } from "../../button/index.js";
5
+ import { palettesOf } from "../../button/palettes.js";
6
+ import { hitSlop, usePressFeedback } from "../../press/index.js";
7
+ import { c } from "react/compiler-runtime";
8
+ import { StyleSheet } from "react-native";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import Animated from "react-native-reanimated";
11
+ //#region src/components/icon-button/index.tsx
12
+ const DISABLED = {
13
+ filled: "filledDisabled",
14
+ outlined: "outlinedDisabled",
15
+ standard: "textDisabled",
16
+ tonal: "filledDisabled"
17
+ };
18
+ const ICON_SIZES = {
19
+ lg: 24,
20
+ md: 24,
21
+ xl: 32,
22
+ xs: 20,
23
+ xxl: 40
24
+ };
25
+ const TOGGLE_PALETTES = {
26
+ filled: {
27
+ selected: "filledToggleSelected",
28
+ unselected: "filledToggle"
29
+ },
30
+ outlined: {
31
+ selected: "outlinedToggleSelected",
32
+ unselected: "outlined"
33
+ },
34
+ standard: {
35
+ selected: "standardToggleSelected",
36
+ unselected: "standard"
37
+ },
38
+ tonal: {
39
+ selected: "tonalToggleSelected",
40
+ unselected: "tonal"
41
+ }
42
+ };
43
+ const styles = StyleSheet.create({ base: {
44
+ alignItems: "center",
45
+ flexShrink: 0,
46
+ justifyContent: "center"
47
+ } });
48
+ const outlineWidths = StyleSheet.create({
49
+ lg: { borderWidth: OUTLINE_WIDTHS.lg },
50
+ md: { borderWidth: OUTLINE_WIDTHS.md },
51
+ xl: { borderWidth: OUTLINE_WIDTHS.xl },
52
+ xs: { borderWidth: OUTLINE_WIDTHS.xs },
53
+ xxl: { borderWidth: OUTLINE_WIDTHS.xxl }
54
+ });
55
+ const sizesOf = themedStyles(({ sizing }) => {
56
+ function square(size) {
57
+ const edge = sizing[HEIGHTS[size]];
58
+ return {
59
+ height: edge,
60
+ width: edge
61
+ };
62
+ }
63
+ return StyleSheet.create({
64
+ lg: square("lg"),
65
+ md: square("md"),
66
+ xl: square("xl"),
67
+ xs: square("xs"),
68
+ xxl: square("xxl")
69
+ });
70
+ });
71
+ /**
72
+ * A button that is an icon, at five control heights, with web's props and
73
+ * values. Given `href` it is a link with the same appearance, and given
74
+ * `isSelected`, `defaultSelected` or `onChange` it is a toggle, which reports
75
+ * its state to a screen reader and draws the page's second pair of colour
76
+ * roles for its variant. The three forms are exclusive, so a toggle given
77
+ * `href` does not compile.
78
+ *
79
+ * ```tsx
80
+ * <IconButton aria-label="Label" defaultSelected variant="tonal">
81
+ * <Icon />
82
+ * </IconButton>
83
+ * ```
84
+ *
85
+ * The two sizes under 48dp, `xs` and `md`, take presses over a 48dp target
86
+ * through `hitSlop`, which a `hitSlop` of the call site's own replaces.
87
+ * `style`, `ref` and `testID` land on the `Pressable`.
88
+ */
89
+ function IconButton(t0) {
90
+ const $ = c(58);
91
+ let children;
92
+ let defaultSelected;
93
+ let href;
94
+ let isSelected;
95
+ let onBlur;
96
+ let onChange;
97
+ let onFocus;
98
+ let onHoverIn;
99
+ let onHoverOut;
100
+ let onLayout;
101
+ let onPress;
102
+ let onPressIn;
103
+ let onPressOut;
104
+ let ownHitSlop;
105
+ let props;
106
+ let style;
107
+ let t1;
108
+ let t2;
109
+ let t3;
110
+ let t4;
111
+ let type;
112
+ if ($[0] !== t0) {
113
+ ({children, defaultSelected, disableRipple: t1, hitSlop: ownHitSlop, href, isDisabled: t2, isSelected, onBlur, onChange, onFocus, onHoverIn, onHoverOut, onLayout, onPress, onPressIn, onPressOut, size: t3, style, type, variant: t4, ...props} = t0);
114
+ $[0] = t0;
115
+ $[1] = children;
116
+ $[2] = defaultSelected;
117
+ $[3] = href;
118
+ $[4] = isSelected;
119
+ $[5] = onBlur;
120
+ $[6] = onChange;
121
+ $[7] = onFocus;
122
+ $[8] = onHoverIn;
123
+ $[9] = onHoverOut;
124
+ $[10] = onLayout;
125
+ $[11] = onPress;
126
+ $[12] = onPressIn;
127
+ $[13] = onPressOut;
128
+ $[14] = ownHitSlop;
129
+ $[15] = props;
130
+ $[16] = style;
131
+ $[17] = t1;
132
+ $[18] = t2;
133
+ $[19] = t3;
134
+ $[20] = t4;
135
+ $[21] = type;
136
+ } else {
137
+ children = $[1];
138
+ defaultSelected = $[2];
139
+ href = $[3];
140
+ isSelected = $[4];
141
+ onBlur = $[5];
142
+ onChange = $[6];
143
+ onFocus = $[7];
144
+ onHoverIn = $[8];
145
+ onHoverOut = $[9];
146
+ onLayout = $[10];
147
+ onPress = $[11];
148
+ onPressIn = $[12];
149
+ onPressOut = $[13];
150
+ ownHitSlop = $[14];
151
+ props = $[15];
152
+ style = $[16];
153
+ t1 = $[17];
154
+ t2 = $[18];
155
+ t3 = $[19];
156
+ t4 = $[20];
157
+ type = $[21];
158
+ }
159
+ const disableRipple = t1 === void 0 ? false : t1;
160
+ const isDisabled = t2 === void 0 ? false : t2;
161
+ const size = t3 === void 0 ? "md" : t3;
162
+ const variant = t4 === void 0 ? "standard" : t4;
163
+ const theme = useTheme();
164
+ const isToggle = defaultSelected !== void 0 || isSelected !== void 0 || onChange !== void 0;
165
+ let t5;
166
+ if ($[22] !== defaultSelected || $[23] !== href || $[24] !== isSelected || $[25] !== isToggle || $[26] !== onChange || $[27] !== onPress || $[28] !== type) {
167
+ t5 = {
168
+ defaultSelected,
169
+ href,
170
+ isSelected,
171
+ isToggle,
172
+ onChange,
173
+ onPress,
174
+ type
175
+ };
176
+ $[22] = defaultSelected;
177
+ $[23] = href;
178
+ $[24] = isSelected;
179
+ $[25] = isToggle;
180
+ $[26] = onChange;
181
+ $[27] = onPress;
182
+ $[28] = type;
183
+ $[29] = t5;
184
+ } else t5 = $[29];
185
+ const action = useButtonAction(t5);
186
+ const colors = palettesOf(theme)[isDisabled ? DISABLED[variant] : isToggle ? TOGGLE_PALETTES[variant][action.selected ? "selected" : "unselected"] : variant];
187
+ const feedback = usePressFeedback({
188
+ color: colors.content,
189
+ disabled: isDisabled,
190
+ disableRipple,
191
+ onBlur,
192
+ onFocus,
193
+ onHoverIn,
194
+ onHoverOut,
195
+ onPressIn,
196
+ onPressOut
197
+ });
198
+ const { radii, sizing } = theme;
199
+ const edge = sizing[HEIGHTS[size]];
200
+ const shaped = useCorner(feedback.pressed || action.selected ? radii[PRESSED_CORNERS[size]] : radii.pill, onLayout);
201
+ const T0 = AnimatedPressable;
202
+ const t6 = href === void 0 ? "button" : "link";
203
+ let t7;
204
+ if ($[30] !== action.selected || $[31] !== isToggle) {
205
+ t7 = isToggle ? toggleState(action.selected) : void 0;
206
+ $[30] = action.selected;
207
+ $[31] = isToggle;
208
+ $[32] = t7;
209
+ } else t7 = $[32];
210
+ const t8 = feedback.handlers;
211
+ let t9;
212
+ if ($[33] !== edge || $[34] !== ownHitSlop) {
213
+ t9 = ownHitSlop ?? hitSlop(edge, edge);
214
+ $[33] = edge;
215
+ $[34] = ownHitSlop;
216
+ $[35] = t9;
217
+ } else t9 = $[35];
218
+ const t10 = shaped.onLayout;
219
+ const t11 = action.onPress;
220
+ const t12 = composeStyles(styles.base, sizesOf(theme)[size], variant === "outlined" ? outlineWidths[size] : void 0, colors.container, shaped.corner, feedback.ring, style);
221
+ let t13;
222
+ if ($[36] !== shaped.corner) {
223
+ t13 = composeStyles(buttonStyles.clip, shaped.corner);
224
+ $[36] = shaped.corner;
225
+ $[37] = t13;
226
+ } else t13 = $[37];
227
+ let t14;
228
+ if ($[38] !== feedback.layer || $[39] !== t13) {
229
+ t14 = /* @__PURE__ */ jsx(Animated.View, {
230
+ style: t13,
231
+ children: feedback.layer
232
+ });
233
+ $[38] = feedback.layer;
234
+ $[39] = t13;
235
+ $[40] = t14;
236
+ } else t14 = $[40];
237
+ const T1 = IconStyleContext;
238
+ const t15 = iconStyleOf(colors.content, size);
239
+ let t16;
240
+ if ($[41] !== T1 || $[42] !== children || $[43] !== t15) {
241
+ t16 = /* @__PURE__ */ jsx(T1, {
242
+ value: t15,
243
+ children
244
+ });
245
+ $[41] = T1;
246
+ $[42] = children;
247
+ $[43] = t15;
248
+ $[44] = t16;
249
+ } else t16 = $[44];
250
+ let t17;
251
+ if ($[45] !== T0 || $[46] !== action.onPress || $[47] !== feedback.handlers || $[48] !== isDisabled || $[49] !== props || $[50] !== shaped.onLayout || $[51] !== t12 || $[52] !== t14 || $[53] !== t16 || $[54] !== t6 || $[55] !== t7 || $[56] !== t9) {
252
+ t17 = /* @__PURE__ */ jsxs(T0, {
253
+ role: t6,
254
+ ...t7,
255
+ ...props,
256
+ ...t8,
257
+ disabled: isDisabled,
258
+ hitSlop: t9,
259
+ onLayout: t10,
260
+ onPress: t11,
261
+ style: t12,
262
+ children: [t14, t16]
263
+ });
264
+ $[45] = T0;
265
+ $[46] = action.onPress;
266
+ $[47] = feedback.handlers;
267
+ $[48] = isDisabled;
268
+ $[49] = props;
269
+ $[50] = shaped.onLayout;
270
+ $[51] = t12;
271
+ $[52] = t14;
272
+ $[53] = t16;
273
+ $[54] = t6;
274
+ $[55] = t7;
275
+ $[56] = t9;
276
+ $[57] = t17;
277
+ } else t17 = $[57];
278
+ return t17;
279
+ }
280
+ function iconStyleOf(color, size) {
281
+ return {
282
+ color,
283
+ size: ICON_SIZES[size]
284
+ };
285
+ }
286
+ //#endregion
287
+ export { IconButton };
288
+
289
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ReactNode","Ref","PressableProps","StyleProp","View","ViewStyle","AnimatedStyle","StyleSheet","Animated","ButtonLinkForm","ButtonPressForm","ButtonToggleForm","PaletteName","IconStyle","AnimatedPressable","buttonStyles","HEIGHTS","OUTLINE_WIDTHS","PRESSED_CORNERS","toggleState","useButtonAction","useCorner","palettesOf","IconStyleContext","hitSlop","usePressFeedback","useTheme","composeStyles","themedStyles","IconButtonProps","Omit","children","disableRipple","isDisabled","ref","size","IconButtonSize","style","variant","IconButtonVariant","DISABLED","Readonly","Record","filled","outlined","standard","tonal","ICON_SIZES","lg","md","xl","xs","xxl","TOGGLE_PALETTES","selected","unselected","styles","create","base","alignItems","flexShrink","justifyContent","outlineWidths","borderWidth","sizesOf","sizing","square","edge","height","width","IconButton","t0","$","_c","defaultSelected","href","isSelected","onBlur","onChange","onFocus","onHoverIn","onHoverOut","onLayout","onPress","onPressIn","onPressOut","ownHitSlop","props","t1","t2","t3","t4","type","undefined","theme","isToggle","t5","action","colors","feedback","color","content","disabled","radii","shaped","pressed","pill","T0","t6","t7","t8","handlers","t9","t10","t11","t12","container","corner","ring","t13","clip","t14","layer","T1","t15","iconStyleOf","t16","t17","_c"],"sources":["../../../src/components/icon-button/index.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react'\nimport type { PressableProps, StyleProp, View, ViewStyle } from 'react-native'\nimport type { AnimatedStyle } from 'react-native-reanimated'\n\nimport { StyleSheet } from 'react-native'\nimport Animated from 'react-native-reanimated'\n\nimport type {\n ButtonLinkForm,\n ButtonPressForm,\n ButtonToggleForm,\n} from '../../button'\nimport type { PaletteName } from '../../button/palettes'\nimport type { IconStyle } from '../../glyphs/icon-style'\n\nimport {\n AnimatedPressable,\n buttonStyles,\n HEIGHTS,\n OUTLINE_WIDTHS,\n PRESSED_CORNERS,\n toggleState,\n useButtonAction,\n useCorner,\n} from '../../button'\nimport { palettesOf } from '../../button/palettes'\nimport { IconStyleContext } from '../../glyphs/icon-style'\nimport { hitSlop, usePressFeedback } from '../../press'\nimport { useTheme } from '../../theme/scope'\nimport { composeStyles, themedStyles } from '../../theme/styles'\n\n// The icon buttons spec page's four styles at its five sizes, as kanso-ui's\n// IconButton draws them: Button's chrome around a single icon. The pairs are\n// the page's: filled on primary, tonal on secondary container, outlined with\n// an outline-variant rule and an on-surface-variant icon, and standard,\n// transparent, with the same icon over whatever it sits on. Disabled is\n// Button's, on-surface at the two disabled opacities, and a standard button\n// takes the text button's colour since neither has a container.\n//\n// The sizes are the page's XS to XL at Button's five heights, so the two line\n// up in a row: a square of 32, 40, 56, 96 or 136dp holding an icon of 20, 24,\n// 24, 32 or 40dp. The two middle sizes share one icon, and the container\n// alone grows between them. The two smallest take presses over a 48dp target\n// through `hitSlop`, which is the page's floor for them.\n//\n// **A toggle is the same button reporting a state.** Given `isSelected`,\n// `defaultSelected` or `onChange` it takes the page's second pair of colour\n// roles for its variant: a filled toggle rests on surface container with an\n// on-surface-variant icon and takes primary once selected, a tonal one moves\n// from the secondary container pair to secondary, a standard one stays\n// transparent while its icon moves to primary, and an outlined one swaps its\n// rule for the inverse surface pair. So a selected filled toggle looks like a\n// plain filled button, and an unselected one does not.\n//\n// **The corner morphs from a circle to a rounded square.** A press tightens\n// it to the size's pressed corner, 8dp for the two small sizes, 12dp at\n// `lg` and 16dp at the two large, and a selected toggle rests there, which is\n// the page's round-to-square morph. It eases as Button's does.\n//\n// The forms, the toggle's state, what a press does and the corner's ease are\n// src/button's, shared with Button.\n\ntype IconButtonProps = (ButtonLinkForm | ButtonPressForm | ButtonToggleForm) &\n Omit<PressableProps, 'aria-label' | 'children' | 'disabled' | 'style'> & {\n /**\n * What the button does, in words. Required rather than optional: an icon\n * on its own has no accessible name, so without this the control\n * announces nothing at all.\n */\n readonly 'aria-label': string\n /**\n * The icon. The button hands it its colour and the page's icon size for\n * the button's size through `useIconStyle()`.\n */\n readonly children?: ReactNode\n /**\n * Draws no press ripple. The state layer is unaffected.\n * @default false\n */\n readonly disableRipple?: boolean\n /**\n * Draws the button disabled, and takes no presses.\n * @default false\n */\n readonly isDisabled?: boolean\n readonly ref?: Ref<View>\n /**\n * Control size: `xs` 32dp, `md` 40dp, `lg` 56dp, `xl` 96dp, `xxl` 136dp,\n * the icon buttons spec page's XS to XL, and the same heights `Button`\n * uses, so the two line up beside each other in a row. The icon is 20dp,\n * 24dp, 24dp, 32dp and 40dp in turn.\n * @default 'md'\n */\n readonly size?: IconButtonSize\n readonly style?: StyleProp<ViewStyle>\n /**\n * `standard` is transparent and tints what it sits on; `outlined` is\n * transparent with a rule around it; `filled` and `tonal` carry a\n * container of their own.\n * @default 'standard'\n */\n readonly variant?: IconButtonVariant\n }\n\ntype IconButtonSize = 'lg' | 'md' | 'xl' | 'xs' | 'xxl'\n\ntype IconButtonVariant = 'filled' | 'outlined' | 'standard' | 'tonal'\n\n// The disabled container each variant draws. Filled and tonal share the\n// page's one disabled container, and standard draws the text button's\n// colour, which is the icon alone.\nconst DISABLED: Readonly<Record<IconButtonVariant, PaletteName>> = {\n filled: 'filledDisabled',\n outlined: 'outlinedDisabled',\n standard: 'textDisabled',\n tonal: 'filledDisabled',\n}\n\n// The icon each size holds, from the page's size token sets. Literals, as on\n// web: they are icon sizes, which the theme has no scale for.\nconst ICON_SIZES: Readonly<Record<IconButtonSize, number>> = {\n lg: 24,\n md: 24,\n xl: 32,\n xs: 20,\n xxl: 40,\n}\n\n// Which container a toggle draws, selected and not. An unselected outlined,\n// standard or tonal toggle is the plain button of that variant.\nconst TOGGLE_PALETTES: Readonly<\n Record<\n IconButtonVariant,\n Readonly<Record<'selected' | 'unselected', PaletteName>>\n >\n> = {\n filled: { selected: 'filledToggleSelected', unselected: 'filledToggle' },\n outlined: { selected: 'outlinedToggleSelected', unselected: 'outlined' },\n standard: { selected: 'standardToggleSelected', unselected: 'standard' },\n tonal: { selected: 'tonalToggleSelected', unselected: 'tonal' },\n}\n\nconst styles = StyleSheet.create({\n // The icon sits in the middle of a square that a row never squeezes.\n base: {\n alignItems: 'center',\n flexShrink: 0,\n justifyContent: 'center',\n },\n})\n\n// The outlined rule's width at each size, Button's.\nconst outlineWidths = StyleSheet.create({\n lg: { borderWidth: OUTLINE_WIDTHS.lg },\n md: { borderWidth: OUTLINE_WIDTHS.md },\n xl: { borderWidth: OUTLINE_WIDTHS.xl },\n xs: { borderWidth: OUTLINE_WIDTHS.xs },\n xxl: { borderWidth: OUTLINE_WIDTHS.xxl },\n})\n\n// Square, so one control height sets both edges.\nconst sizesOf = themedStyles(({ sizing }) => {\n function square(size: IconButtonSize): ViewStyle {\n const edge = sizing[HEIGHTS[size]]\n\n return { height: edge, width: edge }\n }\n\n return StyleSheet.create({\n lg: square('lg'),\n md: square('md'),\n xl: square('xl'),\n xs: square('xs'),\n xxl: square('xxl'),\n })\n})\n\n/**\n * A button that is an icon, at five control heights, with web's props and\n * values. Given `href` it is a link with the same appearance, and given\n * `isSelected`, `defaultSelected` or `onChange` it is a toggle, which reports\n * its state to a screen reader and draws the page's second pair of colour\n * roles for its variant. The three forms are exclusive, so a toggle given\n * `href` does not compile.\n *\n * ```tsx\n * <IconButton aria-label=\"Label\" defaultSelected variant=\"tonal\">\n * <Icon />\n * </IconButton>\n * ```\n *\n * The two sizes under 48dp, `xs` and `md`, take presses over a 48dp target\n * through `hitSlop`, which a `hitSlop` of the call site's own replaces.\n * `style`, `ref` and `testID` land on the `Pressable`.\n */\nfunction IconButton({\n children,\n defaultSelected,\n disableRipple = false,\n hitSlop: ownHitSlop,\n href,\n isDisabled = false,\n isSelected,\n onBlur,\n onChange,\n onFocus,\n onHoverIn,\n onHoverOut,\n onLayout,\n onPress,\n onPressIn,\n onPressOut,\n size = 'md',\n style,\n type,\n variant = 'standard',\n ...props\n}: IconButtonProps) {\n const theme = useTheme()\n\n // The three props that make this a toggle, read as web reads them.\n const isToggle =\n defaultSelected !== undefined ||\n isSelected !== undefined ||\n onChange !== undefined\n const action = useButtonAction({\n defaultSelected,\n href,\n isSelected,\n isToggle,\n onChange,\n onPress,\n type,\n })\n const colors =\n palettesOf(theme)[\n isDisabled\n ? DISABLED[variant]\n : isToggle\n ? TOGGLE_PALETTES[variant][\n action.selected ? 'selected' : 'unselected'\n ]\n : variant\n ]\n\n const feedback = usePressFeedback({\n color: colors.content,\n disabled: isDisabled,\n disableRipple,\n onBlur,\n onFocus,\n onHoverIn,\n onHoverOut,\n onPressIn,\n onPressOut,\n })\n\n const { radii, sizing } = theme\n const edge = sizing[HEIGHTS[size]]\n const shaped = useCorner(\n feedback.pressed || action.selected\n ? radii[PRESSED_CORNERS[size]]\n : radii.pill,\n onLayout,\n )\n\n return (\n <AnimatedPressable\n role={href === undefined ? 'button' : 'link'}\n {...(isToggle ? toggleState(action.selected) : undefined)}\n {...props}\n {...feedback.handlers}\n disabled={isDisabled}\n hitSlop={ownHitSlop ?? hitSlop(edge, edge)}\n onLayout={shaped.onLayout}\n onPress={action.onPress}\n style={composeStyles<AnimatedStyle<ViewStyle>>(\n styles.base,\n sizesOf(theme)[size],\n variant === 'outlined' ? outlineWidths[size] : undefined,\n colors.container,\n shaped.corner,\n feedback.ring,\n style,\n )}\n >\n <Animated.View\n style={composeStyles<AnimatedStyle<ViewStyle>>(\n buttonStyles.clip,\n shaped.corner,\n )}\n >\n {feedback.layer}\n </Animated.View>\n <IconStyleContext value={iconStyleOf(colors.content, size)}>\n {children}\n </IconStyleContext>\n </AnimatedPressable>\n )\n}\n\nfunction iconStyleOf(color: string, size: IconButtonSize): IconStyle {\n return { color, size: ICON_SIZES[size] }\n}\n\nexport { IconButton }\nexport type { IconButtonProps, IconButtonSize, IconButtonVariant }\n"],"mappings":";;;;;;;;;;;AA+GA,MAAMwC,WAA6D;CACjEG,QAAQ;CACRC,UAAU;CACVC,UAAU;CACVC,OAAO;AACT;AAIA,MAAMC,aAAuD;CAC3DC,IAAI;CACJC,IAAI;CACJC,IAAI;CACJC,IAAI;CACJC,KAAK;AACP;AAIA,MAAMC,kBAKF;CACFV,QAAQ;EAAEW,UAAU;EAAwBC,YAAY;CAAe;CACvEX,UAAU;EAAEU,UAAU;EAA0BC,YAAY;CAAW;CACvEV,UAAU;EAAES,UAAU;EAA0BC,YAAY;CAAW;CACvET,OAAO;EAAEQ,UAAU;EAAuBC,YAAY;CAAQ;AAChE;AAEA,MAAMC,SAASjD,WAAWkD,OAAO,EAE/BC,MAAM;CACJC,YAAY;CACZC,YAAY;CACZC,gBAAgB;AAClB,EACF,CAAC;AAGD,MAAMC,gBAAgBvD,WAAWkD,OAAO;CACtCT,IAAI,EAAEe,aAAa9C,eAAe+B,GAAG;CACrCC,IAAI,EAAEc,aAAa9C,eAAegC,GAAG;CACrCC,IAAI,EAAEa,aAAa9C,eAAeiC,GAAG;CACrCC,IAAI,EAAEY,aAAa9C,eAAekC,GAAG;CACrCC,KAAK,EAAEW,aAAa9C,eAAemC,IAAI;AACzC,CAAC;AAGD,MAAMY,UAAUpC,cAAc,EAAEqC,aAAa;CAC3C,SAASC,OAAO/B,MAAiC;EAC/C,MAAMgC,OAAOF,OAAOjD,QAAQmB;EAE5B,OAAO;GAAEiC,QAAQD;GAAME,OAAOF;EAAK;CACrC;CAEA,OAAO5D,WAAWkD,OAAO;EACvBT,IAAIkB,OAAO,IAAI;EACfjB,IAAIiB,OAAO,IAAI;EACfhB,IAAIgB,OAAO,IAAI;EACff,IAAIe,OAAO,IAAI;EACfd,KAAKc,OAAO,KAAK;CACnB,CAAC;AACH,CAAC;;;;;;;;;;;;;;;;;;;AAoBD,SAAAI,WAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAA1C;CAAA,IAAA2C;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAlD;CAAA,IAAAmD;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAApB,EAAA,OAAAD,IAAA;EAAoB,CAAA,CAAAxC,UAAA2C,iBAAA1C,eAAAwD,IAAAhE,SAAA8D,YAAAX,MAAA1C,YAAAwD,IAAAb,YAAAC,QAAAC,UAAAC,SAAAC,WAAAC,YAAAC,UAAAC,SAAAC,WAAAC,YAAAlD,MAAAuD,IAAArD,OAAAuD,MAAAtD,SAAAqD,IAAA,GAAAJ,SAAAhB;EAsBFC,EAAA,KAAAD;EAAAC,EAAA,KAAAzC;EAAAyC,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;EAAAL,EAAA,KAAAM;EAAAN,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;EAAAT,EAAA,MAAAU;EAAAV,EAAA,MAAAW;EAAAX,EAAA,MAAAY;EAAAZ,EAAA,MAAAa;EAAAb,EAAA,MAAAc;EAAAd,EAAA,MAAAe;EAAAf,EAAA,MAAAnC;EAAAmC,EAAA,MAAAgB;EAAAhB,EAAA,MAAAiB;EAAAjB,EAAA,MAAAkB;EAAAlB,EAAA,MAAAmB;EAAAnB,EAAA,MAAAoB;CAAA,OAAA;EAAA7D,WAAAyC,EAAA;EAAAE,kBAAAF,EAAA;EAAAG,OAAAH,EAAA;EAAAI,aAAAJ,EAAA;EAAAK,SAAAL,EAAA;EAAAM,WAAAN,EAAA;EAAAO,UAAAP,EAAA;EAAAQ,YAAAR,EAAA;EAAAS,aAAAT,EAAA;EAAAU,WAAAV,EAAA;EAAAW,UAAAX,EAAA;EAAAY,YAAAZ,EAAA;EAAAa,aAAAb,EAAA;EAAAc,aAAAd,EAAA;EAAAe,QAAAf,EAAA;EAAAnC,QAAAmC,EAAA;EAAAgB,KAAAhB,EAAA;EAAAiB,KAAAjB,EAAA;EAAAkB,KAAAlB,EAAA;EAAAmB,KAAAnB,EAAA;EAAAoB,OAAApB,EAAA;CAAA;CAnBhB,MAAAxC,gBAAAwD,OAAAK,KAAAA,IAAA,QAAAL;CAGA,MAAAvD,aAAAwD,OAAAI,KAAAA,IAAA,QAAAJ;CAWA,MAAAtD,OAAAuD,OAAAG,KAAAA,IAAA,OAAAH;CAGA,MAAApD,UAAAqD,OAAAE,KAAAA,IAAA,aAAAF;CAGA,MAAAG,QAAcpE,SAAS;CAGvB,MAAAqE,WACErB,oBAAoBmB,KAAAA,KACpBjB,eAAeiB,KAAAA,KACff,aAAae,KAAAA;CAAS,IAAAG;CAAA,IAAAxB,EAAA,QAAAE,mBAAAF,EAAA,QAAAG,QAAAH,EAAA,QAAAI,cAAAJ,EAAA,QAAAuB,YAAAvB,EAAA,QAAAM,YAAAN,EAAA,QAAAW,WAAAX,EAAA,QAAAoB,MAAA;EACOI,KAAA;GAAAtB;GAAAC;GAAAC;GAAAmB;GAAAjB;GAAAK;GAAAS;EAQ/B;EAACpB,EAAA,MAAAE;EAAAF,EAAA,MAAAG;EAAAH,EAAA,MAAAI;EAAAJ,EAAA,MAAAuB;EAAAvB,EAAA,MAAAM;EAAAN,EAAA,MAAAW;EAAAX,EAAA,MAAAoB;EAAApB,EAAA,MAAAwB;CAAA,OAAAA,KAAAxB,EAAA;CARD,MAAAyB,SAAe7E,gBAAgB4E,EAQ9B;CACD,MAAAE,SACE5E,WAAWwE,KAAK,CAAC,CACf7D,aACIO,SAASF,WACTyD,WACE1C,gBAAgBf,QAAQ,CACtB2D,OAAM3C,WAAN,aAAA,gBAFJhB;CAOR,MAAA6D,WAAiB1E,iBAAiB;EAAA2E,OACzBF,OAAMG;EAAQC,UACXrE;EAAUD;EAAA6C;EAAAE;EAAAC;EAAAC;EAAAG;EAAAC;CAQtB,CAAC;CAED,MAAA,EAAAkB,OAAAtC,WAA0B6B;CAC1B,MAAA3B,OAAaF,OAAOjD,QAAQmB;CAC5B,MAAAqE,SAAenF,UACb8E,SAAQM,WAAYR,OAAM3C,WACtBiD,MAAMrF,gBAAgBiB,SACtBoE,MAAKG,MACTxB,QACF;CAGG,MAAAyB,KAAA7F;CACO,MAAA8F,KAAAjC,SAASkB,KAAAA,IAAT,WAAA;CAAsC,IAAAgB;CAAA,IAAArC,EAAA,QAAAyB,OAAA3C,YAAAkB,EAAA,QAAAuB,UAAA;EACvCc,KAAAd,WAAW5E,YAAY8E,OAAM3C,QAAqB,IAAlDuC,KAAAA;EAAmDrB,EAAA,MAAAyB,OAAA3C;EAAAkB,EAAA,MAAAuB;EAAAvB,EAAA,MAAAqC;CAAA,OAAAA,KAAArC,EAAA;CAEpD,MAAAsC,KAAAX,SAAQY;CAAS,IAAAC;CAAA,IAAAxC,EAAA,QAAAL,QAAAK,EAAA,QAAAc,YAAA;EAEZ0B,KAAA1B,cAAc9D,QAAQ2C,MAAMA,IAAI;EAACK,EAAA,MAAAL;EAAAK,EAAA,MAAAc;EAAAd,EAAA,MAAAwC;CAAA,OAAAA,KAAAxC,EAAA;CAChC,MAAAyC,MAAAT,OAAMtB;CACP,MAAAgC,MAAAjB,OAAMd;CACR,MAAAgC,MAAAxF,cACL6B,OAAME,MACNM,QAAQ8B,KAAK,CAAC,CAAC3D,OACfG,YAAY,aAAawB,cAAc3B,QAAvC0D,KAAAA,GACAK,OAAMkB,WACNZ,OAAMa,QACNlB,SAAQmB,MACRjF,KACF;CAAC,IAAAkF;CAAA,IAAA/C,EAAA,QAAAgC,OAAAa,QAAA;EAGQE,MAAA5F,cACLZ,aAAYyG,MACZhB,OAAMa,MACR;EAAC7C,EAAA,MAAAgC,OAAAa;EAAA7C,EAAA,MAAA+C;CAAA,OAAAA,MAAA/C,EAAA;CAAA,IAAAiD;CAAA,IAAAjD,EAAA,QAAA2B,SAAAuB,SAAAlD,EAAA,QAAA+C,KAAA;EAJHE,MAAA,oBAAA,SAAA,MAAA;GACS,OAAAF;GAKNpB,UAAAA,SAAQuB;EACX,CAAA;EAAgBlD,EAAA,MAAA2B,SAAAuB;EAAAlD,EAAA,MAAA+C;EAAA/C,EAAA,MAAAiD;CAAA,OAAAA,MAAAjD,EAAA;CACf,MAAAmD,KAAApG;CAAwB,MAAAqG,MAAAC,YAAY3B,OAAMG,SAAUlE,IAAI;CAAC,IAAA2F;CAAA,IAAAtD,EAAA,QAAAmD,MAAAnD,EAAA,QAAAzC,YAAAyC,EAAA,QAAAoD,KAAA;EAA1DE,MAAA,oBAAC,IAAD;GAAyB,OAAAF;GACtB7F;EADc,CAAA;EAEEyC,EAAA,MAAAmD;EAAAnD,EAAA,MAAAzC;EAAAyC,EAAA,MAAAoD;EAAApD,EAAA,MAAAsD;CAAA,OAAAA,MAAAtD,EAAA;CAAA,IAAAuD;CAAA,IAAAvD,EAAA,QAAAmC,MAAAnC,EAAA,QAAAyB,OAAAd,WAAAX,EAAA,QAAA2B,SAAAY,YAAAvC,EAAA,QAAAvC,cAAAuC,EAAA,QAAAe,SAAAf,EAAA,QAAAgC,OAAAtB,YAAAV,EAAA,QAAA2C,OAAA3C,EAAA,QAAAiD,OAAAjD,EAAA,QAAAsD,OAAAtD,EAAA,QAAAoC,MAAApC,EAAA,QAAAqC,MAAArC,EAAA,QAAAwC,IAAA;EA7BrBe,MAAA,qBAAC,IAAD;GACQ,MAAAnB;GAAsC,GACvCC;GAAmD,GACpDtB;GAAK,GACLuB;GACM7E,UAAAA;GACD,SAAA+E;GACC,UAAAC;GACD,SAAAC;GACF,OAAAC;GATT,UAAA,CAmBEM,KAQAK,GA3BgB;;EA8BEtD,EAAA,MAAAmC;EAAAnC,EAAA,MAAAyB,OAAAd;EAAAX,EAAA,MAAA2B,SAAAY;EAAAvC,EAAA,MAAAvC;EAAAuC,EAAA,MAAAe;EAAAf,EAAA,MAAAgC,OAAAtB;EAAAV,EAAA,MAAA2C;EAAA3C,EAAA,MAAAiD;EAAAjD,EAAA,MAAAsD;EAAAtD,EAAA,MAAAoC;EAAApC,EAAA,MAAAqC;EAAArC,EAAA,MAAAwC;EAAAxC,EAAA,MAAAuD;CAAA,OAAAA,MAAAvD,EAAA;CAAA,OA9BpBuD;AA8BoB;AAIxB,SAASF,YAAYzB,OAAejE,MAAiC;CACnE,OAAO;EAAEiE;EAAOjE,MAAMY,WAAWZ;CAAM;AACzC"}
@@ -0,0 +1,59 @@
1
+ import { Text, TextProps } from "react-native";
2
+ import { ComponentRef, Ref } from "react";
3
+ //#region src/components/link/index.d.ts
4
+ type LinkProps = Omit<TextProps, 'disabled'> & {
5
+ /**
6
+ * Where the link leads. A press opens it through the `RouterProvider`
7
+ * around the link, or through the platform for a URL with a scheme of its
8
+ * own, after the call site's own `onPress`.
9
+ */
10
+ readonly href?: string;
11
+ /**
12
+ * Fades the link to the disabled content colour, and takes no press. It is
13
+ * still announced as a link, a disabled one.
14
+ */
15
+ readonly isDisabled?: boolean;
16
+ readonly ref?: Ref<ComponentRef<typeof Text>>;
17
+ /**
18
+ * Which colour role to render in. `primary` marks the link out from the
19
+ * text around it; `inherit` takes the colour of the Text around it and
20
+ * leans on the underline alone, for a link in a place already understood
21
+ * to be links, such as a footer.
22
+ * @default 'primary'
23
+ */
24
+ readonly tone?: LinkTone;
25
+ /**
26
+ * When to draw the rule. Leave it at `always` in prose: without it, colour
27
+ * is the only thing separating the link from the sentence, which some
28
+ * readers cannot see. `hover` and `none` are for links whose position
29
+ * already announces them, such as a row of footer links. A phone has no
30
+ * pointer, so `hover` draws no rule there.
31
+ * @default 'always'
32
+ */
33
+ readonly underline?: LinkUnderline;
34
+ };
35
+ type LinkTone = 'inherit' | 'primary';
36
+ type LinkUnderline = 'always' | 'hover' | 'none';
37
+ /**
38
+ * A run of text that leads somewhere, inside the sentence it belongs to.
39
+ *
40
+ * ```tsx
41
+ * <Text variant="bodyLarge">
42
+ * Supporting copy with <Link href="/first">a link inside it</Link>.
43
+ * </Text>
44
+ * ```
45
+ *
46
+ * It is React Native's Text with the link role, nested in the library's
47
+ * Text, so it flows and wraps with the words around it and takes their type.
48
+ * Given no Text around it, it draws in the platform's default face rather
49
+ * than the theme's, so a link standing on its own, such as one of a row of
50
+ * footer links, is a Text holding one link.
51
+ *
52
+ * `onPress` fires for a tap, a click and the Enter key alike, then `href` is
53
+ * followed, through the `RouterProvider` around the link or the platform.
54
+ * `style`, `ref` and `testID` land on React Native's own Text.
55
+ */
56
+ declare function Link({ href, isDisabled, onPress, style, suppressHighlighting, tone, underline, ...props }: LinkProps): import("react").JSX.Element;
57
+ //#endregion
58
+ export { Link, type LinkProps, type LinkTone, type LinkUnderline };
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,191 @@
1
+ import { useTheme } from "../../theme/scope.js";
2
+ import { composeStyles, themedStyles } from "../../theme/styles.js";
3
+ import { useLinkPress } from "../../router/index.js";
4
+ import { withOpacity } from "../../theme/color.js";
5
+ import { stylesOf as stylesOf$1 } from "../../press/styles.js";
6
+ import { c } from "react/compiler-runtime";
7
+ import { Platform, StyleSheet, Text } from "react-native";
8
+ import { useState } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ //#region src/components/link/index.tsx
11
+ const underlines = StyleSheet.create({
12
+ always: { textDecorationLine: "underline" },
13
+ hover: { textDecorationLine: "none" },
14
+ none: { textDecorationLine: "none" }
15
+ });
16
+ const stylesOf = themedStyles(({ colors, radii, stateLayerOpacity }) => {
17
+ const disabledContent = withOpacity(colors.onSurface, stateLayerOpacity.disabledContent);
18
+ return StyleSheet.create({
19
+ base: { borderRadius: radii.xs },
20
+ disabled: {
21
+ color: disabledContent,
22
+ textDecorationColor: disabledContent
23
+ },
24
+ hovered: {
25
+ color: colors.primary,
26
+ textDecorationColor: colors.primary
27
+ },
28
+ inherit: { textDecorationColor: colors.outline },
29
+ primary: {
30
+ color: colors.primary,
31
+ textDecorationColor: withOpacity(colors.primary, .7)
32
+ }
33
+ });
34
+ });
35
+ /**
36
+ * A run of text that leads somewhere, inside the sentence it belongs to.
37
+ *
38
+ * ```tsx
39
+ * <Text variant="bodyLarge">
40
+ * Supporting copy with <Link href="/first">a link inside it</Link>.
41
+ * </Text>
42
+ * ```
43
+ *
44
+ * It is React Native's Text with the link role, nested in the library's
45
+ * Text, so it flows and wraps with the words around it and takes their type.
46
+ * Given no Text around it, it draws in the platform's default face rather
47
+ * than the theme's, so a link standing on its own, such as one of a row of
48
+ * footer links, is a Text holding one link.
49
+ *
50
+ * `onPress` fires for a tap, a click and the Enter key alike, then `href` is
51
+ * followed, through the `RouterProvider` around the link or the platform.
52
+ * `style`, `ref` and `testID` land on React Native's own Text.
53
+ */
54
+ function Link(t0) {
55
+ const $ = c(38);
56
+ let href;
57
+ let onPress;
58
+ let props;
59
+ let style;
60
+ let t1;
61
+ let t2;
62
+ let t3;
63
+ let t4;
64
+ if ($[0] !== t0) {
65
+ ({href, isDisabled: t1, onPress, style, suppressHighlighting: t2, tone: t3, underline: t4, ...props} = t0);
66
+ $[0] = t0;
67
+ $[1] = href;
68
+ $[2] = onPress;
69
+ $[3] = props;
70
+ $[4] = style;
71
+ $[5] = t1;
72
+ $[6] = t2;
73
+ $[7] = t3;
74
+ $[8] = t4;
75
+ } else {
76
+ href = $[1];
77
+ onPress = $[2];
78
+ props = $[3];
79
+ style = $[4];
80
+ t1 = $[5];
81
+ t2 = $[6];
82
+ t3 = $[7];
83
+ t4 = $[8];
84
+ }
85
+ const isDisabled = t1 === void 0 ? false : t1;
86
+ const suppressHighlighting = t2 === void 0 ? true : t2;
87
+ const tone = t3 === void 0 ? "primary" : t3;
88
+ const underline = t4 === void 0 ? "always" : t4;
89
+ const theme = useTheme();
90
+ const press = useLinkPress(href, onPress);
91
+ const [hoveredState, setHovered] = useState(false);
92
+ const [ringShown, setRingShown] = useState(false);
93
+ let T0;
94
+ let t10;
95
+ let t5;
96
+ let t6;
97
+ let t7;
98
+ let t8;
99
+ let t9;
100
+ if ($[9] !== hoveredState || $[10] !== href || $[11] !== isDisabled || $[12] !== onPress || $[13] !== press || $[14] !== props || $[15] !== ringShown || $[16] !== style || $[17] !== theme || $[18] !== tone || $[19] !== underline) {
101
+ const styles = stylesOf(theme);
102
+ const hovered = !isDisabled && hoveredState;
103
+ const pressable = !isDisabled && (href !== void 0 || onPress != null);
104
+ let t11;
105
+ if ($[27] !== isDisabled) {
106
+ t11 = Platform.OS === "web" ? webPropsOf(isDisabled, setHovered, setRingShown) : void 0;
107
+ $[27] = isDisabled;
108
+ $[28] = t11;
109
+ } else t11 = $[28];
110
+ const web = t11;
111
+ T0 = Text;
112
+ t5 = props;
113
+ t6 = web;
114
+ t7 = isDisabled;
115
+ t8 = pressable ? press : void 0;
116
+ t9 = "link";
117
+ t10 = composeStyles(styles.base, styles[tone], underlines[underline], hovered && styles.hovered, hovered && underline === "hover" && underlines.always, isDisabled && styles.disabled, !isDisabled && ringShown && stylesOf$1(theme).ring, style);
118
+ $[9] = hoveredState;
119
+ $[10] = href;
120
+ $[11] = isDisabled;
121
+ $[12] = onPress;
122
+ $[13] = press;
123
+ $[14] = props;
124
+ $[15] = ringShown;
125
+ $[16] = style;
126
+ $[17] = theme;
127
+ $[18] = tone;
128
+ $[19] = underline;
129
+ $[20] = T0;
130
+ $[21] = t10;
131
+ $[22] = t5;
132
+ $[23] = t6;
133
+ $[24] = t7;
134
+ $[25] = t8;
135
+ $[26] = t9;
136
+ } else {
137
+ T0 = $[20];
138
+ t10 = $[21];
139
+ t5 = $[22];
140
+ t6 = $[23];
141
+ t7 = $[24];
142
+ t8 = $[25];
143
+ t9 = $[26];
144
+ }
145
+ let t11;
146
+ if ($[29] !== T0 || $[30] !== suppressHighlighting || $[31] !== t10 || $[32] !== t5 || $[33] !== t6 || $[34] !== t7 || $[35] !== t8 || $[36] !== t9) {
147
+ t11 = /* @__PURE__ */ jsx(T0, {
148
+ ...t5,
149
+ ...t6,
150
+ "aria-disabled": t7,
151
+ onPress: t8,
152
+ role: t9,
153
+ style: t10,
154
+ suppressHighlighting
155
+ });
156
+ $[29] = T0;
157
+ $[30] = suppressHighlighting;
158
+ $[31] = t10;
159
+ $[32] = t5;
160
+ $[33] = t6;
161
+ $[34] = t7;
162
+ $[35] = t8;
163
+ $[36] = t9;
164
+ $[37] = t11;
165
+ } else t11 = $[37];
166
+ return t11;
167
+ }
168
+ function webPropsOf(isDisabled, setHovered, setRingShown) {
169
+ return {
170
+ focusable: !isDisabled,
171
+ onBlur: () => {
172
+ setRingShown(false);
173
+ },
174
+ onFocus: (event) => {
175
+ setRingShown(event.currentTarget.matches(":focus-visible"));
176
+ },
177
+ onKeyDown: (event) => {
178
+ if (!isDisabled && event.key === "Enter" && !event.repeat) event.currentTarget.click();
179
+ },
180
+ onPointerEnter: (event) => {
181
+ setHovered(event.pointerType !== "touch");
182
+ },
183
+ onPointerLeave: () => {
184
+ setHovered(false);
185
+ }
186
+ };
187
+ }
188
+ //#endregion
189
+ export { Link };
190
+
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ComponentRef","Ref","TextProps","NativeTextProps","TextStyle","useState","Text","NativeText","Platform","StyleSheet","stylesOf","ringStylesOf","useLinkPress","withOpacity","useTheme","composeStyles","themedStyles","LinkProps","Omit","href","isDisabled","ref","tone","LinkTone","underline","LinkUnderline","WebProps","focusable","onBlur","onFocus","event","currentTarget","matches","selector","onKeyDown","click","key","repeat","onPointerEnter","pointerType","onPointerLeave","underlines","create","always","textDecorationLine","hover","none","colors","radii","stateLayerOpacity","disabledContent","onSurface","base","borderRadius","xs","disabled","color","textDecorationColor","hovered","primary","inherit","outline","Link","t0","$","_c","onPress","props","style","t1","t2","t3","t4","suppressHighlighting","undefined","theme","press","hoveredState","setHovered","ringShown","setRingShown","T0","t10","t5","t6","t7","t8","t9","styles","pressable","t11","OS","webPropsOf","web","ring","shown","_c","NativeText","ringStylesOf"],"sources":["../../../src/components/link/index.tsx"],"sourcesContent":["import type { ComponentRef, Ref } from 'react'\nimport type { TextProps as NativeTextProps, TextStyle } from 'react-native'\n\nimport { useState } from 'react'\nimport { Text as NativeText, Platform, StyleSheet } from 'react-native'\n\nimport { stylesOf as ringStylesOf } from '../../press/styles'\nimport { useLinkPress } from '../../router'\nimport { withOpacity } from '../../theme/color'\nimport { useTheme } from '../../theme/scope'\nimport { composeStyles, themedStyles } from '../../theme/styles'\n\n// No Material Design page draws an inline link, so this takes web's reading:\n// the text button's label, the primary role on no container, with the\n// disabled treatment every page gives content, and a rule under it to say it\n// can be followed. That rule is 70% of the primary role, or the outline role\n// under `inherit`, and turns fully primary under a pointer. 70% is web's\n// figure, the least that keeps the rule at 3:1 against the surface in every\n// scheme the library is shown in.\n//\n// It is a nested Text, so it sets no type of its own and takes the size and\n// face of the sentence around it, as web's takes them from its paragraph. A\n// nested Text has no frame of its own, so it takes no `hitSlop` either.\n//\n// Where it departs from web, the platform is the reason:\n//\n// - The disabled colour is on-surface at the `disabledContent` opacity,\n// translucent over whatever the sentence sits on. Web mixes the two over\n// the surface role, and React Native has no `color-mix()`.\n// - Android draws the rule in the text's own colour, since it has no\n// `textDecorationColor`, and every platform draws it at its own thickness\n// and offset, which React Native has no properties for.\n// - Hover, the focus ring and the Enter key are the web's alone: a phone has\n// no pointer to hover with and focuses no span inside a sentence, so on\n// native `hover` draws no rule at all. The colour changes at once rather\n// than over a transition.\n// - iOS's own pressed highlight is off, since web's link draws no pressed\n// state; `suppressHighlighting={false}` turns it back on.\n\ntype LinkProps = Omit<NativeTextProps, 'disabled'> & {\n /**\n * Where the link leads. A press opens it through the `RouterProvider`\n * around the link, or through the platform for a URL with a scheme of its\n * own, after the call site's own `onPress`.\n */\n readonly href?: string\n /**\n * Fades the link to the disabled content colour, and takes no press. It is\n * still announced as a link, a disabled one.\n */\n readonly isDisabled?: boolean\n readonly ref?: Ref<ComponentRef<typeof NativeText>>\n /**\n * Which colour role to render in. `primary` marks the link out from the\n * text around it; `inherit` takes the colour of the Text around it and\n * leans on the underline alone, for a link in a place already understood\n * to be links, such as a footer.\n * @default 'primary'\n */\n readonly tone?: LinkTone\n /**\n * When to draw the rule. Leave it at `always` in prose: without it, colour\n * is the only thing separating the link from the sentence, which some\n * readers cannot see. `hover` and `none` are for links whose position\n * already announces them, such as a row of footer links. A phone has no\n * pointer, so `hover` draws no rule there.\n * @default 'always'\n */\n readonly underline?: LinkUnderline\n}\n\ntype LinkTone = 'inherit' | 'primary'\n\ntype LinkUnderline = 'always' | 'hover' | 'none'\n\n// What React Native Web hands a link's span, which React Native's own Text\n// declares none of: the browser's pointer, focus and key events, each typed\n// by the fields the link reads, and whether the span takes the Tab key.\ntype WebProps = {\n readonly focusable: boolean\n readonly onBlur: () => void\n readonly onFocus: (event: {\n readonly currentTarget: { readonly matches: (selector: string) => boolean }\n }) => void\n readonly onKeyDown: (event: {\n readonly currentTarget: { readonly click: () => void }\n readonly key: string\n readonly repeat: boolean\n }) => void\n readonly onPointerEnter: (event: { readonly pointerType: string }) => void\n readonly onPointerLeave: () => void\n}\n\n// React Native's underline is off unless a style turns it on, and a nested\n// Text inherits its sentence's, so `hover` and `none` say `none` outright, as\n// web's do over an anchor's own underline.\nconst underlines = StyleSheet.create({\n always: { textDecorationLine: 'underline' },\n hover: { textDecorationLine: 'none' },\n none: { textDecorationLine: 'none' },\n})\n\nconst stylesOf = themedStyles(({ colors, radii, stateLayerOpacity }) => {\n const disabledContent = withOpacity(\n colors.onSurface,\n stateLayerOpacity.disabledContent,\n )\n\n return StyleSheet.create({\n // The ring's corner on web, where an outline follows it. A nested Text\n // draws no frame on native, so there it draws nothing.\n base: {\n borderRadius: radii.xs,\n },\n disabled: {\n color: disabledContent,\n textDecorationColor: disabledContent,\n },\n // Under a pointer, either tone turns its text and its rule fully primary.\n hovered: {\n color: colors.primary,\n textDecorationColor: colors.primary,\n },\n // No colour, so the Text around it lends its own.\n inherit: {\n textDecorationColor: colors.outline,\n },\n primary: {\n color: colors.primary,\n textDecorationColor: withOpacity(colors.primary, 0.7),\n },\n })\n})\n\n/**\n * A run of text that leads somewhere, inside the sentence it belongs to.\n *\n * ```tsx\n * <Text variant=\"bodyLarge\">\n * Supporting copy with <Link href=\"/first\">a link inside it</Link>.\n * </Text>\n * ```\n *\n * It is React Native's Text with the link role, nested in the library's\n * Text, so it flows and wraps with the words around it and takes their type.\n * Given no Text around it, it draws in the platform's default face rather\n * than the theme's, so a link standing on its own, such as one of a row of\n * footer links, is a Text holding one link.\n *\n * `onPress` fires for a tap, a click and the Enter key alike, then `href` is\n * followed, through the `RouterProvider` around the link or the platform.\n * `style`, `ref` and `testID` land on React Native's own Text.\n */\nfunction Link({\n href,\n isDisabled = false,\n onPress,\n style,\n suppressHighlighting = true,\n tone = 'primary',\n underline = 'always',\n ...props\n}: LinkProps) {\n const theme = useTheme()\n const press = useLinkPress(href, onPress)\n const [hoveredState, setHovered] = useState(false)\n const [ringShown, setRingShown] = useState(false)\n\n const styles = stylesOf(theme)\n const hovered = !isDisabled && hoveredState\n const pressable = !isDisabled && (href !== undefined || onPress != null)\n const web =\n Platform.OS === 'web'\n ? webPropsOf(isDisabled, setHovered, setRingShown)\n : undefined\n\n return (\n <NativeText\n {...props}\n {...web}\n aria-disabled={isDisabled}\n onPress={pressable ? press : undefined}\n role=\"link\"\n style={composeStyles<TextStyle>(\n styles.base,\n styles[tone],\n underlines[underline],\n hovered && styles.hovered,\n hovered && underline === 'hover' && underlines.always,\n isDisabled && styles.disabled,\n !isDisabled && ringShown && ringStylesOf(theme).ring,\n style,\n )}\n suppressHighlighting={suppressHighlighting}\n />\n )\n}\n\n// The browser's events, read into the link's two states. Hover counts a mouse\n// or a pen and never a touch, which leaves a tapped link's emulated pointer\n// over it, as React Aria's hover does on web. The ring follows the browser's\n// own `:focus-visible`, the rule web's ring is drawn under, read as focus\n// arrives. Enter clicks the span, which is what a browser does for an\n// anchor and what React Native Web hands to `onPress`; a key held down\n// follows the link once.\nfunction webPropsOf(\n isDisabled: boolean,\n setHovered: (hovered: boolean) => void,\n setRingShown: (shown: boolean) => void,\n): WebProps {\n return {\n focusable: !isDisabled,\n onBlur: () => {\n setRingShown(false)\n },\n onFocus: (event) => {\n setRingShown(event.currentTarget.matches(':focus-visible'))\n },\n onKeyDown: (event) => {\n if (!isDisabled && event.key === 'Enter' && !event.repeat) {\n event.currentTarget.click()\n }\n },\n onPointerEnter: (event) => {\n setHovered(event.pointerType !== 'touch')\n },\n onPointerLeave: () => {\n setHovered(false)\n },\n }\n}\n\nexport type { LinkProps, LinkTone, LinkUnderline }\n\nexport { Link }\n"],"mappings":"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"}