@mostfeatured/dbi 0.2.13 → 0.2.15

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 (45) hide show
  1. package/dist/src/types/Components/HTMLComponentsV2/index.d.ts +33 -1
  2. package/dist/src/types/Components/HTMLComponentsV2/index.d.ts.map +1 -1
  3. package/dist/src/types/Components/HTMLComponentsV2/index.js +408 -82
  4. package/dist/src/types/Components/HTMLComponentsV2/index.js.map +1 -1
  5. package/dist/src/types/Components/HTMLComponentsV2/parser.d.ts +52 -0
  6. package/dist/src/types/Components/HTMLComponentsV2/parser.d.ts.map +1 -1
  7. package/dist/src/types/Components/HTMLComponentsV2/parser.js +275 -0
  8. package/dist/src/types/Components/HTMLComponentsV2/parser.js.map +1 -1
  9. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts +26 -0
  10. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts.map +1 -1
  11. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js +509 -34
  12. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js.map +1 -1
  13. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts +10 -0
  14. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts.map +1 -1
  15. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js +76 -11
  16. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js.map +1 -1
  17. package/dist/test/index.js +76 -3
  18. package/dist/test/index.js.map +1 -1
  19. package/docs/ADVANCED_FEATURES.md +4 -0
  20. package/docs/API_REFERENCE.md +4 -0
  21. package/docs/CHAT_INPUT.md +4 -0
  22. package/docs/COMPONENTS.md +4 -0
  23. package/docs/EVENTS.md +4 -0
  24. package/docs/GETTING_STARTED.md +4 -0
  25. package/docs/LOCALIZATION.md +4 -0
  26. package/docs/README.md +4 -0
  27. package/docs/SVELTE_COMPONENTS.md +162 -6
  28. package/docs/llm/ADVANCED_FEATURES.txt +521 -0
  29. package/docs/llm/API_REFERENCE.txt +659 -0
  30. package/docs/llm/CHAT_INPUT.txt +514 -0
  31. package/docs/llm/COMPONENTS.txt +595 -0
  32. package/docs/llm/EVENTS.txt +449 -0
  33. package/docs/llm/GETTING_STARTED.txt +296 -0
  34. package/docs/llm/LOCALIZATION.txt +501 -0
  35. package/docs/llm/README.txt +193 -0
  36. package/docs/llm/SVELTE_COMPONENTS.txt +566 -0
  37. package/generated/svelte-dbi.d.ts +122 -0
  38. package/package.json +1 -1
  39. package/src/types/Components/HTMLComponentsV2/index.ts +466 -94
  40. package/src/types/Components/HTMLComponentsV2/parser.ts +317 -0
  41. package/src/types/Components/HTMLComponentsV2/svelteParser.ts +567 -35
  42. package/src/types/Components/HTMLComponentsV2/svelteRenderer.ts +91 -13
  43. package/test/index.ts +76 -3
  44. package/test/product-showcase.svelte +380 -24
  45. package/llm.txt +0 -1088
@@ -6,26 +6,126 @@
6
6
  products = [],
7
7
  currentIndex = 0,
8
8
  cart = [],
9
- view = "browse", // 'browse' | 'cart' | 'details'
9
+ view = "browse", // 'browse' | 'cart' | 'details' | 'reviews'
10
10
  elapsedTime = 0,
11
+ editingProduct = null, // Product being edited in modal
12
+ reviewText = "", // Review text from modal
13
+ reviews = [], // Array of { productId, productName, rating, review, date }
14
+ selectedCategory = "all", // Category filter
15
+ sortBy = "default", // Sorting option
11
16
  } = $props();
12
17
 
18
+ // Get unique categories from products
19
+ // Note: Uses local variables for SSR template rendering
20
+ function getCategories() {
21
+ const cats = [...new Set(products.map((p) => p.category))];
22
+ return cats;
23
+ }
24
+
25
+ // Filter and sort products
26
+ // Note: Uses local variables for SSR template rendering
27
+ function getFilteredProducts() {
28
+ let filtered = products;
29
+
30
+ // Apply category filter
31
+ if (selectedCategory !== "all") {
32
+ filtered = filtered.filter((p) => p.category === selectedCategory);
33
+ }
34
+
35
+ // Apply sorting
36
+ if (sortBy === "price-low") {
37
+ filtered = [...filtered].sort((a, b) => a.price - b.price);
38
+ } else if (sortBy === "price-high") {
39
+ filtered = [...filtered].sort((a, b) => b.price - a.price);
40
+ } else if (sortBy === "name") {
41
+ filtered = [...filtered].sort((a, b) => a.name.localeCompare(b.name));
42
+ } else if (sortBy === "rating") {
43
+ filtered = [...filtered].sort((a, b) => b.rating - a.rating);
44
+ }
45
+
46
+ return filtered;
47
+ }
48
+
49
+ // Get current product from filtered list
50
+ // Note: Uses local variables for SSR template rendering
51
+ function getCurrentProduct() {
52
+ const filtered = getFilteredProducts();
53
+ if (filtered.length === 0) return null;
54
+ const idx = Math.min(currentIndex, filtered.length - 1);
55
+ return filtered[idx];
56
+ }
57
+
13
58
  // Format elapsed time using stuffs
