@krizaka/ui 2.0.0-beta.2 → 2.0.0-beta.4

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 (187) hide show
  1. package/README.md +98 -6
  2. package/dist/alert.d.ts +2 -0
  3. package/dist/alert.js.map +1 -1
  4. package/dist/avatar.d.ts +5 -0
  5. package/dist/avatar.js.map +1 -1
  6. package/dist/badge.d.ts +12 -0
  7. package/dist/badge.js.map +1 -1
  8. package/dist/{button-G5qY4qSY.d.ts → button-8La7l0V4.d.ts} +15 -0
  9. package/dist/button.d.ts +19 -0
  10. package/dist/button.js.map +1 -1
  11. package/dist/card.d.ts +24 -1
  12. package/dist/card.js.map +1 -1
  13. package/dist/chip.d.ts +23 -0
  14. package/dist/chip.js.map +1 -1
  15. package/dist/{chunk-5FRYKFTO.js → chunk-3X5MVH54.js} +2 -2
  16. package/dist/chunk-3X5MVH54.js.map +1 -0
  17. package/dist/{chunk-QRG5RYEI.js → chunk-ZUD4U22H.js} +1 -1
  18. package/dist/chunk-ZUD4U22H.js.map +1 -0
  19. package/dist/command.d.ts +4 -1
  20. package/dist/command.js +2 -2
  21. package/dist/command.js.map +1 -1
  22. package/dist/confirm-button.d.ts +1 -1
  23. package/dist/confirm-button.js +1 -1
  24. package/dist/countdown.d.ts +3 -0
  25. package/dist/countdown.js.map +1 -1
  26. package/dist/{dialog-DGBY2grk.d.ts → dialog-GQ4Nvuyf.d.ts} +10 -0
  27. package/dist/dialog.d.ts +9 -1
  28. package/dist/dialog.js +2 -2
  29. package/dist/dialog.js.map +1 -1
  30. package/dist/dropdown-menu.d.ts +1 -0
  31. package/dist/dropdown-menu.js.map +1 -1
  32. package/dist/empty-state.d.ts +2 -0
  33. package/dist/empty-state.js.map +1 -1
  34. package/dist/kbd.d.ts +7 -1
  35. package/dist/kbd.js.map +1 -1
  36. package/dist/native.d.ts +471 -3
  37. package/dist/native.js +1005 -36
  38. package/dist/native.js.map +1 -1
  39. package/dist/page-header.d.ts +2 -0
  40. package/dist/page-header.js.map +1 -1
  41. package/dist/progress.d.ts +5 -0
  42. package/dist/progress.js.map +1 -1
  43. package/dist/skeleton.d.ts +7 -1
  44. package/dist/skeleton.js.map +1 -1
  45. package/dist/slider.d.ts +2 -0
  46. package/dist/slider.js.map +1 -1
  47. package/dist/spinner.d.ts +5 -0
  48. package/dist/spinner.js.map +1 -1
  49. package/dist/stat.d.ts +2 -0
  50. package/dist/stat.js.map +1 -1
  51. package/dist/switch.d.ts +7 -3
  52. package/dist/switch.js.map +1 -1
  53. package/dist/tabs.d.ts +4 -1
  54. package/dist/tabs.js.map +1 -1
  55. package/dist/theme.d.ts +10 -2
  56. package/dist/theme.js +4 -2
  57. package/dist/theme.js.map +1 -1
  58. package/dist/tooltip.d.ts +3 -0
  59. package/dist/tooltip.js.map +1 -1
  60. package/package.json +31 -8
  61. package/registry/alert.json +59 -0
  62. package/registry/avatar.json +114 -0
  63. package/registry/badge.json +59 -0
  64. package/registry/button.json +115 -0
  65. package/registry/card.json +154 -0
  66. package/registry/checkbox.json +46 -0
  67. package/registry/chip.json +164 -0
  68. package/registry/cn.json +21 -0
  69. package/registry/command.json +162 -0
  70. package/registry/confirm-button.json +104 -0
  71. package/registry/countdown.json +84 -0
  72. package/registry/demos/alert.d.ts +5 -0
  73. package/registry/demos/alert.js +12 -0
  74. package/registry/demos/alert.tsx +15 -0
  75. package/registry/demos/avatar.d.ts +5 -0
  76. package/registry/demos/avatar.js +14 -0
  77. package/registry/demos/avatar.tsx +13 -0
  78. package/registry/demos/badge.d.ts +5 -0
  79. package/registry/demos/badge.js +11 -0
  80. package/registry/demos/badge.tsx +5 -0
  81. package/registry/demos/button.d.ts +5 -0
  82. package/registry/demos/button.js +11 -0
  83. package/registry/demos/button.tsx +5 -0
  84. package/registry/demos/card.d.ts +5 -0
  85. package/registry/demos/card.js +30 -0
  86. package/registry/demos/card.tsx +37 -0
  87. package/registry/demos/checkbox.d.ts +5 -0
  88. package/registry/demos/checkbox.js +11 -0
  89. package/registry/demos/checkbox.tsx +5 -0
  90. package/registry/demos/chip.d.ts +5 -0
  91. package/registry/demos/chip.js +15 -0
  92. package/registry/demos/chip.tsx +11 -0
  93. package/registry/demos/cn.d.ts +7 -0
  94. package/registry/demos/cn.js +17 -0
  95. package/registry/demos/cn.tsx +9 -0
  96. package/registry/demos/command.d.ts +5 -0
  97. package/registry/demos/command.js +32 -0
  98. package/registry/demos/command.tsx +28 -0
  99. package/registry/demos/confirm-button.d.ts +5 -0
  100. package/registry/demos/confirm-button.js +12 -0
  101. package/registry/demos/confirm-button.tsx +13 -0
  102. package/registry/demos/countdown.d.ts +5 -0
  103. package/registry/demos/countdown.js +13 -0
  104. package/registry/demos/countdown.tsx +10 -0
  105. package/registry/demos/dialog.d.ts +7 -0
  106. package/registry/demos/dialog.js +29 -0
  107. package/registry/demos/dialog.tsx +31 -0
  108. package/registry/demos/dropdown-menu.d.ts +7 -0
  109. package/registry/demos/dropdown-menu.js +36 -0
  110. package/registry/demos/dropdown-menu.tsx +27 -0
  111. package/registry/demos/empty-state.d.ts +5 -0
  112. package/registry/demos/empty-state.js +15 -0
  113. package/registry/demos/empty-state.tsx +12 -0
  114. package/registry/demos/field.d.ts +5 -0
  115. package/registry/demos/field.js +15 -0
  116. package/registry/demos/field.tsx +11 -0
  117. package/registry/demos/kbd.d.ts +5 -0
  118. package/registry/demos/kbd.js +11 -0
  119. package/registry/demos/kbd.tsx +5 -0
  120. package/registry/demos/page-header.d.ts +5 -0
  121. package/registry/demos/page-header.js +11 -0
  122. package/registry/demos/page-header.tsx +5 -0
  123. package/registry/demos/popover.d.ts +7 -0
  124. package/registry/demos/popover.js +25 -0
  125. package/registry/demos/popover.tsx +31 -0
  126. package/registry/demos/progress.d.ts +5 -0
  127. package/registry/demos/progress.js +11 -0
  128. package/registry/demos/progress.tsx +5 -0
  129. package/registry/demos/radio-group.d.ts +5 -0
  130. package/registry/demos/radio-group.js +16 -0
  131. package/registry/demos/radio-group.tsx +14 -0
  132. package/registry/demos/separator.d.ts +5 -0
  133. package/registry/demos/separator.js +15 -0
  134. package/registry/demos/separator.tsx +11 -0
  135. package/registry/demos/skeleton.d.ts +5 -0
  136. package/registry/demos/skeleton.js +20 -0
  137. package/registry/demos/skeleton.tsx +16 -0
  138. package/registry/demos/slider.d.ts +5 -0
  139. package/registry/demos/slider.js +11 -0
  140. package/registry/demos/slider.tsx +5 -0
  141. package/registry/demos/slot.d.ts +5 -0
  142. package/registry/demos/slot.js +14 -0
  143. package/registry/demos/slot.tsx +13 -0
  144. package/registry/demos/spinner.d.ts +5 -0
  145. package/registry/demos/spinner.js +11 -0
  146. package/registry/demos/spinner.tsx +5 -0
  147. package/registry/demos/stat.d.ts +5 -0
  148. package/registry/demos/stat.js +11 -0
  149. package/registry/demos/stat.tsx +5 -0
  150. package/registry/demos/switch.d.ts +5 -0
  151. package/registry/demos/switch.js +11 -0
  152. package/registry/demos/switch.tsx +5 -0
  153. package/registry/demos/tabs.d.ts +5 -0
  154. package/registry/demos/tabs.js +22 -0
  155. package/registry/demos/tabs.tsx +28 -0
  156. package/registry/demos/theme.d.ts +5 -0
  157. package/registry/demos/theme.js +11 -0
  158. package/registry/demos/theme.tsx +9 -0
  159. package/registry/demos/toast.d.ts +8 -0
  160. package/registry/demos/toast.js +29 -0
  161. package/registry/demos/toast.tsx +31 -0
  162. package/registry/demos/tooltip.d.ts +7 -0
  163. package/registry/demos/tooltip.js +15 -0
  164. package/registry/demos/tooltip.tsx +15 -0
  165. package/registry/dialog.json +218 -0
  166. package/registry/dropdown-menu.json +63 -0
  167. package/registry/empty-state.json +59 -0
  168. package/registry/field.json +66 -0
  169. package/registry/index.json +320 -0
  170. package/registry/kbd.json +38 -0
  171. package/registry/page-header.json +66 -0
  172. package/registry/popover.json +44 -0
  173. package/registry/progress.json +80 -0
  174. package/registry/radio-group.json +64 -0
  175. package/registry/separator.json +25 -0
  176. package/registry/skeleton.json +38 -0
  177. package/registry/slider.json +95 -0
  178. package/registry/slot.json +31 -0
  179. package/registry/spinner.json +45 -0
  180. package/registry/stat.json +66 -0
  181. package/registry/switch.json +53 -0
  182. package/registry/tabs.json +44 -0
  183. package/registry/theme.json +78 -0
  184. package/registry/toast.json +54 -0
  185. package/registry/tooltip.json +91 -0
  186. package/dist/chunk-5FRYKFTO.js.map +0 -1
  187. package/dist/chunk-QRG5RYEI.js.map +0 -1
