@cimplify/sdk 0.10.3 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -3,8 +3,12 @@
3
3
 
4
4
  var React3 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var numberField = require('@base-ui/react/number-field');
6
7
  var clsx = require('clsx');
7
8
  var tailwindMerge = require('tailwind-merge');
9
+ var radioGroup = require('@base-ui/react/radio-group');
10
+ var radio = require('@base-ui/react/radio');
11
+ var checkbox = require('@base-ui/react/checkbox');
8
12
 
9
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
14
 
@@ -7830,52 +7834,60 @@ function QuantitySelector({
7830
7834
  className,
7831
7835
  classNames
7832
7836
  }) {
7833
- return /* @__PURE__ */ jsxRuntime.jsxs(
7834
- "div",
7837
+ return /* @__PURE__ */ jsxRuntime.jsx(
7838
+ numberField.NumberField.Root,
7835
7839
  {
7836
- "data-cimplify-quantity": true,
7837
- className: cn("inline-flex items-center gap-3 border border-border px-2", className, classNames?.root),
7838
- children: [
7839
- /* @__PURE__ */ jsxRuntime.jsx(
7840
- "button",
7841
- {
7842
- type: "button",
7843
- onClick: () => onChange(Math.max(min, value - 1)),
7844
- disabled: value <= min,
7845
- "aria-label": "Decrease quantity",
7846
- "data-cimplify-quantity-decrement": true,
7847
- className: cn(
7848
- "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7849
- classNames?.button
7840
+ value,
7841
+ onValueChange: (val) => {
7842
+ if (val != null) {
7843
+ onChange(val);
7844
+ }
7845
+ },
7846
+ min,
7847
+ max,
7848
+ step: 1,
7849
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
7850
+ numberField.NumberField.Group,
7851
+ {
7852
+ "data-cimplify-quantity": true,
7853
+ className: cn("inline-flex items-center gap-3 border border-border px-2", className, classNames?.root),
7854
+ children: [
7855
+ /* @__PURE__ */ jsxRuntime.jsx(
7856
+ numberField.NumberField.Decrement,
7857
+ {
7858
+ "aria-label": "Decrease quantity",
7859
+ "data-cimplify-quantity-decrement": true,
7860
+ className: cn(
7861
+ "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7862
+ classNames?.button
7863
+ ),
7864
+ children: "\u2212"
7865
+ }
7850
7866
  ),
7851
- children: "\u2212"
7852
- }
7853
- ),
7854
- /* @__PURE__ */ jsxRuntime.jsx(
7855
- "span",
7856
- {
7857
- "data-cimplify-quantity-value": true,
7858
- "aria-live": "polite",
7859
- className: cn("w-8 text-center font-medium", classNames?.value),
7860
- children: value
7861
- }
7862
- ),
7863
- /* @__PURE__ */ jsxRuntime.jsx(
7864
- "button",
7865
- {
7866
- type: "button",
7867
- onClick: () => onChange(max != null ? Math.min(max, value + 1) : value + 1),
7868
- disabled: max != null && value >= max,
7869
- "aria-label": "Increase quantity",
7870
- "data-cimplify-quantity-increment": true,
7871
- className: cn(
7872
- "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7873
- classNames?.button
7867
+ /* @__PURE__ */ jsxRuntime.jsx(
7868
+ numberField.NumberField.Input,
7869
+ {
7870
+ "data-cimplify-quantity-value": true,
7871
+ "aria-live": "polite",
7872
+ readOnly: true,
7873
+ className: cn("w-8 text-center font-medium bg-transparent border-none outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none", classNames?.value)
7874
+ }
7874
7875
  ),
7875
- children: "+"
7876
- }
7877
- )
7878
- ]
7876
+ /* @__PURE__ */ jsxRuntime.jsx(
7877
+ numberField.NumberField.Increment,
7878
+ {
7879
+ "aria-label": "Increase quantity",
7880
+ "data-cimplify-quantity-increment": true,
7881
+ className: cn(
7882
+ "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7883
+ classNames?.button
7884
+ ),
7885
+ children: "+"
7886
+ }
7887
+ )
7888
+ ]
7889
+ }
7890
+ )
7879
7891
  }
7880
7892
  );
7881
7893
  }
@@ -7928,6 +7940,7 @@ function VariantSelector({
7928
7940
  }) {
7929
7941
  const [axisSelections, setAxisSelections] = React3.useState({});
7930
7942
  const initialized = React3.useRef(false);
7943
+ const idPrefix = React3.useId();
7931
7944
  React3.useEffect(() => {
7932
7945
  initialized.current = false;
7933
7946
  }, [variants]);
@@ -7964,106 +7977,126 @@ function VariantSelector({
7964
7977
  }
7965
7978
  const basePriceNum = basePrice != null ? parsePrice(basePrice) : 0;
7966
7979
  if (variantAxes && variantAxes.length > 0) {
7967
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-variant-axis": true, children: [
7968
- /* @__PURE__ */ jsxRuntime.jsx(
7969
- "label",
7970
- {
7971
- "data-cimplify-variant-axis-label": true,
7972
- className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.axisLabel),
7973
- children: axis.name
7974
- }
7975
- ),
7976
- /* @__PURE__ */ jsxRuntime.jsx(
7977
- "div",
7978
- {
7979
- "data-cimplify-variant-axis-options": true,
7980
- className: cn("flex flex-wrap gap-2", classNames?.axisOptions),
7981
- children: axis.values.map((value) => {
7982
- const isSelected = axisSelections[axis.id] === value.id;
7983
- return /* @__PURE__ */ jsxRuntime.jsx(
7984
- "button",
7985
- {
7986
- type: "button",
7987
- "aria-selected": isSelected,
7988
- onClick: () => {
7989
- setAxisSelections((prev) => ({
7990
- ...prev,
7991
- [axis.id]: value.id
7992
- }));
7980
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => {
7981
+ const labelId = `${idPrefix}-axis-${axis.id}`;
7982
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-variant-axis": true, children: [
7983
+ /* @__PURE__ */ jsxRuntime.jsx(
7984
+ "label",
7985
+ {
7986
+ id: labelId,
7987
+ "data-cimplify-variant-axis-label": true,
7988
+ className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.axisLabel),
7989
+ children: axis.name
7990
+ }
7991
+ ),
7992
+ /* @__PURE__ */ jsxRuntime.jsx(
7993
+ radioGroup.RadioGroup,
7994
+ {
7995
+ "aria-labelledby": labelId,
7996
+ value: axisSelections[axis.id] ?? "",
7997
+ onValueChange: (value) => {
7998
+ setAxisSelections((prev) => ({
7999
+ ...prev,
8000
+ [axis.id]: value
8001
+ }));
8002
+ },
8003
+ "data-cimplify-variant-axis-options": true,
8004
+ className: cn("flex flex-wrap gap-2", classNames?.axisOptions),
8005
+ children: axis.values.map((value) => {
8006
+ const isSelected = axisSelections[axis.id] === value.id;
8007
+ return /* @__PURE__ */ jsxRuntime.jsx(
8008
+ radio.Radio.Root,
8009
+ {
8010
+ value: value.id,
8011
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button" }),
8012
+ "data-cimplify-variant-option": true,
8013
+ "data-selected": isSelected || void 0,
8014
+ className: cn(
8015
+ "px-4 py-2 border text-sm font-medium transition-colors border-border hover:border-primary/50",
8016
+ isSelected && "bg-primary text-primary-foreground border-primary",
8017
+ isSelected ? classNames?.optionSelected : classNames?.option
8018
+ ),
8019
+ children: value.name
7993
8020
  },
7994
- "data-cimplify-variant-option": true,
7995
- "data-selected": isSelected || void 0,
7996
- className: cn(
7997
- "px-4 py-2 border text-sm font-medium transition-colors border-border hover:border-primary/50",
7998
- isSelected && "bg-primary text-primary-foreground border-primary",
7999
- isSelected ? classNames?.optionSelected : classNames?.option
8000
- ),
8001
- children: value.name
8002
- },
8003
- value.id
8004
- );
8005
- })
8006
- }
8007
- )
8008
- ] }, axis.id)) });
8021
+ value.id
8022
+ );
8023
+ })
8024
+ }
8025
+ )
8026
+ ] }, axis.id);
8027
+ }) });
8009
8028
  }