14
59
  function formatTime(seconds) {
15
60
  return stuffs.formatSeconds(seconds);
16
61
  }
17
62
 
63
+ // Handle category selection
64
+ function onCategoryChange(ctx) {
65
+ const selected = ctx.interaction.values[0];
66
+ data.selectedCategory = selected;
67
+ data.currentIndex = 0; // Reset to first product when filter changes
68
+ ctx.interaction.deferUpdate();
69
+ }
70
+
71
+ // Handle sort selection
72
+ function onSortChange(ctx) {
73
+ const selected = ctx.interaction.values[0];
74
+ data.sortBy = selected;
75
+ data.currentIndex = 0; // Reset to first product when sort changes
76
+ ctx.interaction.deferUpdate();
77
+ }
78
+
18
79
  function nextProduct() {
19
- data.currentIndex = (currentIndex + 1) % products.length;
80
+ // Get filtered length using data context
81
+ let filtered = data.products || [];
82
+ const category = data.selectedCategory ?? "all";
83
+ if (category !== "all") {
84
+ filtered = filtered.filter((p) => p.category === category);
85
+ }
86
+ const currentIdx = data.currentIndex ?? 0;
87
+ data.currentIndex = (currentIdx + 1) % filtered.length;
20
88
  }
21
89
 
22
90
  function prevProduct() {
23
- data.currentIndex = (currentIndex - 1 + products.length) % products.length;
91
+ // Get filtered length using data context
92
+ let filtered = data.products || [];
93
+ const category = data.selectedCategory ?? "all";
94
+ if (category !== "all") {
95
+ filtered = filtered.filter((p) => p.category === category);
96
+ }
97
+ const currentIdx = data.currentIndex ?? 0;
98
+ data.currentIndex = (currentIdx - 1 + filtered.length) % filtered.length;
99
+ }
100
+
101
+ // Helper to get current product in handler context
102
+ function getProductInHandler() {
103
+ let filtered = data.products || [];
104
+ const category = data.selectedCategory ?? "all";
105
+ const sort = data.sortBy ?? "default";
106
+
107
+ if (category !== "all") {
108
+ filtered = filtered.filter((p) => p.category === category);
109
+ }
110
+ // Apply sorting
111
+ if (sort === "price-low") {
112
+ filtered = [...filtered].sort((a, b) => a.price - b.price);
113
+ } else if (sort === "price-high") {
114
+ filtered = [...filtered].sort((a, b) => b.price - a.price);
115
+ } else if (sort === "name") {
116
+ filtered = [...filtered].sort((a, b) => a.name.localeCompare(b.name));
117
+ } else if (sort === "rating") {
118
+ filtered = [...filtered].sort((a, b) => b.rating - a.rating);
119
+ }
120
+ if (filtered.length === 0) return null;
121
+ const idx = Math.min(data.currentIndex ?? 0, filtered.length - 1);
122
+ return filtered[idx];
24
123
  }
25
124
 
