@cimplify/sdk 0.10.4 → 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.mjs CHANGED
@@ -1,8 +1,12 @@
1
1
  "use client";
2
- import React3, { createContext, useContext, useState, useEffect, useRef, useMemo, useSyncExternalStore, useCallback } from 'react';
2
+ import React3, { createContext, useContext, useState, useEffect, useRef, useMemo, useSyncExternalStore, useCallback, useId } from 'react';
3
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
+ import { NumberField } from '@base-ui/react/number-field';
4
5
  import { clsx } from 'clsx';
5
6
  import { twMerge } from 'tailwind-merge';
7
+ import { RadioGroup } from '@base-ui/react/radio-group';
8
+ import { Radio } from '@base-ui/react/radio';
9
+ import { Checkbox } from '@base-ui/react/checkbox';
6
10
 
7
11
  // src/ads/index.tsx
8
12
 
@@ -7824,52 +7828,60 @@ function QuantitySelector({
7824
7828
  className,
7825
7829
  classNames
7826
7830
  }) {
7827
- return /* @__PURE__ */ jsxs(
7828
- "div",
7831
+ return /* @__PURE__ */ jsx(
7832
+ NumberField.Root,
7829
7833
  {
7830
- "data-cimplify-quantity": true,
7831
- className: cn("inline-flex items-center gap-3 border border-border px-2", className, classNames?.root),
7832
- children: [
7833
- /* @__PURE__ */ jsx(
7834
- "button",
7835
- {
7836
- type: "button",
7837
- onClick: () => onChange(Math.max(min, value - 1)),
7838
- disabled: value <= min,
7839
- "aria-label": "Decrease quantity",
7840
- "data-cimplify-quantity-decrement": true,
7841
- className: cn(
7842
- "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7843
- classNames?.button
7834
+ value,
7835
+ onValueChange: (val) => {
7836
+ if (val != null) {
7837
+ onChange(val);
7838
+ }
7839
+ },
7840
+ min,
7841
+ max,
7842
+ step: 1,
7843
+ children: /* @__PURE__ */ jsxs(
7844
+ NumberField.Group,
7845
+ {
7846
+ "data-cimplify-quantity": true,
7847
+ className: cn("inline-flex items-center gap-3 border border-border px-2", className, classNames?.root),
7848
+ children: [
7849
+ /* @__PURE__ */ jsx(
7850
+ NumberField.Decrement,
7851
+ {
7852
+ "aria-label": "Decrease quantity",
7853
+ "data-cimplify-quantity-decrement": true,
7854
+ className: cn(
7855
+ "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7856
+ classNames?.button
7857
+ ),
7858
+ children: "\u2212"
7859
+ }
7844
7860
  ),
7845
- children: "\u2212"
7846
- }
7847
- ),
7848
- /* @__PURE__ */ jsx(
7849
- "span",
7850
- {
7851
- "data-cimplify-quantity-value": true,
7852
- "aria-live": "polite",
7853
- className: cn("w-8 text-center font-medium", classNames?.value),
7854
- children: value
7855
- }
7856
- ),
7857
- /* @__PURE__ */ jsx(
7858
- "button",
7859
- {
7860
- type: "button",
7861
- onClick: () => onChange(max != null ? Math.min(max, value + 1) : value + 1),
7862
- disabled: max != null && value >= max,
7863
- "aria-label": "Increase quantity",
7864
- "data-cimplify-quantity-increment": true,
7865
- className: cn(
7866
- "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7867
- classNames?.button
7861
+ /* @__PURE__ */ jsx(
7862
+ NumberField.Input,
7863
+ {
7864
+ "data-cimplify-quantity-value": true,
7865
+ "aria-live": "polite",
7866
+ readOnly: true,
7867
+ 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)
7868
+ }
7868
7869
  ),
7869
- children: "+"
7870
- }
7871
- )
7872
- ]
7870
+ /* @__PURE__ */ jsx(
7871
+ NumberField.Increment,
7872
+ {
7873
+ "aria-label": "Increase quantity",
7874
+ "data-cimplify-quantity-increment": true,
7875
+ className: cn(
7876
+ "w-10 h-10 flex items-center justify-center hover:text-primary transition-colors disabled:opacity-30",
7877
+ classNames?.button
7878
+ ),
7879
+ children: "+"
7880
+ }
7881
+ )
7882
+ ]
7883
+ }
7884
+ )
7873
7885
  }
7874
7886
  );
7875
7887
  }
@@ -7922,6 +7934,7 @@ function VariantSelector({
7922
7934
  }) {
7923
7935
  const [axisSelections, setAxisSelections] = useState({});
7924
7936
  const initialized = useRef(false);
7937
+ const idPrefix = useId();
7925
7938
  useEffect(() => {
7926
7939
  initialized.current = false;
7927
7940
  }, [variants]);
@@ -7958,106 +7971,126 @@ function VariantSelector({
7958
7971
  }
7959
7972
  const basePriceNum = basePrice != null ? parsePrice(basePrice) : 0;
7960
7973
  if (variantAxes && variantAxes.length > 0) {
7961
- return /* @__PURE__ */ jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => /* @__PURE__ */ jsxs("div", { "data-cimplify-variant-axis": true, children: [
7962
- /* @__PURE__ */ jsx(
7963
- "label",
7964
- {
7965
- "data-cimplify-variant-axis-label": true,
7966
- className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.axisLabel),
7967
- children: axis.name
7968
- }
7969
- ),
7970
- /* @__PURE__ */ jsx(
7971
- "div",
7972
- {
7973
- "data-cimplify-variant-axis-options": true,
7974
- className: cn("flex flex-wrap gap-2", classNames?.axisOptions),
7975
- children: axis.values.map((value) => {
7976
- const isSelected = axisSelections[axis.id] === value.id;
7977
- return /* @__PURE__ */ jsx(
7978
- "button",
7979
- {
7980
- type: "button",
7981
- "aria-selected": isSelected,
7982
- onClick: () => {
7983
- setAxisSelections((prev) => ({
7984
- ...prev,
7985
- [axis.id]: value.id
7986
- }));
7974
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: variantAxes.map((axis) => {
7975
+ const labelId = `${idPrefix}-axis-${axis.id}`;
7976
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-variant-axis": true, children: [
7977
+ /* @__PURE__ */ jsx(
7978
+ "label",
7979
+ {
7980
+ id: labelId,
7981
+ "data-cimplify-variant-axis-label": true,
7982
+ className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.axisLabel),
7983
+ children: axis.name
7984
+ }
7985
+ ),
7986
+ /* @__PURE__ */ jsx(
7987
+ RadioGroup,
7988
+ {
7989
+ "aria-labelledby": labelId,
7990
+ value: axisSelections[axis.id] ?? "",
7991
+ onValueChange: (value) => {
7992
+ setAxisSelections((prev) => ({
7993
+ ...prev,
7994
+ [axis.id]: value
7995
+ }));
7996
+ },
7997
+ "data-cimplify-variant-axis-options": true,
7998
+ className: cn("flex flex-wrap gap-2", classNames?.axisOptions),
7999
+ children: axis.values.map((value) => {
8000
+ const isSelected = axisSelections[axis.id] === value.id;
8001
+ return /* @__PURE__ */ jsx(
8002
+ Radio.Root,
8003
+ {
8004
+ value: value.id,
8005
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
8006
+ "data-cimplify-variant-option": true,
8007
+ "data-selected": isSelected || void 0,
8008
+ className: cn(
8009
+ "px-4 py-2 border text-sm font-medium transition-colors border-border hover:border-primary/50",
8010
+ isSelected && "bg-primary text-primary-foreground border-primary",
8011
+ isSelected ? classNames?.optionSelected : classNames?.option
8012
+ ),
8013
+ children: value.name
7987
8014
  },
7988
- "data-cimplify-variant-option": true,
7989
- "data-selected": isSelected || void 0,
7990
- className: cn(
7991
- "px-4 py-2 border text-sm font-medium transition-colors border-border hover:border-primary/50",
7992
- isSelected && "bg-primary text-primary-foreground border-primary",
7993
- isSelected ? classNames?.optionSelected : classNames?.option
7994
- ),
7995
- children: value.name
7996
- },
7997
- value.id
7998
- );
7999
- })
8000
- }
8001
- )
8002
- ] }, axis.id)) });
8015
+ value.id
8016
+ );
8017
+ })
8018
+ }
8019
+ )
8020
+ ] }, axis.id);
8021
+ }) });
8003
8022
  }
