@kanso-labs/react-native-kanso-ui 0.7.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 (150) hide show
  1. package/README.md +37 -0
  2. package/dist/badge/index.js +9 -68
  3. package/dist/badge/index.js.map +1 -1
  4. package/dist/button/index.d.ts +2 -1
  5. package/dist/button/index.js +1 -1
  6. package/dist/button/index.js.map +1 -1
  7. package/dist/button/palettes.d.ts +2 -0
  8. package/dist/button/pending.js +17 -21
  9. package/dist/button/pending.js.map +1 -1
  10. package/dist/calendar/index.js +1 -1
  11. package/dist/components/autocomplete/index.js +28 -26
  12. package/dist/components/autocomplete/index.js.map +1 -1
  13. package/dist/components/avatar/index.d.ts +2 -2
  14. package/dist/components/avatar/index.js +2 -2
  15. package/dist/components/avatar/index.js.map +1 -1
  16. package/dist/components/badge/index.d.ts +48 -0
  17. package/dist/components/badge/index.js +122 -0
  18. package/dist/components/badge/index.js.map +1 -0
  19. package/dist/{badge → components/badge}/styles.js +10 -6
  20. package/dist/components/badge/styles.js.map +1 -0
  21. package/dist/components/breadcrumbs/index.d.ts +66 -0
  22. package/dist/components/breadcrumbs/index.js +285 -0
  23. package/dist/components/breadcrumbs/index.js.map +1 -0
  24. package/dist/components/calendar/index.d.ts +1 -1
  25. package/dist/components/calendar/index.js +77 -38
  26. package/dist/components/calendar/index.js.map +1 -1
  27. package/dist/components/checkbox/index.d.ts +7 -1
  28. package/dist/components/checkbox/index.js +183 -138
  29. package/dist/components/checkbox/index.js.map +1 -1
  30. package/dist/components/checkbox-group/index.d.ts +93 -0
  31. package/dist/components/checkbox-group/index.js +306 -0
  32. package/dist/components/checkbox-group/index.js.map +1 -0
  33. package/dist/components/chip-group/index.d.ts +4 -3
  34. package/dist/components/chip-group/index.js +47 -45
  35. package/dist/components/chip-group/index.js.map +1 -1
  36. package/dist/components/code/index.d.ts +25 -0
  37. package/dist/components/code/index.js +87 -0
  38. package/dist/components/code/index.js.map +1 -0
  39. package/dist/components/container/index.d.ts +47 -0
  40. package/dist/components/container/index.js +85 -0
  41. package/dist/components/container/index.js.map +1 -0
  42. package/dist/components/copy-field/index.d.ts +5 -5
  43. package/dist/components/copy-field/index.js +30 -28
  44. package/dist/components/copy-field/index.js.map +1 -1
  45. package/dist/components/currency/index.d.ts +2 -2
  46. package/dist/components/currency/index.js +3 -1
  47. package/dist/components/currency/index.js.map +1 -1
  48. package/dist/components/fab/index.d.ts +80 -0
  49. package/dist/components/fab/index.js +231 -0
  50. package/dist/components/fab/index.js.map +1 -0
  51. package/dist/components/fab-menu/index.d.ts +120 -0
  52. package/dist/components/fab-menu/index.js +640 -0
  53. package/dist/components/fab-menu/index.js.map +1 -0
  54. package/dist/components/feed/index.d.ts +57 -0
  55. package/dist/components/feed/index.js +167 -0
  56. package/dist/components/feed/index.js.map +1 -0
  57. package/dist/components/keycap/index.d.ts +27 -0
  58. package/dist/components/keycap/index.js +136 -0
  59. package/dist/components/keycap/index.js.map +1 -0
  60. package/dist/components/list/index.d.ts +6 -5
  61. package/dist/components/list/index.js +97 -106
  62. package/dist/components/list/index.js.map +1 -1
  63. package/dist/components/menu/index.d.ts +4 -3
  64. package/dist/components/menu/index.js +33 -40
  65. package/dist/components/menu/index.js.map +1 -1
  66. package/dist/components/meter/index.d.ts +2 -1
  67. package/dist/components/meter/index.js +9 -7
  68. package/dist/components/meter/index.js.map +1 -1
  69. package/dist/components/number-field/index.d.ts +7 -3
  70. package/dist/components/number-field/index.js +214 -192
  71. package/dist/components/number-field/index.js.map +1 -1
  72. package/dist/components/product-icon/index.d.ts +2 -2
  73. package/dist/components/product-icon/index.js +2 -2
  74. package/dist/components/product-icon/index.js.map +1 -1
  75. package/dist/components/progress-indicator/index.d.ts +2 -1
  76. package/dist/components/progress-indicator/index.js +15 -13
  77. package/dist/components/progress-indicator/index.js.map +1 -1
  78. package/dist/components/search-field/index.d.ts +3 -3
  79. package/dist/components/search-field/index.js +105 -104
  80. package/dist/components/search-field/index.js.map +1 -1
  81. package/dist/components/separator/index.d.ts +3 -2
  82. package/dist/components/separator/index.js +29 -26
  83. package/dist/components/separator/index.js.map +1 -1
  84. package/dist/components/sheet/index.d.ts +2 -2
  85. package/dist/components/sheet/index.js +22 -26
  86. package/dist/components/sheet/index.js.map +1 -1
  87. package/dist/components/snackbar/index.d.ts +3 -3
  88. package/dist/components/snackbar/index.js +36 -34
  89. package/dist/components/snackbar/index.js.map +1 -1
  90. package/dist/components/supporting-pane/index.d.ts +44 -0
  91. package/dist/components/supporting-pane/index.js +109 -0
  92. package/dist/components/supporting-pane/index.js.map +1 -0
  93. package/dist/components/tag/index.d.ts +58 -0
  94. package/dist/components/tag/index.js +205 -0
  95. package/dist/components/tag/index.js.map +1 -0
  96. package/dist/components/text/index.d.ts +1 -1
  97. package/dist/components/text/index.js +49 -21
  98. package/dist/components/text/index.js.map +1 -1
  99. package/dist/components/text-area/index.d.ts +145 -0
  100. package/dist/components/text-area/index.js +231 -0
  101. package/dist/components/text-area/index.js.map +1 -0
  102. package/dist/components/text-field/index.d.ts +6 -3
  103. package/dist/components/text-field/index.js +3 -0
  104. package/dist/components/text-field/index.js.map +1 -1
  105. package/dist/components/toolbar/index.d.ts +53 -0
  106. package/dist/components/toolbar/index.js +185 -0
  107. package/dist/components/toolbar/index.js.map +1 -0
  108. package/dist/control/group.js +23 -0
  109. package/dist/control/group.js.map +1 -0
  110. package/dist/fab/index.d.ts +19 -0
  111. package/dist/fab/index.js +147 -0
  112. package/dist/fab/index.js.map +1 -0
  113. package/dist/field/index.js +123 -79
  114. package/dist/field/index.js.map +1 -1
  115. package/dist/field/styles.js +18 -0
  116. package/dist/field/styles.js.map +1 -1
  117. package/dist/form/index.d.ts +1 -2
  118. package/dist/form/index.js +1 -1
  119. package/dist/form/index.js.map +1 -1
  120. package/dist/i18n/index.js +12 -1
  121. package/dist/i18n/index.js.map +1 -1
  122. package/dist/i18n/messages.js +367 -0
  123. package/dist/i18n/messages.js.map +1 -1
  124. package/dist/i18n/provider.d.ts +53 -0
  125. package/dist/i18n/provider.js +96 -0
  126. package/dist/i18n/provider.js.map +1 -0
  127. package/dist/index.d.ts +19 -4
  128. package/dist/index.js +17 -3
  129. package/dist/indicator/index.js +1 -2
  130. package/dist/indicator/index.js.map +1 -1
  131. package/dist/mark/index.js +77 -117
  132. package/dist/mark/index.js.map +1 -1
  133. package/dist/mark/initials.js.map +1 -1
  134. package/dist/modal/index.js +59 -46
  135. package/dist/modal/index.js.map +1 -1
  136. package/dist/navigation/index.js +8 -5
  137. package/dist/navigation/index.js.map +1 -1
  138. package/dist/number/count.js +15 -0
  139. package/dist/number/count.js.map +1 -0
  140. package/dist/number/locale.js.map +1 -1
  141. package/dist/overlay/host.js +30 -21
  142. package/dist/overlay/host.js.map +1 -1
  143. package/dist/overlay/placement.js +3 -1
  144. package/dist/overlay/placement.js.map +1 -1
  145. package/dist/separator/index.js +7 -0
  146. package/dist/separator/index.js.map +1 -0
  147. package/dist/typography/size.js +14 -0
  148. package/dist/typography/size.js.map +1 -0
  149. package/package.json +1 -1
  150. package/dist/badge/styles.js.map +0 -1
