@pisell/private-materials 6.12.236 → 6.12.237

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.js +12 -12
  6. package/build/lowcode/view.js +12 -12
  7. package/es/components/bigSale/components/BookingFloatingPanel/useBookingPanelController.js +1 -0
  8. package/es/components/bigSale/components/TimeBar/index.js +1 -0
  9. package/es/components/bigSale/dialog.js +1 -0
  10. package/es/components/bigSale/hooks/useBigSaleContext.js +1 -0
  11. package/es/components/bigSale/hooks/useSelectFloorMapResourceForBigSale.js +1 -0
  12. package/es/components/bigSale/index.js +1 -0
  13. package/es/components/bigSale/templates/Kiosk/index.js +1 -0
  14. package/es/components/checkout/PaymentModal.js +111 -2
  15. package/es/components/pay/toC/PaymentMethods/MWCreditCard/Add/index.js +10 -3
  16. package/es/components/pay/toC/utils.js +5 -1
  17. package/es/components/sharedSecondaryBigSale/SharedSecondaryBigSaleReceiver.js +1 -0
  18. package/es/index.js +2 -0
  19. package/es/plus/multiCurrencySettlement/index.js +1 -1
  20. package/es/plus/pisellReservation/data/bookingToReservationTables.js +1 -1
  21. package/es/plus/pisellReservation/floorMap/floorPlanApi.js +1 -1
  22. package/es/plus/pisellReservation/floorMap/reservationMock.js +1 -1
  23. package/es/plus/pisellReservation/index.js +17 -0
  24. package/es/plus/saleDetail/Base.js +1 -0
  25. package/es/plus/saleDetail/components/Client/hooks/useClientSelectorProps.js +1 -0
  26. package/es/plus/saleDetail/components/DetailActions/PrintAction.js +1 -0
  27. package/es/plus/saleDetail/components/DetailActions/index.js +1 -0
  28. package/es/plus/saleDetail/components/SummaryFinancialSections/index.js +1 -0
  29. package/es/plus/saleDetail/index.js +1 -0
  30. package/es/plus/saleDetail/tmpl/B/components/Dish/index.js +1 -0
  31. package/es/plus/saleDetail/tmpl/B/components/WalletPass/WalletPassRecordCard.js +1 -1
  32. package/es/plus/saleDetail/tmpl/B/components/WalletPass/utils/format.js +14 -4
  33. package/es/plus/saleDetail/tmpl/B/components/WalletPass/utils/vouchers.js +25 -10
  34. package/es/plus/saleDetail/tmpl/B/index.js +1 -0
  35. package/es/plus/salesSdk/index.js +53 -0
  36. package/es/plus/salesSdk/utils/addProductWithFlowDebounced.js +1 -1
  37. package/es/plus/salesSdk/utils/bookingDate.js +1 -1
  38. package/es/plus/salesSdk/utils/enrichCartLineHolderDisplay.js +1 -1
  39. package/es/pro/Login2.0/AuthModal.d.ts +1 -1
  40. package/es/pro/Login2.0/index.d.ts +2 -2
  41. package/es/pro/Login2.0/shared/types.d.ts +1 -1
  42. package/es/pro/compensatedPisellContainer/floatingLayer/index.js +13 -1
  43. package/lib/components/checkout/PaymentModal.js +111 -2
  44. package/lib/components/pay/toC/PaymentMethods/MWCreditCard/Add/index.js +10 -3
  45. package/lib/components/pay/toC/utils.js +5 -0
  46. package/lib/plus/saleDetail/tmpl/B/components/WalletPass/WalletPassRecordCard.js +1 -1
  47. package/lib/plus/saleDetail/tmpl/B/components/WalletPass/utils/format.js +16 -3
  48. package/lib/plus/saleDetail/tmpl/B/components/WalletPass/utils/vouchers.js +24 -9
  49. package/lib/pro/compensatedPisellContainer/floatingLayer/index.js +13 -1
  50. package/package.json +3 -3
  51. package/es/private-materials/lowcode/authmodal/meta.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- import { AuthMethodType, VerificationMethod } from "./shared/types.js";
1
+ import { AuthMethodType, EmailAuthConfig, EmailRegistrationVerification, LoginFormData, OAuthConfig, PhoneAuthConfig, RegisterFormData, UIConfig, VerificationMethod } from "./shared/types.js";
2
2
  import { Login2, Login2Config, Login2Events, Login2Props } from "./Login2.js";