8029
+ const listLabelId = `${idPrefix}-variant-list`;
8010
8030
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: [
8011
8031
  /* @__PURE__ */ jsxRuntime.jsx(
8012
8032
  "label",
8013
8033
  {
8034
+ id: listLabelId,
8014
8035
  "data-cimplify-variant-list-label": true,
8015
8036
  className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.listLabel),
8016
8037
  children: "Options"
8017
8038
  }
8018
8039
  ),
8019
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cimplify-variant-list": true, className: cn("space-y-2", classNames?.list), children: variants.map((variant) => {
8020
- const isSelected = selectedVariantId === variant.id;
8021
- const adjustment = parsePrice(variant.price_adjustment);
8022
- const effectivePrice = basePriceNum + adjustment;
8023
- return /* @__PURE__ */ jsxRuntime.jsxs(
8024
- "button",
8025
- {
8026
- type: "button",
8027
- "aria-selected": isSelected,
8028
- onClick: () => onVariantChange(variant.id, variant),
8029
- "data-cimplify-variant-option": true,
8030
- "data-selected": isSelected || void 0,
8031
- className: cn(
8032
- "w-full flex items-center justify-between px-4 py-3 border transition-colors border-border hover:border-primary/50",
8033
- isSelected && "bg-primary/5 border-primary",
8034
- isSelected ? classNames?.optionSelected : classNames?.option
8035
- ),
8036
- children: [
8037
- /* @__PURE__ */ jsxRuntime.jsx(
8038
- "span",
8039
- {
8040
- "data-cimplify-variant-name": true,
8041
- className: cn("font-medium", isSelected && "text-primary", classNames?.name),
8042
- children: getVariantDisplayName(variant, productName)
8043
- }
8044
- ),
8045
- /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm", classNames?.pricing), children: [
8046
- adjustment !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
8047
- "span",
8048
- {
8049
- "data-cimplify-variant-adjustment": true,
8050
- className: cn(
8051
- adjustment > 0 ? "text-muted-foreground" : "text-green-600",
8052
- classNames?.adjustment
8053
- ),
8054
- children: [
8055
- adjustment > 0 ? "+" : "",
8056
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: variant.price_adjustment })
8057
- ]
8058
- }
8059
- ),
8060
- /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: effectivePrice, className: "text-muted-foreground" })
8061
- ] })
8062
- ]
8040
+ /* @__PURE__ */ jsxRuntime.jsx(
8041
+ radioGroup.RadioGroup,
8042
+ {
8043
+ "aria-labelledby": listLabelId,
8044
+ value: selectedVariantId ?? "",
8045
+ onValueChange: (value) => {
8046
+ const variant = variants.find((v) => v.id === value);
8047
+ onVariantChange(variant?.id, variant);
8063
8048
  },
8064
- variant.id
8065
- );
8066
- }) })
8049
+ "data-cimplify-variant-list": true,
8050
+ className: cn("space-y-2", classNames?.list),
8051
+ children: variants.map((variant) => {
8052
+ const isSelected = selectedVariantId === variant.id;
8053
+ const adjustment = parsePrice(variant.price_adjustment);
8054
+ const effectivePrice = basePriceNum + adjustment;
8055
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8056
+ radio.Radio.Root,
8057
+ {
8058
+ value: variant.id,
8059
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button" }),
8060
+ "data-cimplify-variant-option": true,
8061
+ "data-selected": isSelected || void 0,
8062
+ className: cn(
8063
+ "w-full flex items-center justify-between px-4 py-3 border transition-colors border-border hover:border-primary/50",
8064
+ isSelected && "bg-primary/5 border-primary",
8065
+ isSelected ? classNames?.optionSelected : classNames?.option
8066
+ ),
8067
+ children: [
8068
+ /* @__PURE__ */ jsxRuntime.jsx(
8069
+ "span",
8070
+ {
8071
+ "data-cimplify-variant-name": true,
8072
+ className: cn("font-medium", isSelected && "text-primary", classNames?.name),
8073
+ children: getVariantDisplayName(variant, productName)
8074
+ }
8075
+ ),
8076
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm", classNames?.pricing), children: [
8077
+ adjustment !== 0 && /* @__PURE__ */ jsxRuntime.jsxs(
8078
+ "span",
8079
+ {
8080
+ "data-cimplify-variant-adjustment": true,
8081
+ className: cn(
8082
+ adjustment > 0 ? "text-muted-foreground" : "text-green-600",
8083
+ classNames?.adjustment
8084
+ ),
8085
+ children: [
8086
+ adjustment > 0 ? "+" : "",
8087
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: variant.price_adjustment })
8088
+ ]
8089
+ }
8090
+ ),
8091
+ /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: effectivePrice, className: "text-muted-foreground" })
8092
+ ] })
8093
+ ]
8094
+ },
8095
+ variant.id
8096
+ );
8097
+ })
8098
+ }
8099
+ )
8067
8100
  ] });
