@adobe-commerce/elsie 1.1.0-alpha8 → 1.1.0-beta1

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.
@@ -1,3 +1,12 @@
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
+
1
10
  const path = require('path');
2
11
  const fs = require('fs');
3
12
  const writeFile = require('../../../lib/write-file');
@@ -1,9 +1,18 @@
1
1
  const { stripIndent } = require('common-tags');
2
2
 
3
3
  module.exports = ({ basename }) => {
4
- return `${stripIndent`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${stripIndent`
5
14
  export const ${basename} = () => {
6
15
  return 'Howdy!';
7
16
  }
8
- `}\n`;
17
+ `}\n`;
9
18
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ basename, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  export * from '${importPath}/${basename}';
6
- `}\n`;
15
+ `}\n`;
7
16
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ pathname, basename, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  import { Meta } from '@storybook/blocks';
6
15
 
7
16
  <Meta title="API/${pathname}" />
@@ -19,5 +28,5 @@ module.exports = ({ pathname, basename, importPath = '.' }) => {
19
28
  \`\`\`ts
20
29
  ${basename}();
21
30
  \`\`\`
22
- `}\n`;
31
+ `}\n`;
23
32
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ name, basename, pathname, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  import { ${basename} } from '${importPath}';
6
15
 
7
16
  describe('${name}/api/${pathname}', () => {
@@ -11,5 +20,5 @@ module.exports = ({ name, basename, pathname, importPath = '.' }) => {
11
20
  expect(value).toEqual('Howdy!');
12
21
  });
13
22
  });
14
- `}\n`;
23
+ `}\n`;
15
24
  };
@@ -1,3 +1,12 @@
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
+
1
10
  const path = require('path');
2
11
  const fs = require('fs');
3
12
  const writeFile = require('../../../lib/write-file');
@@ -5,7 +5,16 @@ module.exports = ({ basename, importPath = '.', skipCSS, cssPrefix }) => {
5
5
  const _name = hyphenatedName(basename);
6
6
 
7
7
  if (skipCSS)
8
- return `${stripIndent`
8
+ return `/********************************************************************
9
+ * Copyright 2025 Adobe
10
+ * All Rights Reserved.
11
+ *
12
+ * NOTICE: Adobe permits you to use, modify, and distribute this
13
+ * file in accordance with the terms of the Adobe license agreement
14
+ * accompanying it.
15
+ *******************************************************************/
16
+
17
+ ${stripIndent`
9
18
  import { FunctionComponent } from 'preact';
10
19
  import { HTMLAttributes } from 'preact/compat';
11
20
 
@@ -18,9 +27,18 @@ module.exports = ({ basename, importPath = '.', skipCSS, cssPrefix }) => {
18
27
  </div>
19
28
  );
20
29
  };
21
- `}\n`;
30
+ `}\n`;
22
31
 
23
- return `${stripIndent`
32
+ return `/********************************************************************
33
+ * Copyright 2025 Adobe
34
+ * All Rights Reserved.
35
+ *
36
+ * NOTICE: Adobe permits you to use, modify, and distribute this
37
+ * file in accordance with the terms of the Adobe license agreement
38
+ * accompanying it.
39
+ *******************************************************************/
40
+
41
+ ${stripIndent`
24
42
  import { FunctionComponent } from 'preact';
25
43
  import { HTMLAttributes } from 'preact/compat';
26
44
  import { classes } from '@adobe-commerce/elsie/lib';
@@ -39,5 +57,5 @@ module.exports = ({ basename, importPath = '.', skipCSS, cssPrefix }) => {
39
57
  </div>
40
58
  );
41
59
  };
42
- `}\n`;
60
+ `}\n`;
43
61
  };
@@ -4,7 +4,16 @@ const { hyphenatedName } = require('../../../../lib/string');
4
4
  module.exports = ({ basename, cssPrefix }) => {
5
5
  const _name = hyphenatedName(basename);
6
6
 
7
- return `${source`
7
+ return `/********************************************************************
8
+ * Copyright 2025 Adobe
9
+ * All Rights Reserved.
10
+ *
11
+ * NOTICE: Adobe permits you to use, modify, and distribute this
12
+ * file in accordance with the terms of the Adobe license agreement
13
+ * accompanying it.
14
+ *******************************************************************/
15
+
16
+ ${source`
8
17
  /* https://cssguidelin.es/#bem-like-naming */
9
18
 
10
19
  /* .${cssPrefix}${_name} { } */
@@ -20,5 +29,5 @@ module.exports = ({ basename, cssPrefix }) => {
20
29
 
21
30
  /* XXlarge (large laptops and desktops, 1920px and up) */
22
31
  /* @media only screen and (min-width: 1920px) { } */
23
- `}\n`;
32
+ `}\n`;
24
33
  };
@@ -1,8 +1,17 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ basename, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  export * from '${importPath}/${basename}';
6
15
  export { ${basename} as default } from '${importPath}/${basename}';
7
- `}\n`;
16
+ `}\n`;
8
17
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ name, pathname, basename, group, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
6
15
  import type { Meta, StoryObj } from '@storybook/preact';
7
16
  import { ${basename} as component, ${basename}Props } from '${importPath}';
@@ -42,5 +51,5 @@ module.exports = ({ name, pathname, basename, group, importPath = '.' }) => {
42
51
  children: "👋 Hello from your new ${basename} story!",
43
52
  },
44
53
  };
45
- `}\n`;
54
+ `}\n`;
46
55
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ name, basename, pathname, group, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  /** https://preactjs.com/guide/v10/preact-testing-library/ */
6
15
 
7
16
  import { render } from '@adobe-commerce/elsie/lib/tests';
@@ -15,5 +24,5 @@ module.exports = ({ name, basename, pathname, group, importPath = '.' }) => {
15
24
  expect(!!container).toEqual(true);
16
25
  });
17
26
  });
18
- `}\n`;
27
+ `}\n`;
19
28
  };
@@ -1,3 +1,12 @@
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
+
1
10
  const path = require('path');
2
11
  const fs = require('fs/promises');
3
12
  const m = require('../../../lib/log-message');
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ name, importPath }) =>
4
- `${source`
4
+ `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  module.exports = {
6
15
  name: '${name}',
7
16
  api: {
@@ -1,3 +1,12 @@
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
+
1
10
  const path = require('path');
2
11
  const fs = require('fs');
3
12
  const writeFile = require('../../../lib/write-file');
@@ -1,7 +1,16 @@
1
1
  const { stripIndent } = require('common-tags');
2
2
 
3
3
  module.exports = ({ basename }) => {
4
- return `${stripIndent`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${stripIndent`
5
14
  import { HTMLAttributes } from 'preact/compat';
6
15
  import { Container } from '@adobe-commerce/elsie/lib';
7
16
 
@@ -14,5 +23,5 @@ module.exports = ({ basename }) => {
14
23
  </div>
15
24
  );
16
25
  };
17
- `}\n`;
26
+ `}\n`;
18
27
  };
@@ -1,8 +1,17 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ basename, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  export * from '${importPath}/${basename}';
6
15
  export { ${basename} as default } from '${importPath}/${basename}';
7
- `}\n`;
16
+ `}\n`;
8
17
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ pathname, basename, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
6
15
  import type { Meta, StoryObj } from '@storybook/preact';
7
16
  import { ${basename} as component, ${basename}Props } from '${importPath}';
@@ -30,5 +39,5 @@ module.exports = ({ pathname, basename, importPath = '.' }) => {
30
39
  children: "👋 Howdy, I'm Howdy!",
31
40
  },
32
41
  };
33
- `}\n`;
42
+ `}\n`;
34
43
  };
@@ -1,7 +1,16 @@
1
1
  const { source } = require('common-tags');
2
2
 
3
3
  module.exports = ({ name, basename, pathname, importPath = '.' }) => {
4
- return `${source`
4
+ return `/********************************************************************
5
+ * Copyright 2025 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: Adobe permits you to use, modify, and distribute this
9
+ * file in accordance with the terms of the Adobe license agreement
10
+ * accompanying it.
11
+ *******************************************************************/
12
+
13
+ ${source`
5
14
  /** https://preactjs.com/guide/v10/preact-testing-library/ */
6
15
 
7
16
  import { render } from '@adobe-commerce/elsie/lib/tests';
@@ -15,5 +24,5 @@ module.exports = ({ name, basename, pathname, importPath = '.' }) => {
15
24
  expect(!!container).toEqual(true);
16
25
  });
17
26
  });
18
- `}\n`;
27
+ `}\n`;
19
28
  };
@@ -1,3 +1,12 @@
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
+
1
10
  const path = require('path');
2
11
  const { toPascalCase, toCamelCase } = require('../../lib/string');
3
12
  const m = require('../../lib/log-message');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe-commerce/elsie",
3
- "version": "1.1.0-alpha8",
3
+ "version": "1.1.0-beta1",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "description": "Domain Package SDK",
6
6
  "engines": {
@@ -340,15 +340,15 @@ export const CartItem: FunctionComponent<CartItemProps> = ({
340
340
  )}
341
341
  </div>
342
342
 
343
+ {/* Actions */}
343
344
  {actions && (
344
345
  <div className={classes(['dropin-cart-item__actions'])}>
345
- {/* Actions */}
346
- {actions && (
346
+ {
347
347
  <VComponent
348
348
  node={actions}
349
349
  className={classes(['dropin-cart-item__buttons'])}
350
350
  />
351
- )}
351
+ }
352
352
  </div>
353
353
  )}
354
354
 
@@ -32,6 +32,41 @@ The `<Slot />` component is used to define a slot in a container. It receives a
32
32
 
33
33
  The name of the slot in _PascalCase_. `string` (required).
34
34
 
35
+ ### slotTag
36
+
37
+ The HTML tag to use for the slot's wrapper element. This allows you to change the wrapper element from the default `div` to any valid HTML tag (e.g., 'span', 'p', 'a', etc.). When using specific tags like 'a', you can also provide their respective HTML attributes (e.g., 'href', 'target', etc.).
38
+
39
+ Example:
40
+ ```tsx
41
+ // Render with a span wrapper
42
+ <Slot name="MySlot" slotTag="span">
43
+ Inline content
44
+ </Slot>
45
+
46
+ // Render with an anchor wrapper
47
+ <Slot name="MySlot" slotTag="a" href="https://example.com" target="_blank">
48
+ Link content
49
+ </Slot>
50
+ ```
51
+
52
+ ### contentTag
53
+
54
+ The HTML tag to use for wrapping dynamically inserted content within the slot. This is separate from the slot's wrapper tag and allows you to control how dynamic content is structured. Defaults to 'div'.
55
+
56
+ Example:
57
+ ```tsx
58
+ <Slot
59
+ name="MySlot"
60
+ slotTag="article" // The outer wrapper will be an article
61
+ contentTag="section" // Dynamic content will be wrapped in sections
62
+ slot={(ctx) => {
63
+ const elem = document.createElement('div');
64
+ elem.innerHTML = 'Dynamic content';
65
+ ctx.appendChild(elem); // This will be wrapped in a section tag
66
+ }}
67
+ />
68
+ ```
69
+
35
70
  ### slot (required)
36
71
 
37
72
  - `ctx`: An object representing the context of the slot, including methods for manipulating the slot's content.
package/src/lib/slot.tsx CHANGED
@@ -7,7 +7,7 @@
7
7
  * accompanying it.
8
8
  *******************************************************************/
9
9
 
10
- import { cloneElement, ComponentChildren, RefObject, VNode } from 'preact';
10
+ import { cloneElement, ComponentChildren, RefObject, VNode, createElement } from 'preact';
11
11
  import {
12
12
  StateUpdater,
13
13
  useContext,
@@ -42,7 +42,7 @@ interface PrivateContext<T> {
42
42
  _registerMethod: (
43
43
  cb: (next: T & DefaultSlotContext<T>, state: State) => void
44
44
  ) => void;
45
- _htmlElementToVNode: (element: HTMLElement) => VNode;
45
+ _htmlElementToVNode: (element: HTMLElement, tag: keyof HTMLElementTagNameMap) => VNode;
46
46
  }
47
47
 
48
48
  interface DefaultSlotContext<T> extends PrivateContext<T> {
@@ -69,13 +69,14 @@ export type SlotMethod<P = any> = (
69
69
  ) => void;
70
70
 
71
71
  // Slot Hook
72
- export function useSlot<K, V extends HTMLDivElement>(
72
+ export function useSlot<K, V extends HTMLElement>(
73
73
  name: string,
74
74
  // @ts-ignore
75
75
  context: Context<K> = {},
76
76
  callback?: SlotProps<K>,
77
77
  children?: ComponentChildren,
78
- render?: Function
78
+ render?: Function,
79
+ contentTag: keyof HTMLElementTagNameMap = 'div'
79
80
  ): [RefObject<V>, Record<string, any>] {
80
81
  const slotsQueue = useContext(SlotQueueContext);
81
82
 
@@ -146,15 +147,17 @@ export function useSlot<K, V extends HTMLDivElement>(
146
147
  context._registerMethod = _registerMethod;
147
148
 
148
149
  const _htmlElementToVNode = useCallback((elem: HTMLElement) => {
149
- return (
150
- <div
151
- data-slot-html-element={elem.tagName.toLowerCase()}
152
- ref={(refElem) => {
150
+ return createElement(
151
+ contentTag,
152
+ {
153
+ 'data-slot-html-element': elem.tagName.toLowerCase(),
154
+ ref: (refElem: HTMLElement | null): void => {
153
155
  refElem?.appendChild(elem);
154
- }}
155
- />
156
+ }
157
+ },
158
+ null
156
159
  );
157
- }, []);
160
+ }, [contentTag]);
158
161
 
159
162
  // @ts-ignore
160
163
  context._htmlElementToVNode = _htmlElementToVNode;
@@ -351,11 +354,14 @@ export function useSlot<K, V extends HTMLDivElement>(
351
354
 
352
355
  // Slot Component
353
356
  interface SlotPropsComponent<T>
354
- extends Omit<HTMLAttributes<HTMLDivElement>, 'slot'> {
357
+ extends Omit<HTMLAttributes<HTMLElement>, 'slot'> {
355
358
  name: string;
356
359
  slot?: SlotProps<T>;
357
360
  context?: Context<T>;
358
361
  render?: (props: Record<string, any>) => VNode | VNode[];
362
+ slotTag?: keyof HTMLElementTagNameMap; // The tag for the slot wrapper itself
363
+ contentTag?: keyof HTMLElementTagNameMap; // The tag for dynamically inserted content
364
+ children?: ComponentChildren;
359
365
  }
360
366
 
361
367
  export function Slot<T>({
@@ -364,16 +370,19 @@ export function Slot<T>({
364
370
  slot,
365
371
  children,
366
372
  render,
373
+ slotTag = 'div',
374
+ contentTag = 'div',
367
375
  ...props
368
376
  }: Readonly<SlotPropsComponent<T>>) {
369
377
  const slotsQueue = useContext(SlotQueueContext);
370
378
 
371
- const [elementRef, slotProps] = useSlot<T, HTMLDivElement>(
379
+ const [elementRef, slotProps] = useSlot<T, HTMLElement>(
372
380
  name,
373
381
  context,
374
382
  slot,
375
383
  children,
376
- render
384
+ render,
385
+ contentTag
377
386
  );
378
387
 
379
388
  useMemo(() => {
@@ -388,10 +397,14 @@ export function Slot<T>({
388
397
  }
389
398
  }, [name, slotsQueue]);
390
399
 
391
- return (
392
- <div {...props} ref={elementRef} data-slot={name}>
393
- {slotProps.children}
394
- </div>
400
+ return createElement(
401
+ slotTag,
402
+ {
403
+ ...props,
404
+ ref: elementRef,
405
+ 'data-slot': name,
406
+ },
407
+ slotProps.children
395
408
  );
396
409
  }
397
410