@adobe-commerce/elsie 1.2.0 → 1.2.1
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/config/vite.mjs
CHANGED
|
@@ -274,12 +274,12 @@ export default {
|
|
|
274
274
|
|
|
275
275
|
// Normalize elsie imports to point to the correct paths
|
|
276
276
|
content = content.replace(
|
|
277
|
-
/'(.*@adobe\/elsie\/src\/)/g,
|
|
277
|
+
/'(.*@adobe-commerce\/elsie\/src\/)/g,
|
|
278
278
|
"'@dropins/tools/types/elsie/src/"
|
|
279
279
|
);
|
|
280
280
|
|
|
281
281
|
content = content.replace(
|
|
282
|
-
/'(@adobe\/elsie\/icons)'/g,
|
|
282
|
+
/'(@adobe-commerce\/elsie\/icons)'/g,
|
|
283
283
|
"'@dropins/tools/types/elsie/src/icons'"
|
|
284
284
|
);
|
|
285
285
|
|
package/package.json
CHANGED
|
@@ -432,9 +432,7 @@ export const CartItem: FunctionComponent<CartItemProps> = ({
|
|
|
432
432
|
|
|
433
433
|
{/* Footer */}
|
|
434
434
|
{footer && (
|
|
435
|
-
|
|
436
|
-
<VComponent node={footer} />
|
|
437
|
-
</div>
|
|
435
|
+
<VComponent node={footer} className={classes(['dropin-cart-item__footer'])} />
|
|
438
436
|
)}
|
|
439
437
|
</div>
|
|
440
438
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Meta, Unstyled } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Utilities/VComponent" />
|
|
4
|
+
<Unstyled>
|
|
5
|
+
|
|
6
|
+
# VComponent: A VNode wrapper for dynamic rendering
|
|
7
|
+
|
|
8
|
+
In modern Preact-based architectures, composability and flexibility are essential for building reusable UI components. `VComponent` is a utility provided by the SDK that enables rendering of virtual nodes (`VNode`) passed as props—empowering consumers to inject arbitrary content while maintaining a clean separation of concerns.
|
|
9
|
+
|
|
10
|
+
## Why use VComponent?
|
|
11
|
+
|
|
12
|
+
By default, Preact allows children to be passed as virtual nodes, enabling dynamic rendering:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
<MyComponent>
|
|
16
|
+
<h1>Hello</h1>
|
|
17
|
+
</MyComponent>
|
|
18
|
+
```
|
|
19
|
+
However, flexibility increases when we extend this pattern to named props like `header`, `footer`, or `image`. Instead of hardcoding internal markup, we delegate the responsibility of rendering to the consumer.
|
|
20
|
+
|
|
21
|
+
## Traditional approach (tightly coupled)
|
|
22
|
+
|
|
23
|
+
The standard approach to rendering a component is to pass values as props directly to the component.
|
|
24
|
+
|
|
25
|
+
**Implementation:**
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
const Card = ({ imageProps }) => {
|
|
29
|
+
return <img {...imageProps} />;
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Usage:**
|
|
34
|
+
```tsx
|
|
35
|
+
<Card imageProps={{ src: 'logo.png', alt: 'Logo' }} />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This implementation tightly couples the component to a specific HTML element (`<img>`), which limits its flexibility and reuse.
|
|
39
|
+
|
|
40
|
+
## Composable approach with VComponent
|
|
41
|
+
|
|
42
|
+
The composable approach with `VComponent` allows consumers to pass arbitrary DOM nodes through props.
|
|
43
|
+
|
|
44
|
+
**Implementation:**
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { VComponent } from '@adobe-commerce/elsie/lib';
|
|
48
|
+
|
|
49
|
+
interface Props {
|
|
50
|
+
image: VNode;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const Card = ({ image }: Props) => {
|
|
54
|
+
return <VComponent node={image} className="dropin-header-image" />;
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Usage:**
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<Card image={<img src="logo.png" alt="Logo" />} />
|
|
62
|
+
// or with a custom slot/component
|
|
63
|
+
<Card image={<Slot name="brand-image" />} />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This decouples the component from a specific element. Instead, it renders whatever VNode is passed in. Consumers now have full control over what gets displayed.
|
|
67
|
+
|
|
68
|
+
## How it works
|
|
69
|
+
|
|
70
|
+
`VComponent` is a thin wrapper around a virtual node (`VNode`). It renders the node it receives as-is, while optionally applying extra props like `className`.
|
|
71
|
+
|
|
72
|
+
This makes it ideal for rendering content passed through slots or injected from a higher-order component.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<VComponent node={header} className="my-header" />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## When to use it
|
|
79
|
+
|
|
80
|
+
Use `VComponent` when:
|
|
81
|
+
|
|
82
|
+
- You want to allow injected custom DOM nodes (icons, slots, rich content)
|
|
83
|
+
- You're designing reusable components meant to be extended or implemented by different consumers (Containers, Slots, etc.)
|
|
84
|
+
|
|
85
|
+
## Benefits
|
|
86
|
+
|
|
87
|
+
- Promotes reusability and composability
|
|
88
|
+
- Supports custom rendering logic with no assumptions
|
|
89
|
+
- Reduces internal complexity by offloading rendering decisions
|
|
90
|
+
- Ideal for BYO-UI and dynamic layout strategies
|
|
91
|
+
|
|
92
|
+
</Unstyled>
|