@akinon/pz-theme 2.0.161-rc.24 → 2.0.162-beta.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/CHANGELOG.md CHANGED
@@ -1,71 +1,21 @@
1
1
  # @akinon/pz-theme
2
2
 
3
- ## 2.0.161-rc.24
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [92086b29]
8
- - @akinon/next@2.0.161-rc.24
9
- - @akinon/theme-contract@2.0.161-rc.24
10
-
11
- ## 2.0.161-rc.23
12
-
13
- ### Patch Changes
14
-
15
- - Updated dependencies [9a7b0937]
16
- - @akinon/next@2.0.161-rc.23
17
- - @akinon/theme-contract@2.0.161-rc.23
18
-
19
- ## 2.0.161-rc.22
20
-
21
- ### Patch Changes
22
-
23
- - 8e040731: ZERO-5235: let brands hang actions on order detail lines
24
- - c761b9fd: ZERO-5296: fall back to the storefront default language in the text block
25
- - 17a598da: ZERO-5296: report the storefront default language to the editor
26
- - 3b05a407: ZERO-5232: allow richtext settings on custom blocks
27
- - ad5240c40: ZERO-5254: add custom render and theme editor support to pz-rate-review
28
- - Updated dependencies [86187b1c2]
29
- - Updated dependencies [08390a87]
30
- - Updated dependencies [0cf9ea239]
31
- - Updated dependencies [97d29893b]
32
- - Updated dependencies [324f97d55]
33
- - Updated dependencies [4c3465ae]
34
- - Updated dependencies [51ea06888]
35
- - Updated dependencies
36
- - Updated dependencies [549da545]
37
- - Updated dependencies [2fea41430]
38
- - Updated dependencies [b55acb768]
39
- - Updated dependencies [760258c1c]
40
- - Updated dependencies [143be2b9d]
41
- - Updated dependencies [7889b08fe]
42
- - Updated dependencies [9f8cd3bc5]
43
- - Updated dependencies [d635d345]
44
- - Updated dependencies [bfafa3f49]
45
- - Updated dependencies [d860c917]
46
- - Updated dependencies [ac6cada1]
47
- - Updated dependencies [e90c0e02]
48
- - Updated dependencies [dc7f9ca5]
49
- - Updated dependencies [57d7eb305]
50
- - Updated dependencies [0145dc3f]
51
- - Updated dependencies [d99a6a7d5]
52
- - Updated dependencies [227b7408]
53
- - Updated dependencies [9db81a714]
54
- - Updated dependencies [591e345e1]
55
- - Updated dependencies [4de5303c5]
56
- - Updated dependencies [95b139dc1]
57
- - Updated dependencies [1d00f2d06]
58
- - Updated dependencies [4ac7b2a1e]
59
- - Updated dependencies [4998a9631]
60
- - Updated dependencies [804d2bd6c]
61
- - Updated dependencies [3909d3224]
62
- - Updated dependencies [6a3d8a631]
63
- - Updated dependencies [e18836b20]
64
- - Updated dependencies [b1111d7b1]
65
- - Updated dependencies [1595d458e]
66
- - Updated dependencies [dca128112]
67
- - @akinon/next@2.0.161-rc.22
68
- - @akinon/theme-contract@2.0.161-rc.22
3
+ ## 2.0.162-beta.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [cbbbfd757]
8
+ - @akinon/next@2.0.162-beta.0
9
+ - @akinon/theme-contract@2.0.162-beta.0
10
+
11
+ ## 2.0.161
12
+
13
+ ### Patch Changes
14
+
15
+ - ad5240c4: ZERO-5254: add custom render and theme editor support to pz-rate-review
16
+ - Updated dependencies [97d29893]
17
+ - @akinon/next@2.0.161
18
+ - @akinon/theme-contract@2.0.161
69
19
 
70
20
  ## 2.0.160
71
21
 
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@akinon/pz-theme",
3
3
  "description": "Theme package for Project Zero Next — ThemePlaceholder system and theme editor infrastructure",
4
- "version": "2.0.161-rc.24",
4
+ "version": "2.0.162-beta.0",
5
5
  "license": "MIT",
6
6
  "main": "src/index.ts",
7
7
  "scripts": {
8
8
  "test": "jest"
9
9
  },
