@kanso-labs/react-native-kanso-ui 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/badge/index.js +9 -70
  2. package/dist/badge/index.js.map +1 -1
  3. package/dist/button/index.js +1 -1
  4. package/dist/button/palettes.d.ts +2 -0
  5. package/dist/components/badge/index.d.ts +48 -0
  6. package/dist/components/badge/index.js +122 -0
  7. package/dist/components/badge/index.js.map +1 -0
  8. package/dist/{badge → components/badge}/styles.js +10 -6
  9. package/dist/components/badge/styles.js.map +1 -0
  10. package/dist/components/breadcrumbs/index.d.ts +66 -0
  11. package/dist/components/breadcrumbs/index.js +285 -0
  12. package/dist/components/breadcrumbs/index.js.map +1 -0
  13. package/dist/components/checkbox/index.d.ts +7 -1
  14. package/dist/components/checkbox/index.js +183 -138
  15. package/dist/components/checkbox/index.js.map +1 -1
  16. package/dist/components/checkbox-group/index.d.ts +93 -0
  17. package/dist/components/checkbox-group/index.js +306 -0
  18. package/dist/components/checkbox-group/index.js.map +1 -0
  19. package/dist/components/code/index.d.ts +25 -0
  20. package/dist/components/code/index.js +87 -0
  21. package/dist/components/code/index.js.map +1 -0
  22. package/dist/components/container/index.d.ts +47 -0
  23. package/dist/components/container/index.js +85 -0
  24. package/dist/components/container/index.js.map +1 -0
  25. package/dist/components/fab/index.d.ts +80 -0
  26. package/dist/components/fab/index.js +231 -0
  27. package/dist/components/fab/index.js.map +1 -0
  28. package/dist/components/fab-menu/index.d.ts +120 -0
  29. package/dist/components/fab-menu/index.js +640 -0
  30. package/dist/components/fab-menu/index.js.map +1 -0
  31. package/dist/components/feed/index.d.ts +57 -0
  32. package/dist/components/feed/index.js +167 -0
  33. package/dist/components/feed/index.js.map +1 -0
  34. package/dist/components/keycap/index.d.ts +27 -0
  35. package/dist/components/keycap/index.js +136 -0
  36. package/dist/components/keycap/index.js.map +1 -0
  37. package/dist/components/menu/index.js +1 -1
  38. package/dist/components/separator/index.d.ts +3 -2
  39. package/dist/components/separator/index.js +29 -26
  40. package/dist/components/separator/index.js.map +1 -1
  41. package/dist/components/supporting-pane/index.d.ts +44 -0
  42. package/dist/components/supporting-pane/index.js +109 -0
  43. package/dist/components/supporting-pane/index.js.map +1 -0
  44. package/dist/components/text/index.d.ts +1 -1
  45. package/dist/components/text/index.js +49 -21
  46. package/dist/components/text/index.js.map +1 -1
  47. package/dist/components/text-area/index.d.ts +145 -0
  48. package/dist/components/text-area/index.js +231 -0
  49. package/dist/components/text-area/index.js.map +1 -0
  50. package/dist/components/toolbar/index.d.ts +53 -0
  51. package/dist/components/toolbar/index.js +185 -0
  52. package/dist/components/toolbar/index.js.map +1 -0
  53. package/dist/control/group.js +23 -0
  54. package/dist/control/group.js.map +1 -0
  55. package/dist/fab/index.d.ts +19 -0
  56. package/dist/fab/index.js +147 -0
  57. package/dist/fab/index.js.map +1 -0
  58. package/dist/field/index.js +84 -43
  59. package/dist/field/index.js.map +1 -1
  60. package/dist/field/styles.js +18 -0
  61. package/dist/field/styles.js.map +1 -1
  62. package/dist/form/index.d.ts +1 -2
  63. package/dist/form/index.js +1 -1
  64. package/dist/form/index.js.map +1 -1
  65. package/dist/index.d.ts +17 -4
  66. package/dist/index.js +15 -3
  67. package/dist/modal/index.js +59 -46
  68. package/dist/modal/index.js.map +1 -1
  69. package/dist/navigation/index.js +8 -5
  70. package/dist/navigation/index.js.map +1 -1
  71. package/dist/overlay/placement.js +3 -1
  72. package/dist/overlay/placement.js.map +1 -1
  73. package/dist/separator/index.js +7 -0
  74. package/dist/separator/index.js.map +1 -0
  75. package/dist/typography/size.js +14 -0
  76. package/dist/typography/size.js.map +1 -0
  77. package/package.json +1 -1
  78. package/dist/badge/styles.js.map +0 -1
