@xaui/native 0.9.1-alpha.22 → 0.9.1-alpha.24

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 (63) hide show
  1. package/dist/{chunk-KM2TI5IC.js → chunk-4HELPMAK.js} +76 -82
  2. package/dist/{chunk-AHL33YAO.js → chunk-4J26FA6O.js} +9 -7
  3. package/dist/{chunk-BNWS26PX.cjs → chunk-6FBGCF5T.cjs} +9 -7
  4. package/dist/chunk-6RO26ORT.js +451 -0
  5. package/dist/{chunk-ZQ3JSWRO.js → chunk-A4RGJBP2.js} +4 -2
  6. package/dist/{chunk-I6PE5UUH.cjs → chunk-AV5LMFS3.cjs} +13 -11
  7. package/dist/{chunk-OGC4RKE3.js → chunk-AXSJPWSJ.js} +5 -5
  8. package/dist/chunk-EGLLDKN6.js +9 -0
  9. package/dist/chunk-EJQCQPET.cjs +9 -0
  10. package/dist/{chunk-VDRRD6GM.cjs → chunk-EWBBDVTM.cjs} +22 -21
  11. package/dist/{chunk-BH5DSJVX.cjs → chunk-IG4Q3WQO.cjs} +61 -68
  12. package/dist/{chunk-6WW4CSPY.cjs → chunk-J2JJLKLG.cjs} +6 -4
  13. package/dist/{chunk-4MHJOWM4.cjs → chunk-J4JFIC4W.cjs} +7 -7
  14. package/dist/chunk-J4QE34AU.js +732 -0
  15. package/dist/chunk-LIQTGAI7.cjs +621 -0
  16. package/dist/{chunk-FNQF4KQV.js → chunk-MRYLLKML.js} +18 -17
  17. package/dist/chunk-P2XA4DV7.cjs +451 -0
  18. package/dist/{chunk-FTCTTBLG.js → chunk-ZTA47PO5.js} +7 -5
  19. package/dist/components/alert/index.cjs +7 -6
  20. package/dist/components/alert/index.d.cts +2 -2
  21. package/dist/components/alert/index.d.ts +2 -2
  22. package/dist/components/alert/index.js +6 -5
  23. package/dist/components/button/index.cjs +6 -5
  24. package/dist/components/button/index.d.cts +168 -168
  25. package/dist/components/button/index.d.ts +168 -168
  26. package/dist/components/button/index.js +5 -4
  27. package/dist/components/card/index.cjs +5 -4
  28. package/dist/components/card/index.d.cts +170 -170
  29. package/dist/components/card/index.d.ts +170 -170
  30. package/dist/components/card/index.js +4 -3
  31. package/dist/components/chip/index.cjs +7 -6
  32. package/dist/components/chip/index.d.cts +169 -169
  33. package/dist/components/chip/index.d.ts +169 -169
  34. package/dist/components/chip/index.js +6 -5
  35. package/dist/components/input/index.cjs +14 -0
  36. package/dist/components/input/index.d.cts +213 -0
  37. package/dist/components/input/index.d.ts +213 -0
  38. package/dist/components/input/index.js +14 -0
  39. package/dist/components/input-otp/index.cjs +27 -0
  40. package/dist/components/input-otp/index.d.cts +325 -0
  41. package/dist/components/input-otp/index.d.ts +325 -0
  42. package/dist/components/input-otp/index.js +27 -0
  43. package/dist/components/typography/index.cjs +3 -3
  44. package/dist/components/typography/index.d.cts +3 -3
  45. package/dist/components/typography/index.d.ts +3 -3
  46. package/dist/components/typography/index.js +2 -2
  47. package/dist/components/view/index.d.cts +6 -6
  48. package/dist/components/view/index.d.ts +6 -6
  49. package/dist/{create-recipe-CbXika57.d.ts → create-recipe-C4JkINrA.d.ts} +14 -2
  50. package/dist/{create-recipe-jHlk434p.d.cts → create-recipe-dBN_ewZc.d.cts} +14 -2
  51. package/dist/index.cjs +44 -50
  52. package/dist/index.d.cts +3 -1
  53. package/dist/index.d.ts +3 -1
  54. package/dist/index.js +64 -70
  55. package/dist/system/index.cjs +6 -5
  56. package/dist/system/index.d.cts +4 -4
  57. package/dist/system/index.d.ts +4 -4
  58. package/dist/system/index.js +5 -4
  59. package/package.json +21 -1
  60. package/dist/{chunk-DXGQ43IV.cjs → chunk-B4W2XNBP.cjs} +2 -2
  61. package/dist/{chunk-2U6JR7BF.js → chunk-G52TQJBI.js} +3 -3
  62. package/dist/{chunk-FVP5FUVS.js → chunk-ICR42HHG.js} +3 -3
  63. package/dist/{chunk-RAWOJ3N3.cjs → chunk-Y7U6ACMB.cjs} +2 -2
