@pisell/materials 6.12.47 → 6.12.50

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.
@@ -19,6 +19,7 @@ import Promotion from "./components/Promotion/index.js";
19
19
  import Gift from "./components/Gift/index.js";
20
20
  import BookingItem from "./components/BookingItem/index.js";
21
21
  import InlineActions from "./components/inlineActions/index.js";
22
+ import A12 from "./variants/A12/index.js";
22
23
  import React, { useMemo, useRef } from "react";
23
24
  import { locales } from "@pisell/utils";
24
25
  import classNames from "classnames";
@@ -56,12 +57,14 @@ const _excluded = [
56
57
  "rightActionsDisplay",
57
58
  "escapeDom",
58
59
  "maxSpecsCount",
59
- "isShowRelatedProduct"
60
+ "isShowRelatedProduct",
61
+ "a12Slots",
62
+ "a12Presentation"
60
63
  ];
61
64
  const PREFIX = "pisell-cart-sku-card";
62
65
  const CartSkuCard = (props) => {
63
66
  var _context$appHelper$ut;
64
- const { dataSource = defaultValue.dataSource, isShowImage = defaultValue.isShowImage, isShowQuantityBadge = true, isShowOriginalPrice = defaultValue.isShowOriginalPrice, isShowHolder = defaultValue.isShowHolder, isShowNote = defaultValue.isShowNote, isShowDelete = defaultValue.isShowDelete, isShowInlineDelete = isShowDelete, isShowAmountFooter = defaultValue.isShowAmountFooter, isShowPackageNote = defaultValue.isShowPackageNote, isShowEditProduct = defaultValue.isShowEditProduct, disabledClick = defaultValue.disabledClick, disabledEditClick = defaultValue.disabledEditClick, disabledNoteEdit, externalNoteEditor = false, onEditProduct, onAction, onDelete, onNote, onLike, onCard, onChangeResource, onPromotion, onGift, onChangeHolder, itemType = "product", type, rightActions = [], rightActionsDisplay = "swipe", escapeDom, maxSpecsCount = 1, isShowRelatedProduct = true } = props, other = _objectWithoutProperties(props, _excluded);
67
+ const { dataSource = defaultValue.dataSource, isShowImage = defaultValue.isShowImage, isShowQuantityBadge = true, isShowOriginalPrice = defaultValue.isShowOriginalPrice, isShowHolder = defaultValue.isShowHolder, isShowNote = defaultValue.isShowNote, isShowDelete = defaultValue.isShowDelete, isShowInlineDelete = isShowDelete, isShowAmountFooter = defaultValue.isShowAmountFooter, isShowPackageNote = defaultValue.isShowPackageNote, isShowEditProduct = defaultValue.isShowEditProduct, disabledClick = defaultValue.disabledClick, disabledEditClick = defaultValue.disabledEditClick, disabledNoteEdit, externalNoteEditor = false, onEditProduct, onAction, onDelete, onNote, onLike, onCard, onChangeResource, onPromotion, onGift, onChangeHolder, itemType = "product", type, rightActions = [], rightActionsDisplay = "swipe", escapeDom, maxSpecsCount = 1, isShowRelatedProduct = true, a12Slots, a12Presentation } = props, other = _objectWithoutProperties(props, _excluded);
65
68
  const useOpenNoteRef = useRef();
66
69
  const context = useEngineContext();
67
70
  locales.init(locales_default, ((_context$appHelper$ut = context.appHelper.utils) === null || _context$appHelper$ut === void 0 || (_context$appHelper$ut = _context$appHelper$ut.storage) === null || _context$appHelper$ut === void 0 ? void 0 : _context$appHelper$ut.get("umi_locale")) || "en");
@@ -219,13 +222,28 @@ const CartSkuCard = (props) => {
219
222
  openNote: openNoteEditor
220
223
  })) : null);
221
224
  };
225
+ const renderA12 = () => /* @__PURE__ */ React.createElement(A12, {
226
+ dataSource,
227
+ isShowImage,
228
+ isShowDelete,
229
+ isShowOriginalPrice,
230
+ isShowEditProduct,
231
+ disabled: Boolean(disabledClick),
232
+ disabledEditClick,
233
+ slots: a12Slots,
234
+ presentation: a12Presentation,
235
+ onDelete,
236
+ onEditProduct
237
+ });
222
238
  const renderContent = () => {
239
+ if (type === "a12") return renderA12();
223
240
  if (type === "a9") return renderA9();
224
241
  if (type === "a5") return renderA5();
225
242
  return renderA2();
226
243
  };
227
244
  if (dataSource === null || dataSource === void 0 ? void 0 : dataSource.isGift) return null;
228
245
  const content = renderContent();
