@kanso-labs/react-native-kanso-ui 0.4.0 → 0.5.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 (122) hide show
  1. package/dist/autocomplete/index.js +39 -0
  2. package/dist/autocomplete/index.js.map +1 -0
  3. package/dist/button/index.d.ts +2 -1
  4. package/dist/button/index.js +35 -2
  5. package/dist/button/index.js.map +1 -1
  6. package/dist/button/pending.js +1 -1
  7. package/dist/button/slots.d.ts +2 -1
  8. package/dist/button/slots.js.map +1 -1
  9. package/dist/chip/index.js +1 -1
  10. package/dist/components/autocomplete/index.d.ts +49 -0
  11. package/dist/components/autocomplete/index.js +87 -0
  12. package/dist/components/autocomplete/index.js.map +1 -0
  13. package/dist/components/avatar/index.d.ts +1 -1
  14. package/dist/components/button/index.d.ts +2 -2
  15. package/dist/components/button/index.js +196 -150
  16. package/dist/components/button/index.js.map +1 -1
  17. package/dist/components/card/index.d.ts +1 -1
  18. package/dist/components/card/index.js +1 -1
  19. package/dist/components/checkbox/index.d.ts +1 -1
  20. package/dist/components/checkbox/index.js +106 -193
  21. package/dist/components/checkbox/index.js.map +1 -1
  22. package/dist/components/chip/index.d.ts +1 -1
  23. package/dist/components/chip-group/index.d.ts +1 -1
  24. package/dist/components/chip-group/index.js +1 -1
  25. package/dist/components/copy-field/index.d.ts +1 -1
  26. package/dist/components/copy-field/index.js +1 -1
  27. package/dist/components/currency/index.d.ts +1 -1
  28. package/dist/components/currency/index.js +1 -1
  29. package/dist/components/dialog/index.d.ts +1 -1
  30. package/dist/components/dialog/index.js +3 -2
  31. package/dist/components/dialog/index.js.map +1 -1
  32. package/dist/components/icon-button/index.d.ts +2 -2
  33. package/dist/components/icon-button/index.js +205 -159
  34. package/dist/components/icon-button/index.js.map +1 -1
  35. package/dist/components/link/index.d.ts +1 -1
  36. package/dist/components/link/index.js +1 -1
  37. package/dist/components/list/index.d.ts +216 -0
  38. package/dist/components/list/index.js +1118 -0
  39. package/dist/components/list/index.js.map +1 -0
  40. package/dist/components/list-item/index.d.ts +63 -0
  41. package/dist/components/list-item/index.js +275 -0
  42. package/dist/components/list-item/index.js.map +1 -0
  43. package/dist/components/menu/index.d.ts +309 -0
  44. package/dist/components/menu/index.js +1283 -0
  45. package/dist/components/menu/index.js.map +1 -0
  46. package/dist/components/meter/index.d.ts +1 -1
  47. package/dist/components/meter/index.js +1 -1
  48. package/dist/components/number-field/index.d.ts +1 -1
  49. package/dist/components/number-field/index.js +2 -2
  50. package/dist/components/popover/index.d.ts +140 -0
  51. package/dist/components/popover/index.js +704 -0
  52. package/dist/components/popover/index.js.map +1 -0
  53. package/dist/components/product-icon/index.d.ts +1 -1
  54. package/dist/components/progress-indicator/index.d.ts +1 -1
  55. package/dist/components/progress-indicator/index.js +1 -1
  56. package/dist/components/radio-group/index.d.ts +1 -1
  57. package/dist/components/radio-group/index.js +1 -1
  58. package/dist/components/search-field/index.d.ts +12 -4
  59. package/dist/components/search-field/index.js +64 -58
  60. package/dist/components/search-field/index.js.map +1 -1
  61. package/dist/components/segmented-button/index.d.ts +1 -1
  62. package/dist/components/segmented-button/index.js +1 -1
  63. package/dist/components/separator/index.d.ts +1 -1
  64. package/dist/components/separator/index.js +1 -1
  65. package/dist/components/sheet/index.d.ts +1 -1
  66. package/dist/components/sheet/index.js +3 -2
  67. package/dist/components/sheet/index.js.map +1 -1
  68. package/dist/components/snackbar/index.d.ts +1 -1
  69. package/dist/components/snackbar/index.js +1 -1
  70. package/dist/components/stack/index.d.ts +1 -1
  71. package/dist/components/stack/index.js +1 -1
  72. package/dist/components/switch/index.d.ts +1 -1
  73. package/dist/components/switch/index.js +1 -1
  74. package/dist/components/text/index.d.ts +1 -1
  75. package/dist/components/text/index.js +1 -1
  76. package/dist/components/text-field/index.d.ts +1 -1
  77. package/dist/components/text-field/index.js +1 -1
  78. package/dist/control/checkbox-box.js +137 -0
  79. package/dist/control/checkbox-box.js.map +1 -0
  80. package/dist/control/index.js +1 -1
  81. package/dist/field/index.d.ts +1 -1
  82. package/dist/field/index.js +1 -1
  83. package/dist/form/index.d.ts +1 -1
  84. package/dist/glyphs/index.js +21 -2
  85. package/dist/glyphs/index.js.map +1 -1
  86. package/dist/i18n/index.js +16 -1
  87. package/dist/i18n/index.js.map +1 -1
  88. package/dist/i18n/messages.js +272 -34
  89. package/dist/i18n/messages.js.map +1 -1
  90. package/dist/index.d.ts +6 -1
  91. package/dist/index.js +7 -2
  92. package/dist/indicator/index.d.ts +1 -1
  93. package/dist/indicator/index.js +2 -2
  94. package/dist/mark/index.d.ts +1 -1
  95. package/dist/mark/index.js +1 -1
  96. package/dist/modal/index.d.ts +1 -1
  97. package/dist/modal/index.js +2 -9
  98. package/dist/modal/index.js.map +1 -1
  99. package/dist/overlay/anchored.d.ts +2 -0
  100. package/dist/overlay/anchored.js +182 -0
  101. package/dist/overlay/anchored.js.map +1 -0
  102. package/dist/overlay/host.d.ts +2 -0
  103. package/dist/overlay/host.js +1 -1
  104. package/dist/overlay/index.d.ts +4 -0
  105. package/dist/overlay/panel.js +215 -0
  106. package/dist/overlay/panel.js.map +1 -0
  107. package/dist/overlay/placement.d.ts +8 -0
  108. package/dist/overlay/placement.js +87 -0
  109. package/dist/overlay/placement.js.map +1 -0
  110. package/dist/press/index.js +1 -1
  111. package/dist/ref/index.js +15 -0
  112. package/dist/ref/index.js.map +1 -0
  113. package/dist/router/index.js +1 -1
  114. package/dist/row/index.js +158 -0
  115. package/dist/row/index.js.map +1 -0
  116. package/dist/row/styles.js +51 -0
  117. package/dist/row/styles.js.map +1 -0
  118. package/dist/theme/scope.js +1 -1
  119. package/dist/theme-scope.d.ts +1 -1
  120. package/dist/theme-scope.js +1 -1
  121. package/dist/typography/fonts.js +1 -1
  122. package/package.json +3 -3