package/dist/native.js CHANGED
@@ -1,6 +1,616 @@
1
+ // src/countdown/core.ts
2
+ import { useSyncExternalStore } from "react";
3
+ var listeners = /* @__PURE__ */ new Set();
4
+ var timer = null;
5
+ function subscribe(listener) {
6
+ listeners.add(listener);
7
+ timer ??= setInterval(() => listeners.forEach((l) => l()), 1e3);
8
+ return () => {
9
+ listeners.delete(listener);
10
+ if (listeners.size === 0 && timer) {
11
+ clearInterval(timer);
12
+ timer = null;
13
+ }
14
+ };
15
+ }
16
+ var nowSecond = () => Math.floor(Date.now() / 1e3) * 1e3;
17
+ function useCountdown(target, skewMs = 0) {
18
+ const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);
19
+ return Math.max(0, new Date(target).getTime() - (now + skewMs));
20
+ }
21
+ function splitDuration(ms) {
22
+ const total = Math.max(0, Math.floor(ms / 1e3));
23
+ return { d: Math.floor(total / 86400), h: Math.floor(total % 86400 / 3600), m: Math.floor(total % 3600 / 60), s: total % 60 };
24
+ }
25
+ function countdownParts(ms, units) {
26
+ const { d, h, m, s } = splitDuration(ms);
27
+ return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];
28
+ }
29
+
30
+ // src/native/avatar.tsx
31
+ import * as React2 from "react";
32
+ import { Image, StyleSheet, Text, View } from "react-native";
33
+
34
+ // ../tokens/dist/native.js
35
+ var themes = Object.freeze({ dark: Object.freeze({
36
+ "surface0": "#0c0c0e",
37
+ "surface1": "#161618",
38
+ "surface2": "#1f1f23",
39
+ "surface3": "#2a2a2d",
40
+ "media": "#1b1b1d",
41
+ "borderSubtle": "rgba(255,255,255,0.06)",
42
+ "borderDefault": "rgba(255,255,255,0.1)",
43
+ "borderStrong": "rgba(255,255,255,0.16)",
44
+ "textPrimary": "#f5f5f5",
45
+ "textSecondary": "#a0a0a7",
46
+ "textMuted": "#73737d",
47
+ "textOnMedia": "#ffffff",
48
+ "accent": "#196df5",
49
+ "accentHover": "#0e5bd8",
50
+ "accentSoft": "rgba(25,109,245,0.1)",
51
+ "accent2": "#196df5",
52
+ "onAccent": "#ffffff",
53
+ "ring": "#196df5",
54
+ "success": "#10b77f",
55
+ "warning": "#f59f0a",
56
+ "danger": "#ef4343",
57
+ "info": "#196df5",
58
+ "scrim": "rgba(0,0,0,0.6)",
59
+ "scrimStrong": "rgba(0,0,0,0.8)",
60
+ "overlay": "rgba(0,0,0,0.7)"
61
+ }), light: Object.freeze({
62
+ "surface0": "#fafafa",
63
+ "surface1": "#ffffff",
64
+ "surface2": "#f1f1f3",
65
+ "surface3": "#e4e4e7",
66
+ "media": "#e9e9ec",
67
+ "borderSubtle": "rgba(0,0,0,0.06)",
68
+ "borderDefault": "rgba(0,0,0,0.1)",
69
+ "borderStrong": "rgba(0,0,0,0.16)",
70
+ "textPrimary": "#18181b",
71
+ "textSecondary": "#64646d",
72
+ "textMuted": "#808089",
73
+ "textOnMedia": "#ffffff",
74
+ "accent": "#0a64f5",
75
+ "accentHover": "#0d55c9",
76
+ "accentSoft": "rgba(10,100,245,0.08)",
77
+ "accent2": "#0a64f5",
78
+ "onAccent": "#ffffff",
79
+ "ring": "#0a64f5",
80
+ "success": "#10b77f",
81
+ "warning": "#f59f0a",
82
+ "danger": "#ef4343",
83
+ "info": "#0a64f5",
84
+ "scrim": "rgba(0,0,0,0.6)",
85
+ "scrimStrong": "rgba(0,0,0,0.8)",
86
+ "overlay": "rgba(0,0,0,0.7)"
87
+ }) });
88
+ var radius = Object.freeze({
89
+ "sm": 8,
90
+ "md": 12,
91
+ "lg": 16,
92
+ "xl": 20,
93
+ "full": 9999
94
+ });
95
+ var typography = Object.freeze({
96
+ "sans": "Inter",
97
+ "display": "Inter",
98
+ "mono": "JetBrains Mono"
99
+ });
100
+ var motion = Object.freeze({ ease: Object.freeze([0.16, 1, 0.3, 1]) });
101
+
102
+ // src/native/theme.tsx
103
+ import * as React from "react";
104
+ import { AccessibilityInfo, useColorScheme } from "react-native";
105
+ import { jsx } from "react/jsx-runtime";
106
+ var themes2 = themes;
107
+ var radius2 = radius;
108
+ var motion2 = motion;
109
+ var ThemeContext = React.createContext(null);
110
+ function resolve(mode, system) {
111
+ if (mode === "system") return system === "light" ? "light" : "dark";
112
+ return mode;
113
+ }
114
+ function ThemeProvider({ children, mode: controlled, defaultMode = "system", onModeChange, overrides, fonts }) {
115
+ const system = useColorScheme();
116
+ const [own, setOwn] = React.useState(defaultMode);
117
+ const mode = controlled ?? own;
118
+ const setMode = React.useCallback(
119
+ (next) => {
120
+ if (controlled === void 0) setOwn(next);
121
+ onModeChange?.(next);
122
+ },
123
+ [controlled, onModeChange]
124
+ );
125
+ const scheme = resolve(mode, system);
126
+ const override = overrides?.[scheme];
127
+ const theme = React.useMemo(() => override ? { ...themes2[scheme], ...override } : themes2[scheme], [scheme, override]);
128
+ const value = React.useMemo(
129
+ () => ({ mode, setMode, scheme, theme, radius: radius2, motion: motion2, fonts: fonts ?? {} }),
130
+ [mode, setMode, scheme, theme, fonts]
131
+ );
132
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
133
+ }
134
+ var noop = () => void 0;
135
+ function useTheme() {
136
+ const context = React.useContext(ThemeContext);
137
+ const system = useColorScheme();
138
+ if (context) return context;
139
+ const scheme = resolve("system", system);
140
+ return { mode: "system", setMode: noop, scheme, theme: themes2[scheme], radius: radius2, motion: motion2, fonts: {} };
141
+ }
142
+ function useReducedMotion() {
143
+ const [reduce, setReduce] = React.useState(false);
144
+ React.useEffect(() => {
145
+ let alive = true;
146
+ void AccessibilityInfo.isReduceMotionEnabled().then((value) => {
147
+ if (alive) setReduce(value);
148
+ });
149
+ const subscription = AccessibilityInfo.addEventListener("reduceMotionChanged", setReduce);
150
+ return () => {
151
+ alive = false;
152
+ subscription.remove();
153
+ };
154
+ }, []);
155
+ return reduce;
156
+ }
157
+ function alpha(color, opacity) {
158
+ const hex = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color);
159
+ if (!hex) return color;
160
+ const [r, g, b] = hex.slice(1).map((part) => parseInt(part, 16));
161
+ return `rgba(${r},${g},${b},${opacity})`;
162
+ }
163
+ function useSvgId(prefix) {
164
+ return `${prefix}${React.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
165
+ }
166
+
167
+ // src/native/avatar.tsx
168
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
169
+ var SIDE = { xs: 20, sm: 32, md: 40, lg: 56, xl: 80 };
170
+ function AvatarRoot({ src, alt = "", fallback, size = "md", style, ...props }) {
171
+ const { theme } = useTheme();
172
+ const [failedSrc, setFailedSrc] = React2.useState(null);
173
+ const failed = Boolean(src) && failedSrc === src;
174
+ const side = typeof size === "number" ? size : SIDE[size];
175
+ const initial = alt.trim().charAt(0).toUpperCase();
176
+ const content = fallback ?? initial;
177
+ return /* @__PURE__ */ jsx2(
178
+ View,
179
+ {
180
+ accessible: Boolean(alt),
181
+ role: alt ? "img" : void 0,
182
+ "aria-label": alt || void 0,
183
+ ...props,
184
+ style: [styles.root, { width: side, height: side, borderRadius: side / 2, backgroundColor: theme.surface3 }, style],
185
+ children: src && !failed ? /* @__PURE__ */ jsx2(Image, { testID: props.testID ? `${props.testID}.image` : void 0, source: { uri: src }, onError: () => setFailedSrc(src), resizeMode: "cover", style: StyleSheet.absoluteFill }) : typeof content === "string" ? /* @__PURE__ */ jsx2(Text, { style: [styles.initial, { color: theme.textSecondary, fontSize: Math.max(9, Math.round(side * 0.4)) }], children: content }) : content
186
+ }
187
+ );
188
+ }
189
+ function AvatarGroup({ max, size = "md", style, children, ...props }) {
190
+ const { theme } = useTheme();
191
+ const items2 = React2.Children.toArray(children);
192
+ const shown = max === void 0 ? items2 : items2.slice(0, max);
193
+ const rest = items2.length - shown.length;
194
+ const side = typeof size === "number" ? size : SIDE[size];
195
+ const ring = { borderWidth: 2, borderColor: theme.surface0, marginLeft: -side / 5 };
196
+ return /* @__PURE__ */ jsxs(View, { ...props, style: [styles.group, { paddingLeft: side / 5 }, style], children: [
197
+ shown.map((child, i) => /* @__PURE__ */ jsx2(View, { style: [ring, { borderRadius: side }], children: React2.isValidElement(child) ? React2.cloneElement(child, { size }) : child }, i)),
198
+ rest > 0 ? /* @__PURE__ */ jsx2(View, { style: [ring, { borderRadius: side }], children: /* @__PURE__ */ jsx2(AvatarRoot, { size, fallback: `+${rest}` }) }) : null
199
+ ] });
200
+ }
201
+ var Avatar = Object.assign(AvatarRoot, { Group: AvatarGroup });
202
+ var styles = StyleSheet.create({
203
+ root: { overflow: "hidden", alignItems: "center", justifyContent: "center" },
204
+ initial: { fontWeight: "700" },
205
+ group: { flexDirection: "row", alignItems: "center" }
206
+ });
207
+
208
+ // src/native/badge.tsx
209
+ import * as React3 from "react";
210
+ import { Animated, StyleSheet as StyleSheet2, Text as Text2 } from "react-native";
211
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
212
+ function look(tone2, t) {
213
+ switch (tone2) {
214
+ case "accent":
215
+ return { bg: t.accentSoft, fg: t.textPrimary, border: alpha(t.accent, 0.4), dot: t.accent };
216
+ case "success":
217
+ case "warning":
218
+ case "danger":
219
+ return { bg: alpha(t[tone2], 0.15), fg: t.textPrimary, border: alpha(t[tone2], 0.4), dot: t[tone2] };
220
+ case "scrim":
221
+ return { bg: t.scrim, fg: t.textOnMedia, border: "transparent", dot: t.textOnMedia };
222
+ default:
223
+ return { bg: t.surface3, fg: t.textSecondary, border: "transparent", dot: t.textSecondary };
224
+ }
225
+ }
226
+ function Badge({ tone: tone2 = "neutral", size = "sm", dot, pulse, style, children, ...props }) {
227
+ const { theme } = useTheme();
228
+ const colors = look(tone2, theme);
229
+ const reduce = useReducedMotion();
230
+ const [opacity] = React3.useState(() => new Animated.Value(1));
231
+ React3.useEffect(() => {
232
+ if (!dot || !pulse || reduce) return;
233
+ const loop = Animated.loop(
234
+ Animated.sequence([
235
+ Animated.timing(opacity, { toValue: 0.35, duration: 800, useNativeDriver: true }),
236
+ Animated.timing(opacity, { toValue: 1, duration: 800, useNativeDriver: true })
237
+ ])
238
+ );
239
+ loop.start();
240
+ return () => {
241
+ loop.stop();
242
+ opacity.setValue(1);
243
+ };
244
+ }, [dot, pulse, reduce, opacity]);
245
+ return /* @__PURE__ */ jsxs2(
246
+ Animated.View,
247
+ {
248
+ ...props,
249
+ style: [styles2.root, size === "md" ? styles2.md : styles2.sm, { backgroundColor: colors.bg, borderColor: colors.border }, style],
250
+ children: [
251
+ dot ? /* @__PURE__ */ jsx3(Animated.View, { "aria-hidden": true, style: [styles2.dot, { backgroundColor: colors.dot, opacity }] }) : null,
252
+ typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx3(Text2, { style: [styles2.text, { color: colors.fg, fontSize: size === "md" ? 11 : 10 }], children }) : children
253
+ ]
254
+ }
255
+ );
256
+ }
257
+ var styles2 = StyleSheet2.create({
258
+ root: { flexDirection: "row", alignItems: "center", alignSelf: "flex-start", gap: 4, borderRadius: 9999, borderWidth: 1 },
259
+ sm: { paddingHorizontal: 8, paddingVertical: 2 },
260
+ md: { paddingHorizontal: 10, paddingVertical: 4 },
261
+ dot: { width: 6, height: 6, borderRadius: 3 },
262
+ text: { fontWeight: "700", textTransform: "uppercase", letterSpacing: 0.8 }
263
+ });
264
+
265
+ // src/native/button.tsx
266
+ import { ActivityIndicator, Pressable, StyleSheet as StyleSheet4, View as View2 } from "react-native";
267
+
268
+ // src/native/txt.tsx
269
+ import { StyleSheet as StyleSheet3, Text as Text3 } from "react-native";
270
+ import { jsx as jsx4 } from "react/jsx-runtime";
271
+ var TONE = {
272
+ text: "textPrimary",
273
+ secondary: "textSecondary",
274
+ muted: "textMuted",
275
+ accent: "accent",
276
+ success: "success",
277
+ warning: "warning",
278
+ danger: "danger",
279
+ onAccent: "onAccent",
280
+ onMedia: "textOnMedia"
281
+ };
282
+ function Txt({ variant = "body", tone: tone2 = "text", style, ...props }) {
283
+ const { theme, fonts } = useTheme();
284
+ const family = variant === "display" || variant === "title" ? fonts.display : variant === "mono" ? fonts.mono : fonts.sans;
285
+ return /* @__PURE__ */ jsx4(
286
+ Text3,
287
+ {
288
+ role: variant === "display" || variant === "title" ? "heading" : void 0,
289
+ ...props,
290
+ style: [styles3[variant], { color: theme[TONE[tone2]] }, family ? { fontFamily: family } : null, style]
291
+ }
292
+ );
293
+ }
294
+ var textStyles = StyleSheet3.create({
295
+ display: { fontSize: 30, lineHeight: 36, fontWeight: "900", letterSpacing: -0.5 },
296
+ title: { fontSize: 18, lineHeight: 24, fontWeight: "800" },
297
+ body: { fontSize: 15, lineHeight: 21 },
298
+ caption: { fontSize: 12, lineHeight: 16 },
299
+ label: { fontSize: 14, lineHeight: 18, fontWeight: "700" },
300
+ mono: { fontSize: 14, lineHeight: 18, fontWeight: "700", fontVariant: ["tabular-nums"] }
301
+ });
302
+ var styles3 = textStyles;
303
+
304
+ // src/native/button.tsx
305
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
306
+ function look2(variant, t) {
307
+ switch (variant) {
308
+ case "primary":
309
+ return { bg: t.accent, fg: t.onAccent, border: t.accent };
310
+ case "outline":
311
+ return { bg: "transparent", fg: t.textPrimary, border: t.borderDefault };
312
+ case "ghost":
313
+ return { bg: "transparent", fg: t.textSecondary, border: "transparent" };
314
+ case "danger":
315
+ return { bg: alpha(t.danger, 0.1), fg: t.textPrimary, border: alpha(t.danger, 0.5) };
316
+ default:
317
+ return { bg: t.surface2, fg: t.textPrimary, border: t.borderDefault };
318
+ }
319
+ }
320
+ var HEIGHT = { sm: 32, md: 40, lg: 48 };
321
+ var PADDING = { sm: 12, md: 16, lg: 24 };
322
+ function useButton({ variant = "secondary", size = "md", shape = "rounded", loading, disabled }) {
323
+ const { theme, radius: radius3 } = useTheme();
324
+ const colors = look2(variant, theme);
325
+ const inactive = Boolean(disabled || loading);
326
+ const frame = (pressed) => ({
327
+ height: HEIGHT[size],
328
+ borderRadius: shape === "pill" ? radius3.full : radius3.sm,
329
+ backgroundColor: colors.bg,
330
+ borderColor: colors.border,
331
+ opacity: inactive ? 0.4 : pressed ? 0.85 : 1,
332
+ transform: [{ scale: pressed ? 0.98 : 1 }]
333
+ });
334
+ return { colors, inactive, frame };
335
+ }
336
+ function Button({ label, icon, variant, size = "md", shape, loading = false, disabled, style, ...props }) {
337
+ const { colors, inactive, frame } = useButton({ variant, size, shape, loading, disabled });
338
+ return /* @__PURE__ */ jsx5(
339
+ Pressable,
340
+ {
341
+ role: "button",
342
+ "aria-label": label,
343
+ "aria-disabled": inactive,
344
+ "aria-busy": loading,
345
+ ...props,
346
+ disabled: inactive,
347
+ style: ({ pressed }) => [styles4.base, { paddingHorizontal: PADDING[size] }, frame(pressed), style],
348
+ children: /* @__PURE__ */ jsxs3(View2, { style: styles4.row, children: [
349
+ loading ? /* @__PURE__ */ jsx5(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon,
350
+ /* @__PURE__ */ jsx5(Txt, { variant: "label", numberOfLines: 1, style: { color: colors.fg, fontSize: size === "sm" ? 12 : 14 }, children: label })
351
+ ] })
352
+ }
353
+ );
354
+ }
355
+ function IconButton({ label, icon, variant, size = "md", shape, loading = false, disabled, style, ...props }) {
356
+ const { colors, inactive, frame } = useButton({ variant, size, shape, loading, disabled });
357
+ const side = HEIGHT[size];
358
+ return /* @__PURE__ */ jsx5(
359
+ Pressable,
360
+ {
361
+ role: "button",
362
+ "aria-label": label,
363
+ "aria-disabled": inactive,
364
+ "aria-busy": loading,
365
+ hitSlop: side < 44 ? (44 - side) / 2 : void 0,
366
+ ...props,
367
+ disabled: inactive,
368
+ style: ({ pressed }) => [styles4.base, frame(pressed), { width: side }, style],
369
+ children: loading ? /* @__PURE__ */ jsx5(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon
370
+ }
371
+ );
372
+ }
373
+ var styles4 = StyleSheet4.create({
374
+ base: { alignItems: "center", justifyContent: "center", borderWidth: 1 },
375
+ row: { flexDirection: "row", alignItems: "center", gap: 8 }
376
+ });
377
+
378
+ // src/native/card.tsx
379
+ import { Image as Image2, Pressable as Pressable2, StyleSheet as StyleSheet5, View as View3 } from "react-native";
380
+ import { jsx as jsx6 } from "react/jsx-runtime";
381
+ function CardRoot({ tone: tone2 = "default", radius: radius3 = "xl", onPress, style, ...props }) {
382
+ const { theme, radius: r } = useTheme();
383
+ const frame = [
384
+ styles5.root,
385
+ {
386
+ backgroundColor: tone2 === "elevated" ? theme.surface2 : theme.surface1,
387
+ borderColor: theme.borderDefault,
388
+ borderRadius: r[radius3]
389
+ },
390
+ tone2 === "elevated" ? [styles5.shadow, { shadowColor: theme.scrimStrong }] : null
391
+ ];
392
+ if (!onPress) return /* @__PURE__ */ jsx6(View3, { ...props, style: [frame, style] });
393
+ return /* @__PURE__ */ jsx6(
394
+ Pressable2,
395
+ {
396
+ role: "button",
397
+ onPress,
398
+ ...props,
399
+ style: ({ pressed }) => [frame, { opacity: pressed ? 0.92 : 1, transform: [{ scale: pressed ? 0.99 : 1 }] }, style]
400
+ }
401
+ );
402
+ }
403
+ var ASPECT = { video: 16 / 9, square: 1, portrait: 3 / 4 };
404
+ function CardMedia({ aspect = "video", style, ...props }) {
405
+ const { theme } = useTheme();
406
+ return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.media, { backgroundColor: theme.media }, aspect === "auto" ? null : { aspectRatio: ASPECT[aspect] }, style] });
407
+ }
408
+ function CardImage({ src, fallback, alt, style, ...props }) {
409
+ const { theme } = useTheme();
410
+ if (!src) {
411
+ return /* @__PURE__ */ jsx6(View3, { "aria-hidden": true, style: [StyleSheet5.absoluteFill, styles5.center, { backgroundColor: theme.accentSoft }], children: fallback });
412
+ }
413
+ return /* @__PURE__ */ jsx6(Image2, { accessible: Boolean(alt), alt, "aria-label": alt, resizeMode: "cover", ...props, source: { uri: src }, style: [StyleSheet5.absoluteFill, style] });
414
+ }
415
+ var CORNER = {
416
+ "top-left": { top: 10, left: 10 },
417
+ "top-right": { top: 10, right: 10 },
418
+ "bottom-left": { bottom: 10, left: 10 },
419
+ "bottom-right": { bottom: 10, right: 10 }
420
+ };
421
+ function CardOverlay({ corner = "top-left", style, ...props }) {
422
+ return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.overlay, CORNER[corner], style] });
423
+ }
424
+ var PADDING2 = { none: 0, sm: 12, md: 16, lg: 24 };
425
+ function CardBody({ padding = "md", style, ...props }) {
426
+ return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.body, { padding: PADDING2[padding] }, style] });
427
+ }
428
+ function CardTitle({ numberOfLines = 1, ...props }) {
429
+ return /* @__PURE__ */ jsx6(Txt, { variant: "label", role: "heading", numberOfLines, ...props });
430
+ }
431
+ function CardDescription({ numberOfLines = 2, ...props }) {
432
+ return /* @__PURE__ */ jsx6(Txt, { variant: "caption", tone: "secondary", numberOfLines, ...props });
433
+ }
434
+ function CardFooter({ style, ...props }) {
435
+ const { theme } = useTheme();
436
+ return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.footer, { borderTopColor: theme.borderSubtle }, style] });
437
+ }
438
+ var Card = {
439
+ Root: CardRoot,
440
+ Media: CardMedia,
441
+ Image: CardImage,
442
+ Overlay: CardOverlay,
443
+ Body: CardBody,
444
+ Title: CardTitle,
445
+ Description: CardDescription,
446
+ Footer: CardFooter
447
+ };
448
+ var styles5 = StyleSheet5.create({
449
+ root: { overflow: "hidden", borderWidth: StyleSheet5.hairlineWidth },
450
+ shadow: { shadowOpacity: 0.25, shadowRadius: 12, shadowOffset: { width: 0, height: 6 }, elevation: 4 },
451
+ media: { position: "relative", overflow: "hidden", width: "100%" },
452
+ center: { alignItems: "center", justifyContent: "center" },
453
+ overlay: { position: "absolute", zIndex: 1, flexDirection: "row", alignItems: "center", gap: 6 },
454
+ body: { gap: 12 },
455
+ footer: { flexDirection: "row", alignItems: "center", gap: 8, borderTopWidth: StyleSheet5.hairlineWidth, paddingTop: 12, marginTop: "auto" }
456
+ });
457
+
458
+ // src/native/chip.tsx
459
+ import * as React4 from "react";
460
+ import { Pressable as Pressable3, ScrollView, StyleSheet as StyleSheet6, Text as Text4, View as View4 } from "react-native";
461
+ import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
462
+ var ChipGroupContext = React4.createContext(null);
463
+ function Label({ children, color, size }) {
464
+ if (typeof children !== "string" && typeof children !== "number") return /* @__PURE__ */ jsx7(Fragment, { children });
465
+ return /* @__PURE__ */ jsx7(Text4, { style: [styles6.label, { color, fontSize: size === "sm" ? 12 : 13 }], children });
466
+ }
467
+ function ChipBase(props) {
468
+ const group = React4.useContext(ChipGroupContext);
469
+ const { theme, radius: radius3 } = useTheme();
470
+ const [own, setOwn] = React4.useState(props.removable ? false : props.defaultSelected ?? false);
471
+ const size = props.size ?? group?.size ?? "md";
472
+ const frame = (on2, pressed) => ({
473
+ height: size === "sm" ? 28 : 36,
474
+ borderRadius: radius3.full,
475
+ borderColor: on2 ? theme.accent : theme.borderDefault,
476
+ backgroundColor: on2 ? theme.accentSoft : theme.surface1,
477
+ opacity: pressed ? 0.85 : 1
478
+ });
479
+ if (props.removable) {
480
+ const { removable: _r2, removeLabel, onRemove, disabled: disabled2, size: _s2, style: style2, children: children2, ...rest2 } = props;
481
+ return /* @__PURE__ */ jsxs4(View4, { ...rest2, style: [styles6.base, frame(false, false), disabled2 ? styles6.disabled : null, style2], children: [
482
+ /* @__PURE__ */ jsx7(Label, { color: theme.textSecondary, size, children: children2 }),
483
+ /* @__PURE__ */ jsx7(Pressable3, { role: "button", "aria-label": removeLabel, disabled: disabled2 ?? void 0, hitSlop: 10, onPress: onRemove, style: styles6.remove, children: /* @__PURE__ */ jsx7(Text4, { style: [styles6.cross, { color: theme.textSecondary }], children: "\xD7" }) })
484
+ ] });
485
+ }
486
+ const { removable: _r, value, selected, defaultSelected: _d, onSelectedChange, disabled: ownDisabled, size: _s, style, children, ...rest } = props;
487
+ if (group && value === void 0) throw new Error("Chip: a chip inside Chip.Group needs a `value`.");
488
+ const on = group ? group.isSelected(value) : selected ?? own;
489
+ const disabled = Boolean(ownDisabled || group?.disabled);
490
+ const press = () => {
491
+ if (group) return group.toggle(value);
492
+ if (selected === void 0) setOwn(!on);
493
+ onSelectedChange?.(!on);
494
+ };
495
+ const single = group?.type === "single";
496
+ return /* @__PURE__ */ jsx7(
497
+ Pressable3,
498
+ {
499
+ role: single ? "radio" : "checkbox",
500
+ "aria-checked": on,
501
+ "aria-disabled": disabled,
502
+ ...rest,
503
+ disabled,
504
+ onPress: press,
505
+ style: ({ pressed }) => [styles6.base, frame(on, pressed), disabled ? styles6.disabled : null, style],
506
+ children: /* @__PURE__ */ jsx7(Label, { color: on ? theme.textPrimary : theme.textSecondary, size, children })
507
+ }
508
+ );
509
+ }
510
+ function ChipGroup(props) {
511
+ const { size, disabled, scrollable, "aria-label": label, style, children } = props;
512
+ const initial = props.type === "single" ? props.defaultValue ?? "" : props.defaultValue ?? [];
513
+ const [own, setOwn] = React4.useState(initial);
514
+ const current = props.value ?? own;
515
+ const context = React4.useMemo(() => {
516
+ const list = Array.isArray(current) ? current : [current];
517
+ return {
518
+ type: props.type,
519
+ size,
520
+ disabled,
521
+ isSelected: (v) => list.includes(v),
522
+ toggle: (v) => {
523
+ const next = props.type === "single" ? v : list.includes(v) ? list.filter((x) => x !== v) : [...list, v];
524
+ if (props.value === void 0) setOwn(next);
525
+ props.onValueChange?.(next);
526
+ }
527
+ };
528
+ }, [current, props.type, props.value, props.onValueChange, size, disabled]);
529
+ const a11y = { role: props.type === "single" ? "radiogroup" : "group", "aria-label": label };
530
+ return /* @__PURE__ */ jsx7(ChipGroupContext.Provider, { value: context, children: scrollable ? /* @__PURE__ */ jsx7(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, ...a11y, style, contentContainerStyle: styles6.row, children }) : /* @__PURE__ */ jsx7(View4, { ...a11y, style: [styles6.row, styles6.wrap, style], children }) });
531
+ }
532
+ var Chip = Object.assign(ChipBase, { Group: ChipGroup });
533
+ var styles6 = StyleSheet6.create({
534
+ base: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6, paddingHorizontal: 14, borderWidth: 1, alignSelf: "flex-start" },
535
+ label: { fontWeight: "600" },
536
+ remove: { marginRight: -6, width: 24, height: 24, alignItems: "center", justifyContent: "center" },
537
+ cross: { fontSize: 16, lineHeight: 18, fontWeight: "700" },
538
+ disabled: { opacity: 0.4 },
539
+ row: { flexDirection: "row", alignItems: "center", gap: 8 },
540
+ wrap: { flexWrap: "wrap" }
541
+ });
542
+
543
+ // src/native/countdown.tsx
544
+ import * as React5 from "react";
545
+ import { Animated as Animated2, StyleSheet as StyleSheet7, Text as Text5 } from "react-native";
546
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
547
+ var FONT = { sm: 14, md: 20, lg: 32 };
548
+ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md", label, style }) {
549
+ const { theme, fonts } = useTheme();
550
+ const reduce = useReducedMotion();
551
+ const ms = useCountdown(target, skewMs);
552
+ const urgent = ms > 0 && ms < urgentBelowMs;
553
+ const parts = countdownParts(ms, units);
554
+ const [opacity] = React5.useState(() => new Animated2.Value(1));
555
+ React5.useEffect(() => {
556
+ if (!urgent || reduce) return;
557
+ const loop = Animated2.loop(
558
+ Animated2.sequence([
559
+ Animated2.timing(opacity, { toValue: 0.4, duration: 500, useNativeDriver: true }),
560
+ Animated2.timing(opacity, { toValue: 1, duration: 500, useNativeDriver: true })
561
+ ])
562
+ );
563
+ loop.start();
564
+ return () => {
565
+ loop.stop();
566
+ opacity.setValue(1);
567
+ };
568
+ }, [urgent, reduce, opacity]);
569
+ const color = urgent ? theme.danger : theme.textPrimary;
570
+ const text = parts.map(([value, unit]) => `${String(value).padStart(2, "0")}${unit}`).join(" ");
571
+ return /* @__PURE__ */ jsx8(
572
+ Animated2.View,
573
+ {
574
+ accessible: true,
575
+ role: "timer",
576
+ "aria-label": `${label} ${text}`,
577
+ style: [styles7.root, style],
578
+ children: parts.map(([value, unit], i) => /* @__PURE__ */ jsxs5(Animated2.View, { style: [styles7.segment, urgent && i === parts.length - 1 ? { opacity } : null], children: [
579
+ /* @__PURE__ */ jsx8(Text5, { style: [styles7.value, { color, fontSize: FONT[size] }, fonts.display ? { fontFamily: fonts.display } : null], children: String(value).padStart(2, "0") }),
580
+ /* @__PURE__ */ jsx8(Text5, { style: [styles7.unit, { color: theme.textSecondary, fontSize: Math.round(FONT[size] / 2) }], children: unit })
581
+ ] }, unit))
582
+ }
583
+ );
584
+ }
585
+ var styles7 = StyleSheet7.create({
586
+ root: { flexDirection: "row", alignItems: "baseline", gap: 6 },
587
+ segment: { flexDirection: "row", alignItems: "baseline" },
588
+ value: { fontWeight: "900", fontVariant: ["tabular-nums"], letterSpacing: -0.3 },
589
+ unit: { marginLeft: 2, fontWeight: "700", textTransform: "uppercase" }
590
+ });
591
+
592
+ // src/native/empty-state.tsx
593
+ import { StyleSheet as StyleSheet8, View as View5 } from "react-native";
594
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
595
+ function EmptyState({ icon, title, description, action, style, ...props }) {
596
+ const { theme } = useTheme();
597
+ return /* @__PURE__ */ jsxs6(View5, { ...props, style: [styles8.root, style], children: [
598
+ icon ? /* @__PURE__ */ jsx9(View5, { "aria-hidden": true, style: [styles8.icon, { backgroundColor: theme.surface2 }], children: icon }) : null,
599
+ /* @__PURE__ */ jsx9(Txt, { variant: "label", role: "heading", style: styles8.center, children: title }),
600
+ description ? /* @__PURE__ */ jsx9(Txt, { tone: "secondary", style: styles8.center, children: description }) : null,
601
+ action ? /* @__PURE__ */ jsx9(View5, { style: styles8.action, children: action }) : null
602
+ ] });
603
+ }
604
+ var styles8 = StyleSheet8.create({
605
+ root: { alignItems: "center", justifyContent: "center", gap: 8, paddingVertical: 40, paddingHorizontal: 24 },
606
+ icon: { width: 48, height: 48, borderRadius: 24, alignItems: "center", justifyContent: "center", marginBottom: 4 },
607
+ center: { textAlign: "center", maxWidth: 360 },
608
+ action: { marginTop: 8, flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8 }
609
+ });
610
+
1
611
  // src/native/OrochiaMark.tsx
2
- import { useEffect, useState } from "react";
3
- import { AccessibilityInfo, Animated, Easing, View } from "react-native";
612
+ import { useEffect as useEffect4, useState as useState6 } from "react";
613
+ import { AccessibilityInfo as AccessibilityInfo2, Animated as Animated3, Easing, View as View6 } from "react-native";
4
614
  import Svg, { Circle, Defs, Ellipse, G as Group, LinearGradient, Path, RadialGradient, Stop } from "react-native-svg";
5
615
 
6
616
  // src/marks/orochia-geometry.ts
@@ -28,23 +638,23 @@ var OROCHIA = {
28
638
  };
29
639
 
30
640
  // src/native/OrochiaMark.tsx
31
- import { jsx, jsxs } from "react/jsx-runtime";
641
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
32
642
  var CENTER = OROCHIA.offset + 180;
33
643
  function OrochiaMark({ size = 48, animated = true, title, neutral = "rgba(255,255,255,0.35)" }) {
34
- const [spin] = useState(() => new Animated.Value(0));
35
- const [pulse] = useState(() => new Animated.Value(0));
36
- useEffect(() => {
644
+ const [spin] = useState6(() => new Animated3.Value(0));
645
+ const [pulse] = useState6(() => new Animated3.Value(0));
646
+ useEffect4(() => {
37
647
  if (!animated) return;
38
648
  let loops = [];
39
649
  let cancelled = false;
40
- void AccessibilityInfo.isReduceMotionEnabled().then((reduce) => {
650
+ void AccessibilityInfo2.isReduceMotionEnabled().then((reduce) => {
41
651
  if (reduce || cancelled) return;
42
652
  loops = [
43
- Animated.loop(Animated.timing(spin, { toValue: 1, duration: 3e4, easing: Easing.linear, useNativeDriver: true })),
44
- Animated.loop(
45
- Animated.sequence([
46
- Animated.timing(pulse, { toValue: 1, duration: 1600, easing: Easing.inOut(Easing.ease), useNativeDriver: true }),
47
- Animated.timing(pulse, { toValue: 0, duration: 1600, easing: Easing.inOut(Easing.ease), useNativeDriver: true })
653
+ Animated3.loop(Animated3.timing(spin, { toValue: 1, duration: 3e4, easing: Easing.linear, useNativeDriver: true })),
654
+ Animated3.loop(
655
+ Animated3.sequence([
656
+ Animated3.timing(pulse, { toValue: 1, duration: 1600, easing: Easing.inOut(Easing.ease), useNativeDriver: true }),
657
+ Animated3.timing(pulse, { toValue: 0, duration: 1600, easing: Easing.inOut(Easing.ease), useNativeDriver: true })
48
658
  ])
49
659
  )
50
660
  ];
@@ -58,38 +668,397 @@ function OrochiaMark({ size = 48, animated = true, title, neutral = "rgba(255,25
58
668
  const viewBox = size < 48 ? OROCHIA.croppedViewBox : OROCHIA.viewBox;
59
669
  const layer = { position: "absolute", width: size, height: size };
60
670
  const a11y = title ? { accessible: true, accessibilityRole: "image", accessibilityLabel: title } : { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" };
61
- const bodyGradient = /* @__PURE__ */ jsx(LinearGradient, { id: "body", gradientUnits: "userSpaceOnUse", x1: OROCHIA.body.x1 + OROCHIA.offset, y1: OROCHIA.body.y1 + OROCHIA.offset, x2: OROCHIA.body.x2 + OROCHIA.offset, y2: OROCHIA.body.y2 + OROCHIA.offset, children: OROCHIA.body.stops.map(([offset, color]) => /* @__PURE__ */ jsx(Stop, { offset, stopColor: color }, offset)) });
62
- return /* @__PURE__ */ jsxs(View, { style: { width: size, height: size }, ...a11y, children: [
63
- /* @__PURE__ */ jsxs(Svg, { viewBox, style: layer, children: [
64
- /* @__PURE__ */ jsx(Defs, { children: /* @__PURE__ */ jsxs(RadialGradient, { id: "glow", cx: "50%", cy: "50%", r: "50%", children: [
65
- /* @__PURE__ */ jsx(Stop, { offset: "0%", stopColor: OROCHIA.glow.color, stopOpacity: OROCHIA.glow.opacity }),
66
- /* @__PURE__ */ jsx(Stop, { offset: "100%", stopColor: OROCHIA.glow.color, stopOpacity: 0 })
671
+ const bodyGradient = /* @__PURE__ */ jsx10(LinearGradient, { id: "body", gradientUnits: "userSpaceOnUse", x1: OROCHIA.body.x1 + OROCHIA.offset, y1: OROCHIA.body.y1 + OROCHIA.offset, x2: OROCHIA.body.x2 + OROCHIA.offset, y2: OROCHIA.body.y2 + OROCHIA.offset, children: OROCHIA.body.stops.map(([offset, color]) => /* @__PURE__ */ jsx10(Stop, { offset, stopColor: color }, offset)) });
672
+ return /* @__PURE__ */ jsxs7(View6, { style: { width: size, height: size }, ...a11y, children: [
673
+ /* @__PURE__ */ jsxs7(Svg, { viewBox, style: layer, children: [
674
+ /* @__PURE__ */ jsx10(Defs, { children: /* @__PURE__ */ jsxs7(RadialGradient, { id: "glow", cx: "50%", cy: "50%", r: "50%", children: [
675
+ /* @__PURE__ */ jsx10(Stop, { offset: "0%", stopColor: OROCHIA.glow.color, stopOpacity: OROCHIA.glow.opacity }),
676
+ /* @__PURE__ */ jsx10(Stop, { offset: "100%", stopColor: OROCHIA.glow.color, stopOpacity: 0 })
67
677
  ] }) }),
68
- /* @__PURE__ */ jsx(Circle, { cx: CENTER, cy: CENTER, r: 170, fill: "url(#glow)" }),
69
- /* @__PURE__ */ jsx(Circle, { cx: CENTER, cy: CENTER, r: OROCHIA.ring.r, stroke: neutral, strokeWidth: OROCHIA.ring.width, opacity: 0.35, fill: "none" })
678
+ /* @__PURE__ */ jsx10(Circle, { cx: CENTER, cy: CENTER, r: 170, fill: "url(#glow)" }),
679
+ /* @__PURE__ */ jsx10(Circle, { cx: CENTER, cy: CENTER, r: OROCHIA.ring.r, stroke: neutral, strokeWidth: OROCHIA.ring.width, opacity: 0.35, fill: "none" })
70
680
  ] }),
71
- /* @__PURE__ */ jsx(Animated.View, { style: [layer, { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] }], children: /* @__PURE__ */ jsx(Svg, { viewBox, style: layer, children: /* @__PURE__ */ jsx(Circle, { cx: CENTER, cy: CENTER, r: OROCHIA.orbit.r, stroke: neutral, strokeWidth: OROCHIA.orbit.width, strokeDasharray: OROCHIA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
72
- /* @__PURE__ */ jsxs(Svg, { viewBox, style: layer, children: [
73
- /* @__PURE__ */ jsx(Defs, { children: bodyGradient }),
74
- /* @__PURE__ */ jsxs(Group, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
75
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.arc, stroke: "url(#body)", strokeWidth: 22, strokeLinecap: "round", fill: "none" }),
76
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.arc, stroke: OROCHIA.scales.color, strokeOpacity: OROCHIA.scales.opacity, strokeWidth: OROCHIA.scales.width, strokeLinecap: "round", strokeDasharray: OROCHIA.scales.dash, fill: "none" }),
77
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.neck, stroke: "url(#body)", strokeWidth: 14, strokeLinecap: "round", fill: "none" }),
78
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.tail, stroke: "url(#body)", strokeWidth: 6, strokeLinecap: "round", fill: "none" }),
79
- /* @__PURE__ */ jsx(Ellipse, { cx: OROCHIA.head.cx, cy: OROCHIA.head.cy, rx: OROCHIA.head.rx, ry: OROCHIA.head.ry, rotation: OROCHIA.head.rotate, origin: `${OROCHIA.head.cx}, ${OROCHIA.head.cy}`, fill: "url(#body)" }),
80
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.tongue.d, stroke: OROCHIA.tongue.color, strokeWidth: 3, strokeLinecap: "round", fill: "none" })
681
+ /* @__PURE__ */ jsx10(Animated3.View, { style: [layer, { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] }], children: /* @__PURE__ */ jsx10(Svg, { viewBox, style: layer, children: /* @__PURE__ */ jsx10(Circle, { cx: CENTER, cy: CENTER, r: OROCHIA.orbit.r, stroke: neutral, strokeWidth: OROCHIA.orbit.width, strokeDasharray: OROCHIA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
682
+ /* @__PURE__ */ jsxs7(Svg, { viewBox, style: layer, children: [
683
+ /* @__PURE__ */ jsx10(Defs, { children: bodyGradient }),
684
+ /* @__PURE__ */ jsxs7(Group, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
685
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.arc, stroke: "url(#body)", strokeWidth: 22, strokeLinecap: "round", fill: "none" }),
686
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.arc, stroke: OROCHIA.scales.color, strokeOpacity: OROCHIA.scales.opacity, strokeWidth: OROCHIA.scales.width, strokeLinecap: "round", strokeDasharray: OROCHIA.scales.dash, fill: "none" }),
687
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.neck, stroke: "url(#body)", strokeWidth: 14, strokeLinecap: "round", fill: "none" }),
688
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.tail, stroke: "url(#body)", strokeWidth: 6, strokeLinecap: "round", fill: "none" }),
689
+ /* @__PURE__ */ jsx10(Ellipse, { cx: OROCHIA.head.cx, cy: OROCHIA.head.cy, rx: OROCHIA.head.rx, ry: OROCHIA.head.ry, rotation: OROCHIA.head.rotate, origin: `${OROCHIA.head.cx}, ${OROCHIA.head.cy}`, fill: "url(#body)" }),
690
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.tongue.d, stroke: OROCHIA.tongue.color, strokeWidth: 3, strokeLinecap: "round", fill: "none" })
81
691
  ] })
82
692
  ] }),
83
- /* @__PURE__ */ jsx(Animated.View, { style: [layer, { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }], children: /* @__PURE__ */ jsxs(Svg, { viewBox, style: layer, children: [
84
- /* @__PURE__ */ jsx(Defs, { children: /* @__PURE__ */ jsx(LinearGradient, { id: "flame", x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: OROCHIA.flameGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx(Stop, { offset, stopColor: color }, offset)) }) }),
85
- /* @__PURE__ */ jsxs(Group, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
86
- /* @__PURE__ */ jsx(Circle, { cx: OROCHIA.eye.cx, cy: OROCHIA.eye.cy, r: OROCHIA.eye.r, fill: OROCHIA.eye.color }),
87
- /* @__PURE__ */ jsx(Path, { d: OROCHIA.flame.d, transform: `translate(${OROCHIA.flame.translate[0]} ${OROCHIA.flame.translate[1]}) scale(${OROCHIA.flame.scale})`, fill: "url(#flame)" })
693
+ /* @__PURE__ */ jsx10(Animated3.View, { style: [layer, { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }], children: /* @__PURE__ */ jsxs7(Svg, { viewBox, style: layer, children: [
694
+ /* @__PURE__ */ jsx10(Defs, { children: /* @__PURE__ */ jsx10(LinearGradient, { id: "flame", x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: OROCHIA.flameGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx10(Stop, { offset, stopColor: color }, offset)) }) }),
695
+ /* @__PURE__ */ jsxs7(Group, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
696
+ /* @__PURE__ */ jsx10(Circle, { cx: OROCHIA.eye.cx, cy: OROCHIA.eye.cy, r: OROCHIA.eye.r, fill: OROCHIA.eye.color }),
697
+ /* @__PURE__ */ jsx10(Path, { d: OROCHIA.flame.d, transform: `translate(${OROCHIA.flame.translate[0]} ${OROCHIA.flame.translate[1]}) scale(${OROCHIA.flame.scale})`, fill: "url(#flame)" })
88
698
  ] })
89
699
  ] }) })
90
700
  ] });
91
701
  }
702
+
703
+ // src/native/progress.tsx
704
+ import * as React7 from "react";
705
+ import { Animated as Animated4, Easing as Easing2, StyleSheet as StyleSheet9, View as View7 } from "react-native";
706
+ import Svg2, { Circle as Circle2, Defs as Defs2, LinearGradient as LinearGradient2, Rect, Stop as Stop2 } from "react-native-svg";
707
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
708
+ var AnimatedCircle = Animated4.createAnimatedComponent(Circle2);
709
+ var BAR = { sm: 4, md: 8, lg: 12 };
710
+ var RING = { sm: 40, md: 80, lg: 144 };
711
+ var STROKE = { sm: 12, md: 9, lg: 7 };
712
+ function Progress({ variant = "bar", size = "md", value, max = 100, label, valueText, children, style }) {
713
+ const { theme } = useTheme();
714
+ const reduce = useReducedMotion();
715
+ const id = useSvgId("kz-progress-");
716
+ const known = typeof value === "number" && Number.isFinite(value);
717
+ const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;
718
+ const percent = Math.round(ratio * 100);
719
+ const [progress] = React7.useState(() => new Animated4.Value(ratio));
720
+ const [spin] = React7.useState(() => new Animated4.Value(0));
721
+ const [track, setTrack] = React7.useState(0);
722
+ React7.useEffect(() => {
723
+ if (reduce) {
724
+ progress.setValue(ratio);
725
+ return;
726
+ }
727
+ const animation = Animated4.timing(progress, { toValue: ratio, duration: 700, easing: Easing2.out(Easing2.cubic), useNativeDriver: false });
728
+ animation.start();
729
+ return () => animation.stop();
730
+ }, [ratio, reduce, progress]);
731
+ React7.useEffect(() => {
732
+ if (known || reduce) return;
733
+ const loop = Animated4.loop(Animated4.timing(spin, { toValue: 1, duration: 1200, easing: Easing2.linear, useNativeDriver: true }));
734
+ loop.start();
735
+ return () => {
736
+ loop.stop();
737
+ spin.setValue(0);
738
+ };
739
+ }, [known, reduce, spin]);
740
+ const a11y = {
741
+ accessible: true,
742
+ role: "progressbar",
743
+ "aria-label": label,
744
+ "aria-valuemin": known ? 0 : void 0,
745
+ "aria-valuemax": known ? max : void 0,
746
+ "aria-valuenow": known ? Math.min(max, Math.max(0, value)) : void 0,
747
+ "aria-valuetext": known ? valueText ?? `${percent}%` : valueText
748
+ };
749
+ const gradient = /* @__PURE__ */ jsx11(Defs2, { children: /* @__PURE__ */ jsxs8(LinearGradient2, { id, x1: "0", y1: "0", x2: "1", y2: variant === "ring" ? "1" : "0", children: [
750
+ /* @__PURE__ */ jsx11(Stop2, { offset: "0", stopColor: theme.accent }),
751
+ /* @__PURE__ */ jsx11(Stop2, { offset: "1", stopColor: theme.accent2 })
752
+ ] }) });
753
+ if (variant === "ring") {
754
+ const side = RING[size];
755
+ const stroke = STROKE[size];
756
+ const r = 50 - stroke / 2;
757
+ const circumference = 2 * Math.PI * r;
758
+ const offset = known ? progress.interpolate({ inputRange: [0, 1], outputRange: [circumference, 0] }) : circumference * 0.75;
759
+ const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] });
760
+ return /* @__PURE__ */ jsxs8(View7, { ...a11y, style: [styles9.ring, { width: side, height: side }, style], children: [
761
+ /* @__PURE__ */ jsx11(Animated4.View, { style: [StyleSheet9.absoluteFill, { transform: [{ rotate: known ? "-90deg" : rotate }] }], children: /* @__PURE__ */ jsxs8(Svg2, { width: side, height: side, viewBox: "0 0 100 100", children: [
762
+ gradient,
763
+ /* @__PURE__ */ jsx11(Circle2, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: stroke }),
764
+ /* @__PURE__ */ jsx11(
765
+ AnimatedCircle,
766
+ {
767
+ cx: 50,
768
+ cy: 50,
769
+ r,
770
+ fill: "none",
771
+ stroke: `url(#${id})`,
772
+ strokeWidth: stroke,
773
+ strokeLinecap: "round",
774
+ strokeDasharray: `${circumference} ${circumference}`,
775
+ strokeDashoffset: offset
776
+ }
777
+ )
778
+ ] }) }),
779
+ children
780
+ ] });
781
+ }
782
+ const width = known ? progress.interpolate({ inputRange: [0, 1], outputRange: ["0%", "100%"] }) : "40%";
783
+ const translate = spin.interpolate({ inputRange: [0, 1], outputRange: [-0.4 * track, track] });
784
+ return /* @__PURE__ */ jsx11(
785
+ View7,
786
+ {
787
+ ...a11y,
788
+ onLayout: known ? void 0 : (event) => setTrack(event.nativeEvent.layout.width),
789
+ style: [styles9.bar, { height: BAR[size], backgroundColor: theme.surface3 }, style],
790
+ children: /* @__PURE__ */ jsx11(Animated4.View, { style: [styles9.fill, { width }, known || reduce ? null : { transform: [{ translateX: translate }] }], children: /* @__PURE__ */ jsxs8(Svg2, { width: "100%", height: "100%", preserveAspectRatio: "none", children: [
791
+ gradient,
792
+ /* @__PURE__ */ jsx11(Rect, { x: 0, y: 0, width: "100%", height: "100%", fill: `url(#${id})` })
793
+ ] }) })
794
+ }
795
+ );
796
+ }
797
+ var styles9 = StyleSheet9.create({
798
+ ring: { alignItems: "center", justifyContent: "center" },
799
+ bar: { width: "100%", overflow: "hidden", borderRadius: 9999 },
800
+ fill: { height: "100%", overflow: "hidden", borderRadius: 9999 }
801
+ });
802
+
803
+ // src/native/segmented.tsx
804
+ import { Pressable as Pressable4, StyleSheet as StyleSheet10, Text as Text6, View as View8 } from "react-native";
805
+ import { jsx as jsx12 } from "react/jsx-runtime";
806
+ function Segmented({ options, value, onValueChange, size = "md", "aria-label": label, style }) {
807
+ const { theme, radius: radius3 } = useTheme();
808
+ return /* @__PURE__ */ jsx12(
809
+ View8,
810
+ {
811
+ role: "tablist",
812
+ "aria-label": label,
813
+ style: [styles10.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md, height: size === "sm" ? 32 : 40 }, style],
814
+ children: options.map((option) => {
815
+ const selected = option.value === value;
816
+ return /* @__PURE__ */ jsx12(
817
+ Pressable4,
818
+ {
819
+ role: "tab",
820
+ "aria-selected": selected,
821
+ "aria-disabled": option.disabled,
822
+ disabled: option.disabled,
823
+ onPress: () => {
824
+ if (!selected) onValueChange(option.value);
825
+ },
826
+ style: [
827
+ styles10.segment,
828
+ { borderRadius: radius3.sm },
829
+ selected ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null,
830
+ option.disabled ? styles10.disabled : null
831
+ ],
832
+ children: /* @__PURE__ */ jsx12(Text6, { numberOfLines: 1, style: [styles10.label, { color: selected ? theme.textPrimary : theme.textSecondary, fontSize: size === "sm" ? 12 : 13 }], children: option.label })
833
+ },
834
+ option.value
835
+ );
836
+ })
837
+ }
838
+ );
839
+ }
840
+ var styles10 = StyleSheet10.create({
841
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet10.hairlineWidth },
842
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet10.hairlineWidth, borderColor: "transparent" },
843
+ label: { fontWeight: "600" },
844
+ disabled: { opacity: 0.4 }
845
+ });
846
+
847
+ // src/native/skeleton.tsx
848
+ import * as React8 from "react";
849
+ import { Animated as Animated5 } from "react-native";
850
+ import { jsx as jsx13 } from "react/jsx-runtime";
851
+ var SHAPE = {
852
+ text: { width: "100%", height: 12, radius: 4 },
853
+ circle: { width: 40, height: 40, radius: 9999 },
854
+ rect: { width: "100%", height: 96, radius: 12 }
855
+ };
856
+ function Skeleton({ shape = "text", width, height, style, testID }) {
857
+ const { theme } = useTheme();
858
+ const reduce = useReducedMotion();
859
+ const [opacity] = React8.useState(() => new Animated5.Value(1));
860
+ React8.useEffect(() => {
861
+ if (reduce) return;
862
+ const loop = Animated5.loop(
863
+ Animated5.sequence([
864
+ Animated5.timing(opacity, { toValue: 0.5, duration: 900, useNativeDriver: true }),
865
+ Animated5.timing(opacity, { toValue: 1, duration: 900, useNativeDriver: true })
866
+ ])
867
+ );
868
+ loop.start();
869
+ return () => {
870
+ loop.stop();
871
+ opacity.setValue(1);
872
+ };
873
+ }, [reduce, opacity]);
874
+ const s = SHAPE[shape];
875
+ const side = shape === "circle" ? width ?? height ?? s.width : void 0;
876
+ return /* @__PURE__ */ jsx13(
877
+ Animated5.View,
878
+ {
879
+ testID,
880
+ "aria-hidden": true,
881
+ style: [
882
+ { width: side ?? width ?? s.width, height: side ?? height ?? s.height, borderRadius: s.radius, backgroundColor: theme.surface3, opacity },
883
+ style
884
+ ]
885
+ }
886
+ );
887
+ }
888
+
889
+ // src/native/spinner.tsx
890
+ import { ActivityIndicator as ActivityIndicator2 } from "react-native";
891
+ import { jsx as jsx14 } from "react/jsx-runtime";
892
+ function Spinner({ label, size = "md", ...props }) {
893
+ const { theme } = useTheme();
894
+ return /* @__PURE__ */ jsx14(
895
+ ActivityIndicator2,
896
+ {
897
+ accessible: true,
898
+ role: "progressbar",
899
+ "aria-label": label,
900
+ ...props,
901
+ size: size === "lg" ? "large" : "small",
902
+ color: theme.accent,
903
+ style: [size === "sm" ? { transform: [{ scale: 0.75 }] } : null, props.style]
904
+ }
905
+ );
906
+ }
907
+
908
+ // src/native/toast.tsx
909
+ import * as React9 from "react";
910
+ import { AccessibilityInfo as AccessibilityInfo3, Animated as Animated6, Pressable as Pressable5, StyleSheet as StyleSheet11, Text as Text7, View as View9 } from "react-native";
911
+ import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
912
+ var items = [];
913
+ var listeners2 = /* @__PURE__ */ new Set();
914
+ var counter = 0;
915
+ var emit = () => listeners2.forEach((listener) => listener());
916
+ var subscribe2 = (listener) => {
917
+ listeners2.add(listener);
918
+ return () => listeners2.delete(listener);
919
+ };
920
+ var snapshot = () => items;
921
+ function show(title, options = {}) {
922
+ const id = options.id ?? `kz-toast-${++counter}`;
923
+ const item = { ...options, id, title };
924
+ items = items.some((t) => t.id === id) ? items.map((t) => t.id === id ? item : t) : [...items, item];
925
+ emit();
926
+ return id;
927
+ }
928
+ function dismiss(id) {
929
+ const gone = items.filter((t) => id === void 0 || t.id === id);
930
+ if (gone.length === 0) return;
931
+ items = id === void 0 ? [] : items.filter((t) => t.id !== id);
932
+ emit();
933
+ gone.forEach((t) => t.onDismiss?.());
934
+ }
935
+ var tone = (name) => (title, options) => show(title, { ...options, tone: name });
936
+ var toast = Object.assign(show, {
937
+ success: tone("success"),
938
+ warning: tone("warning"),
939
+ error: tone("error"),
940
+ info: tone("info"),
941
+ dismiss
942
+ });
943
+ function ToastView({ item, closeLabel, duration }) {
944
+ const { theme, radius: radius3 } = useTheme();
945
+ const reduce = useReducedMotion();
946
+ const [enter] = React9.useState(() => new Animated6.Value(reduce ? 1 : 0));
947
+ React9.useEffect(() => {
948
+ if (reduce) enter.setValue(1);
949
+ else Animated6.timing(enter, { toValue: 1, duration: 220, useNativeDriver: true }).start();
950
+ }, [enter, reduce]);
951
+ React9.useEffect(() => {
952
+ AccessibilityInfo3.announceForAccessibility(item.description ? `${item.title}. ${item.description}` : item.title);
953
+ }, [item.title, item.description]);
954
+ const ms = item.duration ?? duration;
955
+ React9.useEffect(() => {
956
+ if (!Number.isFinite(ms)) return;
957
+ const timer2 = setTimeout(() => dismiss(item.id), ms);
958
+ return () => clearTimeout(timer2);
959
+ }, [item.id, ms]);
960
+ const edge = { success: theme.success, warning: theme.warning, error: theme.danger, info: theme.info, default: theme.borderDefault }[item.tone ?? "default"];
961
+ const text = /* @__PURE__ */ jsxs9(Fragment2, { children: [
962
+ item.icon ? /* @__PURE__ */ jsx15(View9, { "aria-hidden": true, children: item.icon }) : null,
963
+ /* @__PURE__ */ jsxs9(View9, { style: styles11.content, children: [
964
+ /* @__PURE__ */ jsx15(Txt, { variant: "label", numberOfLines: 2, children: item.title }),
965
+ item.description ? /* @__PURE__ */ jsx15(Txt, { variant: "caption", tone: "secondary", numberOfLines: 3, children: item.description }) : null
966
+ ] })
967
+ ] });
968
+ const body = /* @__PURE__ */ jsxs9(Fragment2, { children: [
969
+ item.onPress ? /* @__PURE__ */ jsx15(
970
+ Pressable5,
971
+ {
972
+ role: "button",
973
+ onPress: () => {
974
+ item.onPress?.();
975
+ dismiss(item.id);
976
+ },
977
+ style: ({ pressed }) => [styles11.main, { opacity: pressed ? 0.8 : 1 }],
978
+ children: text
979
+ }
980
+ ) : /* @__PURE__ */ jsx15(View9, { style: styles11.main, children: text }),
981
+ item.action ? /* @__PURE__ */ jsx15(
982
+ Pressable5,
983
+ {
984
+ role: "button",
985
+ onPress: () => {
986
+ item.action?.onPress();
987
+ dismiss(item.id);
988
+ },
989
+ style: [styles11.action, { backgroundColor: theme.accent, borderRadius: radius3.sm }],
990
+ children: /* @__PURE__ */ jsx15(Text7, { style: [styles11.actionLabel, { color: theme.onAccent }], children: item.action.label })
991
+ }
992
+ ) : null,
993
+ /* @__PURE__ */ jsx15(Pressable5, { role: "button", "aria-label": closeLabel, hitSlop: 10, onPress: () => dismiss(item.id), style: styles11.close, children: /* @__PURE__ */ jsx15(Text7, { style: [styles11.cross, { color: theme.textSecondary }], children: "\xD7" }) })
994
+ ] });
995
+ const frame = [
996
+ styles11.toast,
997
+ { backgroundColor: theme.surface2, borderColor: theme.borderDefault, borderLeftColor: edge, borderRadius: radius3.lg, shadowColor: theme.scrimStrong }
998
+ ];
999
+ const motion3 = { transform: [{ translateY: enter.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }) }] };
1000
+ return /* @__PURE__ */ jsx15(Animated6.View, { "aria-live": "polite", style: motion3, children: /* @__PURE__ */ jsx15(View9, { style: frame, children: body }) });
1001
+ }
1002
+ function Toaster({ closeLabel, position = "top", offset = 12, duration = 6e3, max = 3 }) {
1003
+ const all = React9.useSyncExternalStore(subscribe2, snapshot, snapshot);
1004
+ const shown = all.slice(-max);
1005
+ if (shown.length === 0) return null;
1006
+ return /* @__PURE__ */ jsx15(View9, { pointerEvents: "box-none", style: [styles11.stack, position === "top" ? { top: offset } : { bottom: offset }], children: (position === "top" ? shown : [...shown].reverse()).map((item) => /* @__PURE__ */ jsx15(ToastView, { item, closeLabel, duration }, item.id)) });
1007
+ }
1008
+ var styles11 = StyleSheet11.create({
1009
+ stack: { position: "absolute", left: 12, right: 12, gap: 8, zIndex: 100 },
1010
+ toast: {
1011
+ flexDirection: "row",
1012
+ alignItems: "center",
1013
+ gap: 10,
1014
+ padding: 12,
1015
+ borderWidth: StyleSheet11.hairlineWidth,
1016
+ borderLeftWidth: 4,
1017
+ shadowOpacity: 0.3,
1018
+ shadowRadius: 16,
1019
+ shadowOffset: { width: 0, height: 8 },
1020
+ elevation: 8
1021
+ },
1022
+ main: { flex: 1, flexDirection: "row", alignItems: "center", gap: 10 },
1023
+ content: { flex: 1, gap: 2 },
1024
+ action: { paddingHorizontal: 12, paddingVertical: 6 },
1025
+ actionLabel: { fontSize: 12, fontWeight: "700" },
1026
+ close: { width: 28, height: 28, alignItems: "center", justifyContent: "center" },
1027
+ cross: { fontSize: 18, lineHeight: 20, fontWeight: "700" }
1028
+ });
92
1029
  export {
93
- OrochiaMark
1030
+ Avatar,
1031
+ AvatarGroup,
1032
+ AvatarRoot,
1033
+ Badge,
1034
+ Button,
1035
+ Card,
1036
+ CardBody,
1037
+ CardDescription,
1038
+ CardFooter,
1039
+ CardImage,
1040
+ CardMedia,
1041
+ CardOverlay,
1042
+ CardRoot,
1043
+ CardTitle,
1044
+ Chip,
1045
+ Countdown,
1046
+ EmptyState,
1047
+ IconButton,
1048
+ OrochiaMark,
1049
+ Progress,
1050
+ Segmented,
1051
+ Skeleton,
1052
+ Spinner,
1053
+ ThemeProvider,
1054
+ Toaster,
1055
+ Txt,
1056
+ alpha,
1057
+ splitDuration,
1058
+ textStyles,
1059
+ toast,
1060
+ useCountdown,
1061
+ useReducedMotion,
1062
+ useTheme
94
1063
  };
95
1064
  //# sourceMappingURL=native.js.map