@tamagui/alert-dialog 1.0.1-beta.104

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.
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@tamagui/alert-dialog",
3
+ "version": "1.0.1-beta.104",
4
+ "source": "src/index.ts",
5
+ "types": "./types/index.d.ts",
6
+ "main": "dist/cjs",
7
+ "module": "dist/esm",
8
+ "module:jsx": "dist/jsx",
9
+ "sideEffects": [
10
+ "*.css"
11
+ ],
12
+ "files": [
13
+ "src",
14
+ "types",
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tamagui-build",
19
+ "watch": "tamagui-build --watch",
20
+ "clean": "tamagui-build clean",
21
+ "clean:build": "tamagui-build clean:build"
22
+ },
23
+ "dependencies": {
24
+ "@tamagui/animate-presence": "^1.0.1-beta.104",
25
+ "@tamagui/compose-refs": "^1.0.1-beta.104",
26
+ "@tamagui/core": "^1.0.1-beta.104",
27
+ "@tamagui/create-context": "^1.0.1-beta.104",
28
+ "@tamagui/dialog": "^1.0.1-beta.104",
29
+ "@tamagui/dismissable": "^1.0.1-beta.104",
30
+ "@tamagui/focus-scope": "^1.0.1-beta.104",
31
+ "@tamagui/polyfill-dev": "^1.0.1-beta.104",
32
+ "@tamagui/popper": "^1.0.1-beta.104",
33
+ "@tamagui/portal": "^1.0.1-beta.104",
34
+ "@tamagui/stacks": "^1.0.1-beta.104",
35
+ "@tamagui/text": "^1.0.1-beta.104",
36
+ "@tamagui/use-controllable-state": "^1.0.1-beta.104",
37
+ "aria-hidden": "^1.1.3",
38
+ "react-remove-scroll": "^2.5.5"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "*",
42
+ "react-dom": "*",
43
+ "react-native": "*"
44
+ },
45
+ "devDependencies": {
46
+ "@tamagui/build": "^1.0.1-beta.104",
47
+ "@types/react-dom": "^18.0.3",
48
+ "@types/react-native": "^0.69.2",
49
+ "react": "*",
50
+ "react-dom": "*",
51
+ "react-native": "*"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }
@@ -0,0 +1,313 @@
1
+ // forked from radix-ui
2
+ // https://github.com/radix-ui/primitives/blob/main/packages/react/alert-dialog/src/AlertDialog.tsx
3
+
4
+ import { useComposedRefs } from '@tamagui/compose-refs'
5
+ import {
6
+ Slottable,
7
+ TamaguiElement,
8
+ composeEventHandlers,
9
+ isWeb,
10
+ withStaticProperties,
11
+ } from '@tamagui/core'
12
+ import { Scope, createContextScope } from '@tamagui/create-context'
13
+ import {
14
+ Dialog,
15
+ DialogClose,
16
+ DialogCloseProps,
17
+ DialogContent,
18
+ DialogContentProps,
19
+ DialogDescription,
20
+ DialogDescriptionProps,
21
+ DialogOverlay,
22
+ DialogOverlayProps,
23
+ DialogPortal,
24
+ DialogPortalProps,
25
+ DialogProps,
26
+ DialogTitle,
27
+ DialogTitleProps,
28
+ DialogTrigger,
29
+ DialogTriggerProps,
30
+ DialogWarningProvider,
31
+ createDialogScope,
32
+ } from '@tamagui/dialog'
33
+ import * as React from 'react'
34
+
35
+ const ROOT_NAME = 'AlertDialog'
36
+
37
+ type ScopedProps<P> = P & { __scopeAlertDialog?: Scope }
38
+ const [createAlertDialogContext, createAlertDialogScope] = createContextScope(ROOT_NAME, [
39
+ createDialogScope,
40
+ ])
41
+
42
+ const useDialogScope = createDialogScope()
43
+
44
+ interface AlertDialogProps extends Omit<DialogProps, 'modal'> {}
45
+
46
+ /* -------------------------------------------------------------------------------------------------
47
+ * AlertDialogTrigger
48
+ * -----------------------------------------------------------------------------------------------*/
49
+ const TRIGGER_NAME = 'AlertDialogTrigger'
50
+
51
+ interface AlertDialogTriggerProps extends DialogTriggerProps {}
52
+
53
+ const AlertDialogTrigger = React.forwardRef<TamaguiElement, AlertDialogTriggerProps>(
54
+ (props: ScopedProps<AlertDialogTriggerProps>, forwardedRef) => {
55
+ const { __scopeAlertDialog, ...triggerProps } = props
56
+ const dialogScope = useDialogScope(__scopeAlertDialog)
57
+ return <DialogTrigger {...dialogScope} {...triggerProps} ref={forwardedRef} />
58
+ }
59
+ )
60
+
61
+ AlertDialogTrigger.displayName = TRIGGER_NAME
62
+
63
+ /* -------------------------------------------------------------------------------------------------
64
+ * AlertDialogPortal
65
+ * -----------------------------------------------------------------------------------------------*/
66
+
67
+ const PORTAL_NAME = 'AlertDialogPortal'
68
+
69
+ interface AlertDialogPortalProps extends DialogPortalProps {}
70
+
71
+ const AlertDialogPortal: React.FC<AlertDialogPortalProps> = (
72
+ props: ScopedProps<AlertDialogPortalProps>
73
+ ) => {
74
+ const { __scopeAlertDialog, ...portalProps } = props
75
+ const dialogScope = useDialogScope(__scopeAlertDialog)
76
+ return <DialogPortal {...dialogScope} {...portalProps} />
77
+ }
78
+
79
+ AlertDialogPortal.displayName = PORTAL_NAME
80
+
81
+ /* -------------------------------------------------------------------------------------------------
82
+ * AlertDialogOverlay
83
+ * -----------------------------------------------------------------------------------------------*/
84
+
85
+ const OVERLAY_NAME = 'AlertDialogOverlay'
86
+
87
+ interface AlertDialogOverlayProps extends DialogOverlayProps {}
88
+
89
+ const AlertDialogOverlay = React.forwardRef<TamaguiElement, AlertDialogOverlayProps>(
90
+ (props: ScopedProps<AlertDialogOverlayProps>, forwardedRef) => {
91
+ const { __scopeAlertDialog, ...overlayProps } = props
92
+ const dialogScope = useDialogScope(__scopeAlertDialog)
93
+ return <DialogOverlay {...dialogScope} {...overlayProps} ref={forwardedRef} />
94
+ }
95
+ )
96
+
97
+ AlertDialogOverlay.displayName = OVERLAY_NAME
98
+
99
+ /* -------------------------------------------------------------------------------------------------
100
+ * AlertDialogContent
101
+ * -----------------------------------------------------------------------------------------------*/
102
+
103
+ const CONTENT_NAME = 'AlertDialogContent'
104
+
105
+ type AlertDialogContentContextValue = {
106
+ cancelRef: React.MutableRefObject<TamaguiElement | null>
107
+ }
108
+
109
+ const [AlertDialogContentProvider, useAlertDialogContentContext] =
110
+ createAlertDialogContext<AlertDialogContentContextValue>(CONTENT_NAME)
111
+
112
+ interface AlertDialogContentProps
113
+ extends Omit<DialogContentProps, 'onPointerDownOutside' | 'onInteractOutside'> {}
114
+
115
+ const AlertDialogContent = React.forwardRef<TamaguiElement, AlertDialogContentProps>(
116
+ (props: ScopedProps<AlertDialogContentProps>, forwardedRef) => {
117
+ const { __scopeAlertDialog, children, ...contentProps } = props
118
+ const dialogScope = useDialogScope(__scopeAlertDialog)
119
+ const contentRef = React.useRef<TamaguiElement>(null)
120
+ const composedRefs = useComposedRefs(forwardedRef, contentRef)
121
+ const cancelRef = React.useRef<TamaguiElement | null>(null)
122
+
123
+ return (
124
+ <DialogWarningProvider
125
+ contentName={CONTENT_NAME}
126
+ titleName={TITLE_NAME}
127
+ docsSlug="alert-dialog"
128
+ >
129
+ <AlertDialogContentProvider scope={__scopeAlertDialog} cancelRef={cancelRef}>
130
+ <DialogContent
131
+ // @ts-ignore
132
+ role="alertdialog"
133
+ {...dialogScope}
134
+ {...contentProps}
135
+ ref={composedRefs}
136
+ onOpenAutoFocus={composeEventHandlers(contentProps.onOpenAutoFocus, (event) => {
137
+ event.preventDefault()
138
+ if (isWeb) {
139
+ // @ts-ignore
140
+ cancelRef.current?.focus({ preventScroll: true })
141
+ }
142
+ })}
143
+ onPointerDownOutside={(event) => event.preventDefault()}
144
+ onInteractOutside={(event) => event.preventDefault()}
145
+ >
146
+ {/**
147
+ * We have to use `Slottable` here as we cannot wrap the `AlertDialogContentProvider`
148
+ * around everything, otherwise the `DescriptionWarning` would be rendered straight away.
149
+ * This is because we want the accessibility checks to run only once the content is actually
150
+ * open and that behaviour is already encapsulated in `DialogContent`.
151
+ */}
152
+ <Slottable>{children}</Slottable>
153
+ {process.env.NODE_ENV === 'development' && (
154
+ <DescriptionWarning contentRef={contentRef} />
155
+ )}
156
+ </DialogContent>
157
+ </AlertDialogContentProvider>
158
+ </DialogWarningProvider>
159
+ )
160
+ }
161
+ )
162
+
163
+ AlertDialogContent.displayName = CONTENT_NAME
164
+
165
+ /* -------------------------------------------------------------------------------------------------
166
+ * AlertDialogTitle
167
+ * -----------------------------------------------------------------------------------------------*/
168
+
169
+ const TITLE_NAME = 'AlertDialogTitle'
170
+
171
+ type AlertDialogTitleProps = DialogTitleProps
172
+
173
+ const AlertDialogTitle = React.forwardRef<TamaguiElement, AlertDialogTitleProps>(
174
+ (props: ScopedProps<AlertDialogTitleProps>, forwardedRef) => {
175
+ const { __scopeAlertDialog, ...titleProps } = props
176
+ const dialogScope = useDialogScope(__scopeAlertDialog)
177
+ return <DialogTitle {...dialogScope} {...titleProps} ref={forwardedRef} />
178
+ }
179
+ )
180
+
181
+ AlertDialogTitle.displayName = TITLE_NAME
182
+
183
+ /* -------------------------------------------------------------------------------------------------
184
+ * AlertDialogDescription
185
+ * -----------------------------------------------------------------------------------------------*/
186
+
187
+ const DESCRIPTION_NAME = 'AlertDialogDescription'
188
+
189
+ type AlertDialogDescriptionProps = DialogDescriptionProps
190
+
191
+ const AlertDialogDescription = React.forwardRef<TamaguiElement, AlertDialogDescriptionProps>(
192
+ (props: ScopedProps<AlertDialogDescriptionProps>, forwardedRef) => {
193
+ const { __scopeAlertDialog, ...descriptionProps } = props
194
+ const dialogScope = useDialogScope(__scopeAlertDialog)
195
+ return <DialogDescription {...dialogScope} {...descriptionProps} ref={forwardedRef} />
196
+ }
197
+ )
198
+
199
+ AlertDialogDescription.displayName = DESCRIPTION_NAME
200
+
201
+ /* -------------------------------------------------------------------------------------------------
202
+ * AlertDialogAction
203
+ * -----------------------------------------------------------------------------------------------*/
204
+
205
+ const ACTION_NAME = 'AlertDialogAction'
206
+
207
+ type AlertDialogActionProps = DialogCloseProps
208
+
209
+ const AlertDialogAction = React.forwardRef<TamaguiElement, AlertDialogActionProps>(
210
+ (props: ScopedProps<AlertDialogActionProps>, forwardedRef) => {
211
+ const { __scopeAlertDialog, ...actionProps } = props
212
+ const dialogScope = useDialogScope(__scopeAlertDialog)
213
+ return <DialogClose {...dialogScope} {...actionProps} ref={forwardedRef} />
214
+ }
215
+ )
216
+
217
+ AlertDialogAction.displayName = ACTION_NAME
218
+
219
+ /* -------------------------------------------------------------------------------------------------
220
+ * AlertDialogCancel
221
+ * -----------------------------------------------------------------------------------------------*/
222
+
223
+ const CANCEL_NAME = 'AlertDialogCancel'
224
+
225
+ interface AlertDialogCancelProps extends DialogCloseProps {}
226
+
227
+ const AlertDialogCancel = React.forwardRef<TamaguiElement, AlertDialogCancelProps>(
228
+ (props: ScopedProps<AlertDialogCancelProps>, forwardedRef) => {
229
+ const { __scopeAlertDialog, ...cancelProps } = props
230
+ const { cancelRef } = useAlertDialogContentContext(CANCEL_NAME, __scopeAlertDialog)
231
+ const dialogScope = useDialogScope(__scopeAlertDialog)
232
+ const ref = useComposedRefs(forwardedRef, cancelRef)
233
+ return <DialogClose {...dialogScope} {...cancelProps} ref={ref} />
234
+ }
235
+ )
236
+
237
+ AlertDialogCancel.displayName = CANCEL_NAME
238
+
239
+ /* ---------------------------------------------------------------------------------------------- */
240
+
241
+ type DescriptionWarningProps = {
242
+ contentRef: React.RefObject<TamaguiElement>
243
+ }
244
+
245
+ const DescriptionWarning: React.FC<DescriptionWarningProps> = ({ contentRef }) => {
246
+ const MESSAGE = `\`${CONTENT_NAME}\` requires a description for the component to be accessible for screen reader users.
247
+
248
+ You can add a description to the \`${CONTENT_NAME}\` by passing a \`${DESCRIPTION_NAME}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
249
+
250
+ Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${CONTENT_NAME}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
251
+
252
+ For more information, see https://tamagui.dev/docs/components/alert-dialog`
253
+
254
+ React.useEffect(() => {
255
+ if (!isWeb) return
256
+ const hasDescription = document.getElementById(
257
+ // @ts-ignore
258
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
259
+ contentRef.current?.getAttribute('aria-describedby')!
260
+ )
261
+ if (!hasDescription) console.warn(MESSAGE)
262
+ }, [MESSAGE, contentRef])
263
+
264
+ return null
265
+ }
266
+
267
+ /* -------------------------------------------------------------------------------------------------
268
+ * AlertDialog
269
+ * -----------------------------------------------------------------------------------------------*/
270
+
271
+ const AlertDialogInner: React.FC<AlertDialogProps> = (props: ScopedProps<AlertDialogProps>) => {
272
+ const { __scopeAlertDialog, ...alertDialogProps } = props
273
+ const dialogScope = useDialogScope(__scopeAlertDialog)
274
+ return <Dialog {...dialogScope} {...alertDialogProps} modal={true} />
275
+ }
276
+
277
+ const AlertDialog = withStaticProperties(AlertDialogInner, {
278
+ Trigger: AlertDialogTrigger,
279
+ Portal: AlertDialogPortal,
280
+ Overlay: AlertDialogOverlay,
281
+ Content: AlertDialogContent,
282
+ Action: AlertDialogAction,
283
+ Cancel: AlertDialogCancel,
284
+ Title: AlertDialogTitle,
285
+ Description: AlertDialogDescription,
286
+ })
287
+
288
+ AlertDialog.displayName = ROOT_NAME
289
+
290
+ export {
291
+ createAlertDialogScope,
292
+ //
293
+ AlertDialog,
294
+ AlertDialogTrigger,
295
+ AlertDialogPortal,
296
+ AlertDialogOverlay,
297
+ AlertDialogContent,
298
+ AlertDialogAction,
299
+ AlertDialogCancel,
300
+ AlertDialogTitle,
301
+ AlertDialogDescription,
302
+ }
303
+ export type {
304
+ AlertDialogProps,
305
+ AlertDialogTriggerProps,
306
+ AlertDialogPortalProps,
307
+ AlertDialogOverlayProps,
308
+ AlertDialogContentProps,
309
+ AlertDialogActionProps,
310
+ AlertDialogCancelProps,
311
+ AlertDialogTitleProps,
312
+ AlertDialogDescriptionProps,
313
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './AlertDialog'