@@ -0,0 +1,39 @@
1
+ import { createContext } from "react";
2
+ //#region src/autocomplete/index.ts
3
+ const AutocompleteContext = createContext(null);
4
+ const collators = /* @__PURE__ */ new Map();
5
+ function collatorIn(locale) {
6
+ const made = collators.get(locale);
7
+ if (made !== void 0) return made;
8
+ const collator = new Intl.Collator(locale, {
9
+ sensitivity: "base",
10
+ usage: "search"
11
+ });
12
+ collators.set(locale, collator);
13
+ return collator;
14
+ }
15
+ /**
16
+ * A match anywhere in a row's text, as React Aria's `useFilter` makes it:
17
+ * each slice of the text as long as the search is compared with it by an
18
+ * `Intl.Collator` at base sensitivity, which tells letters apart and nothing
19
+ * else, so case and accents are ignored. Both are normalised first, so an
20
+ * accent typed as a combining mark matches one written as a single letter.
21
+ * An empty search matches every row.
22
+ */
23
+ function containsIn(locale) {
24
+ const collator = collatorIn(locale);
25
+ return (textValue, inputValue) => {
26
+ if (inputValue.length === 0) return true;
27
+ const text = textValue.normalize("NFC");
28
+ const search = inputValue.normalize("NFC");
29
+ for (let start = 0; start + search.length <= text.length; start++) {
30
+ const slice = text.slice(start, start + search.length);
31
+ if (collator.compare(search, slice) === 0) return true;
32
+ }
33
+ return false;
34
+ };
35
+ }
36
+ //#endregion
37
+ export { AutocompleteContext, containsIn };
38
+
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Node","createContext","AutocompleteValue","inputValue","matches","textValue","node","setInputValue","value","AutocompleteContext","collators","Map","Intl","Collator","collatorIn","locale","made","get","undefined","collator","sensitivity","usage","set","containsIn","length","text","normalize","search","start","slice","compare"],"sources":["../../src/autocomplete/index.ts"],"sourcesContent":["import type { Node } from 'react-stately'\n\nimport { createContext } from 'react'\n\n// What Autocomplete hands the search field and the list inside it. The field\n// shows `inputValue` and reports each edit through `setInputValue`; the list\n// keeps the rows `matches` keeps, which is the autocomplete's filter with\n// what has been typed already in it. Neither part takes it as a prop, so a\n// field and a list written out inside an Autocomplete are wired to it\n// wherever the page puts them.\n\ntype AutocompleteValue = {\n /** What has been typed into the search field. */\n readonly inputValue: string\n /** Whether the list keeps a row, given its text and its entry. */\n readonly matches: (textValue: string, node: Node<unknown>) => boolean\n /** Called by the search field with each edit. */\n readonly setInputValue: (value: string) => void\n}\n\nconst AutocompleteContext = createContext<AutocompleteValue | null>(null)\n\n// One collator per locale an app searches in, made the first time a search\n// asks for it.\nconst collators = new Map<string, Intl.Collator>()\n\n// The collator a search in `locale` compares with, made once per locale.\nfunction collatorIn(locale: string) {\n const made = collators.get(locale)\n\n if (made !== undefined) {\n return made\n }\n\n const collator = new Intl.Collator(locale, {\n sensitivity: 'base',\n usage: 'search',\n })\n collators.set(locale, collator)\n return collator\n}\n\n/**\n * A match anywhere in a row's text, as React Aria's `useFilter` makes it:\n * each slice of the text as long as the search is compared with it by an\n * `Intl.Collator` at base sensitivity, which tells letters apart and nothing\n * else, so case and accents are ignored. Both are normalised first, so an\n * accent typed as a combining mark matches one written as a single letter.\n * An empty search matches every row.\n */\nfunction containsIn(locale: string) {\n const collator = collatorIn(locale)\n\n return (textValue: string, inputValue: string) => {\n if (inputValue.length === 0) {\n return true\n }\n\n const text = textValue.normalize('NFC')\n const search = inputValue.normalize('NFC')\n\n for (let start = 0; start + search.length <= text.length; start++) {\n const slice = text.slice(start, start + search.length)\n\n if (collator.compare(search, slice) === 0) {\n return true\n }\n }\n\n return false\n }\n}\n\nexport { AutocompleteContext, containsIn }\nexport type { AutocompleteValue }\n"],"mappings":";;AAoBA,MAAMS,sBAAsBR,cAAwC,IAAI;AAIxE,MAAMS,4BAAY,IAAIC,IAA2B;AAGjD,SAASG,WAAWC,QAAgB;CAClC,MAAMC,OAAON,UAAUO,IAAIF,MAAM;CAEjC,IAAIC,SAASE,KAAAA,GACX,OAAOF;CAGT,MAAMG,WAAW,IAAIP,KAAKC,SAASE,QAAQ;EACzCK,aAAa;EACbC,OAAO;CACT,CAAC;CACDX,UAAUY,IAAIP,QAAQI,QAAQ;CAC9B,OAAOA;AACT;;;;;;;;;AAUA,SAASI,WAAWR,QAAgB;CAClC,MAAMI,WAAWL,WAAWC,MAAM;CAElC,QAAQV,WAAmBF,eAAuB;EAChD,IAAIA,WAAWqB,WAAW,GACxB,OAAO;EAGT,MAAMC,OAAOpB,UAAUqB,UAAU,KAAK;EACtC,MAAMC,SAASxB,WAAWuB,UAAU,KAAK;EAEzC,KAAK,IAAIE,QAAQ,GAAGA,QAAQD,OAAOH,UAAUC,KAAKD,QAAQI,SAAS;GACjE,MAAMC,QAAQJ,KAAKI,MAAMD,OAAOA,QAAQD,OAAOH,MAAM;GAErD,IAAIL,SAASW,QAAQH,QAAQE,KAAK,MAAM,GACtC,OAAO;EAEX;EAEA,OAAO;CACT;AACF"}
@@ -1,4 +1,5 @@
1
- import { PressableProps } from "react-native";
1
+ import { Ref } from "react";
2
+ import { HostInstance, PressableProps } from "react-native";
2
3
  //#region src/button/index.d.ts
3
4
  /**
4
5
  * A plain button, a link, or a toggle, of which a call site writes exactly
@@ -1,10 +1,11 @@
1
1
  import { useTheme } from "../theme/scope.js";
2
2
  import { FormContext } from "../form/index.js";
3
+ import { refsOf } from "../ref/index.js";
3
4
  import { useOpenLink } from "../router/index.js";
4
5
  import { ButtonSlotContext } from "./slots.js";
5
6
  import { c } from "react/compiler-runtime";
6
- import { Platform, Pressable, StyleSheet } from "react-native";
7
7
  import { use, useState } from "react";
8
+ import { Platform, Pressable, StyleSheet } from "react-native";
8
9
  import Animated, { Easing, useAnimatedStyle, useReducedMotion, useSharedValue, withTiming } from "react-native-reanimated";
9
10
  //#region src/button/index.ts
10
11
  const HEIGHTS = {
@@ -42,6 +43,13 @@ const buttonStyles = StyleSheet.create({ clip: {
42
43
  right: 0,
43
44
  top: 0
44
45
  } });
46
+ function andThen(own, slot) {
47
+ if (slot === void 0) return own ?? void 0;
48
+ return (event) => {
49
+ own?.(event);
50
+ slot();
51
+ };
52
+ }
45
53
  function measureThen(height, onLayout) {
46
54
  return (event) => {
47
55
  height.set(event.nativeEvent.layout.height);
@@ -175,7 +183,32 @@ function useCorner(radius, onLayout) {
175
183
  } else t4 = $[10];
176
184
  return t4;
177
185
  }
186
+ /**
187
+ * What a button filling the default slot of an overlay drawn beside it takes
188
+ * on, as src/button's slots.ts sets out: its node is kept for the overlay to
189
+ * be placed against, alongside the call site's own `ref`, `aria-expanded`
190
+ * says whether the overlay is open, and the overlay's hover and long press
191
+ * handlers run after the call site's. A button filling no such slot, or a
192
+ * link, keeps its own props untouched.
193
+ */
194
+ function useSlotTrigger({ delayLongPress, href, onHoverIn, onHoverOut, onLongPress, ref, slot }) {
195
+ const slots = use(ButtonSlotContext);
196
+ const trigger = href === void 0 && slot === void 0 ? slots?.trigger : void 0;
197
+ return {
198
+ ...trigger === void 0 ? {
199
+ delayLongPress,
200
+ ref
201
+ } : {
202
+ "aria-expanded": trigger.expanded,
203
+ delayLongPress: trigger.delayLongPress ?? delayLongPress,
204
+ ref: refsOf(trigger.ref, ref)
205
+ },
206
+ onHoverIn: andThen(onHoverIn, trigger?.onHoverIn),
207
+ onHoverOut: andThen(onHoverOut, trigger?.onHoverOut),
208
+ onLongPress: andThen(onLongPress, trigger?.onLongPress)
209
+ };
210
+ }
178
211
  //#endregion