3
3
  import { Register2, Register2Config, Register2Events, Register2Props } from "./Register2.js";
4
- import { AuthModal, AuthModalProps } from "./AuthModal.js";
4
+ import { AuthModal } from "./AuthModal.js";
@@ -226,4 +226,4 @@ interface RegisterFormData {
226
226
  verification_token?: string;
227
227
  }
228
228
  //#endregion
229
- export { AuthMethodType, EmailAuthConfig, LegalTermsConfig, LoginFormData, LoginMethodItem, OAuthConfig, PhoneAuthConfig, RegisterFormData, RegistrationMethodItem, UIConfig, VerificationMethod };
229
+ export { AuthMethodType, EmailAuthConfig, EmailRegistrationVerification, LegalTermsConfig, LoginFormData, LoginMethodItem, OAuthConfig, PhoneAuthConfig, RegisterFormData, RegistrationMethodItem, UIConfig, VerificationMethod };
@@ -129,6 +129,17 @@ const getWrapperStyle = (mode, placement, size, width, height) => {
129
129
  }
130
130
  return _objectSpread2({ width: width || 520 }, height ? { height } : null);
131
131
  };
132
+ /**
133
+ * 浮层会被挂到带 transform: scale(...) 的 body 下。modal 的 root 已按
134
+ * `viewport / scale` 做过反向补偿,因此不能再把 vw/% 交给浏览器在另一套
135
+ * viewport 参照系中解析;统一转换成 root 坐标系中的像素值。
136
+ */
137
+ const resolveModalWidth = (mode, width, layoutWidth) => {
138
+ if (mode !== "modal" || typeof width !== "string" || !layoutWidth) return width;
139
+ const match = width.trim().match(/^(\d+(?:\.\d+)?)\s*(vw|%)$/);
140
+ if (!match) return width;
141
+ return layoutWidth * Number(match[1]) / 100;
142
+ };
132
143
  const getWrapperMotionStyle = (mode, placement, motionOpen, bodyScale, viewportSize) => {
133
144
  const visibleStyle = { pointerEvents: "auto" };
134
145
  const hiddenStyle = { pointerEvents: "none" };
@@ -310,10 +321,11 @@ const TransformFloatingLayer = (props) => {
310
321
  ]);