8023
+ const listLabelId = `${idPrefix}-variant-list`;
8004
8024
  return /* @__PURE__ */ jsxs("div", { "data-cimplify-variant-selector": true, className: cn("space-y-5", className, classNames?.root), children: [
8005
8025
  /* @__PURE__ */ jsx(
8006
8026
  "label",
8007
8027
  {
8028
+ id: listLabelId,
8008
8029
  "data-cimplify-variant-list-label": true,
8009
8030
  className: cn("block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", classNames?.listLabel),
8010
8031
  children: "Options"
8011
8032
  }
8012
8033
  ),
8013
- /* @__PURE__ */ jsx("div", { "data-cimplify-variant-list": true, className: cn("space-y-2", classNames?.list), children: variants.map((variant) => {
8014
- const isSelected = selectedVariantId === variant.id;
8015
- const adjustment = parsePrice(variant.price_adjustment);
8016
- const effectivePrice = basePriceNum + adjustment;
8017
- return /* @__PURE__ */ jsxs(
8018
- "button",
8019
- {
8020
- type: "button",
8021
- "aria-selected": isSelected,
8022
- onClick: () => onVariantChange(variant.id, variant),
8023
- "data-cimplify-variant-option": true,
8024
- "data-selected": isSelected || void 0,
8025
- className: cn(
8026
- "w-full flex items-center justify-between px-4 py-3 border transition-colors border-border hover:border-primary/50",
8027
- isSelected && "bg-primary/5 border-primary",
8028
- isSelected ? classNames?.optionSelected : classNames?.option
8029
- ),
8030
- children: [
8031
- /* @__PURE__ */ jsx(
8032
- "span",
8033
- {
8034
- "data-cimplify-variant-name": true,
8035
- className: cn("font-medium", isSelected && "text-primary", classNames?.name),
8036
- children: getVariantDisplayName(variant, productName)
8037
- }
8038
- ),
8039
- /* @__PURE__ */ jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm", classNames?.pricing), children: [
8040
- adjustment !== 0 && /* @__PURE__ */ jsxs(
8041
- "span",
8042
- {
8043
- "data-cimplify-variant-adjustment": true,
8044
- className: cn(
8045
- adjustment > 0 ? "text-muted-foreground" : "text-green-600",
8046
- classNames?.adjustment
8047
- ),
8048
- children: [
8049
- adjustment > 0 ? "+" : "",
8050
- /* @__PURE__ */ jsx(Price, { amount: variant.price_adjustment })
8051
- ]
8052
- }
8053
- ),
8054
- /* @__PURE__ */ jsx(Price, { amount: effectivePrice, className: "text-muted-foreground" })
8055
- ] })
8056
- ]
8034
+ /* @__PURE__ */ jsx(
8035
+ RadioGroup,
8036
+ {
8037
+ "aria-labelledby": listLabelId,
8038
+ value: selectedVariantId ?? "",
8039
+ onValueChange: (value) => {
8040
+ const variant = variants.find((v) => v.id === value);
8041
+ onVariantChange(variant?.id, variant);
8057
8042
  },
8058
- variant.id
8059
- );
8060
- }) })
8043
+ "data-cimplify-variant-list": true,
8044
+ className: cn("space-y-2", classNames?.list),
8045
+ children: variants.map((variant) => {
8046
+ const isSelected = selectedVariantId === variant.id;
8047
+ const adjustment = parsePrice(variant.price_adjustment);
8048
+ const effectivePrice = basePriceNum + adjustment;
8049
+ return /* @__PURE__ */ jsxs(
8050
+ Radio.Root,
8051
+ {
8052
+ value: variant.id,
8053
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
8054
+ "data-cimplify-variant-option": true,
8055
+ "data-selected": isSelected || void 0,
8056
+ className: cn(
8057
+ "w-full flex items-center justify-between px-4 py-3 border transition-colors border-border hover:border-primary/50",
8058
+ isSelected && "bg-primary/5 border-primary",
8059
+ isSelected ? classNames?.optionSelected : classNames?.option
8060
+ ),
8061
+ children: [
8062
+ /* @__PURE__ */ jsx(
8063
+ "span",
8064
+ {
8065
+ "data-cimplify-variant-name": true,
8066
+ className: cn("font-medium", isSelected && "text-primary", classNames?.name),
8067
+ children: getVariantDisplayName(variant, productName)
8068
+ }
8069
+ ),
8070
+ /* @__PURE__ */ jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm", classNames?.pricing), children: [
8071
+ adjustment !== 0 && /* @__PURE__ */ jsxs(
8072
+ "span",
8073
+ {
8074
+ "data-cimplify-variant-adjustment": true,
8075
+ className: cn(
8076
+ adjustment > 0 ? "text-muted-foreground" : "text-green-600",
8077
+ classNames?.adjustment
8078
+ ),
8079
+ children: [
8080
+ adjustment > 0 ? "+" : "",
8081
+ /* @__PURE__ */ jsx(Price, { amount: variant.price_adjustment })
8082
+ ]
8083
+ }
8084
+ ),
8085
+ /* @__PURE__ */ jsx(Price, { amount: effectivePrice, className: "text-muted-foreground" })
8086
+ ] })
8087
+ ]
8088
+ },
8089
+ variant.id
8090
+ );
8091
+ })
8092
+ }
8093
+ )
8061
8094
  ] });
