@mostfeatured/dbi 0.2.14 → 0.2.16

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