@standhigher/besttrack-page-extension 0.4.0 → 0.5.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/README.md +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +130 -77
- package/dist/validation.js +6 -5
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -25,7 +25,8 @@ should inject `transport` instead of inventing a new request body:
|
|
|
25
25
|
|
|
26
26
|
That path reuses the original lookup: `POST /track/query?_t=`, snake_case
|
|
27
27
|
`{ order_number, email, tracking_number, lang }`, one retry, independent
|
|
28
|
-
`POST /products/recommend` with `{ page, page_size }`,
|
|
28
|
+
`POST /products/recommend` with `{ page, page_size }`, the original Embla
|
|
29
|
+
recommendation carousel, and the original
|
|
29
30
|
progress / shipping / empty-state mapping. The host only supplies fetch,
|
|
30
31
|
App Proxy prefix, and credentials.
|
|
31
32
|
|
package/dist/index.d.ts
CHANGED
|
@@ -307,6 +307,7 @@ type ReadyToGoRuntimeProviderProps = {
|
|
|
307
307
|
/**
|
|
308
308
|
* Shopify Track Page live transport. When `query` is omitted, lookups use the
|
|
309
309
|
* original `/track/query` body, `_t` cache-bust, retry, and mapping rules.
|
|
310
|
+
* Recommendations still POST `/products/recommend` on mount, even if `query` is set.
|
|
310
311
|
*/
|
|
311
312
|
transport?: ShopifyTrackPageTransport;
|
|
312
313
|
/** When omitted, URL deep-link auto-query is on only for the Shopify Track Page `transport` path. */
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
} from "./chunk-KD7KFFFK.js";
|
|
15
15
|
|
|
16
16
|
// src/ready-to-go.tsx
|
|
17
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState as useState2 } from "react";
|
|
17
|
+
import { createContext, useCallback as useCallback2, useContext, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
18
|
+
import { parseProductReferences } from "@standhigher/puck-page-builder/runtime";
|
|
18
19
|
|
|
19
20
|
// src/shopify-track-page/i18n/locales.ts
|
|
20
21
|
var SUPPORTED_LOCALES = [
|
|
@@ -825,8 +826,10 @@ function createShopifyRecommendationsQuery(post) {
|
|
|
825
826
|
}
|
|
826
827
|
|
|
827
828
|
// src/track-page-display.tsx
|
|
828
|
-
import { useState } from "react";
|
|
829
|
-
import
|
|
829
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
830
|
+
import Autoplay from "embla-carousel-autoplay";
|
|
831
|
+
import useEmblaCarousel from "embla-carousel-react";
|
|
832
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
830
833
|
var pageFont = { fontFamily: "var(--pb-font-family, Inter, system-ui, sans-serif)" };
|
|
831
834
|
var contentWidth = {
|
|
832
835
|
width: "min(1248px, 100%)",
|
|
@@ -953,22 +956,81 @@ function PackageContents({ items }) {
|
|
|
953
956
|
}) });
|
|
954
957
|
}
|
|
955
958
|
function RecommendationCards({ items }) {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
959
|
+
const autoplay = useMemo(() => Autoplay({ delay: 3e3, stopOnInteraction: false, stopOnMouseEnter: true }), []);
|
|
960
|
+
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, align: "start", slidesToScroll: 1 }, [autoplay]);
|
|
961
|
+
const [canScrollPrev, setCanScrollPrev] = useState(false);
|
|
962
|
+
const [canScrollNext, setCanScrollNext] = useState(false);
|
|
963
|
+
const [hideButtons, setHideButtons] = useState(false);
|
|
964
|
+
const onSelect = useCallback(() => {
|
|
965
|
+
if (!emblaApi) return;
|
|
966
|
+
setCanScrollPrev(emblaApi.canScrollPrev());
|
|
967
|
+
setCanScrollNext(emblaApi.canScrollNext());
|
|
968
|
+
}, [emblaApi]);
|
|
969
|
+
useEffect(() => {
|
|
970
|
+
if (!emblaApi) return;
|
|
971
|
+
emblaApi.on("select", onSelect);
|
|
972
|
+
emblaApi.on("reInit", onSelect);
|
|
973
|
+
const frame = requestAnimationFrame(onSelect);
|
|
974
|
+
return () => {
|
|
975
|
+
cancelAnimationFrame(frame);
|
|
976
|
+
emblaApi.off("select", onSelect);
|
|
977
|
+
emblaApi.off("reInit", onSelect);
|
|
978
|
+
};
|
|
979
|
+
}, [emblaApi, onSelect]);
|
|
980
|
+
useEffect(() => {
|
|
981
|
+
if (typeof window.matchMedia !== "function") return;
|
|
982
|
+
const media = window.matchMedia("(max-width: 768px)");
|
|
983
|
+
const update = () => setHideButtons(media.matches);
|
|
984
|
+
const frame = requestAnimationFrame(update);
|
|
985
|
+
media.addEventListener("change", update);
|
|
986
|
+
return () => {
|
|
987
|
+
cancelAnimationFrame(frame);
|
|
988
|
+
media.removeEventListener("change", update);
|
|
989
|
+
};
|
|
990
|
+
}, []);
|
|
991
|
+
if (items.length === 0) return null;
|
|
992
|
+
const arrow = (points) => /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("polyline", { points }) });
|
|
993
|
+
const buttonStyle = {
|
|
994
|
+
position: "absolute",
|
|
995
|
+
top: 115,
|
|
996
|
+
zIndex: 2,
|
|
997
|
+
width: 32,
|
|
998
|
+
height: 32,
|
|
999
|
+
borderRadius: 99,
|
|
1000
|
+
border: 0,
|
|
1001
|
+
background: "#fff",
|
|
1002
|
+
boxShadow: "0 0 0.5px rgba(0, 0, 0, 0.12)",
|
|
1003
|
+
display: "flex",
|
|
1004
|
+
alignItems: "center",
|
|
1005
|
+
justifyContent: "center",
|
|
1006
|
+
cursor: "pointer",
|
|
1007
|
+
color: "#333",
|
|
1008
|
+
padding: 0
|
|
1009
|
+
};
|
|
1010
|
+
return /* @__PURE__ */ jsxs("div", { "aria-label": "Recommended products carousel", style: { position: "relative", marginLeft: 48, marginRight: 48 }, children: [
|
|
1011
|
+
!hideButtons && canScrollPrev ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Previous", onClick: () => emblaApi?.scrollPrev(), style: { ...buttonStyle, left: -40 }, children: arrow("15 18 9 12 15 6") }) : null,
|
|
1012
|
+
/* @__PURE__ */ jsx("div", { ref: emblaRef, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: { display: "flex" }, children: items.map((item) => {
|
|
1013
|
+
const href = safeHref(item.href);
|
|
1014
|
+
const card = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1015
|
+
/* @__PURE__ */ jsx("div", { style: { width: 262, height: 262, maxWidth: "100%", borderRadius: 8, border: "1px solid #E3E3E3", overflow: "hidden", background: "#f1f5f9" }, children: /* @__PURE__ */ jsx(ProductImage, { src: item.imageUrl, alt: item.title, size: 262 }) }),
|
|
1016
|
+
/* @__PURE__ */ jsxs("div", { style: { padding: "12px 8px", textAlign: "center", fontSize: 14 }, children: [
|
|
1017
|
+
/* @__PURE__ */ jsx("p", { style: { margin: 0, color: "#334155" }, children: item.title }),
|
|
1018
|
+
item.price && formatTrackingPageMoney(item.price)?.amount ? /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", fontWeight: 600, color: "#0f172a" }, children: formatTrackingPageMoney(item.price).amount }) : null,
|
|
1019
|
+
item.description ? /* @__PURE__ */ jsx("p", { style: { margin: "4px 0 0", color: "#64748b", fontSize: 13 }, children: item.description }) : null
|
|
1020
|
+
] })
|
|
1021
|
+
] });
|
|
1022
|
+
return /* @__PURE__ */ jsx("div", { style: { flex: "0 0 286px", minWidth: 0, paddingRight: 24, boxSizing: "border-box" }, children: href ? /* @__PURE__ */ jsx("a", { href, style: { display: "block", width: 262, maxWidth: "100%", textDecoration: "none", color: "inherit" }, children: card }) : /* @__PURE__ */ jsx("div", { style: { width: 262, maxWidth: "100%" }, children: card }) }, item.id);
|
|
1023
|
+
}) }) }),
|
|
1024
|
+
!hideButtons && canScrollNext ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Next", onClick: () => emblaApi?.scrollNext(), style: { ...buttonStyle, right: -40 }, children: arrow("9 18 15 12 9 6") }) : null
|
|
1025
|
+
] });
|
|
964
1026
|
}
|
|
965
|
-
function TrackingPageAdSlot({ ad
|
|
1027
|
+
function TrackingPageAdSlot({ ad }) {
|
|
966
1028
|
const [failedUrl, setFailedUrl] = useState();
|
|
967
1029
|
const imageUrl = safeImageUrl(ad?.imageUrl);
|
|
968
|
-
if (
|
|
969
|
-
const content =
|
|
1030
|
+
if (!imageUrl || failedUrl === imageUrl) return null;
|
|
1031
|
+
const content = /* @__PURE__ */ jsx("img", { src: imageUrl, alt: ad?.alt ?? "Promotion", loading: "lazy", onError: () => setFailedUrl(imageUrl), style: { display: "block", width: "100%", height: "auto", objectFit: "cover" } });
|
|
970
1032
|
const href = safeHref(ad?.href);
|
|
971
|
-
if (!
|
|
1033
|
+
if (!href) return /* @__PURE__ */ jsx("div", { "data-tracking-page-ad": true, children: content });
|
|
972
1034
|
return /* @__PURE__ */ jsx("a", { "data-tracking-page-ad": true, href, target: "_blank", rel: "noopener noreferrer", children: content });
|
|
973
1035
|
}
|
|
974
1036
|
function EstimatedDeliveryCard({ dateText }) {
|
|
@@ -1001,7 +1063,7 @@ function TrackingNotFound() {
|
|
|
1001
1063
|
}
|
|
1002
1064
|
|
|
1003
1065
|
// src/ready-to-go.tsx
|
|
1004
|
-
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1066
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1005
1067
|
var initialRuntime = {
|
|
1006
1068
|
phase: "idle",
|
|
1007
1069
|
recommendations: { phase: "idle", items: [] },
|
|
@@ -1037,23 +1099,20 @@ async function queryMockReadyToGoTracking(request) {
|
|
|
1037
1099
|
}
|
|
1038
1100
|
function ReadyToGoRuntimeProvider({ children, query: injectedQuery, queryRecommendations, transport, autoQueryFromUrl, watermark }) {
|
|
1039
1101
|
const [state, setState] = useState2({ phase: "idle" });
|
|
1040
|
-
const [recommendations, setRecommendations] = useState2(() => (
|
|
1041
|
-
phase: queryRecommendations || transport && !injectedQuery ? "loading" : "idle",
|
|
1042
|
-
items: []
|
|
1043
|
-
}));
|
|
1102
|
+
const [recommendations, setRecommendations] = useState2(() => queryRecommendations || transport ? { phase: "loading", items: [] } : { phase: "success", items: previewReadyToGoTracking().recommendations ?? [] });
|
|
1044
1103
|
const requestId = useRef(0);
|
|
1045
|
-
const resolvedQuery =
|
|
1104
|
+
const resolvedQuery = useMemo2(() => {
|
|
1046
1105
|
if (injectedQuery) return injectedQuery;
|
|
1047
1106
|
if (transport) return createShopifyTrackQuery(transport);
|
|
1048
1107
|
return void 0;
|
|
1049
1108
|
}, [injectedQuery, transport]);
|
|
1050
|
-
const resolvedRecommendations =
|
|
1109
|
+
const resolvedRecommendations = useMemo2(() => {
|
|
1051
1110
|
if (queryRecommendations) return queryRecommendations;
|
|
1052
|
-
if (transport
|
|
1111
|
+
if (transport) return createShopifyRecommendationsQuery(transport.post);
|
|
1053
1112
|
return void 0;
|
|
1054
|
-
}, [
|
|
1113
|
+
}, [queryRecommendations, transport]);
|
|
1055
1114
|
const live = Boolean(resolvedQuery);
|
|
1056
|
-
|
|
1115
|
+
useEffect2(() => {
|
|
1057
1116
|
if (!resolvedRecommendations) return;
|
|
1058
1117
|
let active = true;
|
|
1059
1118
|
void resolvedRecommendations().then((items) => {
|
|
@@ -1067,7 +1126,7 @@ function ReadyToGoRuntimeProvider({ children, query: injectedQuery, queryRecomme
|
|
|
1067
1126
|
active = false;
|
|
1068
1127
|
};
|
|
1069
1128
|
}, [resolvedRecommendations]);
|
|
1070
|
-
const query =
|
|
1129
|
+
const query = useCallback2(async (request) => {
|
|
1071
1130
|
const currentRequestId = ++requestId.current;
|
|
1072
1131
|
setState({ phase: "loading" });
|
|
1073
1132
|
try {
|
|
@@ -1080,11 +1139,11 @@ function ReadyToGoRuntimeProvider({ children, query: injectedQuery, queryRecomme
|
|
|
1080
1139
|
}
|
|
1081
1140
|
}, [live, resolvedQuery]);
|
|
1082
1141
|
const resolveAutoQuery = autoQueryFromUrl ?? Boolean(transport && !injectedQuery);
|
|
1083
|
-
const resolvedWatermark =
|
|
1142
|
+
const resolvedWatermark = useMemo2(
|
|
1084
1143
|
() => watermark ?? { visible: !shouldHidePoweredBy() },
|
|
1085
1144
|
[watermark]
|
|
1086
1145
|
);
|
|
1087
|
-
const value =
|
|
1146
|
+
const value = useMemo2(() => ({ ...state, query, recommendations, autoQueryFromUrl: resolveAutoQuery, watermark: resolvedWatermark }), [query, recommendations, resolveAutoQuery, resolvedWatermark, state]);
|
|
1088
1147
|
return /* @__PURE__ */ jsx3(ReadyToGoRuntimeContext.Provider, { value, children });
|
|
1089
1148
|
}
|
|
1090
1149
|
function useReadyToGoRuntime() {
|
|
@@ -1199,7 +1258,7 @@ function eventsFrom(result) {
|
|
|
1199
1258
|
}
|
|
1200
1259
|
function ProgressResult({ result, showEstimatedDelivery = true }) {
|
|
1201
1260
|
const steps = result.progress?.length ? result.progress : defaultProgress(result.status);
|
|
1202
|
-
return /* @__PURE__ */ jsxs3(
|
|
1261
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1203
1262
|
/* @__PURE__ */ jsxs3("p", { style: { margin: 0, fontSize: 20, lineHeight: 1.4, color: "#000" }, children: [
|
|
1204
1263
|
"Tracking: ",
|
|
1205
1264
|
result.trackingNumber
|
|
@@ -1209,14 +1268,14 @@ function ProgressResult({ result, showEstimatedDelivery = true }) {
|
|
|
1209
1268
|
/* @__PURE__ */ jsx3(TrackingProgress, { steps })
|
|
1210
1269
|
] });
|
|
1211
1270
|
}
|
|
1212
|
-
function DeliveryResult({ heading, contentsHeading, carrierHeading, result
|
|
1271
|
+
function DeliveryResult({ heading, contentsHeading, carrierHeading, result }) {
|
|
1213
1272
|
return /* @__PURE__ */ jsxs3("div", { style: { ...contentWidth, display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 280px), 500px))", gap: 40, justifyContent: "center", alignItems: "start" }, children: [
|
|
1214
1273
|
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1215
1274
|
/* @__PURE__ */ jsx3("h3", { style: { margin: 0, fontSize: 20, lineHeight: "20px", fontWeight: 700 }, children: heading }),
|
|
1216
1275
|
/* @__PURE__ */ jsx3(ShippingTimeline, { events: eventsFrom(result) })
|
|
1217
1276
|
] }),
|
|
1218
1277
|
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
|
|
1219
|
-
/* @__PURE__ */ jsx3(TrackingPageAdSlot, { ad: result.ad
|
|
1278
|
+
/* @__PURE__ */ jsx3(TrackingPageAdSlot, { ad: result.ad }),
|
|
1220
1279
|
/* @__PURE__ */ jsxs3("div", { children: [
|
|
1221
1280
|
/* @__PURE__ */ jsx3("h3", { style: { margin: "0 0 12px", fontSize: 18, fontWeight: 700 }, children: contentsHeading }),
|
|
1222
1281
|
/* @__PURE__ */ jsx3(PackageContents, { items: result.orderItems ?? [] })
|
|
@@ -1258,7 +1317,7 @@ function ReadyToGoQueryEditor(block) {
|
|
|
1258
1317
|
] }) });
|
|
1259
1318
|
}
|
|
1260
1319
|
function ReadyToGoProgressEditor() {
|
|
1261
|
-
return /* @__PURE__ */ jsx3("section", { "aria-label": "Ready-to-go progress editor", style: { ...pageFont, background: "var(--pb-color-background, #fff)", color: "var(--pb-color-text, #0f172a)", borderBottom: "1px solid #f1f5f9" }, children: /* @__PURE__ */ jsx3("div", { style: { ...contentWidth, textAlign: "center", width: "min(1248px, 100%)" }, children: /* @__PURE__ */ jsx3(ProgressResult, { result: previewReadyToGoTracking() }) }) });
|
|
1320
|
+
return /* @__PURE__ */ jsx3("section", { "aria-label": "Ready-to-go progress editor", style: { ...pageFont, background: "var(--pb-color-background, #fff)", color: "var(--pb-color-text, #0f172a)", borderBottom: "1px solid #f1f5f9" }, children: /* @__PURE__ */ jsx3("div", { style: { ...contentWidth, textAlign: "center", width: "min(1248px, 100%)" }, children: /* @__PURE__ */ jsx3(ProgressResult, { result: previewReadyToGoTracking(), showEstimatedDelivery: false }) }) });
|
|
1262
1321
|
}
|
|
1263
1322
|
function ReadyToGoDeliveryEditor(block) {
|
|
1264
1323
|
return /* @__PURE__ */ jsx3("section", { "aria-label": "Ready-to-go delivery editor", style: { ...pageFont, background: "var(--pb-color-background, #fff)", color: "var(--pb-color-text, #0f172a)", borderBottom: "1px solid #f1f5f9" }, children: /* @__PURE__ */ jsx3(
|
|
@@ -1267,16 +1326,22 @@ function ReadyToGoDeliveryEditor(block) {
|
|
|
1267
1326
|
heading: /* @__PURE__ */ jsx3(InlineText, { block, name: "heading", fallback: "Shipping Details" }),
|
|
1268
1327
|
contentsHeading: /* @__PURE__ */ jsx3(InlineText, { block, name: "contentsHeading", fallback: "Package Contents" }),
|
|
1269
1328
|
carrierHeading: /* @__PURE__ */ jsx3(InlineText, { block, name: "carrierHeading", fallback: "Carrier" }),
|
|
1270
|
-
result: previewReadyToGoTracking()
|
|
1271
|
-
editor: true
|
|
1329
|
+
result: previewReadyToGoTracking()
|
|
1272
1330
|
}
|
|
1273
1331
|
) });
|
|
1274
1332
|
}
|
|
1275
1333
|
function ReadyToGoRecommendationsEditor(block) {
|
|
1276
|
-
const
|
|
1334
|
+
const selected = parseProductReferences(block.products).map((product) => ({
|
|
1335
|
+
id: product.id,
|
|
1336
|
+
title: product.title || product.id,
|
|
1337
|
+
description: "",
|
|
1338
|
+
imageUrl: product.imageUrl,
|
|
1339
|
+
href: product.handle ? `/products/${product.handle}` : void 0
|
|
1340
|
+
}));
|
|
1341
|
+
const items = selected.length ? selected : previewReadyToGoTracking().recommendations ?? [];
|
|
1277
1342
|
return /* @__PURE__ */ jsx3("section", { "aria-label": "Ready-to-go recommendations editor", style: { ...pageFont, background: "var(--pb-color-background, #fff)", color: "var(--pb-color-text, #0f172a)" }, children: /* @__PURE__ */ jsxs3("div", { style: { ...contentWidth, padding: "48px 24px" }, children: [
|
|
1278
1343
|
/* @__PURE__ */ jsx3("h3", { style: { margin: 0, textAlign: "center", fontSize: 20, lineHeight: "20px", fontWeight: 700 }, children: /* @__PURE__ */ jsx3(InlineText, { block, name: "heading", fallback: "You may also like..." }) }),
|
|
1279
|
-
/* @__PURE__ */ jsx3("div", { style: { marginTop: 24 }, children: /* @__PURE__ */ jsx3(RecommendationCards, { items
|
|
1344
|
+
/* @__PURE__ */ jsx3("div", { style: { marginTop: 24 }, children: /* @__PURE__ */ jsx3(RecommendationCards, { items }) })
|
|
1280
1345
|
] }) });
|
|
1281
1346
|
}
|
|
1282
1347
|
function ReadyToGoQueryBlock(props) {
|
|
@@ -1292,7 +1357,7 @@ function ReadyToGoQueryBlock(props) {
|
|
|
1292
1357
|
const submitLabel = text(props, "submitLabel", "Track Your Order");
|
|
1293
1358
|
const trackingTabLabel = text(props, "trackingTabLabel", "Tracking Number");
|
|
1294
1359
|
const orderTabLabel = text(props, "orderTabLabel", "Order Number");
|
|
1295
|
-
|
|
1360
|
+
useEffect2(() => {
|
|
1296
1361
|
if (!locationState?.canAutoQuery || autoQueryStarted.current) return;
|
|
1297
1362
|
autoQueryStarted.current = true;
|
|
1298
1363
|
void runtime.query(locationState.tab === "tracking" ? { mode: "tracking", trackingNumber: locationState.trackingNumber } : { mode: "order", orderNumber: locationState.orderNumber, email: locationState.email });
|
|
@@ -1330,12 +1395,12 @@ function ReadyToGoQueryBlock(props) {
|
|
|
1330
1395
|
}, style: tabStyle(mode === "order"), children: orderTabLabel })
|
|
1331
1396
|
] }),
|
|
1332
1397
|
/* @__PURE__ */ jsxs3("form", { onSubmit: submit, style: { marginTop: 24, display: "flex", flexDirection: "column", gap: 16, flex: 1 }, children: [
|
|
1333
|
-
mode === "order" ? /* @__PURE__ */ jsxs3(
|
|
1398
|
+
mode === "order" ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1334
1399
|
/* @__PURE__ */ jsx3("label", { htmlFor: "ready-to-go-order-number", style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clipPath: "inset(50%)" }, children: "Order number" }),
|
|
1335
1400
|
/* @__PURE__ */ jsx3("input", { id: "ready-to-go-order-number", "aria-label": "Order number", value: orderNumber, onChange: (event) => setOrderNumber(event.target.value), placeholder: "Order Number", style: inputStyle }),
|
|
1336
1401
|
/* @__PURE__ */ jsx3("label", { htmlFor: "ready-to-go-email", style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clipPath: "inset(50%)" }, children: "Email" }),
|
|
1337
1402
|
/* @__PURE__ */ jsx3("input", { id: "ready-to-go-email", "aria-label": "Email", value: email, onChange: (event) => setEmail(event.target.value), placeholder: "Email", style: inputStyle })
|
|
1338
|
-
] }) : /* @__PURE__ */ jsxs3(
|
|
1403
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1339
1404
|
/* @__PURE__ */ jsx3("label", { htmlFor: "ready-to-go-tracking-number", style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clipPath: "inset(50%)" }, children: "Tracking number" }),
|
|
1340
1405
|
/* @__PURE__ */ jsx3("input", { id: "ready-to-go-tracking-number", "aria-label": "Tracking number", value: trackingNumber, onChange: (event) => setTrackingNumber(event.target.value), placeholder: "Tracking Number", style: inputStyle })
|
|
1341
1406
|
] }),
|
|
@@ -1376,25 +1441,10 @@ function ReadyToGoDeliveryBlock(props) {
|
|
|
1376
1441
|
function ReadyToGoRecommendationsBlock(props) {
|
|
1377
1442
|
const runtime = useReadyToGoRuntime();
|
|
1378
1443
|
const heading = text(props, "heading", "You may also like...");
|
|
1379
|
-
|
|
1380
|
-
if (independent) {
|
|
1381
|
-
if (runtime.recommendations.phase !== "success" || runtime.recommendations.items.length === 0) return null;
|
|
1382
|
-
return /* @__PURE__ */ jsx3(SectionShell, { title: heading, bordered: false, children: /* @__PURE__ */ jsxs3("div", { style: { ...contentWidth, padding: "48px 24px" }, children: [
|
|
1383
|
-
/* @__PURE__ */ jsx3("h3", { style: { margin: 0, textAlign: "center", fontSize: 20, lineHeight: "20px", fontWeight: 700 }, children: heading }),
|
|
1384
|
-
/* @__PURE__ */ jsx3("div", { style: { marginTop: 24 }, children: /* @__PURE__ */ jsx3(RecommendationCards, { items: runtime.recommendations.items }) })
|
|
1385
|
-
] }) });
|
|
1386
|
-
}
|
|
1387
|
-
if (runtime.phase === "empty") return null;
|
|
1388
|
-
const recommendations = runtime.result?.recommendations ?? [];
|
|
1444
|
+
if (runtime.recommendations.phase !== "success" || runtime.recommendations.items.length === 0) return null;
|
|
1389
1445
|
return /* @__PURE__ */ jsx3(SectionShell, { title: heading, bordered: false, children: /* @__PURE__ */ jsxs3("div", { style: { ...contentWidth, padding: "48px 24px" }, children: [
|
|
1390
1446
|
/* @__PURE__ */ jsx3("h3", { style: { margin: 0, textAlign: "center", fontSize: 20, lineHeight: "20px", fontWeight: 700 }, children: heading }),
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
runtime.phase === "loading" ? /* @__PURE__ */ jsx3(IdleMessage, { children: "Loading recommendations\u2026" }) : null,
|
|
1393
|
-
runtime.phase === "error" ? /* @__PURE__ */ jsx3("p", { style: { margin: 0, textAlign: "center", color: "#b42318" }, children: "Recommendations are temporarily unavailable." }) : null,
|
|
1394
|
-
runtime.phase === "idle" ? /* @__PURE__ */ jsx3(IdleMessage, { children: "Recommendations appear with your shipment result." }) : null,
|
|
1395
|
-
runtime.phase === "success" && recommendations.length ? /* @__PURE__ */ jsx3(RecommendationCards, { items: recommendations }) : null,
|
|
1396
|
-
runtime.phase === "success" && !recommendations.length ? /* @__PURE__ */ jsx3(IdleMessage, { children: "No recommendations are available for this shipment." }) : null
|
|
1397
|
-
] })
|
|
1447
|
+
/* @__PURE__ */ jsx3("div", { style: { marginTop: 24 }, children: /* @__PURE__ */ jsx3(RecommendationCards, { items: runtime.recommendations.items }) })
|
|
1398
1448
|
] }) });
|
|
1399
1449
|
}
|
|
1400
1450
|
|
|
@@ -1476,10 +1526,13 @@ var readyToGoBlocks = withTemplatePolicy([
|
|
|
1476
1526
|
label: "Recommended products",
|
|
1477
1527
|
category: "BestTrack Ready-to-go",
|
|
1478
1528
|
targets: ["web"],
|
|
1479
|
-
defaultProps: { heading: "You may also like..." },
|
|
1529
|
+
defaultProps: { heading: "You may also like...", products: [] },
|
|
1480
1530
|
defaultVariant: "default",
|
|
1481
1531
|
variants: [{ id: "default", label: "Default" }, { id: "grid", label: "Grid", theme: { "color.surface": "#ffffff" } }],
|
|
1482
|
-
fields: {
|
|
1532
|
+
fields: {
|
|
1533
|
+
heading: text2("Heading"),
|
|
1534
|
+
products: { field: "besttrack.ready-to-go.products", label: "\u63A8\u8350\u5546\u54C1 (Shopify)", control: "products", group: "Content" }
|
|
1535
|
+
},
|
|
1483
1536
|
render: { web: ReadyToGoRecommendationsBlock, editor: ReadyToGoRecommendationsEditor }
|
|
1484
1537
|
}
|
|
1485
1538
|
], ["besttrack.ready-to-go.query"]);
|
|
@@ -1537,11 +1590,11 @@ var bestTrackPageExtension = Object.freeze({
|
|
|
1537
1590
|
import { createPageDocument as createPageDocument2 } from "@standhigher/puck-page-builder/runtime";
|
|
1538
1591
|
|
|
1539
1592
|
// src/branded.tsx
|
|
1540
|
-
import { createContext as createContext2, useCallback as
|
|
1593
|
+
import { createContext as createContext2, useCallback as useCallback3, useContext as useContext2, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
1541
1594
|
|
|
1542
1595
|
// src/tracking-query-experience.tsx
|
|
1543
|
-
import { useEffect as
|
|
1544
|
-
import { Fragment as
|
|
1596
|
+
import { useEffect as useEffect3, useId, useRef as useRef2, useState as useState3 } from "react";
|
|
1597
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1545
1598
|
var srOnly = {
|
|
1546
1599
|
position: "absolute",
|
|
1547
1600
|
width: 1,
|
|
@@ -1645,7 +1698,7 @@ function TrackingQueryCard({
|
|
|
1645
1698
|
const tabRefs = useRef2({ tracking: null, order: null });
|
|
1646
1699
|
const loading = phase === "loading";
|
|
1647
1700
|
const terminalPhase = phase === "success" || phase === "empty" || phase === "error";
|
|
1648
|
-
|
|
1701
|
+
useEffect3(() => {
|
|
1649
1702
|
if (!terminalPhase) return;
|
|
1650
1703
|
const card = cardRef.current;
|
|
1651
1704
|
const resultNode = resultRef.current;
|
|
@@ -1722,7 +1775,7 @@ function TrackingQueryCard({
|
|
|
1722
1775
|
clearError("tracking");
|
|
1723
1776
|
}, placeholder: trackingPlaceholder, style: inputWithError("tracking") }),
|
|
1724
1777
|
errorFor("tracking") ? /* @__PURE__ */ jsx4("p", { id: trackingInputId + "-error", role: "alert", style: { margin: "6px 0 0", color: "#b42318", fontSize: 13 }, children: errorFor("tracking") }) : null
|
|
1725
|
-
] }) : /* @__PURE__ */ jsxs4(
|
|
1778
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1726
1779
|
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1727
1780
|
/* @__PURE__ */ jsx4("label", { htmlFor: orderInputId, style: srOnly, children: orderInputLabel }),
|
|
1728
1781
|
/* @__PURE__ */ jsx4("input", { ref: orderInputRef, id: orderInputId, "aria-label": orderInputLabel, "aria-invalid": Boolean(errorFor("order")), "aria-describedby": errorFor("order") ? orderInputId + "-error" : void 0, value: orderNumber, onChange: (event) => {
|
|
@@ -1898,7 +1951,7 @@ function BrandedRuntimeProvider({ children, query: injectedQuery, watermark }) {
|
|
|
1898
1951
|
const [state, setState] = useState4({ phase: "idle" });
|
|
1899
1952
|
const [selectedShipmentId, setSelectedShipmentId] = useState4(null);
|
|
1900
1953
|
const requestId = useRef3(0);
|
|
1901
|
-
const query =
|
|
1954
|
+
const query = useCallback3(async (request) => {
|
|
1902
1955
|
const currentRequestId = ++requestId.current;
|
|
1903
1956
|
setState({ phase: "loading" });
|
|
1904
1957
|
try {
|
|
@@ -1912,20 +1965,20 @@ function BrandedRuntimeProvider({ children, query: injectedQuery, watermark }) {
|
|
|
1912
1965
|
setState({ phase: "error", error: "tracking-query-failed" });
|
|
1913
1966
|
}
|
|
1914
1967
|
}, [injectedQuery]);
|
|
1915
|
-
const reset =
|
|
1968
|
+
const reset = useCallback3(() => {
|
|
1916
1969
|
requestId.current += 1;
|
|
1917
1970
|
setSelectedShipmentId(null);
|
|
1918
1971
|
setState({ phase: "idle" });
|
|
1919
1972
|
}, []);
|
|
1920
|
-
const displayedResult =
|
|
1973
|
+
const displayedResult = useMemo3(() => {
|
|
1921
1974
|
if (!state.result) return void 0;
|
|
1922
1975
|
const shipment = state.result.shipments?.find((item) => item.id === selectedShipmentId);
|
|
1923
1976
|
return shipment ? { ...state.result, ...shipment } : state.result;
|
|
1924
1977
|
}, [selectedShipmentId, state.result]);
|
|
1925
|
-
const selectShipment =
|
|
1978
|
+
const selectShipment = useCallback3((id) => {
|
|
1926
1979
|
if (state.result?.shipments?.some((shipment) => shipment.id === id)) setSelectedShipmentId(id);
|
|
1927
1980
|
}, [state.result]);
|
|
1928
|
-
const value =
|
|
1981
|
+
const value = useMemo3(
|
|
1929
1982
|
() => ({ ...state, displayedResult, selectedShipmentId, query, reset, selectShipment, watermark }),
|
|
1930
1983
|
[displayedResult, query, reset, selectedShipmentId, selectShipment, state, watermark]
|
|
1931
1984
|
);
|
|
@@ -2228,8 +2281,8 @@ var bestTrackBrandedExtension = Object.freeze({ name: "besttrack.branded", versi
|
|
|
2228
2281
|
import { createPageDocument as createPageDocument3 } from "@standhigher/puck-page-builder/runtime";
|
|
2229
2282
|
|
|
2230
2283
|
// src/sales.tsx
|
|
2231
|
-
import { createContext as createContext3, useCallback as
|
|
2232
|
-
import { Fragment as
|
|
2284
|
+
import { createContext as createContext3, useCallback as useCallback4, useContext as useContext3, useMemo as useMemo4, useRef as useRef4, useState as useState5 } from "react";
|
|
2285
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2233
2286
|
var initialRuntime3 = { phase: "idle", async query() {
|
|
2234
2287
|
return void 0;
|
|
2235
2288
|
} };
|
|
@@ -2241,7 +2294,7 @@ var gridStyle = { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax
|
|
|
2241
2294
|
function SalesRuntimeProvider({ children, query: injectedQuery, watermark, resourceResolution }) {
|
|
2242
2295
|
const [state, setState] = useState5({ phase: "idle" });
|
|
2243
2296
|
const requestId = useRef4(0);
|
|
2244
|
-
const query =
|
|
2297
|
+
const query = useCallback4(async (request) => {
|
|
2245
2298
|
const currentRequestId = ++requestId.current;
|
|
2246
2299
|
setState({ phase: "loading" });
|
|
2247
2300
|
try {
|
|
@@ -2254,7 +2307,7 @@ function SalesRuntimeProvider({ children, query: injectedQuery, watermark, resou
|
|
|
2254
2307
|
setState({ phase: "error" });
|
|
2255
2308
|
}
|
|
2256
2309
|
}, [injectedQuery]);
|
|
2257
|
-
const value =
|
|
2310
|
+
const value = useMemo4(() => ({ ...state, query, watermark, resourceResolution }), [query, resourceResolution, state, watermark]);
|
|
2258
2311
|
return /* @__PURE__ */ jsx6(SalesRuntimeContext.Provider, { value, children });
|
|
2259
2312
|
}
|
|
2260
2313
|
function useSalesRuntime() {
|
|
@@ -2455,7 +2508,7 @@ function SalesOrderItemsBlock(props) {
|
|
|
2455
2508
|
"Qty ",
|
|
2456
2509
|
Number.isFinite(item.quantity) && item.quantity > 0 ? item.quantity : 1
|
|
2457
2510
|
] }),
|
|
2458
|
-
item.description ? /* @__PURE__ */ jsxs6(
|
|
2511
|
+
item.description ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2459
2512
|
/* @__PURE__ */ jsx6("br", {}),
|
|
2460
2513
|
/* @__PURE__ */ jsx6("small", { style: { color: "var(--pb-color-muted)" }, children: item.description })
|
|
2461
2514
|
] }) : null
|
|
@@ -2496,7 +2549,7 @@ function SalesProductCategoriesBlock(props) {
|
|
|
2496
2549
|
const error = getShopifyResourceResolutionError(collection, runtime.resourceResolution);
|
|
2497
2550
|
if (error) return /* @__PURE__ */ jsx6(Section, { title, children: /* @__PURE__ */ jsx6(Status, { alert: true, children: error.code === "missing" ? "This collection is no longer available." : "Collection details are temporarily unavailable." }) });
|
|
2498
2551
|
if (!resolved) return /* @__PURE__ */ jsx6(Section, { title, children: /* @__PURE__ */ jsx6(Status, { children: "Collection details are resolved by the authorized runtime." }) });
|
|
2499
|
-
const content = /* @__PURE__ */ jsxs6(
|
|
2552
|
+
const content = /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2500
2553
|
/* @__PURE__ */ jsx6("span", { children: resolved.title }),
|
|
2501
2554
|
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", children: "\u2192" })
|
|
2502
2555
|
] });
|
|
@@ -2514,7 +2567,7 @@ function SalesFeaturedProductBlock(props) {
|
|
|
2514
2567
|
if (error) return /* @__PURE__ */ jsx6(Section, { title, children: /* @__PURE__ */ jsx6(Status, { alert: true, children: error.code === "missing" ? "This product is no longer available." : "Product details are temporarily unavailable." }) });
|
|
2515
2568
|
if (!resolved) return /* @__PURE__ */ jsx6(Section, { title, children: /* @__PURE__ */ jsx6(Status, { children: "Product details and availability are resolved by the authorized runtime." }) });
|
|
2516
2569
|
const available = resolved.availability === "available";
|
|
2517
|
-
const body = /* @__PURE__ */ jsxs6(
|
|
2570
|
+
const body = /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2518
2571
|
/* @__PURE__ */ jsx6(ProductImage3, { src: resolved.imageUrl, alt: resolved.title }),
|
|
2519
2572
|
/* @__PURE__ */ jsxs6("span", { style: { minWidth: 0, flex: 1 }, children: [
|
|
2520
2573
|
/* @__PURE__ */ jsx6("strong", { children: resolved.title }),
|
|
@@ -2545,7 +2598,7 @@ function SalesRecommendationsBlock(props) {
|
|
|
2545
2598
|
}
|
|
2546
2599
|
|
|
2547
2600
|
// src/shopify-resources.tsx
|
|
2548
|
-
import { createContext as createContext4, useCallback as
|
|
2601
|
+
import { createContext as createContext4, useCallback as useCallback5, useContext as useContext4, useState as useState6 } from "react";
|
|
2549
2602
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2550
2603
|
var ShopifyResourceBrowserContext = createContext4(void 0);
|
|
2551
2604
|
function ShopifyResourcePickerProvider({ browser, children }) {
|
|
@@ -2561,7 +2614,7 @@ function ResourceField({ value, onChange, kind }) {
|
|
|
2561
2614
|
const [items, setItems] = useState6([]);
|
|
2562
2615
|
const [cursor, setCursor] = useState6();
|
|
2563
2616
|
const [state, setState] = useState6("idle");
|
|
2564
|
-
const search =
|
|
2617
|
+
const search = useCallback5(async (nextQuery, nextCursor, append = false) => {
|
|
2565
2618
|
if (!browser) return;
|
|
2566
2619
|
setState("loading");
|
|
2567
2620
|
try {
|
package/dist/validation.js
CHANGED
|
@@ -6,15 +6,16 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// src/validation.ts
|
|
8
8
|
var textField = { field: "besttrack.validation.text", control: "text" };
|
|
9
|
+
var productsField = { field: "besttrack.validation.products", control: "products" };
|
|
9
10
|
var strictUrlField = {
|
|
10
11
|
field: "besttrack.validation.url",
|
|
11
12
|
control: "url",
|
|
12
13
|
validation: { allowRelativeUrl: false, allowedUrlProtocols: ["https:"], allowLocalhost: true }
|
|
13
14
|
};
|
|
14
|
-
function fields(keys, urlKeys = [], resourceKeys = []) {
|
|
15
|
-
return Object.fromEntries(keys.map((key) => [key, resourceKeys.includes(key) ? { field: "besttrack.validation.resource" } : urlKeys.includes(key) ? strictUrlField : textField]));
|
|
15
|
+
function fields(keys, urlKeys = [], resourceKeys = [], productsKeys = []) {
|
|
16
|
+
return Object.fromEntries(keys.map((key) => [key, productsKeys.includes(key) ? productsField : resourceKeys.includes(key) ? { field: "besttrack.validation.resource" } : urlKeys.includes(key) ? strictUrlField : textField]));
|
|
16
17
|
}
|
|
17
|
-
function block(type, version, keys, variants, validate, urlKeys = [], resourceKeys = []) {
|
|
18
|
+
function block(type, version, keys, variants, validate, urlKeys = [], resourceKeys = [], productsKeys = []) {
|
|
18
19
|
return {
|
|
19
20
|
type,
|
|
20
21
|
version,
|
|
@@ -22,7 +23,7 @@ function block(type, version, keys, variants, validate, urlKeys = [], resourceKe
|
|
|
22
23
|
category: "BestTrack",
|
|
23
24
|
targets: ["web"],
|
|
24
25
|
defaultProps: {},
|
|
25
|
-
fields: fields(keys, urlKeys, resourceKeys),
|
|
26
|
+
fields: fields(keys, urlKeys, resourceKeys, productsKeys),
|
|
26
27
|
defaultVariant: variants[0],
|
|
27
28
|
variants: variants.map((id) => ({ id, label: id })),
|
|
28
29
|
validate,
|
|
@@ -69,7 +70,7 @@ var readyToGoContracts = [
|
|
|
69
70
|
block("besttrack.ready-to-go.query", 1, ["heading", "submitLabel", "defaultTrackingNumber", "defaultOrderNumber", "defaultQueryMode", "trackingTabLabel", "orderTabLabel"], ["default"]),
|
|
70
71
|
block("besttrack.ready-to-go.progress", 1, [], ["default"]),
|
|
71
72
|
block("besttrack.ready-to-go.delivery", 1, ["heading", "contentsHeading", "carrierHeading"], ["default", "compact"]),
|
|
72
|
-
block("besttrack.ready-to-go.recommendations", 1, ["heading"], ["default", "grid"])
|
|
73
|
+
block("besttrack.ready-to-go.recommendations", 1, ["heading", "products"], ["default", "grid"], void 0, [], [], ["products"])
|
|
73
74
|
];
|
|
74
75
|
var brandedContracts = [
|
|
75
76
|
block("besttrack.branded.announcement", 1, ["message", "href"], ["brand", "minimal"], void 0, ["href"]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standhigher/besttrack-page-extension",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "BestTrack business extension entry point for @standhigher/puck-page-builder.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"
|
|
23
|
+
"embla-carousel-autoplay": "^8.6.0",
|
|
24
|
+
"embla-carousel-react": "^8.6.0",
|
|
25
|
+
"@standhigher/puck-page-builder": "0.12.0"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"tsup": "^8.5.1",
|