@adobe-commerce/elsie 1.3.0-alpha04 → 1.3.0-alpha068
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe-commerce/elsie",
|
|
3
|
-
"version": "1.3.0-
|
|
3
|
+
"version": "1.3.0-alpha068",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"description": "Domain Package SDK",
|
|
6
6
|
"engines": {
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@adobe-commerce/event-bus": "~1.0.0",
|
|
30
|
-
"@adobe-commerce/fetch-graphql": "
|
|
31
|
-
"@adobe-commerce/recaptcha": "
|
|
30
|
+
"@adobe-commerce/fetch-graphql": "1.1.0-beta1",
|
|
31
|
+
"@adobe-commerce/recaptcha": "1.0.1-beta1",
|
|
32
32
|
"@adobe-commerce/storefront-design": "~1.0.0",
|
|
33
|
-
"@dropins/build-tools": "
|
|
33
|
+
"@dropins/build-tools": "1.0.1-beta1",
|
|
34
34
|
"preact": "~10.22.1",
|
|
35
35
|
"vite-plugin-banner": "^0.8.0"
|
|
36
36
|
},
|
|
@@ -11,7 +11,7 @@ import { Meta, StoryObj } from '@storybook/preact';
|
|
|
11
11
|
import { Modal as component, ModalProps } from './Modal';
|
|
12
12
|
import { useState } from 'preact/hooks';
|
|
13
13
|
import { Button } from '../Button';
|
|
14
|
-
import { expect, userEvent, within
|
|
14
|
+
import { expect, userEvent, within } from '@storybook/test';
|
|
15
15
|
|
|
16
16
|
const meta: Meta<ModalProps> = {
|
|
17
17
|
title: 'Components/Modal',
|
|
@@ -107,21 +107,13 @@ export const SmallModal: Story = {
|
|
|
107
107
|
const canvas = within(canvasElement);
|
|
108
108
|
await userEvent.click(canvas.getByRole('button'));
|
|
109
109
|
|
|
110
|
-
const portalRoot = await waitFor(() => {
|
|
111
|
-
const root = document.querySelector('[data-portal-root]') as HTMLDivElement;
|
|
112
|
-
expect(root).toBeTruthy();
|
|
113
|
-
return root;
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
await expect(portalRoot).toBeVisible();
|
|
117
|
-
|
|
118
110
|
const modal = document.querySelector(
|
|
119
111
|
'.dropin-modal__body'
|
|
120
112
|
) as HTMLDivElement;
|
|
121
113
|
|
|
122
114
|
await expect(modal).toBeVisible();
|
|
123
115
|
|
|
124
|
-
expect(
|
|
116
|
+
await expect(await canvas.findByText('Small modal')).toBeVisible();
|
|
125
117
|
|
|
126
118
|
const closeButton = document.querySelector(
|
|
127
119
|
'.dropin-modal__header-close-button'
|
|
@@ -156,21 +148,13 @@ export const MediumModal: Story = {
|
|
|
156
148
|
const canvas = within(canvasElement);
|
|
157
149
|
await userEvent.click(canvas.getByRole('button'));
|
|
158
150
|
|
|
159
|
-
const portalRoot = await waitFor(() => {
|
|
160
|
-
const root = document.querySelector('[data-portal-root]') as HTMLDivElement;
|
|
161
|
-
expect(root).toBeTruthy();
|
|
162
|
-
return root;
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
await expect(portalRoot).toBeVisible();
|
|
166
|
-
|
|
167
151
|
const modal = document.querySelector(
|
|
168
152
|
'.dropin-modal__body'
|
|
169
153
|
) as HTMLDivElement;
|
|
170
154
|
|
|
171
155
|
await expect(modal).toBeVisible();
|
|
172
156
|
|
|
173
|
-
expect(
|
|
157
|
+
await expect(await canvas.findByText('Medium modal')).toBeVisible();
|
|
174
158
|
|
|
175
159
|
const closeButton = document.querySelector(
|
|
176
160
|
'.dropin-modal__header-close-button'
|
|
@@ -203,17 +187,11 @@ export const FullModal: Story = {
|
|
|
203
187
|
const canvas = within(canvasElement);
|
|
204
188
|
await userEvent.click(canvas.getByRole('button'));
|
|
205
189
|
|
|
206
|
-
const portalRoot = await waitFor(() => {
|
|
207
|
-
const root = document.querySelector('[data-portal-root]') as HTMLDivElement;
|
|
208
|
-
expect(root).toBeTruthy();
|
|
209
|
-
return root;
|
|
210
|
-
});
|
|
211
|
-
|
|
212
190
|
const modal = document.querySelector(
|
|
213
191
|
'.dropin-modal__body'
|
|
214
192
|
) as HTMLDivElement;
|
|
215
193
|
|
|
216
|
-
await expect(
|
|
194
|
+
await expect(modal).toBeVisible();
|
|
217
195
|
|
|
218
196
|
const closeButton = document.querySelector(
|
|
219
197
|
'.dropin-modal__header-close-button'
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
import { Button } from '../Button';
|
|
19
19
|
import { Close as CloseSVG } from '@adobe-commerce/elsie/icons';
|
|
20
20
|
import { VNode } from 'preact';
|
|
21
|
-
import { Portal } from '../Portal/Portal';
|
|
22
21
|
|
|
23
22
|
import '@adobe-commerce/elsie/components/Modal/Modal.css';
|
|
24
23
|
|
|
@@ -107,54 +106,52 @@ export const Modal: FunctionComponent<ModalProps> = ({
|
|
|
107
106
|
}, []);
|
|
108
107
|
|
|
109
108
|
return (
|
|
110
|
-
<
|
|
109
|
+
<div
|
|
110
|
+
className={classes([
|
|
111
|
+
'dropin-modal',
|
|
112
|
+
['dropin-modal--dim', backgroundDim],
|
|
113
|
+
])}
|
|
114
|
+
>
|
|
111
115
|
<div
|
|
116
|
+
{...props}
|
|
112
117
|
className={classes([
|
|
113
|
-
'dropin-
|
|
114
|
-
[
|
|
118
|
+
'dropin-modal__body',
|
|
119
|
+
[`dropin-modal__body--${size}`, size],
|
|
120
|
+
className,
|
|
115
121
|
])}
|
|
116
122
|
>
|
|
117
123
|
<div
|
|
118
|
-
{...props}
|
|
119
124
|
className={classes([
|
|
120
|
-
'dropin-
|
|
121
|
-
[
|
|
122
|
-
className,
|
|
125
|
+
'dropin-modal__header',
|
|
126
|
+
['dropin-modal__header-title', !!title],
|
|
123
127
|
])}
|
|
124
128
|
>
|
|
125
|
-
|
|
126
|
-
className={classes([
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
className={classes([
|
|
150
|
-
'dropin-modal__content',
|
|
151
|
-
['dropin-modal__body--centered', centered],
|
|
152
|
-
])}
|
|
153
|
-
>
|
|
154
|
-
{children}
|
|
155
|
-
</div>
|
|
129
|
+
{title && (
|
|
130
|
+
<div className={classes(['dropin-modal__header-title-content'])}>
|
|
131
|
+
{title}
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
134
|
+
|
|
135
|
+
{showCloseButton && (
|
|
136
|
+
<Button
|
|
137
|
+
aria-label={translations.modalCloseLabel}
|
|
138
|
+
variant="tertiary"
|
|
139
|
+
className="dropin-modal__header-close-button"
|
|
140
|
+
onClick={handleOnClose}
|
|
141
|
+
icon={<CloseSVG />}
|
|
142
|
+
/>
|
|
143
|
+
)}
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<div
|
|
147
|
+
className={classes([
|
|
148
|
+
'dropin-modal__content',
|
|
149
|
+
['dropin-modal__body--centered', centered],
|
|
150
|
+
])}
|
|
151
|
+
>
|
|
152
|
+
{children}
|
|
156
153
|
</div>
|
|
157
154
|
</div>
|
|
158
|
-
</
|
|
155
|
+
</div>
|
|
159
156
|
);
|
|
160
157
|
};
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/********************************************************************
|
|
2
|
-
* Copyright 2024 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
8
|
-
*******************************************************************/
|
|
9
|
-
|
|
10
|
-
import { Meta, StoryObj } from '@storybook/preact';
|
|
11
|
-
import { Portal } from './Portal';
|
|
12
|
-
import { Button } from '../Button';
|
|
13
|
-
import { useState } from 'preact/compat';
|
|
14
|
-
|
|
15
|
-
const meta: Meta<typeof Portal> = {
|
|
16
|
-
title: 'Components/Portal',
|
|
17
|
-
component: Portal,
|
|
18
|
-
parameters: {
|
|
19
|
-
layout: 'centered',
|
|
20
|
-
},
|
|
21
|
-
tags: ['autodocs'],
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default meta;
|
|
25
|
-
type Story = StoryObj<typeof Portal>;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* ```ts
|
|
29
|
-
* import { Portal } from '@/elsie/components/Portal';
|
|
30
|
-
*
|
|
31
|
-
* <Portal>
|
|
32
|
-
* <div>👋 Howdy, I'm Howdy!</div>
|
|
33
|
-
* </Portal>
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
// Portal with dynamic content
|
|
38
|
-
export const DynamicContent: Story = {
|
|
39
|
-
render: () => {
|
|
40
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
41
|
-
const [count, setCount] = useState(0);
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div style={{ border: '2px dashed #ccc', padding: '20px' }}>
|
|
45
|
-
<Button onClick={() => setIsOpen(!isOpen)}>
|
|
46
|
-
{isOpen ? 'Close Portal' : 'Open Portal'}
|
|
47
|
-
</Button>
|
|
48
|
-
|
|
49
|
-
{isOpen && (
|
|
50
|
-
<Portal>
|
|
51
|
-
<div style={{
|
|
52
|
-
position: 'fixed',
|
|
53
|
-
top: '50%',
|
|
54
|
-
left: '50%',
|
|
55
|
-
transform: 'translate(-50%, -50%)',
|
|
56
|
-
background: 'white',
|
|
57
|
-
padding: '20px',
|
|
58
|
-
border: '1px solid #ccc',
|
|
59
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
|
60
|
-
}}>
|
|
61
|
-
<p>Portal content with counter: {count}</p>
|
|
62
|
-
<Button onClick={() => setCount(c => c + 1)}>
|
|
63
|
-
Increment Counter
|
|
64
|
-
</Button>
|
|
65
|
-
<Button
|
|
66
|
-
variant="tertiary"
|
|
67
|
-
onClick={() => setIsOpen(false)}
|
|
68
|
-
style={{ marginLeft: '8px' }}
|
|
69
|
-
>
|
|
70
|
-
Close
|
|
71
|
-
</Button>
|
|
72
|
-
</div>
|
|
73
|
-
</Portal>
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
);
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// Portal with nested portals
|
|
81
|
-
export const NestedPortals: Story = {
|
|
82
|
-
render: () => {
|
|
83
|
-
const [isOuterOpen, setOuterOpen] = useState(false);
|
|
84
|
-
const [isInnerOpen, setInnerOpen] = useState(false);
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<div style={{ border: '2px dashed #ccc', padding: '20px' }}>
|
|
88
|
-
<Button onClick={() => setOuterOpen(!isOuterOpen)}>
|
|
89
|
-
{isOuterOpen ? 'Close Outer Portal' : 'Open Outer Portal'}
|
|
90
|
-
</Button>
|
|
91
|
-
|
|
92
|
-
{isOuterOpen && (
|
|
93
|
-
<Portal>
|
|
94
|
-
<div style={{
|
|
95
|
-
position: 'fixed',
|
|
96
|
-
top: '50%',
|
|
97
|
-
left: '50%',
|
|
98
|
-
transform: 'translate(-50%, -50%)',
|
|
99
|
-
background: 'white',
|
|
100
|
-
padding: '20px',
|
|
101
|
-
border: '1px solid #ccc',
|
|
102
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
|
103
|
-
}}>
|
|
104
|
-
<p>Outer Portal Content</p>
|
|
105
|
-
<Button onClick={() => setInnerOpen(!isInnerOpen)}>
|
|
106
|
-
{isInnerOpen ? 'Close Inner Portal' : 'Open Inner Portal'}
|
|
107
|
-
</Button>
|
|
108
|
-
|
|
109
|
-
{isInnerOpen && (
|
|
110
|
-
<Portal>
|
|
111
|
-
<div style={{
|
|
112
|
-
position: 'fixed',
|
|
113
|
-
top: '60%',
|
|
114
|
-
left: '50%',
|
|
115
|
-
transform: 'translate(-50%, -50%)',
|
|
116
|
-
background: 'white',
|
|
117
|
-
padding: '20px',
|
|
118
|
-
border: '1px solid #ccc',
|
|
119
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
|
120
|
-
}}>
|
|
121
|
-
<p>Inner Portal Content</p>
|
|
122
|
-
<Button
|
|
123
|
-
variant="tertiary"
|
|
124
|
-
onClick={() => setInnerOpen(false)}
|
|
125
|
-
>
|
|
126
|
-
Close Inner Portal
|
|
127
|
-
</Button>
|
|
128
|
-
</div>
|
|
129
|
-
</Portal>
|
|
130
|
-
)}
|
|
131
|
-
|
|
132
|
-
<Button
|
|
133
|
-
variant="tertiary"
|
|
134
|
-
onClick={() => setOuterOpen(false)}
|
|
135
|
-
style={{ marginLeft: '8px' }}
|
|
136
|
-
>
|
|
137
|
-
Close Outer Portal
|
|
138
|
-
</Button>
|
|
139
|
-
</div>
|
|
140
|
-
</Portal>
|
|
141
|
-
)}
|
|
142
|
-
</div>
|
|
143
|
-
);
|
|
144
|
-
},
|
|
145
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/********************************************************************
|
|
2
|
-
* Copyright 2024 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this
|
|
6
|
-
* file in accordance with the terms of the Adobe license agreement
|
|
7
|
-
* accompanying it.
|
|
8
|
-
*******************************************************************/
|
|
9
|
-
|
|
10
|
-
import { ComponentChildren, render } from 'preact';
|
|
11
|
-
import { FunctionComponent, useEffect, useRef } from 'preact/compat';
|
|
12
|
-
|
|
13
|
-
interface PortalProps {
|
|
14
|
-
children: ComponentChildren;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const Portal: FunctionComponent<PortalProps> = ({ children }) => {
|
|
18
|
-
const portalRoot = useRef<HTMLDivElement | null>(null);
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
// Create portal root if it doesn't exist
|
|
22
|
-
if (!portalRoot.current) {
|
|
23
|
-
portalRoot.current = document.createElement('div');
|
|
24
|
-
portalRoot.current.setAttribute('data-portal-root', '');
|
|
25
|
-
portalRoot.current.classList.add('dropin-design');
|
|
26
|
-
document.body.appendChild(portalRoot.current);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Render children into portal root
|
|
30
|
-
render(children, portalRoot.current);
|
|
31
|
-
|
|
32
|
-
// Cleanup
|
|
33
|
-
return () => {
|
|
34
|
-
if (portalRoot.current) {
|
|
35
|
-
render(null, portalRoot.current);
|
|
36
|
-
portalRoot.current.remove();
|
|
37
|
-
portalRoot.current = null;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}, [children]);
|
|
41
|
-
|
|
42
|
-
return null;
|
|
43
|
-
};
|