246
+ const useIntegratedWrapper = type === "a12" || rightActionsDisplay === "inline";
229
247
  const cardContent = /* @__PURE__ */ React.createElement("div", {
230
248
  className: classNames(PREFIX, `${PREFIX}--${type}`),
231
249
  onClick: (e) => {
@@ -239,7 +257,10 @@ const CartSkuCard = (props) => {
239
257
  isShowRelatedProduct,
240
258
  isShowDelete
241
259
  }, content) : content);
242
- return /* @__PURE__ */ React.createElement("div", { className: classNames(`${PREFIX}-wrapper-container`, { [`${PREFIX}-wrapper-container--inline`]: rightActionsDisplay === "inline" }) }, rightActionsDisplay === "inline" ? /* @__PURE__ */ React.createElement("div", { className: classNames(`${PREFIX}-wrapper`, `${PREFIX}-wrapper--inline`) }, cardContent) : /* @__PURE__ */ React.createElement(SwipeAction, {
260
+ return /* @__PURE__ */ React.createElement("div", { className: classNames(`${PREFIX}-wrapper-container`, {
261
+ [`${PREFIX}-wrapper-container--inline`]: useIntegratedWrapper,
262
+ [`${PREFIX}-wrapper-container--a12`]: type === "a12"
263
+ }) }, useIntegratedWrapper ? /* @__PURE__ */ React.createElement("div", { className: classNames(`${PREFIX}-wrapper`, `${PREFIX}-wrapper--inline`, type === "a12" && `pisell-cart-sku-card-wrapper--a12`) }, cardContent) : /* @__PURE__ */ React.createElement(SwipeAction, {
243
264
  closeOnAction: false,
244
265
  className: classNames(`${PREFIX}-wrapper`),
245
266
  rightActions: _rightActions,
@@ -3,6 +3,10 @@
3
3
  width: 100%;
4
4
  min-width: 0;
5
5
  }
6
+
7
+ &--a12 {
8
+ container-type: inline-size;
9
+ }
6
10
  }
7
11
 
8
12
  .pisell-cart-sku-card-wrapper {
@@ -15,6 +19,14 @@
15
19
  width: 100%;
16
20
  overflow: hidden;
17
21
  }
22
+
23
+
24
+ &--a12 {
25
+ border: 0;
26
+ border-radius: 18px;
27
+ background: transparent;
28
+ overflow: visible;
29
+ }
18
30
  }
19
31
 
20
32
  .pisell-cart-sku-card__main-row {
@@ -52,6 +64,12 @@
52
64
  cursor: pointer;
53
65
  }
54
66
 
67
+ &--a12 {
68
+ display: block;
69
+ padding: 0;
70
+ gap: 0;
71
+ }
72
+
55
73
  &__delete-btn {
56
74
  cursor: pointer;
57
75
  position: absolute;
@@ -0,0 +1,55 @@
1
+ import { CSSProperties, ReactNode } from "react";
2
+
3
+ //#region src/components/productCard/cartSkuCard/types.d.ts
4
+ type CartSkuCardVariant = 'a2' | 'a5' | 'a9' | 'a12';
5
+ interface CartSkuCardA12Display {
6
+ eyebrow?: ReactNode;
7
+ quantityText?: ReactNode;
8
+ }
9
+ interface CartSkuCardSlotContext {
10
+ item: any;
11
+ disabled: boolean;
12
+ }
13
+ interface CartSkuCardA12Slots {
14
+ quantityControl?: (context: CartSkuCardSlotContext) => ReactNode;
15
+ actionRail?: (context: CartSkuCardSlotContext & {
16
+ defaultPrice: ReactNode;
17
+ defaultEdit: ReactNode;
18
+ defaultQuantityControl: ReactNode;
19
+ }) => ReactNode;
20
+ specifications?: (context: CartSkuCardSlotContext & {
21
+ defaultSpecifications: ReactNode;
22
+ }) => ReactNode;
23
+ }
24
+ interface CartSkuCardA12Tokens {
25
+ background: string;
26
+ borderColor: string;
27
+ borderRadius: string;
28
+ minHeight: string;
29
+ mediaWidth: string;
30
+ actionRailWidth: string;
31
+ contentPadding: string;
32
+ actionRailPadding: string;
33
+ accentColor: string;
34
+ titleColor: string;
35
+ titleFontSize: string;
36
+ titleFontWeight: number;
37
+ priceColor: string;
38
+ priceFontSize: string;
39
+ optionBackground: string;
40
+ optionLabelColor: string;
41
+ optionValueColor: string;
42
+ optionGap: string;
43
+ shadow: string;
44
+ }
45
+ interface CartSkuCardA12Presentation {
46
+ density?: 'compact' | 'comfortable';
47
+ optionColumns?: 1 | 2 | 3;
48
+ mediaFit?: 'cover' | 'contain';
49
+ contentAlign?: 'start' | 'center';
50
+ className?: string;
51
+ style?: CSSProperties;
52
+ tokens?: Partial<CartSkuCardA12Tokens>;
53
+ }
54
+ //#endregion
55
+ export { CartSkuCardA12Display, CartSkuCardA12Presentation, CartSkuCardA12Slots, CartSkuCardVariant };
@@ -0,0 +1,124 @@
1
+ import { _objectSpread2 } from "../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
+ import IconFont from "../../../../iconfont/index.js";
3
+ import Weighing from "../../components/weighing/index.js";
4
+ import { PREFIX } from "../../index.js";
5
+ import React, { useMemo } from "react";
6
+ import { formatAmount, image, locales, resolveWeighingSnapshot } from "@pisell/utils";
7
+ import classNames from "classnames";
8
+ import "./index.less";
9
+ //#region src/components/productCard/cartSkuCard/variants/A12/index.tsx
10
+ const TOKEN_VARIABLES = {
11
+ background: "--pc-a12-bg",
12
+ borderColor: "--pc-a12-border-color",
13
+ borderRadius: "--pc-a12-radius",
14
+ minHeight: "--pc-a12-min-height",
15
+ mediaWidth: "--pc-a12-media-width",
16
+ actionRailWidth: "--pc-a12-rail-width",
17
+ contentPadding: "--pc-a12-content-padding",
18
+ actionRailPadding: "--pc-a12-rail-padding",
19
+ accentColor: "--pc-a12-accent",
20
+ titleColor: "--pc-a12-title-color",
21
+ titleFontSize: "--pc-a12-title-size",
22
+ titleFontWeight: "--pc-a12-title-weight",
23
+ priceColor: "--pc-a12-price-color",
24
+ priceFontSize: "--pc-a12-price-size",
25
+ optionBackground: "--pc-a12-option-bg",
26
+ optionLabelColor: "--pc-a12-option-label-color",
27
+ optionValueColor: "--pc-a12-option-value-color",
28
+ optionGap: "--pc-a12-option-gap",
29
+ shadow: "--pc-a12-shadow"
30
+ };
31
+ /** 复用其它变体使用的 options,只在展示阶段合并同组已选项。 */
32
+ function resolveSpecifications(dataSource) {
33
+ if (!Array.isArray(dataSource === null || dataSource === void 0 ? void 0 : dataSource.options)) return [];
34
+ const groups = /* @__PURE__ */ new Map();
35
+ dataSource.options.forEach((option, index) => {
36
+ var _ref, _option$name, _ref2, _option$quantity, _ref3, _ref4, _option$option_group_, _ref5, _ref6, _ref7, _option$option_group_2;
37
+ const name = (_ref = (_option$name = option === null || option === void 0 ? void 0 : option.name) !== null && _option$name !== void 0 ? _option$name : option === null || option === void 0 ? void 0 : option.title) !== null && _ref !== void 0 ? _ref : option === null || option === void 0 ? void 0 : option.variant_item_name;
38
+ if (name === void 0 || name === null || name === "") return;
39
+ const quantity = Math.max(1, Number((_ref2 = (_option$quantity = option.quantity) !== null && _option$quantity !== void 0 ? _option$quantity : option.num) !== null && _ref2 !== void 0 ? _ref2 : 1));
40
+ const value = quantity > 1 ? `${String(name)} × ${quantity}` : name;
41
+ const groupKey = String((_ref3 = (_ref4 = (_option$option_group_ = option.option_group_id) !== null && _option$option_group_ !== void 0 ? _option$option_group_ : option.group_id) !== null && _ref4 !== void 0 ? _ref4 : option.variant_group_id) !== null && _ref3 !== void 0 ? _ref3 : `option-${index}`);
42
+ const label = (_ref5 = (_ref6 = (_ref7 = (_option$option_group_2 = option.option_group_name) !== null && _option$option_group_2 !== void 0 ? _option$option_group_2 : option.group_name) !== null && _ref7 !== void 0 ? _ref7 : option.option_group_title) !== null && _ref6 !== void 0 ? _ref6 : option.group_title) !== null && _ref5 !== void 0 ? _ref5 : option.variant_group_name;
43
+ const current = groups.get(groupKey);
44
+ if (current) {
45
+ current.values.push(value);
46
+ if (!current.label && label) current.label = label;
47
+ return;
48
+ }
49
+ groups.set(groupKey, _objectSpread2(_objectSpread2({ key: groupKey }, label ? { label } : {}), {}, { values: [value] }));
50
+ });
51
+ return Array.from(groups.values()).map((group) => ({
52
+ key: group.key,
53
+ label: group.label,
54
+ value: group.values.map(String).join(", ")
55
+ }));
56
+ }
57
+ function getPresentationStyle(presentation) {
58
+ const style = _objectSpread2({}, (presentation === null || presentation === void 0 ? void 0 : presentation.style) || {});
59
+ Object.entries((presentation === null || presentation === void 0 ? void 0 : presentation.tokens) || {}).forEach(([key, value]) => {
60
+ if (value !== void 0) style[TOKEN_VARIABLES[key]] = value;
61
+ });
62
+ style["--pc-a12-option-columns"] = (presentation === null || presentation === void 0 ? void 0 : presentation.optionColumns) || 2;
63
+ return style;
64
+ }
65
+ const A12 = ({ dataSource, isShowImage = true, isShowDelete = false, isShowOriginalPrice = false, isShowEditProduct = false, disabled = false, disabledEditClick = false, slots, presentation, onDelete, onEditProduct }) => {
66
+ var _ref8, _dataSource$num, _dataSource$total, _dataSource$origin_to;
67
+ const display = (dataSource === null || dataSource === void 0 ? void 0 : dataSource.a12) || {};
68
+ const specificationsData = useMemo(() => resolveSpecifications(dataSource), [dataSource]);
69
+ const weighingInfo = useMemo(() => resolveWeighingSnapshot(dataSource), [dataSource]);
70
+ const quantity = Number((_ref8 = (_dataSource$num = dataSource === null || dataSource === void 0 ? void 0 : dataSource.num) !== null && _dataSource$num !== void 0 ? _dataSource$num : dataSource === null || dataSource === void 0 ? void 0 : dataSource.quantity) !== null && _ref8 !== void 0 ? _ref8 : 1) || 1;
71
+ const lineTotal = Number((_dataSource$total = dataSource === null || dataSource === void 0 ? void 0 : dataSource.total) !== null && _dataSource$total !== void 0 ? _dataSource$total : 0) * quantity - Number((dataSource === null || dataSource === void 0 ? void 0 : dataSource.totalDifference) || 0);
72
+ const originalTotal = Number((_dataSource$origin_to = dataSource === null || dataSource === void 0 ? void 0 : dataSource.origin_total) !== null && _dataSource$origin_to !== void 0 ? _dataSource$origin_to : 0) * quantity;
73
+ const symbol = dataSource === null || dataSource === void 0 ? void 0 : dataSource.symbol;
74
+ const slotContext = useMemo(() => ({
75
+ item: dataSource,
76
+ disabled
77
+ }), [dataSource, disabled]);
78
+ const style = useMemo(() => getPresentationStyle(presentation), [presentation]);
79
+ const defaultSpecifications = specificationsData.length ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__specifications` }, specificationsData.map((specification) => /* @__PURE__ */ React.createElement("div", {
80
+ className: `${PREFIX}-a12__specification`,
81
+ key: specification.key
82
+ }, specification.label ? /* @__PURE__ */ React.createElement("span", { className: `${PREFIX}-a12__specification-label` }, specification.label) : null, /* @__PURE__ */ React.createElement("strong", { className: `${PREFIX}-a12__specification-value` }, specification.value)))) : (dataSource === null || dataSource === void 0 ? void 0 : dataSource.product_option_string) ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__specification-summary` }, dataSource.product_option_string) : null;
83
+ const specifications = (slots === null || slots === void 0 ? void 0 : slots.specifications) ? slots.specifications(_objectSpread2(_objectSpread2({}, slotContext), {}, { defaultSpecifications })) : defaultSpecifications;
84
+ const defaultPrice = /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__price` }, /* @__PURE__ */ React.createElement("strong", null, formatAmount(lineTotal, 2, symbol)), isShowOriginalPrice && originalTotal > 0 && originalTotal !== lineTotal ? /* @__PURE__ */ React.createElement("del", null, formatAmount(originalTotal, 2, symbol)) : null);
85
+ const defaultEdit = Boolean(isShowEditProduct && onEditProduct) ? /* @__PURE__ */ React.createElement("button", {
86
+ type: "button",
87
+ className: `${PREFIX}-a12__edit`,
88
+ disabled: disabled || disabledEditClick,
89
+ onClick: (event) => {
90
+ event.preventDefault();
91
+ event.stopPropagation();
92
+ onEditProduct === null || onEditProduct === void 0 || onEditProduct(dataSource);
93
+ }
94
+ }, locales.getText("pisell2.product.card.edit")) : null;
95
+ const defaultQuantityControl = (slots === null || slots === void 0 ? void 0 : slots.quantityControl) ? slots.quantityControl(slotContext) : /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__quantity-fallback` }, isShowDelete && onDelete ? /* @__PURE__ */ React.createElement("button", {
96
+ type: "button",
97
+ "aria-label": "Delete item",
98
+ disabled,
99
+ onClick: (event) => {
100
+ event.preventDefault();
101
+ event.stopPropagation();
102
+ onDelete(dataSource);
103
+ }
104
+ }, /* @__PURE__ */ React.createElement(IconFont, { type: "pisell2-trash-01" })) : null, /* @__PURE__ */ React.createElement("span", null, display.quantityText || `× ${quantity}`));
105
+ const defaultActionRail = /* @__PURE__ */ React.createElement("aside", { className: `${PREFIX}-a12__rail` }, defaultPrice, defaultEdit, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__quantity-control` }, defaultQuantityControl));
106
+ const actionRail = (slots === null || slots === void 0 ? void 0 : slots.actionRail) ? slots.actionRail(_objectSpread2(_objectSpread2({}, slotContext), {}, {
107
+ defaultPrice,
108
+ defaultEdit,
109
+ defaultQuantityControl
110
+ })) : defaultActionRail;
111
+ return /* @__PURE__ */ React.createElement("div", {
112
+ className: classNames(`${PREFIX}-a12`, `${PREFIX}-a12--${(presentation === null || presentation === void 0 ? void 0 : presentation.density) || "comfortable"}`, `${PREFIX}-a12--align-${(presentation === null || presentation === void 0 ? void 0 : presentation.contentAlign) || "start"}`, !isShowImage && `pisell-cart-sku-card-a12--without-media`, presentation === null || presentation === void 0 ? void 0 : presentation.className),
113
+ style
114
+ }, isShowImage ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__media` }, (dataSource === null || dataSource === void 0 ? void 0 : dataSource.image) ? /* @__PURE__ */ React.createElement("img", {
115
+ alt: "",
116
+ src: image.ali(dataSource.image, 320),
117
+ style: { objectFit: (presentation === null || presentation === void 0 ? void 0 : presentation.mediaFit) || "cover" }
118
+ }) : /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true" }, String((dataSource === null || dataSource === void 0 ? void 0 : dataSource.name) || "").slice(0, 2))) : null, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__content` }, display.eyebrow ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__eyebrow` }, display.eyebrow) : null, /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__name` }, dataSource === null || dataSource === void 0 ? void 0 : dataSource.name), weighingInfo ? /* @__PURE__ */ React.createElement("div", { className: `${PREFIX}-a12__weighing` }, /* @__PURE__ */ React.createElement(Weighing, {
119
+ dataSource: weighingInfo,
120
+ symbol
121
+ })) : null, specifications), actionRail);
122
+ };
123
+ //#endregion
124
+ export { A12 as default };
@@ -0,0 +1,245 @@
1
+ .pisell-cart-sku-card-a12 {
2
+ --pc-a12-bg: #fff;
3
+ --pc-a12-border-color: #e4e7ec;
4
+ --pc-a12-radius: 18px;
5
+ --pc-a12-min-height: 164px;
6
+ --pc-a12-media-width: 228px;
7
+ --pc-a12-rail-width: 174px;
8
+ --pc-a12-content-padding: 20px 22px;
9
+ --pc-a12-rail-padding: 18px 20px;
10
+ --pc-a12-accent: #b20d12;
11
+ --pc-a12-title-color: #101828;
12
+ --pc-a12-title-size: 32px;
13
+ --pc-a12-title-weight: 800;
14
+ --pc-a12-price-color: var(--pc-a12-accent);
15
+ --pc-a12-price-size: 30px;
16
+ --pc-a12-option-bg: #f5f6f8;
17
+ --pc-a12-option-label-color: #667085;
18
+ --pc-a12-option-value-color: #101828;
19
+ --pc-a12-option-gap: 6px;
20
+ --pc-a12-shadow: 0 12px 28px rgba(16, 24, 40, 0.08);
21
+
22
+ display: grid;
23
+ grid-template-columns:
24
+ var(--pc-a12-media-width)
25
+ minmax(0, 1fr)
26
+ var(--pc-a12-rail-width);
27
+ min-height: var(--pc-a12-min-height);
28
+ overflow: hidden;
29
+ border: 1px solid var(--pc-a12-border-color);
30
+ border-radius: var(--pc-a12-radius);
31
+ background: var(--pc-a12-bg);
32
+ box-shadow: var(--pc-a12-shadow);
33
+ hyphens: none;
34
+ overflow-wrap: normal;
35
+ word-break: normal;
36
+
37
+ &--without-media {
38
+ grid-template-columns: minmax(0, 1fr) var(--pc-a12-rail-width);
39
+ }
40
+
41
+ &__media {
42
+ position: relative;
43
+ display: grid;
44
+ min-height: var(--pc-a12-min-height);
45
+ place-items: center;
46
+ overflow: hidden;
47
+ background: #f2f4f7;
48
+ color: var(--pc-a12-accent);
49
+ font-size: 32px;
50
+ font-weight: 800;
51
+
52
+ img {
53
+ position: absolute;
54
+ inset: 0;
55
+ display: block;
56
+ width: 100%;
57
+ height: 100%;
58
+ min-height: 0;
59
+ }
60
+ }
61
+
62
+ &__content {
63
+ display: flex;
64
+ min-width: 0;
65
+ flex-direction: column;
66
+ justify-content: flex-start;
67
+ padding: var(--pc-a12-content-padding);
68
+ }
69
+
70
+ &--align-center &__content {
71
+ justify-content: center;
72
+ }
73
+
74
+ &__eyebrow {
75
+ overflow: hidden;
76
+ margin-bottom: 4px;
77
+ color: var(--pc-a12-accent);
78
+ font-size: 14px;
79
+ font-weight: 800;
80
+ line-height: 20px;
81
+ text-overflow: ellipsis;
82
+ text-transform: uppercase;
83
+ white-space: nowrap;
84
+ }
85
+
86
+ &__name {
87
+ min-width: 0;
88
+ overflow: hidden;
89
+ color: var(--pc-a12-title-color);
90
+ font-size: var(--pc-a12-title-size);
91
+ font-weight: var(--pc-a12-title-weight);
92
+ line-height: 1.15;
93
+ text-overflow: ellipsis;
94
+ white-space: nowrap;
95
+ }
96
+
97
+ &__weighing {
98
+ min-width: 0;
99
+ margin-top: 8px;
100
+ }
101
+
102
+ &__specifications {
103
+ display: grid;
104
+ grid-template-columns: repeat(
105
+ var(--pc-a12-option-columns, 2),
106
+ minmax(0, 1fr)
107
+ );
108
+ gap: var(--pc-a12-option-gap);
109
+ margin-top: 10px;
110
+ }
111
+
112
+ &__specification,
113
+ &__specification-summary {
114
+ min-width: 0;
115
+ padding: 7px 9px;
116
+ border-radius: 7px;
117
+ background: var(--pc-a12-option-bg);
118
+ }
119
+
120
+ &__specification {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 2px;
124
+ }
125
+
126
+ &__specification-label {
127
+ overflow: hidden;
128
+ color: var(--pc-a12-option-label-color);
129
+ font-size: 11px;
130
+ font-weight: 700;
131
+ line-height: 16px;
132
+ text-overflow: ellipsis;
133
+ white-space: nowrap;
134
+ }
135
+
136
+ &__specification-value,
137
+ &__specification-summary {
138
+ overflow: hidden;
139
+ color: var(--pc-a12-option-value-color);
140
+ font-size: 16px;
141
+ font-weight: 700;
142
+ line-height: 20px;
143
+ text-overflow: ellipsis;
144
+ white-space: nowrap;
145
+ }
146
+
147
+ &__rail {
148
+ display: flex;
149
+ min-width: 0;
150
+ flex-direction: column;
151
+ align-items: center;
152
+ justify-content: center;
153
+ padding: var(--pc-a12-rail-padding);
154
+ border-left: 1px solid var(--pc-a12-border-color);
155
+ }
156
+
157
+ &__price {
158
+ display: flex;
159
+ flex-direction: column;
160
+ align-items: center;
161
+ color: var(--pc-a12-price-color);
162
+
163
+ strong {
164
+ font-size: var(--pc-a12-price-size);
165
+ font-weight: 800;
166
+ line-height: 1.15;
167
+ white-space: nowrap;
168
+ }
169
+
170
+ del {
171
+ color: #667085;
172
+ font-size: 13px;
173
+ }
174
+ }
175
+
176
+ &__edit {
177
+ min-width: 62px;
178
+ min-height: 38px;
179
+ margin-top: 10px;
180
+ padding: 7px 14px;
181
+ border: 1px solid #f5b7ba;
182
+ border-radius: 999px;
183
+ background: #fff;
184
+ color: var(--pc-a12-accent);
185
+ font: inherit;
186
+ font-size: 14px;
187
+ font-weight: 700;
188
+ white-space: nowrap;
189
+ cursor: pointer;
190
+
191
+ &:disabled {
192
+ cursor: not-allowed;
193
+ opacity: 0.5;
194
+ }
195
+ }
196
+
197
+ &__quantity-control {
198
+ display: flex;
199
+ width: 100%;
200
+ min-height: 44px;
201
+ align-items: center;
202
+ justify-content: center;
203
+ margin-top: 10px;
204
+ padding-top: 10px;
205
+ }
206
+
207
+ &__quantity-fallback {
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ gap: 16px;
212
+ font-weight: 700;
213
+
214
+ button {
215
+ display: grid;
216
+ width: 40px;
217
+ height: 40px;
218
+ place-items: center;
219
+ border: 1px solid #f5b7ba;
220
+ border-radius: 50%;
221
+ background: #fff;
222
+ color: var(--pc-a12-accent);
223
+ cursor: pointer;
224
+ }
225
+ }
226
+
227
+ &--compact {
228
+ --pc-a12-min-height: 132px;
229
+ --pc-a12-media-width: 124px;
230
+ --pc-a12-rail-width: 156px;
231
+ --pc-a12-content-padding: 15px 18px;
232
+ --pc-a12-rail-padding: 14px 16px;
233
+ --pc-a12-price-size: 25px;
234
+ }
235
+ }
236
+
237
+ @container (max-width: 620px) {
238
+ .pisell-cart-sku-card-a12 {
239
+ --pc-a12-media-width: 112px;
240
+ --pc-a12-rail-width: 150px;
241
+ --pc-a12-content-padding: 14px;
242
+ --pc-a12-price-size: 24px;
243
+ --pc-a12-option-columns: 1;
244
+ }
245
+ }
@@ -34,6 +34,7 @@ const _excluded = [
34
34
  "holderOptions",
35
35
  "onBookingStatusChange",
36
36
  "onAddTimeProductCard",
37
+ "a12UnsupportedFallback",
37
38
  "onAction",
38
39
  "onDelete",
39
40
  "onNote",
@@ -45,6 +46,7 @@ const isBookingItem = (dataSource) => {
45
46
  var _dataSource$_extend;
46
47
  return Boolean((dataSource === null || dataSource === void 0 || (_dataSource$_extend = dataSource._extend) === null || _dataSource$_extend === void 0 ? void 0 : _dataSource$_extend.product) || (dataSource === null || dataSource === void 0 ? void 0 : dataSource.booking_id) || (dataSource === null || dataSource === void 0 ? void 0 : dataSource.appointment_status) || (dataSource === null || dataSource === void 0 ? void 0 : dataSource.start_date));
47
48
  };
49
+ const resolveLineItemType = ({ requestedType, itemKind, hasBundle, fallback = "a9" }) => requestedType === "a12" && (itemKind === "booking" || hasBundle) ? fallback : requestedType;
48
50
  const translateText = (text, translationOriginal) => {
49
51
  if (typeof text === "string") return text;
50
52
  if (!text) return "";
@@ -123,14 +125,36 @@ const mapLineItemOptions = (options, translationOriginal) => options.map((option
123
125
  num: (_ref2 = (_option$num2 = option.num) !== null && _option$num2 !== void 0 ? _option$num2 : option.quantity) !== null && _ref2 !== void 0 ? _ref2 : 1
124
126
  });
125
127
  });
