@cdx-ui/primitives 0.0.1-beta.51 → 0.0.1-beta.52
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/README.md +1 -1
- package/lib/commonjs/dialog/createDialogContent.js +7 -127
- package/lib/commonjs/dialog/createDialogContent.js.map +1 -1
- package/lib/commonjs/dialog/createDialogPopup.js +157 -0
- package/lib/commonjs/dialog/createDialogPopup.js.map +1 -0
- package/lib/commonjs/dialog/index.js +8 -8
- package/lib/commonjs/dialog/index.js.map +1 -1
- package/lib/module/dialog/createDialogContent.js +7 -128
- package/lib/module/dialog/createDialogContent.js.map +1 -1
- package/lib/module/dialog/createDialogPopup.js +152 -0
- package/lib/module/dialog/createDialogPopup.js.map +1 -0
- package/lib/module/dialog/index.js +8 -8
- package/lib/module/dialog/index.js.map +1 -1
- package/lib/typescript/dialog/createDialogContent.d.ts +2 -2
- package/lib/typescript/dialog/createDialogContent.d.ts.map +1 -1
- package/lib/typescript/dialog/createDialogPopup.d.ts +4 -0
- package/lib/typescript/dialog/createDialogPopup.d.ts.map +1 -0
- package/lib/typescript/dialog/index.d.ts +5 -5
- package/lib/typescript/dialog/index.d.ts.map +1 -1
- package/lib/typescript/dialog/types.d.ts +16 -5
- package/lib/typescript/dialog/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/dialog/createDialogContent.tsx +6 -117
- package/src/dialog/createDialogPopup.tsx +146 -0
- package/src/dialog/index.tsx +16 -16
- package/src/dialog/types.ts +20 -9
- package/lib/commonjs/dialog/createDialogBody.js +0 -21
- package/lib/commonjs/dialog/createDialogBody.js.map +0 -1
- package/lib/module/dialog/createDialogBody.js +0 -15
- package/lib/module/dialog/createDialogBody.js.map +0 -1
- package/lib/typescript/dialog/createDialogBody.d.ts +0 -4
- package/lib/typescript/dialog/createDialogBody.d.ts.map +0 -1
- package/src/dialog/createDialogBody.tsx +0 -11
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { forwardRef, useCallback } from 'react';
|
|
4
|
+
import { KeyboardAvoidingView, Modal, Platform, StyleSheet, View } from 'react-native';
|
|
5
|
+
import { FocusScope } from '@react-native-aria/focus';
|
|
6
|
+
import { useEscapeKey } from '../overlay';
|
|
7
|
+
import { createPortalFn } from '../utils/createPortal';
|
|
8
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
9
|
+
import { useDialog } from './context';
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
export const createDialogPopup = (BasePopup, BaseOverlay) => /*#__PURE__*/forwardRef(({
|
|
12
|
+
children,
|
|
13
|
+
forceMount = false,
|
|
14
|
+
avoidKeyboard = true,
|
|
15
|
+
keyboardVerticalOffset = 0,
|
|
16
|
+
...props
|
|
17
|
+
}, ref) => {
|
|
18
|
+
const {
|
|
19
|
+
open,
|
|
20
|
+
onOpenChange,
|
|
21
|
+
closeOnBackdropPress,
|
|
22
|
+
closeOnEscKey,
|
|
23
|
+
nativeID,
|
|
24
|
+
role
|
|
25
|
+
} = useDialog();
|
|
26
|
+
const handleClose = useCallback(() => {
|
|
27
|
+
onOpenChange(false);
|
|
28
|
+
}, [onOpenChange]);
|
|
29
|
+
useEscapeKey(open && closeOnEscKey, handleClose);
|
|
30
|
+
if (!(open || forceMount)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const overlayProps = {
|
|
34
|
+
...(closeOnBackdropPress ? {
|
|
35
|
+
onPress: handleClose
|
|
36
|
+
} : {}),
|
|
37
|
+
accessible: false,
|
|
38
|
+
importantForAccessibility: 'no-hide-descendants',
|
|
39
|
+
...dataAttributes({
|
|
40
|
+
slot: 'dialog-overlay'
|
|
41
|
+
})
|
|
42
|
+
};
|
|
43
|
+
const contentSlotAttrs = dataAttributes({
|
|
44
|
+
slot: 'dialog-popup',
|
|
45
|
+
state: open ? 'open' : 'closed'
|
|
46
|
+
});
|
|
47
|
+
const ariaProps = {
|
|
48
|
+
role,
|
|
49
|
+
'aria-modal': true,
|
|
50
|
+
'aria-labelledby': `${nativeID}-title`,
|
|
51
|
+
'aria-describedby': `${nativeID}-description`
|
|
52
|
+
};
|
|
53
|
+
if (Platform.OS === 'web' && createPortalFn) {
|
|
54
|
+
return createPortalFn(/*#__PURE__*/_jsx(FocusScope, {
|
|
55
|
+
contain: open,
|
|
56
|
+
restoreFocus: true,
|
|
57
|
+
autoFocus: open,
|
|
58
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
59
|
+
style: {
|
|
60
|
+
position: 'fixed',
|
|
61
|
+
inset: 0,
|
|
62
|
+
zIndex: 50,
|
|
63
|
+
display: 'flex',
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
justifyContent: 'center'
|
|
66
|
+
},
|
|
67
|
+
children: [/*#__PURE__*/_jsx(BaseOverlay, {
|
|
68
|
+
...overlayProps
|
|
69
|
+
}), /*#__PURE__*/_jsx(BasePopup, {
|
|
70
|
+
ref: ref,
|
|
71
|
+
...contentSlotAttrs,
|
|
72
|
+
...props,
|
|
73
|
+
...ariaProps,
|
|
74
|
+
children: children
|
|
75
|
+
})]
|
|
76
|
+
})
|
|
77
|
+
}), document.body);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Native layout uses two layers to support both backdrop dismiss and
|
|
81
|
+
// scrollable body content. The overlay Pressable fills the Modal via
|
|
82
|
+
// absolute positioning and handles backdrop taps. A second flex layer with
|
|
83
|
+
// pointerEvents="box-none" centers the content panel — "box-none" lets taps
|
|
84
|
+
// outside the panel pass through to the overlay while allowing the panel and
|
|
85
|
+
// its children to receive touches normally.
|
|
86
|
+
//
|
|
87
|
+
// That centering layer is a KeyboardAvoidingView so the panel (including its
|
|
88
|
+
// footer/actions, which sit at the bottom of a centered, max-h-capped panel)
|
|
89
|
+
// shifts up to clear the on-screen keyboard. `behavior` is platform-specific
|
|
90
|
+
// and the layer is a no-op while no input is focused. The RN Modal renders in
|
|
91
|
+
// its own window, so this MUST live here — a KeyboardAvoidingView wrapping the
|
|
92
|
+
// <Dialog> at the usage level cannot reach this subtree. Web is unaffected
|
|
93
|
+
// (the browser handles focus scrolling; there is no occluding keyboard).
|
|
94
|
+
//
|
|
95
|
+
// Critically, the content panel must NOT claim the JS touch responder
|
|
96
|
+
// (e.g. via onStartShouldSetResponder). Doing so triggers React Native's
|
|
97
|
+
// blockNativeResponder, which suppresses the native UIScrollView /
|
|
98
|
+
// ScrollView pan gesture recognizer and breaks any ScrollView inside
|
|
99
|
+
// Dialog.Content.
|
|
100
|
+
//
|
|
101
|
+
// Static StyleSheet used here because these are structural layout concerns
|
|
102
|
+
// of the primitive's modal chrome — not themeable styles. They must remain
|
|
103
|
+
// stable regardless of the styled layer's className.
|
|
104
|
+
const keyboardBehavior = avoidKeyboard ? Platform.select({
|
|
105
|
+
ios: 'padding',
|
|
106
|
+
default: 'height'
|
|
107
|
+
}) : undefined;
|
|
108
|
+
return /*#__PURE__*/_jsx(Modal, {
|
|
109
|
+
visible: open,
|
|
110
|
+
transparent: true,
|
|
111
|
+
statusBarTranslucent: true,
|
|
112
|
+
onRequestClose: handleClose,
|
|
113
|
+
children: /*#__PURE__*/_jsx(FocusScope, {
|
|
114
|
+
contain: open,
|
|
115
|
+
restoreFocus: true,
|
|
116
|
+
autoFocus: open,
|
|
117
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
118
|
+
style: styles.fill,
|
|
119
|
+
children: [/*#__PURE__*/_jsx(BaseOverlay, {
|
|
120
|
+
...overlayProps
|
|
121
|
+
}), /*#__PURE__*/_jsx(KeyboardAvoidingView, {
|
|
122
|
+
style: styles.center,
|
|
123
|
+
pointerEvents: "box-none",
|
|
124
|
+
behavior: keyboardBehavior,
|
|
125
|
+
keyboardVerticalOffset: keyboardVerticalOffset,
|
|
126
|
+
children: /*#__PURE__*/_jsx(BasePopup, {
|
|
127
|
+
ref: ref,
|
|
128
|
+
...contentSlotAttrs,
|
|
129
|
+
...props,
|
|
130
|
+
...ariaProps,
|
|
131
|
+
children: children
|
|
132
|
+
})
|
|
133
|
+
})]
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Structural layout for the native Modal chrome. These are not themeable —
|
|
140
|
+
// they position the overlay and centering layers that the primitive manages
|
|
141
|
+
// internally. Matches the pattern in OverlayContainer.tsx.
|
|
142
|
+
const styles = StyleSheet.create({
|
|
143
|
+
fill: {
|
|
144
|
+
flex: 1
|
|
145
|
+
},
|
|
146
|
+
center: {
|
|
147
|
+
flex: 1,
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
justifyContent: 'center'
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=createDialogPopup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["forwardRef","useCallback","KeyboardAvoidingView","Modal","Platform","StyleSheet","View","FocusScope","useEscapeKey","createPortalFn","dataAttributes","useDialog","jsx","_jsx","jsxs","_jsxs","createDialogPopup","BasePopup","BaseOverlay","children","forceMount","avoidKeyboard","keyboardVerticalOffset","props","ref","open","onOpenChange","closeOnBackdropPress","closeOnEscKey","nativeID","role","handleClose","overlayProps","onPress","accessible","importantForAccessibility","slot","contentSlotAttrs","state","ariaProps","OS","contain","restoreFocus","autoFocus","style","position","inset","zIndex","display","alignItems","justifyContent","document","body","keyboardBehavior","select","ios","default","undefined","visible","transparent","statusBarTranslucent","onRequestClose","styles","fill","center","pointerEvents","behavior","create","flex"],"sourceRoot":"../../../src","sources":["dialog/createDialogPopup.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import { createDialogRoot } from './createDialogRoot';
|
|
4
4
|
import { createDialogTrigger } from './createDialogTrigger';
|
|
5
|
-
import {
|
|
5
|
+
import { createDialogPopup } from './createDialogPopup';
|
|
6
6
|
import { createDialogHeader } from './createDialogHeader';
|
|
7
7
|
import { createDialogTitle } from './createDialogTitle';
|
|
8
8
|
import { createDialogDescription } from './createDialogDescription';
|
|
9
|
-
import {
|
|
9
|
+
import { createDialogContent } from './createDialogContent';
|
|
10
10
|
import { createDialogFooter } from './createDialogFooter';
|
|
11
11
|
import { createDialogClose } from './createDialogClose';
|
|
12
12
|
import { DialogProvider, useDialog } from './context';
|
|
@@ -14,30 +14,30 @@ export { DialogProvider, useDialog };
|
|
|
14
14
|
export function createDialog(BaseComponents) {
|
|
15
15
|
const Root = createDialogRoot(BaseComponents.Root);
|
|
16
16
|
const Trigger = createDialogTrigger(BaseComponents.Trigger);
|
|
17
|
-
const
|
|
17
|
+
const Popup = createDialogPopup(BaseComponents.Popup, BaseComponents.Overlay);
|
|
18
18
|
const Header = createDialogHeader(BaseComponents.Header);
|
|
19
19
|
const Title = createDialogTitle(BaseComponents.Title);
|
|
20
20
|
const Description = createDialogDescription(BaseComponents.Description);
|
|
21
|
-
const
|
|
21
|
+
const Content = createDialogContent(BaseComponents.Content);
|
|
22
22
|
const Footer = createDialogFooter(BaseComponents.Footer);
|
|
23
23
|
const Close = createDialogClose(BaseComponents.Close);
|
|
24
24
|
Root.displayName = 'DialogPrimitive.Root';
|
|
25
25
|
Trigger.displayName = 'DialogPrimitive.Trigger';
|
|
26
|
-
|
|
26
|
+
Popup.displayName = 'DialogPrimitive.Popup';
|
|
27
27
|
Header.displayName = 'DialogPrimitive.Header';
|
|
28
28
|
Title.displayName = 'DialogPrimitive.Title';
|
|
29
29
|
Description.displayName = 'DialogPrimitive.Description';
|
|
30
|
-
|
|
30
|
+
Content.displayName = 'DialogPrimitive.Content';
|
|
31
31
|
Footer.displayName = 'DialogPrimitive.Footer';
|
|
32
32
|
Close.displayName = 'DialogPrimitive.Close';
|
|
33
33
|
return Object.assign(Root, {
|
|
34
34
|
Root,
|
|
35
35
|
Trigger,
|
|
36
|
-
|
|
36
|
+
Popup,
|
|
37
37
|
Header,
|
|
38
38
|
Title,
|
|
39
39
|
Description,
|
|
40
|
-
|
|
40
|
+
Content,
|
|
41
41
|
Footer,
|
|
42
42
|
Close
|
|
43
43
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createDialogRoot","createDialogTrigger","
|
|
1
|
+
{"version":3,"names":["createDialogRoot","createDialogTrigger","createDialogPopup","createDialogHeader","createDialogTitle","createDialogDescription","createDialogContent","createDialogFooter","createDialogClose","DialogProvider","useDialog","createDialog","BaseComponents","Root","Trigger","Popup","Overlay","Header","Title","Description","Content","Footer","Close","displayName","Object","assign"],"sourceRoot":"../../../src","sources":["dialog/index.tsx"],"mappings":";;AACA,SAASA,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,mBAAmB,QAAQ,uBAAuB;AAC3D,SAASC,iBAAiB,QAAQ,qBAAqB;AACvD,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,iBAAiB,QAAQ,qBAAqB;AACvD,SAASC,uBAAuB,QAAQ,2BAA2B;AACnE,SAASC,mBAAmB,QAAQ,uBAAuB;AAC3D,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,iBAAiB,QAAQ,qBAAqB;AACvD,SAASC,cAAc,EAAEC,SAAS,QAAQ,WAAW;AAGrD,SAASD,cAAc,EAAEC,SAAS;AAelC,OAAO,SAASC,YAAYA,CAW1BC,cAWD,EAAE;EACD,MAAMC,IAAI,GAAGb,gBAAgB,CAACY,cAAc,CAACC,IAAI,CAAC;EAClD,MAAMC,OAAO,GAAGb,mBAAmB,CAACW,cAAc,CAACE,OAAO,CAAC;EAC3D,MAAMC,KAAK,GAAGb,iBAAiB,CAACU,cAAc,CAACG,KAAK,EAAEH,cAAc,CAACI,OAAO,CAAC;EAC7E,MAAMC,MAAM,GAAGd,kBAAkB,CAACS,cAAc,CAACK,MAAM,CAAC;EACxD,MAAMC,KAAK,GAAGd,iBAAiB,CAACQ,cAAc,CAACM,KAAK,CAAC;EACrD,MAAMC,WAAW,GAAGd,uBAAuB,CAACO,cAAc,CAACO,WAAW,CAAC;EACvE,MAAMC,OAAO,GAAGd,mBAAmB,CAACM,cAAc,CAACQ,OAAO,CAAC;EAC3D,MAAMC,MAAM,GAAGd,kBAAkB,CAACK,cAAc,CAACS,MAAM,CAAC;EACxD,MAAMC,KAAK,GAAGd,iBAAiB,CAACI,cAAc,CAACU,KAAK,CAAC;EAErDT,IAAI,CAACU,WAAW,GAAG,sBAAsB;EACzCT,OAAO,CAACS,WAAW,GAAG,yBAAyB;EAC/CR,KAAK,CAACQ,WAAW,GAAG,uBAAuB;EAC3CN,MAAM,CAACM,WAAW,GAAG,wBAAwB;EAC7CL,KAAK,CAACK,WAAW,GAAG,uBAAuB;EAC3CJ,WAAW,CAACI,WAAW,GAAG,6BAA6B;EACvDH,OAAO,CAACG,WAAW,GAAG,yBAAyB;EAC/CF,MAAM,CAACE,WAAW,GAAG,wBAAwB;EAC7CD,KAAK,CAACC,WAAW,GAAG,uBAAuB;EAE3C,OAAOC,MAAM,CAACC,MAAM,CAACZ,IAAI,EAAE;IACzBA,IAAI;IACJC,OAAO;IACPC,KAAK;IACLE,MAAM;IACNC,KAAK;IACLC,WAAW;IACXC,OAAO;IACPC,MAAM;IACNC;EACF,CAAC,CAAC;AAWJ","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import type { IDialogContentProps } from './types';
|
|
3
|
-
export declare const createDialogContent: <
|
|
3
|
+
export declare const createDialogContent: <T>(BaseContent: React.ComponentType<T>) => React.ForwardRefExoticComponent<IDialogContentProps & React.RefAttributes<unknown>>;
|
|
4
4
|
//# sourceMappingURL=createDialogContent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDialogContent.d.ts","sourceRoot":"","sources":["../../../src/dialog/createDialogContent.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"createDialogContent.d.ts","sourceRoot":"","sources":["../../../src/dialog/createDialogContent.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAG,aAAa,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,wFAOvE,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { IDialogPopupProps } from './types';
|
|
3
|
+
export declare const createDialogPopup: <PopupProps, OverlayProps>(BasePopup: React.ComponentType<PopupProps>, BaseOverlay: React.ComponentType<OverlayProps>) => React.ForwardRefExoticComponent<IDialogPopupProps & React.RefAttributes<unknown>>;
|
|
4
|
+
//# sourceMappingURL=createDialogPopup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDialogPopup.d.ts","sourceRoot":"","sources":["../../../src/dialog/createDialogPopup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,iBAAiB,GAAI,UAAU,EAAE,YAAY,EACxD,WAAW,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,EAC1C,aAAa,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,sFAyH7C,CAAC"}
|
|
@@ -2,17 +2,17 @@ import type React from 'react';
|
|
|
2
2
|
import { DialogProvider, useDialog } from './context';
|
|
3
3
|
import type { IDialogComponentType } from './types';
|
|
4
4
|
export { DialogProvider, useDialog };
|
|
5
|
-
export type { IDialogContextType, IDialogRootProps, IDialogTriggerProps,
|
|
6
|
-
export declare function createDialog<RootProps, TriggerProps,
|
|
5
|
+
export type { IDialogContextType, IDialogRootProps, IDialogTriggerProps, IDialogPopupProps, IDialogOverlayProps, IDialogHeaderProps, IDialogTitleProps, IDialogDescriptionProps, IDialogContentProps, IDialogFooterProps, IDialogCloseProps, } from './types';
|
|
6
|
+
export declare function createDialog<RootProps, TriggerProps, PopupProps, OverlayProps, HeaderProps, TitleProps, DescriptionProps, ContentProps, FooterProps, CloseProps>(BaseComponents: {
|
|
7
7
|
Root: React.ComponentType<RootProps>;
|
|
8
8
|
Trigger: React.ComponentType<TriggerProps>;
|
|
9
|
-
|
|
9
|
+
Popup: React.ComponentType<PopupProps>;
|
|
10
10
|
Overlay: React.ComponentType<OverlayProps>;
|
|
11
11
|
Header: React.ComponentType<HeaderProps>;
|
|
12
12
|
Title: React.ComponentType<TitleProps>;
|
|
13
13
|
Description: React.ComponentType<DescriptionProps>;
|
|
14
|
-
|
|
14
|
+
Content: React.ComponentType<ContentProps>;
|
|
15
15
|
Footer: React.ComponentType<FooterProps>;
|
|
16
16
|
Close: React.ComponentType<CloseProps>;
|
|
17
|
-
}): IDialogComponentType<RootProps, TriggerProps,
|
|
17
|
+
}): IDialogComponentType<RootProps, TriggerProps, PopupProps, HeaderProps, TitleProps, DescriptionProps, ContentProps, FooterProps, CloseProps>;
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dialog/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dialog/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,YAAY,CAC1B,SAAS,EACT,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,cAAc,EAAE;IAChB,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC3C,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACvC,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;CACxC,GA+BO,oBAAoB,CACxB,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,UAAU,CACX,CACF"}
|
|
@@ -20,8 +20,19 @@ export interface IDialogRootProps {
|
|
|
20
20
|
export interface IDialogTriggerProps extends PressableProps {
|
|
21
21
|
readonly asChild?: boolean;
|
|
22
22
|
}
|
|
23
|
-
export interface
|
|
23
|
+
export interface IDialogPopupProps extends ViewProps {
|
|
24
24
|
readonly forceMount?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the popup shifts up to clear the on-screen keyboard (native only).
|
|
27
|
+
* No-op on web. Defaults to `true`.
|
|
28
|
+
*/
|
|
29
|
+
readonly avoidKeyboard?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Distance (in px) between the keyboard and the popup when keyboard avoidance
|
|
32
|
+
* is active. Forwarded to the underlying keyboard-avoiding layer on native.
|
|
33
|
+
* Defaults to `0`.
|
|
34
|
+
*/
|
|
35
|
+
readonly keyboardVerticalOffset?: number;
|
|
25
36
|
}
|
|
26
37
|
export interface IDialogOverlayProps extends PressableProps {
|
|
27
38
|
}
|
|
@@ -31,7 +42,7 @@ export interface IDialogTitleProps extends TextProps {
|
|
|
31
42
|
}
|
|
32
43
|
export interface IDialogDescriptionProps extends TextProps {
|
|
33
44
|
}
|
|
34
|
-
export interface
|
|
45
|
+
export interface IDialogContentProps extends ViewProps {
|
|
35
46
|
}
|
|
36
47
|
export interface IDialogFooterProps extends ViewProps {
|
|
37
48
|
}
|
|
@@ -39,13 +50,13 @@ export interface IDialogCloseProps extends PressableProps {
|
|
|
39
50
|
readonly asChild?: boolean;
|
|
40
51
|
readonly accessibilityLabel?: string;
|
|
41
52
|
}
|
|
42
|
-
export type IDialogComponentType<RootProps, TriggerProps,
|
|
53
|
+
export type IDialogComponentType<RootProps, TriggerProps, PopupProps, HeaderProps, TitleProps, DescriptionProps, ContentProps, FooterProps, CloseProps, PopupRef = unknown, TriggerRef = unknown, CloseRef = unknown> = React.ForwardRefExoticComponent<PropsWithoutRef<RootProps & IDialogRootProps> & RefAttributes<unknown>> & {
|
|
43
54
|
Trigger: React.ForwardRefExoticComponent<PropsWithoutRef<TriggerProps & IDialogTriggerProps> & RefAttributes<TriggerRef>>;
|
|
44
|
-
|
|
55
|
+
Popup: React.ForwardRefExoticComponent<PropsWithoutRef<PopupProps & IDialogPopupProps> & RefAttributes<PopupRef>>;
|
|
45
56
|
Header: React.ForwardRefExoticComponent<PropsWithoutRef<HeaderProps & IDialogHeaderProps> & RefAttributes<unknown>>;
|
|
46
57
|
Title: React.ForwardRefExoticComponent<PropsWithoutRef<TitleProps & IDialogTitleProps> & RefAttributes<unknown>>;
|
|
47
58
|
Description: React.ForwardRefExoticComponent<PropsWithoutRef<DescriptionProps & IDialogDescriptionProps> & RefAttributes<unknown>>;
|
|
48
|
-
|
|
59
|
+
Content: React.ForwardRefExoticComponent<PropsWithoutRef<ContentProps & IDialogContentProps> & RefAttributes<unknown>>;
|
|
49
60
|
Footer: React.ForwardRefExoticComponent<PropsWithoutRef<FooterProps & IDialogFooterProps> & RefAttributes<unknown>>;
|
|
50
61
|
Close: React.ForwardRefExoticComponent<PropsWithoutRef<CloseProps & IDialogCloseProps> & RefAttributes<CloseRef>>;
|
|
51
62
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/dialog/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/dialog/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdx-ui/primitives",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.52",
|
|
4
4
|
"main": "lib/commonjs/index.js",
|
|
5
5
|
"module": "lib/module/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@react-stately/checkbox": "3.7.4",
|
|
61
61
|
"@react-stately/radio": "3.12.0",
|
|
62
62
|
"@react-stately/toggle": "3.9.4",
|
|
63
|
-
"@cdx-ui/utils": "0.0.1-beta.
|
|
63
|
+
"@cdx-ui/utils": "0.0.1-beta.52"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/react": "*",
|
|
@@ -1,122 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef, useCallback } from 'react';
|
|
3
|
-
import { Modal, Platform, StyleSheet, View } from 'react-native';
|
|
4
|
-
import { FocusScope } from '@react-native-aria/focus';
|
|
5
|
-
import { useEscapeKey } from '../overlay';
|
|
6
|
-
import { createPortalFn } from '../utils/createPortal';
|
|
7
|
-
import { dataAttributes } from '../utils/dataAttributes';
|
|
8
|
-
import { useDialog } from './context';
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
9
2
|
import type { IDialogContentProps } from './types';
|
|
10
3
|
|
|
11
|
-
export const createDialogContent = <
|
|
12
|
-
|
|
13
|
-
BaseOverlay: React.ComponentType<OverlayProps>,
|
|
14
|
-
) =>
|
|
15
|
-
forwardRef(({ children, forceMount = false, ...props }: IDialogContentProps, ref?: any) => {
|
|
16
|
-
const { open, onOpenChange, closeOnBackdropPress, closeOnEscKey, nativeID, role } = useDialog();
|
|
17
|
-
|
|
18
|
-
const handleClose = useCallback(() => {
|
|
19
|
-
onOpenChange(false);
|
|
20
|
-
}, [onOpenChange]);
|
|
21
|
-
|
|
22
|
-
useEscapeKey(open && closeOnEscKey, handleClose);
|
|
23
|
-
|
|
24
|
-
if (!(open || forceMount)) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const overlayProps = {
|
|
29
|
-
...(closeOnBackdropPress ? { onPress: handleClose } : {}),
|
|
30
|
-
accessible: false,
|
|
31
|
-
importantForAccessibility: 'no-hide-descendants' as const,
|
|
32
|
-
...dataAttributes({ slot: 'dialog-overlay' }),
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const contentSlotAttrs = dataAttributes({
|
|
36
|
-
slot: 'dialog-content',
|
|
37
|
-
state: open ? 'open' : 'closed',
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const ariaProps = {
|
|
41
|
-
role,
|
|
42
|
-
'aria-modal': true,
|
|
43
|
-
'aria-labelledby': `${nativeID}-title`,
|
|
44
|
-
'aria-describedby': `${nativeID}-description`,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
if (Platform.OS === 'web' && createPortalFn) {
|
|
48
|
-
return createPortalFn(
|
|
49
|
-
<FocusScope contain={open} restoreFocus autoFocus={open}>
|
|
50
|
-
<View
|
|
51
|
-
style={{
|
|
52
|
-
position: 'fixed' as any,
|
|
53
|
-
inset: 0 as any,
|
|
54
|
-
zIndex: 50,
|
|
55
|
-
display: 'flex' as any,
|
|
56
|
-
alignItems: 'center',
|
|
57
|
-
justifyContent: 'center',
|
|
58
|
-
}}
|
|
59
|
-
>
|
|
60
|
-
<BaseOverlay {...(overlayProps as any)} />
|
|
61
|
-
<BaseContent
|
|
62
|
-
ref={ref}
|
|
63
|
-
{...contentSlotAttrs}
|
|
64
|
-
{...(props as ContentProps)}
|
|
65
|
-
{...ariaProps}
|
|
66
|
-
>
|
|
67
|
-
{children}
|
|
68
|
-
</BaseContent>
|
|
69
|
-
</View>
|
|
70
|
-
</FocusScope>,
|
|
71
|
-
document.body,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Native layout uses two layers to support both backdrop dismiss and
|
|
76
|
-
// scrollable body content. The overlay Pressable fills the Modal via
|
|
77
|
-
// absolute positioning and handles backdrop taps. A second absolute-fill
|
|
78
|
-
// View with pointerEvents="box-none" centers the content panel — "box-none"
|
|
79
|
-
// lets taps outside the panel pass through to the overlay while allowing
|
|
80
|
-
// the panel and its children to receive touches normally.
|
|
81
|
-
//
|
|
82
|
-
// Critically, the content panel must NOT claim the JS touch responder
|
|
83
|
-
// (e.g. via onStartShouldSetResponder). Doing so triggers React Native's
|
|
84
|
-
// blockNativeResponder, which suppresses the native UIScrollView /
|
|
85
|
-
// ScrollView pan gesture recognizer and breaks any ScrollView inside
|
|
86
|
-
// Dialog.Body.
|
|
87
|
-
//
|
|
88
|
-
// Static StyleSheet used here because these are structural layout concerns
|
|
89
|
-
// of the primitive's modal chrome — not themeable styles. They must remain
|
|
90
|
-
// stable regardless of the styled layer's className.
|
|
4
|
+
export const createDialogContent = <T,>(BaseContent: React.ComponentType<T>) =>
|
|
5
|
+
forwardRef<unknown, IDialogContentProps>(({ children, ...props }, ref) => {
|
|
91
6
|
return (
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<BaseOverlay {...(overlayProps as any)} />
|
|
96
|
-
<View style={styles.center} pointerEvents="box-none">
|
|
97
|
-
<BaseContent
|
|
98
|
-
ref={ref}
|
|
99
|
-
{...contentSlotAttrs}
|
|
100
|
-
{...(props as ContentProps)}
|
|
101
|
-
{...ariaProps}
|
|
102
|
-
>
|
|
103
|
-
{children}
|
|
104
|
-
</BaseContent>
|
|
105
|
-
</View>
|
|
106
|
-
</View>
|
|
107
|
-
</FocusScope>
|
|
108
|
-
</Modal>
|
|
7
|
+
<BaseContent ref={ref} {...(props as T)}>
|
|
8
|
+
{children}
|
|
9
|
+
</BaseContent>
|
|
109
10
|
);
|
|
110
11
|
});
|
|
111
|
-
|
|
112
|
-
// Structural layout for the native Modal chrome. These are not themeable —
|
|
113
|
-
// they position the overlay and centering layers that the primitive manages
|
|
114
|
-
// internally. Matches the pattern in OverlayContainer.tsx.
|
|
115
|
-
const styles = StyleSheet.create({
|
|
116
|
-
fill: { flex: 1 },
|
|
117
|
-
center: {
|
|
118
|
-
...StyleSheet.absoluteFillObject,
|
|
119
|
-
alignItems: 'center',
|
|
120
|
-
justifyContent: 'center',
|
|
121
|
-
},
|
|
122
|
-
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { forwardRef, useCallback } from 'react';
|
|
3
|
+
import { KeyboardAvoidingView, Modal, Platform, StyleSheet, View } from 'react-native';
|
|
4
|
+
import { FocusScope } from '@react-native-aria/focus';
|
|
5
|
+
import { useEscapeKey } from '../overlay';
|
|
6
|
+
import { createPortalFn } from '../utils/createPortal';
|
|
7
|
+
import { dataAttributes } from '../utils/dataAttributes';
|
|
8
|
+
import { useDialog } from './context';
|
|
9
|
+
import type { IDialogPopupProps } from './types';
|
|
10
|
+
|
|
11
|
+
export const createDialogPopup = <PopupProps, OverlayProps>(
|
|
12
|
+
BasePopup: React.ComponentType<PopupProps>,
|
|
13
|
+
BaseOverlay: React.ComponentType<OverlayProps>,
|
|
14
|
+
) =>
|
|
15
|
+
forwardRef(
|
|
16
|
+
(
|
|
17
|
+
{
|
|
18
|
+
children,
|
|
19
|
+
forceMount = false,
|
|
20
|
+
avoidKeyboard = true,
|
|
21
|
+
keyboardVerticalOffset = 0,
|
|
22
|
+
...props
|
|
23
|
+
}: IDialogPopupProps,
|
|
24
|
+
ref?: any,
|
|
25
|
+
) => {
|
|
26
|
+
const { open, onOpenChange, closeOnBackdropPress, closeOnEscKey, nativeID, role } =
|
|
27
|
+
useDialog();
|
|
28
|
+
|
|
29
|
+
const handleClose = useCallback(() => {
|
|
30
|
+
onOpenChange(false);
|
|
31
|
+
}, [onOpenChange]);
|
|
32
|
+
|
|
33
|
+
useEscapeKey(open && closeOnEscKey, handleClose);
|
|
34
|
+
|
|
35
|
+
if (!(open || forceMount)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const overlayProps = {
|
|
40
|
+
...(closeOnBackdropPress ? { onPress: handleClose } : {}),
|
|
41
|
+
accessible: false,
|
|
42
|
+
importantForAccessibility: 'no-hide-descendants' as const,
|
|
43
|
+
...dataAttributes({ slot: 'dialog-overlay' }),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const contentSlotAttrs = dataAttributes({
|
|
47
|
+
slot: 'dialog-popup',
|
|
48
|
+
state: open ? 'open' : 'closed',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const ariaProps = {
|
|
52
|
+
role,
|
|
53
|
+
'aria-modal': true,
|
|
54
|
+
'aria-labelledby': `${nativeID}-title`,
|
|
55
|
+
'aria-describedby': `${nativeID}-description`,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (Platform.OS === 'web' && createPortalFn) {
|
|
59
|
+
return createPortalFn(
|
|
60
|
+
<FocusScope contain={open} restoreFocus autoFocus={open}>
|
|
61
|
+
<View
|
|
62
|
+
style={{
|
|
63
|
+
position: 'fixed' as any,
|
|
64
|
+
inset: 0 as any,
|
|
65
|
+
zIndex: 50,
|
|
66
|
+
display: 'flex' as any,
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
<BaseOverlay {...(overlayProps as any)} />
|
|
72
|
+
<BasePopup ref={ref} {...contentSlotAttrs} {...(props as PopupProps)} {...ariaProps}>
|
|
73
|
+
{children}
|
|
74
|
+
</BasePopup>
|
|
75
|
+
</View>
|
|
76
|
+
</FocusScope>,
|
|
77
|
+
document.body,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Native layout uses two layers to support both backdrop dismiss and
|
|
82
|
+
// scrollable body content. The overlay Pressable fills the Modal via
|
|
83
|
+
// absolute positioning and handles backdrop taps. A second flex layer with
|
|
84
|
+
// pointerEvents="box-none" centers the content panel — "box-none" lets taps
|
|
85
|
+
// outside the panel pass through to the overlay while allowing the panel and
|
|
86
|
+
// its children to receive touches normally.
|
|
87
|
+
//
|
|
88
|
+
// That centering layer is a KeyboardAvoidingView so the panel (including its
|
|
89
|
+
// footer/actions, which sit at the bottom of a centered, max-h-capped panel)
|
|
90
|
+
// shifts up to clear the on-screen keyboard. `behavior` is platform-specific
|
|
91
|
+
// and the layer is a no-op while no input is focused. The RN Modal renders in
|
|
92
|
+
// its own window, so this MUST live here — a KeyboardAvoidingView wrapping the
|
|
93
|
+
// <Dialog> at the usage level cannot reach this subtree. Web is unaffected
|
|
94
|
+
// (the browser handles focus scrolling; there is no occluding keyboard).
|
|
95
|
+
//
|
|
96
|
+
// Critically, the content panel must NOT claim the JS touch responder
|
|
97
|
+
// (e.g. via onStartShouldSetResponder). Doing so triggers React Native's
|
|
98
|
+
// blockNativeResponder, which suppresses the native UIScrollView /
|
|
99
|
+
// ScrollView pan gesture recognizer and breaks any ScrollView inside
|
|
100
|
+
// Dialog.Content.
|
|
101
|
+
//
|
|
102
|
+
// Static StyleSheet used here because these are structural layout concerns
|
|
103
|
+
// of the primitive's modal chrome — not themeable styles. They must remain
|
|
104
|
+
// stable regardless of the styled layer's className.
|
|
105
|
+
const keyboardBehavior = avoidKeyboard
|
|
106
|
+
? Platform.select<'padding' | 'height'>({ ios: 'padding', default: 'height' })
|
|
107
|
+
: undefined;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<Modal visible={open} transparent statusBarTranslucent onRequestClose={handleClose}>
|
|
111
|
+
<FocusScope contain={open} restoreFocus autoFocus={open}>
|
|
112
|
+
<View style={styles.fill}>
|
|
113
|
+
<BaseOverlay {...(overlayProps as any)} />
|
|
114
|
+
<KeyboardAvoidingView
|
|
115
|
+
style={styles.center}
|
|
116
|
+
pointerEvents="box-none"
|
|
117
|
+
behavior={keyboardBehavior}
|
|
118
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
119
|
+
>
|
|
120
|
+
<BasePopup
|
|
121
|
+
ref={ref}
|
|
122
|
+
{...contentSlotAttrs}
|
|
123
|
+
{...(props as PopupProps)}
|
|
124
|
+
{...ariaProps}
|
|
125
|
+
>
|
|
126
|
+
{children}
|
|
127
|
+
</BasePopup>
|
|
128
|
+
</KeyboardAvoidingView>
|
|
129
|
+
</View>
|
|
130
|
+
</FocusScope>
|
|
131
|
+
</Modal>
|
|
132
|
+
);
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Structural layout for the native Modal chrome. These are not themeable —
|
|
137
|
+
// they position the overlay and centering layers that the primitive manages
|
|
138
|
+
// internally. Matches the pattern in OverlayContainer.tsx.
|
|
139
|
+
const styles = StyleSheet.create({
|
|
140
|
+
fill: { flex: 1 },
|
|
141
|
+
center: {
|
|
142
|
+
flex: 1,
|
|
143
|
+
alignItems: 'center',
|
|
144
|
+
justifyContent: 'center',
|
|
145
|
+
},
|
|
146
|
+
});
|