@impulse-ui-native/modal 0.0.0-stage → 7.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.
- package/LICENSE +21 -0
- package/README.md +143 -2
- package/dist/components/close.d.mts +11 -0
- package/dist/components/close.js +49 -0
- package/dist/components/close.js.map +1 -0
- package/dist/components/content.d.mts +11 -0
- package/dist/components/content.js +29 -0
- package/dist/components/content.js.map +1 -0
- package/dist/components/description.d.mts +11 -0
- package/dist/components/description.js +20 -0
- package/dist/components/description.js.map +1 -0
- package/dist/components/footer.d.mts +11 -0
- package/dist/components/footer.js +33 -0
- package/dist/components/footer.js.map +1 -0
- package/dist/components/header.d.mts +11 -0
- package/dist/components/header.js +32 -0
- package/dist/components/header.js.map +1 -0
- package/dist/components/index.d.mts +22 -0
- package/dist/components/index.js +23 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/modal.d.mts +11 -0
- package/dist/components/modal.js +56 -0
- package/dist/components/modal.js.map +1 -0
- package/dist/components/provider.d.mts +11 -0
- package/dist/components/provider.js +17 -0
- package/dist/components/provider.js.map +1 -0
- package/dist/components/root.d.mts +11 -0
- package/dist/components/root.js +96 -0
- package/dist/components/root.js.map +1 -0
- package/dist/components/surface.d.mts +11 -0
- package/dist/components/surface.js +37 -0
- package/dist/components/surface.js.map +1 -0
- package/dist/components/title.d.mts +11 -0
- package/dist/components/title.js +21 -0
- package/dist/components/title.js.map +1 -0
- package/dist/constants/modal.constants.d.mts +4 -0
- package/dist/constants/modal.constants.js +7 -0
- package/dist/constants/modal.constants.js.map +1 -0
- package/dist/contexts/modal.context.d.mts +10 -0
- package/dist/contexts/modal.context.js +8 -0
- package/dist/contexts/modal.context.js.map +1 -0
- package/dist/hooks/use-modal-context.hook.d.mts +10 -0
- package/dist/hooks/use-modal-context.hook.js +13 -0
- package/dist/hooks/use-modal-context.hook.js.map +1 -0
- package/dist/hooks/use-modal-lifecycle.hook.d.mts +17 -0
- package/dist/hooks/use-modal-lifecycle.hook.js +46 -0
- package/dist/hooks/use-modal-lifecycle.hook.js.map +1 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.mts +6 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/modal.types.d.mts +36 -0
- package/dist/types/modal.types.js +1 -0
- package/dist/types/modal.types.js.map +1 -0
- package/package.json +64 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ImpulseUI Native contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,144 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @impulse-ui-native/modal
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A compact, themed native dialog with compound presentation parts and an overlay
|
|
4
|
+
lifecycle. Use it locally inside a Portal or register it globally with OverlayHost.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
pnpm add @impulse-ui-native/modal react-native-reanimated react-native-safe-area-context react-native-worklets
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Complete the native setup for Reanimated and Worklets, and wrap the application
|
|
13
|
+
in ThemeProvider and SafeAreaProvider. Local portal usage additionally requires
|
|
14
|
+
@impulse-ui-native/portal with PortalProvider and PortalsHost. Global usage requires
|
|
15
|
+
@impulse-ui-native/overlay with OverlayProvider and OverlayHost. The toolkit exports Modal.
|
|
16
|
+
|
|
17
|
+
## Local composition
|
|
18
|
+
|
|
19
|
+
Keep Portal mounted and control open from the nearby trigger:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Modal } from "@impulse-ui-native/modal";
|
|
23
|
+
import { Portal } from "@impulse-ui-native/portal";
|
|
24
|
+
import { Button } from "@impulse-ui-native/primitives";
|
|
25
|
+
|
|
26
|
+
<>
|
|
27
|
+
<Button onPress={() => setOpen(true)}>Project details</Button>
|
|
28
|
+
<Portal>
|
|
29
|
+
<Modal
|
|
30
|
+
id="project-details"
|
|
31
|
+
open={open}
|
|
32
|
+
title="Project details"
|
|
33
|
+
onClose={() => setOpen(false)}
|
|
34
|
+
footer={<Button onPress={() => setOpen(false)}>Done</Button>}
|
|
35
|
+
>
|
|
36
|
+
<Modal.Description>Review the project details.</Modal.Description>
|
|
37
|
+
</Modal>
|
|
38
|
+
</Portal>
|
|
39
|
+
</>;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Modal composes Provider, Root, Header, Close, Content, and Footer, with an X close button in the
|
|
43
|
+
header by default, using the neutral text.tertiary color to match the Popover close icon. Set hideClose to omit it. A truthy header replaces the
|
|
44
|
+
generated title beside the close button; a truthy footer renders the footer. Root supplies the
|
|
45
|
+
centered surface, safe-area padding, backdrop, Android back dismissal, and animations.
|
|
46
|
+
Provider owns the lifecycle and shares state with Root and Close. Root renders the container. Neither installs a Portal; put Provider inside the local Portal so its context reaches the dialog without bridging.
|
|
47
|
+
|
|
48
|
+
## Compound composition
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<Portal>
|
|
52
|
+
<Modal.Provider
|
|
53
|
+
id="project-details"
|
|
54
|
+
open={open}
|
|
55
|
+
onClose={() => setOpen(false)}
|
|
56
|
+
>
|
|
57
|
+
<Modal.Root size="medium">
|
|
58
|
+
<Modal.Header>
|
|
59
|
+
<Modal.Title>Project details</Modal.Title>
|
|
60
|
+
<Modal.Close marginLeft="auto">
|
|
61
|
+
<Icon icon={XIcon} size="small" color={colors.text.tertiary} />
|
|
62
|
+
</Modal.Close>
|
|
63
|
+
</Modal.Header>
|
|
64
|
+
<Modal.Content>
|
|
65
|
+
<Modal.Description>Review the project details.</Modal.Description>
|
|
66
|
+
</Modal.Content>
|
|
67
|
+
<Modal.Footer>
|
|
68
|
+
<Modal.Close>
|
|
69
|
+
<Typography.Label>Done</Typography.Label>
|
|
70
|
+
</Modal.Close>
|
|
71
|
+
</Modal.Footer>
|
|
72
|
+
</Modal.Root>
|
|
73
|
+
</Modal.Provider>
|
|
74
|
+
</Portal>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Header, Content, Footer, Title, and Description render supplied children and use
|
|
78
|
+
independent theme styling. They accept the corresponding View or Text primitive
|
|
79
|
+
props. Content is a regular View with no built-in scrolling. Keep dialog content short.
|
|
80
|
+
Root's View props and style customize the surface.
|
|
81
|
+
|
|
82
|
+
Modal.Close renders supplied children and dismisses through Provider's context.
|
|
83
|
+
It accepts Pressable props, including disabled and loading, and preserves the
|
|
84
|
+
consumer onPress callback. Closing or closed dialogs block Close interaction.
|
|
85
|
+
It does not generate an icon or impose minimum dimensions.
|
|
86
|
+
|
|
87
|
+
Import Icon from @impulse-ui-native/icon, XIcon from @impulse-ui-native/icon/icons/x,
|
|
88
|
+
and Typography from @impulse-ui-native/primitives. Use useColors from
|
|
89
|
+
@impulse-ui-native/theme to obtain colors.
|
|
90
|
+
|
|
91
|
+
Custom composable actions can read close, status, and interactive through
|
|
92
|
+
useModalContext inside Modal.Provider. No children callback is needed.
|
|
93
|
+
|
|
94
|
+
## Global OverlayHost usage
|
|
95
|
+
|
|
96
|
+
Register Modal directly with the store provided to OverlayProvider:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
const detailsModal = store.register({
|
|
100
|
+
id: "project-details",
|
|
101
|
+
unique: true,
|
|
102
|
+
Component: Modal,
|
|
103
|
+
Content: ProjectDetails,
|
|
104
|
+
title: "Project details",
|
|
105
|
+
onClose: (id) => store.close(id),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
detailsModal.open();
|
|
109
|
+
detailsModal.close();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
OverlayHost supplies id, open, layer, title, and lifecycle callbacks. It removes
|
|
113
|
+
the entry after onCloseFinished. Do not wrap each registered modal in another
|
|
114
|
+
Portal; mount OverlayHost at the application overlay level.
|
|
115
|
+
|
|
116
|
+
## Lifecycle
|
|
117
|
+
|
|
118
|
+
Provider accepts lifecycle props and layer from OverlayComponentProps. The
|
|
119
|
+
convenience Modal accepts the full contract and uses title to generate its header. id is required, open defaults to
|
|
120
|
+
false, and layer defaults to zero.
|
|
121
|
+
|
|
122
|
+
Opening calls onOpen(id), then onOpenFinished(id) after entry. Header X presses, backdrop presses,
|
|
123
|
+
Android back presses, and changing open to false begin dismissal and call
|
|
124
|
+
onClose(id). The modal stays mounted for the exit animation, then calls
|
|
125
|
+
onCloseFinished(id). For local usage, update open in onClose and keep Provider and Root mounted
|
|
126
|
+
through the exit. Reopening during exit cancels the stale closing completion.
|
|
127
|
+
|
|
128
|
+
The backdrop accepts presses without pressed-state visual feedback. The fade
|
|
129
|
+
and scale animations use Reanimated. Animations are canceled when Provider unmounts.
|
|
130
|
+
|
|
131
|
+
## Tokens and sizes
|
|
132
|
+
|
|
133
|
+
Maximum widths are 320, 440, and 640 for small, medium, and large; medium is the
|
|
134
|
+
default. Available width accounts for safe-area insets and themed viewport padding.
|
|
135
|
+
Root uses the elevated surface, subtle border, 16-point radius, and 16-point inner
|
|
136
|
+
padding. Header is horizontal; Footer aligns trailing actions and wraps.
|
|
137
|
+
|
|
138
|
+
Customize through primitive style props, native style, or ThemeProvider's
|
|
139
|
+
components.modal tokens. Overlay tokens control backdrop color and opacity,
|
|
140
|
+
base z-index, viewport padding, and the closed animation scale. Content does not
|
|
141
|
+
scroll, and keyboard avoidance is not built in.
|
|
142
|
+
|
|
143
|
+
Provider uses the shared useOverlayLifecycle hook from the overlay package. Observe
|
|
144
|
+
local status with onStatusChange(id, status), or hosted status with useOverlayStatus(id).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalCloseProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalClose: react.MemoExoticComponent<({ disabled, loading, style, onPress, ...props }: ModalCloseProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalClose };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useCallback } from "react";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
import { useEventCallback } from "@impulse-ui-native/core";
|
|
5
|
+
import { Pressable } from "@impulse-ui-native/primitives";
|
|
6
|
+
import { useModalContext } from "../hooks/use-modal-context.hook";
|
|
7
|
+
const ModalClose = memo(function ModalClose2({
|
|
8
|
+
disabled,
|
|
9
|
+
loading,
|
|
10
|
+
style,
|
|
11
|
+
onPress,
|
|
12
|
+
...props
|
|
13
|
+
}) {
|
|
14
|
+
const { close, interactive } = useModalContext();
|
|
15
|
+
const blocked = disabled === true || loading === true || !interactive;
|
|
16
|
+
const closeStyle = useCallback(
|
|
17
|
+
(state) => [
|
|
18
|
+
styles.close,
|
|
19
|
+
typeof style === "function" ? style(state) : style
|
|
20
|
+
],
|
|
21
|
+
[styles.close, style]
|
|
22
|
+
);
|
|
23
|
+
const handlePress = useEventCallback((event) => {
|
|
24
|
+
if (blocked) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
close();
|
|
28
|
+
onPress?.(event);
|
|
29
|
+
});
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
Pressable,
|
|
32
|
+
{
|
|
33
|
+
...props,
|
|
34
|
+
disabled: blocked,
|
|
35
|
+
style: closeStyle,
|
|
36
|
+
onPress: handlePress
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
const styles = StyleSheet.create({
|
|
41
|
+
close: {
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center"
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
export {
|
|
47
|
+
ModalClose
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=close.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/close.tsx"],"sourcesContent":["import type {\n GestureResponderEvent,\n PressableStateCallbackType,\n} from \"react-native\";\nimport { memo, useCallback } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Pressable } from \"@impulse-ui-native/primitives\";\n\nimport type { ModalCloseProps } from \"../types\";\nimport { useModalContext } from \"../hooks/use-modal-context.hook\";\n\nexport const ModalClose = memo(function ModalClose({\n disabled,\n loading,\n style,\n onPress,\n ...props\n}: ModalCloseProps) {\n const { close, interactive } = useModalContext();\n const blocked = disabled === true || loading === true || !interactive;\n\n const closeStyle = useCallback(\n (state: PressableStateCallbackType) => [\n styles.close,\n typeof style === \"function\" ? style(state) : style,\n ],\n [styles.close, style],\n );\n\n const handlePress = useEventCallback((event: GestureResponderEvent) => {\n if (blocked) {\n return;\n }\n\n close();\n onPress?.(event);\n });\n\n return (\n <Pressable\n {...props}\n disabled={blocked}\n style={closeStyle}\n onPress={handlePress}\n />\n );\n});\n\nconst styles = StyleSheet.create({\n close: {\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n});\n"],"mappings":"AAyCI;AArCJ,SAAS,MAAM,mBAAmB;AAClC,SAAS,kBAAkB;AAE3B,SAAS,wBAAwB;AACjC,SAAS,iBAAiB;AAG1B,SAAS,uBAAuB;AAEzB,MAAM,aAAa,KAAK,SAASA,YAAW;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,EAAE,OAAO,YAAY,IAAI,gBAAgB;AAC/C,QAAM,UAAU,aAAa,QAAQ,YAAY,QAAQ,CAAC;AAE1D,QAAM,aAAa;AAAA,IACjB,CAAC,UAAsC;AAAA,MACrC,OAAO;AAAA,MACP,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;AAAA,IAC/C;AAAA,IACA,CAAC,OAAO,OAAO,KAAK;AAAA,EACtB;AAEA,QAAM,cAAc,iBAAiB,CAAC,UAAiC;AACrE,QAAI,SAAS;AACX;AAAA,IACF;AAEA,UAAM;AACN,cAAU,KAAK;AAAA,EACjB,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA;AAAA,EACX;AAEJ,CAAC;AAED,MAAM,SAAS,WAAW,OAAO;AAAA,EAC/B,OAAO;AAAA,IACL,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AACF,CAAC;","names":["ModalClose"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalContentProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalContent: react.MemoExoticComponent<({ style, ...props }: ModalContentProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalContent };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
import { View } from "@impulse-ui-native/primitives";
|
|
5
|
+
import { useStyleProps, useThemedStyles } from "@impulse-ui-native/theme";
|
|
6
|
+
const ModalContent = memo(function ModalContent2({
|
|
7
|
+
style,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
const extractedStyleProps = useStyleProps(props);
|
|
11
|
+
const styles = useThemedStyles(themedStyles);
|
|
12
|
+
const partStyle = useMemo(
|
|
13
|
+
() => [styles.part, extractedStyleProps, style],
|
|
14
|
+
[styles.part, extractedStyleProps, style]
|
|
15
|
+
);
|
|
16
|
+
return /* @__PURE__ */ jsx(View, { ...props, style: partStyle });
|
|
17
|
+
});
|
|
18
|
+
function themedStyles(theme) {
|
|
19
|
+
const tokens = theme.components.modal;
|
|
20
|
+
return StyleSheet.create({
|
|
21
|
+
part: {
|
|
22
|
+
gap: tokens.gap
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
ModalContent
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/content.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ModalContentProps } from \"../types\";\n\nexport const ModalContent = memo(function ModalContent({\n style,\n ...props\n}: ModalContentProps) {\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles);\n\n const partStyle = useMemo(\n () => [styles.part, extractedStyleProps, style],\n [styles.part, extractedStyleProps, style],\n );\n\n return <View {...props} style={partStyle} />;\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.modal;\n\n return StyleSheet.create({\n part: {\n gap: tokens.gap,\n },\n });\n}\n"],"mappings":"AAqBS;AArBT,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACrB,SAAS,eAAe,uBAAuB;AAIxC,MAAM,eAAe,KAAK,SAASA,cAAa;AAAA,EACrD;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,YAAY;AAE3C,QAAM,YAAY;AAAA,IAChB,MAAM,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,IAC9C,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,EAC1C;AAEA,SAAO,oBAAC,QAAM,GAAG,OAAO,OAAO,WAAW;AAC5C,CAAC;AAED,SAAS,aAAa,OAAiB;AACrC,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,KAAK,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["ModalContent"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalDescriptionProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalDescription: react.MemoExoticComponent<(props: ModalDescriptionProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalDescription };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { Typography } from "@impulse-ui-native/primitives";
|
|
4
|
+
import { useComponentsTokens } from "@impulse-ui-native/theme";
|
|
5
|
+
const ModalDescription = memo(function ModalDescription2(props) {
|
|
6
|
+
const tokens = useComponentsTokens().modal;
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
Typography.BodySmall,
|
|
9
|
+
{
|
|
10
|
+
color: tokens.descriptionColor,
|
|
11
|
+
fontSize: tokens.descriptionFontSize,
|
|
12
|
+
lineHeight: tokens.descriptionLineHeight,
|
|
13
|
+
...props
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
export {
|
|
18
|
+
ModalDescription
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=description.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/description.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Typography } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { ModalDescriptionProps } from \"../types\";\n\nexport const ModalDescription = memo(function ModalDescription(\n props: ModalDescriptionProps,\n) {\n const tokens = useComponentsTokens().modal;\n\n return (\n <Typography.BodySmall\n color={tokens.descriptionColor}\n fontSize={tokens.descriptionFontSize}\n lineHeight={tokens.descriptionLineHeight}\n {...props}\n />\n );\n});\n"],"mappings":"AAaI;AAbJ,SAAS,YAAY;AAErB,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AAI7B,MAAM,mBAAmB,KAAK,SAASA,kBAC5C,OACA;AACA,QAAM,SAAS,oBAAoB,EAAE;AAErC,SACE;AAAA,IAAC,WAAW;AAAA,IAAX;AAAA,MACC,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MAClB,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;","names":["ModalDescription"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalFooterProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalFooter: react.MemoExoticComponent<({ style, ...props }: ModalFooterProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalFooter };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
import { View } from "@impulse-ui-native/primitives";
|
|
5
|
+
import { useStyleProps, useThemedStyles } from "@impulse-ui-native/theme";
|
|
6
|
+
const ModalFooter = memo(function ModalFooter2({
|
|
7
|
+
style,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
const extractedStyleProps = useStyleProps(props);
|
|
11
|
+
const styles = useThemedStyles(themedStyles);
|
|
12
|
+
const partStyle = useMemo(
|
|
13
|
+
() => [styles.part, extractedStyleProps, style],
|
|
14
|
+
[styles.part, extractedStyleProps, style]
|
|
15
|
+
);
|
|
16
|
+
return /* @__PURE__ */ jsx(View, { ...props, style: partStyle });
|
|
17
|
+
});
|
|
18
|
+
function themedStyles(theme) {
|
|
19
|
+
const tokens = theme.components.modal;
|
|
20
|
+
return StyleSheet.create({
|
|
21
|
+
part: {
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
justifyContent: "flex-end",
|
|
25
|
+
flexWrap: "wrap",
|
|
26
|
+
gap: tokens.footerGap
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
ModalFooter
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=footer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/footer.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ModalFooterProps } from \"../types\";\n\nexport const ModalFooter = memo(function ModalFooter({\n style,\n ...props\n}: ModalFooterProps) {\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles);\n\n const partStyle = useMemo(\n () => [styles.part, extractedStyleProps, style],\n [styles.part, extractedStyleProps, style],\n );\n\n return <View {...props} style={partStyle} />;\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.modal;\n\n return StyleSheet.create({\n part: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"flex-end\",\n flexWrap: \"wrap\",\n gap: tokens.footerGap,\n },\n });\n}\n"],"mappings":"AAqBS;AArBT,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACrB,SAAS,eAAe,uBAAuB;AAIxC,MAAM,cAAc,KAAK,SAASA,aAAY;AAAA,EACnD;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,YAAY;AAE3C,QAAM,YAAY;AAAA,IAChB,MAAM,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,IAC9C,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,EAC1C;AAEA,SAAO,oBAAC,QAAM,GAAG,OAAO,OAAO,WAAW;AAC5C,CAAC;AAED,SAAS,aAAa,OAAiB;AACrC,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,KAAK,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["ModalFooter"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalHeaderProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalHeader: react.MemoExoticComponent<({ style, ...props }: ModalHeaderProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalHeader };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
import { View } from "@impulse-ui-native/primitives";
|
|
5
|
+
import { useStyleProps, useThemedStyles } from "@impulse-ui-native/theme";
|
|
6
|
+
const ModalHeader = memo(function ModalHeader2({
|
|
7
|
+
style,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
const extractedStyleProps = useStyleProps(props);
|
|
11
|
+
const styles = useThemedStyles(themedStyles);
|
|
12
|
+
const partStyle = useMemo(
|
|
13
|
+
() => [styles.part, extractedStyleProps, style],
|
|
14
|
+
[styles.part, extractedStyleProps, style]
|
|
15
|
+
);
|
|
16
|
+
return /* @__PURE__ */ jsx(View, { ...props, style: partStyle });
|
|
17
|
+
});
|
|
18
|
+
function themedStyles(theme) {
|
|
19
|
+
const tokens = theme.components.modal;
|
|
20
|
+
return StyleSheet.create({
|
|
21
|
+
part: {
|
|
22
|
+
flexDirection: "row",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
justifyContent: "space-between",
|
|
25
|
+
gap: tokens.headerGap
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
ModalHeader
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/header.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ModalHeaderProps } from \"../types\";\n\nexport const ModalHeader = memo(function ModalHeader({\n style,\n ...props\n}: ModalHeaderProps) {\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles);\n\n const partStyle = useMemo(\n () => [styles.part, extractedStyleProps, style],\n [styles.part, extractedStyleProps, style],\n );\n\n return <View {...props} style={partStyle} />;\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.modal;\n\n return StyleSheet.create({\n part: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: tokens.headerGap,\n },\n });\n}\n"],"mappings":"AAqBS;AArBT,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACrB,SAAS,eAAe,uBAAuB;AAIxC,MAAM,cAAc,KAAK,SAASA,aAAY;AAAA,EACnD;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,YAAY;AAE3C,QAAM,YAAY;AAAA,IAChB,MAAM,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,IAC9C,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,EAC1C;AAEA,SAAO,oBAAC,QAAM,GAAG,OAAO,OAAO,WAAW;AAC5C,CAAC;AAED,SAAS,aAAa,OAAiB;AACrC,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,KAAK,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["ModalHeader"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ModalProps, ModalProviderProps, ModalRootProps, ModalHeaderProps, ModalCloseProps, ModalContentProps, ModalFooterProps, ModalTitleProps, ModalDescriptionProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const Modal: react.NamedExoticComponent<ModalProps> & {
|
|
10
|
+
readonly type: ({ id, open, layer, onOpen, onOpenFinished, onStatusChange, onClose, onCloseFinished, header, title, footer, hideClose, children, ...props }: ModalProps) => react_jsx_runtime.JSX.Element;
|
|
11
|
+
} & {
|
|
12
|
+
Provider: react.MemoExoticComponent<({ children, layer, ...props }: ModalProviderProps) => react_jsx_runtime.JSX.Element>;
|
|
13
|
+
Root: react.MemoExoticComponent<({ children, ...props }: ModalRootProps) => react_jsx_runtime.JSX.Element | null>;
|
|
14
|
+
Header: react.MemoExoticComponent<({ style, ...props }: ModalHeaderProps) => react_jsx_runtime.JSX.Element>;
|
|
15
|
+
Close: react.MemoExoticComponent<({ disabled, loading, style, onPress, ...props }: ModalCloseProps) => react_jsx_runtime.JSX.Element>;
|
|
16
|
+
Content: react.MemoExoticComponent<({ style, ...props }: ModalContentProps) => react_jsx_runtime.JSX.Element>;
|
|
17
|
+
Footer: react.MemoExoticComponent<({ style, ...props }: ModalFooterProps) => react_jsx_runtime.JSX.Element>;
|
|
18
|
+
Title: react.MemoExoticComponent<(props: ModalTitleProps) => react_jsx_runtime.JSX.Element>;
|
|
19
|
+
Description: react.MemoExoticComponent<(props: ModalDescriptionProps) => react_jsx_runtime.JSX.Element>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { Modal };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ModalClose } from "./close";
|
|
2
|
+
import { ModalContent } from "./content";
|
|
3
|
+
import { ModalDescription } from "./description";
|
|
4
|
+
import { ModalFooter } from "./footer";
|
|
5
|
+
import { ModalHeader } from "./header";
|
|
6
|
+
import { ModalComponent } from "./modal";
|
|
7
|
+
import { ModalProvider } from "./provider";
|
|
8
|
+
import { ModalRoot } from "./root";
|
|
9
|
+
import { ModalTitle } from "./title";
|
|
10
|
+
const Modal = Object.assign(ModalComponent, {
|
|
11
|
+
Provider: ModalProvider,
|
|
12
|
+
Root: ModalRoot,
|
|
13
|
+
Header: ModalHeader,
|
|
14
|
+
Close: ModalClose,
|
|
15
|
+
Content: ModalContent,
|
|
16
|
+
Footer: ModalFooter,
|
|
17
|
+
Title: ModalTitle,
|
|
18
|
+
Description: ModalDescription
|
|
19
|
+
});
|
|
20
|
+
export {
|
|
21
|
+
Modal
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/index.ts"],"sourcesContent":["import { ModalClose } from \"./close\";\nimport { ModalContent } from \"./content\";\nimport { ModalDescription } from \"./description\";\nimport { ModalFooter } from \"./footer\";\nimport { ModalHeader } from \"./header\";\nimport { ModalComponent } from \"./modal\";\nimport { ModalProvider } from \"./provider\";\nimport { ModalRoot } from \"./root\";\nimport { ModalTitle } from \"./title\";\n\nexport const Modal = Object.assign(ModalComponent, {\n Provider: ModalProvider,\n Root: ModalRoot,\n Header: ModalHeader,\n Close: ModalClose,\n Content: ModalContent,\n Footer: ModalFooter,\n Title: ModalTitle,\n Description: ModalDescription,\n});\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAEpB,MAAM,QAAQ,OAAO,OAAO,gBAAgB;AAAA,EACjD,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,aAAa;AACf,CAAC;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalComponent: react.MemoExoticComponent<({ id, open, layer, onOpen, onOpenFinished, onStatusChange, onClose, onCloseFinished, header, title, footer, hideClose, children, ...props }: ModalProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalComponent };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { Icon } from "@impulse-ui-native/icon";
|
|
4
|
+
import { XIcon } from "@impulse-ui-native/icon/icons/x";
|
|
5
|
+
import { useColors } from "@impulse-ui-native/theme";
|
|
6
|
+
import { ModalClose } from "./close";
|
|
7
|
+
import { ModalContent } from "./content";
|
|
8
|
+
import { ModalFooter } from "./footer";
|
|
9
|
+
import { ModalHeader } from "./header";
|
|
10
|
+
import { ModalProvider } from "./provider";
|
|
11
|
+
import { ModalRoot } from "./root";
|
|
12
|
+
import { ModalTitle } from "./title";
|
|
13
|
+
const ModalComponent = memo(function Modal({
|
|
14
|
+
id,
|
|
15
|
+
open,
|
|
16
|
+
layer,
|
|
17
|
+
onOpen,
|
|
18
|
+
onOpenFinished,
|
|
19
|
+
onStatusChange,
|
|
20
|
+
onClose,
|
|
21
|
+
onCloseFinished,
|
|
22
|
+
header,
|
|
23
|
+
title,
|
|
24
|
+
footer,
|
|
25
|
+
hideClose = false,
|
|
26
|
+
children,
|
|
27
|
+
...props
|
|
28
|
+
}) {
|
|
29
|
+
const colors = useColors();
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
ModalProvider,
|
|
32
|
+
{
|
|
33
|
+
id,
|
|
34
|
+
open,
|
|
35
|
+
layer,
|
|
36
|
+
onOpen,
|
|
37
|
+
onOpenFinished,
|
|
38
|
+
onStatusChange,
|
|
39
|
+
onClose,
|
|
40
|
+
onCloseFinished,
|
|
41
|
+
children: /* @__PURE__ */ jsxs(ModalRoot, { ...props, children: [
|
|
42
|
+
header || title || !hideClose ? /* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
43
|
+
header,
|
|
44
|
+
!header && title ? /* @__PURE__ */ jsx(ModalTitle, { children: title }) : null,
|
|
45
|
+
!hideClose ? /* @__PURE__ */ jsx(ModalClose, { marginLeft: "auto", children: /* @__PURE__ */ jsx(Icon, { icon: XIcon, size: "small", color: colors.text.tertiary }) }) : null
|
|
46
|
+
] }) : null,
|
|
47
|
+
/* @__PURE__ */ jsx(ModalContent, { children }),
|
|
48
|
+
footer ? /* @__PURE__ */ jsx(ModalFooter, { children: footer }) : null
|
|
49
|
+
] })
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
export {
|
|
54
|
+
ModalComponent
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/modal.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { XIcon } from \"@impulse-ui-native/icon/icons/x\";\nimport { useColors } from \"@impulse-ui-native/theme\";\n\nimport type { ModalProps } from \"../types\";\nimport { ModalClose } from \"./close\";\nimport { ModalContent } from \"./content\";\nimport { ModalFooter } from \"./footer\";\nimport { ModalHeader } from \"./header\";\nimport { ModalProvider } from \"./provider\";\nimport { ModalRoot } from \"./root\";\nimport { ModalTitle } from \"./title\";\n\nexport const ModalComponent = memo(function Modal({\n id,\n open,\n layer,\n onOpen,\n onOpenFinished,\n onStatusChange,\n onClose,\n onCloseFinished,\n header,\n title,\n footer,\n hideClose = false,\n children,\n ...props\n}: ModalProps) {\n const colors = useColors();\n\n return (\n <ModalProvider\n id={id}\n open={open}\n layer={layer}\n onOpen={onOpen}\n onOpenFinished={onOpenFinished}\n onStatusChange={onStatusChange}\n onClose={onClose}\n onCloseFinished={onCloseFinished}\n >\n <ModalRoot {...props}>\n {header || title || !hideClose ? (\n <ModalHeader>\n {header}\n {!header && title ? <ModalTitle>{title}</ModalTitle> : null}\n {!hideClose ? (\n <ModalClose marginLeft=\"auto\">\n <Icon icon={XIcon} size=\"small\" color={colors.text.tertiary} />\n </ModalClose>\n ) : null}\n </ModalHeader>\n ) : null}\n <ModalContent>{children}</ModalContent>\n {footer ? <ModalFooter>{footer}</ModalFooter> : null}\n </ModalRoot>\n </ModalProvider>\n );\n});\n"],"mappings":"AA8CU,SAEsB,KAFtB;AA9CV,SAAS,YAAY;AAErB,SAAS,YAAY;AACrB,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAG1B,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAEpB,MAAM,iBAAiB,KAAK,SAAS,MAAM;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,GAAG;AACL,GAAe;AACb,QAAM,SAAS,UAAU;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,+BAAC,aAAW,GAAG,OACZ;AAAA,kBAAU,SAAS,CAAC,YACnB,qBAAC,eACE;AAAA;AAAA,UACA,CAAC,UAAU,QAAQ,oBAAC,cAAY,iBAAM,IAAgB;AAAA,UACtD,CAAC,YACA,oBAAC,cAAW,YAAW,QACrB,8BAAC,QAAK,MAAM,OAAO,MAAK,SAAQ,OAAO,OAAO,KAAK,UAAU,GAC/D,IACE;AAAA,WACN,IACE;AAAA,QACJ,oBAAC,gBAAc,UAAS;AAAA,QACvB,SAAS,oBAAC,eAAa,kBAAO,IAAiB;AAAA,SAClD;AAAA;AAAA,EACF;AAEJ,CAAC;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalProviderProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalProvider: react.MemoExoticComponent<({ children, layer, ...props }: ModalProviderProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalProvider };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { ModalContext } from "../contexts/modal.context";
|
|
4
|
+
import { useModalLifecycle } from "../hooks/use-modal-lifecycle.hook";
|
|
5
|
+
const ModalProvider = memo(function ModalProvider2({
|
|
6
|
+
children,
|
|
7
|
+
layer = 0,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
const lifecycle = useModalLifecycle(props);
|
|
11
|
+
const context = useMemo(() => ({ ...lifecycle, layer }), [lifecycle, layer]);
|
|
12
|
+
return /* @__PURE__ */ jsx(ModalContext.Provider, { value: context, children });
|
|
13
|
+
});
|
|
14
|
+
export {
|
|
15
|
+
ModalProvider
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/provider.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\n\nimport type { ModalProviderProps } from \"../types\";\nimport { ModalContext } from \"../contexts/modal.context\";\nimport { useModalLifecycle } from \"../hooks/use-modal-lifecycle.hook\";\n\nexport const ModalProvider = memo(function ModalProvider({\n children,\n layer = 0,\n ...props\n}: ModalProviderProps) {\n const lifecycle = useModalLifecycle(props);\n\n const context = useMemo(() => ({ ...lifecycle, layer }), [lifecycle, layer]);\n\n return (\n <ModalContext.Provider value={context}>{children}</ModalContext.Provider>\n );\n});\n"],"mappings":"AAgBI;AAhBJ,SAAS,MAAM,eAAe;AAG9B,SAAS,oBAAoB;AAC7B,SAAS,yBAAyB;AAE3B,MAAM,gBAAgB,KAAK,SAASA,eAAc;AAAA,EACvD;AAAA,EACA,QAAQ;AAAA,EACR,GAAG;AACL,GAAuB;AACrB,QAAM,YAAY,kBAAkB,KAAK;AAEzC,QAAM,UAAU,QAAQ,OAAO,EAAE,GAAG,WAAW,MAAM,IAAI,CAAC,WAAW,KAAK,CAAC;AAE3E,SACE,oBAAC,aAAa,UAAb,EAAsB,OAAO,SAAU,UAAS;AAErD,CAAC;","names":["ModalProvider"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalRootProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalRoot: react.MemoExoticComponent<({ children, ...props }: ModalRootProps) => react_jsx_runtime.JSX.Element | null>;
|
|
10
|
+
|
|
11
|
+
export { ModalRoot };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useEffect, useMemo } from "react";
|
|
3
|
+
import { BackHandler, Pressable, StyleSheet } from "react-native";
|
|
4
|
+
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
5
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
6
|
+
import { useComponentsTokens, useThemedStyles } from "@impulse-ui-native/theme";
|
|
7
|
+
import { useModalContext } from "../hooks/use-modal-context.hook";
|
|
8
|
+
import { ModalSurface } from "./surface";
|
|
9
|
+
const ModalRoot = memo(function ModalRoot2({
|
|
10
|
+
children,
|
|
11
|
+
...props
|
|
12
|
+
}) {
|
|
13
|
+
const { mounted, interactive, progress, close, layer } = useModalContext();
|
|
14
|
+
const insets = useSafeAreaInsets();
|
|
15
|
+
const tokens = useComponentsTokens().modal;
|
|
16
|
+
const styles = useThemedStyles(themedStyles, { insets, layer }, [
|
|
17
|
+
insets,
|
|
18
|
+
layer
|
|
19
|
+
]);
|
|
20
|
+
const overlayStyle = useAnimatedStyle(() => ({ opacity: progress.value }));
|
|
21
|
+
const surfaceStyle = useAnimatedStyle(() => ({
|
|
22
|
+
transform: [
|
|
23
|
+
{ scale: tokens.closedScale + (1 - tokens.closedScale) * progress.value }
|
|
24
|
+
]
|
|
25
|
+
}));
|
|
26
|
+
const containerStyle = useMemo(
|
|
27
|
+
() => [styles.container, overlayStyle],
|
|
28
|
+
[styles.container, overlayStyle]
|
|
29
|
+
);
|
|
30
|
+
const surfaceContainerStyle = useMemo(
|
|
31
|
+
() => [styles.surfaceContainer, surfaceStyle],
|
|
32
|
+
[styles.surfaceContainer, surfaceStyle]
|
|
33
|
+
);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!mounted) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const subscription = BackHandler.addEventListener(
|
|
39
|
+
"hardwareBackPress",
|
|
40
|
+
() => {
|
|
41
|
+
close();
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
return () => subscription.remove();
|
|
46
|
+
}, [mounted, close]);
|
|
47
|
+
return mounted ? /* @__PURE__ */ jsxs(Animated.View, { style: containerStyle, children: [
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
Pressable,
|
|
50
|
+
{
|
|
51
|
+
style: styles.backdrop,
|
|
52
|
+
onPress: close,
|
|
53
|
+
disabled: !interactive
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
Animated.View,
|
|
58
|
+
{
|
|
59
|
+
style: surfaceContainerStyle,
|
|
60
|
+
pointerEvents: interactive ? "box-none" : "none",
|
|
61
|
+
children: /* @__PURE__ */ jsx(ModalSurface, { ...props, children })
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
] }) : null;
|
|
65
|
+
});
|
|
66
|
+
function themedStyles(theme, {
|
|
67
|
+
insets,
|
|
68
|
+
layer
|
|
69
|
+
}) {
|
|
70
|
+
const tokens = theme.components.modal;
|
|
71
|
+
return StyleSheet.create({
|
|
72
|
+
container: {
|
|
73
|
+
...StyleSheet.absoluteFill,
|
|
74
|
+
zIndex: tokens.zIndexBase + layer,
|
|
75
|
+
alignItems: "center",
|
|
76
|
+
justifyContent: "center",
|
|
77
|
+
paddingTop: insets.top + tokens.viewportPadding,
|
|
78
|
+
paddingRight: insets.right + tokens.viewportPadding,
|
|
79
|
+
paddingBottom: insets.bottom + tokens.viewportPadding,
|
|
80
|
+
paddingLeft: insets.left + tokens.viewportPadding
|
|
81
|
+
},
|
|
82
|
+
backdrop: {
|
|
83
|
+
...StyleSheet.absoluteFill,
|
|
84
|
+
backgroundColor: tokens.overlayColor,
|
|
85
|
+
opacity: tokens.overlayVisibleOpacity
|
|
86
|
+
},
|
|
87
|
+
surfaceContainer: {
|
|
88
|
+
width: "100%",
|
|
89
|
+
alignItems: "center"
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
ModalRoot
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/root.tsx"],"sourcesContent":["import { memo, useEffect, useMemo } from \"react\";\nimport { BackHandler, Pressable, StyleSheet } from \"react-native\";\nimport Animated, { useAnimatedStyle } from \"react-native-reanimated\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { useComponentsTokens, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ModalRootProps } from \"../types\";\nimport { useModalContext } from \"../hooks/use-modal-context.hook\";\nimport { ModalSurface } from \"./surface\";\n\nexport const ModalRoot = memo(function ModalRoot({\n children,\n ...props\n}: ModalRootProps) {\n const { mounted, interactive, progress, close, layer } = useModalContext();\n const insets = useSafeAreaInsets();\n const tokens = useComponentsTokens().modal;\n const styles = useThemedStyles(themedStyles, { insets, layer }, [\n insets,\n layer,\n ]);\n\n const overlayStyle = useAnimatedStyle(() => ({ opacity: progress.value }));\n const surfaceStyle = useAnimatedStyle(() => ({\n transform: [\n { scale: tokens.closedScale + (1 - tokens.closedScale) * progress.value },\n ],\n }));\n\n const containerStyle = useMemo(\n () => [styles.container, overlayStyle],\n [styles.container, overlayStyle],\n );\n const surfaceContainerStyle = useMemo(\n () => [styles.surfaceContainer, surfaceStyle],\n [styles.surfaceContainer, surfaceStyle],\n );\n\n useEffect(() => {\n if (!mounted) {\n return;\n }\n\n const subscription = BackHandler.addEventListener(\n \"hardwareBackPress\",\n () => {\n close();\n\n return true;\n },\n );\n\n return () => subscription.remove();\n }, [mounted, close]);\n\n return mounted ? (\n <Animated.View style={containerStyle}>\n <Pressable\n style={styles.backdrop}\n onPress={close}\n disabled={!interactive}\n />\n <Animated.View\n style={surfaceContainerStyle}\n pointerEvents={interactive ? \"box-none\" : \"none\"}\n >\n <ModalSurface {...props}>{children}</ModalSurface>\n </Animated.View>\n </Animated.View>\n ) : null;\n});\n\nfunction themedStyles(\n theme: AppTheme,\n {\n insets,\n layer,\n }: {\n insets: { top: number; right: number; bottom: number; left: number };\n layer: number;\n },\n) {\n const tokens = theme.components.modal;\n\n return StyleSheet.create({\n container: {\n ...StyleSheet.absoluteFill,\n zIndex: tokens.zIndexBase + layer,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingTop: insets.top + tokens.viewportPadding,\n paddingRight: insets.right + tokens.viewportPadding,\n paddingBottom: insets.bottom + tokens.viewportPadding,\n paddingLeft: insets.left + tokens.viewportPadding,\n },\n backdrop: {\n ...StyleSheet.absoluteFill,\n backgroundColor: tokens.overlayColor,\n opacity: tokens.overlayVisibleOpacity,\n },\n surfaceContainer: {\n width: \"100%\",\n alignItems: \"center\",\n },\n });\n}\n"],"mappings":"AA0DI,SACE,KADF;AA1DJ,SAAS,MAAM,WAAW,eAAe;AACzC,SAAS,aAAa,WAAW,kBAAkB;AACnD,OAAO,YAAY,wBAAwB;AAC3C,SAAS,yBAAyB;AAGlC,SAAS,qBAAqB,uBAAuB;AAGrD,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAEtB,MAAM,YAAY,KAAK,SAASA,WAAU;AAAA,EAC/C;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,QAAM,EAAE,SAAS,aAAa,UAAU,OAAO,MAAM,IAAI,gBAAgB;AACzE,QAAM,SAAS,kBAAkB;AACjC,QAAM,SAAS,oBAAoB,EAAE;AACrC,QAAM,SAAS,gBAAgB,cAAc,EAAE,QAAQ,MAAM,GAAG;AAAA,IAC9D;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,eAAe,iBAAiB,OAAO,EAAE,SAAS,SAAS,MAAM,EAAE;AACzE,QAAM,eAAe,iBAAiB,OAAO;AAAA,IAC3C,WAAW;AAAA,MACT,EAAE,OAAO,OAAO,eAAe,IAAI,OAAO,eAAe,SAAS,MAAM;AAAA,IAC1E;AAAA,EACF,EAAE;AAEF,QAAM,iBAAiB;AAAA,IACrB,MAAM,CAAC,OAAO,WAAW,YAAY;AAAA,IACrC,CAAC,OAAO,WAAW,YAAY;AAAA,EACjC;AACA,QAAM,wBAAwB;AAAA,IAC5B,MAAM,CAAC,OAAO,kBAAkB,YAAY;AAAA,IAC5C,CAAC,OAAO,kBAAkB,YAAY;AAAA,EACxC;AAEA,YAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,UAAM,eAAe,YAAY;AAAA,MAC/B;AAAA,MACA,MAAM;AACJ,cAAM;AAEN,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,SAAS,KAAK,CAAC;AAEnB,SAAO,UACL,qBAAC,SAAS,MAAT,EAAc,OAAO,gBACpB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,SAAS;AAAA,QACT,UAAU,CAAC;AAAA;AAAA,IACb;AAAA,IACA;AAAA,MAAC,SAAS;AAAA,MAAT;AAAA,QACC,OAAO;AAAA,QACP,eAAe,cAAc,aAAa;AAAA,QAE1C,8BAAC,gBAAc,GAAG,OAAQ,UAAS;AAAA;AAAA,IACrC;AAAA,KACF,IACE;AACN,CAAC;AAED,SAAS,aACP,OACA;AAAA,EACE;AAAA,EACA;AACF,GAIA;AACA,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,WAAW;AAAA,MACT,GAAG,WAAW;AAAA,MACd,QAAQ,OAAO,aAAa;AAAA,MAC5B,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,YAAY,OAAO,MAAM,OAAO;AAAA,MAChC,cAAc,OAAO,QAAQ,OAAO;AAAA,MACpC,eAAe,OAAO,SAAS,OAAO;AAAA,MACtC,aAAa,OAAO,OAAO,OAAO;AAAA,IACpC;AAAA,IACA,UAAU;AAAA,MACR,GAAG,WAAW;AAAA,MACd,iBAAiB,OAAO;AAAA,MACxB,SAAS,OAAO;AAAA,IAClB;AAAA,IACA,kBAAkB;AAAA,MAChB,OAAO;AAAA,MACP,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["ModalRoot"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalSurfaceProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalSurface: react.MemoExoticComponent<({ size, style, ...props }: ModalSurfaceProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalSurface };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useMemo } from "react";
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
4
|
+
import { View } from "@impulse-ui-native/primitives";
|
|
5
|
+
import { useStyleProps, useThemedStyles } from "@impulse-ui-native/theme";
|
|
6
|
+
const ModalSurface = memo(function ModalSurface2({
|
|
7
|
+
size = "medium",
|
|
8
|
+
style,
|
|
9
|
+
...props
|
|
10
|
+
}) {
|
|
11
|
+
const extractedStyleProps = useStyleProps(props);
|
|
12
|
+
const styles = useThemedStyles(themedStyles, { size }, [size]);
|
|
13
|
+
const rootStyle = useMemo(
|
|
14
|
+
() => [styles.root, extractedStyleProps, style],
|
|
15
|
+
[styles.root, extractedStyleProps, style]
|
|
16
|
+
);
|
|
17
|
+
return /* @__PURE__ */ jsx(View, { ...props, style: rootStyle });
|
|
18
|
+
});
|
|
19
|
+
function themedStyles(theme, { size }) {
|
|
20
|
+
const tokens = theme.components.modal;
|
|
21
|
+
return StyleSheet.create({
|
|
22
|
+
root: {
|
|
23
|
+
width: "100%",
|
|
24
|
+
maxWidth: tokens.sizes[size].maxWidth,
|
|
25
|
+
padding: tokens.padding,
|
|
26
|
+
gap: tokens.gap,
|
|
27
|
+
backgroundColor: tokens.backgroundColor,
|
|
28
|
+
borderColor: tokens.borderColor,
|
|
29
|
+
borderWidth: tokens.borderWidth,
|
|
30
|
+
borderRadius: tokens.borderRadius
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
ModalSurface
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/surface.tsx"],"sourcesContent":["import { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme, ComponentSize } from \"@impulse-ui-native/theme\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useStyleProps, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ModalSurfaceProps } from \"../types\";\n\nexport const ModalSurface = memo(function ModalSurface({\n size = \"medium\",\n style,\n ...props\n}: ModalSurfaceProps) {\n const extractedStyleProps = useStyleProps(props);\n const styles = useThemedStyles(themedStyles, { size }, [size]);\n\n const rootStyle = useMemo(\n () => [styles.root, extractedStyleProps, style],\n [styles.root, extractedStyleProps, style],\n );\n\n return <View {...props} style={rootStyle} />;\n});\n\nfunction themedStyles(theme: AppTheme, { size }: { size: ComponentSize }) {\n const tokens = theme.components.modal;\n\n return StyleSheet.create({\n root: {\n width: \"100%\",\n maxWidth: tokens.sizes[size].maxWidth,\n padding: tokens.padding,\n gap: tokens.gap,\n backgroundColor: tokens.backgroundColor,\n borderColor: tokens.borderColor,\n borderWidth: tokens.borderWidth,\n borderRadius: tokens.borderRadius,\n },\n });\n}\n"],"mappings":"AAsBS;AAtBT,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACrB,SAAS,eAAe,uBAAuB;AAIxC,MAAM,eAAe,KAAK,SAASA,cAAa;AAAA,EACrD,OAAO;AAAA,EACP;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,sBAAsB,cAAc,KAAK;AAC/C,QAAM,SAAS,gBAAgB,cAAc,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC;AAE7D,QAAM,YAAY;AAAA,IAChB,MAAM,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,IAC9C,CAAC,OAAO,MAAM,qBAAqB,KAAK;AAAA,EAC1C;AAEA,SAAO,oBAAC,QAAM,GAAG,OAAO,OAAO,WAAW;AAC5C,CAAC;AAED,SAAS,aAAa,OAAiB,EAAE,KAAK,GAA4B;AACxE,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,UAAU,OAAO,MAAM,IAAI,EAAE;AAAA,MAC7B,SAAS,OAAO;AAAA,MAChB,KAAK,OAAO;AAAA,MACZ,iBAAiB,OAAO;AAAA,MACxB,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,IACvB;AAAA,EACF,CAAC;AACH;","names":["ModalSurface"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ModalTitleProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react-native-reanimated';
|
|
5
|
+
import '@impulse-ui-native/overlay';
|
|
6
|
+
import '@impulse-ui-native/primitives';
|
|
7
|
+
import '@impulse-ui-native/theme';
|
|
8
|
+
|
|
9
|
+
declare const ModalTitle: react.MemoExoticComponent<(props: ModalTitleProps) => react_jsx_runtime.JSX.Element>;
|
|
10
|
+
|
|
11
|
+
export { ModalTitle };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { Typography } from "@impulse-ui-native/primitives";
|
|
4
|
+
import { useComponentsTokens } from "@impulse-ui-native/theme";
|
|
5
|
+
const ModalTitle = memo(function ModalTitle2(props) {
|
|
6
|
+
const tokens = useComponentsTokens().modal;
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
Typography.Title4,
|
|
9
|
+
{
|
|
10
|
+
color: tokens.titleColor,
|
|
11
|
+
fontSize: tokens.titleFontSize,
|
|
12
|
+
lineHeight: tokens.titleLineHeight,
|
|
13
|
+
flexShrink: 1,
|
|
14
|
+
...props
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
export {
|
|
19
|
+
ModalTitle
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/title.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Typography } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { ModalTitleProps } from \"../types\";\n\nexport const ModalTitle = memo(function ModalTitle(props: ModalTitleProps) {\n const tokens = useComponentsTokens().modal;\n\n return (\n <Typography.Title4\n color={tokens.titleColor}\n fontSize={tokens.titleFontSize}\n lineHeight={tokens.titleLineHeight}\n flexShrink={1}\n {...props}\n />\n );\n});\n"],"mappings":"AAWI;AAXJ,SAAS,YAAY;AAErB,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B;AAI7B,MAAM,aAAa,KAAK,SAASA,YAAW,OAAwB;AACzE,QAAM,SAAS,oBAAoB,EAAE;AAErC,SACE;AAAA,IAAC,WAAW;AAAA,IAAX;AAAA,MACC,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,YAAY;AAAA,MACX,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;","names":["ModalTitle"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/constants/modal.constants.ts"],"sourcesContent":["export const EnterDuration = 180;\nexport const ExitDuration = 150;\n"],"mappings":"AAAO,MAAM,gBAAgB;AACtB,MAAM,eAAe;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ModalContextValue } from '../types/modal.types.mjs';
|
|
3
|
+
import 'react-native-reanimated';
|
|
4
|
+
import '@impulse-ui-native/overlay';
|
|
5
|
+
import '@impulse-ui-native/primitives';
|
|
6
|
+
import '@impulse-ui-native/theme';
|
|
7
|
+
|
|
8
|
+
declare const ModalContext: react.Context<ModalContextValue | undefined>;
|
|
9
|
+
|
|
10
|
+
export { ModalContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/contexts/modal.context.ts"],"sourcesContent":["import { createContext } from \"react\";\n\nimport type { ModalContextValue } from \"../types\";\n\nexport const ModalContext = createContext<ModalContextValue | undefined>(\n undefined,\n);\n"],"mappings":"AAAA,SAAS,qBAAqB;AAIvB,MAAM,eAAe;AAAA,EAC1B;AACF;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ModalContextValue } from '../types/modal.types.mjs';
|
|
2
|
+
import 'react';
|
|
3
|
+
import 'react-native-reanimated';
|
|
4
|
+
import '@impulse-ui-native/overlay';
|
|
5
|
+
import '@impulse-ui-native/primitives';
|
|
6
|
+
import '@impulse-ui-native/theme';
|
|
7
|
+
|
|
8
|
+
declare function useModalContext(): ModalContextValue;
|
|
9
|
+
|
|
10
|
+
export { useModalContext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { ModalContext } from "../contexts/modal.context";
|
|
3
|
+
function useModalContext() {
|
|
4
|
+
const context = useContext(ModalContext);
|
|
5
|
+
if (!context) {
|
|
6
|
+
throw new Error("Modal components must be rendered inside Modal.Provider");
|
|
7
|
+
}
|
|
8
|
+
return context;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
useModalContext
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=use-modal-context.hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/use-modal-context.hook.ts"],"sourcesContent":["import { useContext } from \"react\";\n\nimport { ModalContext } from \"../contexts/modal.context\";\n\nexport function useModalContext() {\n const context = useContext(ModalContext);\n\n if (!context) {\n throw new Error(\"Modal components must be rendered inside Modal.Provider\");\n }\n\n return context;\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAE3B,SAAS,oBAAoB;AAEtB,SAAS,kBAAkB;AAChC,QAAM,UAAU,WAAW,YAAY;AAEvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as _impulse_ui_native_overlay from '@impulse-ui-native/overlay';
|
|
2
|
+
import * as react_native_reanimated from 'react-native-reanimated';
|
|
3
|
+
import { ModalLifecycleProps } from '../types/modal.types.mjs';
|
|
4
|
+
import 'react';
|
|
5
|
+
import '@impulse-ui-native/primitives';
|
|
6
|
+
import '@impulse-ui-native/theme';
|
|
7
|
+
|
|
8
|
+
declare function useModalLifecycle(props: ModalLifecycleProps): {
|
|
9
|
+
progress: react_native_reanimated.SharedValue<number>;
|
|
10
|
+
status: _impulse_ui_native_overlay.OverlayLifecycleStatus;
|
|
11
|
+
mounted: boolean;
|
|
12
|
+
interactive: boolean;
|
|
13
|
+
close: () => void;
|
|
14
|
+
completeTransition: _impulse_ui_native_overlay.OverlayTransitionCompletion;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { useModalLifecycle };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
cancelAnimation,
|
|
4
|
+
useSharedValue,
|
|
5
|
+
withTiming
|
|
6
|
+
} from "react-native-reanimated";
|
|
7
|
+
import { scheduleOnRN } from "react-native-worklets";
|
|
8
|
+
import { useEventCallback } from "@impulse-ui-native/core";
|
|
9
|
+
import { useOverlayLifecycle } from "@impulse-ui-native/overlay";
|
|
10
|
+
import { EnterDuration, ExitDuration } from "../constants/modal.constants";
|
|
11
|
+
function useModalLifecycle(props) {
|
|
12
|
+
const progress = useSharedValue(0);
|
|
13
|
+
const enter = useEventCallback(
|
|
14
|
+
(transitionId, complete) => {
|
|
15
|
+
progress.set(
|
|
16
|
+
withTiming(1, { duration: EnterDuration }, (finished) => {
|
|
17
|
+
if (finished) {
|
|
18
|
+
scheduleOnRN(complete, transitionId);
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
const exit = useEventCallback(
|
|
25
|
+
(transitionId, complete) => {
|
|
26
|
+
progress.set(
|
|
27
|
+
withTiming(0, { duration: ExitDuration }, (finished) => {
|
|
28
|
+
if (finished) {
|
|
29
|
+
scheduleOnRN(complete, transitionId);
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
const options = useMemo(
|
|
36
|
+
() => ({ onEnter: enter, onExit: exit }),
|
|
37
|
+
[enter, exit]
|
|
38
|
+
);
|
|
39
|
+
const lifecycle = useOverlayLifecycle(props, options);
|
|
40
|
+
useEffect(() => () => cancelAnimation(progress), [progress]);
|
|
41
|
+
return useMemo(() => ({ ...lifecycle, progress }), [lifecycle, progress]);
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
useModalLifecycle
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=use-modal-lifecycle.hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/use-modal-lifecycle.hook.ts"],"sourcesContent":["import { useEffect, useMemo } from \"react\";\nimport {\n cancelAnimation,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { scheduleOnRN } from \"react-native-worklets\";\n\nimport type { OverlayTransitionHandler } from \"@impulse-ui-native/overlay\";\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { useOverlayLifecycle } from \"@impulse-ui-native/overlay\";\n\nimport type { ModalLifecycleProps } from \"../types\";\nimport { EnterDuration, ExitDuration } from \"../constants/modal.constants\";\n\nexport function useModalLifecycle(props: ModalLifecycleProps) {\n const progress = useSharedValue(0);\n\n const enter = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(1, { duration: EnterDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n const exit = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(0, { duration: ExitDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n\n const options = useMemo(\n () => ({ onEnter: enter, onExit: exit }),\n [enter, exit],\n );\n const lifecycle = useOverlayLifecycle(props, options);\n\n useEffect(() => () => cancelAnimation(progress), [progress]);\n\n return useMemo(() => ({ ...lifecycle, progress }), [lifecycle, progress]);\n}\n"],"mappings":"AAAA,SAAS,WAAW,eAAe;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAG7B,SAAS,wBAAwB;AACjC,SAAS,2BAA2B;AAGpC,SAAS,eAAe,oBAAoB;AAErC,SAAS,kBAAkB,OAA4B;AAC5D,QAAM,WAAW,eAAe,CAAC;AAEjC,QAAM,QAAQ;AAAA,IACZ,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,cAAc,GAAG,CAAC,aAAa;AACvD,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO;AAAA,IACX,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,aAAa,GAAG,CAAC,aAAa;AACtD,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU;AAAA,IACd,OAAO,EAAE,SAAS,OAAO,QAAQ,KAAK;AAAA,IACtC,CAAC,OAAO,IAAI;AAAA,EACd;AACA,QAAM,YAAY,oBAAoB,OAAO,OAAO;AAEpD,YAAU,MAAM,MAAM,gBAAgB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAE3D,SAAO,QAAQ,OAAO,EAAE,GAAG,WAAW,SAAS,IAAI,CAAC,WAAW,QAAQ,CAAC;AAC1E;","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { Modal } from './components/index.mjs';
|
|
2
|
+
export { ModalCloseProps, ModalContentProps, ModalContextValue, ModalDescriptionProps, ModalFooterProps, ModalHeaderProps, ModalLifecycleProps, ModalProps, ModalProviderProps, ModalRootProps, ModalSurfaceProps, ModalTitleProps } from './types/modal.types.mjs';
|
|
3
|
+
export { useModalContext } from './hooks/use-modal-context.hook.mjs';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'react';
|
|
6
|
+
import 'react-native-reanimated';
|
|
7
|
+
import '@impulse-ui-native/overlay';
|
|
8
|
+
import '@impulse-ui-native/primitives';
|
|
9
|
+
import '@impulse-ui-native/theme';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./components\";\nexport * from \"./types\";\nexport { useModalContext } from \"./hooks/use-modal-context.hook\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,SAAS,uBAAuB;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ModalCloseProps, ModalContentProps, ModalContextValue, ModalDescriptionProps, ModalFooterProps, ModalHeaderProps, ModalLifecycleProps, ModalProps, ModalProviderProps, ModalRootProps, ModalSurfaceProps, ModalTitleProps } from './modal.types.mjs';
|
|
2
|
+
import 'react';
|
|
3
|
+
import 'react-native-reanimated';
|
|
4
|
+
import '@impulse-ui-native/overlay';
|
|
5
|
+
import '@impulse-ui-native/primitives';
|
|
6
|
+
import '@impulse-ui-native/theme';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["export * from \"./modal.types\";\n"],"mappings":"AAAA,cAAc;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PropsWithChildren, ReactNode } from 'react';
|
|
2
|
+
import { SharedValue } from 'react-native-reanimated';
|
|
3
|
+
import { OverlayLifecycleProps, OverlayComponentProps, OverlayLifecycleStatus } from '@impulse-ui-native/overlay';
|
|
4
|
+
import { ViewProps, PressableCoreProps, TextProps } from '@impulse-ui-native/primitives';
|
|
5
|
+
import { ComponentSize } from '@impulse-ui-native/theme';
|
|
6
|
+
|
|
7
|
+
interface ModalSurfaceProps extends ViewProps {
|
|
8
|
+
size?: ComponentSize;
|
|
9
|
+
}
|
|
10
|
+
interface ModalProviderProps extends OverlayLifecycleProps, PropsWithChildren {
|
|
11
|
+
layer?: number;
|
|
12
|
+
}
|
|
13
|
+
type ModalRootProps = ModalSurfaceProps;
|
|
14
|
+
interface ModalContextValue {
|
|
15
|
+
status: OverlayLifecycleStatus;
|
|
16
|
+
mounted: boolean;
|
|
17
|
+
interactive: boolean;
|
|
18
|
+
progress: SharedValue<number>;
|
|
19
|
+
layer: number;
|
|
20
|
+
close: () => void;
|
|
21
|
+
}
|
|
22
|
+
interface ModalProps extends Omit<ModalRootProps, "id" | "children">, ModalProviderProps {
|
|
23
|
+
title?: OverlayComponentProps["title"];
|
|
24
|
+
header?: ReactNode;
|
|
25
|
+
footer?: ReactNode;
|
|
26
|
+
hideClose?: boolean;
|
|
27
|
+
}
|
|
28
|
+
type ModalHeaderProps = ViewProps;
|
|
29
|
+
type ModalCloseProps = PropsWithChildren<Omit<PressableCoreProps, "children">>;
|
|
30
|
+
type ModalContentProps = ViewProps;
|
|
31
|
+
type ModalFooterProps = ViewProps;
|
|
32
|
+
type ModalTitleProps = TextProps;
|
|
33
|
+
type ModalDescriptionProps = TextProps;
|
|
34
|
+
type ModalLifecycleProps = OverlayLifecycleProps;
|
|
35
|
+
|
|
36
|
+
export type { ModalCloseProps, ModalContentProps, ModalContextValue, ModalDescriptionProps, ModalFooterProps, ModalHeaderProps, ModalLifecycleProps, ModalProps, ModalProviderProps, ModalRootProps, ModalSurfaceProps, ModalTitleProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=modal.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,67 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@impulse-ui-native/modal",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Compound modal dialogs with local and OverlayHost lifecycle support.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-native",
|
|
7
|
+
"modal",
|
|
8
|
+
"dialog",
|
|
9
|
+
"components"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"source": "src/index.ts",
|
|
13
|
+
"module": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.mts",
|
|
15
|
+
"react-native": "src/index.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
19
|
+
"react-native": "./src/index.ts",
|
|
20
|
+
"import": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@impulse-ui-native/theme": "7.0.0",
|
|
31
|
+
"@impulse-ui-native/primitives": "7.0.0",
|
|
32
|
+
"@impulse-ui-native/icon": "7.0.0",
|
|
33
|
+
"@impulse-ui-native/core": "7.0.0",
|
|
34
|
+
"@impulse-ui-native/overlay": "7.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/react": "~19.2.14",
|
|
38
|
+
"eslint": "^9.38.0",
|
|
39
|
+
"prettier": "^3.6.2",
|
|
40
|
+
"react": "19.2.3",
|
|
41
|
+
"react-native": "0.86.2",
|
|
42
|
+
"typescript": "~6.0.3",
|
|
43
|
+
"react-native-reanimated": "4.5.1",
|
|
44
|
+
"react-native-safe-area-context": "~5.7.0",
|
|
45
|
+
"react-native-worklets": "0.10.1",
|
|
46
|
+
"@impulse-ui-native/prettier-config": "1.0.0",
|
|
47
|
+
"@impulse-ui-native/eslint-config": "1.0.0",
|
|
48
|
+
"@impulse-ui-native/tsconfig": "1.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": ">=18",
|
|
52
|
+
"react-native": ">=0.73",
|
|
53
|
+
"react-native-reanimated": ">=4",
|
|
54
|
+
"react-native-safe-area-context": ">=5.0.0",
|
|
55
|
+
"react-native-worklets": ">=0.5"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"prettier": "@impulse-ui-native/prettier-config",
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsup --config tsup.config.ts",
|
|
63
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
64
|
+
"lint": "pnpm exec eslint . --fix",
|
|
65
|
+
"format": "prettier --write \"./**/*.{ts,tsx,js,jsx,json,md}\" --ignore-path ../../.prettierignore"
|
|
66
|
+
}
|
|
6
67
|
}
|