@xaui/native 0.9.1-alpha.42 → 0.9.1-alpha.44

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.
@@ -0,0 +1,401 @@
1
+ import {
2
+ CloseButton,
3
+ closeButtonBase
4
+ } from "./chunk-VIJTAIGH.js";
5
+ import {
6
+ Portal
7
+ } from "./chunk-2PMXMKS5.js";
8
+ import {
9
+ overlayEntering,
10
+ overlayExiting
11
+ } from "./chunk-64MXEVT3.js";
12
+ import {
13
+ useControllableState
14
+ } from "./chunk-F6W3JQ7K.js";
15
+ import {
16
+ PressableFeedback
17
+ } from "./chunk-LIUO6D3D.js";
18
+ import {
19
+ usePressState
20
+ } from "./chunk-423RQBOX.js";
21
+ import {
22
+ createSlotContext
23
+ } from "./chunk-K72UDPVN.js";
24
+ import {
25
+ createRecipe,
26
+ radiusAxis
27
+ } from "./chunk-4GTAZM2C.js";
28
+ import {
29
+ useXAUITheme
30
+ } from "./chunk-A3EGFI6T.js";
31
+ import {
32
+ useStyleProps
33
+ } from "./chunk-M63GFNKV.js";
34
+
35
+ // src/components/dialog/dialog-close.tsx
36
+ import { forwardRef, useCallback } from "react";
37
+
38
+ // src/components/dialog/dialog.context.ts
39
+ var [DialogProvider, useDialog] = createSlotContext("Dialog");
40
+
41
+ // src/components/dialog/dialog-close.tsx
42
+ import { jsx } from "react/jsx-runtime";
43
+ var DialogClose = forwardRef(function DialogClose2({ asChild = false, onPress, ...props }, ref) {
44
+ const { close, closeStyle, closeGlyphStyle } = useDialog();
45
+ const handlePress = useCallback(
46
+ (event) => {
47
+ onPress?.(event);
48
+ close();
49
+ },
50
+ [close, onPress]
51
+ );
52
+ return /* @__PURE__ */ jsx(
53
+ CloseButton,
54
+ {
55
+ ref,
56
+ name: "Dialog.Close",
57
+ asChild,
58
+ baseStyle: asChild ? void 0 : closeStyle,
59
+ glyphStyle: closeGlyphStyle,
60
+ onPress: handlePress,
61
+ ...props
62
+ }
63
+ );
64
+ });
65
+ DialogClose.displayName = "XAUI.Dialog.Close";
66
+
67
+ // src/components/dialog/dialog-content.tsx
68
+ import { forwardRef as forwardRef2 } from "react";
69
+ import { View } from "react-native";
70
+ import Animated from "react-native-reanimated";
71
+
72
+ // src/components/dialog/dialog.animation.ts
73
+ import { Easing, Keyframe } from "react-native-reanimated";
74
+ var ENTER_MS = 200;
75
+ var EXIT_MS = 150;
76
+ var contentEntering = new Keyframe({
77
+ 0: { opacity: 0, transform: [{ scale: 0.94 }] },
78
+ 100: {
79
+ opacity: 1,
80
+ transform: [{ scale: 1 }],
81
+ easing: Easing.out(Easing.cubic)
82
+ }
83
+ }).duration(ENTER_MS);
84
+ var contentExiting = new Keyframe({
85
+ 0: { opacity: 1, transform: [{ scale: 1 }] },
86
+ 100: {
87
+ opacity: 0,
88
+ transform: [{ scale: 0.94 }],
89
+ easing: Easing.in(Easing.cubic)
90
+ }
91
+ }).duration(EXIT_MS);
92
+
93
+ // src/components/dialog/dialog-content.tsx
94
+ import { jsx as jsx2 } from "react/jsx-runtime";
95
+ var DialogContent = forwardRef2(
96
+ function DialogContent2({ children, accessibilityViewIsModal = true, style, ...props }, ref) {
97
+ const context = useDialog();
98
+ const { panelStyle, contentStyle, isOpen } = context;
99
+ const [styleProps, rest] = useStyleProps(props);
100
+ if (!isOpen) return null;
101
+ return /* @__PURE__ */ jsx2(Portal, { children: /* @__PURE__ */ jsx2(DialogProvider, { value: context, children: /* @__PURE__ */ jsx2(View, { pointerEvents: "box-none", style: panelStyle, children: /* @__PURE__ */ jsx2(
102
+ Animated.View,
103
+ {
104
+ ref,
105
+ entering: contentEntering,
106
+ exiting: contentExiting,
107
+ accessibilityViewIsModal,
108
+ accessibilityRole: "alert",
109
+ ...rest,
110
+ style: [contentStyle, styleProps, style],
111
+ children
112
+ }
113
+ ) }) }) });
114
+ }
115
+ );
116
+ DialogContent.displayName = "XAUI.Dialog.Content";
117
+
118
+ // src/components/dialog/dialog-description.tsx
119
+ import { forwardRef as forwardRef3 } from "react";
120
+ import { Text } from "react-native";
121
+ import { jsx as jsx3 } from "react/jsx-runtime";
122
+ var DialogDescription = forwardRef3(
123
+ function DialogDescription2({ children, style, ...props }, ref) {
124
+ const { descriptionStyle } = useDialog();
125
+ const [styleProps, rest] = useStyleProps(props);
126
+ return /* @__PURE__ */ jsx3(Text, { ref, ...rest, style: [descriptionStyle, styleProps, style], children });
127
+ }
128
+ );
129
+ DialogDescription.displayName = "XAUI.Dialog.Description";
130
+
131
+ // src/components/dialog/dialog-overlay.tsx
132
+ import { forwardRef as forwardRef4 } from "react";
133
+ import { Pressable } from "react-native";
134
+ import Animated2 from "react-native-reanimated";
135
+ import { jsx as jsx4 } from "react/jsx-runtime";
136
+ var AnimatedPressable = Animated2.createAnimatedComponent(Pressable);
137
+ var DialogOverlay = forwardRef4(
138
+ function DialogOverlay2({ children, isDismissable = true, style, ...props }, ref) {
139
+ const context = useDialog();
140
+ const { overlayStyle, isOpen, close } = context;
141
+ const [styleProps, rest] = useStyleProps(props);
142
+ if (!isOpen) return null;
143
+ return /* @__PURE__ */ jsx4(Portal, { children: /* @__PURE__ */ jsx4(DialogProvider, { value: context, children: /* @__PURE__ */ jsx4(
144
+ AnimatedPressable,
145
+ {
146
+ ref,
147
+ entering: overlayEntering,
148
+ exiting: overlayExiting,
149
+ accessibilityRole: "none",
150
+ importantForAccessibility: "no",
151
+ onPress: isDismissable ? close : void 0,
152
+ ...rest,
153
+ style: [overlayStyle, styleProps, style],
154
+ children
155
+ }
156
+ ) }) });
157
+ }
158
+ );
159
+ DialogOverlay.displayName = "XAUI.Dialog.Overlay";
160
+
161
+ // src/components/dialog/dialog-title.tsx
162
+ import { forwardRef as forwardRef5 } from "react";
163
+ import { Text as Text2 } from "react-native";
164
+ import { jsx as jsx5 } from "react/jsx-runtime";
165
+ var DialogTitle = forwardRef5(function DialogTitle2({ children, accessibilityRole = "header", style, ...props }, ref) {
166
+ const { titleStyle } = useDialog();
167
+ const [styleProps, rest] = useStyleProps(props);
168
+ return /* @__PURE__ */ jsx5(
169
+ Text2,
170
+ {
171
+ ref,
172
+ accessibilityRole,
173
+ ...rest,
174
+ style: [titleStyle, styleProps, style],
175
+ children
176
+ }
177
+ );
178
+ });
179
+ DialogTitle.displayName = "XAUI.Dialog.Title";
180
+
181
+ // src/components/dialog/dialog-trigger.tsx
182
+ import { forwardRef as forwardRef6, useCallback as useCallback2 } from "react";
183
+ import { jsx as jsx6 } from "react/jsx-runtime";
184
+ var DialogTrigger = forwardRef6(
185
+ function DialogTrigger2({
186
+ children,
187
+ asChild = false,
188
+ accessibilityRole = "button",
189
+ accessibilityState,
190
+ style,
191
+ onPress,
192
+ onPressIn,
193
+ onPressOut,
194
+ ...props
195
+ }, ref) {
196
+ const { isOpen, isDisabled, toggle } = useDialog();
197
+ const [styleProps, rest] = useStyleProps(props);
198
+ const [isPressed, press] = usePressState({ onPressIn, onPressOut });
199
+ const handlePress = useCallback2(
200
+ (event) => {
201
+ onPress?.(event);
202
+ toggle();
203
+ },
204
+ [onPress, toggle]
205
+ );
206
+ return /* @__PURE__ */ jsx6(
207
+ PressableFeedback,
208
+ {
209
+ ref,
210
+ isPressed,
211
+ isDisabled,
212
+ asChild,
213
+ accessibilityRole,
214
+ accessibilityState: {
215
+ disabled: isDisabled,
216
+ expanded: isOpen,
217
+ ...accessibilityState
218
+ },
219
+ ...rest,
220
+ style: [
221
+ styleProps,
222
+ typeof style === "function" ? style({ pressed: isPressed }) : style
223
+ ],
224
+ onPress: handlePress,
225
+ onPressIn: press.onPressIn,
226
+ onPressOut: press.onPressOut,
227
+ children
228
+ }
229
+ );
230
+ }
231
+ );
232
+ DialogTrigger.displayName = "XAUI.Dialog.Trigger";
233
+
234
+ // src/components/dialog/dialog.tsx
235
+ import { useCallback as useCallback3, useMemo } from "react";
236
+
237
+ // src/components/dialog/dialog.recipe.ts
238
+ var SLOTS = [
239
+ "overlay",
240
+ "panel",
241
+ "content",
242
+ "title",
243
+ "description",
244
+ "close",
245
+ "closeGlyph"
246
+ ];
247
+ var CLOSE_BOX = 32;
248
+ var CLOSE_BAR = 16;
249
+ var dialogRecipe = createRecipe({
250
+ slots: SLOTS,
251
+ base: (theme) => {
252
+ const shared = closeButtonBase(theme);
253
+ return {
254
+ // Unlike the `Popover`'s, this backdrop dims by default. A popover is an aside you can
255
+ // read the page around; a dialog is a question, and the page behind it is not
256
+ // available until it is answered.
257
+ overlay: {
258
+ position: "absolute",
259
+ top: 0,
260
+ bottom: 0,
261
+ start: 0,
262
+ end: 0,
263
+ backgroundColor: theme.colors.backdrop
264
+ },
265
+ /**
266
+ * The layer the panel is centred in, filling the portal. It is not the panel: a
267
+ * centred box cannot also be the thing that centres it, and the padding here is the
268
+ * margin the dialog keeps from the screen's edges rather than its own inner padding.
269
+ */
270
+ panel: {
271
+ position: "absolute",
272
+ top: 0,
273
+ bottom: 0,
274
+ start: 0,
275
+ end: 0,
276
+ justifyContent: "center",
277
+ padding: theme.spacing(5)
278
+ },
279
+ content: {
280
+ backgroundColor: theme.colors.overlay,
281
+ padding: theme.spacing(5),
282
+ // HeroUI's `--radius-3xl` on a base of 8 is 24 points; our base is 12, so the same
283
+ // 24 is `2xl`. Reading their key rather than their number puts a pill on it.
284
+ borderRadius: theme.radius["2xl"],
285
+ borderCurve: "continuous",
286
+ gap: theme.spacing(2),
287
+ ...theme.shadows.overlay
288
+ },
289
+ title: {
290
+ fontFamily: theme.fontFamilies.body,
291
+ fontWeight: theme.fontWeights.medium,
292
+ fontSize: theme.fontSizes.lg,
293
+ lineHeight: theme.lineHeights.lg,
294
+ color: theme.colors.overlayForeground
295
+ },
296
+ description: {
297
+ fontFamily: theme.fontFamilies.body,
298
+ fontSize: theme.fontSizes.md,
299
+ lineHeight: theme.lineHeights.md,
300
+ color: theme.colors.muted
301
+ },
302
+ /**
303
+ * A filled disc, not a bare glyph. Their `CloseButton` is a `tertiary` button, and
304
+ * their `tertiary` is `background-color: var(--color-default)` — the same token our
305
+ * `secondary` names. A cross floating on the panel with nothing under it reads as
306
+ * decoration; the disc is what makes it a target.
307
+ *
308
+ * It positions nothing. Where the cross sits is the caller's, exactly as it is
309
+ * theirs: `alignSelf: 'flex-end'` above a title that spans the panel, or absolute in
310
+ * the corner over one short enough to leave it free. A slot that placed itself would
311
+ * have to guess which, and their own examples use both.
312
+ */
313
+ close: {
314
+ ...shared.close,
315
+ width: CLOSE_BOX,
316
+ height: CLOSE_BOX,
317
+ borderRadius: CLOSE_BOX / 2,
318
+ backgroundColor: theme.colors.default
319
+ },
320
+ // `muted`, like theirs: the cross is the way out, not the answer. The answer is a
321
+ // `Button` in the words the dialog asked for.
322
+ closeGlyph: {
323
+ ...shared.closeGlyph,
324
+ width: CLOSE_BAR,
325
+ backgroundColor: theme.colors.muted
326
+ }
327
+ };
328
+ },
329
+ /**
330
+ * One variant, and it is not a gap. A dialog is the theme's floating surface: it has no
331
+ * emphasis to report — the question it asks is in its words, not in its fill. The recipe
332
+ * keeps a single-entry `variantTokens` because `resolveTint` walks that mapping.
333
+ */
334
+ variantTokens: { default: {} },
335
+ variants: { radius: radiusAxis("content") },
336
+ defaultVariants: { variant: "default" }
337
+ });
338
+
339
+ // src/components/dialog/dialog.tsx
340
+ import { jsx as jsx7 } from "react/jsx-runtime";
341
+ function Dialog({
342
+ children,
343
+ radius,
344
+ isOpen: controlledOpen,
345
+ defaultOpen = false,
346
+ onOpenChange,
347
+ isDisabled = false
348
+ }) {
349
+ const theme = useXAUITheme();
350
+ const [isOpen, setOpen] = useControllableState({
351
+ value: controlledOpen,
352
+ defaultValue: defaultOpen,
353
+ onChange: onOpenChange
354
+ });
355
+ const styles = dialogRecipe.resolve({ theme, selection: { radius } });
356
+ const open = useCallback3(() => setOpen(true), [setOpen]);
357
+ const close = useCallback3(() => setOpen(false), [setOpen]);
358
+ const toggle = useCallback3(() => setOpen((current) => !current), [setOpen]);
359
+ const context = useMemo(
360
+ () => ({
361
+ overlayStyle: styles.overlay,
362
+ panelStyle: styles.panel,
363
+ contentStyle: styles.content,
364
+ titleStyle: styles.title,
365
+ descriptionStyle: styles.description,
366
+ closeStyle: styles.close,
367
+ closeGlyphStyle: styles.closeGlyph,
368
+ isOpen,
369
+ isDisabled,
370
+ open,
371
+ close,
372
+ toggle
373
+ }),
374
+ [styles, isOpen, isDisabled, open, close, toggle]
375
+ );
376
+ return /* @__PURE__ */ jsx7(DialogProvider, { value: context, children });
377
+ }
378
+ Dialog.displayName = "XAUI.Dialog.Root";
379
+
380
+ // src/components/dialog/index.ts
381
+ var Dialog2 = Object.assign(Dialog, {
382
+ Trigger: DialogTrigger,
383
+ Overlay: DialogOverlay,
384
+ Content: DialogContent,
385
+ Title: DialogTitle,
386
+ Description: DialogDescription,
387
+ Close: DialogClose
388
+ });
389
+
390
+ export {
391
+ useDialog,
392
+ DialogClose,
393
+ DialogContent,
394
+ DialogDescription,
395
+ DialogOverlay,
396
+ DialogTitle,
397
+ DialogTrigger,
398
+ dialogRecipe,
399
+ Dialog,
400
+ Dialog2
401
+ };