@gengage/assistant-fe 0.2.3 → 0.2.5

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 (98) hide show
  1. package/dist/assistant-fe.css +1 -1
  2. package/dist/chat/api.d.ts.map +1 -1
  3. package/dist/chat/catalog.d.ts +2 -0
  4. package/dist/chat/catalog.d.ts.map +1 -1
  5. package/dist/chat/components/ChatDrawer.d.ts +47 -2
  6. package/dist/chat/components/ChatDrawer.d.ts.map +1 -1
  7. package/dist/chat/components/ChoicePrompter.d.ts +3 -1
  8. package/dist/chat/components/ChoicePrompter.d.ts.map +1 -1
  9. package/dist/chat/components/ComparisonTable.d.ts.map +1 -1
  10. package/dist/chat/components/GroundingReviewCard.d.ts.map +1 -1
  11. package/dist/chat/components/PanelTopBar.d.ts +1 -0
  12. package/dist/chat/components/PanelTopBar.d.ts.map +1 -1
  13. package/dist/chat/components/ProductSummaryCard.d.ts.map +1 -1
  14. package/dist/chat/components/ReviewHighlights.d.ts.map +1 -1
  15. package/dist/chat/components/renderUISpec.d.ts.map +1 -1
  16. package/dist/chat/index.d.ts +22 -0
  17. package/dist/chat/index.d.ts.map +1 -1
  18. package/dist/chat/locales/en.d.ts.map +1 -1
  19. package/dist/chat/locales/tr.d.ts.map +1 -1
  20. package/dist/chat/panel-manager.d.ts +6 -4
  21. package/dist/chat/panel-manager.d.ts.map +1 -1
  22. package/dist/chat/session-persistence.d.ts +6 -1
  23. package/dist/chat/session-persistence.d.ts.map +1 -1
  24. package/dist/chat/types.d.ts +23 -1
  25. package/dist/chat/types.d.ts.map +1 -1
  26. package/dist/chat.cjs +1 -1
  27. package/dist/chat.iife.js +29 -29
  28. package/dist/chat.iife.js.map +1 -1
  29. package/dist/chat.js +2 -2
  30. package/dist/common/action-router.d.ts.map +1 -1
  31. package/dist/common/communication-bridge.d.ts.map +1 -1
  32. package/dist/common/ga-datalayer.d.ts.map +1 -1
  33. package/dist/common/price-formatter.d.ts +1 -1
  34. package/dist/common/price-formatter.d.ts.map +1 -1
  35. package/dist/common/product-utils.d.ts.map +1 -1
  36. package/dist/common/quantity-stepper.d.ts +1 -1
  37. package/dist/common/quantity-stepper.d.ts.map +1 -1
  38. package/dist/common/skeleton.d.ts +9 -0
  39. package/dist/common/skeleton.d.ts.map +1 -0
  40. package/dist/common/widget-base.d.ts.map +1 -1
  41. package/dist/common.cjs +1 -1
  42. package/dist/common.js +5 -5
  43. package/dist/{index-Bctbyou5.cjs → index-B6xRdkMq.cjs} +2 -2
  44. package/dist/{index-Bctbyou5.cjs.map → index-B6xRdkMq.cjs.map} +1 -1
  45. package/dist/{index-BaG-fiAK.js → index-BsvmfVa1.js} +3 -3
  46. package/dist/{index-BaG-fiAK.js.map → index-BsvmfVa1.js.map} +1 -1
  47. package/dist/index-BzCc2DCm.cjs +13 -0
  48. package/dist/index-BzCc2DCm.cjs.map +1 -0
  49. package/dist/index-D5UPIXIA.js +4831 -0
  50. package/dist/index-D5UPIXIA.js.map +1 -0
  51. package/dist/index.cjs +1 -1
  52. package/dist/index.js +3 -3
  53. package/dist/native.cjs +1 -1
  54. package/dist/native.iife.js +29 -29
  55. package/dist/native.iife.js.map +1 -1
  56. package/dist/native.js +1 -1
  57. package/dist/qna/index.d.ts.map +1 -1
  58. package/dist/qna.cjs +1 -1
  59. package/dist/qna.cjs.map +1 -1
  60. package/dist/qna.css +1 -1
  61. package/dist/qna.iife.js +14 -14
  62. package/dist/qna.iife.js.map +1 -1
  63. package/dist/qna.js +57 -48
  64. package/dist/qna.js.map +1 -1
  65. package/dist/quantity-stepper-CQWgexMO.cjs +2 -0
  66. package/dist/quantity-stepper-CQWgexMO.cjs.map +1 -0
  67. package/dist/quantity-stepper-CjY_cpgJ.js +80 -0
  68. package/dist/quantity-stepper-CjY_cpgJ.js.map +1 -0
  69. package/dist/{schemas-DOxyUYVA.cjs → schemas-CNzyBhf7.cjs} +8 -8
  70. package/dist/schemas-CNzyBhf7.cjs.map +1 -0
  71. package/dist/{schemas-D1Kd4wn8.js → schemas-Fiaobs4L.js} +306 -308
  72. package/dist/schemas-Fiaobs4L.js.map +1 -0
  73. package/dist/simrel/components/GroupTabs.d.ts.map +1 -1
  74. package/dist/simrel/components/ProductCard.d.ts.map +1 -1
  75. package/dist/simrel/components/ProductGrid.d.ts.map +1 -1
  76. package/dist/simrel/index.d.ts.map +1 -1
  77. package/dist/simrel/locales/en.d.ts.map +1 -1
  78. package/dist/simrel/locales/tr.d.ts.map +1 -1
  79. package/dist/simrel/types.d.ts +6 -0
  80. package/dist/simrel/types.d.ts.map +1 -1
  81. package/dist/simrel.cjs +1 -1
  82. package/dist/simrel.cjs.map +1 -1
  83. package/dist/simrel.css +1 -1
  84. package/dist/simrel.iife.js +11 -11
  85. package/dist/simrel.iife.js.map +1 -1
  86. package/dist/simrel.js +163 -158
  87. package/dist/simrel.js.map +1 -1
  88. package/package.json +1 -1
  89. package/dist/index-BHaQLt-o.js +0 -4468
  90. package/dist/index-BHaQLt-o.js.map +0 -1
  91. package/dist/index-CO5VnxEn.cjs +0 -13
  92. package/dist/index-CO5VnxEn.cjs.map +0 -1
  93. package/dist/quantity-stepper-BKtPQUR1.js +0 -78
  94. package/dist/quantity-stepper-BKtPQUR1.js.map +0 -1
  95. package/dist/quantity-stepper-DU6va4sS.cjs +0 -2
  96. package/dist/quantity-stepper-DU6va4sS.cjs.map +0 -1
  97. package/dist/schemas-D1Kd4wn8.js.map +0 -1
  98. package/dist/schemas-DOxyUYVA.cjs.map +0 -1
