@adobe-commerce/elsie 1.4.1 → 1.5.0-alpha100
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/bin/builders/gql/index.js +8 -4
- package/bin/builders/gql/validate.js +11 -10
- package/package.json +1 -1
- package/src/components/InputFile/InputFile.css +49 -0
- package/src/components/InputFile/InputFile.stories.tsx +90 -0
- package/src/components/InputFile/InputFile.tsx +59 -0
- package/src/components/InputFile/index.ts +11 -0
- package/src/components/Picker/Picker.tsx +3 -5
- package/src/components/TextSwatch/TextSwatch.tsx +2 -5
- package/src/components/index.ts +1 -0
- package/src/docs/API/render.mdx +0 -16
- package/src/lib/aem/configs.ts +7 -4
- package/src/lib/render.tsx +7 -21
|
@@ -77,20 +77,24 @@ module.exports = async function generateResourceBuilder(yargs) {
|
|
|
77
77
|
alias: 's',
|
|
78
78
|
describe: 'Path to the source code containing GraphQL operations',
|
|
79
79
|
type: 'array',
|
|
80
|
-
string: true,
|
|
81
80
|
demandOption: true,
|
|
82
81
|
})
|
|
82
|
+
.option('excluded', {
|
|
83
|
+
alias: 'x',
|
|
84
|
+
describe: 'Paths to exclude from validation',
|
|
85
|
+
type: 'array',
|
|
86
|
+
demandOption: false,
|
|
87
|
+
})
|
|
83
88
|
.option('endpoints', {
|
|
84
89
|
alias: 'e',
|
|
85
90
|
describe: 'Path to GraphQL endpoints',
|
|
86
91
|
type: 'array',
|
|
87
|
-
string: true,
|
|
88
92
|
demandOption: true,
|
|
89
93
|
});
|
|
90
94
|
},
|
|
91
95
|
async (argv) => {
|
|
92
|
-
const { source, endpoints } = argv;
|
|
93
|
-
await validate(source, endpoints);
|
|
96
|
+
const { source, excluded, endpoints } = argv;
|
|
97
|
+
await validate(source, endpoints, excluded);
|
|
94
98
|
},
|
|
95
99
|
)
|
|
96
100
|
.demandCommand(1, 1, 'choose a command: types, mocks or validate');
|
|
@@ -5,17 +5,20 @@ const parser = require('@babel/parser');
|
|
|
5
5
|
const traverse = require('@babel/traverse');
|
|
6
6
|
const { getIntrospectionQuery, buildClientSchema, parse, validate } = require('graphql');
|
|
7
7
|
|
|
8
|
-
async function walk(dir, collected = []) {
|
|
8
|
+
async function walk(dir, excludedPaths = [], collected = []) {
|
|
9
|
+
if (excludedPaths.includes(dir)) return collected;
|
|
10
|
+
|
|
9
11
|
const dirents = await fsPromises.readdir(dir, { withFileTypes: true });
|
|
10
12
|
|
|
11
13
|
for (const d of dirents) {
|
|
12
14
|
const full = path.resolve(dir, d.name);
|
|
13
15
|
|
|
14
16
|
if (d.isDirectory()) {
|
|
15
|
-
|
|
17
|
+
if (excludedPaths.includes(full)) continue;
|
|
16
18
|
if (d.name === 'node_modules' || d.name.startsWith('.')) continue;
|
|
17
|
-
await walk(full, collected);
|
|
19
|
+
await walk(full, excludedPaths, collected);
|
|
18
20
|
} else if (/\.(c?m?js|ts|tsx)$/.test(d.name)) {
|
|
21
|
+
if (excludedPaths.includes(full)) continue;
|
|
19
22
|
collected.push(full);
|
|
20
23
|
}
|
|
21
24
|
}
|
|
@@ -97,10 +100,10 @@ async function validateGqlOperations(endpoint, operation) {
|
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
async function getAllOperations(directories) {
|
|
103
|
+
async function getAllOperations(directories, excludedPaths = []) {
|
|
101
104
|
let fullContent = '';
|
|
102
105
|
for (const directory of directories) {
|
|
103
|
-
const files = await walk(path.resolve(directory));
|
|
106
|
+
const files = await walk(path.resolve(directory), excludedPaths.map(p => path.resolve(p)));
|
|
104
107
|
for (const f of files) {
|
|
105
108
|
const code = await fsPromises.readFile(f, 'utf8');
|
|
106
109
|
|
|
@@ -120,11 +123,9 @@ async function getAllOperations(directories) {
|
|
|
120
123
|
return fullContent;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
module.exports = async function main(sources, endpoints) {
|
|
126
|
+
module.exports = async function main(sources, endpoints, excluded) {
|
|
126
127
|
for (const endpoint of endpoints) {
|
|
127
|
-
const operations = await getAllOperations(sources);
|
|
128
|
+
const operations = await getAllOperations(sources, excluded);
|
|
128
129
|
if (!operations) {
|
|
129
130
|
console.error('No GraphQL operations found in the specified directories.');
|
|
130
131
|
process.exitCode = 0;
|
|
@@ -132,4 +133,4 @@ module.exports = async function main(sources, endpoints) {
|
|
|
132
133
|
}
|
|
133
134
|
await validateGqlOperations(endpoint, operations);
|
|
134
135
|
}
|
|
135
|
-
}
|
|
136
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/********************************************************************
|
|
2
|
+
* Copyright 2025 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
|
+
/* https://cssguidelin.es/#bem-like-naming */
|
|
11
|
+
|
|
12
|
+
.dropin-input-file__input {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.dropin-input-file__label {
|
|
17
|
+
border: 0 none;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
border-radius: var(--shape-border-radius-3);
|
|
20
|
+
padding: var(--spacing-xsmall) var(--spacing-medium);
|
|
21
|
+
display: flex;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
align-items: center;
|
|
24
|
+
background: var(--color-brand-500);
|
|
25
|
+
color: var(--color-neutral-50);
|
|
26
|
+
font: var(--type-button-2-font);
|
|
27
|
+
letter-spacing: var(--type-button-2-letter-spacing);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.dropin-input-file__label:hover {
|
|
31
|
+
background-color: var(--color-button-hover);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.dropin-input-file__icon {
|
|
35
|
+
height: 24px;
|
|
36
|
+
margin-right: var(--spacing-xsmall);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Medium (portrait tablets and large phones, 768px and up) */
|
|
40
|
+
/* @media only screen and (min-width: 768px) { } */
|
|
41
|
+
|
|
42
|
+
/* Large (landscape tablets, 1024px and up) */
|
|
43
|
+
/* @media only screen and (min-width: 1024px) { } */
|
|
44
|
+
|
|
45
|
+
/* XLarge (laptops/desktops, 1366px and up) */
|
|
46
|
+
/* @media only screen and (min-width: 1366px) { } */
|
|
47
|
+
|
|
48
|
+
/* XXlarge (large laptops and desktops, 1920px and up) */
|
|
49
|
+
/* @media only screen and (min-width: 1920px) { } */
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/********************************************************************
|
|
2
|
+
* Copyright 2025 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
|
+
// https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
|
|
11
|
+
import type { Meta, StoryObj } from '@storybook/preact';
|
|
12
|
+
import { InputFile, InputFileProps } from '@adobe-commerce/elsie/components/InputFile';
|
|
13
|
+
import { action } from '@storybook/addon-actions';
|
|
14
|
+
import { IconsList } from '@adobe-commerce/elsie/components/Icon/Icon.stories.helpers';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Use InputFile to upload files.
|
|
18
|
+
*/
|
|
19
|
+
const meta: Meta<InputFileProps> = {
|
|
20
|
+
title: 'Components/InputFile',
|
|
21
|
+
component: InputFile,
|
|
22
|
+
argTypes: {
|
|
23
|
+
label: {
|
|
24
|
+
description: 'Label for the input file.',
|
|
25
|
+
type: 'string',
|
|
26
|
+
},
|
|
27
|
+
accept: {
|
|
28
|
+
description: 'Restrict selectable file types',
|
|
29
|
+
type: 'string',
|
|
30
|
+
},
|
|
31
|
+
multiple: {
|
|
32
|
+
description: 'Allow multiple files selection.',
|
|
33
|
+
type: {
|
|
34
|
+
name: 'boolean',
|
|
35
|
+
required: false
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
id: {
|
|
39
|
+
description: 'id',
|
|
40
|
+
type: {
|
|
41
|
+
required: false,
|
|
42
|
+
name: 'string'
|
|
43
|
+
},
|
|
44
|
+
control: 'text',
|
|
45
|
+
},
|
|
46
|
+
onChange: {
|
|
47
|
+
description: 'Handler for when the file selection changes.',
|
|
48
|
+
control: false,
|
|
49
|
+
table: {
|
|
50
|
+
type: {
|
|
51
|
+
summary: 'function'
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
icon: {
|
|
56
|
+
description: 'Optional icon.',
|
|
57
|
+
table: {
|
|
58
|
+
type: { summary: 'FunctionComponent' },
|
|
59
|
+
},
|
|
60
|
+
options: Object.keys(IconsList),
|
|
61
|
+
mapping: IconsList,
|
|
62
|
+
control: 'select',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default meta;
|
|
68
|
+
|
|
69
|
+
type Story = StoryObj<InputFileProps>;
|
|
70
|
+
|
|
71
|
+
export const Default: Story = {
|
|
72
|
+
args: {
|
|
73
|
+
label: 'Upload File',
|
|
74
|
+
id: 'single-file-input',
|
|
75
|
+
accept: ".pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .txt, .csv, .jpg, .jpeg, .png, .gif, .bmp, .tiff, .ico, .webp",
|
|
76
|
+
onChange: action('onChange'),
|
|
77
|
+
icon: 'none' as any,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const MultipleFiles: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
label: 'Upload Multiple Files',
|
|
84
|
+
id: 'multiple-files-input',
|
|
85
|
+
accept: ".pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .txt, .csv, .jpg, .jpeg, .png, .gif, .bmp, .tiff, .ico, .webp",
|
|
86
|
+
multiple: true,
|
|
87
|
+
onChange: action('onChange'),
|
|
88
|
+
icon: 'none' as any,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/********************************************************************
|
|
2
|
+
* Copyright 2025 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 { FunctionComponent, VNode } from 'preact';
|
|
11
|
+
import { useId } from 'preact/hooks';
|
|
12
|
+
import { HTMLAttributes } from 'preact/compat';
|
|
13
|
+
import { classes } from '@adobe-commerce/elsie/lib';
|
|
14
|
+
import '@adobe-commerce/elsie/components/InputFile/InputFile.css';
|
|
15
|
+
|
|
16
|
+
export interface InputFileProps extends Omit<HTMLAttributes<HTMLInputElement>, 'type' | 'icon'> {
|
|
17
|
+
accept?: string;
|
|
18
|
+
onChange?: (event: Event) => void;
|
|
19
|
+
label?: string;
|
|
20
|
+
multiple?: boolean;
|
|
21
|
+
icon?: VNode<HTMLAttributes<SVGSVGElement>>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const InputFile: FunctionComponent<InputFileProps> = ({
|
|
25
|
+
accept,
|
|
26
|
+
onChange,
|
|
27
|
+
label = 'Upload Document',
|
|
28
|
+
icon,
|
|
29
|
+
className,
|
|
30
|
+
multiple,
|
|
31
|
+
id: providedId,
|
|
32
|
+
...props
|
|
33
|
+
}) => {
|
|
34
|
+
|
|
35
|
+
const generatedId = useId();
|
|
36
|
+
const id = providedId || generatedId;
|
|
37
|
+
|
|
38
|
+
const handleChange = (e: Event) => {
|
|
39
|
+
onChange?.(e);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className={classes(['dropin-input-file', className])}>
|
|
44
|
+
<label htmlFor={id} className="dropin-input-file__label">
|
|
45
|
+
{icon && <span className="dropin-input-file__icon">{icon}</span>}
|
|
46
|
+
{label}
|
|
47
|
+
</label>
|
|
48
|
+
<input
|
|
49
|
+
id={id}
|
|
50
|
+
type="file"
|
|
51
|
+
accept={accept}
|
|
52
|
+
multiple={multiple}
|
|
53
|
+
onChange={handleChange}
|
|
54
|
+
className="dropin-input-file__input"
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/********************************************************************
|
|
2
|
+
* Copyright 2025 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
|
+
export * from '@adobe-commerce/elsie/components/InputFile/InputFile';
|
|
11
|
+
export { InputFile as default } from '@adobe-commerce/elsie/components/InputFile/InputFile';
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
*******************************************************************/
|
|
9
9
|
|
|
10
10
|
import { Icon } from '@adobe-commerce/elsie/components';
|
|
11
|
+
import '@adobe-commerce/elsie/components/Picker/Picker.css';
|
|
11
12
|
import { ChevronDown } from '@adobe-commerce/elsie/icons';
|
|
12
13
|
import { classes } from '@adobe-commerce/elsie/lib';
|
|
13
14
|
import { FunctionComponent, VNode } from 'preact';
|
|
14
15
|
import { HTMLAttributes, useEffect, useState } from 'preact/compat';
|
|
15
16
|
|
|
16
|
-
import '@adobe-commerce/elsie/components/Picker/Picker.css';
|
|
17
|
-
|
|
18
17
|
type PickerValue = string | null;
|
|
19
18
|
|
|
20
19
|
export interface PickerOption {
|
|
@@ -69,10 +68,9 @@ export const Picker: FunctionComponent<PickerProps> = ({
|
|
|
69
68
|
defaultOption,
|
|
70
69
|
icon,
|
|
71
70
|
className,
|
|
72
|
-
id,
|
|
73
71
|
...props
|
|
74
72
|
}) => {
|
|
75
|
-
const
|
|
73
|
+
const id = props?.id || name || `dropin-picker-${Math.random().toString(36)}`;
|
|
76
74
|
const isRequired = !!props?.required;
|
|
77
75
|
|
|
78
76
|
// find the first option that is not disabled
|
|
@@ -156,7 +154,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
|
|
|
156
154
|
)}
|
|
157
155
|
|
|
158
156
|
<select
|
|
159
|
-
id={
|
|
157
|
+
id={id}
|
|
160
158
|
className={classes([
|
|
161
159
|
'dropin-picker__select',
|
|
162
160
|
`dropin-picker__select--${variant}`,
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
useEffect,
|
|
15
15
|
useRef,
|
|
16
16
|
useCallback,
|
|
17
|
-
useMemo,
|
|
18
17
|
} from 'preact/compat';
|
|
19
18
|
import { classes } from '@adobe-commerce/elsie/lib';
|
|
20
19
|
import '@adobe-commerce/elsie/components/TextSwatch/TextSwatch.css';
|
|
@@ -94,8 +93,6 @@ export const TextSwatch: FunctionComponent<TextSwatchProps> = ({
|
|
|
94
93
|
}
|
|
95
94
|
}, [label]);
|
|
96
95
|
|
|
97
|
-
const uniqueId = useMemo(() => id ?? `${name}_${id}_${Math.random().toString(36)}`, [name, id]);
|
|
98
|
-
|
|
99
96
|
return (
|
|
100
97
|
<div
|
|
101
98
|
className="dropin-text-swatch__container"
|
|
@@ -104,7 +101,7 @@ export const TextSwatch: FunctionComponent<TextSwatchProps> = ({
|
|
|
104
101
|
<input
|
|
105
102
|
type={multi ? 'checkbox' : 'radio'}
|
|
106
103
|
name={name}
|
|
107
|
-
id={
|
|
104
|
+
id={id}
|
|
108
105
|
value={value}
|
|
109
106
|
aria-label={handleAriaLabel()}
|
|
110
107
|
checked={selected}
|
|
@@ -119,7 +116,7 @@ export const TextSwatch: FunctionComponent<TextSwatchProps> = ({
|
|
|
119
116
|
])}
|
|
120
117
|
/>
|
|
121
118
|
<label
|
|
122
|
-
htmlFor={
|
|
119
|
+
htmlFor={id}
|
|
123
120
|
ref={spanRef}
|
|
124
121
|
className={classes([
|
|
125
122
|
'dropin-text-swatch__label',
|
package/src/components/index.ts
CHANGED
|
@@ -48,3 +48,4 @@ export * from '@adobe-commerce/elsie/components/Tag';
|
|
|
48
48
|
export * from '@adobe-commerce/elsie/components/ContentGrid';
|
|
49
49
|
export * from '@adobe-commerce/elsie/components/Pagination';
|
|
50
50
|
export * from '@adobe-commerce/elsie/components/ProductItemCard';
|
|
51
|
+
export * from '@adobe-commerce/elsie/components/InputFile';
|
package/src/docs/API/render.mdx
CHANGED
|
@@ -121,21 +121,5 @@ button.addEventListener('click', () => {
|
|
|
121
121
|
});
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
### Unmounting components without instance access
|
|
125
|
-
|
|
126
|
-
The `Render.unmount` static method provides a way to unmount components from the DOM when you don't have direct access to the component instance.
|
|
127
|
-
This is particularly useful in scenarios where components are rendered inside modals, dialogs, or other temporary containers that need to be cleaned up.
|
|
128
|
-
|
|
129
|
-
#### Example
|
|
130
|
-
|
|
131
|
-
```js
|
|
132
|
-
// Close the dialog
|
|
133
|
-
dialog.close();
|
|
134
|
-
|
|
135
|
-
// Unmount any dropin containers rendered in the modal
|
|
136
|
-
dialog.querySelectorAll('[data-dropin-container]').forEach(Render.unmount);
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
This approach ensures that all dropin components are properly cleaned up when their container elements are removed from the DOM, preventing memory leaks and maintaining application performance.
|
|
140
124
|
</Unstyled>
|
|
141
125
|
|
package/src/lib/aem/configs.ts
CHANGED
|
@@ -40,7 +40,7 @@ function resetConfig() {
|
|
|
40
40
|
* @param {Object} [configObj=config] - The config object.
|
|
41
41
|
* @returns {string} - The root path.
|
|
42
42
|
*/
|
|
43
|
-
function getRootPath(configObj: Config | null = config): string {
|
|
43
|
+
function getRootPath(configObj: Config | null = config, options: { match?: (key: string) => boolean }): string {
|
|
44
44
|
if (!configObj) {
|
|
45
45
|
console.warn('No config found. Please call initializeConfig() first.');
|
|
46
46
|
return '/';
|
|
@@ -56,7 +56,7 @@ function getRootPath(configObj: Config | null = config): string {
|
|
|
56
56
|
.find(
|
|
57
57
|
(key) =>
|
|
58
58
|
window.location.pathname === key ||
|
|
59
|
-
window.location.pathname.startsWith(key)
|
|
59
|
+
(options?.match?.(key) ?? window.location.pathname.startsWith(key))
|
|
60
60
|
);
|
|
61
61
|
|
|
62
62
|
return value ?? '/';
|
|
@@ -126,11 +126,14 @@ function applyConfigOverrides(
|
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
128
|
* Initializes the configuration system.
|
|
129
|
+
* @param {Object} configObj - The config object.
|
|
130
|
+
* @param {Object} [options] - The options object.
|
|
131
|
+
* @param {Function} [options.match] - The function to match the path to the config.
|
|
129
132
|
* @returns {Object} The initialized root configuration
|
|
130
133
|
*/
|
|
131
|
-
function initializeConfig(configObj: Config): ConfigRoot {
|
|
134
|
+
function initializeConfig(configObj: Config, options?: { match?: (key: string) => boolean }): ConfigRoot {
|
|
132
135
|
config = configObj;
|
|
133
|
-
rootPath = getRootPath(config);
|
|
136
|
+
rootPath = getRootPath(config, { match: options?.match });
|
|
134
137
|
rootConfig = applyConfigOverrides(config, rootPath);
|
|
135
138
|
return rootConfig;
|
|
136
139
|
}
|
package/src/lib/render.tsx
CHANGED
|
@@ -71,21 +71,17 @@ export class Render {
|
|
|
71
71
|
rootElement.innerHTML = '';
|
|
72
72
|
|
|
73
73
|
// clone the root element to initialize rendering on the background
|
|
74
|
-
const
|
|
74
|
+
const tmp = document.createElement('div');
|
|
75
75
|
|
|
76
76
|
// apply base design tokens and global styles to the root element
|
|
77
77
|
rootElement.classList.add('dropin-design');
|
|
78
|
-
rootElement.setAttribute('data-dropin-container', Component.name);
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
(rootElement as any).__rootElement = root;
|
|
82
|
-
|
|
83
|
-
render(<Root next={state} />, root);
|
|
79
|
+
render(<Root next={state} />, tmp);
|
|
84
80
|
|
|
85
81
|
// API object to control the rendered component
|
|
86
82
|
const API: RenderAPI = {
|
|
87
83
|
remove: () => {
|
|
88
|
-
render(null,
|
|
84
|
+
render(null, tmp);
|
|
89
85
|
},
|
|
90
86
|
setProps: (cb: (prev: T) => T) => {
|
|
91
87
|
const next = cb(state.peek());
|
|
@@ -101,7 +97,7 @@ export class Render {
|
|
|
101
97
|
rootElement.classList.add('dropin-design');
|
|
102
98
|
|
|
103
99
|
// append the rendered component to the DOM only when all slots are resolved
|
|
104
|
-
rootElement.appendChild(
|
|
100
|
+
rootElement.appendChild(tmp.firstChild ?? tmp);
|
|
105
101
|
|
|
106
102
|
return resolve(API);
|
|
107
103
|
}
|
|
@@ -110,24 +106,14 @@ export class Render {
|
|
|
110
106
|
};
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
/**
|
|
114
|
-
* Unmounts a container from a root element.
|
|
115
|
-
* @param rootElement - The root element to unmount the container from.
|
|
116
|
-
*/
|
|
117
|
-
static unmount(rootElement: HTMLElement) {
|
|
118
|
-
const root = (rootElement as any)?.__rootElement;
|
|
119
|
-
if (!root) throw new Error('Root element is not defined');
|
|
120
|
-
render(null, root);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
109
|
/**
|
|
124
110
|
* UnRenders a component from a root element.
|
|
125
111
|
* @param rootElement - The root element to unmount the component from.
|
|
126
|
-
* @deprecated Use `remove` method from the returned object of the `mount` method instead
|
|
112
|
+
* @deprecated Use `remove` method from the returned object of the `mount` method instead.
|
|
127
113
|
*/
|
|
128
114
|
unmount(rootElement: HTMLElement) {
|
|
129
115
|
if (!rootElement) throw new Error('Root element is not defined');
|
|
130
|
-
rootElement.firstChild?.remove();
|
|
116
|
+
rootElement.firstChild?.remove();
|
|
131
117
|
}
|
|
132
118
|
|
|
133
119
|
/**
|
|
@@ -149,4 +135,4 @@ export class Render {
|
|
|
149
135
|
{ ...options }
|
|
150
136
|
);
|
|
151
137
|
}
|
|
152
|
-
}
|
|
138
|
+
}
|