179
- export { AnimatedPressable, HEIGHTS, OUTLINE_WIDTHS, PRESSED_CORNERS, buttonStyles, toggleState, useButtonAction, useCorner };
212
+ export { AnimatedPressable, HEIGHTS, OUTLINE_WIDTHS, PRESSED_CORNERS, buttonStyles, toggleState, useButtonAction, useCorner, useSlotTrigger };
180
213
 
181
214
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["GestureResponderEvent","LayoutChangeEvent","PressableProps","SharedValue","use","useState","Platform","Pressable","StyleSheet","Animated","Easing","useAnimatedStyle","useReducedMotion","useSharedValue","withTiming","ResolvedTheme","FormContext","useOpenLink","useTheme","ButtonSlotContext","ButtonLinkForm","defaultSelected","href","isPending","isSelected","onChange","pendingLabel","slot","type","ButtonPending","ButtonPressForm","ButtonToggleForm","ControlSize","ToggleState","HEIGHTS","lg","md","xl","xs","xxl","const","Record","OUTLINE_WIDTHS","Readonly","PRESSED_CORNERS","AnimatedPressable","createAnimatedComponent","toggleState","select","selected","default","web","buttonStyles","create","clip","bottom","left","overflow","pointerEvents","position","right","top","measureThen","height","onLayout","event","set","nativeEvent","layout","pressThen","onPress","then","useButtonAction","t0","$","_c","isToggle","openLink","form","slots","ownSelected","setOwnSelected","filled","undefined","t1","follow","requestSubmit","t2","t3","useCorner","radius","motion","reduceMotion","durationShort2","easingEmphasized","bezier","duration","easing","timing","corner","measured","get","target","Math","min","borderRadius","t4","_c"],"sources":["../../src/button/index.ts"],"sourcesContent":["import type {\n GestureResponderEvent,\n LayoutChangeEvent,\n PressableProps,\n} from 'react-native'\nimport type { SharedValue } from 'react-native-reanimated'\n\nimport { use, useState } from 'react'\nimport { Platform, Pressable, StyleSheet } from 'react-native'\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\n\nimport type { ResolvedTheme } from '../theme/scope'\n\nimport { FormContext } from '../form'\nimport { useOpenLink } from '../router'\nimport { useTheme } from '../theme/scope'\nimport { ButtonSlotContext } from './slots'\n\n// What every button does past its own styles, shared by Button and\n// IconButton as web's src/button is: the three forms a button takes, the\n// toggle's state and how it is announced, what a press does after the call\n// site's own `onPress`, a submit button's included, and what the slot it\n// fills in an overlay adds to it, the corner that eases between shapes, and\n// the metrics\n// the two components' pages give alike, since the two share their five\n// heights so that they line up in a row. What a pending button draws and\n// says is ./pending.tsx.\n\n/**\n * A plain button, a link, or a toggle, of which a call site writes exactly\n * one. Each form names the props of the other two as `never`, so a toggle\n * given `href` is a compile error rather than a prop that silently does\n * nothing.\n */\ntype ButtonLinkForm = {\n readonly defaultSelected?: never\n /**\n * Where the button leads. Given one, a press opens it through the\n * `RouterProvider` around the button, or through the platform for a URL\n * with a scheme of its own, and the button is announced as a link.\n */\n readonly href: string\n readonly isPending?: never\n readonly isSelected?: never\n readonly onChange?: never\n readonly pendingLabel?: never\n readonly slot?: never\n readonly type?: never\n}\n\n/**\n * Whether the button's action is under way, which the plain button and the\n * toggle both take and the link does not.\n */\ntype ButtonPending = {\n /**\n * Shows that the button's action is under way: a ring takes the place of\n * the label and the icon, which keep their space, and the button keeps its\n * focus and takes no press until it clears. A toggle may be pending, for a\n * state saved somewhere slow.\n * @default false\n */\n readonly isPending?: boolean\n /**\n * The name of the ring shown while the button is pending, for a screen\n * reader. The content it replaces is hidden while it shows. Left out, it is\n * the word for it in the device's locale, \"Loading\" in English.\n */\n readonly pendingLabel?: string\n}\n\ntype ButtonPressForm = ButtonPending & {\n readonly defaultSelected?: never\n readonly href?: never\n readonly isSelected?: never\n readonly onChange?: never\n /**\n * `close` closes the overlay the button is in, as web's React Aria slot of\n * that name does: a `Dialog` given one inside its content closes when it is\n * pressed, after the button's own `onPress`.\n */\n readonly slot?: 'close'\n /**\n * What a press does past `onPress`. `submit` submits the `Form` the button\n * is in, as a submit button does on web; `button` does nothing more.\n * @default 'button'\n */\n readonly type?: 'button' | 'submit'\n}\n\ntype ButtonToggleForm = ButtonPending & {\n /**\n * Whether a toggle starts selected, when it keeps its own state. Passing\n * this, `isSelected` or `onChange` is what makes the button a toggle.\n */\n readonly defaultSelected?: boolean\n readonly href?: never\n /**\n * Whether a toggle is selected, when the call site holds the state. Pass\n * it with `onChange`; passing this, `defaultSelected` or `onChange` is what\n * makes the button a toggle.\n */\n readonly isSelected?: boolean\n /**\n * Called with the new state when a toggle is pressed, after `onPress`.\n * Passing this, `isSelected` or `defaultSelected` is what makes the button\n * a toggle.\n */\n readonly onChange?: (isSelected: boolean) => void\n readonly slot?: never\n readonly type?: never\n}\n\n/** The five control heights both pages give, by the names both props take. */\ntype ControlSize = 'lg' | 'md' | 'xl' | 'xs' | 'xxl'\n\n/** How a toggle reports its state to a screen reader. */\ntype ToggleState = {\n readonly 'aria-pressed'?: boolean\n readonly 'aria-selected'?: boolean\n}\n\n// The control height each size reads: the page's XS, S, M, L and XL, which\n// the theme's sizing scale names one step apart from this prop.\nconst HEIGHTS = {\n lg: 'controlLg',\n md: 'controlSm',\n xl: 'controlXl',\n xs: 'controlXs',\n xxl: 'controlXxl',\n} as const satisfies Record<ControlSize, keyof ResolvedTheme['sizing']>\n\n// The outlined rule thickens with the size, as the buttons page's size tokens\n// have it: 1dp up to M, 2dp at L, 3dp at XL. The icon buttons page keeps its\n// widths in a token set its widget will not open, so the icon button takes\n// these, which a 96dp icon button beside a 96dp outlined button needs anyway.\nconst OUTLINE_WIDTHS: Readonly<Record<ControlSize, number>> = {\n lg: 1,\n md: 1,\n xl: 2,\n xs: 1,\n xxl: 3,\n}\n\n// The corner each size presses to, which both pages give alike.\nconst PRESSED_CORNERS = {\n lg: 'md',\n md: 'sm',\n xl: 'lg',\n xs: 'sm',\n xxl: 'lg',\n} as const satisfies Record<ControlSize, keyof ResolvedTheme['radii']>\n\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable)\n\n// Web's toggle reports `aria-pressed`, which React Native Web writes onto the\n// element. React Native has no pressed state to report, and reports the\n// selected one instead, which VoiceOver and TalkBack both read out.\nconst toggleState = Platform.select<(selected: boolean) => ToggleState>({\n default: (selected) => ({ 'aria-selected': selected }),\n web: (selected) => ({ 'aria-pressed': selected }),\n})\n\nconst buttonStyles = StyleSheet.create({\n // Clips the state layer and the ripple to the corner as it morphs, and\n // takes no touches.\n clip: {\n bottom: 0,\n left: 0,\n overflow: 'hidden',\n pointerEvents: 'none',\n position: 'absolute',\n right: 0,\n top: 0,\n },\n})\n\n// Records the button's height for the corner, then calls the call site's own\n// `onLayout`. Built by a call rather than declared in a component, which is\n// what react-perf's jsx-no-new-function-as-prop is after; the React Compiler\n// memoises the result on its inputs.\nfunction measureThen(\n height: SharedValue<number>,\n onLayout: PressableProps['onLayout'],\n) {\n return (event: LayoutChangeEvent) => {\n height.set(event.nativeEvent.layout.height)\n onLayout?.(event)\n }\n}\n\n// The call site's own `onPress`, then what the button does with the press.\n// Built by a call for the reason `measureThen` is.\nfunction pressThen(\n onPress: PressableProps['onPress'],\n then: (event: GestureResponderEvent) => void,\n) {\n return (event: GestureResponderEvent) => {\n onPress?.(event)\n then(event)\n }\n}\n\n/**\n * What a press does, and whether a toggle is selected. A press calls the call\n * site's own `onPress` first, then opens the link, changes the toggle's state\n * or submits the form the button is in, which is the order web reports them\n * in. A toggle keeps its own state from `defaultSelected` unless the call\n * site holds it in `isSelected`. A submit button outside a form submits\n * nothing, as on web.\n *\n * Given a `slot`, a button that is not a link then does what that slot of\n * the overlay around it does, as src/button's slots.ts sets out: opens it\n * from the trigger, or closes it from its content.\n */\nfunction useButtonAction({\n defaultSelected,\n href,\n isSelected,\n isToggle,\n onChange,\n onPress,\n slot,\n type,\n}: {\n readonly defaultSelected: boolean | undefined\n readonly href: string | undefined\n readonly isSelected: boolean | undefined\n readonly isToggle: boolean\n readonly onChange: ((isSelected: boolean) => void) | undefined\n readonly onPress: PressableProps['onPress']\n readonly slot?: 'close' | 'default'\n readonly type: 'button' | 'submit' | undefined\n}) {\n const openLink = useOpenLink()\n const form = use(FormContext)\n const slots = use(ButtonSlotContext)\n const [ownSelected, setOwnSelected] = useState(defaultSelected ?? false)\n const selected = isToggle && (isSelected ?? ownSelected)\n const filled = slot === undefined ? undefined : slots?.[slot]\n\n function follow(event: GestureResponderEvent) {\n if (href !== undefined) {\n openLink(href)\n return\n }\n if (isToggle) {\n setOwnSelected(!selected)\n onChange?.(!selected)\n } else if (type === 'submit') {\n form?.requestSubmit()\n }\n filled?.(event)\n }\n\n return { onPress: pressThen(onPress, follow), selected }\n}\n\n/**\n * The corner a button eases to, over the motion tokens' short duration on the\n * emphasised curve, and at once for a reader who asks the device for reduced\n * motion. The pill is the radius scale's `pill`, far larger than any button,\n * so the ease runs from half the button's measured height rather than from\n * that: otherwise the corner would hold the pill for most of the ease and\n * jump at its end. The `onLayout` it hands back measures the button, then\n * calls the call site's own.\n */\nfunction useCorner(radius: number, onLayout: PressableProps['onLayout']) {\n const { motion } = useTheme()\n const reduceMotion = useReducedMotion()\n const height = useSharedValue(0)\n const timing = {\n duration: motion.durationShort2,\n easing: Easing.bezier(...motion.easingEmphasized),\n }\n const corner = useAnimatedStyle(() => {\n 'worklet'\n const measured = height.get()\n const target = measured > 0 ? Math.min(radius, measured / 2) : radius\n\n return {\n borderRadius: reduceMotion ? target : withTiming(target, timing),\n }\n })\n\n return { corner, onLayout: measureThen(height, onLayout) }\n}\n\nexport {\n AnimatedPressable,\n buttonStyles,\n HEIGHTS,\n OUTLINE_WIDTHS,\n PRESSED_CORNERS,\n toggleState,\n useButtonAction,\n useCorner,\n}\nexport type { ButtonLinkForm, ButtonPressForm, ButtonToggleForm, ControlSize }\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Ref","GestureResponderEvent","HostInstance","LayoutChangeEvent","PressableProps","SharedValue","use","useState","Platform","Pressable","StyleSheet","Animated","Easing","useAnimatedStyle","useReducedMotion","useSharedValue","withTiming","ResolvedTheme","FormContext","refsOf","useOpenLink","useTheme","ButtonSlotContext","ButtonLinkForm","defaultSelected","href","isPending","isSelected","onChange","pendingLabel","slot","type","ButtonPending","ButtonPressForm","ButtonToggleForm","ControlSize","SlotTriggerProps","delayLongPress","onHoverIn","onHoverOut","onLongPress","ref","ToggleState","HEIGHTS","lg","md","xl","xs","xxl","const","Record","OUTLINE_WIDTHS","Readonly","PRESSED_CORNERS","AnimatedPressable","createAnimatedComponent","toggleState","select","selected","default","web","buttonStyles","create","clip","bottom","left","overflow","pointerEvents","position","right","top","andThen","own","event","E","undefined","measureThen","height","onLayout","set","nativeEvent","layout","pressThen","onPress","then","useButtonAction","t0","$","_c","isToggle","openLink","form","slots","ownSelected","setOwnSelected","filled","t1","follow","requestSubmit","t2","t3","useCorner","radius","motion","reduceMotion","durationShort2","easingEmphasized","bezier","duration","easing","timing","corner","measured","get","target","Math","min","borderRadius","t4","useSlotTrigger","trigger","expanded","_c"],"sources":["../../src/button/index.ts"],"sourcesContent":["import type { Ref } from 'react'\nimport type {\n GestureResponderEvent,\n HostInstance,\n LayoutChangeEvent,\n PressableProps,\n} from 'react-native'\nimport type { SharedValue } from 'react-native-reanimated'\n\nimport { use, useState } from 'react'\nimport { Platform, Pressable, StyleSheet } from 'react-native'\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useReducedMotion,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\n\nimport type { ResolvedTheme } from '../theme/scope'\n\nimport { FormContext } from '../form'\nimport { refsOf } from '../ref'\nimport { useOpenLink } from '../router'\nimport { useTheme } from '../theme/scope'\nimport { ButtonSlotContext } from './slots'\n\n// What every button does past its own styles, shared by Button and\n// IconButton as web's src/button is: the three forms a button takes, the\n// toggle's state and how it is announced, what a press does after the call\n// site's own `onPress`, a submit button's included, and what the slot it\n// fills in an overlay adds to it, the corner that eases between shapes, and\n// the metrics\n// the two components' pages give alike, since the two share their five\n// heights so that they line up in a row. What a pending button draws and\n// says is ./pending.tsx.\n\n/**\n * A plain button, a link, or a toggle, of which a call site writes exactly\n * one. Each form names the props of the other two as `never`, so a toggle\n * given `href` is a compile error rather than a prop that silently does\n * nothing.\n */\ntype ButtonLinkForm = {\n readonly defaultSelected?: never\n /**\n * Where the button leads. Given one, a press opens it through the\n * `RouterProvider` around the button, or through the platform for a URL\n * with a scheme of its own, and the button is announced as a link.\n */\n readonly href: string\n readonly isPending?: never\n readonly isSelected?: never\n readonly onChange?: never\n readonly pendingLabel?: never\n readonly slot?: never\n readonly type?: never\n}\n\n/**\n * Whether the button's action is under way, which the plain button and the\n * toggle both take and the link does not.\n */\ntype ButtonPending = {\n /**\n * Shows that the button's action is under way: a ring takes the place of\n * the label and the icon, which keep their space, and the button keeps its\n * focus and takes no press until it clears. A toggle may be pending, for a\n * state saved somewhere slow.\n * @default false\n */\n readonly isPending?: boolean\n /**\n * The name of the ring shown while the button is pending, for a screen\n * reader. The content it replaces is hidden while it shows. Left out, it is\n * the word for it in the device's locale, \"Loading\" in English.\n */\n readonly pendingLabel?: string\n}\n\ntype ButtonPressForm = ButtonPending & {\n readonly defaultSelected?: never\n readonly href?: never\n readonly isSelected?: never\n readonly onChange?: never\n /**\n * `close` closes the overlay the button is in, as web's React Aria slot of\n * that name does: a `Dialog` given one inside its content closes when it is\n * pressed, after the button's own `onPress`.\n */\n readonly slot?: 'close'\n /**\n * What a press does past `onPress`. `submit` submits the `Form` the button\n * is in, as a submit button does on web; `button` does nothing more.\n * @default 'button'\n */\n readonly type?: 'button' | 'submit'\n}\n\ntype ButtonToggleForm = ButtonPending & {\n /**\n * Whether a toggle starts selected, when it keeps its own state. Passing\n * this, `isSelected` or `onChange` is what makes the button a toggle.\n */\n readonly defaultSelected?: boolean\n readonly href?: never\n /**\n * Whether a toggle is selected, when the call site holds the state. Pass\n * it with `onChange`; passing this, `defaultSelected` or `onChange` is what\n * makes the button a toggle.\n */\n readonly isSelected?: boolean\n /**\n * Called with the new state when a toggle is pressed, after `onPress`.\n * Passing this, `isSelected` or `defaultSelected` is what makes the button\n * a toggle.\n */\n readonly onChange?: (isSelected: boolean) => void\n readonly slot?: never\n readonly type?: never\n}\n\n/** The five control heights both pages give, by the names both props take. */\ntype ControlSize = 'lg' | 'md' | 'xl' | 'xs' | 'xxl'\n\n/** How a toggle reports its state to a screen reader. */\n// What `useSlotTrigger` hands the Pressable, spelled out because the\n// composed ref's inferred type names a private React Native module, which a\n// declaration file cannot reach.\ntype SlotTriggerProps = {\n readonly 'aria-expanded'?: boolean\n readonly delayLongPress: PressableProps['delayLongPress']\n readonly onHoverIn: PressableProps['onHoverIn']\n readonly onHoverOut: PressableProps['onHoverOut']\n readonly onLongPress: PressableProps['onLongPress']\n readonly ref: Ref<HostInstance> | undefined\n}\n\ntype ToggleState = {\n readonly 'aria-pressed'?: boolean\n readonly 'aria-selected'?: boolean\n}\n\n// The control height each size reads: the page's XS, S, M, L and XL, which\n// the theme's sizing scale names one step apart from this prop.\nconst HEIGHTS = {\n lg: 'controlLg',\n md: 'controlSm',\n xl: 'controlXl',\n xs: 'controlXs',\n xxl: 'controlXxl',\n} as const satisfies Record<ControlSize, keyof ResolvedTheme['sizing']>\n\n// The outlined rule thickens with the size, as the buttons page's size tokens\n// have it: 1dp up to M, 2dp at L, 3dp at XL. The icon buttons page keeps its\n// widths in a token set its widget will not open, so the icon button takes\n// these, which a 96dp icon button beside a 96dp outlined button needs anyway.\nconst OUTLINE_WIDTHS: Readonly<Record<ControlSize, number>> = {\n lg: 1,\n md: 1,\n xl: 2,\n xs: 1,\n xxl: 3,\n}\n\n// The corner each size presses to, which both pages give alike.\nconst PRESSED_CORNERS = {\n lg: 'md',\n md: 'sm',\n xl: 'lg',\n xs: 'sm',\n xxl: 'lg',\n} as const satisfies Record<ControlSize, keyof ResolvedTheme['radii']>\n\nconst AnimatedPressable = Animated.createAnimatedComponent(Pressable)\n\n// Web's toggle reports `aria-pressed`, which React Native Web writes onto the\n// element. React Native has no pressed state to report, and reports the\n// selected one instead, which VoiceOver and TalkBack both read out.\nconst toggleState = Platform.select<(selected: boolean) => ToggleState>({\n default: (selected) => ({ 'aria-selected': selected }),\n web: (selected) => ({ 'aria-pressed': selected }),\n})\n\nconst buttonStyles = StyleSheet.create({\n // Clips the state layer and the ripple to the corner as it morphs, and\n // takes no touches.\n clip: {\n bottom: 0,\n left: 0,\n overflow: 'hidden',\n pointerEvents: 'none',\n position: 'absolute',\n right: 0,\n top: 0,\n },\n})\n\n// A handler that runs the call site's own and then the slot's, which takes no\n// event, or the call site's alone where the slot adds nothing.\nfunction andThen<E>(\n own: ((event: E) => void) | null | undefined,\n slot: (() => void) | undefined,\n) {\n if (slot === undefined) {\n return own ?? undefined\n }\n\n return (event: E) => {\n own?.(event)\n slot()\n }\n}\n\n// Records the button's height for the corner, then calls the call site's own\n// `onLayout`. Built by a call rather than declared in a component, which is\n// what react-perf's jsx-no-new-function-as-prop is after; the React Compiler\n// memoises the result on its inputs.\nfunction measureThen(\n height: SharedValue<number>,\n onLayout: PressableProps['onLayout'],\n) {\n return (event: LayoutChangeEvent) => {\n height.set(event.nativeEvent.layout.height)\n onLayout?.(event)\n }\n}\n\n// The call site's own `onPress`, then what the button does with the press.\n// Built by a call for the reason `measureThen` is.\nfunction pressThen(\n onPress: PressableProps['onPress'],\n then: (event: GestureResponderEvent) => void,\n) {\n return (event: GestureResponderEvent) => {\n onPress?.(event)\n then(event)\n }\n}\n\n/**\n * What a press does, and whether a toggle is selected. A press calls the call\n * site's own `onPress` first, then opens the link, changes the toggle's state\n * or submits the form the button is in, which is the order web reports them\n * in. A toggle keeps its own state from `defaultSelected` unless the call\n * site holds it in `isSelected`. A submit button outside a form submits\n * nothing, as on web.\n *\n * Given a `slot`, a button that is not a link then does what that slot of\n * the overlay around it does, as src/button's slots.ts sets out: opens it\n * from the trigger, or closes it from its content.\n */\nfunction useButtonAction({\n defaultSelected,\n href,\n isSelected,\n isToggle,\n onChange,\n onPress,\n slot,\n type,\n}: {\n readonly defaultSelected: boolean | undefined\n readonly href: string | undefined\n readonly isSelected: boolean | undefined\n readonly isToggle: boolean\n readonly onChange: ((isSelected: boolean) => void) | undefined\n readonly onPress: PressableProps['onPress']\n readonly slot?: 'close' | 'default'\n readonly type: 'button' | 'submit' | undefined\n}) {\n const openLink = useOpenLink()\n const form = use(FormContext)\n const slots = use(ButtonSlotContext)\n const [ownSelected, setOwnSelected] = useState(defaultSelected ?? false)\n const selected = isToggle && (isSelected ?? ownSelected)\n const filled = slot === undefined ? undefined : slots?.[slot]\n\n function follow(event: GestureResponderEvent) {\n if (href !== undefined) {\n openLink(href)\n return\n }\n if (isToggle) {\n setOwnSelected(!selected)\n onChange?.(!selected)\n } else if (type === 'submit') {\n form?.requestSubmit()\n }\n filled?.(event)\n }\n\n return { onPress: pressThen(onPress, follow), selected }\n}\n\n/**\n * The corner a button eases to, over the motion tokens' short duration on the\n * emphasised curve, and at once for a reader who asks the device for reduced\n * motion. The pill is the radius scale's `pill`, far larger than any button,\n * so the ease runs from half the button's measured height rather than from\n * that: otherwise the corner would hold the pill for most of the ease and\n * jump at its end. The `onLayout` it hands back measures the button, then\n * calls the call site's own.\n */\nfunction useCorner(radius: number, onLayout: PressableProps['onLayout']) {\n const { motion } = useTheme()\n const reduceMotion = useReducedMotion()\n const height = useSharedValue(0)\n const timing = {\n duration: motion.durationShort2,\n easing: Easing.bezier(...motion.easingEmphasized),\n }\n const corner = useAnimatedStyle(() => {\n 'worklet'\n const measured = height.get()\n const target = measured > 0 ? Math.min(radius, measured / 2) : radius\n\n return {\n borderRadius: reduceMotion ? target : withTiming(target, timing),\n }\n })\n\n return { corner, onLayout: measureThen(height, onLayout) }\n}\n\n/**\n * What a button filling the default slot of an overlay drawn beside it takes\n * on, as src/button's slots.ts sets out: its node is kept for the overlay to\n * be placed against, alongside the call site's own `ref`, `aria-expanded`\n * says whether the overlay is open, and the overlay's hover and long press\n * handlers run after the call site's. A button filling no such slot, or a\n * link, keeps its own props untouched.\n */\nfunction useSlotTrigger({\n delayLongPress,\n href,\n onHoverIn,\n onHoverOut,\n onLongPress,\n ref,\n slot,\n}: {\n readonly delayLongPress: PressableProps['delayLongPress']\n readonly href: string | undefined\n readonly onHoverIn: PressableProps['onHoverIn']\n readonly onHoverOut: PressableProps['onHoverOut']\n readonly onLongPress: PressableProps['onLongPress']\n readonly ref: Ref<HostInstance> | undefined\n readonly slot: 'close' | undefined\n}): SlotTriggerProps {\n const slots = use(ButtonSlotContext)\n const trigger =\n href === undefined && slot === undefined ? slots?.trigger : undefined\n\n return {\n ...(trigger === undefined\n ? { delayLongPress, ref }\n : {\n 'aria-expanded': trigger.expanded,\n delayLongPress: trigger.delayLongPress ?? delayLongPress,\n ref: refsOf(trigger.ref, ref),\n }),\n onHoverIn: andThen(onHoverIn, trigger?.onHoverIn),\n onHoverOut: andThen(onHoverOut, trigger?.onHoverOut),\n onLongPress: andThen(onLongPress, trigger?.onLongPress),\n }\n}\n\nexport {\n AnimatedPressable,\n buttonStyles,\n HEIGHTS,\n OUTLINE_WIDTHS,\n PRESSED_CORNERS,\n toggleState,\n useButtonAction,\n useCorner,\n useSlotTrigger,\n}\nexport type { ButtonLinkForm, ButtonPressForm, ButtonToggleForm, ControlSize }\n"],"mappings":"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"}
@@ -2,9 +2,9 @@ import { IconStyleContext } from "../glyphs/icon-style.js";
2
2
  import { ProgressIndicator } from "../components/progress-indicator/index.js";