8068
8101
  }
8069
8102
  function AddOnSelector({
@@ -8077,8 +8110,8 @@ function AddOnSelector({
8077
8110
  (optionId) => selectedOptions.includes(optionId),
8078
8111
  [selectedOptions]
8079
8112
  );
8080
- const toggleOption = React3.useCallback(
8081
- (addOn, optionId) => {
8113
+ const handleCheckedChange = React3.useCallback(
8114
+ (addOn, optionId, checked) => {
8082
8115
  const isSelected = selectedOptions.includes(optionId);
8083
8116
  if (addOn.is_mutually_exclusive || !addOn.is_multiple_allowed) {
8084
8117
  const groupOptionIds = new Set(addOn.options.map((o) => o.id));
@@ -8114,7 +8147,6 @@ function AddOnSelector({
8114
8147
  (id) => addOn.options.some((o) => o.id === id)
8115
8148
  ).length;
8116
8149
  const minMet = !addOn.min_selections || currentSelections >= addOn.min_selections;
8117
- const isSingleSelect = addOn.is_mutually_exclusive || !addOn.is_multiple_allowed;
8118
8150
  return /* @__PURE__ */ jsxRuntime.jsxs(
8119
8151
  "div",
8120
8152
  {
@@ -8177,12 +8209,12 @@ function AddOnSelector({
8177
8209
  children: addOn.options.map((option) => {
8178
8210
  const isSelected = isOptionSelected(option.id);
8179
8211
  return /* @__PURE__ */ jsxRuntime.jsxs(
8180
- "button",
8212
+ checkbox.Checkbox.Root,
8181
8213
  {
8182
- type: "button",
8183
- role: isSingleSelect ? "radio" : "checkbox",
8184
- "aria-checked": isSelected,
8185
- onClick: () => toggleOption(addOn, option.id),
8214
+ checked: isSelected,
8215
+ onCheckedChange: (checked) => handleCheckedChange(addOn, option.id, checked),
8216
+ value: option.id,
8217
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button" }),
8186
8218
  "data-cimplify-addon-option": true,
8187
8219
  "data-selected": isSelected || void 0,
8188
8220
  className: cn(
@@ -8191,6 +8223,13 @@ function AddOnSelector({
8191
8223
  isSelected ? classNames?.optionSelected : classNames?.option
8192
8224
  ),
8193
8225
  children: [
8226
+ /* @__PURE__ */ jsxRuntime.jsx(
8227
+ checkbox.Checkbox.Indicator,
8228
+ {
8229
+ className: "hidden",
8230
+ keepMounted: false
8231
+ }
8232
+ ),
8194
8233
  /* @__PURE__ */ jsxRuntime.jsx(
8195
8234
  "span",
8196
8235
  {
@@ -8354,11 +8393,13 @@ function BundleComponentCard({
8354
8393
  onVariantChange,
8355
8394
  classNames
8356
8395
  }) {
8396
+ const idPrefix = React3.useId();
8357
8397
  const showVariantPicker = component.allow_variant_choice && component.available_variants.length > 1;
8358
8398
  const displayPrice = React3.useMemo(
8359
8399
  () => getComponentPrice(component, selectedVariantId),
8360
8400
  [component, selectedVariantId]
8361
8401
  );
8402
+ const labelId = `${idPrefix}-bundle-component-${component.id}`;
8362
8403
  return /* @__PURE__ */ jsxRuntime.jsxs(
8363
8404
  "div",
8364
8405
  {
@@ -8386,6 +8427,7 @@ function BundleComponentCard({
8386
8427
  /* @__PURE__ */ jsxRuntime.jsx(
8387
8428
  "span",
8388
8429
  {
8430
+ id: labelId,
8389
8431
  "data-cimplify-bundle-component-name": true,
8390
8432
  className: cn("font-medium text-sm", classNames?.componentName),
8391
8433
  children: component.product_name
@@ -8397,19 +8439,23 @@ function BundleComponentCard({
8397
8439
  }
8398
8440
  ),
8399
8441
  showVariantPicker && /* @__PURE__ */ jsxRuntime.jsx(
8400
- "div",
8442
+ radioGroup.RadioGroup,
8401
8443
  {
8444
+ "aria-labelledby": labelId,
8445
+ value: selectedVariantId ?? "",
8446
+ onValueChange: (value) => {
8447
+ onVariantChange(value);
8448
+ },
8402
8449
  "data-cimplify-bundle-variant-picker": true,
8403
8450
  className: cn("mt-3 flex flex-wrap gap-2", classNames?.variantPicker),
8404
8451
  children: component.available_variants.map((variant) => {
8405
8452
  const isSelected = selectedVariantId === variant.id;
8406
8453
  const adjustment = parsePrice(variant.price_adjustment);
8407
8454
  return /* @__PURE__ */ jsxRuntime.jsxs(
8408
- "button",
8455
+ radio.Radio.Root,
8409
8456
  {
8410
- type: "button",
8411
- "aria-pressed": isSelected,
8412
- onClick: () => onVariantChange(variant.id),
8457
+ value: variant.id,
8458
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button" }),
8413
8459
  "data-cimplify-bundle-variant-option": true,
8414
8460
  "data-selected": isSelected || void 0,
8415
8461
  className: cn(
@@ -8540,12 +8586,13 @@ function CompositeSelector({
8540
8586
  []
8541
8587
  );
8542
8588
  const updateQuantity = React3.useCallback(
8543
- (group, componentId, delta) => {
8589
+ (group, componentId, newValue) => {
8544
8590
  setGroupSelections((prev) => {
8545
8591
  const groupSels = { ...prev[group.id] || {} };
8546
8592
  const current = groupSels[componentId] || 0;
8547
- const next = Math.max(0, current + delta);
8593
+ const next = Math.max(0, newValue);
8548
8594
  if (next === current) return prev;
8595
+ const delta = next - current;
8549
8596
  if (group.max_quantity_per_component && next > group.max_quantity_per_component) {
8550
8597
  return prev;
8551
8598
  }
@@ -8649,12 +8696,12 @@ function CompositeSelector({
8649
8696
  const isSelected = qty > 0;
8650
8697
  const displayName = component.display_name || component.id;
8651
8698
  return /* @__PURE__ */ jsxRuntime.jsxs(
8652
- "button",
8699
+ checkbox.Checkbox.Root,
8653
8700
  {
8654
- type: "button",
8655
- role: isSingleSelect ? "radio" : "checkbox",
8656
- "aria-checked": isSelected,
8657
- onClick: () => toggleComponent(group, component),
8701
+ checked: isSelected,
8702
+ onCheckedChange: () => toggleComponent(group, component),
8703
+ value: component.id,
8704
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button" }),
8658
8705
  "data-cimplify-composite-component": true,
8659
8706
  "data-selected": isSelected || void 0,
8660
8707
  className: cn(
@@ -8663,6 +8710,13 @@ function CompositeSelector({
8663
8710
  isSelected ? classNames?.componentSelected : classNames?.component
8664
8711
  ),
8665
8712
  children: [
8713
+ /* @__PURE__ */ jsxRuntime.jsx(
8714
+ checkbox.Checkbox.Indicator,
8715
+ {
8716
+ className: "hidden",
8717
+ keepMounted: false
8718
+ }
8719
+ ),
8666
8720
  /* @__PURE__ */ jsxRuntime.jsxs(
8667
8721
  "div",
8668
8722
  {
@@ -8715,35 +8769,51 @@ function CompositeSelector({
8715
8769
  ]
8716
8770
  }
8717
8771
  ),
8718
- group.allow_quantity && isSelected && /* @__PURE__ */ jsxRuntime.jsxs(
8719
- "span",
8772
+ group.allow_quantity && isSelected && /* @__PURE__ */ jsxRuntime.jsx(
8773
+ numberField.NumberField.Root,
8720
8774
  {
8721
- "data-cimplify-composite-qty": true,
8722
- onClick: (e) => e.stopPropagation(),
8723
- className: cn("flex items-center gap-2", classNames?.qty),
8724
- children: [
8725
- /* @__PURE__ */ jsxRuntime.jsx(
8726
- "button",
8727
- {
8728
- type: "button",
8729
- onClick: () => updateQuantity(group, component.id, -1),
8730
- "aria-label": `Decrease ${displayName} quantity`,
8731
- className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted", classNames?.qtyButton),
8732
- children: "\u2212"
8733
- }
8734
- ),
8735
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm font-medium w-4 text-center", classNames?.qtyValue), children: qty }),
8736
- /* @__PURE__ */ jsxRuntime.jsx(
8737
- "button",
8738
- {
8739
- type: "button",
8740
- onClick: () => updateQuantity(group, component.id, 1),
8741
- "aria-label": `Increase ${displayName} quantity`,
8742
- className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted", classNames?.qtyButton),
8743
- children: "+"
8744
- }
8745
- )
8746
- ]
8775
+ value: qty,
8776
+ onValueChange: (val) => {
8777
+ if (val != null) {
8778
+ updateQuantity(group, component.id, val);
8779
+ }
8780
+ },
8781
+ min: 0,
8782
+ max: group.max_quantity_per_component || void 0,
8783
+ step: 1,
8784
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
8785
+ numberField.NumberField.Group,
8786
+ {
8787
+ "data-cimplify-composite-qty": true,
8788
+ onClick: (e) => e.stopPropagation(),
8789
+ className: cn("flex items-center gap-2", classNames?.qty),
8790
+ children: [
8791
+ /* @__PURE__ */ jsxRuntime.jsx(
8792
+ numberField.NumberField.Decrement,
8793
+ {
8794
+ "aria-label": `Decrease ${displayName} quantity`,
8795
+ className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted disabled:opacity-30", classNames?.qtyButton),
8796
+ children: "\u2212"
8797
+ }
8798
+ ),
8799
+ /* @__PURE__ */ jsxRuntime.jsx(
8800
+ numberField.NumberField.Input,
8801
+ {
8802
+ readOnly: true,
8803
+ className: cn("w-4 text-center text-sm font-medium bg-transparent border-none outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none", classNames?.qtyValue)
8804
+ }
8805
+ ),
8806
+ /* @__PURE__ */ jsxRuntime.jsx(
8807
+ numberField.NumberField.Increment,
8808
+ {
8809
+ "aria-label": `Increase ${displayName} quantity`,
8810
+ className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted disabled:opacity-30", classNames?.qtyButton),
8811
+ children: "+"
8812
+ }
8813
+ )
8814
+ ]
8815
+ }
8816
+ )
8747
8817
  }
8748
8818
  ),
8749
8819
  component.price != null && parsePrice(component.price) !== 0 && /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: component.price, prefix: "+" })
@@ -9000,7 +9070,8 @@ function ProductCustomizer({
9000
9070
  variantAxes: product.variant_axes,
9001
9071
  basePrice: product.default_price,
9002
9072
  selectedVariantId,
9003
- onVariantChange: handleVariantChange
9073
+ onVariantChange: handleVariantChange,
9074
+ productName: product.name
9004
9075
  }
9005
9076
  ),
9006
9077
  hasAddOns && /* @__PURE__ */ jsxRuntime.jsx(