@@ -0,0 +1,732 @@
1
+ import { warnDev } from "./chunk-EGLLDKN6.js";
2
+ import { createRecipe, radiusAxis } from "./chunk-3JATAB7S.js";
3
+ import { createSlotContext, useStyleProps } from "./chunk-PMO62QK4.js";
4
+ import { useXAUITheme } from "./chunk-A3EGFI6T.js";
5
+
6
+ // src/components/input-otp/input-otp-box.tsx
7
+ import { forwardRef as forwardRef3, useMemo } from "react";
8
+ import { View as View2 } from "react-native";
9
+
10
+ // src/components/input-otp/input-otp.context.ts
11
+ var [InputOTPProvider, useInputOTP] = createSlotContext("InputOTP");
12
+ var [InputOTPBoxProvider, useInputOTPBox] = createSlotContext("InputOTP.Box");
13
+
14
+ // src/components/input-otp/input-otp-caret.tsx
15
+ import { useEffect } from "react";
16
+ import { View } from "react-native";
17
+ import Animated, { Easing, cancelAnimation, useAnimatedStyle, useSharedValue, withRepeat, withTiming } from "react-native-reanimated";
18
+ import { jsx } from "react/jsx-runtime";
19
+ var BLINK_DURATION = 530;
20
+ function InputOTPCaret({
21
+ style,
22
+ animation = true,
23
+ ...props
24
+ }) {
25
+ const {
26
+ caretStyle
27
+ } = useInputOTP();
28
+ const {
29
+ slot
30
+ } = useInputOTPBox();
31
+ const [styleProps] = useStyleProps(props);
32
+ const barStyle = [caretStyle, styleProps, style];
33
+ if (!slot?.isCaretVisible) return null;
34
+ if (!animation) return /* @__PURE__ */jsx(View, {
35
+ style: barStyle
36
+ });
37
+ return /* @__PURE__ */jsx(BlinkingCaret, {
38
+ style: barStyle
39
+ });
40
+ }
41
+ InputOTPCaret.displayName = "XAUI.InputOTP.Caret";
42
+ const _worklet_14878605646981_init_data = {
43
+ code: "function chunkJ4QE34AUJs1(){const{opacity}=this.__closure;return{opacity:opacity.value};}",
44
+ location: "/home/runner/work/xaui/xaui/packages/native/dist/chunk-J4QE34AU.js",
45
+ sourceMap: "{\"version\":3,\"names\":[\"chunkJ4QE34AUJs1\",\"opacity\",\"__closure\",\"value\"],\"sources\":[\"/home/runner/work/xaui/xaui/packages/native/dist/chunk-J4QE34AU.js\"],\"mappings\":\"AA4DyC,SAAAA,iBAAA,QAAAC,OAAA,OAAAC,SAAA,OAAO,CAAED,OAAO,CAAEA,OAAO,CAACE,KAAM,CAAC\",\"ignoreList\":[]}"
46
+ };
47
+ function BlinkingCaret({
48
+ style
49
+ }) {
50
+ const opacity = useSharedValue(1);
51
+ useEffect(() => {
52
+ opacity.value = withRepeat(withTiming(0, {
53
+ duration: BLINK_DURATION,
54
+ easing: Easing.ease
55
+ }), -1, true);
56
+ return () => cancelAnimation(opacity);
57
+ }, [opacity]);
58
+ const animatedStyle = useAnimatedStyle(function chunkJ4QE34AUJs1Factory({
59
+ _worklet_14878605646981_init_data,
60
+ opacity
61
+ }) {
62
+ const _e = [new global.Error(), -2, -27];
63
+ const chunkJ4QE34AUJs1 = () => ({
64
+ opacity: opacity.value
65
+ });
66
+ chunkJ4QE34AUJs1.__closure = {
67
+ opacity
68
+ };
69
+ chunkJ4QE34AUJs1.__workletHash = 14878605646981;
70
+ chunkJ4QE34AUJs1.__pluginVersion = "0.7.4";
71
+ chunkJ4QE34AUJs1.__initData = _worklet_14878605646981_init_data;
72
+ chunkJ4QE34AUJs1.__stackDetails = _e;
73
+ return chunkJ4QE34AUJs1;
74
+ }({
75
+ _worklet_14878605646981_init_data,
76
+ opacity
77
+ }));
78
+ return /* @__PURE__ */jsx(Animated.View, {
79
+ style: [style, animatedStyle]
80
+ });
81
+ }
82
+
83
+ // src/components/input-otp/input-otp-placeholder.tsx
84
+ import { forwardRef } from "react";
85
+ import { Text } from "react-native";
86
+ import { jsx as jsx2 } from "react/jsx-runtime";
87
+ var InputOTPPlaceholder = forwardRef(function InputOTPPlaceholder2({
88
+ children,
89
+ style,
90
+ maxFontSizeMultiplier = 1.6,
91
+ ...props
92
+ }, ref) {
93
+ const {
94
+ placeholderStyle
95
+ } = useInputOTP();
96
+ const {
97
+ slot
98
+ } = useInputOTPBox();
99
+ const [styleProps, rest] = useStyleProps(props);
100
+ const char = children ?? slot?.placeholderChar;
101
+ if (!char) return null;
102
+ return /* @__PURE__ */jsx2(Text, {
103
+ ref,
104
+ maxFontSizeMultiplier,
105
+ style: [placeholderStyle, styleProps, style],
106
+ ...rest,
107
+ children: char
108
+ });
109
+ });
110
+ InputOTPPlaceholder.displayName = "XAUI.InputOTP.Placeholder";
111
+
112
+ // src/components/input-otp/input-otp-value.tsx
113
+ import { forwardRef as forwardRef2 } from "react";
114
+ import { Text as Text2 } from "react-native";
115
+ import { jsx as jsx3 } from "react/jsx-runtime";
116
+ var InputOTPValue = forwardRef2(function InputOTPValue2({
117
+ children,
118
+ style,
119
+ maxFontSizeMultiplier = 1.6,
120
+ ...props
121
+ }, ref) {
122
+ const {
123
+ valueStyle
124
+ } = useInputOTP();
125
+ const {
126
+ slot
127
+ } = useInputOTPBox();
128
+ const [styleProps, rest] = useStyleProps(props);
129
+ const char = children ?? slot?.char;
130
+ if (!char) return null;
131
+ return /* @__PURE__ */jsx3(Text2, {
132
+ ref,
133
+ maxFontSizeMultiplier,
134
+ style: [valueStyle, styleProps, style],
135
+ ...rest,
136
+ children: char
137
+ });
138
+ });
139
+ InputOTPValue.displayName = "XAUI.InputOTP.Value";
140
+
141
+ // src/components/input-otp/input-otp-box.tsx
142
+ import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
143
+ var InputOTPBox = forwardRef3(function InputOTPBox2({
144
+ index,
145
+ children,
146
+ style,
147
+ ...props
148
+ }, ref) {
149
+ const {
150
+ boxStyle,
151
+ boxActiveStyle,
152
+ slots
153
+ } = useInputOTP();
154
+ const [styleProps, rest] = useStyleProps(props);
155
+ const slot = slots[index];
156
+ const context = useMemo(() => ({
157
+ slot
158
+ }), [slot]);
159
+ return /* @__PURE__ */jsx4(InputOTPBoxProvider, {
160
+ value: context,
161
+ children: /* @__PURE__ */jsx4(View2, {
162
+ ref,
163
+ style: [slot?.isActive ? boxActiveStyle : boxStyle, styleProps, style],
164
+ ...rest,
165
+ children: children ?? /* @__PURE__ */jsxs(Fragment, {
166
+ children: [/* @__PURE__ */jsx4(InputOTPPlaceholder, {}), /* @__PURE__ */jsx4(InputOTPValue, {}), /* @__PURE__ */jsx4(InputOTPCaret, {})]
167
+ })
168
+ })
169
+ });
170
+ });
171
+ InputOTPBox.displayName = "XAUI.InputOTP.Box";
172
+
173
+ // src/components/input-otp/input-otp-group.tsx
174
+ import { forwardRef as forwardRef4 } from "react";
175
+ import { View as View3 } from "react-native";
176
+ import { jsx as jsx5 } from "react/jsx-runtime";
177
+ var InputOTPGroup = forwardRef4(function InputOTPGroup2({
178
+ children,
179
+ style,
180
+ ...props
181
+ }, ref) {
182
+ const {
183
+ groupStyle,
184
+ slots,
185
+ value,
186
+ maxLength,
187
+ isFocused,
188
+ isDisabled,
189
+ isInvalid
190
+ } = useInputOTP();
191
+ const [styleProps, rest] = useStyleProps(props);
192
+ const content = typeof children === "function" ? children({
193
+ slots,
194
+ value,
195
+ maxLength,
196
+ isFocused,
197
+ isDisabled,
198
+ isInvalid
199
+ }) : children;
200
+ return /* @__PURE__ */jsx5(View3, {
201
+ ref,
202
+ style: [groupStyle, styleProps, style],
203
+ ...rest,
204
+ children: content
205
+ });
206
+ });
207
+ InputOTPGroup.displayName = "XAUI.InputOTP.Group";
208
+
209
+ // src/components/input-otp/input-otp-separator.tsx
210
+ import { forwardRef as forwardRef5 } from "react";
211
+ import { View as View4 } from "react-native";
212
+ import { jsx as jsx6 } from "react/jsx-runtime";
213
+ var InputOTPSeparator = forwardRef5(function InputOTPSeparator2({
214
+ children,
215
+ style,
216
+ ...props
217
+ }, ref) {
218
+ const {
219
+ separatorStyle
220
+ } = useInputOTP();
221
+ const [styleProps, rest] = useStyleProps(props);
222
+ return /* @__PURE__ */jsx6(View4, {
223
+ ref,
224
+ accessibilityElementsHidden: true,
225
+ importantForAccessibility: "no-hide-descendants",
226
+ style: [separatorStyle, styleProps, style],
227
+ ...rest,
228
+ children
229
+ });
230
+ });
231
+ InputOTPSeparator.displayName = "XAUI.InputOTP.Separator";
232
+
233
+ // src/components/input-otp/input-otp.tsx
234
+ import { forwardRef as forwardRef6, useImperativeHandle, useMemo as useMemo3 } from "react";
235
+ import { TextInput, View as View5 } from "react-native";
236
+
237
+ // src/components/input-otp/input-otp.hook.ts
238
+ import { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
239
+
240
+ // src/hooks/use-controllable-state.ts
241
+ import { useCallback, useRef, useState } from "react";
242
+ function useControllableState({
243
+ value,
244
+ defaultValue,
245
+ onChange
246
+ }) {
247
+ const [uncontrolled, setUncontrolled] = useState(defaultValue);
248
+ const isControlled = value !== void 0;
249
+ const current = isControlled ? value : uncontrolled;
250
+ useControlWarning(isControlled);
251
+ const latest = useRef(current);
252
+ latest.current = current;
253
+ const onChangeRef = useRef(onChange);
254
+ onChangeRef.current = onChange;
255
+ const controlled = useRef(isControlled);
256
+ controlled.current = isControlled;
257
+ const set = useCallback(next => {
258
+ const resolved = typeof next === "function" ? next(latest.current) : next;
259
+ if (resolved === latest.current) return;
260
+ if (!controlled.current) setUncontrolled(resolved);
261
+ onChangeRef.current?.(resolved);
262
+ }, []);
263
+ return [current, set];
264
+ }
265
+ function useControlWarning(isControlled) {
266
+ const wasControlled = useRef(isControlled);
267
+ if (wasControlled.current !== isControlled) {
268
+ warnDev(`a component switched from ${wasControlled.current ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}. Decide for the life of the component: pass \`value\` always, or never. Passing \`undefined\` for a value you do control reads as "uncontrolled" here.`);
269
+ wasControlled.current = isControlled;
270
+ }
271
+ }
272
+
273
+ // src/components/input-otp/input-otp.utils.ts
274
+ function buildSlots({
275
+ value,
276
+ maxLength,
277
+ isFocused,
278
+ placeholder
279
+ }) {
280
+ return Array.from({
281
+ length: maxLength
282
+ }, (_, index) => {
283
+ const char = value[index] ?? null;
284
+ const isActive = isFocused && index === value.length;
285
+ return {
286
+ index,
287
+ char,
288
+ // A box shows its placeholder only when it has neither a character nor the caret.
289
+ placeholderChar: char === null && !isActive ? placeholderFor(placeholder, index) : null,
290
+ isActive,
291
+ isCaretVisible: isActive && char === null
292
+ };
293
+ });
294
+ }
295
+ function placeholderFor(placeholder, index) {
296
+ if (!placeholder) return null;
297
+ return placeholder.length === 1 ? placeholder : placeholder[index] ?? null;
298
+ }
299
+ function extractPastedCode(pasted, maxLength) {
300
+ const match = pasted.match(new RegExp(`(?<!\\d)(\\d{${maxLength}})(?!\\d)`));
301
+ return match?.[1] ?? "";
302
+ }
303
+ function isPaste(text, previous) {
304
+ return text.length > previous.length + 1;
305
+ }
306
+ var OTP_DIGITS = "^\\d+$";
307
+ var OTP_LETTERS = "^[a-zA-Z]+$";
308
+ var OTP_ALPHANUMERIC = "^[a-zA-Z0-9]+$";
309
+
310
+ // src/components/input-otp/input-otp.hook.ts
311
+ function useInputOTPState({
312
+ maxLength,
313
+ value: valueProp,
314
+ defaultValue = "",
315
+ onChangeText: onChangeTextProp,
316
+ onComplete,
317
+ pattern,
318
+ placeholder
319
+ }) {
320
+ const [value, setValue] = useControllableState({
321
+ value: valueProp,
322
+ defaultValue,
323
+ onChange: onChangeTextProp
324
+ });
325
+ const [isFocused, setIsFocused] = useState2(false);
326
+ const inputRef = useRef2(null);
327
+ const regexp = useMemo2(() => {
328
+ if (!pattern) return null;
329
+ return typeof pattern === "string" ? new RegExp(pattern) : pattern;
330
+ }, [pattern]);
331
+ const slots = useMemo2(() => buildSlots({
332
+ value,
333
+ maxLength,
334
+ isFocused,
335
+ placeholder
336
+ }), [value, maxLength, isFocused, placeholder]);
337
+ const latest = useRef2({
338
+ value,
339
+ maxLength,
340
+ regexp,
341
+ onComplete,
342
+ setValue
343
+ });
344
+ latest.current = {
345
+ value,
346
+ maxLength,
347
+ regexp,
348
+ onComplete,
349
+ setValue
350
+ };
351
+ const onChangeText = useCallback2(text => {
352
+ const current = latest.current;
353
+ const candidate = isPaste(text, current.value) ? extractPastedCode(text, current.maxLength) : text;
354
+ const next = candidate.slice(0, current.maxLength);
355
+ if (next.length > 0 && current.regexp && !current.regexp.test(next)) return;
356
+ current.setValue(next);
357
+ if (next.length === current.maxLength) current.onComplete?.(next);
358
+ }, []);
359
+ const onFocus = useCallback2(() => setIsFocused(true), []);
360
+ const onBlur = useCallback2(() => setIsFocused(false), []);
361
+ const handle = useMemo2(() => ({
362
+ focus: () => inputRef.current?.focus(),
363
+ blur: () => inputRef.current?.blur(),
364
+ // Both halves: the native buffer and our value. Clearing one and not the other is
365
+ // how a cleared field comes back on the next keystroke.
366
+ clear: () => {
367
+ inputRef.current?.clear();
368
+ latest.current.setValue("");
369
+ }
370
+ }), []);
371
+ return {
372
+ value,
373
+ slots,
374
+ isFocused,
375
+ inputRef,
376
+ handle,
377
+ onChangeText,
378
+ onFocus,
379
+ onBlur
380
+ };
381
+ }
382
+
383
+ // src/components/input-otp/input-otp.recipe.ts
384
+ var SLOTS = ["root", "group", "box", "value", "placeholder", "caret", "separator"];
385
+ var VARIANT_TOKENS = {
386
+ primary: {
387
+ bg: "fieldBackground",
388
+ border: "fieldBorder",
389
+ borderFocus: "accent",
390
+ fg: "fieldForeground"
391
+ },
392
+ secondary: {
393
+ bg: "default",
394
+ border: "fieldBorder",
395
+ borderFocus: "accent",
396
+ fg: "fieldForeground"
397
+ },
398
+ tertiary: {
399
+ border: "fieldBorder",
400
+ borderFocus: "accent",
401
+ fg: "fieldForeground"
402
+ }
403
+ };
404
+ var PLACEHOLDER_OPACITY = 0.5;
405
+ var ACTIVE_BORDER_WIDTH = 2;
406
+ function sizeAxis(step) {
407
+ const {
408
+ control,
409
+ gap,
410
+ glyph
411
+ } = step;
412
+ return theme => {
413
+ const height = theme.controlHeights[control];
414
+ const type = {
415
+ fontSize: theme.fontSizes[glyph],
416
+ lineHeight: theme.lineHeights[glyph]
417
+ };
418
+ return {
419
+ root: {
420
+ gap: theme.spacing(gap)
421
+ },
422
+ group: {
423
+ gap: theme.spacing(gap)
424
+ },
425
+ box: {
426
+ height,
427
+ width: height - theme.spacing(1)
428
+ },
429
+ value: type,
430
+ placeholder: type,
431
+ // As tall as the character it stands in for, so the box does not change shape
432
+ // between an empty state and a typed one.
433
+ caret: {
434
+ height: theme.lineHeights[glyph],
435
+ width: theme.spacing(CARET_WIDTH)
436
+ },
437
+ separator: {
438
+ height: theme.spacing(CARET_WIDTH),
439
+ width: theme.spacing(SEPARATOR_WIDTH)
440
+ }
441
+ };
442
+ };
443
+ }
444
+ var CARET_WIDTH = 0.5;
445
+ var SEPARATOR_WIDTH = 2;
446
+ var SIZES = {
447
+ sm: {
448
+ control: "sm",
449
+ gap: 2,
450
+ glyph: "md"
451
+ },
452
+ md: {
453
+ control: "md",
454
+ gap: 2,
455
+ glyph: "lg"
456
+ },
457
+ lg: {
458
+ control: "lg",
459
+ gap: 2.5,
460
+ glyph: "xl"
461
+ }
462
+ };
463
+ var inputOTPRecipe = createRecipe({
464
+ slots: SLOTS,
465
+ base: theme => ({
466
+ root: {
467
+ flexDirection: "row",
468
+ alignItems: "center"
469
+ },
470
+ group: {
471
+ flexDirection: "row",
472
+ alignItems: "center"
473
+ },
474
+ box: {
475
+ alignItems: "center",
476
+ justifyContent: "center",
477
+ // `lg` and not `field`, which is the radius the rest of this family uses. A field is
478
+ // wide, so 21 on a 48-tall one reads as a rounded rectangle; a code box is very
479
+ // nearly square — 44 by 48 at `md`, 36 by 40 at `sm` — where the geometric maximum
480
+ // is 22, so the same 21 is a pill in all but name and is clamped to one outright at
481
+ // the small end. Twelve is where HeroUI lands for the same box from the other
482
+ // direction: their `field` radius is their `xl`, and their scale's base is 8 where
483
+ // ours is 12.
484
+ borderRadius: theme.radius.lg,
485
+ borderCurve: "continuous",
486
+ // The one root in the library that clips: the box has no shadow to lose and a
487
+ // character wider than it would otherwise spill onto its neighbour.
488
+ overflow: "hidden"
489
+ },
490
+ // `semibold`, where a field's own text is `regular`. A code is read at a glance and
491
+ // then compared character by character, which is the one thing weight helps with.
492
+ value: {
493
+ fontFamily: theme.fontFamilies.body,
494
+ fontWeight: theme.fontWeights.semibold
495
+ },
496
+ placeholder: {
497
+ fontFamily: theme.fontFamilies.body,
498
+ fontWeight: theme.fontWeights.semibold,
499
+ color: theme.colors.fieldPlaceholder,
500
+ opacity: PLACEHOLDER_OPACITY
501
+ },
502
+ caret: {
503
+ position: "absolute",
504
+ borderRadius: theme.radius.full,
505
+ backgroundColor: theme.colors.fieldPlaceholder
506
+ },
507
+ // The theme's second separator level rather than the first at half opacity: it is
508
+ // already the lighter of the two, and it composites the same way in both modes.
509
+ separator: {
510
+ borderRadius: theme.radius.full,
511
+ backgroundColor: theme.colors.separatorSecondary
512
+ }
513
+ }),
514
+ variantTokens: VARIANT_TOKENS,
515
+ /**
516
+ * Where the variant's colours land. The border width follows the *presence* of the
517
+ * border role, so a variant that names none needs no rule of its own to say so.
518
+ *
519
+ * The active box takes the ring whichever variant it is: the `focused` state sets the
520
+ * width as well as the colour. The box has a fixed width and height and centres what it
521
+ * holds, so an edge appearing moves nothing.
522
+ */
523
+ paint: (theme, colors) => ({
524
+ box: {
525
+ backgroundColor: colors.bg,
526
+ borderColor: colors.border,
527
+ borderWidth: colors.border ? theme.borderWidth.field : 0
528
+ },
529
+ value: {
530
+ color: colors.fg
531
+ }
532
+ }),
533
+ variants: {
534
+ size: {
535
+ sm: sizeAxis(SIZES.sm),
536
+ md: sizeAxis(SIZES.md),
537
+ lg: sizeAxis(SIZES.lg)
538
+ },
539
+ radius: radiusAxis("box"),
540
+ /**
541
+ * Declared after `size` and before the states, so a code that is wrong stays wrong
542
+ * under the finger: the ring below reads `borderFocus`, and the root hands it the
543
+ * danger colour by suppressing the active state and painting every box instead.
544
+ */
545
+ isInvalid: {
546
+ true: theme => ({
547
+ box: {
548
+ borderColor: theme.colors.danger,
549
+ borderWidth: ACTIVE_BORDER_WIDTH
550
+ }
551
+ })
552
+ }
553
+ },
554
+ compoundVariants: [{
555
+ when: {
556
+ variant: "primary"
557
+ },
558
+ style: theme => ({
559
+ box: theme.shadows.field
560
+ })
561
+ }],
562
+ /**
563
+ * `focused` here means **this box is the active one**, not that the component has the
564
+ * keyboard: the root resolves the recipe twice, once each way, and hands both to the
565
+ * boxes so none of them resolves anything itself (R5).
566
+ */
567
+ states: {
568
+ focused: (_theme, colors) => ({
569
+ box: {
570
+ borderColor: colors.borderFocus,
571
+ borderWidth: ACTIVE_BORDER_WIDTH
572
+ }
573
+ }),
574
+ disabled: theme => ({
575
+ root: {
576
+ opacity: theme.opacity.disabled
577
+ }
578
+ })
579
+ },
580
+ defaultVariants: {
581
+ variant: "secondary",
582
+ size: "md"
583
+ }
584
+ });
585
+
586
+ // src/components/input-otp/input-otp.style.ts
587
+ import { Platform, StyleSheet } from "react-native";
588
+ var inputOTPSheet = StyleSheet.create({
589
+ hiddenInput: {
590
+ ...StyleSheet.absoluteFillObject,
591
+ color: "transparent",
592
+ // A caret of our own is drawn in the active box; the platform's would sit wherever
593
+ // the invisible text happens to end.
594
+ ...Platform.select({
595
+ ios: {
596
+ opacity: 0.02
597
+ },
598
+ default: {
599
+ opacity: 0
600
+ }
601
+ })
602
+ }
603
+ });
604
+
605
+ // src/components/input-otp/input-otp.tsx
606
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
607
+ var InputOTPRoot = forwardRef6(function InputOTP({
608
+ children,
609
+ maxLength,
610
+ variant,
611
+ size,
612
+ radius,
613
+ color,
614
+ value: valueProp,
615
+ defaultValue,
616
+ onChangeText,
617
+ onComplete,
618
+ pattern,
619
+ placeholder,
620
+ isInvalid = false,
621
+ isDisabled = false,
622
+ inputMode = "numeric",
623
+ textInputProps,
624
+ style,
625
+ ...props
626
+ }, ref) {
627
+ const theme = useXAUITheme();
628
+ const [styleProps, rest] = useStyleProps(props);
629
+ const state = useInputOTPState({
630
+ maxLength,
631
+ value: valueProp,
632
+ defaultValue,
633
+ onChangeText,
634
+ onComplete,
635
+ pattern,
636
+ placeholder
637
+ });
638
+ useImperativeHandle(ref, () => state.handle, [state.handle]);
639
+ const selection = {
640
+ variant,
641
+ size,
642
+ radius,
643
+ isInvalid: isInvalid ? "true" : void 0
644
+ };
645
+ const states = {
646
+ disabled: isDisabled
647
+ };
648
+ const styles = inputOTPRecipe.resolve({
649
+ theme,
650
+ selection,
651
+ states
652
+ });
653
+ const activeStyles = isInvalid ? styles : inputOTPRecipe.resolve({
654
+ theme,
655
+ selection,
656
+ states: {
657
+ ...states,
658
+ focused: true
659
+ }
660
+ });
661
+ const tint = color ? inputOTPRecipe.tint({
662
+ theme,
663
+ color,
664
+ selection,
665
+ states
666
+ }) : void 0;
667
+ const activeTint = color && !isInvalid ? inputOTPRecipe.tint({
668
+ theme,
669
+ color,
670
+ selection,
671
+ states: {
672
+ ...states,
673
+ focused: true
674
+ }
675
+ }) : tint;
676
+ const context = useMemo3(() => ({
677
+ groupStyle: styles.group,
678
+ boxStyle: tint ? [styles.box, tint.box] : styles.box,
679
+ boxActiveStyle: activeTint ? [activeStyles.box, activeTint.box] : activeStyles.box,
680
+ valueStyle: tint ? [styles.value, tint.value] : styles.value,
681
+ placeholderStyle: styles.placeholder,
682
+ caretStyle: styles.caret,
683
+ separatorStyle: styles.separator,
684
+ slots: state.slots,
685
+ value: state.value,
686
+ maxLength,
687
+ isFocused: state.isFocused,
688
+ isDisabled,
689
+ isInvalid,
690
+ inputRef: state.inputRef
691
+ }), [styles, activeStyles, tint, activeTint, state.slots, state.value, state.isFocused, state.inputRef, maxLength, isDisabled, isInvalid]);
692
+ return /* @__PURE__ */jsx7(InputOTPProvider, {
693
+ value: context,
694
+ children: /* @__PURE__ */jsxs2(View5, {
695
+ style: [styles.root, tint?.root, styleProps, style],
696
+ ...rest,
697
+ children: [children, /* @__PURE__ */jsx7(TextInput, {
698
+ ref: state.inputRef,
699
+ style: inputOTPSheet.hiddenInput,
700
+ value: state.value,
701
+ onChangeText: state.onChangeText,
702
+ onFocus: state.onFocus,
703
+ onBlur: state.onBlur,
704
+ editable: !isDisabled,
705
+ inputMode,
706
+ caretHidden: true,
707
+ autoComplete: "one-time-code",
708
+ textContentType: "oneTimeCode",
709
+ accessibilityLabel: `${maxLength}-character code`,
710
+ accessibilityState: {
711
+ disabled: isDisabled
712
+ },
713
+ accessibilityValue: {
714
+ text: `${state.value.length} of ${maxLength} entered`
715
+ },
716
+ ...textInputProps
717
+ })]
718
+ })
719
+ });
720
+ });
721
+ InputOTPRoot.displayName = "XAUI.InputOTP.Root";
722
+
723
+ // src/components/input-otp/index.ts
724
+ var InputOTP2 = Object.assign(InputOTPRoot, {
725
+ Group: InputOTPGroup,
726
+ Box: InputOTPBox,
727
+ Value: InputOTPValue,
728
+ Placeholder: InputOTPPlaceholder,
729
+ Caret: InputOTPCaret,
730
+ Separator: InputOTPSeparator
731
+ });
732
+ export { useInputOTP, useInputOTPBox, useControllableState, buildSlots, extractPastedCode, OTP_DIGITS, OTP_LETTERS, OTP_ALPHANUMERIC, inputOTPRecipe, InputOTP2 as InputOTP };