10
10
  "peerDependencies": {
11
- "@akinon/next": "2.0.161-rc.24",
11
+ "@akinon/next": "2.0.162-beta.0",
12
12
  "react": "^18.0.0 || ^19.0.0",
13
13
  "react-dom": "^18.0.0 || ^19.0.0"
14
14
  },
15
15
  "dependencies": {
16
- "@akinon/theme-contract": "2.0.161-rc.24",
16
+ "@akinon/theme-contract": "2.0.162-beta.0",
17
17
  "clsx": "2.1.1",
18
18
  "lottie-web": "^5.13.0",
19
19
  "react-multi-carousel": "2.8.4",
@@ -21,7 +21,7 @@
21
21
  "zod": "4.4.1"
22
22
  },
23
23
  "devDependencies": {
24
- "@akinon/next": "2.0.161-rc.24",
24
+ "@akinon/next": "2.0.162-beta.0",
25
25
  "@testing-library/jest-dom": "5.16.4",
26
26
  "@testing-library/react": "16.3.2",
27
27
  "@testing-library/user-event": "14.1.1",
@@ -28,7 +28,6 @@ const SETTINGS_LOCALES = [
28
28
  const mockLocalization = {
29
29
  locale: 'tr',
30
30
  locales: SETTINGS_LOCALES as Array<Record<string, unknown>>,
31
- defaultLocaleValue: 'tr',
32
31
  setLocale: jest.fn()
33
32
  };
34
33
 
@@ -107,7 +106,6 @@ beforeEach(() => {
107
106
  postMessage.mockClear();
108
107
  mockLocalization.locale = 'tr';
109
108
  mockLocalization.locales = SETTINGS_LOCALES;
110
- mockLocalization.defaultLocaleValue = 'tr';
111
109
  mockLocalization.setLocale = jest.fn();
112
110
  delete (window as { __iframeReadySent?: boolean }).__iframeReadySent;
113
111
  });
@@ -146,8 +144,7 @@ describe('inside the editor', () => {
146
144
  { value: 'en', label: 'English' },
147
145
  { value: 'tr', label: 'Türkçe' },
148
146
  { value: 'de', label: 'de' }
149
- ],
150
- defaultLocale: 'tr'
147
+ ]
151
148
  }
152
149
  })
153
150
  ]);
@@ -157,34 +154,6 @@ describe('inside the editor', () => {
157
154
  expect(targetOrigin).toBe(EDITOR_ORIGIN);
158
155
  });
159
156
 
