@design.estate/dees-catalog 9.3.0 → 9.4.0

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.
Files changed (29) hide show
  1. package/dist_bundle/bundle.js +1372 -2727
  2. package/dist_bundle/bundle.js.map +1 -1
  3. package/dist_ts_web/00_commitinfo_data.js +1 -1
  4. package/dist_ts_web/elements/00group-button/dees-button/dees-button.js +2 -1
  5. package/dist_ts_web/elements/00group-input/dees-input-quantityselector/dees-input-quantityselector.js +4 -2
  6. package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.d.ts +11 -9
  7. package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.d.ts +2 -2
  8. package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.js +148 -319
  9. package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.js +60 -279
  10. package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.d.ts +25 -10
  11. package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.d.ts +3 -4
  12. package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.js +229 -388
  13. package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.js +253 -813
  14. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.d.ts +2 -0
  15. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.js +150 -389
  16. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.js +67 -11
  17. package/package.json +1 -1
  18. package/readme.hints.md +26 -0
  19. package/readme.md +76 -15
  20. package/scripts/bdtheme-baseline.json +0 -2
  21. package/ts_web/00_commitinfo_data.ts +1 -1
  22. package/ts_web/elements/00group-button/dees-button/dees-button.ts +1 -0
  23. package/ts_web/elements/00group-input/dees-input-quantityselector/dees-input-quantityselector.ts +3 -1
  24. package/ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.ts +67 -332
  25. package/ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.ts +65 -322
  26. package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.ts +136 -382
  27. package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts +224 -872
  28. package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.ts +116 -421
  29. package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.ts +66 -10
