@cimplify/sdk 0.13.1 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.d.mts CHANGED
@@ -877,8 +877,8 @@ interface ProductCardProps {
877
877
  displayMode?: "card" | "page";
878
878
  /** Link href for page mode. Default: `/menu/${product.slug}` */
879
879
  href?: string;
880
- /** Custom modal content renderer. Receives the fully-loaded product. */
881
- renderModal?: (product: ProductWithDetails) => React.ReactNode;
880
+ /** Custom modal content renderer. Receives the fully-loaded product and a close callback. */
881
+ renderModal?: (product: ProductWithDetails, onClose: () => void) => React.ReactNode;
882
882
  /** Custom image renderer (e.g. Next.js Image). */
883
883
  renderImage?: (props: {
884
884
  src: string;
package/dist/react.d.ts CHANGED
@@ -877,8 +877,8 @@ interface ProductCardProps {
877
877
  displayMode?: "card" | "page";
878
878
  /** Link href for page mode. Default: `/menu/${product.slug}` */
879
879
  href?: string;
880
- /** Custom modal content renderer. Receives the fully-loaded product. */
881
- renderModal?: (product: ProductWithDetails) => React.ReactNode;
880
+ /** Custom modal content renderer. Receives the fully-loaded product and a close callback. */
881
+ renderModal?: (product: ProductWithDetails, onClose: () => void) => React.ReactNode;
882
882
  /** Custom image renderer (e.g. Next.js Image). */
883
883
  renderImage?: (props: {
884
884
  src: string;
package/dist/react.js CHANGED
@@ -7978,7 +7978,7 @@ function VariantSelector({
7978
7978
  if (!variants || variants.length <= 1) {
7979
7979
  return null;
7980
7980
  }
7981
- const basePriceNum = basePrice != null ? parsePrice(basePrice) : 0;
7981
+ basePrice != null ? parsePrice(basePrice) : 0;
7982
7982
  if (variantAxes && variantAxes.length > 0) {
7983
7983
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => {
7984
7984
  const labelId = `${idPrefix}-axis-${axis.id}`;
@@ -8029,14 +8029,16 @@ function VariantSelector({
8029
8029
  }) });
8030
8030
  }
8031
8031
  const listLabelId = `${idPrefix}-variant-list`;
8032
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: [
8033
- /* @__PURE__ */ jsxRuntime.jsx(
8034
- "label",
8032
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-variant-selector": true, className: cn(className, classNames?.root), children: [
8033
+ /* @__PURE__ */ jsxRuntime.jsxs(
8034
+ "div",
8035
8035
  {
8036
- id: listLabelId,
8037
- "data-cimplify-variant-list-label": true,
8038
- className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.listLabel),
8039
- children: "Options"
8036
+ "data-cimplify-variant-list-header": true,
8037
+ className: cn("flex items-center justify-between py-3", classNames?.listLabel),
8038
+ children: [
8039
+ /* @__PURE__ */ jsxRuntime.jsx("label", { id: listLabelId, className: "text-base font-bold", children: "Options" }),
8040
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-destructive bg-destructive/10 px-2.5 py-1 rounded", children: "Required" })
8041
+ ]
8040
8042
  }
8041
8043
  ),
8042
8044
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -8049,11 +8051,10 @@ function VariantSelector({
8049
8051
  onVariantChange(variant?.id, variant);
8050
8052
  },
8051
8053
  "data-cimplify-variant-list": true,
8052
- className: cn("space-y-2", classNames?.list),
8054
+ className: cn("divide-y divide-border", classNames?.list),
8053
8055
  children: variants.map((variant) => {
8054
8056
  const isSelected = selectedVariantId === variant.id;
8055
8057
  const adjustment = parsePrice(variant.price_adjustment);
8056
- const effectivePrice = basePriceNum + adjustment;
8057
8058
  return /* @__PURE__ */ jsxRuntime.jsxs(
8058
8059
  radio.Radio.Root,
8059
8060
  {
@@ -8061,35 +8062,32 @@ function VariantSelector({
8061
8062
  "data-cimplify-variant-option": true,
8062
8063
  "data-selected": isSelected || void 0,
8063
8064
  className: cn(
8064
- "w-full flex items-center justify-between px-4 py-3 border transition-colors border-border hover:border-primary/50",
8065
- isSelected && "bg-primary/5 border-primary",
8065
+ "w-full flex items-center gap-3 py-4 transition-colors cursor-pointer",
8066
8066
  isSelected ? classNames?.optionSelected : classNames?.option
8067
8067
  ),
8068
8068
  children: [
8069
+ /* @__PURE__ */ jsxRuntime.jsx(
8070
+ "span",
8071
+ {
8072
+ "data-cimplify-variant-radio": true,
8073
+ className: cn(
8074
+ "w-5 h-5 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors",
8075
+ isSelected ? "border-primary" : "border-muted-foreground/30"
8076
+ ),
8077
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
8078
+ }
8079
+ ),
8069
8080
  /* @__PURE__ */ jsxRuntime.jsx(
8070
8081
  "span",
8071
8082
  {
8072
8083
  "data-cimplify-variant-name": true,
8073
- className: cn("font-medium", isSelected && "text-primary", classNames?.name),
8084
+ className: cn("flex-1 min-w-0 text-sm", classNames?.name),
8074
8085
  children: getVariantDisplayName(variant, productName)
8075
8086
  }
8076
8087
  ),
8077
- /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm flex items-center gap-2", classNames?.pricing), children: [
8078
- adjustment !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
8079
- "span",
8080
- {
8081
- "data-cimplify-variant-adjustment": true,
8082
- className: cn(
8083
- adjustment > 0 ? "text-muted-foreground" : "text-green-600",
8084
- classNames?.adjustment
8085
- ),
8086
- children: [
8087
- adjustment > 0 ? "+" : "",
8088
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: variant.price_adjustment })
8089
- ]
8090
- }
8091
- ),
8092
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: effectivePrice, className: "text-muted-foreground" })
8088
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
8089
+ adjustment > 0 ? "+" : adjustment < 0 ? "" : "+",
8090
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: variant.price_adjustment })
8093
8091
  ] })
8094
8092
  ]
8095
8093
  },
@@ -8148,54 +8146,46 @@ function AddOnSelector({
8148
8146
  (id) => addOn.options.some((o) => o.id === id)
8149
8147
  ).length;
8150
8148
  const minMet = !addOn.min_selections || currentSelections >= addOn.min_selections;
8149
+ const isSingleSelect = addOn.is_mutually_exclusive || !addOn.is_multiple_allowed;
8151
8150
  return /* @__PURE__ */ jsxRuntime.jsxs(
8152
8151
  "div",
8153
8152
  {
8154
8153
  "data-cimplify-addon-group": true,
8155
- className: cn("border border-border p-5", classNames?.group),
8154
+ className: cn(classNames?.group),
8156
8155
  children: [
8157
8156
  /* @__PURE__ */ jsxRuntime.jsxs(
8158
8157
  "div",
8159
8158
  {
8160
8159
  "data-cimplify-addon-header": true,
8161
- className: cn("flex items-center justify-between mb-4", classNames?.header),
8160
+ className: cn("flex items-center justify-between py-3", classNames?.header),
8162
8161
  children: [
8163
8162
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8164
- /* @__PURE__ */ jsxRuntime.jsxs(
8163
+ /* @__PURE__ */ jsxRuntime.jsx(
8165
8164
  "span",
8166
8165
  {
8167
8166
  "data-cimplify-addon-name": true,
8168
- className: cn("text-xs font-medium uppercase tracking-wider text-muted-foreground", classNames?.name),
8169
- children: [
8170
- addOn.name,
8171
- addOn.is_required && /* @__PURE__ */ jsxRuntime.jsxs(
8172
- "span",
8173
- {
8174
- "data-cimplify-addon-required": true,
8175
- className: cn("text-destructive ml-1", classNames?.required),
8176
- children: [
8177
- " ",
8178
- "*"
8179
- ]
8180
- }
8181
- )
8182
- ]
8167
+ className: cn("text-base font-bold", classNames?.name),
8168
+ children: addOn.name
8183
8169
  }
8184
8170
  ),
8185
8171
  (addOn.min_selections || addOn.max_selections) && /* @__PURE__ */ jsxRuntime.jsx(
8186
8172
  "span",
8187
8173
  {
8188
8174
  "data-cimplify-addon-constraint": true,
8189
- className: cn("text-xs text-muted-foreground/70 mt-1", classNames?.constraint),
8175
+ className: cn("block text-xs text-muted-foreground mt-0.5", classNames?.constraint),
8190
8176
  children: addOn.min_selections && addOn.max_selections ? `Choose ${addOn.min_selections}\u2013${addOn.max_selections}` : addOn.min_selections ? `Choose at least ${addOn.min_selections}` : `Choose up to ${addOn.max_selections}`
8191
8177
  }
8192
8178
  )
8193
8179
  ] }),
8194
- !minMet && /* @__PURE__ */ jsxRuntime.jsx(
8180
+ (addOn.is_required || !minMet) && /* @__PURE__ */ jsxRuntime.jsx(
8195
8181
  "span",
8196
8182
  {
8197
- "data-cimplify-addon-validation": true,
8198
- className: cn("text-xs text-destructive font-medium", classNames?.validation),
8183
+ "data-cimplify-addon-required": true,
8184
+ className: cn(
8185
+ "text-xs font-semibold px-2.5 py-1 rounded",
8186
+ !minMet ? "text-destructive bg-destructive/10" : "text-destructive bg-destructive/10",
8187
+ classNames?.required
8188
+ ),
8199
8189
  children: "Required"
8200
8190
  }
8201
8191
  )
@@ -8206,7 +8196,7 @@ function AddOnSelector({
8206
8196
  "div",
8207
8197
  {
8208
8198
  "data-cimplify-addon-options": true,
8209
- className: cn("space-y-1", classNames?.options),
8199
+ className: cn("divide-y divide-border", classNames?.options),
8210
8200
  children: addOn.options.map((option) => {
8211
8201
  const isSelected = isOptionSelected(option.id);
8212
8202
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -8218,8 +8208,7 @@ function AddOnSelector({
8218
8208
  "data-cimplify-addon-option": true,
8219
8209
  "data-selected": isSelected || void 0,
8220
8210
  className: cn(
8221
- "w-full flex items-center gap-3 px-4 py-3 border transition-colors text-left border-transparent hover:bg-muted/50",
8222
- isSelected && "bg-primary/5 border-primary",
8211
+ "w-full flex items-center gap-3 py-4 transition-colors text-left cursor-pointer",
8223
8212
  isSelected ? classNames?.optionSelected : classNames?.option
8224
8213
  ),
8225
8214
  children: [
@@ -8230,25 +8219,42 @@ function AddOnSelector({
8230
8219
  keepMounted: false
8231
8220
  }
8232
8221
  ),
8222
+ isSingleSelect ? /* @__PURE__ */ jsxRuntime.jsx(
8223
+ "span",
8224
+ {
8225
+ "data-cimplify-addon-radio": true,
8226
+ className: cn(
8227
+ "w-5 h-5 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors",
8228
+ isSelected ? "border-primary" : "border-muted-foreground/30"
8229
+ ),
8230
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
8231
+ }
8232
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
8233
+ "span",
8234
+ {
8235
+ "data-cimplify-addon-checkbox": true,
8236
+ className: cn(
8237
+ "w-5 h-5 rounded-sm border-2 flex items-center justify-center shrink-0 transition-colors",
8238
+ isSelected ? "border-primary bg-primary" : "border-muted-foreground/30"
8239
+ ),
8240
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", className: "w-3 h-3 text-primary-foreground", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 6l3 3 5-5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
8241
+ }
8242
+ ),
8233
8243
  /* @__PURE__ */ jsxRuntime.jsx(
8234
8244
  "span",
8235
8245
  {
8236
8246
  "data-cimplify-addon-option-name": true,
8237
8247
  className: cn(
8238
- "flex-1 min-w-0 text-sm font-medium",
8239
- isSelected && "text-primary",
8248
+ "flex-1 min-w-0 text-sm",
8240
8249
  classNames?.optionName
8241
8250
  ),
8242
8251
  children: option.name
8243
8252
  }
8244
8253
  ),
8245
- option.default_price != null && parsePrice(option.default_price) !== 0 && /* @__PURE__ */ jsxRuntime.jsx(
8246
- Price,
8247
- {
8248
- amount: option.default_price,
8249
- prefix: "+"
8250
- }
8251
- )
8254
+ option.default_price != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground", children: [
8255
+ "+",
8256
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: option.default_price })
8257
+ ] })
8252
8258
  ]
8253
8259
  },
8254
8260
  option.id
@@ -8334,14 +8340,14 @@ function BundleSelector({
8334
8340
  }
8335
8341
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-bundle-selector": true, className: cn("space-y-4", className, classNames?.root), children: [
8336
8342
  /* @__PURE__ */ jsxRuntime.jsx(
8337
- "span",
8343
+ "div",
8338
8344
  {
8339
8345
  "data-cimplify-bundle-heading": true,
8340
- className: cn("text-xs font-medium uppercase tracking-wider text-muted-foreground", classNames?.heading),
8341
- children: "Included in this bundle"
8346
+ className: cn("flex items-center justify-between py-3", classNames?.heading),
8347
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-bold", children: "Included in this bundle" })
8342
8348
  }
8343
8349
  ),
8344
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-bundle-components": true, className: cn("space-y-3", classNames?.components), children: components.map((comp) => /* @__PURE__ */ jsxRuntime.jsx(
8350
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-bundle-components": true, className: cn("divide-y divide-border", classNames?.components), children: components.map((comp) => /* @__PURE__ */ jsxRuntime.jsx(
8345
8351
  BundleComponentCard,
8346
8352
  {
8347
8353
  component: comp,
@@ -8404,20 +8410,20 @@ function BundleComponentCard({
8404
8410
  "div",
8405
8411
  {
8406
8412
  "data-cimplify-bundle-component": true,
8407
- className: cn("border border-border p-4", classNames?.component),
8413
+ className: cn("py-4", classNames?.component),
8408
8414
  children: [
8409
8415
  /* @__PURE__ */ jsxRuntime.jsxs(
8410
8416
  "div",
8411
8417
  {
8412
8418
  "data-cimplify-bundle-component-header": true,
8413
- className: cn("flex items-start justify-between gap-3", classNames?.componentHeader),
8419
+ className: cn("flex items-center justify-between gap-3", classNames?.componentHeader),
8414
8420
  children: [
8415
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8421
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
8416
8422
  component.quantity > 1 && /* @__PURE__ */ jsxRuntime.jsxs(
8417
8423
  "span",
8418
8424
  {
8419
8425
  "data-cimplify-bundle-component-qty": true,
8420
- className: cn("text-xs font-medium text-primary bg-primary/10 px-1.5 py-0.5", classNames?.componentQty),
8426
+ className: cn("text-xs font-medium text-primary bg-primary/10 px-1.5 py-0.5 rounded", classNames?.componentQty),
8421
8427
  children: [
8422
8428
  "\xD7",
8423
8429
  component.quantity
@@ -8429,12 +8435,12 @@ function BundleComponentCard({
8429
8435
  {
8430
8436
  id: labelId,
8431
8437
  "data-cimplify-bundle-component-name": true,
8432
- className: cn("font-medium text-sm", classNames?.componentName),
8438
+ className: cn("text-sm", classNames?.componentName),
8433
8439
  children: component.product_name
8434
8440
  }
8435
8441
  )
8436
8442
  ] }),
8437
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: displayPrice })
8443
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: displayPrice }) })
8438
8444
  ]
8439
8445
  }
8440
8446
  ),
@@ -8447,7 +8453,7 @@ function BundleComponentCard({
8447
8453
  onVariantChange(value);
8448
8454
  },
8449
8455
  "data-cimplify-bundle-variant-picker": true,
8450
- className: cn("mt-3 flex flex-wrap gap-2", classNames?.variantPicker),
8456
+ className: cn("mt-3 divide-y divide-border", classNames?.variantPicker),
8451
8457
  children: component.available_variants.map((variant) => {
8452
8458
  const isSelected = selectedVariantId === variant.id;
8453
8459
  const adjustment = parsePrice(variant.price_adjustment);
@@ -8458,17 +8464,26 @@ function BundleComponentCard({
8458
8464
  "data-cimplify-bundle-variant-option": true,
8459
8465
  "data-selected": isSelected || void 0,
8460
8466
  className: cn(
8461
- "px-3 py-1.5 border text-xs font-medium transition-colors border-border hover:border-primary/50",
8462
- isSelected && "bg-primary text-primary-foreground border-primary",
8467
+ "w-full flex items-center gap-3 py-3 transition-colors cursor-pointer",
8463
8468
  isSelected ? classNames?.variantOptionSelected : classNames?.variantOption
8464
8469
  ),
8465
8470
  children: [
8466
- variant.display_name,
8471
+ /* @__PURE__ */ jsxRuntime.jsx(
8472
+ "span",
8473
+ {
8474
+ className: cn(
8475
+ "w-5 h-5 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors",
8476
+ isSelected ? "border-primary" : "border-muted-foreground/30"
8477
+ ),
8478
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
8479
+ }
8480
+ ),
8481
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-sm", children: variant.display_name }),
8467
8482
  adjustment !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
8468
8483
  "span",
8469
8484
  {
8470
8485
  "data-cimplify-bundle-variant-adjustment": true,
8471
- className: cn("ml-1 opacity-70", classNames?.variantAdjustment),
8486
+ className: cn("text-sm text-muted-foreground", classNames?.variantAdjustment),
8472
8487
  children: [
8473
8488
  adjustment > 0 ? "+" : "",
8474
8489
  /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: variant.price_adjustment })
@@ -8625,41 +8640,28 @@ function CompositeSelector({
8625
8640
  "div",
8626
8641
  {
8627
8642
  "data-cimplify-composite-group": true,
8628
- className: cn("border border-border p-5", classNames?.group),
8643
+ className: cn(classNames?.group),
8629
8644
  children: [
8630
8645
  /* @__PURE__ */ jsxRuntime.jsxs(
8631
8646
  "div",
8632
8647
  {
8633
8648
  "data-cimplify-composite-group-header": true,
8634
- className: cn("flex items-center justify-between mb-4", classNames?.groupHeader),
8649
+ className: cn("flex items-center justify-between py-3", classNames?.groupHeader),
8635
8650
  children: [
8636
8651
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8637
- /* @__PURE__ */ jsxRuntime.jsxs(
8652
+ /* @__PURE__ */ jsxRuntime.jsx(
8638
8653
  "span",
8639
8654
  {
8640
8655
  "data-cimplify-composite-group-name": true,
8641
- className: cn("text-xs font-medium uppercase tracking-wider text-muted-foreground", classNames?.groupName),
8642
- children: [
8643
- group.name,
8644
- group.min_selections > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
8645
- "span",
8646
- {
8647
- "data-cimplify-composite-required": true,
8648
- className: cn("text-destructive ml-1", classNames?.required),
8649
- children: [
8650
- " ",
8651
- "*"
8652
- ]
8653
- }
8654
- )
8655
- ]
8656
+ className: cn("text-base font-bold", classNames?.groupName),
8657
+ children: group.name
8656
8658
  }
8657
8659
  ),
8658
8660
  group.description && /* @__PURE__ */ jsxRuntime.jsx(
8659
8661
  "span",
8660
8662
  {
8661
8663
  "data-cimplify-composite-group-description": true,
8662
- className: cn("text-xs text-muted-foreground/70 mt-0.5", classNames?.groupDescription),
8664
+ className: cn("block text-xs text-muted-foreground mt-0.5", classNames?.groupDescription),
8663
8665
  children: group.description
8664
8666
  }
8665
8667
  ),
@@ -8667,16 +8669,20 @@ function CompositeSelector({
8667
8669
  "span",
8668
8670
  {
8669
8671
  "data-cimplify-composite-group-constraint": true,
8670
- className: cn("text-xs text-muted-foreground/70 mt-1", classNames?.groupConstraint),
8672
+ className: cn("block text-xs text-muted-foreground mt-0.5", classNames?.groupConstraint),
8671
8673
  children: group.min_selections > 0 && group.max_selections ? `Choose ${group.min_selections}\u2013${group.max_selections}` : group.min_selections > 0 ? `Choose at least ${group.min_selections}` : group.max_selections ? `Choose up to ${group.max_selections}` : "Choose as many as you like"
8672
8674
  }
8673
8675
  )
8674
8676
  ] }),
8675
- !minMet && /* @__PURE__ */ jsxRuntime.jsx(
8677
+ group.min_selections > 0 && /* @__PURE__ */ jsxRuntime.jsx(
8676
8678
  "span",
8677
8679
  {
8678
- "data-cimplify-composite-validation": true,
8679
- className: cn("text-xs text-destructive font-medium", classNames?.validation),
8680
+ "data-cimplify-composite-required": true,
8681
+ className: cn(
8682
+ "text-xs font-semibold px-2.5 py-1 rounded shrink-0",
8683
+ !minMet ? "text-destructive bg-destructive/10" : "text-destructive bg-destructive/10",
8684
+ classNames?.required
8685
+ ),
8680
8686
  children: "Required"
8681
8687
  }
8682
8688
  )
@@ -8689,7 +8695,7 @@ function CompositeSelector({
8689
8695
  "data-cimplify-composite-components": true,
8690
8696
  role: isSingleSelect ? "radiogroup" : "group",
8691
8697
  "aria-label": group.name,
8692
- className: cn("space-y-1", classNames?.components),
8698
+ className: cn("divide-y divide-border", classNames?.components),
8693
8699
  children: group.components.filter((c) => c.is_available && !c.is_archived).sort((a, b) => a.display_order - b.display_order).map((component) => {
8694
8700
  const qty = groupSels[component.id] || 0;
8695
8701
  const isSelected = qty > 0;
@@ -8703,8 +8709,7 @@ function CompositeSelector({
8703
8709
  "data-cimplify-composite-component": true,
8704
8710
  "data-selected": isSelected || void 0,
8705
8711
  className: cn(
8706
- "w-full flex items-center gap-3 px-4 py-3 border transition-colors text-left border-transparent hover:bg-muted/50",
8707
- isSelected && "bg-primary/5 border-primary",
8712
+ "w-full flex items-center gap-3 py-4 transition-colors text-left cursor-pointer",
8708
8713
  isSelected ? classNames?.componentSelected : classNames?.component
8709
8714
  ),
8710
8715
  children: [
@@ -8715,6 +8720,27 @@ function CompositeSelector({
8715
8720
  keepMounted: false
8716
8721
  }
8717
8722
  ),
8723
+ isSingleSelect ? /* @__PURE__ */ jsxRuntime.jsx(
8724
+ "span",
8725
+ {
8726
+ "data-cimplify-composite-radio": true,
8727
+ className: cn(
8728
+ "w-5 h-5 rounded-full border-2 flex items-center justify-center shrink-0 transition-colors",
8729
+ isSelected ? "border-primary" : "border-muted-foreground/30"
8730
+ ),
8731
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2.5 h-2.5 rounded-full bg-primary" })
8732
+ }
8733
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
8734
+ "span",
8735
+ {
8736
+ "data-cimplify-composite-checkbox": true,
8737
+ className: cn(
8738
+ "w-5 h-5 rounded-sm border-2 flex items-center justify-center shrink-0 transition-colors",
8739
+ isSelected ? "border-primary bg-primary" : "border-muted-foreground/30"
8740
+ ),
8741
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", className: "w-3 h-3 text-primary-foreground", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 6l3 3 5-5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
8742
+ }
8743
+ ),
8718
8744
  /* @__PURE__ */ jsxRuntime.jsxs(
8719
8745
  "div",
8720
8746
  {
@@ -8725,7 +8751,7 @@ function CompositeSelector({
8725
8751
  "span",
8726
8752
  {
8727
8753
  "data-cimplify-composite-component-name": true,
8728
- className: cn("text-sm font-medium", isSelected && "text-primary", classNames?.componentName),
8754
+ className: cn("text-sm", classNames?.componentName),
8729
8755
  children: displayName
8730
8756
  }
8731
8757
  ),
@@ -8749,7 +8775,7 @@ function CompositeSelector({
8749
8775
  "span",
8750
8776
  {
8751
8777
  "data-cimplify-composite-component-description": true,
8752
- className: cn("text-xs text-muted-foreground truncate", classNames?.componentDescription),
8778
+ className: cn("block text-xs text-muted-foreground truncate", classNames?.componentDescription),
8753
8779
  children: component.display_description
8754
8780
  }
8755
8781
  ),
@@ -8757,7 +8783,7 @@ function CompositeSelector({
8757
8783
  "span",
8758
8784
  {
8759
8785
  "data-cimplify-composite-component-calories": true,
8760
- className: cn("text-xs text-muted-foreground/60", classNames?.componentCalories),
8786
+ className: cn("block text-xs text-muted-foreground/60", classNames?.componentCalories),
8761
8787
  children: [
8762
8788
  component.calories,
8763
8789
  " cal"
@@ -8814,7 +8840,10 @@ function CompositeSelector({
8814
8840
  )
8815
8841
  }
8816
8842
  ),
8817
- component.price != null && parsePrice(component.price) !== 0 && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: component.price, prefix: "+" })
8843
+ component.price != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-muted-foreground shrink-0", children: [
8844
+ "+",
8845
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: component.price })
8846
+ ] })
8818
8847
  ]
8819
8848
  },
8820
8849
  component.id
@@ -9572,6 +9601,14 @@ function ProductCard({
9572
9601
  const [isOpen, setIsOpen] = React3.useState(false);
9573
9602
  const [shouldFetch, setShouldFetch] = React3.useState(false);
9574
9603
  const dialogRef = React3.useRef(null);
9604
+ React3.useEffect(() => {
9605
+ if (!isOpen) return;
9606
+ const original = document.body.style.overflow;
9607
+ document.body.style.overflow = "hidden";
9608
+ return () => {
9609
+ document.body.style.overflow = original;
9610
+ };
9611
+ }, [isOpen]);
9575
9612
  const { product: productDetails } = useProduct(
9576
9613
  product.slug ?? product.id,
9577
9614
  { enabled: shouldFetch || isOpen }
@@ -9711,7 +9748,7 @@ function ProductCard({
9711
9748
  "border-none rounded-2xl p-0 max-w-lg w-full max-h-[85vh] overflow-auto bg-background shadow-2xl backdrop:bg-black/50 backdrop:backdrop-blur-sm open:animate-in open:fade-in-0 open:slide-in-from-bottom-4",
9712
9749
  classNames?.modal
9713
9750
  ),
9714
- children: isOpen && (productDetails ? renderModal ? renderModal(productDetails) : /* @__PURE__ */ jsxRuntime.jsx(
9751
+ children: isOpen && (productDetails ? renderModal ? renderModal(productDetails, handleClose) : /* @__PURE__ */ jsxRuntime.jsx(
9715
9752
  ProductSheet,
9716
9753
  {
9717
9754
  product: productDetails,