@@ -1,78 +0,0 @@
1
- const f = {
2
- currencySymbol: "TL",
3
- currencyPosition: "suffix",
4
- thousandsSeparator: ".",
5
- decimalSeparator: ",",
6
- alwaysShowDecimals: !1
7
- };
8
- function x(t, d) {
9
- const c = Number(t);
10
- if (!Number.isFinite(c) || c < 0) return t;
11
- const e = { ...f, ...d }, s = c % 1 !== 0 || e.alwaysShowDecimals ? c.toFixed(2) : c.toFixed(0), i = s.indexOf("."), n = i === -1 ? s : s.slice(0, i), o = i === -1 ? void 0 : s.slice(i + 1), l = n.replace(/\B(?=(\d{3})+(?!\d))/g, e.thousandsSeparator);
12
- let r;
13
- return o !== void 0 ? r = `${l}${e.decimalSeparator}${o}` : r = l, e.currencySymbol ? e.currencyPosition === "prefix" ? `${e.currencySymbol}${r}` : `${r} ${e.currencySymbol}` : r;
14
- }
15
- function y(t) {
16
- return Number.isFinite(t) ? Math.max(0, Math.min(5, t)) : 0;
17
- }
18
- function h(t) {
19
- return Number.isFinite(t) ? Math.max(0, Math.min(100, Math.round(t))) : 0;
20
- }
21
- function C(t) {
22
- const d = y(t), c = Math.floor(d), e = d - c >= 0.5, m = 5 - c - (e ? 1 : 0), s = document.createElement("span");
23
- if (s.className = "gengage-star-rating", c > 0 && s.appendChild(document.createTextNode("★".repeat(c))), e) {
24
- const i = document.createElement("span");
25
- i.className = "gengage-star-half", i.textContent = "☆";
26
- const n = document.createElement("span");
27
- n.textContent = "★", i.appendChild(n), s.appendChild(i);
28
- }
29
- return m > 0 && s.appendChild(document.createTextNode("☆".repeat(m))), s;
30
- }
31
- function S(t) {
32
- t.addEventListener(
33
- "error",
34
- () => {
35
- t.style.display = "none";
36
- },
37
- { once: !0 }
38
- );
39
- }
40
- function E(t) {
41
- const d = t.min ?? 1, c = t.max ?? 99, e = Math.min(d, c), m = Math.max(d, c), s = Math.max(e, Math.min(m, t.initial ?? e)), i = t.compact ?? !1;
42
- let n = s;
43
- const o = document.createElement("div");
44
- o.className = `gengage-qty-stepper${i ? " gengage-qty-stepper--compact" : ""}`;
45
- const l = document.createElement("button");
46
- l.className = "gengage-qty-btn", l.type = "button", l.textContent = t.decreaseSymbol ?? "−", l.setAttribute("aria-label", t.decreaseLabel ?? "Decrease");
47
- const r = document.createElement("span");
48
- r.className = "gengage-qty-value", r.textContent = String(n), r.setAttribute("aria-live", "polite"), r.setAttribute("aria-atomic", "true");
49
- const u = document.createElement("button");
50
- u.className = "gengage-qty-btn", u.type = "button", u.textContent = t.increaseSymbol ?? "+", u.setAttribute("aria-label", t.increaseLabel ?? "Increase");
51
- const a = document.createElement("button");
52
- a.className = "gengage-qty-submit", a.type = "button", i ? (a.textContent = t.submitIcon ?? "🛒", a.title = t.label ?? "Add to Cart") : a.textContent = t.label ?? "Add to Cart";
53
- function g() {
54
- l.disabled = n <= e, u.disabled = n >= m;
55
- }
56
- return l.addEventListener("click", (p) => {
57
- p.stopPropagation(), n > e && (n--, r.textContent = String(n), g());
58
- }), u.addEventListener("click", (p) => {
59
- p.stopPropagation(), n < m && (n++, r.textContent = String(n), g());
60
- }), a.addEventListener("click", (p) => {
61
- p.stopPropagation(), t.onSubmit(n);
62
- const b = a.textContent;
63
- a.textContent = "✓", a.classList.add("gengage-qty-submit--success"), a.disabled = !0, setTimeout(() => {
64
- a.textContent = b, a.classList.remove("gengage-qty-submit--success"), a.disabled = !1;
65
- }, 1200);
66
- }), o.addEventListener("click", (p) => {
67
- p.stopPropagation();
68
- }), g(), o.appendChild(l), o.appendChild(r), o.appendChild(u), o.appendChild(a), o;
69
- }
70
- export {
71
- S as a,
72
- C as b,
73
- h as c,
74
- E as d,
75
- y as e,
76
- x as f
77
- };
78
- //# sourceMappingURL=quantity-stepper-BKtPQUR1.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"quantity-stepper-BKtPQUR1.js","sources":["../src/common/price-formatter.ts","../src/common/product-utils.ts","../src/common/quantity-stepper.ts"],"sourcesContent":["/**\n * Configurable price formatting.\n *\n * Defaults to Turkish locale (dot thousands, comma decimal, TL suffix).\n * Configure via widget config `pricing` field for any locale/currency.\n */\n\nexport interface PriceFormatConfig {\n /** Currency symbol. Default: 'TL' */\n currencySymbol?: string;\n /** Where to place the symbol. Default: 'suffix' */\n currencyPosition?: 'prefix' | 'suffix';\n /** Separator between thousands. Default: '.' (Turkish) */\n thousandsSeparator?: string;\n /** Decimal point character. Default: ',' (Turkish) */\n decimalSeparator?: string;\n /** Whether to show decimal part for whole numbers. Default: false */\n alwaysShowDecimals?: boolean;\n}\n\nconst TURKISH_DEFAULTS: Required<PriceFormatConfig> = {\n currencySymbol: 'TL',\n currencyPosition: 'suffix',\n thousandsSeparator: '.',\n decimalSeparator: ',',\n alwaysShowDecimals: false,\n};\n\n/**\n * Formats a raw numeric price string into the configured locale format.\n *\n * Examples (default Turkish):\n * \"17990\" → \"17.990 TL\"\n * \"17990.5\" → \"17.990,50 TL\"\n *\n * Examples (GBP prefix):\n * \"17990\" with { currencySymbol: '£', currencyPosition: 'prefix', thousandsSeparator: ',', decimalSeparator: '.' }\n * → \"£17,990\"\n *\n * Returns the input as-is if it's not a valid number.\n */\nexport function formatPrice(raw: string, config?: PriceFormatConfig): string {\n const num = Number(raw);\n if (!Number.isFinite(num) || num < 0) return raw;\n\n const resolved = { ...TURKISH_DEFAULTS, ...config };\n\n const hasDecimals = num % 1 !== 0;\n const fixed = hasDecimals || resolved.alwaysShowDecimals ? num.toFixed(2) : num.toFixed(0);\n const dotIdx = fixed.indexOf('.');\n const intPart = dotIdx === -1 ? fixed : fixed.slice(0, dotIdx);\n const decPart = dotIdx === -1 ? undefined : fixed.slice(dotIdx + 1);\n\n // Add thousands separators to integer part\n const withSeparators = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, resolved.thousandsSeparator);\n\n let formatted: string;\n if (decPart !== undefined) {\n formatted = `${withSeparators}${resolved.decimalSeparator}${decPart}`;\n } else {\n formatted = withSeparators;\n }\n\n if (resolved.currencySymbol) {\n if (resolved.currencyPosition === 'prefix') {\n return `${resolved.currencySymbol}${formatted}`;\n }\n return `${formatted} ${resolved.currencySymbol}`;\n }\n\n return formatted;\n}\n","/**\n * Shared product rendering utilities.\n *\n * Extracted from chat/renderUISpec and simrel/ProductCard to eliminate\n * duplication and provide consistent behavior across all widgets.\n */\n\n/** Clamp a rating value to the 0–5 range. Returns 0 for NaN/non-finite. */\nexport function clampRating(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.max(0, Math.min(5, value));\n}\n\n/** Clamp a discount percentage to the 0–100 range, rounded to integer. Returns 0 for NaN/non-finite. */\nexport function clampDiscount(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.max(0, Math.min(100, Math.round(value)));\n}\n\n/**\n * Render a star rating string with full, half, and empty stars.\n *\n * @param rating - A numeric rating (will be clamped to 0–5).\n * @param halfStars - Whether to render half-star characters. Defaults to true.\n * @returns A string like \"★★★½☆\" or \"★★★☆☆\" (without half-stars).\n */\nexport function renderStarRating(rating: number, halfStars: boolean = true): string {\n const clamped = clampRating(rating);\n if (halfStars) {\n const full = Math.floor(clamped);\n const half = clamped - full >= 0.5 ? 1 : 0;\n const empty = 5 - full - half;\n return '\\u2605'.repeat(full) + (half ? '\\u00BD' : '') + '\\u2606'.repeat(empty);\n }\n const rounded = Math.round(clamped);\n return '\\u2605'.repeat(rounded) + '\\u2606'.repeat(5 - rounded);\n}\n\n/**\n * Create a star rating DOM element with proper half-filled star rendering.\n *\n * Uses a CSS-clipped full star overlaid on an empty star for the half-star,\n * giving a visually accurate half-filled appearance instead of the \"½\" character.\n *\n * @param rating - A numeric rating (will be clamped to 0–5).\n * @returns An HTMLSpanElement containing the star icons.\n */\nexport function createStarRatingElement(rating: number): HTMLSpanElement {\n const clamped = clampRating(rating);\n const full = Math.floor(clamped);\n const hasHalf = clamped - full >= 0.5;\n const empty = 5 - full - (hasHalf ? 1 : 0);\n\n const container = document.createElement('span');\n container.className = 'gengage-star-rating';\n\n if (full > 0) {\n container.appendChild(document.createTextNode('\\u2605'.repeat(full)));\n }\n\n if (hasHalf) {\n const halfStar = document.createElement('span');\n halfStar.className = 'gengage-star-half';\n halfStar.textContent = '\\u2606';\n const filled = document.createElement('span');\n filled.textContent = '\\u2605';\n halfStar.appendChild(filled);\n container.appendChild(halfStar);\n }\n\n if (empty > 0) {\n container.appendChild(document.createTextNode('\\u2606'.repeat(empty)));\n }\n\n return container;\n}\n\n/**\n * Attach a one-time error handler that hides the image on load failure.\n *\n * Works with any HTMLImageElement. Hides the element by setting\n * `display: none` so layout doesn't break from broken images.\n */\nexport function addImageErrorHandler(img: HTMLImageElement): void {\n img.addEventListener(\n 'error',\n () => {\n img.style.display = 'none';\n },\n { once: true },\n );\n}\n","export interface QuantityStepperOptions {\n min?: number | undefined;\n max?: number | undefined;\n initial?: number | undefined;\n label?: string | undefined;\n compact?: boolean | undefined;\n decreaseLabel?: string | undefined;\n increaseLabel?: string | undefined;\n /** Symbol for decrease button (default: '\\u2212' minus sign). */\n decreaseSymbol?: string | undefined;\n /** Symbol for increase button (default: '+'). */\n increaseSymbol?: string | undefined;\n /** Icon/text for compact mode submit button (default: shopping cart emoji). */\n submitIcon?: string | undefined;\n onSubmit: (quantity: number) => void;\n}\n\n/**\n * Creates a quantity stepper with [−] [value] [+] and a submit button.\n * Compact mode renders a cart icon button; full mode renders a labeled button.\n */\nexport function createQuantityStepper(options: QuantityStepperOptions): HTMLElement {\n const rawMin = options.min ?? 1;\n const rawMax = options.max ?? 99;\n // Ensure min <= max; swap if caller provided inverted range\n const min = Math.min(rawMin, rawMax);\n const max = Math.max(rawMin, rawMax);\n const initial = Math.max(min, Math.min(max, options.initial ?? min));\n const compact = options.compact ?? false;\n\n let quantity = initial;\n\n const container = document.createElement('div');\n container.className = `gengage-qty-stepper${compact ? ' gengage-qty-stepper--compact' : ''}`;\n\n const decBtn = document.createElement('button');\n decBtn.className = 'gengage-qty-btn';\n decBtn.type = 'button';\n decBtn.textContent = options.decreaseSymbol ?? '\\u2212'; // minus sign\n decBtn.setAttribute('aria-label', options.decreaseLabel ?? 'Decrease');\n\n const valueEl = document.createElement('span');\n valueEl.className = 'gengage-qty-value';\n valueEl.textContent = String(quantity);\n valueEl.setAttribute('aria-live', 'polite');\n valueEl.setAttribute('aria-atomic', 'true');\n\n const incBtn = document.createElement('button');\n incBtn.className = 'gengage-qty-btn';\n incBtn.type = 'button';\n incBtn.textContent = options.increaseSymbol ?? '+';\n incBtn.setAttribute('aria-label', options.increaseLabel ?? 'Increase');\n\n const submitBtn = document.createElement('button');\n submitBtn.className = 'gengage-qty-submit';\n submitBtn.type = 'button';\n\n if (compact) {\n submitBtn.textContent = options.submitIcon ?? '\\uD83D\\uDED2'; // shopping cart emoji\n submitBtn.title = options.label ?? 'Add to Cart';\n } else {\n submitBtn.textContent = options.label ?? 'Add to Cart';\n }\n\n function updateButtons(): void {\n decBtn.disabled = quantity <= min;\n incBtn.disabled = quantity >= max;\n }\n\n decBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n if (quantity > min) {\n quantity--;\n valueEl.textContent = String(quantity);\n updateButtons();\n }\n });\n\n incBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n if (quantity < max) {\n quantity++;\n valueEl.textContent = String(quantity);\n updateButtons();\n }\n });\n\n submitBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n options.onSubmit(quantity);\n // Brief visual feedback: show checkmark then revert\n const original = submitBtn.textContent;\n submitBtn.textContent = '\\u2713'; // checkmark\n submitBtn.classList.add('gengage-qty-submit--success');\n submitBtn.disabled = true;\n setTimeout(() => {\n submitBtn.textContent = original;\n submitBtn.classList.remove('gengage-qty-submit--success');\n submitBtn.disabled = false;\n }, 1200);\n });\n\n // Prevent card click when interacting with stepper\n container.addEventListener('click', (e) => {\n e.stopPropagation();\n });\n\n updateButtons();\n\n container.appendChild(decBtn);\n container.appendChild(valueEl);\n container.appendChild(incBtn);\n container.appendChild(submitBtn);\n\n return container;\n}\n"],"names":["TURKISH_DEFAULTS","formatPrice","raw","config","num","resolved","fixed","dotIdx","intPart","decPart","withSeparators","formatted","clampRating","value","clampDiscount","createStarRatingElement","rating","clamped","full","hasHalf","empty","container","halfStar","filled","addImageErrorHandler","img","createQuantityStepper","options","rawMin","rawMax","min","max","initial","compact","quantity","decBtn","valueEl","incBtn","submitBtn","updateButtons","e","original"],"mappings":"AAoBA,MAAMA,IAAgD;AAAA,EACpD,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,oBAAoB;AACtB;AAeO,SAASC,EAAYC,GAAaC,GAAoC;AAC3E,QAAMC,IAAM,OAAOF,CAAG;AACtB,MAAI,CAAC,OAAO,SAASE,CAAG,KAAKA,IAAM,EAAG,QAAOF;AAE7C,QAAMG,IAAW,EAAE,GAAGL,GAAkB,GAAGG,EAAA,GAGrCG,IADcF,IAAM,MAAM,KACHC,EAAS,qBAAqBD,EAAI,QAAQ,CAAC,IAAIA,EAAI,QAAQ,CAAC,GACnFG,IAASD,EAAM,QAAQ,GAAG,GAC1BE,IAAUD,MAAW,KAAKD,IAAQA,EAAM,MAAM,GAAGC,CAAM,GACvDE,IAAUF,MAAW,KAAK,SAAYD,EAAM,MAAMC,IAAS,CAAC,GAG5DG,IAAiBF,EAAQ,QAAQ,yBAAyBH,EAAS,kBAAkB;AAE3F,MAAIM;AAOJ,SANIF,MAAY,SACdE,IAAY,GAAGD,CAAc,GAAGL,EAAS,gBAAgB,GAAGI,CAAO,KAEnEE,IAAYD,GAGVL,EAAS,iBACPA,EAAS,qBAAqB,WACzB,GAAGA,EAAS,cAAc,GAAGM,CAAS,KAExC,GAAGA,CAAS,IAAIN,EAAS,cAAc,KAGzCM;AACT;AC/DO,SAASC,EAAYC,GAAuB;AACjD,SAAK,OAAO,SAASA,CAAK,IACnB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGA,CAAK,CAAC,IADD;AAEtC;AAGO,SAASC,EAAcD,GAAuB;AACnD,SAAK,OAAO,SAASA,CAAK,IACnB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAMA,CAAK,CAAC,CAAC,IADf;AAEtC;AA8BO,SAASE,EAAwBC,GAAiC;AACvE,QAAMC,IAAUL,EAAYI,CAAM,GAC5BE,IAAO,KAAK,MAAMD,CAAO,GACzBE,IAAUF,IAAUC,KAAQ,KAC5BE,IAAQ,IAAIF,KAAQC,IAAU,IAAI,IAElCE,IAAY,SAAS,cAAc,MAAM;AAO/C,MANAA,EAAU,YAAY,uBAElBH,IAAO,KACTG,EAAU,YAAY,SAAS,eAAe,IAAS,OAAOH,CAAI,CAAC,CAAC,GAGlEC,GAAS;AACX,UAAMG,IAAW,SAAS,cAAc,MAAM;AAC9C,IAAAA,EAAS,YAAY,qBACrBA,EAAS,cAAc;AACvB,UAAMC,IAAS,SAAS,cAAc,MAAM;AAC5C,IAAAA,EAAO,cAAc,KACrBD,EAAS,YAAYC,CAAM,GAC3BF,EAAU,YAAYC,CAAQ;AAAA,EAChC;AAEA,SAAIF,IAAQ,KACVC,EAAU,YAAY,SAAS,eAAe,IAAS,OAAOD,CAAK,CAAC,CAAC,GAGhEC;AACT;AAQO,SAASG,EAAqBC,GAA6B;AAChE,EAAAA,EAAI;AAAA,IACF;AAAA,IACA,MAAM;AACJ,MAAAA,EAAI,MAAM,UAAU;AAAA,IACtB;AAAA,IACA,EAAE,MAAM,GAAA;AAAA,EAAK;AAEjB;ACtEO,SAASC,EAAsBC,GAA8C;AAClF,QAAMC,IAASD,EAAQ,OAAO,GACxBE,IAASF,EAAQ,OAAO,IAExBG,IAAM,KAAK,IAAIF,GAAQC,CAAM,GAC7BE,IAAM,KAAK,IAAIH,GAAQC,CAAM,GAC7BG,IAAU,KAAK,IAAIF,GAAK,KAAK,IAAIC,GAAKJ,EAAQ,WAAWG,CAAG,CAAC,GAC7DG,IAAUN,EAAQ,WAAW;AAEnC,MAAIO,IAAWF;AAEf,QAAMX,IAAY,SAAS,cAAc,KAAK;AAC9C,EAAAA,EAAU,YAAY,sBAAsBY,IAAU,kCAAkC,EAAE;AAE1F,QAAME,IAAS,SAAS,cAAc,QAAQ;AAC9C,EAAAA,EAAO,YAAY,mBACnBA,EAAO,OAAO,UACdA,EAAO,cAAcR,EAAQ,kBAAkB,KAC/CQ,EAAO,aAAa,cAAcR,EAAQ,iBAAiB,UAAU;AAErE,QAAMS,IAAU,SAAS,cAAc,MAAM;AAC7C,EAAAA,EAAQ,YAAY,qBACpBA,EAAQ,cAAc,OAAOF,CAAQ,GACrCE,EAAQ,aAAa,aAAa,QAAQ,GAC1CA,EAAQ,aAAa,eAAe,MAAM;AAE1C,QAAMC,IAAS,SAAS,cAAc,QAAQ;AAC9C,EAAAA,EAAO,YAAY,mBACnBA,EAAO,OAAO,UACdA,EAAO,cAAcV,EAAQ,kBAAkB,KAC/CU,EAAO,aAAa,cAAcV,EAAQ,iBAAiB,UAAU;AAErE,QAAMW,IAAY,SAAS,cAAc,QAAQ;AACjD,EAAAA,EAAU,YAAY,sBACtBA,EAAU,OAAO,UAEbL,KACFK,EAAU,cAAcX,EAAQ,cAAc,MAC9CW,EAAU,QAAQX,EAAQ,SAAS,iBAEnCW,EAAU,cAAcX,EAAQ,SAAS;AAG3C,WAASY,IAAsB;AAC7B,IAAAJ,EAAO,WAAWD,KAAYJ,GAC9BO,EAAO,WAAWH,KAAYH;AAAA,EAChC;AAEA,SAAAI,EAAO,iBAAiB,SAAS,CAACK,MAAM;AACtC,IAAAA,EAAE,gBAAA,GACEN,IAAWJ,MACbI,KACAE,EAAQ,cAAc,OAAOF,CAAQ,GACrCK,EAAA;AAAA,EAEJ,CAAC,GAEDF,EAAO,iBAAiB,SAAS,CAACG,MAAM;AACtC,IAAAA,EAAE,gBAAA,GACEN,IAAWH,MACbG,KACAE,EAAQ,cAAc,OAAOF,CAAQ,GACrCK,EAAA;AAAA,EAEJ,CAAC,GAEDD,EAAU,iBAAiB,SAAS,CAACE,MAAM;AACzC,IAAAA,EAAE,gBAAA,GACFb,EAAQ,SAASO,CAAQ;AAEzB,UAAMO,IAAWH,EAAU;AAC3B,IAAAA,EAAU,cAAc,KACxBA,EAAU,UAAU,IAAI,6BAA6B,GACrDA,EAAU,WAAW,IACrB,WAAW,MAAM;AACf,MAAAA,EAAU,cAAcG,GACxBH,EAAU,UAAU,OAAO,6BAA6B,GACxDA,EAAU,WAAW;AAAA,IACvB,GAAG,IAAI;AAAA,EACT,CAAC,GAGDjB,EAAU,iBAAiB,SAAS,CAACmB,MAAM;AACzC,IAAAA,EAAE,gBAAA;AAAA,EACJ,CAAC,GAEDD,EAAA,GAEAlB,EAAU,YAAYc,CAAM,GAC5Bd,EAAU,YAAYe,CAAO,GAC7Bf,EAAU,YAAYgB,CAAM,GAC5BhB,EAAU,YAAYiB,CAAS,GAExBjB;AACT;"}
@@ -1,2 +0,0 @@
1
- "use strict";const y={currencySymbol:"TL",currencyPosition:"suffix",thousandsSeparator:".",decimalSeparator:",",alwaysShowDecimals:!1};function h(t,d){const r=Number(t);if(!Number.isFinite(r)||r<0)return t;const e={...y,...d},i=r%1!==0||e.alwaysShowDecimals?r.toFixed(2):r.toFixed(0),s=i.indexOf("."),n=s===-1?i:i.slice(0,s),o=s===-1?void 0:i.slice(s+1),l=n.replace(/\B(?=(\d{3})+(?!\d))/g,e.thousandsSeparator);let c;return o!==void 0?c=`${l}${e.decimalSeparator}${o}`:c=l,e.currencySymbol?e.currencyPosition==="prefix"?`${e.currencySymbol}${c}`:`${c} ${e.currencySymbol}`:c}function b(t){return Number.isFinite(t)?Math.max(0,Math.min(5,t)):0}function x(t){return Number.isFinite(t)?Math.max(0,Math.min(100,Math.round(t))):0}function S(t){const d=b(t),r=Math.floor(d),e=d-r>=.5,m=5-r-(e?1:0),i=document.createElement("span");if(i.className="gengage-star-rating",r>0&&i.appendChild(document.createTextNode("★".repeat(r))),e){const s=document.createElement("span");s.className="gengage-star-half",s.textContent="☆";const n=document.createElement("span");n.textContent="★",s.appendChild(n),i.appendChild(s)}return m>0&&i.appendChild(document.createTextNode("☆".repeat(m))),i}function C(t){t.addEventListener("error",()=>{t.style.display="none"},{once:!0})}function E(t){const d=t.min??1,r=t.max??99,e=Math.min(d,r),m=Math.max(d,r),i=Math.max(e,Math.min(m,t.initial??e)),s=t.compact??!1;let n=i;const o=document.createElement("div");o.className=`gengage-qty-stepper${s?" gengage-qty-stepper--compact":""}`;const l=document.createElement("button");l.className="gengage-qty-btn",l.type="button",l.textContent=t.decreaseSymbol??"−",l.setAttribute("aria-label",t.decreaseLabel??"Decrease");const c=document.createElement("span");c.className="gengage-qty-value",c.textContent=String(n),c.setAttribute("aria-live","polite"),c.setAttribute("aria-atomic","true");const u=document.createElement("button");u.className="gengage-qty-btn",u.type="button",u.textContent=t.increaseSymbol??"+",u.setAttribute("aria-label",t.increaseLabel??"Increase");const a=document.createElement("button");a.className="gengage-qty-submit",a.type="button",s?(a.textContent=t.submitIcon??"🛒",a.title=t.label??"Add to Cart"):a.textContent=t.label??"Add to Cart";function g(){l.disabled=n<=e,u.disabled=n>=m}return l.addEventListener("click",p=>{p.stopPropagation(),n>e&&(n--,c.textContent=String(n),g())}),u.addEventListener("click",p=>{p.stopPropagation(),n<m&&(n++,c.textContent=String(n),g())}),a.addEventListener("click",p=>{p.stopPropagation(),t.onSubmit(n);const f=a.textContent;a.textContent="✓",a.classList.add("gengage-qty-submit--success"),a.disabled=!0,setTimeout(()=>{a.textContent=f,a.classList.remove("gengage-qty-submit--success"),a.disabled=!1},1200)}),o.addEventListener("click",p=>{p.stopPropagation()}),g(),o.appendChild(l),o.appendChild(c),o.appendChild(u),o.appendChild(a),o}exports.addImageErrorHandler=C;exports.clampDiscount=x;exports.clampRating=b;exports.createQuantityStepper=E;exports.createStarRatingElement=S;exports.formatPrice=h;
2
- //# sourceMappingURL=quantity-stepper-DU6va4sS.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"quantity-stepper-DU6va4sS.cjs","sources":["../src/common/price-formatter.ts","../src/common/product-utils.ts","../src/common/quantity-stepper.ts"],"sourcesContent":["/**\n * Configurable price formatting.\n *\n * Defaults to Turkish locale (dot thousands, comma decimal, TL suffix).\n * Configure via widget config `pricing` field for any locale/currency.\n */\n\nexport interface PriceFormatConfig {\n /** Currency symbol. Default: 'TL' */\n currencySymbol?: string;\n /** Where to place the symbol. Default: 'suffix' */\n currencyPosition?: 'prefix' | 'suffix';\n /** Separator between thousands. Default: '.' (Turkish) */\n thousandsSeparator?: string;\n /** Decimal point character. Default: ',' (Turkish) */\n decimalSeparator?: string;\n /** Whether to show decimal part for whole numbers. Default: false */\n alwaysShowDecimals?: boolean;\n}\n\nconst TURKISH_DEFAULTS: Required<PriceFormatConfig> = {\n currencySymbol: 'TL',\n currencyPosition: 'suffix',\n thousandsSeparator: '.',\n decimalSeparator: ',',\n alwaysShowDecimals: false,\n};\n\n/**\n * Formats a raw numeric price string into the configured locale format.\n *\n * Examples (default Turkish):\n * \"17990\" → \"17.990 TL\"\n * \"17990.5\" → \"17.990,50 TL\"\n *\n * Examples (GBP prefix):\n * \"17990\" with { currencySymbol: '£', currencyPosition: 'prefix', thousandsSeparator: ',', decimalSeparator: '.' }\n * → \"£17,990\"\n *\n * Returns the input as-is if it's not a valid number.\n */\nexport function formatPrice(raw: string, config?: PriceFormatConfig): string {\n const num = Number(raw);\n if (!Number.isFinite(num) || num < 0) return raw;\n\n const resolved = { ...TURKISH_DEFAULTS, ...config };\n\n const hasDecimals = num % 1 !== 0;\n const fixed = hasDecimals || resolved.alwaysShowDecimals ? num.toFixed(2) : num.toFixed(0);\n const dotIdx = fixed.indexOf('.');\n const intPart = dotIdx === -1 ? fixed : fixed.slice(0, dotIdx);\n const decPart = dotIdx === -1 ? undefined : fixed.slice(dotIdx + 1);\n\n // Add thousands separators to integer part\n const withSeparators = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, resolved.thousandsSeparator);\n\n let formatted: string;\n if (decPart !== undefined) {\n formatted = `${withSeparators}${resolved.decimalSeparator}${decPart}`;\n } else {\n formatted = withSeparators;\n }\n\n if (resolved.currencySymbol) {\n if (resolved.currencyPosition === 'prefix') {\n return `${resolved.currencySymbol}${formatted}`;\n }\n return `${formatted} ${resolved.currencySymbol}`;\n }\n\n return formatted;\n}\n","/**\n * Shared product rendering utilities.\n *\n * Extracted from chat/renderUISpec and simrel/ProductCard to eliminate\n * duplication and provide consistent behavior across all widgets.\n */\n\n/** Clamp a rating value to the 0–5 range. Returns 0 for NaN/non-finite. */\nexport function clampRating(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.max(0, Math.min(5, value));\n}\n\n/** Clamp a discount percentage to the 0–100 range, rounded to integer. Returns 0 for NaN/non-finite. */\nexport function clampDiscount(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.max(0, Math.min(100, Math.round(value)));\n}\n\n/**\n * Render a star rating string with full, half, and empty stars.\n *\n * @param rating - A numeric rating (will be clamped to 0–5).\n * @param halfStars - Whether to render half-star characters. Defaults to true.\n * @returns A string like \"★★★½☆\" or \"★★★☆☆\" (without half-stars).\n */\nexport function renderStarRating(rating: number, halfStars: boolean = true): string {\n const clamped = clampRating(rating);\n if (halfStars) {\n const full = Math.floor(clamped);\n const half = clamped - full >= 0.5 ? 1 : 0;\n const empty = 5 - full - half;\n return '\\u2605'.repeat(full) + (half ? '\\u00BD' : '') + '\\u2606'.repeat(empty);\n }\n const rounded = Math.round(clamped);\n return '\\u2605'.repeat(rounded) + '\\u2606'.repeat(5 - rounded);\n}\n\n/**\n * Create a star rating DOM element with proper half-filled star rendering.\n *\n * Uses a CSS-clipped full star overlaid on an empty star for the half-star,\n * giving a visually accurate half-filled appearance instead of the \"½\" character.\n *\n * @param rating - A numeric rating (will be clamped to 0–5).\n * @returns An HTMLSpanElement containing the star icons.\n */\nexport function createStarRatingElement(rating: number): HTMLSpanElement {\n const clamped = clampRating(rating);\n const full = Math.floor(clamped);\n const hasHalf = clamped - full >= 0.5;\n const empty = 5 - full - (hasHalf ? 1 : 0);\n\n const container = document.createElement('span');\n container.className = 'gengage-star-rating';\n\n if (full > 0) {\n container.appendChild(document.createTextNode('\\u2605'.repeat(full)));\n }\n\n if (hasHalf) {\n const halfStar = document.createElement('span');\n halfStar.className = 'gengage-star-half';\n halfStar.textContent = '\\u2606';\n const filled = document.createElement('span');\n filled.textContent = '\\u2605';\n halfStar.appendChild(filled);\n container.appendChild(halfStar);\n }\n\n if (empty > 0) {\n container.appendChild(document.createTextNode('\\u2606'.repeat(empty)));\n }\n\n return container;\n}\n\n/**\n * Attach a one-time error handler that hides the image on load failure.\n *\n * Works with any HTMLImageElement. Hides the element by setting\n * `display: none` so layout doesn't break from broken images.\n */\nexport function addImageErrorHandler(img: HTMLImageElement): void {\n img.addEventListener(\n 'error',\n () => {\n img.style.display = 'none';\n },\n { once: true },\n );\n}\n","export interface QuantityStepperOptions {\n min?: number | undefined;\n max?: number | undefined;\n initial?: number | undefined;\n label?: string | undefined;\n compact?: boolean | undefined;\n decreaseLabel?: string | undefined;\n increaseLabel?: string | undefined;\n /** Symbol for decrease button (default: '\\u2212' minus sign). */\n decreaseSymbol?: string | undefined;\n /** Symbol for increase button (default: '+'). */\n increaseSymbol?: string | undefined;\n /** Icon/text for compact mode submit button (default: shopping cart emoji). */\n submitIcon?: string | undefined;\n onSubmit: (quantity: number) => void;\n}\n\n/**\n * Creates a quantity stepper with [−] [value] [+] and a submit button.\n * Compact mode renders a cart icon button; full mode renders a labeled button.\n */\nexport function createQuantityStepper(options: QuantityStepperOptions): HTMLElement {\n const rawMin = options.min ?? 1;\n const rawMax = options.max ?? 99;\n // Ensure min <= max; swap if caller provided inverted range\n const min = Math.min(rawMin, rawMax);\n const max = Math.max(rawMin, rawMax);\n const initial = Math.max(min, Math.min(max, options.initial ?? min));\n const compact = options.compact ?? false;\n\n let quantity = initial;\n\n const container = document.createElement('div');\n container.className = `gengage-qty-stepper${compact ? ' gengage-qty-stepper--compact' : ''}`;\n\n const decBtn = document.createElement('button');\n decBtn.className = 'gengage-qty-btn';\n decBtn.type = 'button';\n decBtn.textContent = options.decreaseSymbol ?? '\\u2212'; // minus sign\n decBtn.setAttribute('aria-label', options.decreaseLabel ?? 'Decrease');\n\n const valueEl = document.createElement('span');\n valueEl.className = 'gengage-qty-value';\n valueEl.textContent = String(quantity);\n valueEl.setAttribute('aria-live', 'polite');\n valueEl.setAttribute('aria-atomic', 'true');\n\n const incBtn = document.createElement('button');\n incBtn.className = 'gengage-qty-btn';\n incBtn.type = 'button';\n incBtn.textContent = options.increaseSymbol ?? '+';\n incBtn.setAttribute('aria-label', options.increaseLabel ?? 'Increase');\n\n const submitBtn = document.createElement('button');\n submitBtn.className = 'gengage-qty-submit';\n submitBtn.type = 'button';\n\n if (compact) {\n submitBtn.textContent = options.submitIcon ?? '\\uD83D\\uDED2'; // shopping cart emoji\n submitBtn.title = options.label ?? 'Add to Cart';\n } else {\n submitBtn.textContent = options.label ?? 'Add to Cart';\n }\n\n function updateButtons(): void {\n decBtn.disabled = quantity <= min;\n incBtn.disabled = quantity >= max;\n }\n\n decBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n if (quantity > min) {\n quantity--;\n valueEl.textContent = String(quantity);\n updateButtons();\n }\n });\n\n incBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n if (quantity < max) {\n quantity++;\n valueEl.textContent = String(quantity);\n updateButtons();\n }\n });\n\n submitBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n options.onSubmit(quantity);\n // Brief visual feedback: show checkmark then revert\n const original = submitBtn.textContent;\n submitBtn.textContent = '\\u2713'; // checkmark\n submitBtn.classList.add('gengage-qty-submit--success');\n submitBtn.disabled = true;\n setTimeout(() => {\n submitBtn.textContent = original;\n submitBtn.classList.remove('gengage-qty-submit--success');\n submitBtn.disabled = false;\n }, 1200);\n });\n\n // Prevent card click when interacting with stepper\n container.addEventListener('click', (e) => {\n e.stopPropagation();\n });\n\n updateButtons();\n\n container.appendChild(decBtn);\n container.appendChild(valueEl);\n container.appendChild(incBtn);\n container.appendChild(submitBtn);\n\n return container;\n}\n"],"names":["TURKISH_DEFAULTS","formatPrice","raw","config","num","resolved","fixed","dotIdx","intPart","decPart","withSeparators","formatted","clampRating","value","clampDiscount","createStarRatingElement","rating","clamped","full","hasHalf","empty","container","halfStar","filled","addImageErrorHandler","img","createQuantityStepper","options","rawMin","rawMax","min","max","initial","compact","quantity","decBtn","valueEl","incBtn","submitBtn","updateButtons","e","original"],"mappings":"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"}