3
3
  import { messagesFor } from "../i18n/index.js";
4
4
  import { c } from "react/compiler-runtime";
5
- import { AccessibilityInfo, Platform, StyleSheet, View } from "react-native";
6
5
  import { useEffect, useRef } from "react";
7
6
  import { jsx } from "react/jsx-runtime";
7
+ import { AccessibilityInfo, Platform, StyleSheet, View } from "react-native";
8
8
  //#region src/button/pending.tsx
9
9
  const pendingStyles = StyleSheet.create({
10
10
  hidden: { opacity: 0 },
@@ -1 +1,2 @@
1
- import "react-native";
1
+ import { RefObject } from "react";
2
+ import { HostInstance } from "react-native";
@@ -1 +1 @@
1
- {"version":3,"file":"slots.js","names":["GestureResponderEvent","createContext","ButtonSlots","close","event","default","ButtonSlotContext"],"sources":["../../src/button/slots.ts"],"sourcesContent":["import type { GestureResponderEvent } from 'react-native'\n\nimport { createContext } from 'react'\n\n/**\n * What a button does past its own press when it sits in an overlay's trigger\n * or content, as web's React Aria hands the same through a button's `slot`:\n * the default slot opens the overlay, which a button inside `Dialog` or\n * `Sheet` and outside its content takes, and `close` closes it, which one\n * given `slot=\"close\"` inside the content takes. The overlay provides the\n * slots it fills, and resets the default one inside its content, so a button\n * there opens nothing.\n */\ntype ButtonSlots = {\n readonly close?: (event: GestureResponderEvent) => void\n readonly default?: (event: GestureResponderEvent) => void\n}\n\nconst ButtonSlotContext = createContext<ButtonSlots | null>(null)\n\nexport { ButtonSlotContext }\nexport type { ButtonSlots }\n"],"mappings":";;AAkBA,MAAMM,oBAAoBL,cAAkC,IAAI"}
1
+ {"version":3,"file":"slots.js","names":["RefObject","GestureResponderEvent","HostInstance","createContext","ButtonSlots","close","event","default","trigger","ButtonSlotTrigger","delayLongPress","expanded","onHoverIn","onHoverOut","onLongPress","ref","ButtonSlotContext"],"sources":["../../src/button/slots.ts"],"sourcesContent":["import type { RefObject } from 'react'\nimport type { GestureResponderEvent, HostInstance } from 'react-native'\n\nimport { createContext } from 'react'\n\n/**\n * What a button does past its own press when it sits in an overlay's trigger\n * or content, as web's React Aria hands the same through a button's `slot`:\n * the default slot opens the overlay, which a button inside `Dialog`,\n * `Popover` or `Sheet` and outside its content takes, and `close` closes it,\n * which one given `slot=\"close\"` inside the content takes. The overlay\n * provides the slots it fills, and resets the default one inside its content,\n * so a button there opens nothing.\n */\ntype ButtonSlots = {\n readonly close?: (event: GestureResponderEvent) => void\n readonly default?: (event: GestureResponderEvent) => void\n /**\n * What the button filling the default slot takes on beside its press, for\n * an overlay drawn beside it.\n */\n readonly trigger?: ButtonSlotTrigger\n}\n\n/**\n * What a button filling the default slot takes on for an overlay drawn beside\n * it: its node, which the overlay is placed against, whether the overlay is\n * open, which a screen reader announces, and the hover and long press a\n * hovered popover opens on. The handlers run after the button's own.\n */\ntype ButtonSlotTrigger = {\n /** How long a press is held before it is a long press, in milliseconds. */\n readonly delayLongPress?: number\n /** Whether the overlay the button opens is open. */\n readonly expanded: boolean\n readonly onHoverIn?: () => void\n readonly onHoverOut?: () => void\n readonly onLongPress?: () => void\n /** Where the button's node is kept, for the overlay to be placed against. */\n readonly ref: RefObject<HostInstance | null>\n}\n\nconst ButtonSlotContext = createContext<ButtonSlots | null>(null)\n\nexport { ButtonSlotContext }\nexport type { ButtonSlots, ButtonSlotTrigger }\n"],"mappings":";;AA0CA,MAAMgB,oBAAoBb,cAAkC,IAAI"}
@@ -6,8 +6,8 @@ import { useTypeRole } from "../typography/roles.js";
6
6
  import { withOpacity } from "../theme/color.js";
7
7
  import { styles, stylesOf } from "./styles.js";
8
8
  import { c } from "react/compiler-runtime";
9
- import { View } from "react-native";
10
9
  import { jsx } from "react/jsx-runtime";
10
+ import { View } from "react-native";
11
11
  import Animated, { Easing, useAnimatedStyle, useReducedMotion, withTiming } from "react-native-reanimated";
12
12
  //#region src/chip/index.tsx
13
13
  const CHECK = /* @__PURE__ */ jsx(CheckGlyph, {});
@@ -0,0 +1,49 @@
1
+ import { ReactNode } from "react";
2
+ import { Node } from "react-stately";
3
+ //#region src/components/autocomplete/index.d.ts
4
+ /**
5
+ * Whether a search keeps a row: handed the row's text, what has been typed
6
+ * and the row's entry in the collection, as React Aria's is.
7
+ */
8
+ type AutocompleteFilter<T extends object = object> = (textValue: string, inputValue: string, node: Node<T>) => boolean;
9
+ type AutocompleteProps<T extends object = object> = {
10
+ /**
11
+ * The search field and the list it filters, in whatever the page puts
12
+ * around them.
13
+ */
14
+ readonly children?: ReactNode;
15
+ /** What has been typed at first, when the autocomplete keeps its own. */
16
+ readonly defaultInputValue?: string;
17
+ /**
18
+ * Which rows a search keeps. Left out, a row is kept when its text
19
+ * contains what has been typed anywhere in it, ignoring case and accents.
20
+ */
21
+ readonly filter?: AutocompleteFilter<T>;
22
+ /** What has been typed, when the call site holds it. */
23
+ readonly inputValue?: string;
24
+ /** Called with what has been typed whenever an edit changes it. */
25
+ readonly onInputChange?: (value: string) => void;
26
+ };
27
+ /**
28
+ * A search field that filters the list under it. What has been typed is the
29
+ * autocomplete's: pass `inputValue` with `onInputChange` to control it, or
30
+ * `defaultInputValue` to let it keep its own. The field inside shows it, and
31
+ * its own `value` and `defaultValue` are not read there.
32
+ *
33
+ * ```tsx
34
+ * <Autocomplete>
35
+ * <SearchField label="Search" placeholder="Search" />
36
+ * <List aria-label="Results" selectionMode="single">
37
+ * <List.Item id="first">First item</List.Item>
38
+ * </List>
39
+ * </Autocomplete>
40
+ * ```
41
+ *
42
+ * It renders nothing of its own, so the field and the list sit wherever the
43
+ * page puts them, and the list says how many rows each search leaves to a
44
+ * screen reader.
45
+ */
46
+ declare function Autocomplete<T extends object = object>({ children, defaultInputValue, filter, inputValue, onInputChange }: AutocompleteProps<T>): import("react").JSX.Element;
47
+ //#endregion
48
+ export { Autocomplete, type AutocompleteFilter, type AutocompleteProps };
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,87 @@
1
+ import { AutocompleteContext, containsIn } from "../../autocomplete/index.js";
2
+ import { localeOf } from "../../number/locale.js";
3
+ import { c } from "react/compiler-runtime";
4
+ import { useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/components/autocomplete/index.tsx
7
+ /**
8
+ * A search field that filters the list under it. What has been typed is the
9
+ * autocomplete's: pass `inputValue` with `onInputChange` to control it, or
10
+ * `defaultInputValue` to let it keep its own. The field inside shows it, and
11
+ * its own `value` and `defaultValue` are not read there.
12
+ *
13
+ * ```tsx
14
+ * <Autocomplete>
15
+ * <SearchField label="Search" placeholder="Search" />
16
+ * <List aria-label="Results" selectionMode="single">
17
+ * <List.Item id="first">First item</List.Item>
18
+ * </List>
19
+ * </Autocomplete>
20
+ * ```
21
+ *
22
+ * It renders nothing of its own, so the field and the list sit wherever the
23
+ * page puts them, and the list says how many rows each search leaves to a
24
+ * screen reader.
25
+ */
26
+ function Autocomplete(t0) {
27
+ const $ = c(14);
28
+ const { children, defaultInputValue: t1, filter, inputValue, onInputChange } = t0;
29
+ const [own, setOwn] = useState(t1 === void 0 ? "" : t1);
30
+ const current = inputValue ?? own;
31
+ let t2;
32
+ if ($[0] !== filter) {
33
+ t2 = filter ?? containsIn(localeOf(void 0));
34
+ $[0] = filter;
35
+ $[1] = t2;
36
+ } else t2 = $[1];
37
+ let t3;
38
+ if ($[2] !== current || $[3] !== t2) {
39
+ t3 = matchesOf(t2, current);
40
+ $[2] = current;
41
+ $[3] = t2;
42
+ $[4] = t3;
43
+ } else t3 = $[4];
44
+ let t4;
45
+ if ($[5] !== onInputChange) {
46
+ t4 = setterOf(setOwn, onInputChange);
47
+ $[5] = onInputChange;
48
+ $[6] = t4;
49
+ } else t4 = $[6];
50
+ let t5;
51
+ if ($[7] !== current || $[8] !== t3 || $[9] !== t4) {
52
+ t5 = {
53
+ inputValue: current,
54
+ matches: t3,
55
+ setInputValue: t4
56
+ };
57
+ $[7] = current;
58
+ $[8] = t3;
59
+ $[9] = t4;
60
+ $[10] = t5;
61
+ } else t5 = $[10];
62
+ const value = t5;
63
+ let t6;
64
+ if ($[11] !== children || $[12] !== value) {
65
+ t6 = /* @__PURE__ */ jsx(AutocompleteContext, {
66
+ value,
67
+ children
68
+ });
69
+ $[11] = children;
70
+ $[12] = value;
71
+ $[13] = t6;
72
+ } else t6 = $[13];
73
+ return t6;
74
+ }
75
+ function matchesOf(filter, inputValue) {
76
+ return (textValue, node) => filter(textValue, inputValue, node);
77
+ }
78
+ function setterOf(setOwn, onInputChange) {
79
+ return (value) => {
80
+ setOwn(value);
81
+ onInputChange?.(value);
82
+ };
83
+ }
84
+ //#endregion
85
+ export { Autocomplete };
86
+
87
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["ReactNode","Node","useMemo","useState","AutocompleteValue","AutocompleteContext","containsIn","localeOf","AutocompleteFilter","textValue","inputValue","node","T","AutocompleteProps","children","defaultInputValue","filter","onInputChange","value","Autocomplete","t0","$","_c","t1","undefined","own","setOwn","current","t2","t3","matchesOf","t4","setterOf","t5","matches","setInputValue","t6","_c"],"sources":["../../../src/components/autocomplete/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport type { Node } from 'react-stately'\n\nimport { useMemo, useState } from 'react'\n\nimport type { AutocompleteValue } from '../../autocomplete'\n\nimport { AutocompleteContext, containsIn } from '../../autocomplete'\nimport { localeOf } from '../../number/locale'\n\n// kanso-ui's Autocomplete, from the search page's search with suggestions: a\n// SearchField over a List, where typing narrows the rows the list shows. It\n// draws nothing of its own, as web's draws nothing: the bar is SearchField's,\n// the rows are List's, and where the two sit is the page's business. So it\n// takes no `style`, since there is nothing for one to land on.\n//\n// Three things are worth knowing, and the last two differ from web's.\n//\n// **Filtering is on by default,** as on web: `filter` falls back to a match\n// anywhere in a row's text, compared by an `Intl.Collator` in the device's\n// locale at base sensitivity, so case and accents are ignored, which is what\n// web's falls back to as well.\n//\n// **There is no virtual focus.** Web keeps the keyboard in the input while\n// the arrow keys move through the list. A touch screen has no arrow keys, so\n// the list's rows are pressed where they are, and a press on one selects it\n// or runs its action, as it does in any List. A list inside an Autocomplete\n// keeps the keyboard up through that press, with `keyboardShouldPersistTaps`\n// at `handled`, so a row is reached on the first tap rather than the one\n// that would otherwise only close the keyboard.\n//\n// **The count is announced.** Web says only that a search left nothing.\n// Here the list says how many rows a search leaves each time the number\n// changes, in React Aria's words for a ComboBox's count, and that it left\n// none in the empty row's: through a polite live region on Android and\n// under React Native Web, and `AccessibilityInfo` on iOS, which has no live\n// regions. The list's empty row is drawn as ever when nothing matches.\n\n/**\n * Whether a search keeps a row: handed the row's text, what has been typed\n * and the row's entry in the collection, as React Aria's is.\n */\ntype AutocompleteFilter<T extends object = object> = (\n textValue: string,\n inputValue: string,\n node: Node<T>,\n) => boolean\n\ntype AutocompleteProps<T extends object = object> = {\n /**\n * The search field and the list it filters, in whatever the page puts\n * around them.\n */\n readonly children?: ReactNode\n /** What has been typed at first, when the autocomplete keeps its own. */\n readonly defaultInputValue?: string\n /**\n * Which rows a search keeps. Left out, a row is kept when its text\n * contains what has been typed anywhere in it, ignoring case and accents.\n */\n readonly filter?: AutocompleteFilter<T>\n /** What has been typed, when the call site holds it. */\n readonly inputValue?: string\n /** Called with what has been typed whenever an edit changes it. */\n readonly onInputChange?: (value: string) => void\n}\n\n/**\n * A search field that filters the list under it. What has been typed is the\n * autocomplete's: pass `inputValue` with `onInputChange` to control it, or\n * `defaultInputValue` to let it keep its own. The field inside shows it, and\n * its own `value` and `defaultValue` are not read there.\n *\n * ```tsx\n * <Autocomplete>\n * <SearchField label=\"Search\" placeholder=\"Search\" />\n * <List aria-label=\"Results\" selectionMode=\"single\">\n * <List.Item id=\"first\">First item</List.Item>\n * </List>\n * </Autocomplete>\n * ```\n *\n * It renders nothing of its own, so the field and the list sit wherever the\n * page puts them, and the list says how many rows each search leaves to a\n * screen reader.\n */\nfunction Autocomplete<T extends object = object>({\n children,\n defaultInputValue = '',\n filter,\n inputValue,\n onInputChange,\n}: AutocompleteProps<T>) {\n const [own, setOwn] = useState(defaultInputValue)\n const current = inputValue ?? own\n const value = useMemo<AutocompleteValue>(\n () => ({\n inputValue: current,\n matches: matchesOf(filter ?? containsIn(localeOf(undefined)), current),\n setInputValue: setterOf(setOwn, onInputChange),\n }),\n [current, filter, onInputChange],\n )\n\n return <AutocompleteContext value={value}>{children}</AutocompleteContext>\n}\n\n// The filter with what has been typed already in it, which is all a list\n// asks of a row.\nfunction matchesOf<T extends object>(\n filter: AutocompleteFilter<T>,\n inputValue: string,\n): AutocompleteValue['matches'] {\n return (textValue, node) =>\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- the rows are the call site's, which typed the filter it wrote for them\n filter(textValue, inputValue, node as Node<T>)\n}\n\n// Keeps an edit as the autocomplete's own value and reports it, so one the\n// call site controls is told and one it does not still filters.\nfunction setterOf(\n setOwn: (value: string) => void,\n onInputChange: ((value: string) => void) | undefined,\n) {\n return (value: string) => {\n setOwn(value)\n onInputChange?.(value)\n }\n}\n\nexport { Autocomplete }\nexport type { AutocompleteFilter, AutocompleteProps }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,SAAAmB,aAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAiD,MAAA,EAAAR,UAAAC,mBAAAQ,IAAAP,QAAAN,YAAAO,kBAAAG;CAO/C,MAAA,CAAAK,KAAAC,UAAsBvB,SALtBoB,OAAAC,KAAAA,IAAA,KAAAD,EAKgD;CAChD,MAAAI,UAAgBjB,cAAAe;CAAiB,IAAAG;CAAA,IAAAP,EAAA,OAAAL,QAAA;EAIVY,KAAAZ,UAAUV,WAAWC,SAASiB,KAAAA,CAAS,CAAC;EAACH,EAAA,KAAAL;EAAAK,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAAA,IAAAQ;CAAA,IAAAR,EAAA,OAAAM,WAAAN,EAAA,OAAAO,IAAA;EAAnDC,KAAAC,UAAUF,IAA2CD,OAAO;EAACN,EAAA,KAAAM;EAAAN,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAJ,eAAA;EACvDc,KAAAC,SAASN,QAAQT,aAAa;EAACI,EAAA,KAAAJ;EAAAI,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,IAAAY;CAAA,IAAAZ,EAAA,OAAAM,WAAAN,EAAA,OAAAQ,MAAAR,EAAA,OAAAU,IAAA;EAHzCE,KAAA;GAAAvB,YACOiB;GAAOO,SACVL;GAA6DM,eACvDJ;EACjB;EAACV,EAAA,KAAAM;EAAAN,EAAA,KAAAQ;EAAAR,EAAA,KAAAU;EAAAV,EAAA,MAAAY;CAAA,OAAAA,KAAAZ,EAAA;CALH,MAAAH,QACSe;CAMR,IAAAG;CAAA,IAAAf,EAAA,QAAAP,YAAAO,EAAA,QAAAH,OAAA;EAEMkB,KAAA,oBAAC,qBAAD;GAA4BlB;GAAQJ;EAAhB,CAAA;EAA+CO,EAAA,MAAAP;EAAAO,EAAA,MAAAH;EAAAG,EAAA,MAAAe;CAAA,OAAAA,KAAAf,EAAA;CAAA,OAAnEe;AAAmE;AAK5E,SAASN,UACPd,QACAN,YAC8B;CAC9B,QAAQD,WAAWE,SAEjBK,OAAOP,WAAWC,YAAYC,IAAe;AACjD;AAIA,SAASqB,SACPN,QACAT,eACA;CACA,QAAQC,UAAkB;EACxBQ,OAAOR,KAAK;EACZD,gBAAgBC,KAAK;CACvB;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { MarkImageProps } from "../../mark/index.js";
2
- import { StyleProp, View, ViewProps, ViewStyle } from "react-native";
3
2
  import { ComponentRef, Ref } from "react";
3
+ import { StyleProp, View, ViewProps, ViewStyle } from "react-native";
4
4
  //#region src/components/avatar/index.d.ts
5
5
  type AvatarProps = Omit<ViewProps, 'children' | 'style'> & {
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import { ButtonLinkForm, ButtonPressForm, ButtonToggleForm } from "../../button/index.js";
2
- import { PressableProps, StyleProp, View, ViewStyle } from "react-native";
3
2
  import { ComponentRef, ReactNode, Ref } from "react";
3
+ import { PressableProps, StyleProp, View, ViewStyle } from "react-native";
4
4
  //#region src/components/button/index.d.ts
5
5
  type ButtonForm = ButtonLinkForm | ButtonPressForm | (ButtonToggleForm & {
6
6
  /**
@@ -81,7 +81,7 @@ type ButtonVariant = 'elevated' | 'filled' | 'outlined' | 'text' | 'tonal';
81
81
  * target through `hitSlop`, which a `hitSlop` of the call site's own replaces.
82
82
  * `style`, `ref` and `testID` land on the `Pressable`.
83
83
  */
84
- declare function Button({ children, defaultSelected, disableRipple, hitSlop: ownHitSlop, href, icon, isDisabled, isPending, isSelected, onBlur, onChange, onFocus, onHoverIn, onHoverOut, onLayout, onLongPress, onPress, onPressIn, onPressOut, pendingLabel, shape, size, slot, style, type, variant, ...props }: ButtonProps): import("react").JSX.Element;
84
+ declare function Button({ children, defaultSelected, delayLongPress, disableRipple, hitSlop: ownHitSlop, href, icon, isDisabled, isPending, isSelected, onBlur, onChange, onFocus, onHoverIn, onHoverOut, onLayout, onLongPress, onPress, onPressIn, onPressOut, pendingLabel, ref, shape, size, slot, style, type, variant, ...props }: ButtonProps): import("react").JSX.Element;
85
85
  //#endregion
86
86
  export { Button, type ButtonProps, type ButtonShape, type ButtonSize, type ButtonVariant };
87
87
  //# sourceMappingURL=index.d.ts.map