311
322
  const wrapperStyle = useMemo(() => {
312
323
  const scaleX = bodyScale.x || 1;
324
+ const resolvedWidth = resolveModalWidth(mode, width, viewportSize.width / scaleX);
313
325
  const modalScaleStyle = mode === "modal" ? { maxWidth: Math.max((viewportSize.width - 48) / scaleX, 0) } : null;
314
326
  const layoutChangingStyle = mode === "modal" && isLayoutChanging ? { transition: "none" } : null;
315
327
  const skipEnterMotionStyle = skipCurrentEnterMotion ? { transition: "none" } : null;
316
- return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, getWrapperStyle(mode, placement, size, width, height)), modalScaleStyle), style), contentWrapperStyle), styles === null || styles === void 0 ? void 0 : styles.wrapper), getWrapperMotionStyle(mode, placement, effectiveMotionOpen, bodyScale, viewportSize)), layoutChangingStyle), skipEnterMotionStyle);
328
+ return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, getWrapperStyle(mode, placement, size, resolvedWidth, height)), modalScaleStyle), style), contentWrapperStyle), styles === null || styles === void 0 ? void 0 : styles.wrapper), getWrapperMotionStyle(mode, placement, effectiveMotionOpen, bodyScale, viewportSize)), layoutChangingStyle), skipEnterMotionStyle);
317
329
  }, [
318
330
  bodyScale,
319
331
  contentWrapperStyle,
@@ -2705,11 +2705,11 @@ const PaymentModal = ({ open, baseSales, baseSalesModuleName, walletPassMode = "
2705
2705
  }, [interaction, open]);
2706
2706
  const checkoutModalScale = (0, react.useMemo)(() => {
2707
2707
  if (variant === "smallTablet") return {
2708
- width: "98vw",
2708
+ width: "98%",
2709
2709
  heightRatio: .98
2710
2710
  };
2711
2711
  if (variant === "tablet") return {
2712
- width: "98vw",
2712
+ width: "98%",
2713
2713
  heightRatio: .98
2714
2714
  };
2715
2715
  return {
@@ -2986,6 +2986,115 @@ const PaymentModal = ({ open, baseSales, baseSalesModuleName, walletPassMode = "
2986
2986
  if (data === null || data === void 0 || (_data$order_info = data.order_info) === null || _data$order_info === void 0 ? void 0 : _data$order_info.order_note) setOrderNote(data.order_info.order_note);
2987
2987
  }, [data]);
2988
2988
  const logger = require_usePaymentLogger.default();
2989
+ const addPaymentLog = logger === null || logger === void 0 ? void 0 : logger.addLog;
2990
+ const flushPaymentLogs = (0, react.useCallback)(() => {
2991
+ var _logger$storeLog;
2992
+ logger === null || logger === void 0 || (_logger$storeLog = logger.storeLog) === null || _logger$storeLog === void 0 || _logger$storeLog.call(logger, true);
2993
+ }, [logger === null || logger === void 0 ? void 0 : logger.storeLog]);
2994
+ (0, react.useEffect)(() => {
2995
+ var _window$visualViewpor;
2996
+ if (!open || typeof window === "undefined" || typeof document === "undefined") return;
2997
+ const sessionId = `checkout-layout-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2998
+ let lastLoggedAt = 0;
2999
+ const getRect = (selector) => {
3000
+ const element = document.querySelector(selector);
3001
+ if (!element) return null;
3002
+ const rect = element.getBoundingClientRect();
3003
+ return {
3004
+ width: Number(rect.width.toFixed(2)),
3005
+ height: Number(rect.height.toFixed(2)),
3006
+ top: Number(rect.top.toFixed(2)),
3007
+ left: Number(rect.left.toFixed(2)),
3008
+ right: Number(rect.right.toFixed(2)),
3009
+ bottom: Number(rect.bottom.toFixed(2))
3010
+ };
3011
+ };
3012
+ const logLayout = (reason, force = false) => {
3013
+ const now = Date.now();
3014
+ if (!force && now - lastLoggedAt < 120) return;
3015
+ lastLoggedAt = now;
3016
+ try {
3017
+ var _wrapperStyle$width, _wrapperStyle$maxWidt, _wrapperStyle$transfo, _rootStyle$width, _rootStyle$height;
3018
+ const wrapper = document.querySelector(".payment-modal-modal");
3019
+ const root = document.querySelector(".payment-modal-wrapper");
3020
+ const bodyStyle = window.getComputedStyle(document.body);
3021
+ const wrapperStyle = wrapper ? window.getComputedStyle(wrapper) : null;
3022
+ const rootStyle = root ? window.getComputedStyle(root) : null;
3023
+ const viewport = window.visualViewport;
3024
+ addPaymentLog === null || addPaymentLog === void 0 || addPaymentLog({
3025
+ type: "info",
3026
+ title: "Checkout modal layout diagnostic",
3027
+ metadata: {
3028
+ sessionId,
3029
+ reason,
3030
+ timestamp: new Date(now).toISOString(),
3031
+ variant,
3032
+ configuredWidth: checkoutModalScale.width,
3033
+ window: {
3034
+ innerWidth: window.innerWidth,
3035
+ innerHeight: window.innerHeight,
3036
+ documentClientWidth: document.documentElement.clientWidth,
3037
+ documentClientHeight: document.documentElement.clientHeight,
3038
+ devicePixelRatio: window.devicePixelRatio
3039
+ },
3040
+ visualViewport: viewport ? {
3041
+ width: viewport.width,
3042
+ height: viewport.height,
3043
+ scale: viewport.scale,
3044
+ offsetLeft: viewport.offsetLeft,
3045
+ offsetTop: viewport.offsetTop
3046
+ } : null,
3047
+ body: {
3048
+ transform: bodyStyle.transform,
3049
+ zoom: bodyStyle.zoom
3050
+ },
3051
+ modalWrapper: {
3052
+ rect: getRect(".payment-modal-modal"),
3053
+ width: (_wrapperStyle$width = wrapperStyle === null || wrapperStyle === void 0 ? void 0 : wrapperStyle.width) !== null && _wrapperStyle$width !== void 0 ? _wrapperStyle$width : null,
3054
+ maxWidth: (_wrapperStyle$maxWidt = wrapperStyle === null || wrapperStyle === void 0 ? void 0 : wrapperStyle.maxWidth) !== null && _wrapperStyle$maxWidt !== void 0 ? _wrapperStyle$maxWidt : null,
3055
+ transform: (_wrapperStyle$transfo = wrapperStyle === null || wrapperStyle === void 0 ? void 0 : wrapperStyle.transform) !== null && _wrapperStyle$transfo !== void 0 ? _wrapperStyle$transfo : null
3056
+ },
3057
+ floatingRoot: {
3058
+ rect: getRect(".payment-modal-wrapper"),
3059
+ width: (_rootStyle$width = rootStyle === null || rootStyle === void 0 ? void 0 : rootStyle.width) !== null && _rootStyle$width !== void 0 ? _rootStyle$width : null,
3060
+ height: (_rootStyle$height = rootStyle === null || rootStyle === void 0 ? void 0 : rootStyle.height) !== null && _rootStyle$height !== void 0 ? _rootStyle$height : null
3061
+ }
3062
+ }
3063
+ });
3064
+ flushPaymentLogs();
3065
+ } catch (error) {
3066
+ console.warn("Failed to record checkout modal layout diagnostic", error);
3067
+ }
3068
+ };
3069
+ const handleViewportChange = () => logLayout("viewport-change");
3070
+ const bodyObserver = new MutationObserver(() => logLayout("body-mutation"));
3071
+ bodyObserver.observe(document.body, {
3072
+ attributes: true,
3073
+ attributeFilter: ["style", "class"]
3074
+ });
3075
+ logLayout("modal-open", true);
3076
+ const animationFrame = window.requestAnimationFrame(() => logLayout("next-frame", true));
3077
+ const settleTimer = window.setTimeout(() => logLayout("startup-settled", true), 500);
3078
+ window.addEventListener("resize", handleViewportChange);
3079
+ window.addEventListener("orientationchange", handleViewportChange);
3080
+ (_window$visualViewpor = window.visualViewport) === null || _window$visualViewpor === void 0 || _window$visualViewpor.addEventListener("resize", handleViewportChange);
3081
+ return () => {
3082
+ var _window$visualViewpor2;
3083
+ window.cancelAnimationFrame(animationFrame);
3084
+ window.clearTimeout(settleTimer);
3085
+ window.removeEventListener("resize", handleViewportChange);
3086
+ window.removeEventListener("orientationchange", handleViewportChange);
3087
+ (_window$visualViewpor2 = window.visualViewport) === null || _window$visualViewpor2 === void 0 || _window$visualViewpor2.removeEventListener("resize", handleViewportChange);
3088
+ bodyObserver.disconnect();
3089
+ logLayout("modal-close", true);
3090
+ };
3091
+ }, [
3092
+ addPaymentLog,
3093
+ checkoutModalScale.width,
3094
+ flushPaymentLogs,
3095
+ open,
3096
+ variant
3097
+ ]);
2989
3098
  const isLocalOrderCreated = (0, react.useRef)(void 0);
2990
3099
  const unsubscribeRef = (0, react.useRef)(void 0);
2991
3100
  (0, react.useEffect)(() => {
@@ -1,5 +1,6 @@
1
1
  const require_runtime = require("../../../../../../_virtual/_rolldown/runtime.js");
2
2
  const require_asyncToGenerator = require("../../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js");
3
+ const require_utils = require("../../../utils.js");
3
4
  const require_model = require("../../../model.js");
4
5
  let react = require("react");
5
6
  react = require_runtime.__toESM(react);
@@ -57,6 +58,7 @@ const AddMWCreditCard = (props, ref) => {
57
58
  const { onCreate, shopName = "", btnLoading = false } = props;
58
59
  const [open, setOpen] = (0, react.useState)(false);
59
60
  const [form] = antd.Form.useForm();
61
+ const cardIsAmex = require_utils.isAmex(antd.Form.useWatch("card_number", form) || "");
60
62
  const { state } = (0, react.useContext)(require_model.Context);
61
63
  /**
62
64
  * @title: 初始化
@@ -98,7 +100,9 @@ const AddMWCreditCard = (props, ref) => {
98
100
  console.log(_pisell_utils.locales.getText("tocPay.text.enterCardNumber"));
99
101
  return;
100
102
  }
101
- if (values.card_number.replace(/\s/g, "").length < 16) {
103
+ const cardNumber = values.card_number.replace(/\D/g, "");
104
+ const amex = require_utils.isAmex(cardNumber);
105
+ if (cardNumber.length < (amex ? 15 : 16)) {
102
106
  (0, _pisell_materials.PisellToast)({
103
107
  content: _pisell_utils.locales.getText("tocPay.text.enterValidCardNumber"),
104
108
  duration: 2
@@ -135,7 +139,7 @@ const AddMWCreditCard = (props, ref) => {
135
139
  console.log(_pisell_utils.locales.getText("tocPay.text.enterCVV"));
136
140
  return;
137
141
  }
138
- if ((values.card_ccv + "").length < 3) {
142
+ if ((values.card_ccv + "").length !== (amex ? 4 : 3)) {
139
143
  (0, _pisell_materials.PisellToast)({
140
144
  content: _pisell_utils.locales.getText("tocPay.text.enterValidCVV"),
141
145
  duration: 2
@@ -254,7 +258,10 @@ const AddMWCreditCard = (props, ref) => {
254
258
  required: true,
255
259
  message: _pisell_utils.locales.getText("tocPay.text.incorrectSecurityCode")
256
260
  }]
257
- }, /* @__PURE__ */ react.default.createElement(_pisell_materials.PisellInput.SecurityCode, { maxLength: 3 }))), /* @__PURE__ */ react.default.createElement(antd.Col, { span: 24 }, /* @__PURE__ */ react.default.createElement(antd.Form.Item, {
261
+ }, /* @__PURE__ */ react.default.createElement(_pisell_materials.PisellInput.SecurityCode, {
262
+ maxLength: cardIsAmex ? 4 : 3,
263
+ placeholder: cardIsAmex ? "CID" : "CVC"
264
+ }))), /* @__PURE__ */ react.default.createElement(antd.Col, { span: 24 }, /* @__PURE__ */ react.default.createElement(antd.Form.Item, {
258
265
  label: _pisell_utils.locales.getText("tocPay.text.cardholderName"),
259
266
  name: "card_name",
260
267
  rules: [{
@@ -98,6 +98,10 @@ const clientPayment = (params) => {
98
98
  const getUniqueIdempotencyToken = () => {
99
99
  return `${(0, dayjs.default)().format("YYYYMMDDHHmmssSSS")}-${(0, _pisell_utils.getUniqueId)()}`;
100
100
  };
101
+ const isAmex = (str) => {
102
+ const cardNumber = str.replace(/\D/g, "");
103
+ return cardNumber.startsWith("34") || cardNumber.startsWith("37");
104
+ };
101
105
  //#endregion
102
106
  exports.clientPayment = clientPayment;
103
107
  exports.formatFranchiseeRoute = formatFranchiseeRoute;
@@ -106,3 +110,4 @@ exports.formatWalletPassParams = formatWalletPassParams;
106
110
  exports.getAvailableMaxAmount = getAvailableMaxAmount;
107
111
  exports.getIsWalletPassAndTripartitePayment = getIsWalletPassAndTripartitePayment;
108
112
  exports.getUniqueIdempotencyToken = getUniqueIdempotencyToken;
113
+ exports.isAmex = isAmex;
@@ -11,7 +11,7 @@ function WalletPassRecordCard({ record }) {
11
11
  return /* @__PURE__ */ react.default.createElement("article", { className: (0, classnames.default)(PREFIX, {
12
12
  [`${PREFIX}--received`]: isReceived,
13
13
  [`${PREFIX}--used`]: !isReceived
14
- }) }, /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__content` }, !isReceived ? /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__pass-id` }, record.code || "—") : null, /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__badges` }, /* @__PURE__ */ react.default.createElement("span", { className: `${PREFIX}__badge ${PREFIX}__badge--${record.status}` }, record.status)), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__name` }, record.productName || "—"), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__meta` }, record.encoded ? /* @__PURE__ */ react.default.createElement("span", null, _pisell_utils.locales.getText("pisell2.sale-detail.walletpass.code"), ":", " ", record.encoded) : null, record.balanceText ? /* @__PURE__ */ react.default.createElement("span", null, record.balanceText) : null)), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__amount` }, /* @__PURE__ */ react.default.createElement("span", null, record.usageLabel), /* @__PURE__ */ react.default.createElement("strong", null, record.usageValue)));
14
+ }) }, /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__content` }, !isReceived ? /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__pass-id` }, record.code || "—") : null, /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__badges` }, /* @__PURE__ */ react.default.createElement("span", { className: `${PREFIX}__badge ${PREFIX}__badge--${record.status}` }, record.status)), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__name` }, record.productName || "—"), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__meta` }, record.encoded ? /* @__PURE__ */ react.default.createElement("span", null, _pisell_utils.locales.getText("pisell2.sale-detail.walletpass.code"), ":", " ", record.encoded) : null, record.balanceText ? /* @__PURE__ */ react.default.createElement("span", null, record.balanceText) : null)), /* @__PURE__ */ react.default.createElement("div", { className: `${PREFIX}__amount` }, record.usageLabel ? /* @__PURE__ */ react.default.createElement("span", null, record.usageLabel) : null, /* @__PURE__ */ react.default.createElement("strong", null, record.usageValue)));
15
15
  }
