@tamagui/alert-dialog 3.0.0-beta.922.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/AlertDialog.cjs +34 -31
  2. package/dist/cjs/AlertDialog.native.cjs +33 -106
  3. package/dist/cjs/AlertDialog.native.js +33 -106
  4. package/dist/cjs/AlertDialog.native.js.map +1 -1
  5. package/dist/cjs/alertDialogPart.cjs +30 -0
  6. package/dist/cjs/alertDialogPart.native.cjs +32 -0
  7. package/dist/cjs/alertDialogPart.native.js +34 -0
  8. package/dist/cjs/alertDialogPart.native.js.map +1 -0
  9. package/dist/cjs/useNativeAlertDialog.cjs +24 -0
  10. package/dist/cjs/useNativeAlertDialog.native.cjs +139 -0
  11. package/dist/cjs/useNativeAlertDialog.native.js +141 -0
  12. package/dist/cjs/useNativeAlertDialog.native.js.map +1 -0
  13. package/dist/esm/AlertDialog.mjs +35 -19
  14. package/dist/esm/AlertDialog.mjs.map +1 -1
  15. package/dist/esm/AlertDialog.native.js +33 -104
  16. package/dist/esm/AlertDialog.native.js.map +1 -1
  17. package/dist/esm/alertDialogPart.mjs +7 -0
  18. package/dist/esm/alertDialogPart.mjs.map +1 -0
  19. package/dist/esm/alertDialogPart.native.js +7 -0
  20. package/dist/esm/alertDialogPart.native.js.map +1 -0
  21. package/dist/esm/useNativeAlertDialog.mjs +4 -0
  22. package/dist/esm/useNativeAlertDialog.mjs.map +1 -0
  23. package/dist/esm/useNativeAlertDialog.native.js +112 -0
  24. package/dist/esm/useNativeAlertDialog.native.js.map +1 -0
  25. package/dist/jsx/AlertDialog.mjs +35 -19
  26. package/dist/jsx/AlertDialog.mjs.map +1 -1
  27. package/dist/jsx/AlertDialog.native.cjs +33 -106
  28. package/dist/jsx/AlertDialog.native.js +33 -106
  29. package/dist/jsx/AlertDialog.native.js.map +1 -1
  30. package/dist/jsx/alertDialogPart.mjs +7 -0
  31. package/dist/jsx/alertDialogPart.mjs.map +1 -0
  32. package/dist/jsx/alertDialogPart.native.cjs +32 -0
  33. package/dist/jsx/alertDialogPart.native.js +34 -0
  34. package/dist/jsx/alertDialogPart.native.js.map +1 -0
  35. package/dist/jsx/useNativeAlertDialog.mjs +4 -0
  36. package/dist/jsx/useNativeAlertDialog.mjs.map +1 -0
  37. package/dist/jsx/useNativeAlertDialog.native.cjs +139 -0
  38. package/dist/jsx/useNativeAlertDialog.native.js +141 -0
  39. package/dist/jsx/useNativeAlertDialog.native.js.map +1 -0
  40. package/package.json +21 -19
  41. package/src/AlertDialog.tsx +19 -141
  42. package/src/alertDialogPart.ts +26 -0
  43. package/src/useNativeAlertDialog.native.tsx +129 -0
  44. package/src/useNativeAlertDialog.ts +11 -0
  45. package/types/AlertDialog.d.ts +41 -83
  46. package/types/AlertDialog.d.ts.map +1 -1
  47. package/types/alertDialogPart.d.ts +15 -0
  48. package/types/alertDialogPart.d.ts.map +1 -0
  49. package/types/useNativeAlertDialog.d.ts +11 -0
  50. package/types/useNativeAlertDialog.d.ts.map +1 -0
  51. package/types/useNativeAlertDialog.native.d.ts +11 -0
  52. package/types/useNativeAlertDialog.native.d.ts.map +1 -0
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all) __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true
13
+ });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
+ get: () => from[key],
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var useNativeAlertDialog_native_exports = {};
30
+ __export(useNativeAlertDialog_native_exports, { useNativeAlertDialog: () => useNativeAlertDialog });
31
+ module.exports = __toCommonJS(useNativeAlertDialog_native_exports);
32
+ var import_constants = require("@tamagui/constants");
33
+ var import_core = require("@tamagui/core");
34
+ var import_use_controllable_state = require("@tamagui/use-controllable-state");
35
+ var React = __toESM(require("react"), 1);
36
+ var import_react_native = require("react-native");
37
+ var import_alertDialogPart = require("./alertDialogPart.native.js");
38
+ var useNativeAlertDialog = function(props) {
39
+ var { native } = props;
40
+ var [open, setOpen] = (0, import_use_controllable_state.useControllableState)({
41
+ prop: props.open,
42
+ defaultProp: props.defaultOpen || false,
43
+ onChange: props.onOpenChange,
44
+ transition: true
45
+ });
46
+ var triggerElement = null;
47
+ var title = "";
48
+ var description = "";
49
+ var buttons = [];
50
+ forEachChildDeep(React.Children.toArray(props.children), function(child) {
51
+ if (!/* @__PURE__ */ React.isValidElement(child)) return false;
52
+ var part = (0, import_core.isTamaguiElement)(child) ? child.type.staticConfig[import_alertDialogPart.ALERT_DIALOG_PART] : void 0;
53
+ switch (part) {
54
+ case "trigger": {
55
+ triggerElement = /* @__PURE__ */ React.cloneElement(child, { __native: true });
56
+ return false;
57
+ }
58
+ case "title": {
59
+ title = getStringChildren(child);
60
+ return false;
61
+ }
62
+ case "description": {
63
+ description = getStringChildren(child);
64
+ return false;
65
+ }
66
+ case "action":
67
+ case "destructive":
68
+ case "cancel": {
69
+ var style = part === "action" ? "default" : part === "destructive" ? "destructive" : "cancel";
70
+ var text = getStringChildren(child);
71
+ var onPress = function() {
72
+ var _childProps_onPress;
73
+ var childProps = child.props;
74
+ childProps === null || childProps === void 0 ? void 0 : (_childProps_onPress = childProps.onPress) === null || _childProps_onPress === void 0 ? void 0 : _childProps_onPress.call(childProps, { native: true });
75
+ setOpen(false);
76
+ };
77
+ buttons.push({
78
+ style,
79
+ text,
80
+ onPress
81
+ });
82
+ return false;
83
+ }
84
+ default: {
85
+ return true;
86
+ }
87
+ }
88
+ });
89
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
90
+ if (!open || !native) return;
91
+ if (title || description) {
92
+ import_react_native.Alert.alert(title, description, buttons);
93
+ }
94
+ }, [native, open]);
95
+ if (native) {
96
+ return /* @__PURE__ */ React.cloneElement(triggerElement, { __onPress: function() {
97
+ setOpen(true);
98
+ } });
99
+ }
100
+ return null;
101
+ };
102
+ function forEachChildDeep(children, onChild) {
103
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
104
+ try {
105
+ for (var _iterator = children[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
106
+ var child = _step.value;
107
+ if (!/* @__PURE__ */ React.isValidElement(child)) continue;
108
+ if (!onChild(child)) continue;
109
+ var childProps = child.props;
110
+ if (childProps.children) {
111
+ forEachChildDeep(React.Children.toArray(childProps.children), onChild);
112
+ }
113
+ }
114
+ } catch (err) {
115
+ _didIteratorError = true;
116
+ _iteratorError = err;
117
+ } finally {
118
+ try {
119
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
120
+ _iterator.return();
121
+ }
122
+ } finally {
123
+ if (_didIteratorError) {
124
+ throw _iteratorError;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ function getStringChildren(child) {
130
+ var string = "";
131
+ forEachChildDeep(React.Children.toArray(child), function(child2) {
132
+ if (typeof child2.props.children === "string") {
133
+ string = child2.props.children;
134
+ return false;
135
+ }
136
+ return true;
137
+ });
138
+ return string;
139
+ }
140
+
141
+ //# sourceMappingURL=useNativeAlertDialog.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNativeAlertDialog.native.js","names":[],"sources":["jsx/useNativeAlertDialog.native.js"],"sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\nvar useNativeAlertDialog_native_exports = {};\n__export(useNativeAlertDialog_native_exports, {\n useNativeAlertDialog: () => useNativeAlertDialog\n});\nmodule.exports = __toCommonJS(useNativeAlertDialog_native_exports);\nvar import_constants = require(\"@tamagui/constants\");\nvar import_core = require(\"@tamagui/core\");\nvar import_use_controllable_state = require(\"@tamagui/use-controllable-state\");\nvar React = __toESM(require(\"react\"), 1);\nvar import_react_native = require(\"react-native\");\nvar import_alertDialogPart = require(\"./alertDialogPart\");\nvar useNativeAlertDialog = function(props) {\n var { native } = props;\n var [open, setOpen] = (0, import_use_controllable_state.useControllableState)({\n prop: props.open,\n defaultProp: props.defaultOpen || false,\n onChange: props.onOpenChange,\n transition: true\n });\n var triggerElement = null;\n var title = \"\";\n var description = \"\";\n var buttons = [];\n forEachChildDeep(React.Children.toArray(props.children), function(child) {\n if (!/* @__PURE__ */ React.isValidElement(child)) return false;\n var part = (0, import_core.isTamaguiElement)(child) ? child.type.staticConfig[import_alertDialogPart.ALERT_DIALOG_PART] : void 0;\n switch (part) {\n case \"trigger\": {\n triggerElement = /* @__PURE__ */ React.cloneElement(child, {\n __native: true\n });\n return false;\n }\n case \"title\": {\n title = getStringChildren(child);\n return false;\n }\n case \"description\": {\n description = getStringChildren(child);\n return false;\n }\n case \"action\":\n case \"destructive\":\n case \"cancel\": {\n var style = part === \"action\" ? \"default\" : part === \"destructive\" ? \"destructive\" : \"cancel\";\n var text = getStringChildren(child);\n var onPress = function() {\n var _childProps_onPress;\n var childProps = child.props;\n childProps === null || childProps === void 0 ? void 0 : (_childProps_onPress = childProps.onPress) === null || _childProps_onPress === void 0 ? void 0 : _childProps_onPress.call(childProps, {\n native: true\n });\n setOpen(false);\n };\n buttons.push({\n style,\n text,\n // @ts-ignore\n onPress\n });\n return false;\n }\n default: {\n return true;\n }\n }\n });\n (0, import_constants.useIsomorphicLayoutEffect)(function() {\n if (!open || !native) return;\n if (title || description) {\n import_react_native.Alert.alert(title, description, buttons);\n }\n }, [\n native,\n open\n ]);\n if (native) {\n return /* @__PURE__ */ React.cloneElement(triggerElement, {\n __onPress: function() {\n setOpen(true);\n }\n });\n }\n return null;\n};\nfunction forEachChildDeep(children, onChild) {\n var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;\n try {\n for (var _iterator = children[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var child = _step.value;\n if (!/* @__PURE__ */ React.isValidElement(child)) continue;\n if (!onChild(child)) continue;\n var childProps = child.props;\n if (childProps.children) {\n forEachChildDeep(React.Children.toArray(childProps.children), onChild);\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n}\nfunction getStringChildren(child) {\n var string = \"\";\n forEachChildDeep(React.Children.toArray(child), function(child2) {\n if (typeof child2.props.children === \"string\") {\n string = child2.props.children;\n return false;\n }\n return true;\n });\n return string;\n}\n//# sourceMappingURL=useNativeAlertDialog.native.js.map\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@tamagui/alert-dialog",
3
- "version": "3.0.0-beta.922.1",
3
+ "version": "3.0.0",
4
+ "license": "MIT",
4
5
  "source": "src/index.ts",
5
6
  "files": [
6
7
  "src",
@@ -34,26 +35,26 @@
34
35
  "clean:build": "tamagui-build clean:build"
35
36
  },
36
37
  "dependencies": {
37
- "@tamagui/animate-presence": "3.0.0-beta.922.1",
38
- "@tamagui/compose-refs": "3.0.0-beta.922.1",
39
- "@tamagui/constants": "3.0.0-beta.922.1",
40
- "@tamagui/core": "3.0.0-beta.922.1",
41
- "@tamagui/create-context": "3.0.0-beta.922.1",
42
- "@tamagui/dialog": "3.0.0-beta.922.1",
43
- "@tamagui/dismissable": "3.0.0-beta.922.1",
44
- "@tamagui/focus-scope": "3.0.0-beta.922.1",
45
- "@tamagui/helpers": "3.0.0-beta.922.1",
46
- "@tamagui/polyfill-dev": "3.0.0-beta.922.1",
47
- "@tamagui/portal": "3.0.0-beta.922.1",
48
- "@tamagui/remove-scroll": "3.0.0-beta.922.1",
49
- "@tamagui/stacks": "3.0.0-beta.922.1",
50
- "@tamagui/text": "3.0.0-beta.922.1",
51
- "@tamagui/use-controllable-state": "3.0.0-beta.922.1"
38
+ "@tamagui/animate-presence": "3.0.0",
39
+ "@tamagui/compose-refs": "3.0.0",
40
+ "@tamagui/constants": "3.0.0",
41
+ "@tamagui/core": "3.0.0",
42
+ "@tamagui/create-context": "3.0.0",
43
+ "@tamagui/dialog": "3.0.0",
44
+ "@tamagui/dismissable": "3.0.0",
45
+ "@tamagui/focus-scope": "3.0.0",
46
+ "@tamagui/helpers": "3.0.0",
47
+ "@tamagui/polyfill-dev": "3.0.0",
48
+ "@tamagui/portal": "3.0.0",
49
+ "@tamagui/remove-scroll": "3.0.0",
50
+ "@tamagui/stacks": "3.0.0",
51
+ "@tamagui/text": "3.0.0",
52
+ "@tamagui/use-controllable-state": "3.0.0"
52
53
  },
53
54
  "devDependencies": {
54
- "@tamagui/build": "3.0.0-beta.922.1",
55
+ "@tamagui/build": "3.0.0",
55
56
  "react": "19.2.3",
56
- "react-native": "0.86.2"
57
+ "react-native": "0.87.1"
57
58
  },
58
59
  "peerDependencies": {
59
60
  "react": ">=19",
@@ -65,5 +66,6 @@
65
66
  "type": "git",
66
67
  "url": "git+https://github.com/tamagui/tamagui.git",
67
68
  "directory": "code/ui/alert-dialog"
68
- }
69
+ },
70
+ "releaseSourceCommit": "15fbca480b143f876f6975601e23a17d3f90d2ee"
69
71
  }
@@ -1,17 +1,11 @@
1
- import { createStyledHOC, createRefComponent } from '@tamagui/core'
1
+ import { createStyledHOC } from '@tamagui/core'
2
2
  // forked from radix-ui
3
3
  // https://github.com/radix-ui/primitives/blob/main/packages/react/alert-dialog/src/AlertDialog.tsx
4
4
 
5
5
  import { useComposedRefs } from '@tamagui/compose-refs'
6
6
  import { isWeb, useIsomorphicLayoutEffect } from '@tamagui/constants'
7
7
  import type { TamaguiElement } from '@tamagui/core'
8
- import {
9
- Slottable,
10
- View,
11
- createStyledContext,
12
- isTamaguiElement,
13
- styled,
14
- } from '@tamagui/core'
8
+ import { Slottable, View, createStyledContext, styled } from '@tamagui/core'
15
9
  import type {
16
10
  DialogCloseProps,
17
11
  DialogContentProps,
@@ -27,6 +21,7 @@ import {
27
21
  Dialog,
28
22
  DialogClose,
29
23
  DialogContent,
24
+ DialogContentFrame,
30
25
  DialogDescription,
31
26
  DialogOverlay,
32
27
  DialogOverlayFrame,
@@ -36,9 +31,10 @@ import {
36
31
  DialogWarningProvider,
37
32
  } from '@tamagui/dialog'
38
33
  import { composeEventHandlers, withStaticProperties } from '@tamagui/helpers'
39
- import { useControllableState } from '@tamagui/use-controllable-state'
40
34
  import * as React from 'react'
41
- import { Alert } from 'react-native'
35
+
36
+ import { markAlertDialogPart } from './alertDialogPart'
37
+ import { useNativeAlertDialog } from './useNativeAlertDialog'
42
38
 
43
39
  const getAlertDialogScope = (scope?: string) => scope
44
40
 
@@ -47,27 +43,6 @@ const getAlertDialogScope = (scope?: string) => scope
47
43
  * -----------------------------------------------------------------------------------------------*/
48
44
 
49
45
  const ROOT_NAME = 'AlertDialog'
50
- const ALERT_DIALOG_PART = Symbol('AlertDialogPart')
51
-
52
- type AlertDialogPart =
53
- | 'trigger'
54
- | 'title'
55
- | 'description'
56
- | 'action'
57
- | 'cancel'
58
- | 'destructive'
59
-
60
- type AlertDialogPartStaticConfig = {
61
- [ALERT_DIALOG_PART]?: AlertDialogPart
62
- }
63
-
64
- const markAlertDialogPart = (
65
- component: { staticConfig: object },
66
- part: AlertDialogPart
67
- ) => {
68
- Object.assign(component.staticConfig, { [ALERT_DIALOG_PART]: part })
69
- }
70
-
71
46
  export type AlertDialogScopes = string
72
47
 
73
48
  type ScopedProps<P> = Omit<P, 'scope'> & { scope?: AlertDialogScopes }
@@ -175,8 +150,17 @@ type AlertDialogContentProps = ScopedProps<
175
150
  Omit<DialogContentProps, 'onPointerDownOutside' | 'onInteractOutside'>
176
151
  >
177
152
 
178
- const AlertDialogContent = createRefComponent<TamaguiElement, AlertDialogContentProps>(
179
- function AlertDialogContent(props, forwardedRef) {
153
+ // a styled HOC, not a plain component wrapping DialogContent: `styled()` on a
154
+ // plain component would land the animation props on this outer frame, which
155
+ // renders above the presence boundary DialogContent creates, and an exiting
156
+ // frame that never joins presence finishes its exit instantly
157
+ const AlertDialogContentFrame = styled(DialogContentFrame, {
158
+ displayName: CONTENT_NAME,
159
+ })
160
+
161
+ const AlertDialogContent = createStyledHOC(
162
+ AlertDialogContentFrame,
163
+ function AlertDialogContent(props: AlertDialogContentProps, forwardedRef) {
180
164
  const { scope, children, ...contentProps } = props
181
165
  const dialogScope = getAlertDialogScope(scope)
182
166
  const contentRef = React.useRef<TamaguiElement>(null)
@@ -392,118 +376,12 @@ const AlertDialogInner: React.FC<AlertDialogProps> = (props) => {
392
376
  const { scope, native, ...alertDialogProps } = props
393
377
  const dialogScope = getAlertDialogScope(scope)
394
378
 
395
- if (process.env.TAMAGUI_TARGET === 'native') {
396
- const [open, setOpen] = useControllableState({
397
- prop: props.open,
398
- defaultProp: props.defaultOpen || false,
399
- onChange: props.onOpenChange,
400
- transition: true,
401
- })
402
-
403
- let triggerElement: any = null
404
- let title = ''
405
- let description = ''
406
- const buttons: {
407
- text: string
408
- onPress: (value?: string | undefined) => void
409
- style?: 'default' | 'cancel' | 'destructive'
410
- }[] = []
411
-
412
- forEachChildDeep(React.Children.toArray(props.children), (child) => {
413
- if (!React.isValidElement(child)) return false
414
- const part = isTamaguiElement(child)
415
- ? (child.type.staticConfig as AlertDialogPartStaticConfig)[ALERT_DIALOG_PART]
416
- : undefined
417
- switch (part) {
418
- case 'trigger': {
419
- triggerElement = React.cloneElement(child as any, {
420
- __native: true,
421
- })
422
- return false
423
- }
424
- case 'title': {
425
- title = getStringChildren(child)
426
- return false
427
- }
428
- case 'description': {
429
- description = getStringChildren(child)
430
- return false
431
- }
432
- case 'action':
433
- case 'destructive':
434
- case 'cancel': {
435
- const style =
436
- part === 'action'
437
- ? 'default'
438
- : part === 'destructive'
439
- ? 'destructive'
440
- : 'cancel'
441
- const text = getStringChildren(child)
442
- const onPress = () => {
443
- const childProps = child.props as any
444
- childProps?.onPress?.({ native: true })
445
- setOpen(false)
446
- }
447
- buttons.push({
448
- style,
449
- text,
450
- // @ts-ignore
451
- onPress,
452
- })
453
- return false
454
- }
455
- default: {
456
- return true
457
- }
458
- }
459
- })
460
-
461
- useIsomorphicLayoutEffect(() => {
462
- if (!open || !native) return
463
- if (title || description) {
464
- Alert.alert(title, description, buttons)
465
- }
466
- }, [native, open])
467
-
468
- if (native) {
469
- return React.cloneElement(triggerElement, {
470
- __onPress: () => {
471
- setOpen(true)
472
- },
473
- })
474
- }
475
- }
379
+ const nativeAlert = useNativeAlertDialog(props)
380
+ if (nativeAlert) return nativeAlert
476
381
 
477
382
  return <Dialog scope={dialogScope} {...alertDialogProps} modal />
478
383
  }
479
384
 
480
- function forEachChildDeep(
481
- children: React.ReactNode[],
482
- onChild: (el: React.ReactElement) => boolean
483
- ) {
484
- for (const child of children) {
485
- if (!React.isValidElement(child)) continue
486
- if (!onChild(child)) continue
487
- // TODO react 19 doesn't like child.props
488
- const childProps = child.props as unknown as any
489
- if (childProps.children) {
490
- forEachChildDeep(React.Children.toArray(childProps.children), onChild)
491
- }
492
- }
493
- }
494
-
495
- function getStringChildren(child: React.ReactElement) {
496
- let string = ''
497
- forEachChildDeep(React.Children.toArray(child), (child) => {
498
- if (typeof (child.props as Record<string, any>).children === 'string') {
499
- string = (child.props as Record<string, any>).children
500
- return false
501
- }
502
- return true
503
- })
504
- return string
505
- }
506
-
507
385
  const AlertDialog = withStaticProperties(AlertDialogInner, {
508
386
  Trigger: AlertDialogTrigger,
509
387
  Portal: AlertDialogPortal,
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Which slot a child fills, stamped onto the styled component's staticConfig so
3
+ * the native path can find the title, description and buttons by walking the
4
+ * tree instead of rendering it. Lives here so the native-only walker can read
5
+ * it without importing back into `AlertDialog`.
6
+ */
7
+ export const ALERT_DIALOG_PART = Symbol('AlertDialogPart')
8
+
9
+ export type AlertDialogPart =
10
+ | 'trigger'
11
+ | 'title'
12
+ | 'description'
13
+ | 'action'
14
+ | 'cancel'
15
+ | 'destructive'
16
+
17
+ export type AlertDialogPartStaticConfig = {
18
+ [ALERT_DIALOG_PART]?: AlertDialogPart
19
+ }
20
+
21
+ export const markAlertDialogPart = (
22
+ component: { staticConfig: object },
23
+ part: AlertDialogPart
24
+ ) => {
25
+ Object.assign(component.staticConfig, { [ALERT_DIALOG_PART]: part })
26
+ }
@@ -0,0 +1,129 @@
1
+ import { useIsomorphicLayoutEffect } from '@tamagui/constants'
2
+ import { isTamaguiElement } from '@tamagui/core'
3
+ import type { DialogProps } from '@tamagui/dialog'
4
+ import { useControllableState } from '@tamagui/use-controllable-state'
5
+ import * as React from 'react'
6
+ import { Alert } from 'react-native'
7
+
8
+ import type { AlertDialogPartStaticConfig } from './alertDialogPart'
9
+ import { ALERT_DIALOG_PART } from './alertDialogPart'
10
+
11
+ /**
12
+ * With `native`, the dialog is the platform's own alert: the children are never
13
+ * rendered, they are read for their title, description and buttons and handed
14
+ * to `Alert.alert`, and only the trigger stays in the tree.
15
+ */
16
+ export const useNativeAlertDialog = (
17
+ props: DialogProps & { native?: boolean }
18
+ ): React.ReactElement | null => {
19
+ const { native } = props
20
+
21
+ const [open, setOpen] = useControllableState({
22
+ prop: props.open,
23
+ defaultProp: props.defaultOpen || false,
24
+ onChange: props.onOpenChange,
25
+ transition: true,
26
+ })
27
+
28
+ let triggerElement: any = null
29
+ let title = ''
30
+ let description = ''
31
+ const buttons: {
32
+ text: string
33
+ onPress: (value?: string | undefined) => void
34
+ style?: 'default' | 'cancel' | 'destructive'
35
+ }[] = []
36
+
37
+ forEachChildDeep(React.Children.toArray(props.children), (child) => {
38
+ if (!React.isValidElement(child)) return false
39
+ const part = isTamaguiElement(child)
40
+ ? (child.type.staticConfig as AlertDialogPartStaticConfig)[ALERT_DIALOG_PART]
41
+ : undefined
42
+ switch (part) {
43
+ case 'trigger': {
44
+ triggerElement = React.cloneElement(child as any, {
45
+ __native: true,
46
+ })
47
+ return false
48
+ }
49
+ case 'title': {
50
+ title = getStringChildren(child)
51
+ return false
52
+ }
53
+ case 'description': {
54
+ description = getStringChildren(child)
55
+ return false
56
+ }
57
+ case 'action':
58
+ case 'destructive':
59
+ case 'cancel': {
60
+ const style =
61
+ part === 'action'
62
+ ? 'default'
63
+ : part === 'destructive'
64
+ ? 'destructive'
65
+ : 'cancel'
66
+ const text = getStringChildren(child)
67
+ const onPress = () => {
68
+ const childProps = child.props as any
69
+ childProps?.onPress?.({ native: true })
70
+ setOpen(false)
71
+ }
72
+ buttons.push({
73
+ style,
74
+ text,
75
+ // @ts-ignore
76
+ onPress,
77
+ })
78
+ return false
79
+ }
80
+ default: {
81
+ return true
82
+ }
83
+ }
84
+ })
85
+
86
+ useIsomorphicLayoutEffect(() => {
87
+ if (!open || !native) return
88
+ if (title || description) {
89
+ Alert.alert(title, description, buttons)
90
+ }
91
+ }, [native, open])
92
+
93
+ if (native) {
94
+ return React.cloneElement(triggerElement, {
95
+ __onPress: () => {
96
+ setOpen(true)
97
+ },
98
+ })
99
+ }
100
+
101
+ return null
102
+ }
103
+
104
+ function forEachChildDeep(
105
+ children: React.ReactNode[],
106
+ onChild: (el: React.ReactElement) => boolean
107
+ ) {
108
+ for (const child of children) {
109
+ if (!React.isValidElement(child)) continue
110
+ if (!onChild(child)) continue
111
+ // TODO react 19 doesn't like child.props
112
+ const childProps = child.props as unknown as any
113
+ if (childProps.children) {
114
+ forEachChildDeep(React.Children.toArray(childProps.children), onChild)
115
+ }
116
+ }
117
+ }
118
+
119
+ function getStringChildren(child: React.ReactElement) {
120
+ let string = ''
121
+ forEachChildDeep(React.Children.toArray(child), (child) => {
122
+ if (typeof (child.props as Record<string, any>).children === 'string') {
123
+ string = (child.props as Record<string, any>).children
124
+ return false
125
+ }
126
+ return true
127
+ })
128
+ return string
129
+ }
@@ -0,0 +1,11 @@
1
+ import type { DialogProps } from '@tamagui/dialog'
2
+ import type * as React from 'react'
3
+
4
+ /**
5
+ * `native` asks for the platform's own alert, which the web does not have, so
6
+ * the web build always falls through to the real dialog. The native sibling is
7
+ * where the work happens.
8
+ */
9
+ export const useNativeAlertDialog = (
10
+ _props: DialogProps & { native?: boolean }
11
+ ): React.ReactElement | null => null