@@ -1,332 +1,67 @@
1
- import { html, css, cssManager } from '@design.estate/dees-element';
2
- import '@design.estate/dees-element/demotools';
3
- import '../../00group-layout/dees-panel/dees-panel.js';
4
- import type { DeesShoppingProductcard } from '../dees-shopping-productcard/dees-shopping-productcard.js';
5
-
6
- export const demoFunc = () => html`
7
- <dees-demowrapper>
8
- <style>
9
- ${css`
10
- .demo-container {
11
- display: flex;
12
- flex-direction: column;
13
- gap: 24px;
14
- padding: 24px;
15
- max-width: 1200px;
16
- margin: 0 auto;
17
- }
18
-
19
- .product-grid {
20
- display: grid;
21
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
22
- gap: 20px;
23
- }
24
-
25
- .cart-summary {
26
- margin-top: 24px;
27
- padding: 20px;
28
- background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(215 20.2% 16.8%)')};
29
- border: 1px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(215 20.2% 21.8%)')};
30
- border-radius: 8px;
31
- }
32
-
33
- .cart-summary-title {
34
- font-size: 18px;
35
- font-weight: 600;
36
- margin-bottom: 16px;
37
- color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
38
- }
39
-
40
- .cart-item {
41
- display: flex;
42
- justify-content: space-between;
43
- align-items: center;
44
- padding: 8px 0;
45
- font-size: 14px;
46
- color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
47
- }
48
-
49
- .cart-total {
50
- display: flex;
51
- justify-content: space-between;
52
- align-items: center;
53
- padding-top: 16px;
54
- margin-top: 16px;
55
- border-top: 2px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
56
- font-size: 18px;
57
- font-weight: 600;
58
- color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
59
- }
60
-
61
- .selected-products {
62
- padding: 16px;
63
- background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(215 20.2% 16.8%)')};
64
- border-radius: 6px;
65
- font-size: 14px;
66
- color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
67
- }
68
- `}
69
- </style>
70
-
71
- <div class="demo-container">
72
- <dees-panel .title=${'Basic Product Cards'} .subtitle=${'Simple product display with various configurations'}>
73
- <div class="product-grid">
74
- <dees-shopping-productcard
75
- .productData=${{
76
- name: 'Wireless Bluetooth Headphones',
77
- category: 'Audio',
78
- description: 'Premium sound quality with active noise cancellation',
79
- price: 149.99,
80
- originalPrice: 199.99,
81
- iconName: 'lucide:headphones'
82
- }}
83
- .quantity=${1}
84
- ></dees-shopping-productcard>
85
-
86
- <dees-shopping-productcard
87
- .productData=${{
88
- name: 'Smart Watch Series 7',
89
- category: 'Wearables',
90
- description: 'Track your fitness and stay connected on the go',
91
- price: 399.00,
92
- iconName: 'lucide:watch'
93
- }}
94
- .quantity=${1}
95
- ></dees-shopping-productcard>
96
-
97
- <dees-shopping-productcard
98
- .productData=${{
99
- name: 'USB-C Hub',
100
- category: 'Accessories',
101
- price: 49.99,
102
- iconName: 'lucide:usb',
103
- inStock: false
104
- }}
105
- .quantity=${0}
106
- ></dees-shopping-productcard>
107
- </div>
108
- </dees-panel>
109
-
110
- <dees-panel .title=${'Interactive Shopping Cart'} .subtitle=${'Product cards with dynamic cart calculation'} .runAfterRender=${async (elementArg: HTMLElement) => {
111
- const products = [
112
- { id: 'laptop', element: null as DeesShoppingProductcard | null, data: { name: 'MacBook Pro 14"', category: 'Computers', description: 'M3 Pro chip with 18GB RAM', price: 1999, originalPrice: 2199, iconName: 'lucide:laptop' }},
113
- { id: 'tablet', element: null as DeesShoppingProductcard | null, data: { name: 'Tablet Air', category: 'Tablets', description: '10.9" high-resolution display', price: 599, iconName: 'lucide:tablet' }},
114
- { id: 'keyboard', element: null as DeesShoppingProductcard | null, data: { name: 'Magic Keyboard', category: 'Accessories', description: 'Wireless keyboard with Touch ID', price: 149, iconName: 'lucide:keyboard' }}
115
- ];
116
-
117
- const updateCartSummary = () => {
118
- let total = 0;
119
- const items: string[] = [];
120
-
121
- products.forEach(product => {
122
- const element = elementArg.querySelector(`#${product.id}`) as DeesShoppingProductcard;
123
- if (element && element.quantity > 0) {
124
- const subtotal = product.data.price * element.quantity;
125
- total += subtotal;
126
- items.push(`
127
- <div class="cart-item">
128
- <span>${product.data.name} (${element.quantity})</span>
129
- <span>$${subtotal.toFixed(2)}</span>
130
- </div>
131
- `);
132
- }
133
- });
134
-
135
- const summary = elementArg.querySelector('#interactive-cart-summary');
136
- if (summary) {
137
- summary.innerHTML = `
138
- ${items.join('')}
139
- ${items.length === 0 ? '<div class="cart-item" style="text-align: center; color: #999;">Your cart is empty</div>' : ''}
140
- <div class="cart-total">
141
- <span>Total</span>
142
- <span>$${total.toFixed(2)}</span>
143
- </div>
144
- `;
145
- }
146
- };
147
-
148
- // Initial update
149
- setTimeout(updateCartSummary, 100);
150
-
151
- // Set up listeners
152
- elementArg.querySelectorAll('dees-shopping-productcard').forEach(card => {
153
- card.addEventListener('quantityChange', updateCartSummary);
154
- });
155
- }}>
156
- <div class="product-grid">
157
- <dees-shopping-productcard
158
- id="laptop"
159
- .productData=${{
160
- name: 'MacBook Pro 14"',
161
- category: 'Computers',
162
- description: 'M3 Pro chip with 18GB RAM',
163
- price: 1999,
164
- originalPrice: 2199,
165
- iconName: 'lucide:laptop'
166
- }}
167
- .quantity=${1}
168
- ></dees-shopping-productcard>
169
-
170
- <dees-shopping-productcard
171
- id="tablet"
172
- .productData=${{
173
- name: 'Tablet Air',
174
- category: 'Tablets',
175
- description: '10.9" high-resolution display',
176
- price: 599,
177
- iconName: 'lucide:tablet'
178
- }}
179
- .quantity=${0}
180
- ></dees-shopping-productcard>
181
-
182
- <dees-shopping-productcard
183
- id="keyboard"
184
- .productData=${{
185
- name: 'Magic Keyboard',
186
- category: 'Accessories',
187
- description: 'Wireless keyboard with Touch ID',
188
- price: 149,
189
- iconName: 'lucide:keyboard'
190
- }}
191
- .quantity=${2}
192
- ></dees-shopping-productcard>
193
- </div>
194
-
195
- <div class="cart-summary">
196
- <h3 class="cart-summary-title">Shopping Cart</h3>
197
- <div id="interactive-cart-summary">
198
- <!-- Dynamically updated -->
199
- </div>
200
- </div>
201
- </dees-panel>
202
-
203
- <dees-panel .title=${'Selectable Product Cards'} .subtitle=${'Click cards or checkboxes to select products'}>
204
- <div class="product-grid">
205
- <dees-shopping-productcard
206
- .productData=${{
207
- name: 'Sony Alpha 7 IV',
208
- category: 'Cameras',
209
- description: 'Full-frame mirrorless camera',
210
- price: 2498,
211
- iconName: 'lucide:camera'
212
- }}
213
- .selectable=${true}
214
- .showQuantitySelector=${false}
215
- @selectionChange=${(e: CustomEvent) => {
216
- const output = document.querySelector('#selection-output');
217
- if (output) {
218
- const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
219
- const selectedProducts: string[] = [];
220
- (selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
221
- if (card.selected) {
222
- selectedProducts.push(card.productData.name);
223
- }
224
- });
225
- output.textContent = selectedProducts.length > 0
226
- ? `Selected: ${selectedProducts.join(', ')}`
227
- : 'No products selected';
228
- }
229
- }}
230
- ></dees-shopping-productcard>
231
-
232
- <dees-shopping-productcard
233
- .productData=${{
234
- name: 'DJI Mini 3 Pro',
235
- category: 'Drones',
236
- description: 'Lightweight drone with 4K camera',
237
- price: 759,
238
- iconName: 'lucide:plane'
239
- }}
240
- .selectable=${true}
241
- .showQuantitySelector=${false}
242
- @selectionChange=${(e: CustomEvent) => {
243
- const output = document.querySelector('#selection-output');
244
- if (output) {
245
- const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
246
- const selectedProducts: string[] = [];
247
- (selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
248
- if (card.selected) {
249
- selectedProducts.push(card.productData.name);
250
- }
251
- });
252
- output.textContent = selectedProducts.length > 0
253
- ? `Selected: ${selectedProducts.join(', ')}`
254
- : 'No products selected';
255
- }
256
- }}
257
- ></dees-shopping-productcard>
258
-
259
- <dees-shopping-productcard
260
- .productData=${{
261
- name: 'GoPro HERO12',
262
- category: 'Action Cameras',
263
- description: '5.3K video with HyperSmooth 6.0',
264
- price: 399,
265
- originalPrice: 449,
266
- iconName: 'lucide:video'
267
- }}
268
- .selectable=${true}
269
- .showQuantitySelector=${false}
270
- @selectionChange=${(e: CustomEvent) => {
271
- const output = document.querySelector('#selection-output');
272
- if (output) {
273
- const selectedCards = document.querySelectorAll('dees-shopping-productcard[selectable]');
274
- const selectedProducts: string[] = [];
275
- (selectedCards as NodeListOf<DeesShoppingProductcard>).forEach((card) => {
276
- if (card.selected) {
277
- selectedProducts.push(card.productData.name);
278
- }
279
- });
280
- output.textContent = selectedProducts.length > 0
281
- ? `Selected: ${selectedProducts.join(', ')}`
282
- : 'No products selected';
283
- }
284
- }}
285
- ></dees-shopping-productcard>
286
- </div>
287
-
288
- <div class="selected-products" id="selection-output" style="margin-top: 16px;">
289
- No products selected
290
- </div>
291
- </dees-panel>
292
-
293
- <dees-panel .title=${'Product Variations'} .subtitle=${'Different states and configurations'}>
294
- <div class="product-grid">
295
- <dees-shopping-productcard
296
- .productData=${{
297
- name: 'Limited Edition Sneakers',
298
- category: 'Footwear',
299
- description: 'Exclusive colorway - Only 500 pairs',
300
- price: 299,
301
- iconName: 'lucide:footprints',
302
- inStock: false,
303
- stockText: 'Sold Out'
304
- }}
305
- .quantity=${0}
306
- ></dees-shopping-productcard>
307
-
308
- <dees-shopping-productcard
309
- .productData=${{
310
- name: 'Minimalist Wallet',
311
- price: 39.99,
312
- iconName: 'lucide:wallet'
313
- }}
314
- .quantity=${1}
315
- ></dees-shopping-productcard>
316
-
317
- <dees-shopping-productcard
318
- .productData=${{
319
- name: 'Premium Coffee Beans',
320
- category: 'Food & Beverage',
321
- description: 'Single origin, medium roast',
322
- price: 18.50,
323
- iconName: 'lucide:coffee',
324
- currency: '€'
325
- }}
326
- .quantity=${2}
327
- ></dees-shopping-productcard>
328
- </div>
329
- </dees-panel>
330
- </div>
331
- </dees-demowrapper>
332
- `;
1
+ import { html, css, cssManager, customElement, state, DeesElement } from '@design.estate/dees-element';
2
+ import { themeDefaultStyles } from '../../00theme.js';
3
+ import { demoPage } from '../../../demos/templates.js';
4
+ import type { IProductData } from './dees-shopping-productcard.js';
5
+ import '../../00group-input/dees-input-multitoggle/dees-input-multitoggle.js';
6
+ import '../../00group-button/dees-button/dees-button.js';
7
+
8
+ // Small original vector product studies keep this fixture sharp and self-contained.
9
+ const illustration = (content: string) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300"><rect width="400" height="300" fill="#e8e6e1"/>${content}</svg>`)}`;
10
+ const products: IProductData[] = [
11
+ { name: 'Studio headphones', category: 'Sound', description: 'A quiet space, wherever you work.', price: 179, originalPrice: 219, iconName: 'lucide:headphones', imageUrl: illustration('<path d="M125 172v-40a75 75 0 0 1 150 0v40" fill="none" stroke="#383a3c" stroke-width="17"/><path d="M135 136v-5a65 65 0 0 1 130 0v5" fill="none" stroke="#b4b1ab" stroke-width="7"/><rect x="106" y="130" width="42" height="88" rx="20" fill="#343638"/><rect x="124" y="130" width="30" height="88" rx="15" fill="#616467"/><rect x="252" y="130" width="42" height="88" rx="20" fill="#343638"/><rect x="246" y="130" width="30" height="88" rx="15" fill="#616467"/>') },
12
+ { name: 'Everyday keyboard', category: 'Desk', description: 'Low-profile keys. A little more focus.', price: 89, iconName: 'lucide:keyboard', imageUrl: illustration('<rect x="54" y="109" width="292" height="111" rx="14" fill="#a6a4a0"/><rect x="54" y="101" width="292" height="111" rx="14" fill="#cecbc4"/>' + Array.from({ length: 3 }, (_, row) => Array.from({ length: 11 }, (_, col) => `<rect x="${67 + col * 24}" y="${112 + row * 23}" width="19" height="17" rx="4" fill="#f6f5f1"/>`).join('')).join('') + '<rect x="67" y="181" width="42" height="17" rx="4" fill="#f6f5f1"/><rect x="115" y="181" width="165" height="17" rx="4" fill="#f6f5f1"/><rect x="286" y="181" width="43" height="17" rx="4" fill="#f6f5f1"/>') },
13
+ { name: 'Pocket notebook', category: 'Ideas', description: 'For the ideas that start on paper.', price: 24, iconName: 'lucide:notebook', imageUrl: illustration('<rect x="122" y="51" width="156" height="210" rx="8" fill="#a7ada5"/><rect x="116" y="43" width="156" height="210" rx="8" fill="#737e6d"/><path d="M129 43v210" stroke="#596750" stroke-width="3"/><path d="M248 43v210" stroke="#485541" stroke-width="7"/><rect x="151" y="94" width="72" height="1" fill="#aeb6a6"/><rect x="151" y="103" width="50" height="1" fill="#aeb6a6"/><path d="M207 252v18l8-5 8 5v-18" fill="#c0b391"/>') },
14
+ { name: 'Desktop hub', category: 'Connections', description: 'One cable. Everything connected.', price: 69, inStock: false, stockText: 'Back soon', iconName: 'lucide:usb', imageUrl: illustration('<path d="M253 135h30q37 0 37-40v-8" fill="none" stroke="#53565a" stroke-width="10"/><rect x="307" y="58" width="25" height="35" rx="5" fill="#33383d"/><rect x="76" y="130" width="220" height="73" rx="19" fill="#646a71"/><rect x="76" y="118" width="220" height="67" rx="19" fill="#adb3ba"/><rect x="97" y="159" width="40" height="9" rx="3" fill="#33383d"/><rect x="151" y="159" width="40" height="9" rx="3" fill="#33383d"/><rect x="217" y="159" width="31" height="9" rx="4" fill="#33383d"/><circle cx="268" cy="163" r="3" fill="#d4dddc"/>') },
15
+ ];
16
+ const money = (value: number) => `$${value.toFixed(2)}`;
17
+
18
+ @customElement('dees-demo-simple-shop')
19
+ class DeesDemoSimpleShop extends DeesElement {
20
+ @state() private accessor mode = 'shop';
21
+ @state() private accessor quantities = products.map(() => 0);
22
+ @state() private accessor selected: number[] = [];
23
+ @state() private accessor restocked = false;
24
+ @state() private accessor result = 'Add a few essentials to your bag, or build a kit.';
25
+ private get inventory(): IProductData[] { return products.map(product => product.inStock === false && this.restocked ? { ...product, inStock: true, stockText: 'In stock' } : product); }
26
+ public static styles = [themeDefaultStyles, cssManager.defaultStyles, css`
27
+ :host { display: grid; gap: 24px; container-type: inline-size; font: 13px/1.5 var(--dees-font-family); }
28
+ .toolbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
29
+ .layout { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 24px; align-items: start; }
30
+ .products { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
31
+ .bag { position: sticky; top: 20px; display: grid; gap: 20px; padding: 24px; border-radius: var(--dees-radius-2xl); corner-shape: var(--dees-corner-shape); background: var(--dees-color-bg-primary); border: 1px solid var(--dees-color-border-subtle); }
32
+ h2 { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -.02em; }
33
+ p { margin: 0; color: var(--dees-color-text-secondary); }
34
+ .empty { display: grid; justify-items: start; gap: 12px; padding: 16px 0; color: var(--dees-color-text-secondary); }
35
+ .lines { display: grid; gap: 16px; }
36
+ .line, .total { display: flex; gap: 16px; justify-content: space-between; }
37
+ .line small { display: block; color: var(--dees-color-text-secondary); margin-top: 3px; }
38
+ .line > span, .total { font-variant-numeric: tabular-nums; }
39
+ .total { border-top: 1px solid var(--dees-color-border-subtle); padding-top: 16px; font-weight: 600; }
40
+ .kit { display: grid; gap: 12px; padding-top: 20px; border-top: 1px solid var(--dees-color-border-subtle); }
41
+ output { padding: 14px 16px; border-radius: var(--dees-radius-lg); background: var(--dees-color-bg-secondary); color: var(--dees-color-text-secondary); }
42
+ @container (max-width: 760px) { .layout { grid-template-columns: minmax(0, 1fr); } .bag { position: static; } }
43
+ @container (max-width: 500px) { .products { grid-template-columns: minmax(0, 1fr); } }
44
+ `];
45
+ public render() {
46
+ const inventory = this.inventory;
47
+ const count = this.quantities.reduce((sum, quantity) => sum + quantity, 0);
48
+ const total = this.quantities.reduce((sum, quantity, index) => sum + quantity * inventory[index].price, 0);
49
+ return html`<div class="toolbar"><dees-input-multitoggle aria-label="Shopping mode" .options=${[{ key: 'shop', label: 'Shop essentials' }, { key: 'kit', label: 'Build a kit' }]} .value=${this.mode}
50
+ @change=${(event: CustomEvent) => { this.mode = event.detail.value; }}></dees-input-multitoggle>
51
+ <dees-button type="ghost" text=${this.restocked ? 'Hub restocked' : 'Restock hub'} .disabled=${this.restocked} @clicked=${() => { this.restocked = true; this.result = 'Desktop hub is available again.'; }}></dees-button></div>
52
+ <div class="layout"><div class="products">${inventory.map((product, index) => html`<dees-shopping-productcard .productData=${product} .quantity=${this.quantities[index]}
53
+ .selectable=${this.mode === 'kit' && product.inStock !== false} .selected=${this.mode === 'kit' && this.selected.includes(index)} .showQuantitySelector=${product.inStock !== false}
54
+ @quantityChange=${(event: CustomEvent<{ quantity: number }>) => { this.quantities = this.quantities.map((value, i) => i === index ? event.detail.quantity : value); this.result = `${product.name}: ${event.detail.quantity} in your bag.`; }}
55
+ @selectionChange=${(event: CustomEvent<{ selected: boolean }>) => { this.selected = event.detail.selected ? [...this.selected, index] : this.selected.filter(i => i !== index); this.result = `${this.selected.length} essentials selected for your kit.`; }}></dees-shopping-productcard>`)}</div>
56
+ <aside class="bag" aria-label="Shopping bag"><h2>Your bag${count ? ` · ${count}` : ''}</h2>
57
+ ${count ? html`<div class="lines">${inventory.map((product, index) => this.quantities[index] ? html`<div class="line"><div>${product.name}<small>Quantity ${this.quantities[index]}</small></div><span>${money(product.price * this.quantities[index])}</span></div>` : '')}</div>` : html`<div class="empty"><dees-icon icon="lucide:shoppingBag" iconSize="28"></dees-icon><p>A few good essentials.<br>A space that feels like yours.</p></div>`}
58
+ <div class="total"><span>Subtotal</span><span>${money(total)}</span></div>
59
+ <dees-button full-width type="accent" text="Review bag" .disabled=${count === 0} @clicked=${() => { this.result = `Your sample bag has ${count} items, totaling ${money(total)}. No order has been placed.`; }}></dees-button>
60
+ ${count ? html`<dees-button type="ghost" size="sm" text="Clear bag" @clicked=${() => { this.quantities = products.map(() => 0); this.result = 'Your bag is empty.'; }}></dees-button>` : ''}
61
+ ${this.mode === 'kit' ? html`<div class="kit"><p>${this.selected.length} items selected for your kit.</p><dees-button full-width type="outline" text="Add kit to bag" .disabled=${!this.selected.length}
62
+ @clicked=${() => { this.quantities = this.quantities.map((quantity, index) => quantity + (this.selected.includes(index) ? 1 : 0)); this.result = 'One of each selected essential was added to your bag.'; }}></dees-button></div>` : ''}
63
+ </aside>
64
+ </div><output role="status">${this.result}</output>`;
65
+ }
66
+ }
67
+ export const demoFunc = () => demoPage('Good things for good work.', 'A considered set of desk essentials. Find your favorites and build a kit that works together.', html`<dees-demo-simple-shop></dees-demo-simple-shop>`);