16
16
  //#endregion
17
17
  exports.WalletPassRecordCard = WalletPassRecordCard;
@@ -9,6 +9,9 @@ function formatCount(count, locale) {
9
9
  const value = Math.round(count || 0);
10
10
  return locale === "zh" ? `${value} 次` : `${value} use${value === 1 ? "" : "s"}`;
11
11
  }
12
+ function formatCountValue(count) {
13
+ return String(Math.round(count || 0));
14
+ }
12
15
  function formatPoints(points, locale) {
13
16
  const value = formatPlainNumber(points);
14
17
  return locale === "zh" ? `${value} 积分` : `${value} pts`;
@@ -22,12 +25,19 @@ function getUsageValue(amount, unit, symbol, locale) {
22
25
  if (unit === "count") return formatCount(amount, locale);
23
26
  return formatMoney(amount, symbol);
24
27
  }
25
- function formatBalanceText(amount, unit, symbol, locale, remainingUses) {
28
+ function formatPercentage(amount) {
29
+ return `${formatPlainNumber(amount)}%`;
30
+ }
31
+ function formatPercentageBalanceText(amount, locale) {
32
+ const value = formatPercentage(amount);
33
+ return locale === "zh" ? `余额 / 剩余:${value}` : `Balance / remaining: ${value}`;
34
+ }
35
+ function formatBalanceText(amount, unit, symbol, locale, remainingUses, showCountUnit = true) {
26
36
  if (amount !== null && Number.isFinite(amount)) {
27
- const value = unit === "points" ? formatPoints(amount, locale) : unit === "count" ? formatCount(amount, locale) : formatMoney(amount, symbol);
37
+ const value = unit === "points" ? formatPoints(amount, locale) : unit === "count" ? showCountUnit ? formatCount(amount, locale) : formatPlainNumber(amount) : formatMoney(amount, symbol);
28
38
  return locale === "zh" ? `余额 / 剩余:${value}` : `Balance / remaining: ${value}`;
29
39
  }
30
- if (remainingUses !== void 0 && remainingUses !== null) return locale === "zh" ? `余额 / 剩余:${formatCount(remainingUses, locale)}` : `Balance / remaining: ${formatCount(remainingUses, locale)}`;
40
+ if (remainingUses !== void 0 && remainingUses !== null) return locale === "zh" ? `余额 / 剩余:${showCountUnit ? formatCount(remainingUses, locale) : formatPlainNumber(remainingUses)}` : `Balance / remaining: ${showCountUnit ? formatCount(remainingUses, locale) : formatPlainNumber(remainingUses)}`;
31
41
  return "";
32
42
  }
33
43
  function maskPassId(value) {
@@ -37,6 +47,9 @@ function maskPassId(value) {
37
47
  }
38
48
  //#endregion
39
49
  exports.formatBalanceText = formatBalanceText;
50
+ exports.formatCountValue = formatCountValue;
51
+ exports.formatPercentage = formatPercentage;
52
+ exports.formatPercentageBalanceText = formatPercentageBalanceText;
40
53
  exports.getUsageLabel = getUsageLabel;
41
54
  exports.getUsageValue = getUsageValue;
42
55
  exports.maskPassId = maskPassId;
@@ -8,6 +8,10 @@ const WALLET_PASS_VOUCHER_TAGS = new Set([
8
8
  "gift_card",
9
9
  "product_voucher"
10
10
  ]);
11
+ function getVoucherAmountUnit(tag) {
12
+ if (tag === "good_pass") return "count";
13
+ return "money";
14
+ }
11
15
  const TICKET_VOUCHER_TAGS = new Set([
12
16
  "ticket",
13
17
  "product_package_ticket",
@@ -29,30 +33,41 @@ function isWalletPassVoucher(voucher) {
29
33
  function normalizeVoucherStatus(voucher) {
30
34
  return require_read.readText(voucher, ["status"]).trim().toLowerCase().replace(/[\s-]+/g, "_") === "used" ? "used" : "unused";
31
35
  }
32
- function readVoucherAmount(voucher, status) {
36
+ function isPercentageDiscountVoucher(voucher, tag) {
37
+ return tag === "product_discount_card" && require_read.readText(voucher, ["metadata.discount_card_type"]).trim().toLowerCase() === "percent";
38
+ }
39
+ function readVoucherAmount(voucher, status, amountUnit) {
40
+ var _ref;
33
41
  const usedAmount = require_read.readMoneyFromKeys(voucher, ["used_par_value"]);
34
42
  const issuedAmount = require_read.readMoneyFromKeys(voucher, ["par_value"]);
35
- return Math.max(0, status === "used" ? usedAmount !== null && usedAmount !== void 0 ? usedAmount : 0 : issuedAmount !== null && issuedAmount !== void 0 ? issuedAmount : 0);
43
+ const balance = amountUnit === "money" ? null : require_read.readMoneyFromKeys(voucher, ["balance"]);
44
+ return Math.max(0, status === "used" ? usedAmount !== null && usedAmount !== void 0 ? usedAmount : 0 : (_ref = issuedAmount !== null && issuedAmount !== void 0 ? issuedAmount : balance) !== null && _ref !== void 0 ? _ref : 0);
36
45
  }
37
- function readVoucherBalance(voucher) {
46
+ function readVoucherBalance(voucher, amountUnit) {
38
47
  var _readMoneyFromKeys, _readMoneyFromKeys2;
48
+ if (amountUnit !== "money") {
49
+ const balance = require_read.readMoneyFromKeys(voucher, ["balance"]);
50
+ if (balance !== null) return Math.max(0, balance);
51
+ }
39
52
  return ((_readMoneyFromKeys = require_read.readMoneyFromKeys(voucher, ["par_value"])) !== null && _readMoneyFromKeys !== void 0 ? _readMoneyFromKeys : 0) - ((_readMoneyFromKeys2 = require_read.readMoneyFromKeys(voucher, ["used_par_value"])) !== null && _readMoneyFromKeys2 !== void 0 ? _readMoneyFromKeys2 : 0);
40
53
  }
41
54
  function buildVoucherWalletPassRecord(voucher, index, symbol, locale) {
42
55
  if (!isWalletPassVoucher(voucher)) return null;
43
56
  const status = normalizeVoucherStatus(voucher);
44
57
  const direction = "received";
45
- const amountUnit = "money";
46
- const amountValue = readVoucherAmount(voucher, status);
58
+ const tag = normalizeVoucherTag(voucher);
59
+ const amountUnit = getVoucherAmountUnit(tag);
60
+ const amountValue = readVoucherAmount(voucher, status, amountUnit);
61
+ const isPercentageDiscount = isPercentageDiscountVoucher(voucher, tag);
47
62
  const productName = require_read.readText(voucher, ["product_name"]);
48
63
  const code = require_format.maskPassId(require_read.readText(voucher, ["code"]));
49
64
  const encoded = require_read.readText(voucher, ["encoded"]);
50
- const balance = readVoucherBalance(voucher);
65
+ const balance = readVoucherBalance(voucher, amountUnit);
51
66
  const id = String(require_read.readText(voucher, ["voucher_id"]) || code || `voucher-${index}`);
52
67
  return require_recordFactory.buildRecord({
53
68
  amountUnit,
54
69
  amountValue,
55
- balanceText: require_format.formatBalanceText(balance, amountUnit, symbol, locale),
70
+ balanceText: isPercentageDiscount ? require_format.formatPercentageBalanceText(balance, locale) : require_format.formatBalanceText(balance, amountUnit, symbol, locale, void 0, amountUnit !== "count"),
56
71
  code,
57
72
  direction,
58
73
  encoded,
@@ -61,8 +76,8 @@ function buildVoucherWalletPassRecord(voucher, index, symbol, locale) {
61
76
  sortTime: require_recordFactory.getRecordTime(voucher, index),
62
77
  sourceVoucher: voucher,
63
78
  status,
64
- usageLabel: require_format.getUsageLabel(status, locale),
65
- usageValue: require_format.getUsageValue(amountValue, amountUnit, symbol, locale)
79
+ usageLabel: isPercentageDiscount ? "" : require_format.getUsageLabel(status, locale),
80
+ usageValue: isPercentageDiscount ? require_format.formatPercentage(amountValue) : amountUnit === "count" ? require_format.formatCountValue(amountValue) : require_format.getUsageValue(amountValue, amountUnit, symbol, locale)
66
81
  });
67
82
  }
68
83
  function getVoucherRows(input) {
@@ -132,6 +132,17 @@ const getWrapperStyle = (mode, placement, size, width, height) => {
132
132
  }
133
133
  return require_objectSpread2._objectSpread2({ width: width || 520 }, height ? { height } : null);
134
134
  };
135
+ /**
136
+ * 浮层会被挂到带 transform: scale(...) 的 body 下。modal 的 root 已按
137
+ * `viewport / scale` 做过反向补偿,因此不能再把 vw/% 交给浏览器在另一套
138
+ * viewport 参照系中解析;统一转换成 root 坐标系中的像素值。
139
+ */
140
+ const resolveModalWidth = (mode, width, layoutWidth) => {
141
+ if (mode !== "modal" || typeof width !== "string" || !layoutWidth) return width;
142
+ const match = width.trim().match(/^(\d+(?:\.\d+)?)\s*(vw|%)$/);
143
+ if (!match) return width;
144
+ return layoutWidth * Number(match[1]) / 100;
145
+ };
135
146
  const getWrapperMotionStyle = (mode, placement, motionOpen, bodyScale, viewportSize) => {
136
147
  const visibleStyle = { pointerEvents: "auto" };
137
148
  const hiddenStyle = { pointerEvents: "none" };
@@ -313,10 +324,11 @@ const TransformFloatingLayer = (props) => {
313
324
  ]);
314
325
  const wrapperStyle = (0, react.useMemo)(() => {
315
326
  const scaleX = bodyScale.x || 1;
327
+ const resolvedWidth = resolveModalWidth(mode, width, viewportSize.width / scaleX);
316
328
  const modalScaleStyle = mode === "modal" ? { maxWidth: Math.max((viewportSize.width - 48) / scaleX, 0) } : null;
317
329
  const layoutChangingStyle = mode === "modal" && isLayoutChanging ? { transition: "none" } : null;
318
330
  const skipEnterMotionStyle = skipCurrentEnterMotion ? { transition: "none" } : null;
319
- return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, getWrapperStyle(mode, placement, size, width, height)), modalScaleStyle), style), contentWrapperStyle), styles === null || styles === void 0 ? void 0 : styles.wrapper), getWrapperMotionStyle(mode, placement, effectiveMotionOpen, bodyScale, viewportSize)), layoutChangingStyle), skipEnterMotionStyle);
331
+ return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, getWrapperStyle(mode, placement, size, resolvedWidth, height)), modalScaleStyle), style), contentWrapperStyle), styles === null || styles === void 0 ? void 0 : styles.wrapper), getWrapperMotionStyle(mode, placement, effectiveMotionOpen, bodyScale, viewportSize)), layoutChangingStyle), skipEnterMotionStyle);
320
332
  }, [
321
333
  bodyScale,
322
334
  contentWrapperStyle,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pisell/private-materials",
3
- "version": "6.12.236",
3
+ "version": "6.12.237",
4
4
  "main": "./lib/index.js",
5
5
  "module": "./es/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -70,9 +70,9 @@
70
70
  "styled-components": "^6.0.0-rc.3",
71
71
  "use-sync-external-store": "^1.6.0",
72
72
  "@pisell/pi-payment-sdk": "0.0.3",
73
- "@pisell/materials": "6.12.63",
74
- "@pisell/date-picker": "3.0.10",
75
73
  "@pisell/utils": "3.0.4",
74
+ "@pisell/materials": "6.12.64",
75
+ "@pisell/date-picker": "3.0.10",
76
76
  "@pisell/icon": "0.0.11"
77
77
  },
78
78
  "peerDependencies": {
@@ -1 +0,0 @@
1
- export { };