26
125
  function addToCart(ctx) {
27
- const product = products[currentIndex];
28
- data.cart = [...cart, product];
126
+ const product = getProductInHandler();
127
+ if (!product) return;
128
+ data.cart = [...data.cart, product];
29
129
  ctx.interaction.reply({
30
130
  content:
31
131
  "✅ Added **" +
@@ -49,6 +149,10 @@
49
149
  data.view = "details";
50
150
  }
51
151
 
152
+ function showReviews() {
153
+ data.view = "reviews";
154
+ }
155
+
52
156
  function clearCart(ctx) {
53
157
  data.cart = [];
54
158
  ctx.interaction.reply({
@@ -58,7 +162,7 @@
58
162
  }
59
163
 
60
164
  function checkout(ctx) {
61
- if (cart.length === 0) {
165
+ if (data.cart.length === 0) {
62
166
  ctx.interaction.reply({
63
167
  content: "Cart is empty!",
64
168
  flags: ["Ephemeral"],
@@ -66,20 +170,100 @@
66
170
  noRender(); // Cart boşsa UI güncellemeye gerek yok
67
171
  return;
68
172
  }
69
- const total = cart.reduce((sum, p) => sum + p.price, 0);
173
+ const total = data.cart.reduce((sum, p) => sum + p.price, 0);
70
174
  ctx.interaction.reply({
71
175
  content:
72
- "💳 **Order Placed!**\\nItems: " + cart.length + "\\nTotal: $" + total,
176
+ "💳 **Order Placed!**\\nItems: " +
177
+ data.cart.length +
178
+ "\\nTotal: $" +
179
+ total,
73
180
  flags: ["Ephemeral"],
74
181
  });
75
182
  data.cart = [];
76
183
  data.view = "browse";
77
184
  }
78
185
 
186
+ // Open the review modal for current product
187
+ async function openReviewModal(ctx) {
188
+ // Store which product we're reviewing
189
+ const product = getProductInHandler();
190
+ if (!product) {
191
+ ctx.interaction.reply({
192
+ content: "No product selected!",
193
+ flags: ["Ephemeral"],
194
+ });
195
+ noRender();
196
+ return;
197
+ }
198
+ data.editingProduct = product;
199
+
200
+ // Show the modal and await the response
201
+ const { fields, interaction } = await showModal("review-modal");
202
+
203
+ // Handle the response - rating now comes from string-select as an array
204
+ const ratingArray = fields.rating || ["5"]; // string-select returns array
205
+ const rating = Array.isArray(ratingArray) ? ratingArray[0] : ratingArray;
206
+ const review = fields.review || "";
207
+
208
+ // Add review to the reviews array (use data.reviews for current value after await)
209
+ data.reviews = [
210
+ ...data.reviews,
211
+ {
212
+ productId: currentIndex,
213
+ productName: product?.name,
214
+ rating: parseInt(rating),
215
+ review: review,
216
+ date: new Date().toLocaleDateString(),
217
+ },
218
+ ];
219
+
220
+ interaction.reply({
221
+ content: `⭐ **Review Submitted!**\n**Product:** ${product?.name}\n**Rating:** ${rating}/5\n**Review:** ${review}`,
222
+ flags: ["Ephemeral"],
223
+ });
224
+
225
+ // Clear editing state
226
+ data.editingProduct = null;
227
+ }
228
+
229
+ // Open quantity modal for adding to cart
230
+ async function openQuantityModal(ctx) {
231
+ const product = getProductInHandler();
232
+ if (!product) {
233
+ ctx.interaction.reply({
234
+ content: "No product selected!",
235
+ flags: ["Ephemeral"],
236
+ });
237
+ noRender();
238
+ return;
239
+ }
240
+ data.editingProduct = product;
241
+
242
+ // Show the modal and await the response
243
+ const { fields, interaction } = await showModal("quantity-modal");
244
+
245
+ const quantity = parseInt(fields.quantity) || 1;
246
+
247
+ // Add multiple of the same product
248
+ for (let i = 0; i < quantity; i++) {
249
+ data.cart = [...data.cart, product];
250
+ }
251
+
252
+ interaction.reply({
253
+ content: `✅ Added **${quantity}x ${product?.name}** to cart! (Cart: ${data.cart.length} items)`,
254
+ flags: ["Ephemeral"],
255
+ });
256
+
257
+ data.editingProduct = null;
258
+ }
259
+
79
260
  onMount(() => {
80
261
  data.elapsedTime = 0;
81
262
  const interval = setInterval(() => {
82
- data.elapsedTime += 1;
263
+ // Use lowPriorityUpdate to skip render if a user interaction is in progress
264
+ lowPriorityUpdate(() => {
265
+ data.elapsedTime += 1;
266
+ });
83
267
  }, 1000);
84
268
 
85
269
  return () => {
@@ -88,6 +272,7 @@
88
272
  });
89
273
  </script>
90
274
 
275
+ <!-- Main UI Components -->
91
276
  <components>
92
277
  {#if view === "browse"}
93
278
  <container accent-color="5865F2">
@@ -96,32 +281,115 @@
96
281
  <components>
97
282
  <text-display>## 🛍️ Product Showcase</text-display>
98
283
  <text-display
99
- >**{products[currentIndex]?.name}**
100
- {products[currentIndex]?.description}</text-display
284
+ >**{getCurrentProduct()?.name || "No products"}**
285
+ {getCurrentProduct()?.description || ""}</text-display
101
286
  >
102
- <text-display>💰 **\${products[currentIndex]?.price}**</text-display
287
+ <text-display
288
+ >💰 **\${getCurrentProduct()?.price || 0}**</text-display
103
289
  >
104
290
  </components>
105
- <thumbnail media={products[currentIndex]?.image}></thumbnail>
291
+ <thumbnail media={getCurrentProduct()?.image}></thumbnail>
106
292
  </section>
107
293
 
108
294
  <separator></separator>
109
295
 
296
+ <!-- Category Filter -->
297
+ <action-row>
298
+ <string-select
299
+ placeholder="🏷️ Filter by Category"
300
+ onchange={onCategoryChange}
301
+ >
302
+ <option
303
+ value="all"
304
+ description="Show all products"
305
+ default={selectedCategory === "all"}
306
+ >
307
+ 📦 All Categories
308
+ </option>
309
+ {#each getCategories() as cat}
310
+ <option
311
+ value={cat}
312
+ description="Filter by {cat}"
313
+ default={selectedCategory === cat}
314
+ >
315
+ 🏷️ {cat}
316
+ </option>
317
+ {/each}
318
+ </string-select>
319
+ </action-row>
320
+
321
+ <!-- Sort Options -->
322
+ <action-row>
323
+ <string-select placeholder="📊 Sort Products" onchange={onSortChange}>
324
+ <option
325
+ value="default"
326
+ description="Original order"
327
+ default={sortBy === "default"}
328
+ >
329
+ 📋 Default Order
330
+ </option>
331
+ <option
332
+ value="price-low"
333
+ description="Cheapest first"
334
+ default={sortBy === "price-low"}
335
+ >
336
+ 💰 Price: Low to High
337
+ </option>
338
+ <option
339
+ value="price-high"
340
+ description="Most expensive first"
341
+ default={sortBy === "price-high"}
342
+ >
343
+ 💎 Price: High to Low
344
+ </option>
345
+ <option
346
+ value="name"
347
+ description="A-Z alphabetically"
348
+ default={sortBy === "name"}
349
+ >
350
+ 🔤 Name: A-Z
351
+ </option>
352
+ <option
353
+ value="rating"
354
+ description="Best rated first"
355
+ default={sortBy === "rating"}
356
+ >
357
+ ⭐ Rating: Best First
358
+ </option>
359
+ </string-select>
360
+ </action-row>
361
+
362
+ <separator></separator>
363
+
110
364
  <text-display
111
- >📦 Product {currentIndex + 1} of {products.length} | 🛒 Cart: {cart.length}
112
- items</text-display
365
+ >📦 Product {currentIndex + 1} of {getFilteredProducts().length} | 🛒 Cart:
366
+ {cart.length}
367
+ items {selectedCategory !== "all"
368
+ ? `| 🏷️ ${selectedCategory}`
369
+ : ""}</text-display
113
370
  >
114
371
 
115
372
  <action-row>
116
373
  <button style="Secondary" onclick={prevProduct}>◀️ Prev</button>
117
374
  <button style="Secondary" onclick={nextProduct}>Next ▶️</button>
118
- <button style="Success" onclick={addToCart}>🛒 Add to Cart</button>
375
+ <button style="Success" onclick={openQuantityModal}
376
+ >🛒 Add to Cart</button
377
+ >
119
378
  <button style="Primary" onclick={showDetails}>📋 Details</button>
120
379
  <button style="Primary" onclick={showCart}
121
380
  >🛒 View Cart ({cart.length})</button
122
381
  >
123
382
  </action-row>
124
383
 
384
+ <action-row>
385
+ <button style="Secondary" onclick={openReviewModal}
386
+ >⭐ Write Review</button
387
+ >
388
+ <button style="Secondary" onclick={showReviews}
389
+ >📝 View Reviews ({reviews.length})</button
390
+ >
391
+ </action-row>
392
+
125
393
  <separator></separator>
126
394
  <text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
127
395
  </components>
@@ -164,31 +432,75 @@
164
432
  <section>
165
433
  <components>
166
434
  <text-display>## 📋 Product Details</text-display>
167
- <text-display>**{products[currentIndex]?.name}**</text-display>
435
+ <text-display>**{getCurrentProduct()?.name}**</text-display>
168
436
  </components>
169
- <thumbnail media={products[currentIndex]?.image}></thumbnail>
437
+ <thumbnail media={getCurrentProduct()?.image}></thumbnail>
170
438
  </section>
171
439
 
172
440
  <separator></separator>
173
441
 
174
442
  <text-display
175
443
  >### Description
176
- {products[currentIndex]?.description}</text-display
444
+ {getCurrentProduct()?.description}</text-display
177
445
  >
178
446
 
179
447
  <separator></separator>
180
448
 
181
449
  <text-display
182
- >### Specifications • **Category:** {products[currentIndex]?.category}
183
- • **Rating:** ⭐ {products[currentIndex]?.rating}/5 • **Stock:** {products[
184
- currentIndex
185
- ]?.stock} available • **Price:** 💰 **\${products[currentIndex]
450
+ >### Specifications • **Category:** {getCurrentProduct()?.category}
451
+ • **Rating:** ⭐ {getCurrentProduct()?.rating}/5 • **Stock:** {getCurrentProduct()
452
+ ?.stock} available • **Price:** 💰 **\${getCurrentProduct()
186
453
  ?.price}**</text-display
187
454
  >
188
455
 
189
456
  <action-row>
190
457
  <button style="Secondary" onclick={showBrowse}>◀️ Back</button>
191
- <button style="Success" onclick={addToCart}>🛒 Add to Cart</button>
458
+ <button style="Success" onclick={openQuantityModal}
459
+ >🛒 Add to Cart</button
460
+ >
461
+ <button style="Secondary" onclick={openReviewModal}
462
+ >⭐ Write Review</button
463
+ >
464
+ </action-row>
465
+
466
+ <separator></separator>
467
+ <text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
468
+ </components>
469
+ </container>
470
+ {:else if view === "reviews"}
471
+ <container accent-color="EB459E">
472
+ <components>
473
+ <text-display>## 📝 Product Reviews</text-display>
474
+
475
+ {#if reviews.length === 0}
476
+ <text-display
477
+ >*No reviews yet. Be the first to write one!*</text-display
478
+ >
479
+ {:else}
480
+ {#each reviews as r, i}
481
+ <text-display
482
+ >**{r.productName}** - {"⭐".repeat(r.rating)}{"☆".repeat(
483
+ 5 - r.rating
484
+ )} ({r.rating}/5)
485
+ {r.review ? `> ${r.review}` : ""}
486
+ *{r.date}*</text-display
487
+ >
488
+ {#if i < reviews.length - 1}
489
+ <separator></separator>
490
+ {/if}
491
+ {/each}
492
+ {/if}
493
+
494
+ <separator></separator>
495
+ <text-display>**Total Reviews:** {reviews.length}</text-display>
496
+
497
+ <action-row>
498
+ <button style="Secondary" onclick={showBrowse}
499
+ >◀️ Back to Browse</button
500
+ >
501
+ <button style="Primary" onclick={openReviewModal}
502
+ >⭐ Write Review</button
503
+ >
192
504
  </action-row>
193
505
 
194
506
  <separator></separator>
@@ -197,3 +509,47 @@
197
509
  </container>
198
510
  {/if}
199
511
  </components>
512
+
513
+ <!-- Review Modal: Now using new Label component structure with String Select -->
514
+ <components
515
+ type="modal"
516
+ id="review-modal"
517
+ title="Write a Review for {editingProduct?.name || 'Product'}"
518
+ >
519
+ <field label="Rating" description="How would you rate this product?">
520
+ <string-select id="rating" placeholder="Select a rating">
521
+ <option value="5" emoji="⭐">5 Stars - Excellent!</option>
522
+ <option value="4" emoji="⭐">4 Stars - Great</option>
523
+ <option value="3" emoji="⭐">3 Stars - Good</option>
524
+ <option value="2" emoji="⭐">2 Stars - Fair</option>
525
+ <option value="1" emoji="⭐">1 Star - Poor</option>
526
+ </string-select>
527
+ </field>
528
+ <field
529
+ label="Your Review"
530
+ description="Share your experience with this product"
531
+ >
532
+ <text-input
533
+ id="review"
534
+ placeholder="Write your detailed review here..."
535
+ style="Paragraph"
536
+ ></text-input>
537
+ </field>
538
+ </components>
539
+
540
+ <!-- Quantity Modal: Opens when user clicks "Add to Cart" -->
541
+ <components
542
+ type="modal"
543
+ id="quantity-modal"
544
+ title="Add {editingProduct?.name || 'Product'} to Cart"
545
+ >
546
+ <field label="Quantity" description="How many would you like to add?">
547
+ <text-input
548
+ id="quantity"
549
+ placeholder="Enter quantity (1-10)"
550
+ style="Short"
551
+ value="1"
552
+ required
553
+ ></text-input>
554
+ </field>
555
+ </components>