@adobe-commerce/elsie 1.0.0 → 1.0.1-alpha04151330
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 +1 -1
- package/src/components/CartItem/CartItem.tsx +332 -332
- package/src/docs/slots.mdx +17 -0
- package/src/lib/slot.tsx +15 -8
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { FunctionComponent, VNode } from 'preact';
|
|
11
11
|
import { HTMLAttributes, useContext } from 'preact/compat';
|
|
12
|
-
import {classes, VComponent} from '@adobe-commerce/elsie/lib';
|
|
12
|
+
import { classes, VComponent } from '@adobe-commerce/elsie/lib';
|
|
13
13
|
import {
|
|
14
14
|
Button,
|
|
15
15
|
CartItemSkeleton,
|
|
@@ -25,7 +25,7 @@ import { Trash } from '@adobe-commerce/elsie/icons';
|
|
|
25
25
|
import '@adobe-commerce/elsie/components/CartItem/CartItem.css';
|
|
26
26
|
|
|
27
27
|
export interface CartItemProps
|
|
28
|
-
|
|
28
|
+
extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'loading'> {
|
|
29
29
|
ariaLabel?: string;
|
|
30
30
|
image?: VNode;
|
|
31
31
|
title?: VNode;
|
|
@@ -54,35 +54,35 @@ export interface CartItemProps
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export const CartItem: FunctionComponent<CartItemProps> = ({
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
57
|
+
className,
|
|
58
|
+
children,
|
|
59
|
+
ariaLabel,
|
|
60
|
+
image,
|
|
61
|
+
title,
|
|
62
|
+
price,
|
|
63
|
+
taxIncluded = false,
|
|
64
|
+
taxExcluded = false,
|
|
65
|
+
total,
|
|
66
|
+
totalExcludingTax,
|
|
67
|
+
sku,
|
|
68
|
+
configurations,
|
|
69
|
+
warning,
|
|
70
|
+
alert,
|
|
71
|
+
discount,
|
|
72
|
+
savings,
|
|
73
|
+
actions,
|
|
74
|
+
quantity,
|
|
75
|
+
description,
|
|
76
|
+
attributes,
|
|
77
|
+
footer,
|
|
78
|
+
loading = false,
|
|
79
|
+
updating = false,
|
|
80
|
+
quantityType,
|
|
81
|
+
dropdownOptions,
|
|
82
|
+
onQuantity,
|
|
83
|
+
onRemove,
|
|
84
|
+
...props
|
|
85
|
+
}) => {
|
|
86
86
|
const { locale } = useContext(UIContext);
|
|
87
87
|
|
|
88
88
|
const labels = useText({
|
|
@@ -100,368 +100,368 @@ export const CartItem: FunctionComponent<CartItemProps> = ({
|
|
|
100
100
|
if (loading) return <CartItemSkeleton />;
|
|
101
101
|
|
|
102
102
|
const quantityComponent =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
103
|
+
quantityType === 'dropdown' ? (
|
|
104
|
+
<Picker
|
|
105
|
+
className={classes(['dropin-cart-item__quantity__picker'])}
|
|
106
|
+
value={String(quantity)}
|
|
107
|
+
name="quantity"
|
|
108
|
+
aria-label={labels.quantity}
|
|
109
|
+
disabled={updating}
|
|
110
|
+
variant={'primary'}
|
|
111
|
+
options={dropdownOptions}
|
|
112
|
+
handleSelect={(event) =>
|
|
113
|
+
onQuantity?.(Number((event.target as HTMLSelectElement).value))
|
|
114
|
+
}
|
|
115
|
+
/>
|
|
116
|
+
) : (
|
|
117
|
+
<Incrementer
|
|
118
|
+
className={classes(['dropin-cart-item__quantity__incrementer'])}
|
|
119
|
+
value={quantity}
|
|
120
|
+
min={1}
|
|
121
|
+
onValue={(value) => onQuantity?.(Number(value))}
|
|
122
|
+
name="quantity"
|
|
123
|
+
aria-label={labels.quantity}
|
|
124
|
+
disabled={updating}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
127
|
|
|
128
128
|
return (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
/>
|
|
146
|
-
)}
|
|
147
|
-
<div className="dropin-cart-item__wrapper">
|
|
148
|
-
{
|
|
149
|
-
/* Image */
|
|
150
|
-
image && (
|
|
151
|
-
<VComponent
|
|
152
|
-
node={image}
|
|
153
|
-
className={classes(['dropin-cart-item__image'])}
|
|
154
|
-
/>
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
{
|
|
159
|
-
/* Title */
|
|
160
|
-
title && (
|
|
161
|
-
<VComponent
|
|
162
|
-
node={title}
|
|
163
|
-
className={classes([
|
|
164
|
-
'dropin-cart-item__title',
|
|
165
|
-
['dropin-cart-item__title--edit', !!onQuantity || !!onRemove],
|
|
166
|
-
])}
|
|
167
|
-
/>
|
|
168
|
-
)
|
|
129
|
+
<div
|
|
130
|
+
{...props}
|
|
131
|
+
className={classes([
|
|
132
|
+
'dropin-cart-item',
|
|
133
|
+
['dropin-cart-item--updating', updating],
|
|
134
|
+
className,
|
|
135
|
+
])}
|
|
136
|
+
>
|
|
137
|
+
{updating && (
|
|
138
|
+
<ProgressSpinner
|
|
139
|
+
className={classes(['dropin-cart-item__spinner'])}
|
|
140
|
+
ariaLabel={
|
|
141
|
+
ariaLabel
|
|
142
|
+
? labels.updating?.replace('{product}', ariaLabel)
|
|
143
|
+
: labels.updatingDefault
|
|
169
144
|
}
|
|
145
|
+
/>
|
|
146
|
+
)}
|
|
147
|
+
<div className="dropin-cart-item__wrapper">
|
|
148
|
+
{
|
|
149
|
+
/* Image */
|
|
150
|
+
image && (
|
|
151
|
+
<VComponent
|
|
152
|
+
node={image}
|
|
153
|
+
className={classes(['dropin-cart-item__image'])}
|
|
154
|
+
/>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
{
|
|
159
|
+
/* Title */
|
|
160
|
+
title && (
|
|
161
|
+
<VComponent
|
|
162
|
+
node={title}
|
|
163
|
+
className={classes([
|
|
164
|
+
'dropin-cart-item__title',
|
|
165
|
+
['dropin-cart-item__title--edit', !!onQuantity || !!onRemove],
|
|
166
|
+
])}
|
|
167
|
+
/>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
{
|
|
172
|
+
/* Description */
|
|
173
|
+
description && (
|
|
174
|
+
<VComponent
|
|
175
|
+
node={description}
|
|
176
|
+
className={classes(['dropin-cart-item__description'])}
|
|
177
|
+
/>
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
{
|
|
182
|
+
/* SKU */
|
|
183
|
+
sku && (
|
|
184
|
+
<VComponent
|
|
185
|
+
node={sku}
|
|
186
|
+
className={classes(['dropin-cart-item__sku'])}
|
|
187
|
+
/>
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
<div className={classes(['dropin-cart-item__savings__wrapper'])}>
|
|
191
|
+
{/* Discount amount */}
|
|
192
|
+
{discount && (
|
|
193
|
+
<VComponent
|
|
194
|
+
node={discount}
|
|
195
|
+
className={classes([
|
|
196
|
+
'dropin-cart-item__discount',
|
|
197
|
+
'dropin-cart-item__discount__large-screen',
|
|
198
|
+
])}
|
|
199
|
+
/>
|
|
200
|
+
)}
|
|
170
201
|
|
|
171
|
-
{
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
179
|
-
|
|
202
|
+
{/* Savings amount */}
|
|
203
|
+
{savings && (
|
|
204
|
+
<VComponent
|
|
205
|
+
node={savings}
|
|
206
|
+
className={classes([
|
|
207
|
+
'dropin-cart-item__savings',
|
|
208
|
+
'dropin-cart-item__savings__large-screen',
|
|
209
|
+
])}
|
|
210
|
+
/>
|
|
211
|
+
)}
|
|
212
|
+
</div>
|
|
180
213
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
/>
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
|
-
<div className={classes(['dropin-cart-item__savings__wrapper'])}>
|
|
191
|
-
{/* Discount amount */}
|
|
192
|
-
{discount && (
|
|
193
|
-
<VComponent
|
|
194
|
-
node={discount}
|
|
195
|
-
className={classes([
|
|
196
|
-
'dropin-cart-item__discount',
|
|
197
|
-
'dropin-cart-item__discount__large-screen',
|
|
198
|
-
])}
|
|
199
|
-
/>
|
|
200
|
-
)}
|
|
214
|
+
{/* Product Attributes */}
|
|
215
|
+
{attributes && (
|
|
216
|
+
<div className={classes(['dropin-cart-item__attributes'])}>
|
|
217
|
+
<VComponent node={attributes} />
|
|
218
|
+
</div>
|
|
219
|
+
)}
|
|
201
220
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
221
|
+
{
|
|
222
|
+
/* Configurations */
|
|
223
|
+
configurations && (
|
|
224
|
+
<ul className={classes(['dropin-cart-item__configurations'])}>
|
|
225
|
+
{Object.entries(configurations).map(([key, value]) => (
|
|
226
|
+
<li
|
|
227
|
+
key={key}
|
|
228
|
+
className={classes([
|
|
229
|
+
'dropin-cart-item__configurations__item',
|
|
230
|
+
])}
|
|
231
|
+
>
|
|
232
|
+
{key}:{' '}
|
|
233
|
+
<strong
|
|
206
234
|
className={classes([
|
|
207
|
-
'dropin-cart-
|
|
208
|
-
'dropin-cart-item__savings__large-screen',
|
|
235
|
+
'dropin-cart-item__configurations__item__value',
|
|
209
236
|
])}
|
|
210
|
-
/>
|
|
211
|
-
)}
|
|
212
|
-
</div>
|
|
213
|
-
|
|
214
|
-
{/* Product Attributes */}
|
|
215
|
-
{attributes && (
|
|
216
|
-
<div className={classes(['dropin-cart-item__attributes'])}>
|
|
217
|
-
<VComponent node={attributes} />
|
|
218
|
-
</div>
|
|
219
|
-
)}
|
|
220
|
-
|
|
221
|
-
{
|
|
222
|
-
/* Configurations */
|
|
223
|
-
configurations && (
|
|
224
|
-
<ul className={classes(['dropin-cart-item__configurations'])}>
|
|
225
|
-
{Object.entries(configurations).map(([key, value]) => (
|
|
226
|
-
<li
|
|
227
|
-
key={key}
|
|
228
|
-
className={classes([
|
|
229
|
-
'dropin-cart-item__configurations__item',
|
|
230
|
-
])}
|
|
231
|
-
>
|
|
232
|
-
{key}:{' '}
|
|
233
|
-
<strong
|
|
234
|
-
className={classes([
|
|
235
|
-
'dropin-cart-item__configurations__item__value',
|
|
236
|
-
])}
|
|
237
|
-
>
|
|
238
|
-
{value}
|
|
239
|
-
</strong>
|
|
240
|
-
</li>
|
|
241
|
-
))}
|
|
242
|
-
</ul>
|
|
243
|
-
)
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
{
|
|
247
|
-
/* Price */
|
|
248
|
-
price && (
|
|
249
|
-
<span
|
|
250
|
-
className={classes(['dropin-cart-item__price'])}
|
|
251
|
-
aria-label={labels.pricePerItem}
|
|
252
237
|
>
|
|
238
|
+
{value}
|
|
239
|
+
</strong>
|
|
240
|
+
</li>
|
|
241
|
+
))}
|
|
242
|
+
</ul>
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
{
|
|
247
|
+
/* Price */
|
|
248
|
+
price && (
|
|
249
|
+
<span
|
|
250
|
+
className={classes(['dropin-cart-item__price'])}
|
|
251
|
+
aria-label={labels.pricePerItem}
|
|
252
|
+
>
|
|
253
253
|
{quantity && !onQuantity && (
|
|
254
|
-
|
|
254
|
+
<>
|
|
255
255
|
<span
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
className="dropin-cart-item__price__quantity"
|
|
257
|
+
aria-hidden={true}
|
|
258
258
|
>
|
|
259
259
|
{quantity.toLocaleString(locale)} x{' '}
|
|
260
260
|
</span>
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
<div className="dropin-cart-item__sr-only">
|
|
263
|
+
{labels.quantity}: {quantity?.toLocaleString(locale)};
|
|
264
|
+
</div>
|
|
265
|
+
</>
|
|
266
266
|
)}
|
|
267
267
|
|
|
268
|
-
|
|
268
|
+
<VComponent node={price} role="text" />
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
270
|
+
{quantity && quantity > 1 && (
|
|
271
|
+
<>
|
|
272
|
+
|
|
273
|
+
{labels.each}
|
|
274
|
+
</>
|
|
275
|
+
)}
|
|
276
276
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
{taxIncluded && (
|
|
278
|
+
<span
|
|
279
|
+
data-testid="tax-message"
|
|
280
|
+
className="dropin-cart-item__price-tax-message"
|
|
281
|
+
>
|
|
282
282
|
|
|
283
|
-
|
|
283
|
+
{labels.taxIncluded}
|
|
284
284
|
</span>
|
|
285
|
-
|
|
285
|
+
)}
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
287
|
+
{taxExcluded && (
|
|
288
|
+
<span
|
|
289
|
+
data-testid="tax-message"
|
|
290
|
+
className="dropin-cart-item__price-tax-message"
|
|
291
|
+
>
|
|
292
292
|
|
|
293
|
-
|
|
293
|
+
{labels.taxExcluded}
|
|
294
294
|
</span>
|
|
295
|
-
|
|
295
|
+
)}
|
|
296
296
|
</span>
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
300
|
+
{/* Quantity */}
|
|
301
|
+
<div
|
|
302
|
+
className={classes([
|
|
303
|
+
'dropin-cart-item__quantity',
|
|
304
|
+
['dropin-cart-item__quantity--edit', !!onQuantity],
|
|
305
|
+
])}
|
|
306
|
+
>
|
|
307
|
+
{onQuantity
|
|
308
|
+
? quantityComponent
|
|
309
|
+
: quantity && (
|
|
310
310
|
<span
|
|
311
|
-
|
|
311
|
+
className={classes(['dropin-cart-item__quantity__value'])}
|
|
312
312
|
>
|
|
313
313
|
{labels.quantity}:{' '}
|
|
314
314
|
<strong className="dropin-cart-item__quantity__number">
|
|
315
315
|
{Number(quantity).toLocaleString(locale)}
|
|
316
316
|
</strong>
|
|
317
317
|
</span>
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
{/* Warning */}
|
|
321
|
-
{warning && (
|
|
322
|
-
<VComponent
|
|
323
|
-
node={warning}
|
|
324
|
-
className={classes([
|
|
325
|
-
'dropin-cart-item__warning',
|
|
326
|
-
'dropin-cart-item__warning--quantity',
|
|
327
|
-
])}
|
|
328
|
-
/>
|
|
329
|
-
)}
|
|
330
|
-
|
|
331
|
-
{/* Alert */}
|
|
332
|
-
{alert && (
|
|
333
|
-
<VComponent
|
|
334
|
-
node={alert}
|
|
335
|
-
className={classes([
|
|
336
|
-
'dropin-cart-item__alert',
|
|
337
|
-
'dropin-cart-item__alert--quantity',
|
|
338
|
-
])}
|
|
339
|
-
/>
|
|
340
|
-
)}
|
|
341
|
-
|
|
342
|
-
</div>
|
|
343
|
-
|
|
344
|
-
<div className={classes(['dropin-cart-item__actions'])}>
|
|
345
|
-
{/* Actions */}
|
|
346
|
-
{actions && (
|
|
347
|
-
<VComponent
|
|
348
|
-
node={actions}
|
|
349
|
-
className={classes(['dropin-cart-item__buttons'])}
|
|
350
|
-
/>
|
|
351
|
-
)}
|
|
352
|
-
</div>
|
|
318
|
+
)}
|
|
353
319
|
|
|
354
320
|
{/* Warning */}
|
|
355
321
|
{warning && (
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
322
|
+
<VComponent
|
|
323
|
+
node={warning}
|
|
324
|
+
className={classes([
|
|
325
|
+
'dropin-cart-item__warning',
|
|
326
|
+
'dropin-cart-item__warning--quantity',
|
|
327
|
+
])}
|
|
328
|
+
/>
|
|
360
329
|
)}
|
|
361
330
|
|
|
362
331
|
{/* Alert */}
|
|
363
332
|
{alert && (
|
|
333
|
+
<VComponent
|
|
334
|
+
node={alert}
|
|
335
|
+
className={classes([
|
|
336
|
+
'dropin-cart-item__alert',
|
|
337
|
+
'dropin-cart-item__alert--quantity',
|
|
338
|
+
])}
|
|
339
|
+
/>
|
|
340
|
+
)}
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
{/* Actions */}
|
|
344
|
+
{actions && (
|
|
345
|
+
<div className={classes(['dropin-cart-item__actions'])}>
|
|
346
|
+
{
|
|
364
347
|
<VComponent
|
|
365
|
-
|
|
366
|
-
|
|
348
|
+
node={actions}
|
|
349
|
+
className={classes(['dropin-cart-item__buttons'])}
|
|
367
350
|
/>
|
|
368
|
-
|
|
351
|
+
}
|
|
352
|
+
</div>
|
|
353
|
+
)}
|
|
369
354
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
<div className="dropin-cart-item__row-total__wrapper">
|
|
378
|
-
{
|
|
379
|
-
/* Total */
|
|
380
|
-
total && (
|
|
381
|
-
<div className="dropin-cart-item__row-total">
|
|
382
|
-
<VComponent node={total} role="text" />
|
|
383
|
-
</div>
|
|
384
|
-
)
|
|
385
|
-
}
|
|
355
|
+
{/* Warning */}
|
|
356
|
+
{warning && (
|
|
357
|
+
<VComponent
|
|
358
|
+
node={warning}
|
|
359
|
+
className={classes(['dropin-cart-item__warning'])}
|
|
360
|
+
/>
|
|
361
|
+
)}
|
|
386
362
|
|
|
387
|
-
|
|
388
|
-
|
|
363
|
+
{/* Alert */}
|
|
364
|
+
{alert && (
|
|
365
|
+
<VComponent
|
|
366
|
+
node={alert}
|
|
367
|
+
className={classes(['dropin-cart-item__alert'])}
|
|
368
|
+
/>
|
|
369
|
+
)}
|
|
370
|
+
|
|
371
|
+
{/* Total */}
|
|
372
|
+
<div
|
|
373
|
+
className={classes([
|
|
374
|
+
'dropin-cart-item__total',
|
|
375
|
+
['dropin-cart-item__total--edit', !!onRemove],
|
|
376
|
+
])}
|
|
377
|
+
>
|
|
378
|
+
<div className="dropin-cart-item__row-total__wrapper">
|
|
379
|
+
{
|
|
380
|
+
/* Total */
|
|
381
|
+
total && (
|
|
382
|
+
<div className="dropin-cart-item__row-total">
|
|
383
|
+
<VComponent node={total} role="text" />
|
|
384
|
+
</div>
|
|
385
|
+
)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
{taxIncluded && (
|
|
389
|
+
<div className="dropin-cart-item__total-tax-included">
|
|
389
390
|
<span
|
|
390
|
-
|
|
391
|
-
|
|
391
|
+
data-testid="tax-message"
|
|
392
|
+
className={classes(['dropin-cart-item__total-tax-message'])}
|
|
392
393
|
>
|
|
393
394
|
{labels.taxIncluded}
|
|
394
395
|
</span>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
396
|
+
</div>
|
|
397
|
+
)}
|
|
398
|
+
</div>
|
|
399
|
+
{taxExcluded && (
|
|
400
|
+
<div className="dropin-cart-item__total-tax-excluded">
|
|
400
401
|
<span
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
402
|
+
data-testid="tax-message"
|
|
403
|
+
className={classes([
|
|
404
|
+
'dropin-cart-item__total-tax-excluded-message',
|
|
405
|
+
])}
|
|
405
406
|
>
|
|
406
407
|
{totalExcludingTax && (
|
|
407
|
-
|
|
408
|
+
<VComponent node={totalExcludingTax} role="text" />
|
|
408
409
|
)}
|
|
409
410
|
|
|
410
411
|
{labels.taxExcluded}
|
|
411
412
|
</span>
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
{/* Discount amount */}
|
|
416
|
-
{discount && (
|
|
417
|
-
<VComponent
|
|
418
|
-
node={discount}
|
|
419
|
-
className={classes(['dropin-cart-item__discount'])}
|
|
420
|
-
/>
|
|
421
|
-
)}
|
|
422
|
-
|
|
423
|
-
{/* Savings amount */}
|
|
424
|
-
{savings && (
|
|
425
|
-
<VComponent
|
|
426
|
-
node={savings}
|
|
427
|
-
className={classes(['dropin-cart-item__savings'])}
|
|
428
|
-
/>
|
|
429
|
-
)}
|
|
413
|
+
</div>
|
|
414
|
+
)}
|
|
430
415
|
|
|
431
|
-
|
|
416
|
+
{/* Discount amount */}
|
|
417
|
+
{discount && (
|
|
418
|
+
<VComponent
|
|
419
|
+
node={discount}
|
|
420
|
+
className={classes(['dropin-cart-item__discount'])}
|
|
421
|
+
/>
|
|
422
|
+
)}
|
|
432
423
|
|
|
433
|
-
{/*
|
|
434
|
-
{
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
424
|
+
{/* Savings amount */}
|
|
425
|
+
{savings && (
|
|
426
|
+
<VComponent
|
|
427
|
+
node={savings}
|
|
428
|
+
className={classes(['dropin-cart-item__savings'])}
|
|
429
|
+
/>
|
|
438
430
|
)}
|
|
439
431
|
</div>
|
|
440
432
|
|
|
441
|
-
{/*
|
|
442
|
-
{
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
variant="tertiary"
|
|
447
|
-
onClick={() => onRemove?.()}
|
|
448
|
-
icon={
|
|
449
|
-
<Icon
|
|
450
|
-
data-testid="cart-item-remove-icon"
|
|
451
|
-
source={Trash}
|
|
452
|
-
size="24"
|
|
453
|
-
stroke="2"
|
|
454
|
-
viewBox="0 0 24 24"
|
|
455
|
-
aria-label={
|
|
456
|
-
ariaLabel
|
|
457
|
-
? labels.remove?.replace('{product}', ariaLabel)
|
|
458
|
-
: labels.removeDefault
|
|
459
|
-
}
|
|
460
|
-
/>
|
|
461
|
-
}
|
|
462
|
-
disabled={updating}
|
|
463
|
-
/>
|
|
433
|
+
{/* Footer */}
|
|
434
|
+
{footer && (
|
|
435
|
+
<div className={classes(['dropin-cart-item__footer'])}>
|
|
436
|
+
<VComponent node={footer} />
|
|
437
|
+
</div>
|
|
464
438
|
)}
|
|
465
439
|
</div>
|
|
440
|
+
|
|
441
|
+
{/* Remove Item */}
|
|
442
|
+
{onRemove && (
|
|
443
|
+
<Button
|
|
444
|
+
data-testid="cart-item-remove-button"
|
|
445
|
+
className={classes(['dropin-cart-item__remove'])}
|
|
446
|
+
variant="tertiary"
|
|
447
|
+
onClick={() => onRemove?.()}
|
|
448
|
+
icon={
|
|
449
|
+
<Icon
|
|
450
|
+
data-testid="cart-item-remove-icon"
|
|
451
|
+
source={Trash}
|
|
452
|
+
size="24"
|
|
453
|
+
stroke="2"
|
|
454
|
+
viewBox="0 0 24 24"
|
|
455
|
+
aria-label={
|
|
456
|
+
ariaLabel
|
|
457
|
+
? labels.remove?.replace('{product}', ariaLabel)
|
|
458
|
+
: labels.removeDefault
|
|
459
|
+
}
|
|
460
|
+
/>
|
|
461
|
+
}
|
|
462
|
+
disabled={updating}
|
|
463
|
+
/>
|
|
464
|
+
)}
|
|
465
|
+
</div>
|
|
466
466
|
);
|
|
467
467
|
};
|
package/src/docs/slots.mdx
CHANGED
|
@@ -32,6 +32,23 @@ 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
|
+
### wrapperTag
|
|
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" wrapperTag="span">
|
|
43
|
+
Inline content
|
|
44
|
+
</Slot>
|
|
45
|
+
|
|
46
|
+
// Render with an anchor wrapper
|
|
47
|
+
<Slot name="MySlot" wrapperTag="a" href="https://example.com" target="_blank">
|
|
48
|
+
Link content
|
|
49
|
+
</Slot>
|
|
50
|
+
```
|
|
51
|
+
|
|
35
52
|
### slot (required)
|
|
36
53
|
|
|
37
54
|
- `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,
|
|
@@ -69,7 +69,7 @@ export type SlotMethod<P = any> = (
|
|
|
69
69
|
) => void;
|
|
70
70
|
|
|
71
71
|
// Slot Hook
|
|
72
|
-
export function useSlot<K, V extends
|
|
72
|
+
export function useSlot<K, V extends HTMLElement>(
|
|
73
73
|
name: string,
|
|
74
74
|
// @ts-ignore
|
|
75
75
|
context: Context<K> = {},
|
|
@@ -351,11 +351,13 @@ export function useSlot<K, V extends HTMLDivElement>(
|
|
|
351
351
|
|
|
352
352
|
// Slot Component
|
|
353
353
|
interface SlotPropsComponent<T>
|
|
354
|
-
extends Omit<HTMLAttributes<
|
|
354
|
+
extends Omit<HTMLAttributes<HTMLElement>, 'slot'> {
|
|
355
355
|
name: string;
|
|
356
356
|
slot?: SlotProps<T>;
|
|
357
357
|
context?: Context<T>;
|
|
358
358
|
render?: (props: Record<string, any>) => VNode | VNode[];
|
|
359
|
+
wrapperTag?: keyof HTMLElementTagNameMap;
|
|
360
|
+
children?: ComponentChildren;
|
|
359
361
|
}
|
|
360
362
|
|
|
361
363
|
export function Slot<T>({
|
|
@@ -364,11 +366,12 @@ export function Slot<T>({
|
|
|
364
366
|
slot,
|
|
365
367
|
children,
|
|
366
368
|
render,
|
|
369
|
+
wrapperTag = 'div',
|
|
367
370
|
...props
|
|
368
371
|
}: Readonly<SlotPropsComponent<T>>) {
|
|
369
372
|
const slotsQueue = useContext(SlotQueueContext);
|
|
370
373
|
|
|
371
|
-
const [elementRef, slotProps] = useSlot<T,
|
|
374
|
+
const [elementRef, slotProps] = useSlot<T, HTMLElement>(
|
|
372
375
|
name,
|
|
373
376
|
context,
|
|
374
377
|
slot,
|
|
@@ -388,10 +391,14 @@ export function Slot<T>({
|
|
|
388
391
|
}
|
|
389
392
|
}, [name, slotsQueue]);
|
|
390
393
|
|
|
391
|
-
return (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
394
|
+
return createElement(
|
|
395
|
+
wrapperTag,
|
|
396
|
+
{
|
|
397
|
+
...props,
|
|
398
|
+
ref: elementRef,
|
|
399
|
+
'data-slot': name,
|
|
400
|
+
},
|
|
401
|
+
slotProps.children
|
|
395
402
|
);
|
|
396
403
|
}
|
|
397
404
|
|