@@ -0,0 +1,231 @@
1
+ import { useLocaleOf } from "../../i18n/provider.js";
2
+ import { useFieldValidation } from "../../form/index.js";
3
+ import { FieldBox, FieldInput, FieldMessage, describedBy, useFieldFocus } from "../../field/index.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { View } from "react-native";
6
+ import { useId, useImperativeHandle, useRef, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/text-area/index.tsx
9
+ function blurThen(onBlur, then) {
10
+ return (event) => {
11
+ onBlur();
12
+ then?.(event);
13
+ };
14
+ }
15
+ function editInto(setOwn, onChange, onEdit) {
16
+ return (text) => {
17
+ setOwn(text);
18
+ onEdit();
19
+ onChange?.(text);
20
+ };
21
+ }
22
+ /**
23
+ * A labelled multi-line input, the text fields page's filled or outlined
24
+ * field holding several lines. Pass `value` with `onChange` to control it, or
25
+ * `defaultValue` to let it keep its own; `onChange` is handed the string.
26
+ *
27
+ * It shows `rows` lines at the least and grows with what it holds, or holds
28
+ * at `rows` and scrolls with `autosize={false}`. The page's configurations
29
+ * are props: `leadingIcon` and `trailingIcon` at the box's ends, and
30
+ * `characterCount` opposite the supporting text, counting against
31
+ * `maxLength`. React Native's own `TextInput` props reach the control;
32
+ * `style` and `ref` are the field as a whole, and `inputRef` the control.
33
+ *
34
+ * ```tsx
35
+ * <TextArea label="Label" description="Supporting line" />
36
+ * ```
37
+ */
38
+ function TextArea(t0) {
39
+ const $ = c(59);
40
+ const { autosize: t1, characterCount: t2, characterLimitLabel, defaultValue: t3, description, error, floatingLabel: t4, inputRef, isDisabled: t5, isReadOnly: t6, isRequired: t7, label, leadingIcon, name, onBlur, onChange, onFocus, ref, rows: t8, style, trailingIcon, validate, value, variant: t9, ...props } = t0;
41
+ const autosize = t1 === void 0 ? true : t1;
42
+ const characterCount = t2 === void 0 ? false : t2;
43
+ const defaultValue = t3 === void 0 ? "" : t3;
44
+ const floatingLabel = t4 === void 0 ? true : t4;
45
+ const isDisabled = t5 === void 0 ? false : t5;
46
+ const isReadOnly = t6 === void 0 ? false : t6;
47
+ const isRequired = t7 === void 0 ? false : t7;
48
+ const rows = t8 === void 0 ? 3 : t8;
49
+ const variant = t9 === void 0 ? "filled" : t9;
50
+ const id = useId();
51
+ const control = useRef(null);
52
+ const [own, setOwn] = useState(defaultValue);
53
+ const current = value ?? own;
54
+ const t10 = current === "";
55
+ let t11;
56
+ if ($[0] !== current || $[1] !== error || $[2] !== isDisabled || $[3] !== isReadOnly || $[4] !== isRequired || $[5] !== name || $[6] !== t10 || $[7] !== validate) {
57
+ t11 = {
58
+ control,
59
+ error,
60
+ isDisabled,
61
+ isEmpty: t10,
62
+ isReadOnly,
63
+ isRequired,
64
+ name,
65
+ submitted: current,
66
+ validate,
67
+ value: current
68
+ };
69
+ $[0] = current;
70
+ $[1] = error;
71
+ $[2] = isDisabled;
72
+ $[3] = isReadOnly;
73
+ $[4] = isRequired;
74
+ $[5] = name;
75
+ $[6] = t10;
76
+ $[7] = validate;
77
+ $[8] = t11;
78
+ } else t11 = $[8];
79
+ const validation = useFieldValidation(t11);
80
+ let t12;
81
+ if ($[9] !== onBlur || $[10] !== validation.onBlur) {
82
+ t12 = blurThen(validation.onBlur, onBlur);
83
+ $[9] = onBlur;
84
+ $[10] = validation.onBlur;
85
+ $[11] = t12;
86
+ } else t12 = $[11];
87
+ let t13;
88
+ if ($[12] !== onFocus || $[13] !== t12) {
89
+ t13 = {
90
+ onBlur: t12,
91
+ onFocus
92
+ };
93
+ $[12] = onFocus;
94
+ $[13] = t12;
95
+ $[14] = t13;
96
+ } else t13 = $[14];
97
+ const focus = useFieldFocus(t13);
98
+ const shownError = validation.error;
99
+ const locale = useLocaleOf(void 0);
100
+ let t14;
101
+ let t15;
102
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
103
+ t14 = () => control.current;
104
+ t15 = [];
105
+ $[15] = t14;
106
+ $[16] = t15;
107
+ } else {
108
+ t14 = $[15];
109
+ t15 = $[16];
110
+ }
111
+ useImperativeHandle(inputRef, t14, t15);
112
+ const T0 = View;
113
+ const T1 = FieldBox;
114
+ const t16 = focus.focused;
115
+ const t17 = shownError !== void 0;
116
+ const t18 = current !== "";
117
+ const T2 = FieldInput;
118
+ const t19 = focus.handlers;
119
+ const t20 = describedBy(id, {
120
+ characterLimitLabel,
121
+ description,
122
+ error: shownError,
123
+ locale,
124
+ maxLength: props.maxLength
125
+ });
126
+ const t21 = !isDisabled && !isReadOnly;
127
+ let t22;
128
+ if ($[17] !== onChange || $[18] !== setOwn || $[19] !== validation.onEdit) {
129
+ t22 = editInto(setOwn, onChange, validation.onEdit);
130
+ $[17] = onChange;
131
+ $[18] = setOwn;
132
+ $[19] = validation.onEdit;
133
+ $[20] = t22;
134
+ } else t22 = $[20];
135
+ let t23;
136
+ if ($[21] !== T2 || $[22] !== autosize || $[23] !== current || $[24] !== focus.handlers || $[25] !== label || $[26] !== props || $[27] !== rows || $[28] !== t20 || $[29] !== t21 || $[30] !== t22) {
137
+ t23 = /* @__PURE__ */ jsx(T2, {
138
+ ...props,
139
+ ...t19,
140
+ "aria-label": label,
141
+ autosize,
142
+ described: t20,
143
+ editable: t21,
144
+ multiline: true,
145
+ onChangeText: t22,
146
+ ref: control,
147
+ rows,
148
+ value: current
149
+ });
150
+ $[21] = T2;
151
+ $[22] = autosize;
152
+ $[23] = current;
153
+ $[24] = focus.handlers;
154
+ $[25] = label;
155
+ $[26] = props;
156
+ $[27] = rows;
157
+ $[28] = t20;
158
+ $[29] = t21;
159
+ $[30] = t22;
160
+ $[31] = t23;
161
+ } else t23 = $[31];
162
+ let t24;
163
+ if ($[32] !== T1 || $[33] !== floatingLabel || $[34] !== focus.focused || $[35] !== isDisabled || $[36] !== isRequired || $[37] !== label || $[38] !== leadingIcon || $[39] !== t17 || $[40] !== t18 || $[41] !== t23 || $[42] !== trailingIcon || $[43] !== variant) {
164
+ t24 = /* @__PURE__ */ jsx(T1, {
165
+ control,
166
+ floatingLabel,
167
+ isDisabled,
168
+ isFocused: t16,
169
+ isInvalid: t17,
170
+ isPopulated: t18,
171
+ isRequired,
172
+ label,
173
+ leading: leadingIcon,
174
+ trailing: trailingIcon,
175
+ variant,
176
+ children: t23
177
+ });
178
+ $[32] = T1;
179
+ $[33] = floatingLabel;
180
+ $[34] = focus.focused;
181
+ $[35] = isDisabled;
182
+ $[36] = isRequired;
183
+ $[37] = label;
184
+ $[38] = leadingIcon;
185
+ $[39] = t17;
186
+ $[40] = t18;
187
+ $[41] = t23;
188
+ $[42] = trailingIcon;
189
+ $[43] = variant;
190
+ $[44] = t24;
191
+ } else t24 = $[44];
192
+ let t25;
193
+ if ($[45] !== characterCount || $[46] !== characterLimitLabel || $[47] !== current.length || $[48] !== description || $[49] !== id || $[50] !== props.maxLength || $[51] !== shownError) {
194
+ t25 = /* @__PURE__ */ jsx(FieldMessage, {
195
+ characterCount,
196
+ characterLimitLabel,
197
+ description,
198
+ error: shownError,
199
+ id,
200
+ length: current.length,
201
+ maxLength: props.maxLength
202
+ });
203
+ $[45] = characterCount;
204
+ $[46] = characterLimitLabel;
205
+ $[47] = current.length;
206
+ $[48] = description;
207
+ $[49] = id;
208
+ $[50] = props.maxLength;
209
+ $[51] = shownError;
210
+ $[52] = t25;
211
+ } else t25 = $[52];
212
+ let t26;
213
+ if ($[53] !== T0 || $[54] !== ref || $[55] !== style || $[56] !== t24 || $[57] !== t25) {
214
+ t26 = /* @__PURE__ */ jsxs(T0, {
215
+ ref,
216
+ style,
217
+ children: [t24, t25]
218
+ });
219
+ $[53] = T0;
220
+ $[54] = ref;
221
+ $[55] = style;
222
+ $[56] = t24;
223
+ $[57] = t25;
224
+ $[58] = t26;
225
+ } else t26 = $[58];
226
+ return t26;
227
+ }
228
+ //#endregion
229
+ export { TextArea };
230
+
231
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ComponentRef","ReactNode","Ref","StyleProp","TextInput","TextInputProps","ViewStyle","useId","useImperativeHandle","useRef","useState","View","FieldVariant","ValidationResult","describedBy","FieldBox","FieldInput","FieldMessage","useFieldFocus","useFieldValidation","useLocaleOf","TextAreaProps","Omit","autosize","characterCount","characterLimitLabel","defaultValue","description","error","floatingLabel","inputRef","isDisabled","isReadOnly","isRequired","label","leadingIcon","name","onChange","value","ref","rows","style","trailingIcon","validate","variant","blurThen","onBlur","then","event","editInto","setOwn","onEdit","text","TextArea","t0","$","_c","t1","t2","t3","t4","t5","t6","t7","onFocus","t8","t9","props","undefined","id","control","own","current","t10","t11","isEmpty","submitted","validation","t12","t13","focus","shownError","locale","t14","t15","Symbol","for","T0","T1","t16","focused","t17","t18","T2","t19","handlers","t20","maxLength","t21","t22","t23","t24","t25","length","t26","_c"],"sources":["../../../src/components/text-area/index.tsx"],"sourcesContent":["import type { ComponentRef, ReactNode, Ref } from 'react'\nimport type {\n StyleProp,\n TextInput,\n TextInputProps,\n ViewStyle,\n} from 'react-native'\n\nimport { useId, useImperativeHandle, useRef, useState } from 'react'\nimport { View } from 'react-native'\n\nimport type { FieldVariant } from '../../field'\nimport type { ValidationResult } from '../../form'\n\nimport {\n describedBy,\n FieldBox,\n FieldInput,\n FieldMessage,\n useFieldFocus,\n} from '../../field'\nimport { useFieldValidation } from '../../form'\nimport { useLocaleOf } from '../../i18n/provider'\n\n// kanso-ui's TextArea, the text fields page's multi-line configuration of the\n// field: the same box, floating label, icons, rule and supporting line as\n// TextField, drawn through the field chrome in src/field, around a control\n// that holds several lines. The page gives the box 56dp at the least, with\n// 8dp above and below the text and the label resting on its first line; a box\n// holding more grows a line at a time, which the chrome's height floor\n// already does, and its icons stay centred in its height, as web's do. The\n// page draws no resize handle, and React Native draws none.\n//\n// Its own component rather than a prop of TextField, as on web, so `rows` and\n// `autosize` stay off TextField's type and `numeric`, `prefix` and `suffix`\n// off this one.\n//\n// The value is the field's own or the call site's, as TextField's is, and\n// `onChange` is handed the string. The error shown is `error`, or what the\n// field's `validate` and the `Form` around it say, which src/form decides.\n\ntype TextAreaProps = Omit<\n TextInputProps,\n | 'accessibilityHint'\n | 'accessibilityLabel'\n | 'aria-disabled'\n | 'aria-label'\n | 'children'\n | 'cursorColor'\n | 'defaultValue'\n | 'editable'\n | 'multiline'\n | 'numberOfLines'\n | 'onChange'\n | 'onChangeText'\n | 'placeholder'\n | 'placeholderTextColor'\n | 'readOnly'\n | 'rows'\n | 'selectionColor'\n | 'style'\n | 'underlineColorAndroid'\n | 'value'\n> & {\n /**\n * Whether the field grows with the text it holds, from `rows` up. `false`\n * keeps it at `rows` and scrolls the text inside.\n * @default true\n */\n readonly autosize?: boolean\n /**\n * Counts the characters the field holds at the end of the supporting line,\n * against `maxLength` where there is one, as the text fields page's\n * character counter does. The count is written in the digits of the\n * `I18nProvider`'s locale, or the device's outside one.\n * @default false\n */\n readonly characterCount?: boolean\n /**\n * How the limit is said to a screen reader, where there is a `maxLength`.\n * Read with the field rather than as the value changes, so it names the\n * limit and not what is left of it; the visible count is hidden from\n * screen readers, which is what this replaces. Left out, it is the\n * library's sentence in the `I18nProvider`'s locale, or the device's\n * outside one, in the plural form the limit takes there: \"Up to 20\n * characters\" in English, singular for a limit of one.\n */\n readonly characterLimitLabel?: string\n /** The value the field opens with, when it keeps its own. */\n readonly defaultValue?: string\n /**\n * A hint shown under the field. Replaced by `error` when there is one, so\n * the two never stack.\n */\n readonly description?: string\n /**\n * The problem with the current value, in words. Its presence is what puts\n * the field in its error state: the message, the error colours, and the\n * invalid state a screen reader reads all follow from it. The line under\n * the field arrives with the message, so the field grows when this does,\n * unless it is inside a `Form`, which keeps the line drawn. It wins over\n * what `validate` and the form say, and holds a `native` form back.\n */\n readonly error?: string\n /**\n * Whether the label sits in the empty box and floats to the top once the\n * field is focused or holds a value, as the text fields page draws it.\n * `false` keeps it small at the top in every state.\n * @default true\n */\n readonly floatingLabel?: boolean\n /**\n * A ref to the field's own `TextInput`, which is what a call site moves\n * focus to, after a server's error, say. `ref` is the field as a whole.\n */\n readonly inputRef?: Ref<ComponentRef<typeof TextInput>>\n /**\n * Draws the field disabled: it takes no focus and no input.\n * @default false\n */\n readonly isDisabled?: boolean\n /**\n * Shows the value and takes focus, but takes no input.\n * @default false\n */\n readonly isReadOnly?: boolean\n /**\n * Marks the label with an asterisk, as the text fields page marks a field\n * that must be filled.\n * @default false\n */\n readonly isRequired?: boolean\n /**\n * What the field is for, and the name a screen reader reads for it.\n * Required, since a text area with no label is a box nobody can name.\n */\n readonly label: string\n /**\n * An icon at the start of the box, before the label and the text: the\n * page's 24dp leading icon, in the muted role. The slot hands it that\n * colour and size through `useIconStyle()`.\n */\n readonly leadingIcon?: ReactNode\n /**\n * The name the value is submitted under by the `Form` around the field,\n * and the key its `validationErrors` reach the field by.\n */\n readonly name?: string\n /** Called with the new value as it is edited. */\n readonly onChange?: (value: string) => void\n readonly ref?: Ref<ComponentRef<typeof View>>\n /**\n * How many lines of text the field shows: the least it shows while it\n * grows, or all it shows when it does not.\n * @default 3\n */\n readonly rows?: number\n /** Positions and sizes the field as a whole. */\n readonly style?: StyleProp<ViewStyle>\n /**\n * An icon at the end of the box, after the text: the page's 24dp trailing\n * icon, in the muted role and the error role while the field has an\n * error. The slot hands it that colour and size through `useIconStyle()`.\n */\n readonly trailingIcon?: ReactNode\n /**\n * Checks the value, and returns its problem in words, or several, where\n * there is one, and `true`, `null` or `undefined` where there is none.\n * Under the default `aria` validation the error shows as the value\n * changes; inside a `native` form it shows once a submission is tried, or\n * once the field loses focus after an edit, and holds the form back.\n */\n readonly validate?: (value: string) => ValidationResult\n /** The value, when the call site keeps it. */\n readonly value?: string\n /**\n * The filled box, or the outlined one: no fill, an outline that thickens\n * and takes the primary role while focused, and the label cutting it once\n * it floats, the text fields page's two fields.\n * @default 'filled'\n */\n readonly variant?: FieldVariant\n}\n\n// The field's own blur handling, then the call site's.\nfunction blurThen(\n onBlur: () => void,\n then: TextInputProps['onBlur'],\n): TextInputProps['onBlur'] {\n return (event) => {\n onBlur()\n then?.(event)\n }\n}\n\n// Keeps an edit as the field's own value and reports it, so a field the call\n// site controls is told and one it does not still shows what was typed, and\n// tells the field's validation it was edited.\nfunction editInto(\n setOwn: (value: string) => void,\n onChange: ((value: string) => void) | undefined,\n onEdit: () => void,\n) {\n return (text: string) => {\n setOwn(text)\n onEdit()\n onChange?.(text)\n }\n}\n\n/**\n * A labelled multi-line input, the text fields page's filled or outlined\n * field holding several lines. Pass `value` with `onChange` to control it, or\n * `defaultValue` to let it keep its own; `onChange` is handed the string.\n *\n * It shows `rows` lines at the least and grows with what it holds, or holds\n * at `rows` and scrolls with `autosize={false}`. The page's configurations\n * are props: `leadingIcon` and `trailingIcon` at the box's ends, and\n * `characterCount` opposite the supporting text, counting against\n * `maxLength`. React Native's own `TextInput` props reach the control;\n * `style` and `ref` are the field as a whole, and `inputRef` the control.\n *\n * ```tsx\n * <TextArea label=\"Label\" description=\"Supporting line\" />\n * ```\n */\nfunction TextArea({\n autosize = true,\n characterCount = false,\n characterLimitLabel,\n defaultValue = '',\n description,\n error,\n floatingLabel = true,\n inputRef,\n isDisabled = false,\n isReadOnly = false,\n isRequired = false,\n label,\n leadingIcon,\n name,\n onBlur,\n onChange,\n onFocus,\n ref,\n rows = 3,\n style,\n trailingIcon,\n validate,\n value,\n variant = 'filled',\n ...props\n}: TextAreaProps) {\n const id = useId()\n const control = useRef<ComponentRef<typeof TextInput>>(null)\n const [own, setOwn] = useState(defaultValue)\n const current = value ?? own\n const validation = useFieldValidation({\n control,\n error,\n isDisabled,\n isEmpty: current === '',\n isReadOnly,\n isRequired,\n name,\n submitted: current,\n validate,\n value: current,\n })\n const focus = useFieldFocus({\n onBlur: blurThen(validation.onBlur, onBlur),\n onFocus,\n })\n const shownError = validation.error\n const locale = useLocaleOf(undefined)\n\n useImperativeHandle<\n ComponentRef<typeof TextInput> | null,\n ComponentRef<typeof TextInput> | null\n >(inputRef, () => control.current, [])\n\n return (\n <View ref={ref} style={style}>\n <FieldBox\n control={control}\n floatingLabel={floatingLabel}\n isDisabled={isDisabled}\n isFocused={focus.focused}\n isInvalid={shownError !== undefined}\n isPopulated={current !== ''}\n isRequired={isRequired}\n label={label}\n leading={leadingIcon}\n trailing={trailingIcon}\n variant={variant}\n >\n <FieldInput\n {...props}\n {...focus.handlers}\n aria-label={label}\n autosize={autosize}\n described={describedBy(id, {\n characterLimitLabel,\n description,\n error: shownError,\n locale,\n maxLength: props.maxLength,\n })}\n editable={!isDisabled && !isReadOnly}\n multiline\n onChangeText={editInto(setOwn, onChange, validation.onEdit)}\n ref={control}\n rows={rows}\n value={current}\n />\n </FieldBox>\n <FieldMessage\n characterCount={characterCount}\n characterLimitLabel={characterLimitLabel}\n description={description}\n error={shownError}\n id={id}\n length={current.length}\n maxLength={props.maxLength}\n />\n </View>\n )\n}\n\nexport { TextArea }\nexport type { TextAreaProps }\n"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { StyleProp, View, ViewProps, ViewStyle } from "react-native";
2
+ import { ComponentRef, ReactNode, Ref } from "react";
3
+ //#region src/components/toolbar/index.d.ts
4
+ type ToolbarProps = Omit<ViewProps, 'children' | 'style'> & {
5
+ /** The controls, and any rule between them. */
6
+ readonly children?: ReactNode;
7
+ /**
8
+ * Which way the bar runs. A `Separator` among its controls runs across it.
9
+ * @default 'horizontal'
10
+ */
11
+ readonly orientation?: 'horizontal' | 'vertical';
12
+ readonly ref?: Ref<ComponentRef<typeof View>>;
13
+ readonly style?: StyleProp<ViewStyle>;
14
+ /**
15
+ * Which of the page's two colour schemes the bar takes. `neutral` is the
16
+ * page's standard scheme, the surface container it draws by default;
17
+ * `vibrant` moves it to primary container, for a bar meant to carry the
18
+ * screen's accent.
19
+ * @default 'neutral'
20
+ */
21
+ readonly tone?: ToolbarTone;
22
+ };
23
+ type ToolbarTone = 'neutral' | 'vibrant';
24
+ /**
25
+ * A container for a set of controls, announced as a toolbar so a screen
26
+ * reader reads them as one group.
27
+ *
28
+ * ```tsx
29
+ * <Toolbar aria-label="Label">
30
+ * <IconButton aria-label="First item">
31
+ * <FirstIcon />
32
+ * </IconButton>
33
+ * <Separator />
34
+ * <IconButton aria-label="Second item">
35
+ * <SecondIcon />
36
+ * </IconButton>
37
+ * </Toolbar>
38
+ * ```
39
+ *
40
+ * Name it with `aria-label` or `aria-labelledby`: nothing here labels it for
41
+ * you, and a toolbar with no name is a group a screen reader cannot
42
+ * announce.
43
+ *
44
+ * `orientation` decides which way the bar runs, and a `Separator` among its
45
+ * controls draws across that direction without being told; one inside an
46
+ * overlay opened from the bar draws as it would anywhere else. `style`,
47
+ * `ref` and `testID` land on the bar, which is the element a layout
48
+ * positions.
49
+ */
50
+ declare function Toolbar({ children, orientation, style, tone, ...props }: ToolbarProps): import("react").JSX.Element;
51
+ //#endregion
52
+ export { Toolbar, type ToolbarProps, type ToolbarTone };
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,185 @@
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 { SeparatorOrientationContext } from "../../separator/index.js";
5
+ import { c } from "react/compiler-runtime";
6
+ import { Platform, StyleSheet, View } from "react-native";
7
+ import { jsx } from "react/jsx-runtime";
8
+ //#region src/components/toolbar/index.tsx
9
+ const ICON_SIZE = 24;
10
+ const VERTICAL = { "aria-orientation": "vertical" };
11
+ const stylesOf = themedStyles(({ colors, radii, spacing }) => StyleSheet.create({
12
+ base: {
13
+ alignItems: "center",
14
+ alignSelf: "flex-start",
15
+ borderRadius: radii.pill,
16
+ gap: spacing.sm,
17
+ justifyContent: "center"
18
+ },
19
+ horizontal: {
20
+ flexDirection: "row",
21
+ minHeight: 64,
22
+ paddingHorizontal: spacing.lg,
23
+ paddingVertical: spacing.sm
24
+ },
25
+ neutral: { backgroundColor: colors.surfaceContainer },
26
+ vertical: {
27
+ flexDirection: "column",
28
+ minWidth: 64,
29
+ paddingHorizontal: spacing.sm,
30
+ paddingVertical: spacing.lg
31
+ },
32
+ vibrant: { backgroundColor: colors.primaryContainer }
33
+ }));
34
+ function iconStyleOf(color) {
35
+ return {
36
+ color,
37
+ size: ICON_SIZE
38
+ };
39
+ }
40
+ /**
41
+ * A container for a set of controls, announced as a toolbar so a screen
42
+ * reader reads them as one group.
43
+ *
44
+ * ```tsx
45
+ * <Toolbar aria-label="Label">
46
+ * <IconButton aria-label="First item">
47
+ * <FirstIcon />
48
+ * </IconButton>
49
+ * <Separator />
50
+ * <IconButton aria-label="Second item">
51
+ * <SecondIcon />
52
+ * </IconButton>
53
+ * </Toolbar>
54
+ * ```
55
+ *
56
+ * Name it with `aria-label` or `aria-labelledby`: nothing here labels it for
57
+ * you, and a toolbar with no name is a group a screen reader cannot
58
+ * announce.
59
+ *
60
+ * `orientation` decides which way the bar runs, and a `Separator` among its
61
+ * controls draws across that direction without being told; one inside an
62
+ * overlay opened from the bar draws as it would anywhere else. `style`,
63
+ * `ref` and `testID` land on the bar, which is the element a layout
64
+ * positions.
65
+ */
66
+ function Toolbar(t0) {
67
+ const $ = c(37);
68
+ let children;
69
+ let props;
70
+ let style;
71
+ let t1;
72
+ let t2;
73
+ if ($[0] !== t0) {
74
+ ({children, orientation: t1, style, tone: t2, ...props} = t0);
75
+ $[0] = t0;
76
+ $[1] = children;
77
+ $[2] = props;
78
+ $[3] = style;
79
+ $[4] = t1;
80
+ $[5] = t2;
81
+ } else {
82
+ children = $[1];
83
+ props = $[2];
84
+ style = $[3];
85
+ t1 = $[4];
86
+ t2 = $[5];
87
+ }
88
+ const orientation = t1 === void 0 ? "horizontal" : t1;
89
+ const tone = t2 === void 0 ? "neutral" : t2;
90
+ const theme = useTheme();
91
+ let T0;
92
+ let T1;
93
+ let T2;
94
+ let t3;
95
+ let t4;
96
+ let t5;
97
+ let t6;
98
+ let t7;
99
+ let t8;
100
+ if ($[6] !== orientation || $[7] !== props || $[8] !== style || $[9] !== theme || $[10] !== tone) {
101
+ const own = stylesOf(theme);
102
+ const content = tone === "vibrant" ? theme.colors.onPrimaryContainer : theme.colors.onSurfaceVariant;
103
+ T2 = SeparatorOrientationContext;
104
+ t8 = orientation === "horizontal" ? "vertical" : "horizontal";
105
+ T1 = IconStyleContext;
106
+ if ($[20] !== content) {
107
+ t7 = iconStyleOf(content);
108
+ $[20] = content;
109
+ $[21] = t7;
110
+ } else t7 = $[21];
111
+ T0 = View;
112
+ t3 = "toolbar";
113
+ t4 = Platform.OS === "web" && orientation === "vertical" ? VERTICAL : void 0;
114
+ t5 = props;
115
+ t6 = composeStyles(own.base, own[orientation], own[tone], style);
116
+ $[6] = orientation;
117
+ $[7] = props;
118
+ $[8] = style;
119
+ $[9] = theme;
120
+ $[10] = tone;
121
+ $[11] = T0;
122
+ $[12] = T1;
123
+ $[13] = T2;
124
+ $[14] = t3;
125
+ $[15] = t4;
126
+ $[16] = t5;
127
+ $[17] = t6;
128
+ $[18] = t7;
129
+ $[19] = t8;
130
+ } else {
131
+ T0 = $[11];
132
+ T1 = $[12];
133
+ T2 = $[13];
134
+ t3 = $[14];
135
+ t4 = $[15];
136
+ t5 = $[16];
137
+ t6 = $[17];
138
+ t7 = $[18];
139
+ t8 = $[19];
140
+ }
141
+ let t9;
142
+ if ($[22] !== T0 || $[23] !== children || $[24] !== t3 || $[25] !== t4 || $[26] !== t5 || $[27] !== t6) {
143
+ t9 = /* @__PURE__ */ jsx(T0, {
144
+ role: t3,
145
+ ...t4,
146
+ ...t5,
147
+ style: t6,
148
+ children
149
+ });
150
+ $[22] = T0;
151
+ $[23] = children;
152
+ $[24] = t3;
153
+ $[25] = t4;
154
+ $[26] = t5;
155
+ $[27] = t6;
156
+ $[28] = t9;
157
+ } else t9 = $[28];
158
+ let t10;
159
+ if ($[29] !== T1 || $[30] !== t7 || $[31] !== t9) {
160
+ t10 = /* @__PURE__ */ jsx(T1, {
161
+ value: t7,
162
+ children: t9
163
+ });
164
+ $[29] = T1;
165
+ $[30] = t7;
166
+ $[31] = t9;
167
+ $[32] = t10;
168
+ } else t10 = $[32];
169
+ let t11;
170
+ if ($[33] !== T2 || $[34] !== t10 || $[35] !== t8) {
171
+ t11 = /* @__PURE__ */ jsx(T2, {
172
+ value: t8,
173
+ children: t10
174
+ });
175
+ $[33] = T2;
176
+ $[34] = t10;
177
+ $[35] = t8;
178
+ $[36] = t11;
179
+ } else t11 = $[36];
180
+ return t11;
181
+ }
182
+ //#endregion
183
+ export { Toolbar };
184
+
185
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ComponentRef","ReactNode","Ref","ColorValue","StyleProp","ViewProps","ViewStyle","Platform","StyleSheet","View","IconStyle","IconStyleContext","SeparatorOrientationContext","useTheme","composeStyles","themedStyles","ToolbarProps","Omit","children","orientation","ref","style","tone","ToolbarTone","ICON_SIZE","VERTICAL","const","stylesOf","colors","radii","spacing","create","base","alignItems","alignSelf","borderRadius","pill","gap","sm","justifyContent","horizontal","flexDirection","minHeight","paddingHorizontal","lg","paddingVertical","neutral","backgroundColor","surfaceContainer","vertical","minWidth","vibrant","primaryContainer","iconStyleOf","color","size","Toolbar","t0","$","_c","props","t1","t2","undefined","theme","T0","T1","T2","t3","t4","t5","t6","t7","t8","own","content","onPrimaryContainer","onSurfaceVariant","OS","t9","t10","t11","_c"],"sources":["../../../src/components/toolbar/index.tsx"],"sourcesContent":["import type { ComponentRef, ReactNode, Ref } from 'react'\nimport type { ColorValue, StyleProp, ViewProps, ViewStyle } from 'react-native'\n\nimport { Platform, StyleSheet, View } from 'react-native'\n\nimport type { IconStyle } from '../../glyphs/icon-style'\n\nimport { IconStyleContext } from '../../glyphs/icon-style'\nimport { SeparatorOrientationContext } from '../../separator'\nimport { useTheme } from '../../theme/scope'\nimport { composeStyles, themedStyles } from '../../theme/styles'\n\n// kanso-ui's Toolbar: the toolbars page's container, a row of frequently used\n// controls on a surface of its own. The page calls it \"a container with\n// configurable slots\", so nothing here says what goes in one: an icon\n// button, a button, a field or a rule are all the call site's to place.\n//\n// The measurements are the page's, stated there in words: 64dp across the\n// bar, its contents centred, 8dp between items and 16dp of padding at the two\n// ends. The two colour schemes are its own too, standard on surface container\n// and vibrant on primary container, each with its content role on what the\n// bar holds: on-surface variant, and on-primary container. `tone` spells the\n// standard one `neutral`, the word every `tone` in the library uses for its\n// neutral role. That role reaches a bare icon placed in the bar through\n// `useIconStyle()`, while a control keeps its own colours.\n//\n// **A rule inside it runs across the bar, not along it.** The bar tells a\n// `Separator` among its controls to run the other way, so a rule between two\n// controls is correct without the call site saying which way it runs. A modal\n// window opened from the bar clears that, and an overlay never sees it, so a\n// rule in a dialog, sheet or popover draws as it does anywhere else.\n//\n// It is announced as a toolbar, which tells a screen reader its controls\n// belong together. Web's arrow keys between the controls are React Aria's and\n// have no counterpart on a touch screen, so each control is reached as any\n// other is.\n//\n// One departure, about the shape, and it is web's. The page gives the\n// container's corner as a token its widget draws rather than writes, so there\n// is no value to read. The fully rounded corner here, and the bar hugging its\n// controls rather than spanning its parent, are the library's choice for a\n// bar that floats over a screen; a docked one spans its container and squares\n// its corner, both from the call site's `style`.\n\ntype ToolbarProps = Omit<ViewProps, 'children' | 'style'> & {\n /** The controls, and any rule between them. */\n readonly children?: ReactNode\n /**\n * Which way the bar runs. A `Separator` among its controls runs across it.\n * @default 'horizontal'\n */\n readonly orientation?: 'horizontal' | 'vertical'\n readonly ref?: Ref<ComponentRef<typeof View>>\n readonly style?: StyleProp<ViewStyle>\n /**\n * Which of the page's two colour schemes the bar takes. `neutral` is the\n * page's standard scheme, the surface container it draws by default;\n * `vibrant` moves it to primary container, for a bar meant to carry the\n * screen's accent.\n * @default 'neutral'\n */\n readonly tone?: ToolbarTone\n}\n\ntype ToolbarTone = 'neutral' | 'vibrant'\n\n// The icon a bare glyph in the bar draws at, the 24dp grid Material Symbols\n// are drawn on.\nconst ICON_SIZE = 24\n\n// React Native Web writes `aria-orientation` onto the element, which React\n// Native's types do not name. A horizontal bar needs none, since that is the\n// toolbar role's own default.\nconst VERTICAL = { 'aria-orientation': 'vertical' } as const\n\nconst stylesOf = themedStyles(({ colors, radii, spacing }) =>\n StyleSheet.create({\n base: {\n alignItems: 'center',\n alignSelf: 'flex-start',\n borderRadius: radii.pill,\n gap: spacing.sm,\n justifyContent: 'center',\n },\n // The page's 64dp across the bar, and its 16dp of padding at the two\n // ends. A minimum rather than a fixed size, since a field or a button\n // taller than 64dp should make the bar taller rather than overflow it.\n //\n // The cross axis takes the 8dp the page puts between items rather than\n // nothing. A `Separator` takes its length from the bar, so with no\n // padding there a rule would run the full 64dp and cut the container in\n // two instead of dividing what is inside it.\n horizontal: {\n flexDirection: 'row',\n minHeight: 64,\n paddingHorizontal: spacing.lg,\n paddingVertical: spacing.sm,\n },\n neutral: {\n backgroundColor: colors.surfaceContainer,\n },\n vertical: {\n flexDirection: 'column',\n minWidth: 64,\n paddingHorizontal: spacing.sm,\n paddingVertical: spacing.lg,\n },\n vibrant: {\n backgroundColor: colors.primaryContainer,\n },\n }),\n)\n\n// Built by a call rather than written inline at the prop, which is what\n// react-perf's jsx-no-new-object-as-prop is after; the React Compiler\n// memoises the result on its inputs.\nfunction iconStyleOf(color: ColorValue): IconStyle {\n return { color, size: ICON_SIZE }\n}\n\n/**\n * A container for a set of controls, announced as a toolbar so a screen\n * reader reads them as one group.\n *\n * ```tsx\n * <Toolbar aria-label=\"Label\">\n * <IconButton aria-label=\"First item\">\n * <FirstIcon />\n * </IconButton>\n * <Separator />\n * <IconButton aria-label=\"Second item\">\n * <SecondIcon />\n * </IconButton>\n * </Toolbar>\n * ```\n *\n * Name it with `aria-label` or `aria-labelledby`: nothing here labels it for\n * you, and a toolbar with no name is a group a screen reader cannot\n * announce.\n *\n * `orientation` decides which way the bar runs, and a `Separator` among its\n * controls draws across that direction without being told; one inside an\n * overlay opened from the bar draws as it would anywhere else. `style`,\n * `ref` and `testID` land on the bar, which is the element a layout\n * positions.\n */\nfunction Toolbar({\n children,\n orientation = 'horizontal',\n style,\n tone = 'neutral',\n ...props\n}: ToolbarProps) {\n const theme = useTheme()\n const own = stylesOf(theme)\n const content =\n tone === 'vibrant'\n ? theme.colors.onPrimaryContainer\n : theme.colors.onSurfaceVariant\n\n return (\n <SeparatorOrientationContext\n value={orientation === 'horizontal' ? 'vertical' : 'horizontal'}\n >\n <IconStyleContext value={iconStyleOf(content)}>\n <View\n role=\"toolbar\"\n {...(Platform.OS === 'web' && orientation === 'vertical'\n ? VERTICAL\n : undefined)}\n {...props}\n style={composeStyles<ViewStyle>(\n own.base,\n own[orientation],\n own[tone],\n style,\n )}\n >\n {children}\n </View>\n </IconStyleContext>\n </SeparatorOrientationContext>\n )\n}\n\nexport { Toolbar }\nexport type { ToolbarProps, ToolbarTone }\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { createContext } from "react";
2
+ //#region src/control/group.ts
3
+ const CheckboxGroupContext = createContext(null);
4
+ /** An empty list of a group's checkboxes, made once per group. */
5
+ function createMembers() {
6
+ const controls = /* @__PURE__ */ new Map();
7
+ return {
8
+ add: (id, control) => {
9
+ controls.set(id, control);
10
+ },
11
+ get current() {
12
+ for (const control of controls.values()) if (control.current !== null) return control.current;
13
+ return null;
14
+ },
15
+ remove: (id) => {
16
+ controls.delete(id);
17
+ }
18
+ };
19
+ }
20
+ //#endregion
21
+ export { CheckboxGroupContext, createMembers };
22
+
23
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","names":["RefObject","createContext","Focusable","CheckboxGroupContextValue","isDisabled","isInvalid","isReadOnly","isSelected","value","members","CheckboxGroupMembers","set","add","id","control","remove","CheckboxGroupContext","createMembers","controls","Map","current","values","delete"],"sources":["../../src/control/group.ts"],"sourcesContent":["import type { RefObject } from 'react'\n\nimport { createContext } from 'react'\n\nimport type { Focusable } from '../form'\n\n// What a CheckboxGroup tells the checkboxes inside it, as React Aria's group\n// state does on web: which entries are selected, how to change one, and the\n// states that reach every box from the group. Beside src/control's row\n// rather than in the group's own module, so Checkbox reads it without\n// importing the group.\n\ntype CheckboxGroupContextValue = {\n readonly isDisabled: boolean\n readonly isInvalid: boolean\n readonly isReadOnly: boolean\n readonly isSelected: (value: string) => boolean\n readonly members: CheckboxGroupMembers\n /** Selects or clears one entry, as a press on its checkbox does. */\n readonly set: (value: string, isSelected: boolean) => void\n}\n\n/**\n * A group's checkboxes, in the order they mounted, which is the order they\n * are drawn in. As a ref it holds the first of them that has a control, which\n * is what the form around the group focuses when the group holds a native\n * submission back.\n */\ntype CheckboxGroupMembers = RefObject<Focusable | null> & {\n /** Adds a checkbox's control, keeping its place if it is already there. */\n readonly add: (id: string, control: RefObject<Focusable | null>) => void\n readonly remove: (id: string) => void\n}\n\nconst CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(\n null,\n)\n\n/** An empty list of a group's checkboxes, made once per group. */\nfunction createMembers(): CheckboxGroupMembers {\n const controls = new Map<string, RefObject<Focusable | null>>()\n\n return {\n add: (id, control) => {\n controls.set(id, control)\n },\n get current() {\n for (const control of controls.values()) {\n if (control.current !== null) {\n return control.current\n }\n }\n return null\n },\n remove: (id) => {\n controls.delete(id)\n },\n }\n}\n\nexport { CheckboxGroupContext, createMembers }\nexport type { CheckboxGroupContextValue, CheckboxGroupMembers }\n"],"mappings":";;AAkCA,MAAMgB,uBAAuBf,cAC3B,IACF;;AAGA,SAASgB,gBAAsC;CAC7C,MAAMC,2BAAW,IAAIC,IAAyC;CAE9D,OAAO;EACLP,MAAMC,IAAIC,YAAY;GACpBI,SAASP,IAAIE,IAAIC,OAAO;EAC1B;EACA,IAAIM,UAAU;GACZ,KAAK,MAAMN,WAAWI,SAASG,OAAO,GACpC,IAAIP,QAAQM,YAAY,MACtB,OAAON,QAAQM;GAGnB,OAAO;EACT;EACAL,SAASF,OAAO;GACdK,SAASI,OAAOT,EAAE;EACpB;CACF;AACF"}
@@ -0,0 +1,19 @@
1
+ import "../button/palettes.js";
2
+ import "../typography/roles.js";
3
+ import { ViewStyle } from "react-native";
4
+ //#region src/fab/index.d.ts
5
+ /**
6
+ * The pages' three sizes: `md` the FAB at 56dp, `lg` the medium FAB at 80dp
7
+ * and `xl` the large FAB at 96dp.
8
+ */
9
+ type FabSize = 'lg' | 'md' | 'xl';
10
+ /** The colour role a FAB is drawn in. */
11
+ type FabTone = 'primary' | 'secondary' | 'tertiary';
12
+ /**
13
+ * `tonal` draws the tone's container pair, the pages' default; `filled`
14
+ * draws the tone itself.
15
+ */
16
+ type FabVariant = 'filled' | 'tonal';
17
+ //#endregion
18
+ export type { FabSize, FabTone, FabVariant };
19
+ //# sourceMappingURL=index.d.ts.map