polpo 0.1.4 → 0.1.6
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/dist/chunk-LJM5NQBY.js +3 -0
- package/dist/chunk-LJM5NQBY.js.map +1 -0
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +2 -2
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +1 -1
- package/dist/ui.cjs +110 -112
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.d.cts +6 -6
- package/dist/ui.d.ts +6 -6
- package/dist/ui.js +107 -109
- package/dist/ui.js.map +1 -1
- package/dist/{use-modal-in-container-DiNW1PE_.d.cts → use-modal-transition-C6mR_NZh.d.cts} +17 -19
- package/dist/{use-modal-in-container-neGo-kMk.d.ts → use-modal-transition-DBAyFSqW.d.ts} +17 -19
- package/package.json +4 -3
- package/src/components/form/checkbox/checkbox.style.ts +0 -2
- package/src/components/form/input-color/input-color.tsx +7 -1
- package/src/components/form/select/options.tsx +15 -4
- package/src/components/modals/menu/menu.tsx +9 -4
- package/src/components/modals/modal/modal.tsx +20 -16
- package/src/components/modals/portal/portal.tsx +2 -3
- package/src/hooks/use-dom-container.ts +26 -19
- package/src/hooks/use-modal-in-container.ts +7 -13
- package/src/hooks/use-modal-transition.ts +16 -4
- package/dist/chunk-LWUSFVRE.js +0 -3
- package/dist/chunk-LWUSFVRE.js.map +0 -1
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
import { P as PositionContainer } from './get-modal-position-drle0OjP.cjs';
|
|
3
3
|
|
|
4
|
-
declare enum ModalState {
|
|
5
|
-
OPENING = "OPENING",
|
|
6
|
-
OPEN = "OPEN",
|
|
7
|
-
CLOSING = "CLOSING",
|
|
8
|
-
CLOSED = "CLOSED"
|
|
9
|
-
}
|
|
10
|
-
declare const useModalTransition: (transitionDuration?: number, onClose?: () => void) => {
|
|
11
|
-
isVisible: boolean;
|
|
12
|
-
closeModal: () => void;
|
|
13
|
-
openModal: () => void;
|
|
14
|
-
modalState: ModalState;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
4
|
type UseModalInContainerParams<Container extends HTMLElement = HTMLElement, Modal extends HTMLElement = Container> = {
|
|
18
5
|
closeOnClickOutside?: boolean;
|
|
19
|
-
transitionDuration?: number;
|
|
20
6
|
windowOffset?: number;
|
|
21
7
|
offset?: number;
|
|
22
8
|
position?: `${PositionContainer}`;
|
|
23
9
|
modalRef: RefObject<Modal>;
|
|
24
10
|
containerRef?: RefObject<Container>;
|
|
25
|
-
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
};
|
|
14
|
+
declare const useModalInContainer: <Container extends HTMLElement = HTMLElement, Modal extends HTMLElement = Container>({ closeOnClickOutside, offset, windowOffset, position, modalRef, containerRef, isOpen, onClose, }: UseModalInContainerParams<Container, Modal>) => void;
|
|
15
|
+
|
|
16
|
+
declare enum ModalState {
|
|
17
|
+
OPENING = "OPENING",
|
|
18
|
+
OPEN = "OPEN",
|
|
19
|
+
CLOSING = "CLOSING",
|
|
20
|
+
CLOSED = "CLOSED"
|
|
21
|
+
}
|
|
22
|
+
type UseModalTransitionParams = {
|
|
23
|
+
transitionDuration?: number;
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
isOpen: boolean;
|
|
26
26
|
};
|
|
27
|
-
declare const
|
|
27
|
+
declare const useModalTransition: ({ transitionDuration, onClose, isOpen }: UseModalTransitionParams) => {
|
|
28
28
|
isVisible: boolean;
|
|
29
|
-
closeModal: () => void;
|
|
30
|
-
openModal: () => void;
|
|
31
29
|
modalState: ModalState;
|
|
32
30
|
};
|
|
33
31
|
|
|
34
|
-
export { ModalState as M, type
|
|
32
|
+
export { ModalState as M, type UseModalTransitionParams as U, type UseModalInContainerParams as a, useModalTransition as b, useModalInContainer as u };
|
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
import { P as PositionContainer } from './get-modal-position-drle0OjP.js';
|
|
3
3
|
|
|
4
|
-
declare enum ModalState {
|
|
5
|
-
OPENING = "OPENING",
|
|
6
|
-
OPEN = "OPEN",
|
|
7
|
-
CLOSING = "CLOSING",
|
|
8
|
-
CLOSED = "CLOSED"
|
|
9
|
-
}
|
|
10
|
-
declare const useModalTransition: (transitionDuration?: number, onClose?: () => void) => {
|
|
11
|
-
isVisible: boolean;
|
|
12
|
-
closeModal: () => void;
|
|
13
|
-
openModal: () => void;
|
|
14
|
-
modalState: ModalState;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
4
|
type UseModalInContainerParams<Container extends HTMLElement = HTMLElement, Modal extends HTMLElement = Container> = {
|
|
18
5
|
closeOnClickOutside?: boolean;
|
|
19
|
-
transitionDuration?: number;
|
|
20
6
|
windowOffset?: number;
|
|
21
7
|
offset?: number;
|
|
22
8
|
position?: `${PositionContainer}`;
|
|
23
9
|
modalRef: RefObject<Modal>;
|
|
24
10
|
containerRef?: RefObject<Container>;
|
|
25
|
-
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
};
|
|
14
|
+
declare const useModalInContainer: <Container extends HTMLElement = HTMLElement, Modal extends HTMLElement = Container>({ closeOnClickOutside, offset, windowOffset, position, modalRef, containerRef, isOpen, onClose, }: UseModalInContainerParams<Container, Modal>) => void;
|
|
15
|
+
|
|
16
|
+
declare enum ModalState {
|
|
17
|
+
OPENING = "OPENING",
|
|
18
|
+
OPEN = "OPEN",
|
|
19
|
+
CLOSING = "CLOSING",
|
|
20
|
+
CLOSED = "CLOSED"
|
|
21
|
+
}
|
|
22
|
+
type UseModalTransitionParams = {
|
|
23
|
+
transitionDuration?: number;
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
isOpen: boolean;
|
|
26
26
|
};
|
|
27
|
-
declare const
|
|
27
|
+
declare const useModalTransition: ({ transitionDuration, onClose, isOpen }: UseModalTransitionParams) => {
|
|
28
28
|
isVisible: boolean;
|
|
29
|
-
closeModal: () => void;
|
|
30
|
-
openModal: () => void;
|
|
31
29
|
modalState: ModalState;
|
|
32
30
|
};
|
|
33
31
|
|
|
34
|
-
export { ModalState as M, type
|
|
32
|
+
export { ModalState as M, type UseModalTransitionParams as U, type UseModalInContainerParams as a, useModalTransition as b, useModalInContainer as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polpo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,8 +41,9 @@
|
|
|
41
41
|
"build": "yarn clean && tsup",
|
|
42
42
|
"publish-package": "yarn lint && yarn build && yarn publish --no-git-tag-version",
|
|
43
43
|
"transform-svgs": "svg-to-react && yarn lint:fix",
|
|
44
|
-
"dev": "storybook dev -p 6006 --quiet",
|
|
45
|
-
"build-storybook": "storybook build"
|
|
44
|
+
"dev": "storybook dev -p 6006 --quiet --debug hmr",
|
|
45
|
+
"build-storybook": "storybook build",
|
|
46
|
+
"debug": "storybook doctor"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@juanmsl/eslint-config": "*",
|
|
@@ -82,7 +82,6 @@ export const CheckboxContainerStyle = styled.section<CheckboxContainerStyleProps
|
|
|
82
82
|
${CheckboxStyle}:hover,
|
|
83
83
|
&:has(.checkbox-label:hover) ${CheckboxStyle} {
|
|
84
84
|
box-shadow: 0 0 0 0.3em ${props => props.$color}88;
|
|
85
|
-
padding: 2px;
|
|
86
85
|
|
|
87
86
|
${CheckboxFillStyle} {
|
|
88
87
|
width: 20%;
|
|
@@ -106,6 +105,5 @@ export const CheckboxContainerStyle = styled.section<CheckboxContainerStyleProps
|
|
|
106
105
|
&:has(.checkbox-input:focus) ${CheckboxStyle},
|
|
107
106
|
&:has(.checkbox-label:focus) ${CheckboxStyle} {
|
|
108
107
|
box-shadow: 0 0 0 0.3em ${props => props.$color}88;
|
|
109
|
-
padding: 2px;
|
|
110
108
|
}
|
|
111
109
|
`;
|
|
@@ -85,7 +85,13 @@ export const InputColor = ({
|
|
|
85
85
|
|
|
86
86
|
return (
|
|
87
87
|
<Field id={id} error={error} isFocus={isFocus} {...fieldProps}>
|
|
88
|
-
<InputColorStyle
|
|
88
|
+
<InputColorStyle
|
|
89
|
+
onClick={e => {
|
|
90
|
+
e.stopPropagation();
|
|
91
|
+
setIsOpen(true);
|
|
92
|
+
}}
|
|
93
|
+
ref={containerRef}
|
|
94
|
+
>
|
|
89
95
|
<InputColorBoxStyle
|
|
90
96
|
className={className}
|
|
91
97
|
style={{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { useTheme } from 'styled-components';
|
|
3
3
|
|
|
4
|
-
import { Menu } from '../../modals';
|
|
4
|
+
import { Menu } from '../../modals/menu';
|
|
5
5
|
|
|
6
6
|
import { OptionsHeaderStyle, OptionsMenuStyle } from './select.style';
|
|
7
7
|
import { OptionsProps, SelectItem } from './select.types';
|
|
@@ -29,6 +29,8 @@ export const Options = <T extends SelectItem>({
|
|
|
29
29
|
maxHeight = 400,
|
|
30
30
|
}: OptionsProps<T>) => {
|
|
31
31
|
const theme = useTheme();
|
|
32
|
+
const optionsGroupRef = useRef<HTMLUListElement>(null);
|
|
33
|
+
const modalRef = useRef<HTMLElement>(null);
|
|
32
34
|
const modalContainerRef = useRef<HTMLElement>(null);
|
|
33
35
|
const isMobile = useMediaQuery(`(max-width: ${theme.constants.breakpoints.mobileL})`);
|
|
34
36
|
const [internalSearchQuery, setInternalSearchQuery] = useState('');
|
|
@@ -123,14 +125,20 @@ export const Options = <T extends SelectItem>({
|
|
|
123
125
|
);
|
|
124
126
|
|
|
125
127
|
const [height, setHeight] = useState<string>('400px');
|
|
128
|
+
const [minHeight, setMinHeight] = useState<string | undefined>(undefined);
|
|
126
129
|
|
|
127
130
|
const getHeight = useCallback(() => {
|
|
128
131
|
const containerBottom = containerRef.current?.getBoundingClientRect().bottom ?? 0;
|
|
132
|
+
const modalHeight = modalRef.current?.getBoundingClientRect().height ?? 0;
|
|
133
|
+
const optionsHeight = optionsGroupRef.current?.scrollHeight ?? 0;
|
|
129
134
|
|
|
130
135
|
const height = Math.min(window.innerHeight - containerBottom - 20, maxHeight);
|
|
136
|
+
const minHeight =
|
|
137
|
+
options.length <= 3 ? modalHeight : optionsHeight > height ? Math.min(150, window.innerHeight - 20) : 0;
|
|
131
138
|
|
|
132
139
|
setHeight(`${Math.round(height)}px`);
|
|
133
|
-
|
|
140
|
+
setMinHeight(`${Math.round(minHeight)}px`);
|
|
141
|
+
}, [containerRef, maxHeight, options.length]);
|
|
134
142
|
|
|
135
143
|
useResizeObserver(containerRef, getHeight);
|
|
136
144
|
useEventListener('resize', getHeight);
|
|
@@ -144,10 +152,12 @@ export const Options = <T extends SelectItem>({
|
|
|
144
152
|
id='form-select'
|
|
145
153
|
isOpen={isOpen}
|
|
146
154
|
onClose={onClose}
|
|
147
|
-
backdrop={isMobile ? 'blur' : '
|
|
155
|
+
backdrop={isMobile ? 'blur' : 'transparent'}
|
|
148
156
|
opacity={isMobile ? 0.8 : 0.4}
|
|
149
157
|
position={isMobile ? 'center' : 'bottom'}
|
|
150
158
|
offset={5}
|
|
159
|
+
windowOffset={10}
|
|
160
|
+
modalRef={modalRef}
|
|
151
161
|
transitionDuration={200}
|
|
152
162
|
containerRef={isMobile ? undefined : containerRef}
|
|
153
163
|
className={menuClassName}
|
|
@@ -158,8 +168,8 @@ export const Options = <T extends SelectItem>({
|
|
|
158
168
|
width: window.innerWidth - 100,
|
|
159
169
|
}
|
|
160
170
|
: {
|
|
171
|
+
minHeight,
|
|
161
172
|
maxHeight: height,
|
|
162
|
-
minHeight: '200px',
|
|
163
173
|
width: containerRef.current?.offsetWidth ?? 'auto',
|
|
164
174
|
}
|
|
165
175
|
}
|
|
@@ -186,6 +196,7 @@ export const Options = <T extends SelectItem>({
|
|
|
186
196
|
data={options}
|
|
187
197
|
renderItem={renderInternalOption}
|
|
188
198
|
emptyMessage={emptyMessage}
|
|
199
|
+
ref={optionsGroupRef}
|
|
189
200
|
/>
|
|
190
201
|
</OptionsMenuStyle>
|
|
191
202
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useMemo } from 'react';
|
|
1
|
+
import React, { ForwardedRef, forwardRef, ReactElement, useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Checkbox } from '../../form';
|
|
4
4
|
import { Icon, IconNameT } from '../../icon';
|
|
@@ -128,12 +128,17 @@ type MenuOptionsGroupProps<T> = InfinityScrollProps<T> & {
|
|
|
128
128
|
style?: React.CSSProperties;
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
const MenuOptionsGroup = <T,>(
|
|
131
|
+
const MenuOptionsGroup = <T,>(
|
|
132
|
+
{ className = '', style = {}, ...infinityScrollProps }: MenuOptionsGroupProps<T>,
|
|
133
|
+
ref: ForwardedRef<HTMLUListElement>,
|
|
134
|
+
) => {
|
|
132
135
|
return (
|
|
133
|
-
<ul className={`menu-content ${className}`} role='listbox' style={style}>
|
|
136
|
+
<ul className={`menu-content ${className}`} role='listbox' style={style} ref={ref}>
|
|
134
137
|
<InfinityScroll {...infinityScrollProps} />
|
|
135
138
|
</ul>
|
|
136
139
|
);
|
|
137
140
|
};
|
|
138
141
|
|
|
139
|
-
Menu.OptionsGroup = MenuOptionsGroup
|
|
142
|
+
Menu.OptionsGroup = forwardRef(MenuOptionsGroup) as <T>(
|
|
143
|
+
p: MenuOptionsGroupProps<T> & { ref?: ForwardedRef<HTMLUListElement> },
|
|
144
|
+
) => ReactElement;
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import React, { CSSProperties,
|
|
1
|
+
import React, { CSSProperties, useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Portal } from '../portal';
|
|
4
4
|
|
|
5
5
|
import { Backdrop, BackdropProps } from './backdrop';
|
|
6
6
|
import { ModalContentStyle, ModalStyle } from './modal.style';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
ModalState,
|
|
10
|
+
useClassNames,
|
|
11
|
+
useModalInContainer,
|
|
12
|
+
UseModalInContainerParams,
|
|
13
|
+
useModalTransition,
|
|
14
|
+
UseModalTransitionParams,
|
|
15
|
+
} from '@polpo/hooks';
|
|
9
16
|
|
|
10
17
|
export type ModalProps = Omit<BackdropProps, 'modalState'> &
|
|
11
|
-
|
|
18
|
+
UseModalTransitionParams &
|
|
19
|
+
Omit<UseModalInContainerParams, 'modalRef'> & {
|
|
12
20
|
id: string;
|
|
13
21
|
children: React.ReactNode;
|
|
14
|
-
isOpen: boolean;
|
|
15
|
-
onClose: () => void;
|
|
16
22
|
className?: string;
|
|
17
23
|
style?: React.CSSProperties;
|
|
18
24
|
rootStyle?: CSSProperties;
|
|
@@ -41,15 +47,21 @@ export const Modal = ({
|
|
|
41
47
|
zIndex = 1000,
|
|
42
48
|
...backdropProps
|
|
43
49
|
}: ModalProps) => {
|
|
50
|
+
const uuid = useMemo(() => crypto.randomUUID(), []);
|
|
44
51
|
const modalRef = useRef<HTMLElement>(null);
|
|
45
|
-
const {
|
|
52
|
+
const { modalState, isVisible } = useModalTransition({
|
|
53
|
+
transitionDuration,
|
|
54
|
+
onClose,
|
|
55
|
+
isOpen,
|
|
56
|
+
});
|
|
57
|
+
useModalInContainer({
|
|
46
58
|
modalRef: modalRefProp ?? modalRef,
|
|
47
59
|
containerRef,
|
|
48
60
|
closeOnClickOutside,
|
|
49
61
|
offset,
|
|
50
62
|
windowOffset,
|
|
51
63
|
position,
|
|
52
|
-
|
|
64
|
+
isOpen: isVisible,
|
|
53
65
|
onClose,
|
|
54
66
|
});
|
|
55
67
|
|
|
@@ -59,20 +71,12 @@ export const Modal = ({
|
|
|
59
71
|
[closeAnimationClassName]: modalState === ModalState.CLOSING || modalState === ModalState.CLOSED,
|
|
60
72
|
});
|
|
61
73
|
|
|
62
|
-
useLayoutEffect(() => {
|
|
63
|
-
if (modalState === ModalState.CLOSED && isOpen) {
|
|
64
|
-
openModal();
|
|
65
|
-
} else if (modalState === ModalState.OPEN && !isOpen) {
|
|
66
|
-
closeModal();
|
|
67
|
-
}
|
|
68
|
-
}, [isOpen, openModal, closeModal, modalState]);
|
|
69
|
-
|
|
70
74
|
if (!isVisible) {
|
|
71
75
|
return null;
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
return (
|
|
75
|
-
<Portal id={`modal-${id}`}>
|
|
79
|
+
<Portal id={`modal-${id}-${uuid}`}>
|
|
76
80
|
<Backdrop {...backdropProps} modalState={modalState} zIndex={zIndex} />
|
|
77
81
|
<ModalStyle
|
|
78
82
|
ref={modalRefProp ?? modalRef}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, ReactNode
|
|
1
|
+
import { forwardRef, ReactNode } from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
3
|
|
|
4
4
|
import { useDomContainer } from '@polpo/hooks';
|
|
@@ -9,8 +9,7 @@ type PortalProps = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
const PortalComponent = ({ children, id }: PortalProps) => {
|
|
12
|
-
const
|
|
13
|
-
const root = useDomContainer(`${id}-${uuid}`);
|
|
12
|
+
const root = useDomContainer(id);
|
|
14
13
|
|
|
15
14
|
if (root === null) {
|
|
16
15
|
return null;
|
|
@@ -1,28 +1,35 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
const createContainer = (containerID: string) => {
|
|
4
|
+
let domContainer = document.getElementById(containerID);
|
|
5
|
+
|
|
6
|
+
if (domContainer === null) {
|
|
7
|
+
domContainer = document.createElement('div');
|
|
8
|
+
domContainer.setAttribute('id', containerID);
|
|
9
|
+
document.body.appendChild(domContainer);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return domContainer;
|
|
13
|
+
};
|
|
2
14
|
|
|
3
15
|
export const useDomContainer = (containerID: string) => {
|
|
16
|
+
const [container, setContainer] = useState<HTMLElement | null>(() => createContainer(containerID));
|
|
17
|
+
|
|
4
18
|
useEffect(() => {
|
|
5
19
|
const domContainer = document.getElementById(containerID);
|
|
6
20
|
|
|
7
|
-
if (domContainer === null) {
|
|
8
|
-
|
|
9
|
-
if (domContainer) {
|
|
10
|
-
document.body.removeChild(domContainer);
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
}, [containerID]);
|
|
15
|
-
|
|
16
|
-
return useMemo(() => {
|
|
17
|
-
let domContainer = document.getElementById(containerID);
|
|
21
|
+
if (container === null || domContainer === null) {
|
|
22
|
+
const domContainer = createContainer(containerID);
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
domContainer = document.createElement('div');
|
|
21
|
-
domContainer.setAttribute('id', containerID);
|
|
22
|
-
|
|
23
|
-
document.body.appendChild(domContainer);
|
|
24
|
+
setContainer(domContainer);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
return
|
|
27
|
-
|
|
27
|
+
return () => {
|
|
28
|
+
if (container && container.parentNode) {
|
|
29
|
+
//document.body.removeChild(container);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}, [container, containerID]);
|
|
33
|
+
|
|
34
|
+
return container;
|
|
28
35
|
};
|
|
@@ -2,7 +2,6 @@ import { RefObject, useCallback, useLayoutEffect, useRef } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { useClickOutside } from './use-click-outside';
|
|
4
4
|
import { useEventListener } from './use-event-listener';
|
|
5
|
-
import { useModalTransition } from './use-modal-transition';
|
|
6
5
|
import { useResizeObserver } from './use-resize-observer';
|
|
7
6
|
|
|
8
7
|
import {
|
|
@@ -26,13 +25,13 @@ export type UseModalInContainerParams<
|
|
|
26
25
|
Modal extends HTMLElement = Container,
|
|
27
26
|
> = {
|
|
28
27
|
closeOnClickOutside?: boolean;
|
|
29
|
-
transitionDuration?: number;
|
|
30
28
|
windowOffset?: number;
|
|
31
29
|
offset?: number;
|
|
32
30
|
position?: `${PositionContainer}`;
|
|
33
31
|
modalRef: RefObject<Modal>;
|
|
34
32
|
containerRef?: RefObject<Container>;
|
|
35
|
-
|
|
33
|
+
isOpen: boolean;
|
|
34
|
+
onClose: () => void;
|
|
36
35
|
};
|
|
37
36
|
|
|
38
37
|
export const useModalInContainer = <
|
|
@@ -43,19 +42,16 @@ export const useModalInContainer = <
|
|
|
43
42
|
offset = 0,
|
|
44
43
|
windowOffset = 0,
|
|
45
44
|
position = PositionContainer.BOTTOM,
|
|
46
|
-
transitionDuration = 0,
|
|
47
45
|
modalRef,
|
|
48
46
|
containerRef,
|
|
47
|
+
isOpen,
|
|
49
48
|
onClose,
|
|
50
49
|
}: UseModalInContainerParams<Container, Modal>) => {
|
|
51
50
|
const containerTemporalRef = useRef<Container>(null);
|
|
52
|
-
const modalState = useModalTransition(transitionDuration, onClose);
|
|
53
|
-
|
|
54
|
-
const { isVisible, closeModal } = modalState;
|
|
55
51
|
|
|
56
52
|
useClickOutside<Modal>(modalRef, () => {
|
|
57
|
-
if (
|
|
58
|
-
|
|
53
|
+
if (isOpen && closeOnClickOutside) {
|
|
54
|
+
onClose();
|
|
59
55
|
}
|
|
60
56
|
});
|
|
61
57
|
|
|
@@ -86,10 +82,10 @@ export const useModalInContainer = <
|
|
|
86
82
|
);
|
|
87
83
|
|
|
88
84
|
const callback = useCallback(() => {
|
|
89
|
-
if (
|
|
85
|
+
if (isOpen) {
|
|
90
86
|
getPosition(modalRef, containerRef ?? containerTemporalRef);
|
|
91
87
|
}
|
|
92
|
-
}, [getPosition,
|
|
88
|
+
}, [getPosition, isOpen, containerRef, modalRef]);
|
|
93
89
|
|
|
94
90
|
useLayoutEffect(callback, [callback]);
|
|
95
91
|
|
|
@@ -97,6 +93,4 @@ export const useModalInContainer = <
|
|
|
97
93
|
useResizeObserver<Modal>(modalRef, callback);
|
|
98
94
|
useEventListener('resize', callback);
|
|
99
95
|
useEventListener('scroll', callback, modalRef);
|
|
100
|
-
|
|
101
|
-
return modalState;
|
|
102
96
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useLayoutEffect, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
export enum ModalState {
|
|
4
4
|
OPENING = 'OPENING',
|
|
@@ -7,7 +7,13 @@ export enum ModalState {
|
|
|
7
7
|
CLOSED = 'CLOSED',
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export type UseModalTransitionParams = {
|
|
11
|
+
transitionDuration?: number;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
isOpen: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const useModalTransition = ({ transitionDuration = 0, onClose, isOpen }: UseModalTransitionParams) => {
|
|
11
17
|
const [modalState, setModalState] = React.useState<ModalState>(ModalState.CLOSED);
|
|
12
18
|
|
|
13
19
|
const isVisible = useMemo(() => {
|
|
@@ -45,10 +51,16 @@ export const useModalTransition = (transitionDuration: number = 0, onClose: () =
|
|
|
45
51
|
}
|
|
46
52
|
}, [modalState, transitionDuration]);
|
|
47
53
|
|
|
54
|
+
useLayoutEffect(() => {
|
|
55
|
+
if (modalState === ModalState.CLOSED && isOpen) {
|
|
56
|
+
openModal();
|
|
57
|
+
} else if (modalState === ModalState.OPEN && !isOpen) {
|
|
58
|
+
closeModal();
|
|
59
|
+
}
|
|
60
|
+
}, [isOpen, openModal, closeModal, modalState]);
|
|
61
|
+
|
|
48
62
|
return {
|
|
49
63
|
isVisible,
|
|
50
|
-
closeModal,
|
|
51
|
-
openModal,
|
|
52
64
|
modalState,
|
|
53
65
|
};
|
|
54
66
|
};
|
package/dist/chunk-LWUSFVRE.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import{a as R,h as O,i as S}from"./chunk-MAWW6AA7.js";import{useCallback as p,useMemo as $,useReducer as X}from"react";import{useCallback as z,useLayoutEffect as F,useRef as V}from"react";var C=e=>{let t=V(!1);return F(()=>(t.current=!0,()=>{t.current=!1}),[]),z((...o)=>{t.current&&e(...o)},[e])};var Y=(e,t)=>{switch(t.type){case"pending":return{status:"pending",data:null,error:null};case"resolved":return{status:"resolved",data:t.data,error:null};case"rejected":return{status:"rejected",data:null,error:t.error};default:throw new Error(`Unhandled action: ${JSON.stringify(t)}`)}},_e=e=>{let[t,o]=X(Y,{status:"idle",data:null,error:null,...e}),n=C(o),r=p(a=>{n({type:"pending"}),a.then(c=>{n({type:"resolved",data:c})},c=>{n({type:"rejected",error:c})})},[n]),s=p(a=>n({type:"resolved",data:a}),[n]),i=p(a=>n({type:"rejected",error:a}),[n]);return $(()=>({setData:s,setError:i,run:r,...t}),[t,r,s,i])};import{useMemo as Q}from"react";var Ze=e=>Q(()=>Object.entries(e).reduce((t,[o,n])=>n?[...t,o]:t,[]).join(" "),[e]);import{useEffect as W,useLayoutEffect as B,useRef as J}from"react";function l(e,t,o,n){let r=J(t);W(()=>{r.current=t},[t]),B(()=>{let s=o?.current??window;if(!(s&&s.addEventListener))return;let i=a=>r.current(a);return s.addEventListener(e,i,n),()=>{s.removeEventListener(e,i,n)}},[e,o,n])}var _=(e,t)=>e.current&&!e.current.contains(t),h=(e,t)=>{l("keydown",o=>{o.key==="Escape"&&t()}),l("mousedown",o=>{let n=o.target;if(!n?.isConnected)return;(Array.isArray(e)?e:[e]).every(s=>_(s,n))&&t()})};import{useState as q}from"react";var at=e=>q(e)[0];import{useState as K,useCallback as L}from"react";var Z=e=>{let t=[];if(e.expires instanceof Date)t.push(`expires=${e.expires.toUTCString()}`);else if(typeof e.days=="number"){let o=new Date;o.setTime(o.getTime()+e.days*24*60*60*1e3),t.push(`expires=${o.toUTCString()}`)}return typeof e.maxAge=="number"&&t.push(`max-age=${e.maxAge}`),t.push(`path=${e.path??"/"}`),e.domain&&t.push(`domain=${e.domain}`),e.secure&&t.push("secure"),e.sameSite&&t.push(`SameSite=${e.sameSite}`),t.length>0?`; ${t.join("; ")}`:""},A=(e,t,o={})=>{if(typeof document>"u")return;let n=encodeURIComponent(t),r=Z(o);document.cookie=`${e}=${n}${r}`},ee=e=>{if(typeof document>"u")return null;let t=`${e}=`,o=document.cookie?document.cookie.split(";"):[];for(let n of o){let r=n.trim();if(r.indexOf(t)===0)return decodeURIComponent(r.substring(t.length))}return null},te=(e,t={})=>{typeof document>"u"||A(e,"",{...t,days:-1})},lt=(e,t,o={})=>{let[n,r]=K(()=>{let a=ee(e);if(a!==null)try{return JSON.parse(a)}catch{return t}return t}),s=L((a,c={})=>{let u={...o,...c},m=JSON.stringify(a);A(e,m,u),r(a)},[e,o]),i=L(()=>{te(e,o),r(t)},[e,t,o]);return[n,s,i]};import{useEffect as ne,useState as oe}from"react";var ft=(e,t=500)=>{let[o,n]=oe(e);return ne(()=>{let r=setTimeout(()=>n(e),t);return()=>{clearTimeout(r)}},[e,t]),o};import{useState as se}from"react";import{useEffect as re}from"react";var f=(e,t)=>{re(()=>{let o=Array.isArray(e)?e:[e],n=new ResizeObserver(t);return o.forEach(r=>r.current&&n.observe(r.current)),()=>{n.disconnect()}},[e,t])};var bt=e=>{let[t,o]=se({width:0,height:0});return f(e,([n])=>{if((n?.borderBoxSize??[])[0]){let{inlineSize:r,blockSize:s}=n.borderBoxSize[0];o({width:r,height:s})}else if(n.contentRect){let{width:r,height:s}=n.contentRect;o({width:r,height:s})}}),t};import{useEffect as ie,useMemo as ae}from"react";var Rt=e=>(ie(()=>{let t=document.getElementById(e);if(t===null)return()=>{t&&document.body.removeChild(t)}},[e]),ae(()=>{let t=document.getElementById(e);return t===null&&(t=document.createElement("div"),t.setAttribute("id",e),document.body.appendChild(t)),t},[e]));import{useEffect as ce,useState as ue}from"react";var le=(o=>(o.PNG="image/png",o.PDF="application/pdf",o))(le||{}),ht=e=>{let[t,o]=ue([]);return ce(()=>{let n=[],r=!1;if(!Array.isArray(e)||e.length===0)o([]);else{let s=e.map(i=>new Promise((a,c)=>{let u=new FileReader;n.push(u),u.onload=m=>{m.target?.result&&a({name:i.name,size:i.size,formatSize:R(i.size),type:i.type,url:m.target.result})},u.onabort=()=>{c(new Error("File reading aborted"))},u.onerror=()=>{c(new Error("Failed to read file"))},u.readAsDataURL(i)}));Promise.all(s).then(i=>{r||o(i)})}return()=>{r=!0,n.forEach(s=>{s.abort()})}},[e]),t};import{useEffect as me,useRef as de,useState as E}from"react";var Pt=()=>{let[e,t]=E(null),[o,n]=E(null),[r,s]=E(!0),i=de(null);return me(()=>{if(!navigator.geolocation){n({code:0,message:"Geolocation is not supported by your browser."}),s(!1);return}let a=u=>{t({...u.coords,timestamp:u.timestamp}),s(!1)},c=u=>{n({code:u.code,message:u.message}),s(!1)};return navigator.geolocation.getCurrentPosition(a,c),i.current=navigator.geolocation.watchPosition(a,c),()=>{i.current!==null&&navigator.geolocation.clearWatch(i.current)}},[]),{data:e,error:o,isLoading:r}};import{useCallback as P,useRef as fe,useState as pe}from"react";var Dt=()=>{let[e,t]=pe(!1),o=fe(null),n=P(()=>t(!0),[]),r=P(()=>t(!1),[]);return l("mouseenter",n,o),l("mouseleave",r,o),e};import{useRef as ve,useState as Te}from"react";import{useEffect as Ee}from"react";var k=(e,t,o={})=>{Ee(()=>{let n=Array.isArray(e)?e:[e],r=new IntersectionObserver(t,o);return n.forEach(s=>s.current&&r.observe(s.current)),()=>{r.disconnect()}},[t,o,e])};var Ft=(e={})=>{let[t,o]=Te(!1),n=ve(null);return k(n,([r])=>{o(r.isIntersecting)},e),{ref:n,inView:t}};import{useCallback as v,useState as ye}from"react";var Yt=({onBlur:e,onFocus:t,onChange:o}={})=>{let[n,r]=ye(!1),s=v(c=>{r(!0),t&&t(c)},[t]),i=v(c=>{r(!1),e&&e(c)},[e]),a=v(c=>{o&&o(c)},[o]);return{isFocus:n,handlers:{onFocus:s,onBlur:i,onChange:a}}};import{useEffect as ge,useState as be}from"react";var Bt=e=>{let[t,o]=be(!1);return ge(()=>{let n=window.matchMedia(e);n.matches!==t&&o(n.matches);let r=()=>{o(n.matches)};return n.addEventListener("change",r),()=>{n.removeEventListener("change",r)}},[t,e]),t};import{useRef as xe,useState as Me}from"react";var qt=()=>{let e=xe(null),[t,o]=Me(!1);return{containerRef:e,isOpen:t,openModal:()=>{o(!0)},closeModal:()=>{o(!1)}}};import{useCallback as D,useLayoutEffect as he,useRef as Le}from"react";import Re,{useCallback as w,useEffect as Oe,useMemo as Se}from"react";var Ce=(r=>(r.OPENING="OPENING",r.OPEN="OPEN",r.CLOSING="CLOSING",r.CLOSED="CLOSED",r))(Ce||{}),N=(e=0,t=()=>null)=>{let[o,n]=Re.useState("CLOSED"),r=Se(()=>o!=="CLOSED",[o]);Oe(()=>{document.documentElement.style.overflow=r?"hidden":"auto"},[r]);let s=w(()=>{["OPENING","OPEN"].includes(o)&&(e>0?(n("CLOSING"),setTimeout(()=>{n("CLOSED"),t()},e)):n("CLOSED"))},[t,o,e]),i=w(()=>{["CLOSING","CLOSED"].includes(o)&&(e>0?(n("OPENING"),setTimeout(()=>{n("OPEN")},e)):n("OPEN"))},[o,e]);return{isVisible:r,closeModal:s,openModal:i,modalState:o}};var I=e=>({x:e.x,y:e.y,w:e.width,h:e.height,top:e.top,left:e.left}),mn=({closeOnClickOutside:e=!0,offset:t=0,windowOffset:o=0,position:n="bottom",transitionDuration:r=0,modalRef:s,containerRef:i,onClose:a})=>{let c=Le(null),u=N(r,a),{isVisible:m,closeModal:G}=u;h(s,()=>{m&&e&&G()});let T=D((y,U)=>{let g=y.current?.getClientRects()[0],b=U.current?.getClientRects()[0];if(!g)return;let x=b?O({c:I(b),m:I(g),offset:t,windowOffset:o,position:n}):S({position:n,windowOffset:o});Object.keys(x).forEach(M=>{y.current?.style.setProperty(M,x[M])})},[n,o,t]),d=D(()=>{m&&T(s,i??c)},[T,m,i,s]);return he(d,[d]),f(i??c,d),f(s,d),l("resize",d),l("scroll",d,s),u};import{useRef as Ae,useState as Pe}from"react";var H=(e,t)=>{let{left:o,top:n}=e,r=o+window.scrollX,s=n+window.scrollY,i=t.pageX-r,a=t.pageY-s;return{x:t.pageX,y:t.pageY,elementX:i,elementY:a,elementPositionX:r,elementPositionY:s}},vn=e=>{let t=Ae(null),[o,n]=Pe({x:null,y:null,elementX:null,elementY:null,elementPositionX:null,elementPositionY:null});return l("mousemove",s=>{let{clientX:i,clientY:a}=s;if(n(c=>({...c,x:i,y:a})),e?.current instanceof Element){let c=H(e.current.getBoundingClientRect(),s);n(u=>({...u,...c}))}else if(t.current instanceof Element){let c=H(t.current.getBoundingClientRect(),s);n(u=>({...u,...c}))}}),{...o,ref:t}};import{useState as ke}from"react";var bn=()=>{let[e,t]=ke(navigator.onLine);return l("online",()=>t(navigator.onLine)),l("offline",()=>t(navigator.onLine)),e};import{useEffect as we,useRef as Ne}from"react";var Rn=()=>{let e=Ne(1);return we(()=>{e.current++}),e.current};import{useEffect as De,useRef as Ie,useState as He}from"react";var Cn=()=>{let e=Ie(null),[t,o]=He([0,0]);return De(()=>{let n=e.current,r=()=>{n&&o([n.scrollLeft,n.scrollTop])};return n&&n.addEventListener("scroll",r),()=>{n&&n.removeEventListener("scroll",r)}},[]),{ref:e,position:t}};import{useEffect as je,useState as j}from"react";function kn(e){let[t,o]=j(e),[n,r]=j([]);return je(()=>{t!==void 0&&r(s=>[...s,t])},[t]),[t,o,n]}import{useCallback as Ge,useState as Ue}from"react";var Dn=(e=!1)=>{let[t,o]=Ue(e),n=Ge(()=>{o(r=>!r)},[]);return[t,n,o]};import{useCallback as ze,useState as Fe}from"react";var jn=(e,t=0)=>{let[o,n]=Fe(t),r=ze(s=>{n(s!==void 0?s:i=>(i+1)%e.length)},[e.length]);return[e[o],r]};import{useEffect as Ve,useState as $e}from"react";var Fn=()=>{let e=()=>{let{innerWidth:n,innerHeight:r}=window;return{width:n,height:r,orientation:n>r?"landscape":"portrait"}},[t,o]=$e(e);return l("resize",()=>{o(e())}),Ve(()=>{o(e())},[]),t};export{C as a,_e as b,Ze as c,l as d,h as e,at as f,lt as g,ft as h,f as i,bt as j,Rt as k,le as l,ht as m,Pt as n,Dt as o,k as p,Ft as q,Yt as r,Bt as s,qt as t,Ce as u,N as v,mn as w,vn as x,bn as y,Rn as z,Cn as A,kn as B,Dn as C,jn as D,Fn as E};
|
|
3
|
-
//# sourceMappingURL=chunk-LWUSFVRE.js.map
|