@akinon/pz-theme 2.0.35-beta.0 → 2.0.35

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 (39) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/package.json +4 -3
  3. package/src/__tests__/theme-contract.test.ts +130 -0
  4. package/src/blocks/__tests__/text-block.test.tsx +8 -1
  5. package/src/blocks/__tests__/video-block.test.tsx +14 -7
  6. package/src/blocks/counter-block.tsx +44 -56
  7. package/src/blocks/group-block.tsx +23 -22
  8. package/src/blocks/hotspot-block.tsx +171 -80
  9. package/src/blocks/input-block.tsx +15 -17
  10. package/src/blocks/link-block.tsx +18 -21
  11. package/src/blocks/slider-block.tsx +15 -12
  12. package/src/components/with-designer-features.tsx +2 -0
  13. package/src/editor-bridge.ts +160 -0
  14. package/src/hooks/use-designer-features.tsx +30 -37
  15. package/src/placeholder-registry.ts +5 -7
  16. package/src/sections/__tests__/countdown-campaign-banner-section.test.tsx +8 -4
  17. package/src/sections/__tests__/coupon-banner-section.test.tsx +4 -2
  18. package/src/sections/before-after-section.tsx +189 -134
  19. package/src/sections/contact-form-section.tsx +185 -60
  20. package/src/sections/countdown-campaign-banner-section.tsx +73 -27
  21. package/src/sections/coupon-banner-section.tsx +152 -48
  22. package/src/sections/featured-product-spotlight-section.tsx +67 -66
  23. package/src/sections/find-in-store-section.tsx +37 -25
  24. package/src/sections/hover-showcase-section.tsx +221 -89
  25. package/src/sections/image-hotspot-section.tsx +208 -94
  26. package/src/sections/installment-options-section.tsx +268 -259
  27. package/src/sections/notification-banner-section.tsx +111 -25
  28. package/src/sections/order-tracking-lookup-section.tsx +272 -247
  29. package/src/sections/posts-slider-section.tsx +17 -16
  30. package/src/sections/pre-order-launch-banner-section.tsx +31 -50
  31. package/src/sections/section-wrapper.tsx +9 -10
  32. package/src/sections/shipping-threshold-progress-section.tsx +72 -29
  33. package/src/sections/stats-counter-section.tsx +68 -30
  34. package/src/sections/tabs-section.tsx +124 -147
  35. package/src/theme-placeholder-client.tsx +11 -14
  36. package/src/theme-placeholder-wrapper.tsx +42 -51
  37. package/src/theme-section.tsx +27 -34
  38. package/src/utils/__tests__/transform-styles.test.ts +97 -0
  39. package/src/utils/index.ts +9 -0
@@ -23,6 +23,8 @@ import {
23
23
  resolveThemeCssVariables
24
24
  } from '../utils';
25
25
 