8062
8095
  }
8063
8096
  function AddOnSelector({
@@ -8071,8 +8104,8 @@ function AddOnSelector({
8071
8104
  (optionId) => selectedOptions.includes(optionId),
8072
8105
  [selectedOptions]
8073
8106
  );
8074
- const toggleOption = useCallback(
8075
- (addOn, optionId) => {
8107
+ const handleCheckedChange = useCallback(
8108
+ (addOn, optionId, checked) => {
8076
8109
  const isSelected = selectedOptions.includes(optionId);
8077
8110
  if (addOn.is_mutually_exclusive || !addOn.is_multiple_allowed) {
8078
8111
  const groupOptionIds = new Set(addOn.options.map((o) => o.id));
@@ -8108,7 +8141,6 @@ function AddOnSelector({
8108
8141
  (id) => addOn.options.some((o) => o.id === id)
8109
8142
  ).length;
8110
8143
  const minMet = !addOn.min_selections || currentSelections >= addOn.min_selections;
8111
- const isSingleSelect = addOn.is_mutually_exclusive || !addOn.is_multiple_allowed;
8112
8144
  return /* @__PURE__ */ jsxs(
8113
8145
  "div",
8114
8146
  {
@@ -8171,12 +8203,12 @@ function AddOnSelector({
8171
8203
  children: addOn.options.map((option) => {
8172
8204
  const isSelected = isOptionSelected(option.id);
8173
8205
  return /* @__PURE__ */ jsxs(
8174
- "button",
8206
+ Checkbox.Root,
8175
8207
  {
8176
- type: "button",
8177
- role: isSingleSelect ? "radio" : "checkbox",
8178
- "aria-checked": isSelected,
8179
- onClick: () => toggleOption(addOn, option.id),
8208
+ checked: isSelected,
8209
+ onCheckedChange: (checked) => handleCheckedChange(addOn, option.id, checked),
8210
+ value: option.id,
8211
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
8180
8212
  "data-cimplify-addon-option": true,
8181
8213
  "data-selected": isSelected || void 0,
8182
8214
  className: cn(
@@ -8185,6 +8217,13 @@ function AddOnSelector({
8185
8217
  isSelected ? classNames?.optionSelected : classNames?.option
8186
8218
  ),
8187
8219
  children: [
8220
+ /* @__PURE__ */ jsx(
8221
+ Checkbox.Indicator,
8222
+ {
8223
+ className: "hidden",
8224
+ keepMounted: false
8225
+ }
8226
+ ),
8188
8227
  /* @__PURE__ */ jsx(
8189
8228
  "span",
8190
8229
  {
@@ -8348,11 +8387,13 @@ function BundleComponentCard({
8348
8387
  onVariantChange,
8349
8388
  classNames
8350
8389
  }) {
8390
+ const idPrefix = useId();
8351
8391
  const showVariantPicker = component.allow_variant_choice && component.available_variants.length > 1;
8352
8392
  const displayPrice = useMemo(
8353
8393
  () => getComponentPrice(component, selectedVariantId),
8354
8394
  [component, selectedVariantId]
8355
8395
  );
8396
+ const labelId = `${idPrefix}-bundle-component-${component.id}`;
8356
8397
  return /* @__PURE__ */ jsxs(
8357
8398
  "div",
8358
8399
  {
@@ -8380,6 +8421,7 @@ function BundleComponentCard({
8380
8421
  /* @__PURE__ */ jsx(
8381
8422
  "span",
8382
8423
  {
8424
+ id: labelId,
8383
8425
  "data-cimplify-bundle-component-name": true,
8384
8426
  className: cn("font-medium text-sm", classNames?.componentName),
8385
8427
  children: component.product_name
@@ -8391,19 +8433,23 @@ function BundleComponentCard({
8391
8433
  }
8392
8434
  ),
8393
8435
  showVariantPicker && /* @__PURE__ */ jsx(
8394
- "div",
8436
+ RadioGroup,
8395
8437
  {
8438
+ "aria-labelledby": labelId,
8439
+ value: selectedVariantId ?? "",
8440
+ onValueChange: (value) => {
8441
+ onVariantChange(value);
8442
+ },
8396
8443
  "data-cimplify-bundle-variant-picker": true,
8397
8444
  className: cn("mt-3 flex flex-wrap gap-2", classNames?.variantPicker),
8398
8445
  children: component.available_variants.map((variant) => {
8399
8446
  const isSelected = selectedVariantId === variant.id;
8400
8447
  const adjustment = parsePrice(variant.price_adjustment);
8401
8448
  return /* @__PURE__ */ jsxs(
8402
- "button",
8449
+ Radio.Root,
8403
8450
  {
8404
- type: "button",
8405
- "aria-pressed": isSelected,
8406
- onClick: () => onVariantChange(variant.id),
8451
+ value: variant.id,
8452
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
8407
8453
  "data-cimplify-bundle-variant-option": true,
8408
8454
  "data-selected": isSelected || void 0,
8409
8455
  className: cn(
@@ -8534,12 +8580,13 @@ function CompositeSelector({
8534
8580
  []
8535
8581
  );
8536
8582
  const updateQuantity = useCallback(
8537
- (group, componentId, delta) => {
8583
+ (group, componentId, newValue) => {
8538
8584
  setGroupSelections((prev) => {
8539
8585
  const groupSels = { ...prev[group.id] || {} };
8540
8586
  const current = groupSels[componentId] || 0;
8541
- const next = Math.max(0, current + delta);
8587
+ const next = Math.max(0, newValue);
8542
8588
  if (next === current) return prev;
8589
+ const delta = next - current;
8543
8590
  if (group.max_quantity_per_component && next > group.max_quantity_per_component) {
8544
8591
  return prev;
8545
8592
  }
@@ -8643,12 +8690,12 @@ function CompositeSelector({
8643
8690
  const isSelected = qty > 0;
8644
8691
  const displayName = component.display_name || component.id;
8645
8692
  return /* @__PURE__ */ jsxs(
8646
- "button",
8693
+ Checkbox.Root,
8647
8694
  {
8648
- type: "button",
8649
- role: isSingleSelect ? "radio" : "checkbox",
8650
- "aria-checked": isSelected,
8651
- onClick: () => toggleComponent(group, component),
8695
+ checked: isSelected,
8696
+ onCheckedChange: () => toggleComponent(group, component),
8697
+ value: component.id,
8698
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
8652
8699
  "data-cimplify-composite-component": true,
8653
8700
  "data-selected": isSelected || void 0,
8654
8701
  className: cn(
@@ -8657,6 +8704,13 @@ function CompositeSelector({
8657
8704
  isSelected ? classNames?.componentSelected : classNames?.component
8658
8705
  ),
8659
8706
  children: [
8707
+ /* @__PURE__ */ jsx(
8708
+ Checkbox.Indicator,
8709
+ {
8710
+ className: "hidden",
8711
+ keepMounted: false
8712
+ }
8713
+ ),
8660
8714
  /* @__PURE__ */ jsxs(
8661
8715
  "div",
8662
8716
  {
@@ -8709,35 +8763,51 @@ function CompositeSelector({
8709
8763
  ]
8710
8764
  }
8711
8765
  ),
8712
- group.allow_quantity && isSelected && /* @__PURE__ */ jsxs(
8713
- "span",
8766
+ group.allow_quantity && isSelected && /* @__PURE__ */ jsx(
8767
+ NumberField.Root,
8714
8768
  {
8715
- "data-cimplify-composite-qty": true,
8716
- onClick: (e) => e.stopPropagation(),
8717
- className: cn("flex items-center gap-2", classNames?.qty),
8718
- children: [
8719
- /* @__PURE__ */ jsx(
8720
- "button",
8721
- {
8722
- type: "button",
8723
- onClick: () => updateQuantity(group, component.id, -1),
8724
- "aria-label": `Decrease ${displayName} quantity`,
8725
- className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted", classNames?.qtyButton),
8726
- children: "\u2212"
8727
- }
8728
- ),
8729
- /* @__PURE__ */ jsx("span", { className: cn("text-sm font-medium w-4 text-center", classNames?.qtyValue), children: qty }),
8730
- /* @__PURE__ */ jsx(
8731
- "button",
8732
- {
8733
- type: "button",
8734
- onClick: () => updateQuantity(group, component.id, 1),
8735
- "aria-label": `Increase ${displayName} quantity`,
8736
- className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted", classNames?.qtyButton),
8737
- children: "+"
8738
- }
8739
- )
8740
- ]
8769
+ value: qty,
8770
+ onValueChange: (val) => {
8771
+ if (val != null) {
8772
+ updateQuantity(group, component.id, val);
8773
+ }
8774
+ },
8775
+ min: 0,
8776
+ max: group.max_quantity_per_component || void 0,
8777
+ step: 1,
8778
+ children: /* @__PURE__ */ jsxs(
8779
+ NumberField.Group,
8780
+ {
8781
+ "data-cimplify-composite-qty": true,
8782
+ onClick: (e) => e.stopPropagation(),
8783
+ className: cn("flex items-center gap-2", classNames?.qty),
8784
+ children: [
8785
+ /* @__PURE__ */ jsx(
8786
+ NumberField.Decrement,
8787
+ {
8788
+ "aria-label": `Decrease ${displayName} quantity`,
8789
+ className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted disabled:opacity-30", classNames?.qtyButton),
8790
+ children: "\u2212"
8791
+ }
8792
+ ),
8793
+ /* @__PURE__ */ jsx(
8794
+ NumberField.Input,
8795
+ {
8796
+ readOnly: true,
8797
+ 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)
8798
+ }
8799
+ ),
8800
+ /* @__PURE__ */ jsx(
8801
+ NumberField.Increment,
8802
+ {
8803
+ "aria-label": `Increase ${displayName} quantity`,
8804
+ className: cn("w-6 h-6 border border-border flex items-center justify-center text-xs hover:bg-muted disabled:opacity-30", classNames?.qtyButton),
8805
+ children: "+"
8806
+ }
8807
+ )
8808
+ ]
8809
+ }
8810
+ )
8741
8811
  }
8742
8812
  ),
8743
8813
  component.price != null && parsePrice(component.price) !== 0 && /* @__PURE__ */ jsx(Price, { amount: component.price, prefix: "+" })
@@ -8994,7 +9064,8 @@ function ProductCustomizer({
8994
9064
  variantAxes: product.variant_axes,
8995
9065
  basePrice: product.default_price,
8996
9066
  selectedVariantId,
8997
- onVariantChange: handleVariantChange
9067
+ onVariantChange: handleVariantChange,
9068
+ productName: product.name
8998
9069
  }
8999
9070
  ),
9000
9071
  hasAddOns && /* @__PURE__ */ jsx(
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.w-full{width:100%}.flex-1{flex:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-border{border-color:var(--color-border,oklch(90% 0 0))}.border-primary{border-color:var(--color-primary,oklch(50% .1 35))}.border-transparent{border-color:#0000}.bg-primary{background-color:var(--color-primary,oklch(50% .1 35))}.bg-primary\/5{background-color:#934c3a0d}@supports (color:color-mix(in lab, red, red)){.bg-primary\/5{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 5%, transparent)}}.bg-primary\/10{background-color:#934c3a1a}@supports (color:color-mix(in lab, red, red)){.bg-primary\/10{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 10%, transparent)}}.text-center{text-align:center}.text-left{text-align:left}.text-\[10px\]{font-size:10px}.text-destructive{color:var(--color-destructive,oklch(50% .2 25))}.text-muted-foreground{color:var(--color-muted-foreground,oklch(50% 0 0))}.text-muted-foreground\/60{color:#63636399}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/60{color:color-mix(in oklab, var(--color-muted-foreground,oklch(50% 0 0)) 60%, transparent)}}.text-muted-foreground\/70{color:#636363b3}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/70{color:color-mix(in oklab, var(--color-muted-foreground,oklch(50% 0 0)) 70%, transparent)}}.text-primary{color:var(--color-primary,oklch(50% .1 35))}.text-primary-foreground{color:var(--color-primary-foreground,oklch(99% 0 0))}.uppercase{text-transform:uppercase}.opacity-70{opacity:.7}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.\[cimplify\:checkout\]{cimplify:checkout}@media (hover:hover){.hover\:border-primary\/50:hover{border-color:#934c3a80}@supports (color:color-mix(in lab, red, red)){.hover\:border-primary\/50:hover{border-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 50%, transparent)}}.hover\:bg-muted:hover{background-color:var(--color-muted,oklch(95% 0 0))}.hover\:bg-muted\/50:hover{background-color:#eeeeee80}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--color-muted,oklch(95% 0 0)) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:#934c3ae6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 90%, transparent)}}.hover\:text-primary:hover{color:var(--color-primary,oklch(50% .1 35))}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.w-full{width:100%}.flex-1{flex:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.\[appearance\:textfield\]{appearance:textfield}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-border{border-color:var(--color-border,oklch(90% 0 0))}.border-primary{border-color:var(--color-primary,oklch(50% .1 35))}.border-transparent{border-color:#0000}.bg-primary{background-color:var(--color-primary,oklch(50% .1 35))}.bg-primary\/5{background-color:#934c3a0d}@supports (color:color-mix(in lab, red, red)){.bg-primary\/5{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 5%, transparent)}}.bg-primary\/10{background-color:#934c3a1a}@supports (color:color-mix(in lab, red, red)){.bg-primary\/10{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 10%, transparent)}}.bg-transparent{background-color:#0000}.text-center{text-align:center}.text-left{text-align:left}.text-\[10px\]{font-size:10px}.text-destructive{color:var(--color-destructive,oklch(50% .2 25))}.text-muted-foreground{color:var(--color-muted-foreground,oklch(50% 0 0))}.text-muted-foreground\/60{color:#63636399}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/60{color:color-mix(in oklab, var(--color-muted-foreground,oklch(50% 0 0)) 60%, transparent)}}.text-muted-foreground\/70{color:#636363b3}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/70{color:color-mix(in oklab, var(--color-muted-foreground,oklch(50% 0 0)) 70%, transparent)}}.text-primary{color:var(--color-primary,oklch(50% .1 35))}.text-primary-foreground{color:var(--color-primary-foreground,oklch(99% 0 0))}.uppercase{text-transform:uppercase}.opacity-70{opacity:.7}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.outline-none{--tw-outline-style:none;outline-style:none}.\[cimplify\:checkout\]{cimplify:checkout}@media (hover:hover){.hover\:border-primary\/50:hover{border-color:#934c3a80}@supports (color:color-mix(in lab, red, red)){.hover\:border-primary\/50:hover{border-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 50%, transparent)}}.hover\:bg-muted:hover{background-color:var(--color-muted,oklch(95% 0 0))}.hover\:bg-muted\/50:hover{background-color:#eeeeee80}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--color-muted,oklch(95% 0 0)) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:#934c3ae6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary,oklch(50% .1 35)) 90%, transparent)}}.hover\:text-primary:hover{color:var(--color-primary,oklch(50% .1 35))}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-50:disabled{opacity:.5}.\[\&\:\:-webkit-inner-spin-button\]\:appearance-none::-webkit-inner-spin-button{appearance:none}.\[\&\:\:-webkit-outer-spin-button\]\:appearance-none::-webkit-outer-spin-button{appearance:none}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cimplify/sdk",
3
- "version": "0.10.4",
3
+ "version": "0.11.0",
4
4
  "description": "Cimplify Commerce SDK for storefronts",
5
5
  "keywords": [
6
6
  "cimplify",
@@ -84,6 +84,7 @@
84
84
  "vitest": "^4.0.18"
85
85
  },
86
86
  "dependencies": {
87
+ "@base-ui/react": "^1.2.0",
87
88
  "clsx": "^2.1.0",
88
89
  "tailwind-merge": "^2.6.0"
89
90
  }