160
- it('posts the languages before the document reports ready', () => {
161
- // The editor holds every per-language write until IFRAME_READY and takes
162
- // "ready without languages" to mean they are never coming, so the order
163
- // of the two frames is part of the contract.
164
- render(placeholder('header'));
165
-
166
- const types = postMessage.mock.calls.map(([message]) => message?.type);
167
- expect(types).toContain('LOCALE_UPDATE');
168
- expect(types).toContain('IFRAME_READY');
169
- expect(types.indexOf('LOCALE_UPDATE')).toBeLessThan(
170
- types.indexOf('IFRAME_READY')
171
- );
172
- });
173
-
174
- it("posts the brand's default language, whichever it is", () => {
175
- // The editor's per-language text controls take the plain-string form to
176
- // mean this language; left to guess, the editor assumed English.
177
- mockLocalization.defaultLocaleValue = 'de';
178
-
179
- render(<EditorLocaleBridge />);
180
-
181
- expect(localeFrames()).toEqual([
182
- expect.objectContaining({
183
- data: expect.objectContaining({ locale: 'tr', defaultLocale: 'de' })
184
- })
185
- ]);
186
- });
187
-
188
157
  it("follows the editor's switch exactly once, with several placeholders mounted", () => {
189
158
  render(
190
159
  <>
@@ -2,31 +2,9 @@ import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
3
  import TextBlock from '../text-block';
4
4
 
5
- // The page's language and the storefront's default, as the localization
6
- // provider reports them. Most cases run on an English-default store showing
7
- // English; the fallback case moves both.
8
- const mockLocalization = { locale: 'en-us', defaultLocaleValue: 'en-us' };
9
-
10
- jest.mock('@akinon/next/hooks', () => ({
11
- __esModule: true,
12
- useLocalization: () => ({
13
- t: (path: string) => path,
14
- setLocale: () => {},
15
- setCurrency: () => {},
16
- locale: mockLocalization.locale,
17
- currency: 'USD',
18
- locales: [{ value: 'en-us' }, { value: 'tr-tr' }],
19
- currencies: ['USD'],
20
- defaultLocaleValue: mockLocalization.defaultLocaleValue,
21
- defaultCurrencyCode: 'USD',
22
- localeUrlStrategy: 'hide-default-locale'
23
- })
24
- }));
25
-
26
- beforeEach(() => {
27
- mockLocalization.locale = 'en-us';
28
- mockLocalization.defaultLocaleValue = 'en-us';
29
- });
5
+ // The mocked useLocalization (jest/__mocks__/akinon-next-hooks.js) returns
6
+ // locale: 'en-us'. process.env.NEXT_PUBLIC_DEFAULT_LOCALE is unset in the
7
+ // jest env, so the component's defaultLocale falls back to 'en'.
30
8
 
31
9
  const renderBlock = (value: unknown, styles?: Record<string, unknown>) => {
32
10
  const block: any = { id: 'b1', type: 'text', value, styles };
@@ -56,16 +34,10 @@ describe('TextBlock value-shape resolution', () => {
56
34
  );
57
35
  });
58
36
 
59
- it("falls back to the storefront's default language when the active one is absent", () => {
60
- // A Turkish-default store showing German. The entry under `en` is what
61
- // the block used to show: its default was read from an env variable
62
- // that falls back to English, not from the storefront (ZERO-5296).
63
- mockLocalization.locale = 'de-de';
64
- mockLocalization.defaultLocaleValue = 'tr-tr';
65
-
66
- const { container } = renderBlock({ en: 'EN', 'tr-tr': 'TR' });
37
+ it('falls back to defaultLocale ("en") when active locale is absent', () => {
38
+ const { container } = renderBlock({ en: 'EN', fr: 'FR' });
67
39
  expect((container.querySelector('div') as HTMLDivElement).innerHTML).toBe(
68
- 'TR'
40
+ 'EN'
69
41
  );
70
42
  });
71
43
 
@@ -9,7 +9,6 @@ import { getResponsiveValue, partAttrs } from '../utils';
9
9
  import { formatDate, formatMoney } from './commerce-format';
10
10
  import { readMoneyStyle } from './money-style';
11
11
  import { hasItemTemplate, ItemTemplateList } from './item-template';
12
- import { renderOrderLineActions } from './order-line-actions';
13
12
  import { BlockRendererProps } from './block-renderer-registry';
14
13
  import {
15
14
  DesignerPlaceholder,
@@ -25,7 +24,7 @@ import {
25
24
  useOrderActionRules
26
25
  } from '../utils/order-action-rules';
27
26
 
28
- type OrderItemLike = {
27
+ interface OrderItemLike {
29
28
  id?: number;
30
29
  price?: string;
31
30
  quantity?: string | number;
@@ -44,7 +43,7 @@ type OrderItemLike = {
44
43
  absolute_url?: string;
45
44
  attributes?: Record<string, unknown>;
46
45
  } | null;
47
- };
46
+ }
48
47
 
49
48
  interface AddressLike {
50
49
  first_name?: string;
@@ -409,7 +408,7 @@ const formatAddress = (address: AddressLike | null | undefined): string[] => {
409
408
  * currencyText, currencyPosition.
410
409
  * Parts: detail, header, number, date, header-total, status,
411
410
  * invoice-link, cancel-link, return-link, list, item, image, name, quantity,
412
- * color, size, item-status, item-tracking, item-return-code, item-actions,
411
+ * color, size, item-status, item-tracking, item-return-code,
413
412
  * item-return-method, item-return-carrier, item-pickup-date, price, shipment,
414
413
  * delivery, tracking, addresses, address, address-label, totals, total-row,
415
414
  * total-label, total-value, grand-total, payment-info, payment-info-label.
@@ -956,21 +955,6 @@ const OrderDetailBlock = ({
956
955
  showPickupDate && returnDetails.pickupDate
957
956
  ? formatPickupDate(returnDetails.pickupDate, locale)
958
957
  : '';
959
- const lineActions = renderOrderLineActions({
960
- order,
961
- line,
962
- isDesigner
963
- });
964
- const showLineMeta =
965
- showShipmentStatus &&
966
- Boolean(
967
- item.status?.label ||
968
- trackingValue ||
969
- returnCodeValue ||
970
- returnMethodValue ||
971
- returnCarrierValue ||
972
- pickupDateValue
973
- );
974
958
 
975
959
  return (
976
960
  <li
@@ -1086,100 +1070,98 @@ const OrderDetailBlock = ({
1086
1070
  </div>
1087
1071
  </div>
1088
1072
 
1089
- {(showLineMeta || lineActions) && (
1090
- <div
1091
- style={{
1092
- display: 'flex',
1093
- flexDirection: 'column',
1094
- alignItems: isMobile ? 'flex-start' : 'flex-end',
1095
- textAlign: isMobile ? 'left' : 'right',
1096
- gap: '4px',
1097
- flex: isMobile ? '1 1 100%' : '0 0 auto'
1098
- }}
1099
- >
1100
- {lineActions && (
1101
- <div
1102
- data-order-detail-item-actions=""
1103
- {...partAttrs('item-actions')}
1104
- >
1105
- {lineActions}
1106
- </div>
1107
- )}
1108
- {showLineMeta && item.status?.label && (
1109
- <span
1110
- data-order-detail-item-status=""
1111
- data-order-status-value={item.status.value}
1112
- {...partAttrs('item-status')}
1113
- style={{ display: 'inline-block' }}
1114
- >
1115
- {item.status.label}
1116
- </span>
1117
- )}
1118
- {/* Label and value in their own spans, so a
1119
- composition can colour them apart. */}
1120
- {showLineMeta && returnMethodValue && (
1121
- <span
1122
- data-order-detail-item-return-method=""
1123
- {...partAttrs('item-return-method')}
1124
- style={{ opacity: 0.8 }}
1125
- >
1126
- <span data-label="">{returnMethodLabel}</span>{' '}
1127
- <span data-value="">{returnMethodValue}</span>
1128
- </span>
1129
- )}
1130
- {showLineMeta && returnCarrierValue && (
1131
- <span
1132
- data-order-detail-item-return-carrier=""
1133
- {...partAttrs('item-return-carrier')}
1134
- style={{ opacity: 0.8 }}
1135
- >
1136
- <span data-label="">{returnCarrierLabel}</span>{' '}
1137
- <span data-value="">{returnCarrierValue}</span>
1138
- </span>
1139
- )}
1140
- {showLineMeta && pickupDateValue && (
1141
- <span
1142
- data-order-detail-item-pickup-date=""
1143
- {...partAttrs('item-pickup-date')}
1144
- style={{ opacity: 0.8 }}
1145
- >
1146
- <span data-label="">{pickupDateLabel}</span>{' '}
1147
- <span data-value="">{pickupDateValue}</span>
1148
- </span>
1149
- )}
1150
- {showLineMeta && trackingValue && (
1151
- <span
1152
- data-order-detail-item-tracking=""
1153
- {...partAttrs('item-tracking')}
1154
- style={{ opacity: 0.8 }}
1155
- >
1156
- {lineTrackingLabel}{' '}
1157
- {item.tracking_url ? (
1158
- <a
1159
- href={isDesigner ? '#' : item.tracking_url}
1160
- onClick={guard}
1161
- target={isDesigner ? undefined : '_blank'}
1162
- rel="noreferrer"
1163
- style={{ color: 'inherit' }}
1164
- >
1165
- {item.tracking_number || item.tracking_url}
1166
- </a>
1167
- ) : (
1168
- trackingValue
1169
- )}
1170
- </span>
1171
- )}
1172
- {showLineMeta && returnCodeValue && (
1173
- <span
1174
- data-order-detail-item-return-code=""
1175
- {...partAttrs('item-return-code')}
1176
- style={{ opacity: 0.8 }}
1177
- >
1178
- {returnCodeLabel} {returnCodeValue}
1179
- </span>
1180
- )}
1181
- </div>
1182
- )}
1073
+ {showShipmentStatus &&
1074
+ (item.status?.label ||
1075
+ trackingValue ||
1076
+ returnCodeValue ||
1077
+ returnMethodValue ||
1078
+ returnCarrierValue ||
1079
+ pickupDateValue) && (
1080
+ <div
1081
+ style={{
1082
+ display: 'flex',
1083
+ flexDirection: 'column',
1084
+ alignItems: isMobile ? 'flex-start' : 'flex-end',
1085
+ textAlign: isMobile ? 'left' : 'right',
1086
+ gap: '4px',
1087
+ flex: isMobile ? '1 1 100%' : '0 0 auto'
1088
+ }}
1089
+ >
1090
+ {item.status?.label && (
1091
+ <span
1092
+ data-order-detail-item-status=""
1093
+ data-order-status-value={item.status.value}
1094
+ {...partAttrs('item-status')}
1095
+ style={{ display: 'inline-block' }}
1096
+ >
1097
+ {item.status.label}
1098
+ </span>
1099
+ )}
1100
+ {/* Label and value in their own spans, so a
1101
+ composition can colour them apart. */}
1102
+ {returnMethodValue && (
1103
+ <span
1104
+ data-order-detail-item-return-method=""
1105
+ {...partAttrs('item-return-method')}
1106
+ style={{ opacity: 0.8 }}
1107
+ >
1108
+ <span data-label="">{returnMethodLabel}</span>{' '}
1109
+ <span data-value="">{returnMethodValue}</span>
1110
+ </span>
1111
+ )}
1112
+ {returnCarrierValue && (
1113
+ <span
1114
+ data-order-detail-item-return-carrier=""
1115
+ {...partAttrs('item-return-carrier')}
1116
+ style={{ opacity: 0.8 }}
1117
+ >
1118
+ <span data-label="">{returnCarrierLabel}</span>{' '}
1119
+ <span data-value="">{returnCarrierValue}</span>
1120
+ </span>
1121
+ )}
1122
+ {pickupDateValue && (
1123
+ <span
1124
+ data-order-detail-item-pickup-date=""
1125
+ {...partAttrs('item-pickup-date')}
1126
+ style={{ opacity: 0.8 }}
1127
+ >
1128
+ <span data-label="">{pickupDateLabel}</span>{' '}
1129
+ <span data-value="">{pickupDateValue}</span>
1130
+ </span>
1131
+ )}
1132
+ {trackingValue && (
1133
+ <span
1134
+ data-order-detail-item-tracking=""
1135
+ {...partAttrs('item-tracking')}
1136
+ style={{ opacity: 0.8 }}
1137
+ >
1138
+ {lineTrackingLabel}{' '}
1139
+ {item.tracking_url ? (
1140
+ <a
1141
+ href={isDesigner ? '#' : item.tracking_url}
1142
+ onClick={guard}
1143
+ target={isDesigner ? undefined : '_blank'}
1144
+ rel="noreferrer"
1145
+ style={{ color: 'inherit' }}
1146
+ >
1147
+ {item.tracking_number || item.tracking_url}
1148
+ </a>
1149
+ ) : (
1150
+ trackingValue
1151
+ )}
1152
+ </span>
1153
+ )}
1154
+ {returnCodeValue && (
1155
+ <span
1156
+ data-order-detail-item-return-code=""
1157
+ {...partAttrs('item-return-code')}
1158
+ style={{ opacity: 0.8 }}
1159
+ >
1160
+ {returnCodeLabel} {returnCodeValue}
1161
+ </span>
1162
+ )}
1163
+ </div>
1164
+ )}
1183
1165
  </div>
1184
1166
  </li>
1185
1167
  );
@@ -7,7 +7,6 @@ import { getInnerRootInlineStyles, partAttrs } from '../utils';
7
7
  import { useThemeSettingsContext } from '../theme-settings-context';
8
8
  import { useLocalizeHref } from '../hooks/use-localize-href';
9
9
  import { localizeHtmlLinks } from '../utils/localize-href';
10
- import { useValueLocale } from '../utils/localized-value';
11
10
 
12
11
  const TextBlock = ({
13
12
  block,
@@ -15,7 +14,7 @@ const TextBlock = ({
15
14
  }: BlockRendererProps) => {
16
15
  const { locale } = useLocalization();
17
16
  const localize = useLocalizeHref();
18
- const { defaultLocale } = useValueLocale();
17
+ const defaultLocale = process.env.NEXT_PUBLIC_DEFAULT_LOCALE || 'en';
19
18
  const themeSettings = useThemeSettingsContext();
20
19
 
21
20
  const getLocalizedContent = (): string => {
@@ -31,10 +30,7 @@ const TextBlock = ({
31
30
 
32
31
  if (typeof value === 'object' && value !== null) {
33
32
  return (
34
- value[locale] ||
35
- (defaultLocale && value[defaultLocale]) ||
36
- Object.values(value)[0] ||
37
- ''
33
+ value[locale] || value[defaultLocale] || Object.values(value)[0] || ''
38
34
  );
39
35
  }
40
36