26
+ import { postToEditor } from '../editor-bridge';
27
+ import { PreviewToEditorMessageType } from '@akinon/theme-contract';
26
28
  interface OrderTrackingLookupSectionProps {
27
29
  section: Section;
28
30
  currentBreakpoint?: string;
@@ -225,7 +227,9 @@ const resolveTrackingNumber = (order: Order | null): string => {
225
227
  }
226
228
 
227
229
  const trackedItem = order.orderitem_set?.find(
228
- (item) => typeof (item as OrderItem & { tracking_number?: string }).tracking_number === 'string'
230
+ (item) =>
231
+ typeof (item as OrderItem & { tracking_number?: string })
232
+ .tracking_number === 'string'
229
233
  ) as (OrderItem & { tracking_number?: string }) | undefined;
230
234
 
231
235
  return trackedItem?.tracking_number || '';
@@ -240,7 +244,10 @@ const formatAmount = (value: unknown, currency: unknown): string => {
240
244
  (currency as { label?: string; value?: string } | undefined)?.value ||
241
245
  '';
242
246
 
243
- if (!currencyLabel || amount.toUpperCase().includes(currencyLabel.toUpperCase())) {
247
+ if (
248
+ !currencyLabel ||
249
+ amount.toUpperCase().includes(currencyLabel.toUpperCase())
250
+ ) {
244
251
  return amount;
245
252
  }
246
253
 
@@ -293,10 +300,7 @@ const getStatusTone = (
293
300
  return { background: '#fef3c7', color: '#92400e' };
294
301
  };
295
302
 
296
- const extractErrorMessage = (
297
- error: unknown,
298
- fallback: string
299
- ): string => {
303
+ const extractErrorMessage = (error: unknown, fallback: string): string => {
300
304
  if (!error || typeof error !== 'object') return fallback;
301
305
 
302
306
  const errorData = (error as { data?: Record<string, unknown> }).data;
@@ -375,7 +379,10 @@ const findAuthenticatedOrder = async (
375
379
  buildClientRequestUrl(account.getOldOrders({ page, limit: 100 }));
376
380
 
377
381
  return (
378
- (await findMatchingOrderInPagedResponse(buildCurrentOrdersUrl, orderNumber)) ||
382
+ (await findMatchingOrderInPagedResponse(
383
+ buildCurrentOrdersUrl,
384
+ orderNumber
385
+ )) ||
379
386
  (await findMatchingOrderInPagedResponse(buildOldOrdersUrl, orderNumber))
380
387
  );
381
388
  };
@@ -495,10 +502,10 @@ export default function OrderTrackingLookupSection({
495
502
  maxWidth === 'narrow'
496
503
  ? 'max-w-4xl'
497
504
  : maxWidth === 'normal'
498
- ? 'max-w-7xl'
499
- : maxWidth === 'full'
500
- ? 'w-full'
501
- : '';
505
+ ? 'max-w-7xl'
506
+ : maxWidth === 'full'
507
+ ? 'w-full'
508
+ : '';
502
509
  const hasMaxWidth = maxWidth !== 'none' && maxWidth !== 'full';
503
510
 
504
511
  const inputBg = resolveThemeCssVariables(
@@ -748,20 +755,21 @@ export default function OrderTrackingLookupSection({
748
755
  currentBreakpoint
749
756
  );
750
757
 
751
- const postBlockAction = (type: string, blockId: string, label?: string) => {
758
+ const postBlockAction = (
759
+ type: PreviewToEditorMessageType,
760
+ blockId: string,
761
+ label?: string
762
+ ) => {
752
763
  if (!window.parent) return;
753
- window.parent.postMessage(
754
- {
755
- type,
756
- data: {
757
- placeholderId,
758
- sectionId: section.id,
759
- blockId,
760
- ...(label ? { label } : {})
761
- }
762
- },
763
- '*'
764
- );
764
+ postToEditor({
765
+ type,
766
+ data: {
767
+ placeholderId,
768
+ sectionId: section.id,
769
+ blockId,
770
+ ...(label ? { label } : {})
771
+ }
772
+ });
765
773
  };
766
774
 
767
775
  const renderBlock = (block: Block, keyOverride?: React.Key) => {
@@ -1033,7 +1041,10 @@ export default function OrderTrackingLookupSection({
1033
1041
  const groupedPackageCount = lookupOrder
1034
1042
  ? new Set(
1035
1043
  lookupOrder.orderitem_set
1036
- .map((item) => (item as OrderItem & { tracking_number?: string }).tracking_number)
1044
+ .map(
1045
+ (item) =>
1046
+ (item as OrderItem & { tracking_number?: string }).tracking_number
1047
+ )
1037
1048
  .filter(Boolean)
1038
1049
  ).size || 1
1039
1050
  : 0;
@@ -1055,14 +1066,15 @@ export default function OrderTrackingLookupSection({
1055
1066
  isMobile ? 'grid-cols-1' : 'md:grid-cols-[0.9fr_1.1fr]'
1056
1067
  )}
1057
1068
  >
1058
- <div className="flex flex-col gap-4">
1059
- {textBlocks.map(renderBlock)}
1060
- </div>
1069
+ <div className="flex flex-col gap-4">{textBlocks.map(renderBlock)}</div>
1061
1070
 
1062
1071
  <div className="flex flex-col gap-4" style={{ gap: `${formGap}px` }}>
1063
1072
  {renderSelectableWrapper(
1064
1073
  formPanelWrapperBlock,
1065
- <form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-3">
1074
+ <form
1075
+ onSubmit={handleSubmit(onSubmit)}
1076
+ className="flex flex-col gap-3"
1077
+ >
1066
1078
  {renderSelectableElement(
1067
1079
  orderInputBlock,
1068
1080
  <input
@@ -1137,243 +1149,256 @@ export default function OrderTrackingLookupSection({
1137
1149
  }
1138
1150
  )}
1139
1151
 
1140
- {lookupError ? (
1141
- renderSelectableWrapper(
1142
- errorWrapperBlock,
1143
- errorTextBlock ? (
1144
- renderBlock(
1145
- cloneOrderTrackingBlock(errorTextBlock, {
1146
- value: toHtmlText(lookupError)
1147
- }),
1148
- 'error-text'
1149
- )
1150
- ) : (
1151
- <div className="text-sm text-[#b91c1c]">{lookupError}</div>
1152
- ),
1153
- {
1154
- className:
1155
- 'rounded-[12px] border border-[#fecaca] bg-[#fff1f2] px-4 py-3',
1156
- keyOverride: 'lookup-error'
1157
- }
1158
- )
1159
- ) : null}
1160
- </div>
1161
- </div>
1162
-
1163
- {lookupOrder ? (
1164
- renderSelectableWrapper(
1165
- resultWrapperBlock,
1166
- <div className="flex flex-col gap-4">
1167
- <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
1168
- <div className="flex flex-col gap-1">
1169
- <span className="text-xs font-semibold uppercase tracking-[0.12em] text-[#64748b]">
1170
- {t('account.my_orders.detail.title')}
1171
- </span>
1172
- <h3 className="m-0 text-2xl font-bold text-[#0f172a]">
1173
- #{lookupOrder.number}
1174
- </h3>
1175
- </div>
1176
-
1177
- {showStatusBadge && statusLabel ? (
1178
- renderSelectableElement(
1179
- statusBadgeBlock,
1180
- <span
1181
- className="inline-flex w-fit items-center px-3 py-2 text-xs font-semibold uppercase tracking-[0.08em]"
1182
- style={statusBadgeStyle}
1183
- >
1184
- {statusLabel}
1185
- </span>,
1186
- {
1187
- keyOverride: 'status-badge'
1188
- }
1189
- )
1190
- ) : null}
1191
- </div>
1192
-
1193
- <div
1194
- className={clsx(
1195
- 'grid gap-3',
1196
- isMobile ? 'grid-cols-2' : 'md:grid-cols-4'
1197
- )}
1198
- >
1199
- {[
1200
- {
1201
- key: 'summary-order-number',
1202
- label: t('account.my_orders.detail.order_number'),
1203
- value: `#${lookupOrder.number}`
1204
- },
1205
- {
1206
- key: 'summary-order-date',
1207
- label: t('account.my_orders.detail.order_date'),
1208
- value: formatDate(lookupOrder.created_date, localeCode)
1209
- },
1210
- {
1211
- key: 'summary-order-total',
1212
- label: t('account.my_orders.detail.total'),
1213
- value: formatAmount(lookupOrder.amount, lookupOrder.currency)
1214
- },
1215
- {
1216
- key: 'summary-order-products',
1217
- label: t('account.my_orders.detail.products'),
1218
- value: `${lookupOrder.orderitem_set?.length || 0} / ${groupedPackageCount} ${t(
1219
- 'account.my_orders.detail.packages'
1220
- )}`
1221
- }
1222
- ].map((summaryItem) =>
1223
- renderSelectableWrapper(
1224
- summaryCardWrapperBlock,
1225
- <>
1226
- <div className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1227
- {summaryItem.label}
1228
- </div>
1229
- <div className="mt-2 text-sm font-semibold text-[#0f172a]">
1230
- {summaryItem.value}
1231
- </div>
1232
- </>,
1152
+ {lookupError
1153
+ ? renderSelectableWrapper(
1154
+ errorWrapperBlock,
1155
+ errorTextBlock ? (
1156
+ renderBlock(
1157
+ cloneOrderTrackingBlock(errorTextBlock, {
1158
+ value: toHtmlText(lookupError)
1159
+ }),
1160
+ 'error-text'
1161
+ )
1162
+ ) : (
1163
+ <div className="text-sm text-[#b91c1c]">{lookupError}</div>
1164
+ ),
1233
1165
  {
1234
- className: 'rounded-[10px] bg-[#f8fafc] p-3',
1235
- keyOverride: summaryItem.key
1166
+ className:
1167
+ 'rounded-[12px] border border-[#fecaca] bg-[#fff1f2] px-4 py-3',
1168
+ keyOverride: 'lookup-error'
1236
1169
  }
1237
1170
  )
1238
- )}
1239
- </div>
1171
+ : null}
1172
+ </div>
1173
+ </div>
1240
1174
 
1241
- {showTrackingCard && (trackingUrl || trackingNumber) ? (
1242
- renderSelectableWrapper(
1243
- trackingCardWrapperBlock,
1244
- <>
1175
+ {lookupOrder
1176
+ ? renderSelectableWrapper(
1177
+ resultWrapperBlock,
1178
+ <div className="flex flex-col gap-4">
1179
+ <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
1245
1180
  <div className="flex flex-col gap-1">
1246
- <span className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#1d4ed8]">
1247
- {localeCode === 'tr' ? 'Kargo Bilgisi' : 'Shipment Details'}
1181
+ <span className="text-xs font-semibold uppercase tracking-[0.12em] text-[#64748b]">
1182
+ {t('account.my_orders.detail.title')}
1248
1183
  </span>
1249
- <span className="text-sm font-semibold text-[#0f172a]">
1250
- {trackingNumber || statusLabel}
1251
- </span>
1252
- </div>
1253
-
1254
- {trackingUrl ? (
1255
- <a
1256
- href={trackingUrl}
1257
- target="_blank"
1258
- rel="noreferrer"
1259
- className="inline-flex w-fit items-center justify-center rounded-[10px] bg-[#0f172a] px-5 py-3 text-sm font-semibold text-white no-underline"
1260
- >
1261
- {trackShipmentText}
1262
- </a>
1263
- ) : null}
1264
- </>,
1265
- {
1266
- className:
1267
- 'flex flex-col gap-3 rounded-[12px] border border-[#dbeafe] bg-[#eff6ff] p-4 md:flex-row md:items-center md:justify-between',
1268
- keyOverride: 'tracking-card'
1269
- }
1270
- )
1271
- ) : null}
1272
-
1273
- {showShippingAddress && lookupOrder.shipping_address?.line ? (
1274
- renderSelectableWrapper(
1275
- shippingAddressWrapperBlock,
1276
- <>
1277
- <div className="mb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1278
- {t('account.my_orders.detail.delivery_address')}
1184
+ <h3 className="m-0 text-2xl font-bold text-[#0f172a]">
1185
+ #{lookupOrder.number}
1186
+ </h3>
1279
1187
  </div>
1280
- <div>
1281
- {lookupOrder.shipping_address.line}{' '}
1282
- {lookupOrder.shipping_address.district?.name}{' '}
1283
- {lookupOrder.shipping_address.township?.name}{' '}
1284
- {lookupOrder.shipping_address.city?.name}
1285
- </div>
1286
- </>,
1287
- {
1288
- className: 'rounded-[12px] bg-[#f8fafc] p-4 text-sm leading-6 text-[#334155]',
1289
- keyOverride: 'shipping-address'
1290
- }
1291
- )
1292
- ) : null}
1293
1188
 
1294
- {showOrderItems ? (
1295
- <div className="flex flex-col gap-3">
1296
- <div className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1297
- {t('account.my_orders.detail.products')}
1189
+ {showStatusBadge && statusLabel
1190
+ ? renderSelectableElement(
1191
+ statusBadgeBlock,
1192
+ <span
1193
+ className="inline-flex w-fit items-center px-3 py-2 text-xs font-semibold uppercase tracking-[0.08em]"
1194
+ style={statusBadgeStyle}
1195
+ >
1196
+ {statusLabel}
1197
+ </span>,
1198
+ {
1199
+ keyOverride: 'status-badge'
1200
+ }
1201
+ )
1202
+ : null}
1298
1203
  </div>
1299
- {renderSelectableWrapper(
1300
- itemsListWrapperBlock,
1301
- visibleItems.map((item, index) =>
1204
+
1205
+ <div
1206
+ className={clsx(
1207
+ 'grid gap-3',
1208
+ isMobile ? 'grid-cols-2' : 'md:grid-cols-4'
1209
+ )}
1210
+ >
1211
+ {[
1212
+ {
1213
+ key: 'summary-order-number',
1214
+ label: t('account.my_orders.detail.order_number'),
1215
+ value: `#${lookupOrder.number}`
1216
+ },
1217
+ {
1218
+ key: 'summary-order-date',
1219
+ label: t('account.my_orders.detail.order_date'),
1220
+ value: formatDate(lookupOrder.created_date, localeCode)
1221
+ },
1222
+ {
1223
+ key: 'summary-order-total',
1224
+ label: t('account.my_orders.detail.total'),
1225
+ value: formatAmount(
1226
+ lookupOrder.amount,
1227
+ lookupOrder.currency
1228
+ )
1229
+ },
1230
+ {
1231
+ key: 'summary-order-products',
1232
+ label: t('account.my_orders.detail.products'),
1233
+ value: `${
1234
+ lookupOrder.orderitem_set?.length || 0
1235
+ } / ${groupedPackageCount} ${t(
1236
+ 'account.my_orders.detail.packages'
1237
+ )}`
1238
+ }
1239
+ ].map((summaryItem) =>
1302
1240
  renderSelectableWrapper(
1303
- orderItemWrapperBlock,
1241
+ summaryCardWrapperBlock,
1304
1242
  <>
1305
- <div className="flex min-w-0 items-center gap-3">
1306
- <div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-[8px] bg-[#f1f5f9]">
1307
- <Image
1308
- src={item.product?.image || '/noimage.jpg'}
1309
- alt={item.product?.name || ''}
1310
- fill
1311
- sizes="64px"
1312
- aspectRatio={1}
1313
- imageClassName="object-cover"
1314
- />
1315
- </div>
1316
- <div className="min-w-0">
1317
- <div className="truncate text-sm font-semibold text-[#0f172a]">
1318
- {item.product?.name}
1319
- </div>
1320
- <div className="mt-1 text-xs text-[#64748b]">
1321
- {t('account.my_orders.detail.items')}: {item.quantity}
1322
- {' · '}
1323
- {item.status?.label}
1324
- </div>
1325
- </div>
1243
+ <div className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1244
+ {summaryItem.label}
1245
+ </div>
1246
+ <div className="mt-2 text-sm font-semibold text-[#0f172a]">
1247
+ {summaryItem.value}
1326
1248
  </div>
1327
- <div className="flex shrink-0 flex-col items-start text-sm md:items-end">
1328
- {parseFloat(item.retail_price) > parseFloat(item.price) ? (
1329
- <span className="text-xs text-[#94a3b8] line-through">
1330
- {formatAmount(item.retail_price, item.price_currency)}
1331
- </span>
1332
- ) : null}
1333
- <span className="font-semibold text-[#0f172a]">
1334
- {formatAmount(item.price, item.price_currency)}
1249
+ </>,
1250
+ {
1251
+ className: 'rounded-[10px] bg-[#f8fafc] p-3',
1252
+ keyOverride: summaryItem.key
1253
+ }
1254
+ )
1255
+ )}
1256
+ </div>
1257
+
1258
+ {showTrackingCard && (trackingUrl || trackingNumber)
1259
+ ? renderSelectableWrapper(
1260
+ trackingCardWrapperBlock,
1261
+ <>
1262
+ <div className="flex flex-col gap-1">
1263
+ <span className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#1d4ed8]">
1264
+ {localeCode === 'tr'
1265
+ ? 'Kargo Bilgisi'
1266
+ : 'Shipment Details'}
1267
+ </span>
1268
+ <span className="text-sm font-semibold text-[#0f172a]">
1269
+ {trackingNumber || statusLabel}
1335
1270
  </span>
1336
1271
  </div>
1272
+
1273
+ {trackingUrl ? (
1274
+ <a
1275
+ href={trackingUrl}
1276
+ target="_blank"
1277
+ rel="noreferrer"
1278
+ className="inline-flex w-fit items-center justify-center rounded-[10px] bg-[#0f172a] px-5 py-3 text-sm font-semibold text-white no-underline"
1279
+ >
1280
+ {trackShipmentText}
1281
+ </a>
1282
+ ) : null}
1337
1283
  </>,
1338
1284
  {
1339
1285
  className:
1340
- 'flex flex-col gap-3 p-4 md:flex-row md:items-center md:justify-between',
1341
- keyOverride: `order-item-${item.id}-${index}`
1286
+ 'flex flex-col gap-3 rounded-[12px] border border-[#dbeafe] bg-[#eff6ff] p-4 md:flex-row md:items-center md:justify-between',
1287
+ keyOverride: 'tracking-card'
1342
1288
  }
1343
1289
  )
1344
- ),
1345
- {
1346
- className:
1347
- 'flex flex-col divide-y divide-[#e2e8f0] overflow-hidden rounded-[12px] border border-[#e2e8f0] bg-white',
1348
- keyOverride: 'items-list-wrapper'
1349
- }
1350
- )}
1351
- </div>
1352
- ) : null}
1353
-
1354
- <div className="pt-2">
1355
- {renderSelectableElement(
1356
- resetButtonBlock,
1357
- <button
1358
- type="button"
1359
- onClick={handleReset}
1360
- style={resetButtonStyle}
1361
- >
1362
- {resetButtonText}
1363
- </button>,
1364
- {
1365
- keyOverride: 'reset-button'
1366
- }
1367
- )}
1368
- </div>
1369
- </div>,
1370
- {
1371
- className: 'mt-6 flex flex-col gap-4 p-5 md:p-6',
1372
- style: panelStyle,
1373
- keyOverride: 'result-wrapper'
1374
- }
1375
- )
1376
- ) : null}
1290
+ : null}
1291
+
1292
+ {showShippingAddress && lookupOrder.shipping_address?.line
1293
+ ? renderSelectableWrapper(
1294
+ shippingAddressWrapperBlock,
1295
+ <>
1296
+ <div className="mb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1297
+ {t('account.my_orders.detail.delivery_address')}
1298
+ </div>
1299
+ <div>
1300
+ {lookupOrder.shipping_address.line}{' '}
1301
+ {lookupOrder.shipping_address.district?.name}{' '}
1302
+ {lookupOrder.shipping_address.township?.name}{' '}
1303
+ {lookupOrder.shipping_address.city?.name}
1304
+ </div>
1305
+ </>,
1306
+ {
1307
+ className:
1308
+ 'rounded-[12px] bg-[#f8fafc] p-4 text-sm leading-6 text-[#334155]',
1309
+ keyOverride: 'shipping-address'
1310
+ }
1311
+ )
1312
+ : null}
1313
+
1314
+ {showOrderItems ? (
1315
+ <div className="flex flex-col gap-3">
1316
+ <div className="text-[11px] font-semibold uppercase tracking-[0.08em] text-[#64748b]">
1317
+ {t('account.my_orders.detail.products')}
1318
+ </div>
1319
+ {renderSelectableWrapper(
1320
+ itemsListWrapperBlock,
1321
+ visibleItems.map((item, index) =>
1322
+ renderSelectableWrapper(
1323
+ orderItemWrapperBlock,
1324
+ <>
1325
+ <div className="flex min-w-0 items-center gap-3">
1326
+ <div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-[8px] bg-[#f1f5f9]">
1327
+ <Image
1328
+ src={item.product?.image || '/noimage.jpg'}
1329
+ alt={item.product?.name || ''}
1330
+ fill
1331
+ sizes="64px"
1332
+ aspectRatio={1}
1333
+ imageClassName="object-cover"
1334
+ />
1335
+ </div>
1336
+ <div className="min-w-0">
1337
+ <div className="truncate text-sm font-semibold text-[#0f172a]">
1338
+ {item.product?.name}
1339
+ </div>
1340
+ <div className="mt-1 text-xs text-[#64748b]">
1341
+ {t('account.my_orders.detail.items')}:{' '}
1342
+ {item.quantity}
1343
+ {' · '}
1344
+ {item.status?.label}
1345
+ </div>
1346
+ </div>
1347
+ </div>
1348
+ <div className="flex shrink-0 flex-col items-start text-sm md:items-end">
1349
+ {parseFloat(item.retail_price) >
1350
+ parseFloat(item.price) ? (
1351
+ <span className="text-xs text-[#94a3b8] line-through">
1352
+ {formatAmount(
1353
+ item.retail_price,
1354
+ item.price_currency
1355
+ )}
1356
+ </span>
1357
+ ) : null}
1358
+ <span className="font-semibold text-[#0f172a]">
1359
+ {formatAmount(item.price, item.price_currency)}
1360
+ </span>
1361
+ </div>
1362
+ </>,
1363
+ {
1364
+ className:
1365
+ 'flex flex-col gap-3 p-4 md:flex-row md:items-center md:justify-between',
1366
+ keyOverride: `order-item-${item.id}-${index}`
1367
+ }
1368
+ )
1369
+ ),
1370
+ {
1371
+ className:
1372
+ 'flex flex-col divide-y divide-[#e2e8f0] overflow-hidden rounded-[12px] border border-[#e2e8f0] bg-white',
1373
+ keyOverride: 'items-list-wrapper'
1374
+ }
1375
+ )}
1376
+ </div>
1377
+ ) : null}
1378
+
1379
+ <div className="pt-2">
1380
+ {renderSelectableElement(
1381
+ resetButtonBlock,
1382
+ <button
1383
+ type="button"
1384
+ onClick={handleReset}
1385
+ style={resetButtonStyle}
1386
+ >
1387
+ {resetButtonText}
1388
+ </button>,
1389
+ {
1390
+ keyOverride: 'reset-button'
1391
+ }
1392
+ )}
1393
+ </div>
1394
+ </div>,
1395
+ {
1396
+ className: 'mt-6 flex flex-col gap-4 p-5 md:p-6',
1397
+ style: panelStyle,
1398
+ keyOverride: 'result-wrapper'
1399
+ }
1400
+ )
1401
+ : null}
1377
1402
  </div>
1378
1403
  );
1379
1404
  }
@@ -13,6 +13,8 @@ import {
13
13
  getResponsiveValue
14
14
  } from '../utils';
15
15
 
16
+ import { postToEditor } from '../editor-bridge';
17
+ import { PreviewToEditorMessageType } from '@akinon/theme-contract';
16
18
  interface PostsSliderSectionProps {
17
19
  section: any;
18
20
  currentBreakpoint?: string;
@@ -55,9 +57,7 @@ const getNestedValue = (source: unknown, path: string): unknown => {
55
57
  const cloneBlock = (block: any): any => ({
56
58
  ...block,
57
59
  properties: block.properties ? { ...block.properties } : block.properties,
58
- styles: block.styles
59
- ? safeDeepClone(block.styles)
60
- : block.styles,
60
+ styles: block.styles ? safeDeepClone(block.styles) : block.styles,
61
61
  blocks: block.blocks
62
62
  ? block.blocks.map((child: any) => cloneBlock(child))
63
63
  : undefined
@@ -378,20 +378,21 @@ const PostsSliderSection: React.FC<PostsSliderSectionProps> = ({
378
378
  const useInfinite = infinite && hasMultipleSlides;
379
379
  const useAutoPlay = autoPlay && hasMultipleSlides;
380
380
 
381
- const postBlockAction = (type: string, blockId: string, label?: string) => {
381
+ const postBlockAction = (
382
+ type: PreviewToEditorMessageType,
383
+ blockId: string,
384
+ label?: string
385
+ ) => {
382
386
  if (!window.parent) return;
383
- window.parent.postMessage(
384
- {
385
- type,
386
- data: {
387
- placeholderId,
388
- sectionId: section.id,
389
- blockId,
390
- ...(label ? { label } : {})
391
- }
392
- },
393
- '*'
394
- );
387
+ postToEditor({
388
+ type,
389
+ data: {
390
+ placeholderId,
391
+ sectionId: section.id,
392
+ blockId,
393
+ ...(label ? { label } : {})
394
+ }
395
+ });
395
396
  };
396
397
 
397
398
  if (expandedBlocks.length === 0) {