@@ -1 +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","TextFieldProps","Omit","characterCount","characterLimitLabel","defaultValue","description","error","floatingLabel","inputRef","isDisabled","isReadOnly","isRequired","label","leadingIcon","name","numeric","onChange","value","prefix","ref","style","suffix","trailingIcon","validate","variant","blurThen","onBlur","then","event","editInto","setOwn","onEdit","text","TextField","t0","$","_c","t1","t2","t3","t4","t5","t6","t7","onFocus","t8","props","undefined","id","control","own","current","t9","t10","isEmpty","submitted","validation","t11","t12","focus","shownError","t13","t14","Symbol","for","T0","T1","t15","focused","t16","t17","T2","t18","handlers","t19","maxLength","t20","t21","t22","t23","t24","length","t25","_c"],"sources":["../../../src/components/text-field/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'\n\n// kanso-ui's TextField, drawn through the field chrome in src/field: the box\n// with its label and icons, the control on the value's line with its prefix\n// and suffix, and the supporting line under it with the count. What the\n// chrome draws, and how it draws it, is written there.\n//\n// The value is the field's own or the call site's. Given `value` it shows\n// that and reports edits through `onChange`; given `defaultValue`, or\n// nothing, it keeps what is typed itself. `onChange` is handed the string, as\n// web's is, rather than React Native's event.\n//\n// **Web's `isInvalid` is not a prop here either.** The error is what puts the\n// field in its error state, the message and the colours and the invalid\n// state a screen reader reads following from it, so a field cannot be\n// invalid with nothing to say why. The error shown is `error`, or what the\n// field's `validate` and the `Form` around it say, which src/form decides.\n\ntype TextFieldProps = 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 | 'selectionColor'\n | 'style'\n | 'underlineColorAndroid'\n | 'value'\n> & {\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 device's digits.\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 English\n * sentence, \"Up to 20 characters\", 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 field 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 value: 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 /**\n * Renders the value in the mono face with tabular figures, for amounts and\n * other numbers meant to be compared down a column.\n * @default false\n */\n readonly numeric?: boolean\n /** Called with the new value as it is edited. */\n readonly onChange?: (value: string) => void\n /**\n * Text before the value on its line, in the muted role, shown while the\n * field is focused or holds a value.\n */\n readonly prefix?: ReactNode\n readonly ref?: Ref<ComponentRef<typeof View>>\n /** Positions and sizes the field as a whole. */\n readonly style?: StyleProp<ViewStyle>\n /**\n * Text after the value on its line, in the muted role, shown while the\n * field is focused or holds a value.\n */\n readonly suffix?: ReactNode\n /**\n * An icon at the end of the box, after the value: 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 single-line input, the text fields page's filled or outlined\n * field. Pass `value` with `onChange` to control it, or `defaultValue` to let\n * it keep its own; `onChange` is handed the string.\n *\n * The page's configurations are props: `leadingIcon` and `trailingIcon` at\n * the box's ends, `prefix` and `suffix` on the value's line, and\n * `characterCount` opposite the supporting text, counting against\n * `maxLength`. React Native's own `TextInput` props, the keyboard and the\n * return key among them, reach the control; `style` and `ref` are the field\n * as a whole, and `inputRef` the control.\n *\n * ```tsx\n * <TextField label=\"Label\" description=\"Supporting line\" />\n * ```\n */\nfunction TextField({\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 numeric = false,\n onBlur,\n onChange,\n onFocus,\n prefix,\n ref,\n style,\n suffix,\n trailingIcon,\n validate,\n value,\n variant = 'filled',\n ...props\n}: TextFieldProps) {\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\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 described={describedBy(id, {\n characterLimitLabel,\n description,\n error: shownError,\n maxLength: props.maxLength,\n })}\n editable={!isDisabled && !isReadOnly}\n numeric={numeric}\n onChangeText={editInto(setOwn, onChange, validation.onEdit)}\n prefix={prefix}\n ref={control}\n suffix={suffix}\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 { TextField }\nexport type { TextFieldProps }\n"],"mappings":"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"}
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","TextFieldProps","Omit","characterCount","characterLimitLabel","defaultValue","description","error","floatingLabel","inputRef","isDisabled","isReadOnly","isRequired","label","leadingIcon","name","numeric","onChange","value","prefix","ref","style","suffix","trailingIcon","validate","variant","blurThen","onBlur","then","event","editInto","setOwn","onEdit","text","TextField","t0","$","_c","t1","t2","t3","t4","t5","t6","t7","onFocus","t8","props","undefined","id","control","own","current","t9","t10","isEmpty","submitted","validation","t11","t12","focus","shownError","locale","t13","t14","Symbol","for","T0","T1","t15","focused","t16","t17","T2","t18","handlers","t19","maxLength","t20","t21","t22","t23","t24","length","t25","_c"],"sources":["../../../src/components/text-field/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 TextField, drawn through the field chrome in src/field: the box\n// with its label and icons, the control on the value's line with its prefix\n// and suffix, and the supporting line under it with the count. What the\n// chrome draws, and how it draws it, is written there.\n//\n// The value is the field's own or the call site's. Given `value` it shows\n// that and reports edits through `onChange`; given `defaultValue`, or\n// nothing, it keeps what is typed itself. `onChange` is handed the string, as\n// web's is, rather than React Native's event.\n//\n// **Web's `isInvalid` is not a prop here either.** The error is what puts the\n// field in its error state, the message and the colours and the invalid\n// state a screen reader reads following from it, so a field cannot be\n// invalid with nothing to say why. The error shown is `error`, or what the\n// field's `validate` and the `Form` around it say, which src/form decides.\n\ntype TextFieldProps = 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 | 'selectionColor'\n | 'style'\n | 'underlineColorAndroid'\n | 'value'\n> & {\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 field 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 value: 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 /**\n * Renders the value in the mono face with tabular figures, for amounts and\n * other numbers meant to be compared down a column.\n * @default false\n */\n readonly numeric?: boolean\n /** Called with the new value as it is edited. */\n readonly onChange?: (value: string) => void\n /**\n * Text before the value on its line, in the muted role, shown while the\n * field is focused or holds a value.\n */\n readonly prefix?: ReactNode\n readonly ref?: Ref<ComponentRef<typeof View>>\n /** Positions and sizes the field as a whole. */\n readonly style?: StyleProp<ViewStyle>\n /**\n * Text after the value on its line, in the muted role, shown while the\n * field is focused or holds a value.\n */\n readonly suffix?: ReactNode\n /**\n * An icon at the end of the box, after the value: 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 single-line input, the text fields page's filled or outlined\n * field. Pass `value` with `onChange` to control it, or `defaultValue` to let\n * it keep its own; `onChange` is handed the string.\n *\n * The page's configurations are props: `leadingIcon` and `trailingIcon` at\n * the box's ends, `prefix` and `suffix` on the value's line, and\n * `characterCount` opposite the supporting text, counting against\n * `maxLength`. React Native's own `TextInput` props, the keyboard and the\n * return key among them, reach the control; `style` and `ref` are the field\n * as a whole, and `inputRef` the control.\n *\n * ```tsx\n * <TextField label=\"Label\" description=\"Supporting line\" />\n * ```\n */\nfunction TextField({\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 numeric = false,\n onBlur,\n onChange,\n onFocus,\n prefix,\n ref,\n style,\n suffix,\n trailingIcon,\n validate,\n value,\n variant = 'filled',\n ...props\n}: TextFieldProps) {\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 described={describedBy(id, {\n characterLimitLabel,\n description,\n error: shownError,\n locale,\n maxLength: props.maxLength,\n })}\n editable={!isDisabled && !isReadOnly}\n numeric={numeric}\n onChangeText={editInto(setOwn, onChange, validation.onEdit)}\n prefix={prefix}\n ref={control}\n suffix={suffix}\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 { TextField }\nexport type { TextFieldProps }\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
@@ -0,0 +1,147 @@
1
+ import { themedStyles } from "../theme/styles.js";
2
+ import { palettesOf } from "../button/palettes.js";
3
+ import { StyleSheet } from "react-native";
4
+ //#region src/fab/index.ts
5
+ const MEDIUM_SIZE = 80;
6
+ const MEDIUM_CORNER = 20;
7
+ /** The icon each size draws, from the pages' size token sets. */
8
+ const FAB_ICON_SIZES = {
9
+ lg: 28,
10
+ md: 24,
11
+ xl: 36
12
+ };
13
+ /** The type role the extended form sets its label in at each size. */
14
+ const EXTENDED_FAB_ROLES = {
15
+ lg: "titleLarge",
16
+ md: "titleMedium",
17
+ xl: "headlineSmall"
18
+ };
19
+ /**
20
+ * Each size's corner, apart from its size so the press feedback can clip to
21
+ * the same one.
22
+ */
23
+ const fabCornersOf = themedStyles(({ radii }) => StyleSheet.create({
24
+ lg: { borderRadius: MEDIUM_CORNER },
25
+ md: { borderRadius: radii.lg },
26
+ xl: { borderRadius: radii.xl }
27
+ }));
28
+ /** The FAB on its own: a square of the size's edge. */
29
+ const fabSizesOf = themedStyles(({ sizing }) => StyleSheet.create({
30
+ lg: {
31
+ height: MEDIUM_SIZE,
32
+ width: MEDIUM_SIZE
33
+ },
34
+ md: {
35
+ height: sizing.controlLg,
36
+ width: sizing.controlLg
37
+ },
38
+ xl: {
39
+ height: sizing.controlXl,
40
+ width: sizing.controlXl
41
+ }
42
+ }));
43
+ /**
44
+ * The extended form: the size's height, with its padding at either end and
45
+ * the gap before the label. The 26dp and 28dp paddings fall between steps of
46
+ * the spacing scale and are written out, as on web.
47
+ *
48
+ * The height is a floor rather than a fixed size, so a label the device's
49
+ * text size enlarges grows the button rather than spilling out of it, which
50
+ * web's fixed height has no need to allow for.
51
+ */
52
+ const extendedFabSizesOf = themedStyles(({ sizing, spacing }) => StyleSheet.create({
53
+ lg: {
54
+ columnGap: spacing.md,
55
+ minHeight: MEDIUM_SIZE,
56
+ paddingHorizontal: 26
57
+ },
58
+ md: {
59
+ columnGap: spacing.sm,
60
+ minHeight: sizing.controlLg,
61
+ paddingHorizontal: spacing.lg
62
+ },
63
+ xl: {
64
+ columnGap: spacing.lg,
65
+ minHeight: sizing.controlXl,
66
+ paddingHorizontal: 28
67
+ }
68
+ }));
69
+ /**
70
+ * The six colour pairs, by variant and tone: each tone's container pair, and
71
+ * the tone itself. Plain colours, for FabMenu's FAB, which eases from one
72
+ * pair to another as its menu opens.
73
+ */
74
+ const fabColorsOf = themedStyles(({ colors }) => ({
75
+ filled: {
76
+ primary: {
77
+ container: colors.primary,
78
+ content: colors.onPrimary
79
+ },
80
+ secondary: {
81
+ container: colors.secondary,
82
+ content: colors.onSecondary
83
+ },
84
+ tertiary: {
85
+ container: colors.tertiary,
86
+ content: colors.onTertiary
87
+ }
88
+ },
89
+ tonal: {
90
+ primary: {
91
+ container: colors.primaryContainer,
92
+ content: colors.onPrimaryContainer
93
+ },
94
+ secondary: {
95
+ container: colors.secondaryContainer,
96
+ content: colors.onSecondaryContainer
97
+ },
98
+ tertiary: {
99
+ container: colors.tertiaryContainer,
100
+ content: colors.onTertiaryContainer
101
+ }
102
+ }
103
+ }));
104
+ /**
105
+ * The six colour pairs as the palettes a button draws, and the one disabled
106
+ * container every button shares: on-surface at the two disabled opacities,
107
+ * as src/button/palettes.ts draws it.
108
+ */
109
+ const fabPalettesOf = themedStyles((theme) => {
110
+ const pairs = fabColorsOf(theme);
111
+ return {
112
+ disabled: palettesOf(theme).filledDisabled,
113
+ filled: palettesFor(pairs.filled),
114
+ tonal: palettesFor(pairs.tonal)
115
+ };
116
+ });
117
+ const fabShadowsOf = themedStyles(({ shadows }) => StyleSheet.create({
118
+ elevation3: { boxShadow: shadows.elevation3 },
119
+ elevation4: { boxShadow: shadows.elevation4 }
120
+ }));
121
+ /**
122
+ * The shadow a FAB draws in its state: level 3 at rest and while pressed,
123
+ * level 4 under a hovering pointer, and none while disabled, since a shadow
124
+ * says a control is there to press.
125
+ */
126
+ function fabShadowOf({ hovered, pressed }, isDisabled, theme) {
127
+ if (isDisabled) return;
128
+ return fabShadowsOf(theme)[hovered && !pressed ? "elevation4" : "elevation3"];
129
+ }
130
+ function palette({ container, content }) {
131
+ return {
132
+ container: { backgroundColor: container },
133
+ content,
134
+ label: { color: content }
135
+ };
136
+ }
137
+ function palettesFor(pairs) {
138
+ return {
139
+ primary: palette(pairs.primary),
140
+ secondary: palette(pairs.secondary),
141
+ tertiary: palette(pairs.tertiary)
142
+ };
143
+ }
144
+ //#endregion
145
+ export { EXTENDED_FAB_ROLES, FAB_ICON_SIZES, extendedFabSizesOf, fabColorsOf, fabCornersOf, fabPalettesOf, fabShadowOf, fabSizesOf };
146
+
147
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ViewStyle","StyleSheet","Palette","ResolvedTheme","TypeRole","palettesOf","themedStyles","FabSize","FabTone","FabVariant","MEDIUM_SIZE","MEDIUM_CORNER","FAB_ICON_SIZES","Readonly","Record","lg","md","xl","EXTENDED_FAB_ROLES","fabCornersOf","radii","create","borderRadius","fabSizesOf","sizing","height","width","controlLg","controlXl","extendedFabSizesOf","spacing","columnGap","minHeight","paddingHorizontal","sm","FabColors","container","content","fabColorsOf","colors","filled","primary","onPrimary","secondary","onSecondary","tertiary","onTertiary","tonal","primaryContainer","onPrimaryContainer","secondaryContainer","onSecondaryContainer","tertiaryContainer","onTertiaryContainer","fabPalettesOf","theme","disabled","pairs","filledDisabled","palettesFor","fabShadowsOf","shadows","elevation3","boxShadow","elevation4","fabShadowOf","hovered","pressed","isDisabled","undefined","palette","backgroundColor","label","color"],"sources":["../../src/fab/index.ts"],"sourcesContent":["import type { ViewStyle } from 'react-native'\n\nimport { StyleSheet } from 'react-native'\n\nimport type { Palette } from '../button/palettes'\nimport type { ResolvedTheme } from '../theme/scope'\nimport type { TypeRole } from '../typography/roles'\n\nimport { palettesOf } from '../button/palettes'\nimport { themedStyles } from '../theme/styles'\n\n// The FAB's metrics and colours, shared by Fab and by the FAB that opens\n// FabMenu, which is the same button until its menu opens, as web's\n// src/fab/styles.ts is shared. Apart from either component, and outside\n// `src/components`, which holds the public components alone. Fab's header\n// gives the values and where they come from.\n\n/**\n * The pages' three sizes: `md` the FAB at 56dp, `lg` the medium FAB at 80dp\n * and `xl` the large FAB at 96dp.\n */\ntype FabSize = 'lg' | 'md' | 'xl'\n\n/** The colour role a FAB is drawn in. */\ntype FabTone = 'primary' | 'secondary' | 'tertiary'\n\n/**\n * `tonal` draws the tone's container pair, the pages' default; `filled`\n * draws the tone itself.\n */\ntype FabVariant = 'filled' | 'tonal'\n\n// The medium FAB's container and corner, between the steps of the control\n// and radius scales, so written out as web writes them.\nconst MEDIUM_SIZE = 80\nconst MEDIUM_CORNER = 20\n\n/** The icon each size draws, from the pages' size token sets. */\nconst FAB_ICON_SIZES: Readonly<Record<FabSize, number>> = {\n lg: 28,\n md: 24,\n xl: 36,\n}\n\n/** The type role the extended form sets its label in at each size. */\nconst EXTENDED_FAB_ROLES: Readonly<Record<FabSize, TypeRole>> = {\n lg: 'titleLarge',\n md: 'titleMedium',\n xl: 'headlineSmall',\n}\n\n/**\n * Each size's corner, apart from its size so the press feedback can clip to\n * the same one.\n */\nconst fabCornersOf = themedStyles(({ radii }) =>\n StyleSheet.create({\n lg: { borderRadius: MEDIUM_CORNER },\n md: { borderRadius: radii.lg },\n xl: { borderRadius: radii.xl },\n }),\n)\n\n/** The FAB on its own: a square of the size's edge. */\nconst fabSizesOf = themedStyles(({ sizing }) =>\n StyleSheet.create({\n lg: { height: MEDIUM_SIZE, width: MEDIUM_SIZE },\n md: { height: sizing.controlLg, width: sizing.controlLg },\n xl: { height: sizing.controlXl, width: sizing.controlXl },\n }),\n)\n\n/**\n * The extended form: the size's height, with its padding at either end and\n * the gap before the label. The 26dp and 28dp paddings fall between steps of\n * the spacing scale and are written out, as on web.\n *\n * The height is a floor rather than a fixed size, so a label the device's\n * text size enlarges grows the button rather than spilling out of it, which\n * web's fixed height has no need to allow for.\n */\nconst extendedFabSizesOf = themedStyles(({ sizing, spacing }) =>\n StyleSheet.create({\n lg: {\n columnGap: spacing.md,\n minHeight: MEDIUM_SIZE,\n paddingHorizontal: 26,\n },\n md: {\n columnGap: spacing.sm,\n minHeight: sizing.controlLg,\n paddingHorizontal: spacing.lg,\n },\n xl: {\n columnGap: spacing.lg,\n minHeight: sizing.controlXl,\n paddingHorizontal: 28,\n },\n }),\n)\n\n/** A FAB's container colour and the colour drawn on it. */\ntype FabColors = { readonly container: string; readonly content: string }\n\n/**\n * The six colour pairs, by variant and tone: each tone's container pair, and\n * the tone itself. Plain colours, for FabMenu's FAB, which eases from one\n * pair to another as its menu opens.\n */\nconst fabColorsOf = themedStyles(\n ({\n colors,\n }): Readonly<Record<FabVariant, Readonly<Record<FabTone, FabColors>>>> => ({\n filled: {\n primary: { container: colors.primary, content: colors.onPrimary },\n secondary: { container: colors.secondary, content: colors.onSecondary },\n tertiary: { container: colors.tertiary, content: colors.onTertiary },\n },\n tonal: {\n primary: {\n container: colors.primaryContainer,\n content: colors.onPrimaryContainer,\n },\n secondary: {\n container: colors.secondaryContainer,\n content: colors.onSecondaryContainer,\n },\n tertiary: {\n container: colors.tertiaryContainer,\n content: colors.onTertiaryContainer,\n },\n },\n }),\n)\n\n/**\n * The six colour pairs as the palettes a button draws, and the one disabled\n * container every button shares: on-surface at the two disabled opacities,\n * as src/button/palettes.ts draws it.\n */\nconst fabPalettesOf = themedStyles(\n (\n theme,\n ): {\n readonly disabled: Palette\n readonly filled: Readonly<Record<FabTone, Palette>>\n readonly tonal: Readonly<Record<FabTone, Palette>>\n } => {\n const pairs = fabColorsOf(theme)\n\n return {\n disabled: palettesOf(theme).filledDisabled,\n filled: palettesFor(pairs.filled),\n tonal: palettesFor(pairs.tonal),\n }\n },\n)\n\nconst fabShadowsOf = themedStyles(({ shadows }) =>\n StyleSheet.create({\n elevation3: { boxShadow: shadows.elevation3 },\n elevation4: { boxShadow: shadows.elevation4 },\n }),\n)\n\n/**\n * The shadow a FAB draws in its state: level 3 at rest and while pressed,\n * level 4 under a hovering pointer, and none while disabled, since a shadow\n * says a control is there to press.\n */\nfunction fabShadowOf(\n {\n hovered,\n pressed,\n }: { readonly hovered: boolean; readonly pressed: boolean },\n isDisabled: boolean,\n theme: ResolvedTheme,\n): undefined | ViewStyle {\n if (isDisabled) {\n return undefined\n }\n\n return fabShadowsOf(theme)[hovered && !pressed ? 'elevation4' : 'elevation3']\n}\n\nfunction palette({ container, content }: FabColors): Palette {\n return {\n container: { backgroundColor: container },\n content,\n label: { color: content },\n }\n}\n\nfunction palettesFor(\n pairs: Readonly<Record<FabTone, FabColors>>,\n): Readonly<Record<FabTone, Palette>> {\n return {\n primary: palette(pairs.primary),\n secondary: palette(pairs.secondary),\n tertiary: palette(pairs.tertiary),\n }\n}\n\nexport {\n EXTENDED_FAB_ROLES,\n extendedFabSizesOf,\n FAB_ICON_SIZES,\n fabColorsOf,\n fabCornersOf,\n fabPalettesOf,\n fabShadowOf,\n fabSizesOf,\n}\nexport type { FabColors, FabSize, FabTone, FabVariant }\n"],"mappings":";;;;AAkCA,MAAMU,cAAc;AACpB,MAAMC,gBAAgB;;AAGtB,MAAMC,iBAAoD;CACxDG,IAAI;CACJC,IAAI;CACJC,IAAI;AACN;;AAGA,MAAMC,qBAA0D;CAC9DH,IAAI;CACJC,IAAI;CACJC,IAAI;AACN;;;;;AAMA,MAAME,eAAeb,cAAc,EAAEc,YACnCnB,WAAWoB,OAAO;CAChBN,IAAI,EAAEO,cAAcX,cAAc;CAClCK,IAAI,EAAEM,cAAcF,MAAML,GAAG;CAC7BE,IAAI,EAAEK,cAAcF,MAAMH,GAAG;AAC/B,CAAC,CACH;;AAGA,MAAMM,aAAajB,cAAc,EAAEkB,aACjCvB,WAAWoB,OAAO;CAChBN,IAAI;EAAEU,QAAQf;EAAagB,OAAOhB;CAAY;CAC9CM,IAAI;EAAES,QAAQD,OAAOG;EAAWD,OAAOF,OAAOG;CAAU;CACxDV,IAAI;EAAEQ,QAAQD,OAAOI;EAAWF,OAAOF,OAAOI;CAAU;AAC1D,CAAC,CACH;;;;;;;;;;AAWA,MAAMC,qBAAqBvB,cAAc,EAAEkB,QAAQM,cACjD7B,WAAWoB,OAAO;CAChBN,IAAI;EACFgB,WAAWD,QAAQd;EACnBgB,WAAWtB;EACXuB,mBAAmB;CACrB;CACAjB,IAAI;EACFe,WAAWD,QAAQI;EACnBF,WAAWR,OAAOG;EAClBM,mBAAmBH,QAAQf;CAC7B;CACAE,IAAI;EACFc,WAAWD,QAAQf;EACnBiB,WAAWR,OAAOI;EAClBK,mBAAmB;CACrB;AACF,CAAC,CACH;;;;;;AAUA,MAAMK,cAAchC,cACjB,EACCiC,cACyE;CACzEC,QAAQ;EACNC,SAAS;GAAEL,WAAWG,OAAOE;GAASJ,SAASE,OAAOG;EAAU;EAChEC,WAAW;GAAEP,WAAWG,OAAOI;GAAWN,SAASE,OAAOK;EAAY;EACtEC,UAAU;GAAET,WAAWG,OAAOM;GAAUR,SAASE,OAAOO;EAAW;CACrE;CACAC,OAAO;EACLN,SAAS;GACPL,WAAWG,OAAOS;GAClBX,SAASE,OAAOU;EAClB;EACAN,WAAW;GACTP,WAAWG,OAAOW;GAClBb,SAASE,OAAOY;EAClB;EACAN,UAAU;GACRT,WAAWG,OAAOa;GAClBf,SAASE,OAAOc;EAClB;CACF;AACF,EACF;;;;;;AAOA,MAAMC,gBAAgBhD,cAElBiD,UAKG;CACH,MAAME,QAAQnB,YAAYiB,KAAK;CAE/B,OAAO;EACLC,UAAUnD,WAAWkD,KAAK,CAAC,CAACG;EAC5BlB,QAAQmB,YAAYF,MAAMjB,MAAM;EAChCO,OAAOY,YAAYF,MAAMV,KAAK;CAChC;AACF,CACF;AAEA,MAAMa,eAAetD,cAAc,EAAEuD,cACnC5D,WAAWoB,OAAO;CAChByC,YAAY,EAAEC,WAAWF,QAAQC,WAAW;CAC5CE,YAAY,EAAED,WAAWF,QAAQG,WAAW;AAC9C,CAAC,CACH;;;;;;AAOA,SAASC,YACP,EACEC,SACAC,WAEFC,YACAb,OACuB;CACvB,IAAIa,YACF;CAGF,OAAOR,aAAaL,KAAK,CAAC,CAACW,WAAW,CAACC,UAAU,eAAe;AAClE;AAEA,SAASG,QAAQ,EAAElC,WAAWC,WAA+B;CAC3D,OAAO;EACLD,WAAW,EAAEmC,iBAAiBnC,UAAU;EACxCC;EACAmC,OAAO,EAAEC,OAAOpC,QAAQ;CAC1B;AACF;AAEA,SAASsB,YACPF,OACoC;CACpC,OAAO;EACLhB,SAAS6B,QAAQb,MAAMhB,OAAO;EAC9BE,WAAW2B,QAAQb,MAAMd,SAAS;EAClCE,UAAUyB,QAAQb,MAAMZ,QAAQ;CAClC;AACF"}