@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-alpha04",
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": "~1.0.0",
31
- "@adobe-commerce/recaptcha": "~1.0.0",
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": "~1.0.0",
33
+ "@dropins/build-tools": "1.0.1-beta1",
34
34
  "preact": "~10.22.1",
35
35
  "vite-plugin-banner": "^0.8.0"
36
36
  },
@@ -10,10 +10,10 @@
10
10
  /* https://cssguidelin.es/#bem-like-naming */
11
11
 
12
12
  .dropin-modal {
13
+ height: 100vh;
14
+ width: 100vw;
13
15
  position: fixed;
14
16
  top: 0;
15
- right: 0;
16
- bottom: 0;
17
17
  left: 0;
18
18
  z-index: 99999;
19
19
  overflow: auto;
@@ -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, waitFor } from '@storybook/test';
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(portalRoot.querySelector('h4')?.innerText).toBe('Small modal');
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(portalRoot.querySelector('h3')?.innerText).toBe('Medium modal');
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(portalRoot).toBeVisible();
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
- <Portal>
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-modal',
114
- ['dropin-modal--dim', backgroundDim],
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-modal__body',
121
- [`dropin-modal__body--${size}`, size],
122
- className,
125
+ 'dropin-modal__header',
126
+ ['dropin-modal__header-title', !!title],
123
127
  ])}
124
128
  >
125
- <div
126
- className={classes([
127
- 'dropin-modal__header',
128
- ['dropin-modal__header-title', !!title],
129
- ])}
130
- >
131
- {title && (
132
- <div className={classes(['dropin-modal__header-title-content'])}>
133
- {title}
134
- </div>
135
- )}
136
-
137
- {showCloseButton && (
138
- <Button
139
- aria-label={translations.modalCloseLabel}
140
- variant="tertiary"
141
- className="dropin-modal__header-close-button"
142
- onClick={handleOnClose}
143
- icon={<CloseSVG />}
144
- />
145
- )}
146
- </div>
147
-
148
- <div
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
- </Portal>
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
- };