128
+ const getFirstDisplayText = (candidates, translationOriginal) => {
129
+ for (const candidate of candidates) {
130
+ const translated = translateText(candidate, translationOriginal).trim();
131
+ if (translated) return translated;
132
+ }
133
+ return "";
134
+ };
135
+ const resolveA12Eyebrow = (product, translationOriginal) => {
136
+ var _product$a, _product$metadata2, _product$metadata3, _categories$find, _categories$;
137
+ const categories = Array.isArray(product === null || product === void 0 ? void 0 : product.categories) ? product.categories : Array.isArray(product === null || product === void 0 ? void 0 : product.product_categories) ? product.product_categories : [];
138
+ return getFirstDisplayText([
139
+ product === null || product === void 0 || (_product$a = product.a12) === null || _product$a === void 0 ? void 0 : _product$a.eyebrow,
140
+ product === null || product === void 0 ? void 0 : product.category_name,
141
+ product === null || product === void 0 ? void 0 : product.product_category_name,
142
+ product === null || product === void 0 ? void 0 : product.product_type_name,
143
+ product === null || product === void 0 || (_product$metadata2 = product.metadata) === null || _product$metadata2 === void 0 ? void 0 : _product$metadata2.category_name,
144
+ product === null || product === void 0 || (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.product_category_name,
145
+ (_categories$find = categories.find((category) => category === null || category === void 0 ? void 0 : category.direct)) === null || _categories$find === void 0 ? void 0 : _categories$find.name,
146
+ (_categories$ = categories[0]) === null || _categories$ === void 0 ? void 0 : _categories$.name
147
+ ], translationOriginal);
148
+ };
126
149
  const convertProductToLineItemProduct = (product, translationOriginal, symbol) => {
127
- var _product$metadata2, _ref3, _product$num, _ref4, _product$num2, _product$metadata3, _product$metadata4, _product$discount_lis, _product$discount_lis2, _product$metadata5, _product$metadata6, _ref5, _product$num3;
150
+ var _product$metadata4, _ref3, _product$num, _ref4, _product$num2, _product$metadata5, _product$metadata6, _product$product_opti, _product$product_sku2, _product$discount_lis, _product$discount_lis2, _product$metadata7, _product$metadata8, _ref5, _product$num3;
128
151
  const title = translateText(product.product_title || product.title, translationOriginal);
129
152
  const bundle = (product.product_bundle || []).map((bundleItem) => convertBundle(bundleItem, translationOriginal));
130
153
  const lineOriginTotal = resolveLineOriginTotal(product);
131
154
  const lineOptions = mapLineItemOptions(resolveLineItemOptions(product), translationOriginal);
155
+ const a12Eyebrow = resolveA12Eyebrow(product, translationOriginal);
132
156
  return {
133
- _id: ((_product$metadata2 = product.metadata) === null || _product$metadata2 === void 0 ? void 0 : _product$metadata2.unique_identification_number) || product.order_detail_id || product.product_id,
157
+ _id: ((_product$metadata4 = product.metadata) === null || _product$metadata4 === void 0 ? void 0 : _product$metadata4.unique_identification_number) || product.order_detail_id || product.product_id,
134
158
  id: product.product_id,
135
159
  product_id: product.product_id,
136
160
  product_variant_id: product.product_variant_id,
@@ -141,11 +165,11 @@ const convertProductToLineItemProduct = (product, translationOriginal, symbol) =
141
165
  image: product.cover,
142
166
  num: (_ref3 = (_product$num = product.num) !== null && _product$num !== void 0 ? _product$num : product.product_quantity) !== null && _ref3 !== void 0 ? _ref3 : 1,
143
167
  quantity: (_ref4 = (_product$num2 = product.num) !== null && _product$num2 !== void 0 ? _product$num2 : product.product_quantity) !== null && _ref4 !== void 0 ? _ref4 : 1,
144
- price: (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.source_product_price,
168
+ price: (_product$metadata5 = product.metadata) === null || _product$metadata5 === void 0 ? void 0 : _product$metadata5.source_product_price,
145
169
  total: product.selling_price,
146
170
  origin_total: lineOriginTotal,
147
171
  original_total: lineOriginTotal,
148
- source_product_price: (_product$metadata4 = product.metadata) === null || _product$metadata4 === void 0 ? void 0 : _product$metadata4.source_product_price,
172
+ source_product_price: (_product$metadata6 = product.metadata) === null || _product$metadata6 === void 0 ? void 0 : _product$metadata6.source_product_price,
149
173
  selling_price: product.selling_price,
150
174
  payment_price: product.payment_price,
151
175
  tax_fee: product.tax_fee,
@@ -154,12 +178,13 @@ const convertProductToLineItemProduct = (product, translationOriginal, symbol) =
154
178
  product_sku: product.product_sku,
155
179
  product_bundle: bundle,
156
180
  bundle,
157
- product_option_string: product.product_option_string,
181
+ product_option_string: (_product$product_opti = product.product_option_string) !== null && _product$product_opti !== void 0 ? _product$product_opti : (_product$product_sku2 = product.product_sku) === null || _product$product_sku2 === void 0 ? void 0 : _product$product_sku2.product_option_string,
158
182
  options: lineOptions,
183
+ a12: _objectSpread2(_objectSpread2({}, product.a12 || {}), a12Eyebrow ? { eyebrow: a12Eyebrow } : {}),
159
184
  discount_list: product.discount_list,
160
185
  promotions: product.promotions,
161
- discount_reason: (_product$discount_lis = (_product$discount_lis2 = product.discount_list) === null || _product$discount_lis2 === void 0 || (_product$discount_lis2 = _product$discount_lis2.find((d) => (d === null || d === void 0 ? void 0 : d.type) === "product")) === null || _product$discount_lis2 === void 0 || (_product$discount_lis2 = _product$discount_lis2.discount) === null || _product$discount_lis2 === void 0 ? void 0 : _product$discount_lis2.message) !== null && _product$discount_lis !== void 0 ? _product$discount_lis : (_product$metadata5 = product.metadata) === null || _product$metadata5 === void 0 ? void 0 : _product$metadata5.product_discount_reason,
162
- isGift: Boolean(product.gift_card || product.isGift || product._isGiftPromotion || ((_product$metadata6 = product.metadata) === null || _product$metadata6 === void 0 ? void 0 : _product$metadata6._giftInfo) || product._giftInfo),
186
+ discount_reason: (_product$discount_lis = (_product$discount_lis2 = product.discount_list) === null || _product$discount_lis2 === void 0 || (_product$discount_lis2 = _product$discount_lis2.find((d) => (d === null || d === void 0 ? void 0 : d.type) === "product")) === null || _product$discount_lis2 === void 0 || (_product$discount_lis2 = _product$discount_lis2.discount) === null || _product$discount_lis2 === void 0 ? void 0 : _product$discount_lis2.message) !== null && _product$discount_lis !== void 0 ? _product$discount_lis : (_product$metadata7 = product.metadata) === null || _product$metadata7 === void 0 ? void 0 : _product$metadata7.product_discount_reason,
187
+ isGift: Boolean(product.gift_card || product.isGift || product._isGiftPromotion || ((_product$metadata8 = product.metadata) === null || _product$metadata8 === void 0 ? void 0 : _product$metadata8._giftInfo) || product._giftInfo),
163
188
  giftData: product.giftData,
164
189
  _origin: product,
165
190
  _extend: {
@@ -179,7 +204,7 @@ const convertProductToLineItemProduct = (product, translationOriginal, symbol) =
179
204
  };
180
205
  const LineItem = (props) => {
181
206
  var _context$appHelper$ut, _context$appHelper$ut2, _context$appHelper$ut3, _context$appHelper$ut4, _dataSource$_extend2, _dataSource$_extend4;
182
- const { dataSource = defaultValue.dataSource, itemType, type = "a9", isShowBookingHeader, rightActions = [], rightActionsDisplay = "swipe", escapeDom, isShowImage = defaultValue.isShowImage, isShowDelete = defaultValue.isShowDelete, isShowInlineDelete = isShowDelete, isShowNote = defaultValue.isShowNote, isShowAmountFooter = defaultValue.isShowAmountFooter, disabledClick = defaultValue.disabledClick, disabledEdit = defaultValue.disabledEdit, disabledNoteEdit = disabledEdit, statusOptions = [], statusLoading = false, statusDisabled = false, isShowRelatedProduct = true, holderOptions, onBookingStatusChange, onAddTimeProductCard, onAction, onDelete, onNote, onCard, onPromotion, onGift } = props, other = _objectWithoutProperties(props, _excluded);
207
+ const { dataSource = defaultValue.dataSource, itemType, type = "a9", isShowBookingHeader, rightActions = [], rightActionsDisplay = "swipe", escapeDom, isShowImage = defaultValue.isShowImage, isShowDelete = defaultValue.isShowDelete, isShowInlineDelete = isShowDelete, isShowNote = defaultValue.isShowNote, isShowAmountFooter = defaultValue.isShowAmountFooter, disabledClick = defaultValue.disabledClick, disabledEdit = defaultValue.disabledEdit, disabledNoteEdit = disabledEdit, statusOptions = [], statusLoading = false, statusDisabled = false, isShowRelatedProduct = true, holderOptions, onBookingStatusChange, onAddTimeProductCard, a12UnsupportedFallback = "a9", onAction, onDelete, onNote, onCard, onPromotion, onGift } = props, other = _objectWithoutProperties(props, _excluded);
183
208
  const itemKind = itemType || (isBookingItem(dataSource) ? "booking" : "product");
184
209
  const context = useEngineContext();
185
210
  const translationOriginal = useTranslationOriginal();
@@ -210,9 +235,15 @@ const LineItem = (props) => {
210
235
  symbol,
211
236
  translationOriginal
212
237
  ]);
238
+ const resolvedType = resolveLineItemType({
239
+ requestedType: type,
240
+ itemKind,
241
+ hasBundle: Boolean(Array.isArray(dataSource === null || dataSource === void 0 ? void 0 : dataSource.product_bundle) && dataSource.product_bundle.length || Array.isArray(dataSource === null || dataSource === void 0 ? void 0 : dataSource.bundle) && dataSource.bundle.length),
242
+ fallback: a12UnsupportedFallback
243
+ });
213
244
  if (itemKind === "product") return /* @__PURE__ */ React.createElement(CartSkuCard, _objectSpread2(_objectSpread2({}, other), {}, {
214
245
  dataSource: productDataSource,
215
- type,
246
+ type: resolvedType,
216
247
  rightActions,
217
248
  rightActionsDisplay,
218
249
  escapeDom,
@@ -233,8 +264,8 @@ const LineItem = (props) => {
233
264
  }));
234
265
  return /* @__PURE__ */ React.createElement(BookingLineItem, _objectSpread2(_objectSpread2({}, other), {}, {
235
266
  dataSource,
236
- type,
237
- cartSkuType: type,
267
+ type: resolvedType,
268
+ cartSkuType: resolvedType,
238
269
  isShowBookingHeader,
239
270
  relatedProductDataSource,
240
271
  addTimeProductDataSources,