@standhigher/besttrack-page-extension 0.2.1 → 0.3.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 +22 -2
- package/dist/index.d.ts +44 -25
- package/dist/index.js +298 -74
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# @standhigher/besttrack-page-extension
|
|
2
2
|
|
|
3
3
|
V0.7.1 adds the besttrack.branded built-in template. Its announcement, order
|
|
4
|
-
query, order items, recommendations, quick links and Blog blocks use the
|
|
5
|
-
host-injected
|
|
4
|
+
query, order items, recommendations, quick links and Blog blocks use the
|
|
5
|
+
shared, host-injected `TrackingPageQuery` contract. The
|
|
6
|
+
`ReadyToGoTrackingQuery` name remains a compatible alias. Logo and content are
|
|
6
7
|
JSON-only block props; brand colour, font and radius use the template Theme
|
|
7
8
|
Tokens and may be overridden through PageDocument.theme.
|
|
8
9
|
|
|
@@ -12,3 +13,22 @@ the Shopify Track Page layout (query card, five-step progress, shipping
|
|
|
12
13
|
timeline, package contents and product cards) using inline styles and `--pb-*`
|
|
13
14
|
Theme Tokens. Live tracking is injected by the host Runtime; this package never
|
|
14
15
|
stores credentials or network endpoints in a `PageDocument`.
|
|
16
|
+
|
|
17
|
+
V0.7.2 Sales uses the shared, transient `TrackingPageQuery` contract exported
|
|
18
|
+
by this package. The external Go Consumer Runtime API owns live-query
|
|
19
|
+
authorization and transport; Sales only receives its display-safe result and
|
|
20
|
+
never falls back to mock data after a live failure.
|
|
21
|
+
|
|
22
|
+
Sales keeps the stable `besttrack.sales` v1 template and seven block IDs.
|
|
23
|
+
Its host must inject the query from an authorized Consumer Runtime flow; this
|
|
24
|
+
package provides neither a Go client nor a BFF. The editor validates
|
|
25
|
+
merchant-authored text, preview-only tracking placeholders and collection
|
|
26
|
+
links, while the storefront renders only site-relative or HTTPS resource
|
|
27
|
+
links. See `docs/integration/sales-template.md` and
|
|
28
|
+
`docs/integration/consumer-runtime-api.md` for the host contract.
|
|
29
|
+
|
|
30
|
+
New Sales pages use the `hero` visual Variant: a token-driven announcement,
|
|
31
|
+
merchant HTTPS hero image and tracking-only query card. Existing `commerce`
|
|
32
|
+
Variants and published v1 documents stay valid. The browser does not offer an
|
|
33
|
+
order-number mode because the shared Consumer Runtime API currently accepts
|
|
34
|
+
only a tracking number.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,14 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { PageBuilderExtension, TemplateDefinition } from '@standhigher/puck-page-builder/runtime';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Display-safe, transient data returned by a Consumer Runtime query.
|
|
7
|
+
*
|
|
8
|
+
* These types intentionally describe the boundary between a storefront host
|
|
9
|
+
* and the template. They are not PageDocument props and must never be saved
|
|
10
|
+
* with a draft or published document.
|
|
11
|
+
*/
|
|
12
|
+
type TrackingPageOrderItem = {
|
|
6
13
|
id: string;
|
|
7
14
|
title: string;
|
|
8
15
|
quantity: number;
|
|
@@ -10,7 +17,7 @@ type ReadyToGoOrderItem = {
|
|
|
10
17
|
description?: string;
|
|
11
18
|
href?: string;
|
|
12
19
|
};
|
|
13
|
-
type
|
|
20
|
+
type TrackingPageRecommendation = {
|
|
14
21
|
id: string;
|
|
15
22
|
title: string;
|
|
16
23
|
description: string;
|
|
@@ -18,21 +25,21 @@ type ReadyToGoRecommendation = {
|
|
|
18
25
|
href?: string;
|
|
19
26
|
price?: string;
|
|
20
27
|
};
|
|
21
|
-
type
|
|
28
|
+
type TrackingPageTrackingStep = {
|
|
22
29
|
id: string;
|
|
23
30
|
label: string;
|
|
24
31
|
state: "complete" | "current" | "upcoming";
|
|
25
32
|
date?: string;
|
|
26
33
|
icon?: "check" | "bag" | "truck" | "box";
|
|
27
34
|
};
|
|
28
|
-
type
|
|
35
|
+
type TrackingPageTrackingEvent = {
|
|
29
36
|
id: string;
|
|
30
37
|
title: string;
|
|
31
38
|
at?: string;
|
|
32
39
|
detail?: string;
|
|
33
40
|
state?: "complete" | "current" | "upcoming";
|
|
34
41
|
};
|
|
35
|
-
type
|
|
42
|
+
type TrackingPageShipment = {
|
|
36
43
|
id: string;
|
|
37
44
|
label: string;
|
|
38
45
|
trackingNumber?: string;
|
|
@@ -42,12 +49,14 @@ type ReadyToGoShipment = {
|
|
|
42
49
|
updatedAt?: string;
|
|
43
50
|
deliveryAddress?: string;
|
|
44
51
|
estimatedDelivery?: string;
|
|
45
|
-
progress?:
|
|
46
|
-
events?:
|
|
47
|
-
orderItems?:
|
|
48
|
-
recommendations?:
|
|
52
|
+
progress?: TrackingPageTrackingStep[];
|
|
53
|
+
events?: TrackingPageTrackingEvent[];
|
|
54
|
+
orderItems?: TrackingPageOrderItem[];
|
|
55
|
+
recommendations?: TrackingPageRecommendation[];
|
|
49
56
|
};
|
|
50
|
-
type
|
|
57
|
+
type TrackingPageQueryResult = {
|
|
58
|
+
/** `empty` is a successful query with no customer-visible tracking result. */
|
|
59
|
+
outcome?: "found" | "empty";
|
|
51
60
|
trackingNumber: string;
|
|
52
61
|
status: string;
|
|
53
62
|
carrier?: string;
|
|
@@ -55,13 +64,22 @@ type ReadyToGoTrackingResult = {
|
|
|
55
64
|
updatedAt?: string;
|
|
56
65
|
deliveryAddress?: string;
|
|
57
66
|
estimatedDelivery?: string;
|
|
58
|
-
progress?:
|
|
59
|
-
events?:
|
|
60
|
-
orderItems?:
|
|
61
|
-
recommendations?:
|
|
62
|
-
shipments?:
|
|
67
|
+
progress?: TrackingPageTrackingStep[];
|
|
68
|
+
events?: TrackingPageTrackingEvent[];
|
|
69
|
+
orderItems?: TrackingPageOrderItem[];
|
|
70
|
+
recommendations?: TrackingPageRecommendation[];
|
|
71
|
+
shipments?: TrackingPageShipment[];
|
|
63
72
|
};
|
|
64
|
-
|
|
73
|
+
/** The UI receives an injected function; it never knows a Go endpoint or credential. */
|
|
74
|
+
type TrackingPageQuery = (trackingNumber: string) => Promise<TrackingPageQueryResult>;
|
|
75
|
+
type TrackingPageRuntimePhase = "idle" | "loading" | "success" | "empty" | "error";
|
|
76
|
+
declare function isEmptyTrackingPageResult(result: TrackingPageQueryResult): boolean;
|
|
77
|
+
|
|
78
|
+
type ReadyToGoTrackingStep = TrackingPageTrackingStep;
|
|
79
|
+
type ReadyToGoTrackingEvent = TrackingPageTrackingEvent;
|
|
80
|
+
type ReadyToGoShipment = TrackingPageShipment;
|
|
81
|
+
type ReadyToGoTrackingResult = TrackingPageQueryResult;
|
|
82
|
+
type ReadyToGoTrackingQuery = TrackingPageQuery;
|
|
65
83
|
type ReadyToGoRuntimeState = {
|
|
66
84
|
phase: "idle" | "loading" | "success" | "error";
|
|
67
85
|
result?: ReadyToGoTrackingResult;
|
|
@@ -79,31 +97,32 @@ declare const bestTrackPageExtension: PageBuilderExtension;
|
|
|
79
97
|
declare function createBrandedTemplate(): TemplateDefinition;
|
|
80
98
|
declare const bestTrackBrandedExtension: PageBuilderExtension;
|
|
81
99
|
|
|
100
|
+
/** Branded uses the shared, display-safe Consumer Runtime result without persisting it. */
|
|
82
101
|
type BrandedRuntimeState = {
|
|
83
|
-
phase:
|
|
84
|
-
result?:
|
|
102
|
+
phase: TrackingPageRuntimePhase;
|
|
103
|
+
result?: TrackingPageQueryResult;
|
|
85
104
|
error?: string;
|
|
86
105
|
};
|
|
87
106
|
type BrandedRuntimeProviderProps = {
|
|
88
107
|
children: ReactNode;
|
|
89
|
-
queryTracking:
|
|
108
|
+
queryTracking: TrackingPageQuery;
|
|
90
109
|
};
|
|
91
110
|
declare function BrandedRuntimeProvider({ children, queryTracking }: BrandedRuntimeProviderProps): react.JSX.Element;
|
|
92
111
|
|
|
112
|
+
/** Stable Sales v1 document and block IDs are intentionally retained for published-page compatibility. */
|
|
93
113
|
declare function createSalesTemplate(): TemplateDefinition;
|
|
94
114
|
declare const bestTrackSalesExtension: PageBuilderExtension;
|
|
95
115
|
|
|
96
|
-
|
|
116
|
+
/** Transient, consumer-safe state. The host error is deliberately never retained for display. */
|
|
97
117
|
type SalesRuntimeState = {
|
|
98
|
-
phase:
|
|
99
|
-
result?:
|
|
100
|
-
error?: string;
|
|
118
|
+
phase: TrackingPageRuntimePhase;
|
|
119
|
+
result?: TrackingPageQueryResult;
|
|
101
120
|
};
|
|
102
121
|
type SalesRuntimeProviderProps = {
|
|
103
122
|
children: ReactNode;
|
|
104
|
-
queryTracking:
|
|
123
|
+
queryTracking: TrackingPageQuery;
|
|
105
124
|
};
|
|
106
125
|
/** The host injects a validated query; Sales never calls a DataSource itself. */
|
|
107
126
|
declare function SalesRuntimeProvider({ children, queryTracking }: SalesRuntimeProviderProps): react.JSX.Element;
|
|
108
127
|
|
|
109
|
-
export { BrandedRuntimeProvider, type BrandedRuntimeProviderProps, type BrandedRuntimeState, ReadyToGoRuntimeProvider, type ReadyToGoRuntimeProviderProps, type ReadyToGoRuntimeState, type ReadyToGoShipment, type ReadyToGoTrackingEvent, type ReadyToGoTrackingQuery, type ReadyToGoTrackingResult, type ReadyToGoTrackingStep, SalesRuntimeProvider, type SalesRuntimeProviderProps, type SalesRuntimeState, bestTrackBrandedExtension, bestTrackPageExtension, bestTrackSalesExtension, createBrandedTemplate, createReadyToGoTemplate, createSalesTemplate };
|
|
128
|
+
export { BrandedRuntimeProvider, type BrandedRuntimeProviderProps, type BrandedRuntimeState, ReadyToGoRuntimeProvider, type ReadyToGoRuntimeProviderProps, type ReadyToGoRuntimeState, type ReadyToGoShipment, type ReadyToGoTrackingEvent, type ReadyToGoTrackingQuery, type ReadyToGoTrackingResult, type ReadyToGoTrackingStep, SalesRuntimeProvider, type SalesRuntimeProviderProps, type SalesRuntimeState, type TrackingPageOrderItem, type TrackingPageQuery, type TrackingPageQueryResult, type TrackingPageRecommendation, type TrackingPageRuntimePhase, type TrackingPageShipment, type TrackingPageTrackingEvent, type TrackingPageTrackingStep, bestTrackBrandedExtension, bestTrackPageExtension, bestTrackSalesExtension, createBrandedTemplate, createReadyToGoTemplate, createSalesTemplate, isEmptyTrackingPageResult };
|
package/dist/index.js
CHANGED
|
@@ -345,7 +345,7 @@ function ReadyToGoQueryEditor(block) {
|
|
|
345
345
|
/* @__PURE__ */ jsx2("p", { style: { marginTop: "auto", paddingTop: 28, textAlign: "center", fontSize: 12, lineHeight: "17px", fontStyle: "italic", color: "#b8b8b8" }, children: "Powered by BestTrack" })
|
|
346
346
|
] }) });
|
|
347
347
|
}
|
|
348
|
-
function ReadyToGoProgressEditor(
|
|
348
|
+
function ReadyToGoProgressEditor() {
|
|
349
349
|
return /* @__PURE__ */ jsx2("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__ */ jsx2("div", { style: { ...contentWidth, textAlign: "center", width: "min(1248px, 100%)" }, children: /* @__PURE__ */ jsx2(ProgressResult, { showEstimatedDelivery: false, result: previewReadyToGoTracking() }) }) });
|
|
350
350
|
}
|
|
351
351
|
function ReadyToGoDeliveryEditor(block) {
|
|
@@ -577,7 +577,14 @@ var bestTrackPageExtension = Object.freeze({
|
|
|
577
577
|
import { createPageDocument as createPageDocument2 } from "@standhigher/puck-page-builder/runtime";
|
|
578
578
|
|
|
579
579
|
// src/branded.tsx
|
|
580
|
-
import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useMemo as useMemo2, useState as useState3 } from "react";
|
|
580
|
+
import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
581
|
+
|
|
582
|
+
// src/tracking-page-runtime.ts
|
|
583
|
+
function isEmptyTrackingPageResult(result) {
|
|
584
|
+
return result.outcome === "empty";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// src/branded.tsx
|
|
581
588
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
582
589
|
var initialRuntime2 = {
|
|
583
590
|
phase: "idle",
|
|
@@ -598,17 +605,22 @@ var cardStyle = { background: "#fff", color: "#0a0a0a", border: "1px solid #e7e7
|
|
|
598
605
|
function BrandedRuntimeProvider({ children, queryTracking }) {
|
|
599
606
|
const [state, setState] = useState3({ phase: "idle" });
|
|
600
607
|
const [selectedShipmentId, setSelectedShipmentId] = useState3(null);
|
|
608
|
+
const requestId = useRef(0);
|
|
601
609
|
const query = useCallback2(async (trackingNumber) => {
|
|
610
|
+
const currentRequestId = ++requestId.current;
|
|
602
611
|
setState({ phase: "loading" });
|
|
603
612
|
try {
|
|
604
613
|
const result = await queryTracking(trackingNumber);
|
|
614
|
+
if (currentRequestId !== requestId.current) return;
|
|
605
615
|
setSelectedShipmentId(result.shipments?.[0]?.id ?? null);
|
|
606
|
-
setState({ phase: "success", result });
|
|
607
|
-
} catch
|
|
608
|
-
|
|
616
|
+
setState({ phase: isEmptyTrackingPageResult(result) ? "empty" : "success", result });
|
|
617
|
+
} catch {
|
|
618
|
+
if (currentRequestId !== requestId.current) return;
|
|
619
|
+
setState({ phase: "error", error: "tracking-query-failed" });
|
|
609
620
|
}
|
|
610
621
|
}, [queryTracking]);
|
|
611
622
|
const reset = useCallback2(() => {
|
|
623
|
+
requestId.current += 1;
|
|
612
624
|
setSelectedShipmentId(null);
|
|
613
625
|
setState({ phase: "idle" });
|
|
614
626
|
}, []);
|
|
@@ -617,7 +629,9 @@ function BrandedRuntimeProvider({ children, queryTracking }) {
|
|
|
617
629
|
const shipment = state.result.shipments?.find((item) => item.id === selectedShipmentId);
|
|
618
630
|
return shipment ? { ...state.result, ...shipment } : state.result;
|
|
619
631
|
}, [selectedShipmentId, state.result]);
|
|
620
|
-
const selectShipment = useCallback2((id) =>
|
|
632
|
+
const selectShipment = useCallback2((id) => {
|
|
633
|
+
if (state.result?.shipments?.some((shipment) => shipment.id === id)) setSelectedShipmentId(id);
|
|
634
|
+
}, [state.result]);
|
|
621
635
|
const value = useMemo2(
|
|
622
636
|
() => ({ ...state, displayedResult, selectedShipmentId, query, reset, selectShipment }),
|
|
623
637
|
[displayedResult, query, reset, selectedShipmentId, selectShipment, state]
|
|
@@ -632,7 +646,7 @@ function text3(props, key, fallback) {
|
|
|
632
646
|
}
|
|
633
647
|
function safeHref2(value) {
|
|
634
648
|
if (typeof value !== "string") return "#";
|
|
635
|
-
if (value.startsWith("/")) return value;
|
|
649
|
+
if (value.startsWith("/") && !value.startsWith("//")) return value;
|
|
636
650
|
try {
|
|
637
651
|
const url = new URL(value);
|
|
638
652
|
return url.protocol === "https:" || url.protocol === "http:" ? url.toString() : "#";
|
|
@@ -663,7 +677,7 @@ function ProductImage2({ src, alt }) {
|
|
|
663
677
|
function ShipmentSwitcher({ shipmentLabels: configuredLabels }) {
|
|
664
678
|
const runtime = useBrandedRuntime();
|
|
665
679
|
const configuredShipments = shipmentLabels(configuredLabels);
|
|
666
|
-
const shipments = runtime.
|
|
680
|
+
const shipments = runtime.phase === "idle" || runtime.phase === "loading" ? configuredShipments : runtime.result?.shipments ?? [];
|
|
667
681
|
if (!shipments.length) return null;
|
|
668
682
|
return /* @__PURE__ */ jsx3("div", { "aria-label": "Shipment switcher", style: { ...contentWidth2, minHeight: 56, display: "flex", alignItems: "center", gap: 8, overflowX: "auto", whiteSpace: "nowrap" }, children: shipments.map((shipment, index) => {
|
|
669
683
|
const selected = (runtime.selectedShipmentId ?? shipments[0]?.id) === shipment.id;
|
|
@@ -693,7 +707,8 @@ function QueryHero(props) {
|
|
|
693
707
|
/* @__PURE__ */ jsx3("input", { id: "branded-tracking-number", "aria-label": mode === "order" ? "Order number" : "Tracking number", value: trackingNumber, onChange: (event) => setTrackingNumber(event.target.value), required: true, minLength: 4, maxLength: 64, placeholder: mode === "order" ? "Enter your order number" : "Enter your tracking number", style: { width: "100%", height: 48, padding: "0 16px", boxSizing: "border-box", border: "1px solid #e2e2e2", borderRadius: 10, font: "inherit" } }),
|
|
694
708
|
/* @__PURE__ */ jsx3("button", { type: "submit", disabled: runtime.phase === "loading", style: { width: "100%", minHeight: 48, marginTop: 24, border: 0, borderRadius: 10, background: runtime.phase === "loading" ? "#6b6b6b" : "#000", color: "#fff", font: "inherit", cursor: runtime.phase === "loading" ? "wait" : "pointer" }, children: runtime.phase === "loading" ? "Tracking\u2026" : text3(props, "submitLabel", "Track") })
|
|
695
709
|
] }),
|
|
696
|
-
runtime.phase === "
|
|
710
|
+
runtime.phase === "empty" ? /* @__PURE__ */ jsx3("p", { role: "status", style: { marginBottom: 0, color: "#6b6b6b" }, children: "We couldn\u2019t find an order for that number." }) : null,
|
|
711
|
+
runtime.phase === "error" ? /* @__PURE__ */ jsx3("p", { role: "alert", style: { marginBottom: 0, color: "#b42318" }, children: "We couldn\u2019t retrieve this order right now. Please try again later." }) : null,
|
|
697
712
|
/* @__PURE__ */ jsx3("small", { style: { display: "block", marginTop: 10, color: "#8a8a8a", fontSize: 8, textAlign: "right" }, children: "Powered by BestTrack" })
|
|
698
713
|
] })
|
|
699
714
|
] });
|
|
@@ -873,13 +888,14 @@ function BrandedOrderItemsBlock(props) {
|
|
|
873
888
|
] }) });
|
|
874
889
|
}
|
|
875
890
|
function RecommendationCard({ item }) {
|
|
891
|
+
const href = safeHref2(item.href);
|
|
876
892
|
return /* @__PURE__ */ jsxs3("article", { style: { overflow: "hidden", borderRadius: 6, background: "#fff", boxShadow: "0 1px 2px rgb(0 0 0 / 8%)" }, children: [
|
|
877
893
|
/* @__PURE__ */ jsx3(ProductImage2, { src: item.imageUrl, alt: item.title }),
|
|
878
894
|
/* @__PURE__ */ jsxs3("div", { style: { padding: 14 }, children: [
|
|
879
895
|
/* @__PURE__ */ jsx3("strong", { children: item.title }),
|
|
880
896
|
item.price ? /* @__PURE__ */ jsx3("p", { style: { margin: "6px 0", fontWeight: 700 }, children: item.price }) : null,
|
|
881
897
|
/* @__PURE__ */ jsx3("p", { style: { margin: "6px 0", color: "#6b6b6b", fontSize: 13 }, children: item.description }),
|
|
882
|
-
/* @__PURE__ */ jsx3("
|
|
898
|
+
href === "#" ? /* @__PURE__ */ jsx3("span", { style: { color: "#6b6b6b", fontSize: 13, fontWeight: 700 }, children: "View product" }) : /* @__PURE__ */ jsx3("a", { href, style: { color: "#0a0a0a", fontSize: 13, fontWeight: 700 }, children: "View product" })
|
|
883
899
|
] })
|
|
884
900
|
] });
|
|
885
901
|
}
|
|
@@ -887,10 +903,10 @@ function BrandedRecommendationsBlock(props) {
|
|
|
887
903
|
const runtime = useBrandedRuntime();
|
|
888
904
|
const recommendations = runtime.displayedResult?.recommendations ?? [];
|
|
889
905
|
const title = text3(props, "heading", "You might also like");
|
|
890
|
-
if (runtime.phase === "success" && !recommendations.length && text3(props, "hideWhenEmpty", "false") === "true") return null;
|
|
906
|
+
if ((runtime.phase === "success" || runtime.phase === "empty") && !recommendations.length && text3(props, "hideWhenEmpty", "false") === "true") return null;
|
|
891
907
|
return /* @__PURE__ */ jsx3("section", { "aria-label": title, style: { background: "#fffdf0", color: "#0a0a0a", fontFamily: "var(--pb-font-family)", padding: "clamp(28px, 4vw, 48px) 0" }, children: /* @__PURE__ */ jsxs3("div", { style: contentWidth2, children: [
|
|
892
908
|
/* @__PURE__ */ jsx3("h2", { style: { margin: "0 0 24px", textAlign: "center", fontSize: 20 }, children: title }),
|
|
893
|
-
runtime.phase === "loading" ? /* @__PURE__ */ jsx3("div", { "aria-label": "Loading recommendations", style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 16 }, children: [0, 1, 2].map((item) => /* @__PURE__ */ jsx3("span", { style: { display: "block", height: 220, borderRadius: 6, background: "#e7e7e7" } }, item)) }) : runtime.phase === "success" && recommendations.length ? /* @__PURE__ */ jsx3("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 16 }, children: recommendations.map((item) => /* @__PURE__ */ jsx3(RecommendationCard, { item }, item.id)) }) : /* @__PURE__ */ jsx3("p", { style: { margin: 0, textAlign: "center", color: runtime.phase === "error" ? "#b42318" : "#6b6b6b" }, children: runtime.phase === "error" ? "Recommendations are temporarily unavailable." : "Recommendations will appear with your order." })
|
|
909
|
+
runtime.phase === "loading" ? /* @__PURE__ */ jsx3("div", { "aria-label": "Loading recommendations", style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 16 }, children: [0, 1, 2].map((item) => /* @__PURE__ */ jsx3("span", { style: { display: "block", height: 220, borderRadius: 6, background: "#e7e7e7" } }, item)) }) : runtime.phase === "success" && recommendations.length ? /* @__PURE__ */ jsx3("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 16 }, children: recommendations.map((item) => /* @__PURE__ */ jsx3(RecommendationCard, { item }, item.id)) }) : /* @__PURE__ */ jsx3("p", { style: { margin: 0, textAlign: "center", color: runtime.phase === "error" ? "#b42318" : "#6b6b6b" }, children: runtime.phase === "error" ? "Recommendations are temporarily unavailable." : runtime.phase === "empty" ? "No recommendations are available for that number." : "Recommendations will appear with your order." })
|
|
894
910
|
] }) });
|
|
895
911
|
}
|
|
896
912
|
function BrandedQuickLinksBlock(props) {
|
|
@@ -936,22 +952,30 @@ var bestTrackBrandedExtension = Object.freeze({ name: "besttrack.branded", versi
|
|
|
936
952
|
import { createPageDocument as createPageDocument3 } from "@standhigher/puck-page-builder/runtime";
|
|
937
953
|
|
|
938
954
|
// src/sales.tsx
|
|
939
|
-
import { createContext as createContext3, useCallback as useCallback3, useContext as useContext3, useMemo as useMemo3, useState as useState4 } from "react";
|
|
940
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
955
|
+
import { createContext as createContext3, useCallback as useCallback3, useContext as useContext3, useId, useMemo as useMemo3, useRef as useRef2, useState as useState4 } from "react";
|
|
956
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
941
957
|
var initialRuntime3 = { phase: "idle", async query() {
|
|
942
958
|
return void 0;
|
|
943
959
|
} };
|
|
944
960
|
var SalesRuntimeContext = createContext3(initialRuntime3);
|
|
945
|
-
var
|
|
946
|
-
var
|
|
961
|
+
var contentWidth3 = { boxSizing: "border-box", width: "min(1120px, calc(100% - 32px))", margin: "0 auto" };
|
|
962
|
+
var sectionStyle = { ...contentWidth3, marginTop: "clamp(32px, 6vw, 72px)", color: "var(--pb-color-text)", fontFamily: "var(--pb-font-family)" };
|
|
963
|
+
var panelStyle = { boxSizing: "border-box", border: "1px solid var(--pb-color-border)", borderRadius: "var(--pb-radius)", padding: "clamp(20px, 3vw, 32px)", background: "var(--pb-color-surface)", color: "var(--pb-color-text)", overflowWrap: "anywhere" };
|
|
964
|
+
var gridStyle = { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 220px), 1fr))", gap: "clamp(16px, 2vw, 24px)" };
|
|
965
|
+
var trackingNumberPattern = /^[A-Za-z0-9-]{4,64}$/;
|
|
947
966
|
function SalesRuntimeProvider({ children, queryTracking }) {
|
|
948
967
|
const [state, setState] = useState4({ phase: "idle" });
|
|
968
|
+
const requestId = useRef2(0);
|
|
949
969
|
const query = useCallback3(async (trackingNumber) => {
|
|
970
|
+
const currentRequestId = ++requestId.current;
|
|
950
971
|
setState({ phase: "loading" });
|
|
951
972
|
try {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
setState({ phase:
|
|
973
|
+
const result = await queryTracking(trackingNumber);
|
|
974
|
+
if (currentRequestId !== requestId.current) return;
|
|
975
|
+
setState({ phase: isEmptyTrackingPageResult(result) ? "empty" : "success", result });
|
|
976
|
+
} catch {
|
|
977
|
+
if (currentRequestId !== requestId.current) return;
|
|
978
|
+
setState({ phase: "error" });
|
|
955
979
|
}
|
|
956
980
|
}, [queryTracking]);
|
|
957
981
|
const value = useMemo3(() => ({ ...state, query }), [query, state]);
|
|
@@ -961,115 +985,314 @@ function useSalesRuntime() {
|
|
|
961
985
|
return useContext3(SalesRuntimeContext);
|
|
962
986
|
}
|
|
963
987
|
function text5(props, key, fallback) {
|
|
964
|
-
|
|
988
|
+
const value = props[key];
|
|
989
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
990
|
+
}
|
|
991
|
+
function hasControlCharacter(value) {
|
|
992
|
+
return [...value].some((character) => character.charCodeAt(0) < 32);
|
|
965
993
|
}
|
|
966
994
|
function safeHref3(value) {
|
|
967
|
-
if (typeof value !== "string") return
|
|
968
|
-
if (value.startsWith("/")) return value;
|
|
995
|
+
if (typeof value !== "string") return void 0;
|
|
996
|
+
if (value.startsWith("/") && !value.startsWith("//") && !value.startsWith("/\\") && !value.includes("\\") && !hasControlCharacter(value)) return value;
|
|
969
997
|
try {
|
|
970
998
|
const url = new URL(value);
|
|
971
|
-
return url.protocol === "https:"
|
|
999
|
+
return url.protocol === "https:" ? url.toString() : void 0;
|
|
972
1000
|
} catch {
|
|
973
|
-
return
|
|
1001
|
+
return void 0;
|
|
974
1002
|
}
|
|
975
1003
|
}
|
|
976
|
-
function
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1004
|
+
function safeImageUrl3(value) {
|
|
1005
|
+
if (typeof value !== "string") return void 0;
|
|
1006
|
+
try {
|
|
1007
|
+
const url = new URL(value);
|
|
1008
|
+
return url.protocol === "https:" ? url.toString() : void 0;
|
|
1009
|
+
} catch {
|
|
1010
|
+
return void 0;
|
|
1011
|
+
}
|
|
981
1012
|
}
|
|
982
1013
|
function resourceState(value) {
|
|
983
1014
|
return typeof value !== "string" ? "invalid" : value.trim() ? "ready" : "empty";
|
|
984
1015
|
}
|
|
1016
|
+
function Status({ children, alert = false }) {
|
|
1017
|
+
return /* @__PURE__ */ jsx4("p", { role: alert ? "alert" : "status", "aria-live": alert ? "assertive" : "polite", style: { margin: "16px 0 0", color: alert ? "#a61b1b" : "var(--pb-color-muted)" }, children });
|
|
1018
|
+
}
|
|
1019
|
+
function Section({ title, children, busy = false }) {
|
|
1020
|
+
return /* @__PURE__ */ jsx4("section", { "aria-label": title, "aria-busy": busy || void 0, style: sectionStyle, children: /* @__PURE__ */ jsxs4("div", { style: panelStyle, children: [
|
|
1021
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px", fontSize: "clamp(24px, 3vw, 34px)", lineHeight: 1.15 }, children: title }),
|
|
1022
|
+
children
|
|
1023
|
+
] }) });
|
|
1024
|
+
}
|
|
1025
|
+
function ProductImage3({ src, alt }) {
|
|
1026
|
+
const [failed, setFailed] = useState4(false);
|
|
1027
|
+
const safeSrc = safeImageUrl3(src);
|
|
1028
|
+
if (!safeSrc || failed) return /* @__PURE__ */ jsx4("span", { "aria-label": `${alt} image unavailable`, role: "img", style: { display: "grid", placeItems: "center", width: 76, height: 76, flex: "0 0 auto", border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)", color: "var(--pb-color-muted)", fontWeight: 700 }, children: alt.slice(0, 1).toUpperCase() });
|
|
1029
|
+
return /* @__PURE__ */ jsx4("img", { src: safeSrc, alt, onError: () => setFailed(true), style: { width: 76, height: 76, flex: "0 0 auto", borderRadius: "calc(var(--pb-radius) / 1.5)", objectFit: "cover", background: "var(--pb-color-background)" } });
|
|
1030
|
+
}
|
|
1031
|
+
function HeroAsset({ src }) {
|
|
1032
|
+
const [failed, setFailed] = useState4(false);
|
|
1033
|
+
const safeSrc = safeImageUrl3(src);
|
|
1034
|
+
if (!safeSrc || failed) return null;
|
|
1035
|
+
return /* @__PURE__ */ jsx4("img", { "data-sales-hero-image": true, src: safeSrc, alt: "", "aria-hidden": "true", onError: () => setFailed(true), style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: 0.62 } });
|
|
1036
|
+
}
|
|
985
1037
|
function SalesTextField({ value, onChange }) {
|
|
986
1038
|
return /* @__PURE__ */ jsx4("input", { "aria-label": "Sales text", value: typeof value === "string" ? value : "", onChange: (event) => onChange(event.target.value) });
|
|
987
1039
|
}
|
|
1040
|
+
var editorSurfaceStyle = { boxSizing: "border-box", border: "1px solid #dfddd7", borderRadius: 10, padding: 24, background: "#ffffff", color: "#0a0a0a", fontFamily: "Arial, Helvetica, sans-serif" };
|
|
1041
|
+
var editorCardStyle = { boxSizing: "border-box", padding: 18, border: "1px solid #dfddd7", borderRadius: 7, background: "#f7f5f0" };
|
|
1042
|
+
function editorText(block, name, fallback) {
|
|
1043
|
+
return text5(block, name, fallback);
|
|
1044
|
+
}
|
|
1045
|
+
function SalesInlineText({ block, name, fallback, style }) {
|
|
1046
|
+
const value = editorText(block, name, fallback);
|
|
1047
|
+
if (!block.selected) return /* @__PURE__ */ jsx4("span", { "data-sales-editor-field": name, style, children: value });
|
|
1048
|
+
return /* @__PURE__ */ jsx4("input", { "aria-label": `Canvas ${name}`, "data-sales-editor-field": name, value, onMouseDown: (event) => event.stopPropagation(), onClick: (event) => event.stopPropagation(), onChange: (event) => block.onPropsChange({ [name]: event.currentTarget.value }), style: { boxSizing: "border-box", width: "100%", border: "1px dashed currentColor", borderRadius: 3, padding: "2px 5px", background: "transparent", color: "inherit", font: "inherit", fontWeight: "inherit", lineHeight: "inherit", textAlign: "inherit", ...style } });
|
|
1049
|
+
}
|
|
1050
|
+
function SalesEditorSurface({ block, children }) {
|
|
1051
|
+
return /* @__PURE__ */ jsx4("section", { "aria-label": "Sales editor preview", style: { ...editorSurfaceStyle, outline: block.selected ? "2px solid #2563eb" : void 0, outlineOffset: -2 }, children });
|
|
1052
|
+
}
|
|
1053
|
+
function SalesAnnouncementEditor(block) {
|
|
1054
|
+
return /* @__PURE__ */ jsx4("section", { "aria-label": "Sales announcement editor", style: { display: "grid", minHeight: 38, placeItems: "center", boxSizing: "border-box", padding: "10px 16px", borderBottom: "1px solid #dfddd7", background: "#f7f5f0", color: "#0a0a0a", fontFamily: "Arial, Helvetica, sans-serif", fontSize: 13, fontWeight: 700, textAlign: "center" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "message", fallback: "Free delivery on orders over $50" }) });
|
|
1055
|
+
}
|
|
1056
|
+
function SalesQueryEditor(block) {
|
|
1057
|
+
const imageUrl = safeImageUrl3(block.heroImageUrl);
|
|
1058
|
+
const trackingNumber = editorText(block, "defaultTrackingNumber", "BT-2048-DEMO");
|
|
1059
|
+
return /* @__PURE__ */ jsxs4("section", { "aria-label": "Sales Hero query editor", style: { position: "relative", display: "grid", minHeight: "clamp(460px, 52vw, 620px)", placeItems: "center", boxSizing: "border-box", overflow: "hidden", padding: "clamp(28px, 6vw, 72px) 16px", background: "#0a0a0a", fontFamily: "Arial, Helvetica, sans-serif" }, children: [
|
|
1060
|
+
imageUrl ? /* @__PURE__ */ jsx4("img", { src: imageUrl, alt: "", "aria-hidden": "true", style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", opacity: 0.62 } }) : null,
|
|
1061
|
+
/* @__PURE__ */ jsx4("div", { "aria-hidden": "true", style: { position: "absolute", inset: 0, background: "rgb(0 0 0 / 42%)" } }),
|
|
1062
|
+
/* @__PURE__ */ jsxs4("div", { style: { position: "relative", zIndex: 1, boxSizing: "border-box", width: "min(560px, 100%)", padding: "clamp(28px, 5vw, 48px)", borderRadius: 10, background: "#ffffff", color: "#0a0a0a", boxShadow: "0 20px 56px rgb(0 0 0 / 28%)" }, children: [
|
|
1063
|
+
/* @__PURE__ */ jsx4("h1", { style: { margin: "0 0 28px", fontSize: "clamp(32px, 5vw, 48px)", fontWeight: 800, letterSpacing: "-0.035em", lineHeight: 1.02, textAlign: "center" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Track your order" }) }),
|
|
1064
|
+
/* @__PURE__ */ jsx4("input", { "aria-label": "Canvas default tracking number", readOnly: !block.selected, value: trackingNumber, onMouseDown: (event) => block.selected && event.stopPropagation(), onClick: (event) => block.selected && event.stopPropagation(), onChange: (event) => block.onPropsChange({ defaultTrackingNumber: event.currentTarget.value }), style: { boxSizing: "border-box", width: "100%", minHeight: 58, padding: "12px 16px", border: "1px solid #dfddd7", borderRadius: 8, background: "#ffffff", color: "#0a0a0a", font: "inherit", fontSize: 17 } }),
|
|
1065
|
+
/* @__PURE__ */ jsx4("div", { style: { display: "grid", minHeight: 58, placeItems: "center", marginTop: 14, padding: "12px 18px", borderRadius: 8, background: "#0a0a0a", color: "#ffffff", fontSize: 16, fontWeight: 700 }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "submitLabel", fallback: "Track order" }) }),
|
|
1066
|
+
/* @__PURE__ */ jsx4("small", { style: { display: "block", marginTop: 14, color: "#6b6b6b", fontSize: 11, textAlign: "right" }, children: "Powered by BestTrack" })
|
|
1067
|
+
] })
|
|
1068
|
+
] });
|
|
1069
|
+
}
|
|
1070
|
+
function SalesOrderItemsEditor(block) {
|
|
1071
|
+
return /* @__PURE__ */ jsxs4(SalesEditorSurface, { block, children: [
|
|
1072
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Items in your order" }) }),
|
|
1073
|
+
/* @__PURE__ */ jsxs4("article", { style: { ...editorCardStyle, display: "flex", alignItems: "center", gap: 14 }, children: [
|
|
1074
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": "true", style: { width: 68, height: 68, borderRadius: 7, background: "#dfddd7" } }),
|
|
1075
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1076
|
+
/* @__PURE__ */ jsx4("strong", { children: "Order item" }),
|
|
1077
|
+
/* @__PURE__ */ jsx4("br", {}),
|
|
1078
|
+
/* @__PURE__ */ jsx4("small", { style: { color: "#6b6b6b" }, children: "Items appear after a successful tracking query." })
|
|
1079
|
+
] })
|
|
1080
|
+
] })
|
|
1081
|
+
] });
|
|
1082
|
+
}
|
|
1083
|
+
function SalesOtherTrackingEditor(block) {
|
|
1084
|
+
return /* @__PURE__ */ jsxs4(SalesEditorSurface, { block, children: [
|
|
1085
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Other shipments" }) }),
|
|
1086
|
+
/* @__PURE__ */ jsx4("p", { style: { margin: 0, color: "#6b6b6b" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "emptyMessage", fallback: "No other shipments are linked to this order." }) })
|
|
1087
|
+
] });
|
|
1088
|
+
}
|
|
1089
|
+
function SalesServiceCardsEditor(block) {
|
|
1090
|
+
return /* @__PURE__ */ jsxs4(SalesEditorSurface, { block, children: [
|
|
1091
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Shop with confidence" }) }),
|
|
1092
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 180px), 1fr))", gap: 14 }, children: [
|
|
1093
|
+
/* @__PURE__ */ jsxs4("article", { style: editorCardStyle, children: [
|
|
1094
|
+
/* @__PURE__ */ jsx4("strong", { children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "firstTitle", fallback: "Easy returns" }) }),
|
|
1095
|
+
/* @__PURE__ */ jsx4("p", { style: { marginBottom: 0, color: "#6b6b6b" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "firstDescription", fallback: "Simple support when plans change." }) })
|
|
1096
|
+
] }),
|
|
1097
|
+
/* @__PURE__ */ jsxs4("article", { style: editorCardStyle, children: [
|
|
1098
|
+
/* @__PURE__ */ jsx4("strong", { children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "secondTitle", fallback: "Secure delivery" }) }),
|
|
1099
|
+
/* @__PURE__ */ jsx4("p", { style: { marginBottom: 0, color: "#6b6b6b" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "secondDescription", fallback: "Follow every milestone in one place." }) })
|
|
1100
|
+
] })
|
|
1101
|
+
] })
|
|
1102
|
+
] });
|
|
1103
|
+
}
|
|
1104
|
+
function SalesProductCategoriesEditor(block) {
|
|
1105
|
+
return /* @__PURE__ */ jsxs4(SalesEditorSurface, { block, children: [
|
|
1106
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Shop by category" }) }),
|
|
1107
|
+
/* @__PURE__ */ jsxs4("div", { style: { ...editorCardStyle, display: "flex", justifyContent: "space-between", fontWeight: 700 }, children: [
|
|
1108
|
+
/* @__PURE__ */ jsx4(SalesInlineText, { block, name: "collectionLabel", fallback: "Featured collection" }),
|
|
1109
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: "\u2192" })
|
|
1110
|
+
] })
|
|
1111
|
+
] });
|
|
1112
|
+
}
|
|
1113
|
+
function SalesRecommendationsEditor(block) {
|
|
1114
|
+
return /* @__PURE__ */ jsxs4(SalesEditorSurface, { block, children: [
|
|
1115
|
+
/* @__PURE__ */ jsx4("h2", { style: { margin: "0 0 20px" }, children: /* @__PURE__ */ jsx4(SalesInlineText, { block, name: "heading", fallback: "Complete your order" }) }),
|
|
1116
|
+
/* @__PURE__ */ jsx4("div", { style: { ...editorCardStyle, color: "#6b6b6b" }, children: "Recommended products appear after a successful tracking query." })
|
|
1117
|
+
] });
|
|
1118
|
+
}
|
|
988
1119
|
function SalesAnnouncementBlock(props) {
|
|
989
|
-
return /* @__PURE__ */ jsx4("section", { "aria-label": "Sales announcement", style: {
|
|
1120
|
+
return /* @__PURE__ */ jsx4("section", { "aria-label": "Sales announcement", "data-sales-announcement": true, style: { display: "grid", minHeight: 38, placeItems: "center", boxSizing: "border-box", padding: "10px 16px", borderBottom: "1px solid var(--pb-color-border)", background: "var(--pb-color-background)", color: "var(--pb-color-text)", fontFamily: "var(--pb-font-family)", fontSize: 13, textAlign: "center" }, children: /* @__PURE__ */ jsx4("strong", { children: text5(props, "message", "Free delivery on orders over $50") }) });
|
|
990
1121
|
}
|
|
991
1122
|
function SalesQueryBlock(props) {
|
|
992
1123
|
const runtime = useSalesRuntime();
|
|
1124
|
+
const inputId = useId();
|
|
1125
|
+
const errorId = useId();
|
|
993
1126
|
const [trackingNumber, setTrackingNumber] = useState4(text5(props, "defaultTrackingNumber", "BT-2048-DEMO"));
|
|
1127
|
+
const [inputError, setInputError] = useState4(null);
|
|
994
1128
|
const submit = (event) => {
|
|
995
1129
|
event.preventDefault();
|
|
996
|
-
|
|
1130
|
+
const normalizedTrackingNumber = trackingNumber.trim();
|
|
1131
|
+
if (!trackingNumberPattern.test(normalizedTrackingNumber)) {
|
|
1132
|
+
setInputError("Enter a tracking number using 4\u201364 letters, numbers, or hyphens.");
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
setInputError(null);
|
|
1136
|
+
void runtime.query(normalizedTrackingNumber);
|
|
997
1137
|
};
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
/* @__PURE__ */
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1138
|
+
const description = inputError ?? (runtime.phase === "empty" ? "We couldn\u2019t find an order for that number." : runtime.phase === "error" ? "We couldn\u2019t retrieve this order right now. Please try again later." : void 0);
|
|
1139
|
+
return /* @__PURE__ */ jsxs4("section", { "aria-label": "Sales tracking query", "aria-busy": runtime.phase === "loading" || void 0, "data-sales-hero": true, style: { position: "relative", display: "grid", minHeight: "clamp(460px, 52vw, 620px)", placeItems: "center", boxSizing: "border-box", overflow: "hidden", padding: "clamp(28px, 6vw, 72px) 16px", background: "var(--pb-color-text)", color: "var(--pb-color-surface)", fontFamily: "var(--pb-font-family)" }, children: [
|
|
1140
|
+
/* @__PURE__ */ jsx4(HeroAsset, { src: props.heroImageUrl }),
|
|
1141
|
+
/* @__PURE__ */ jsx4("div", { "aria-hidden": "true", style: { position: "absolute", inset: 0, background: "rgb(0 0 0 / 42%)" } }),
|
|
1142
|
+
/* @__PURE__ */ jsxs4("div", { "data-sales-query-card": true, style: { position: "relative", zIndex: 1, boxSizing: "border-box", width: "min(560px, 100%)", padding: "clamp(28px, 5vw, 48px)", borderRadius: "var(--pb-radius)", background: "var(--pb-color-surface)", color: "var(--pb-color-text)", boxShadow: "0 20px 56px rgb(0 0 0 / 28%)" }, children: [
|
|
1143
|
+
/* @__PURE__ */ jsx4("h1", { style: { margin: "0 0 28px", color: "var(--pb-color-text)", fontSize: "clamp(32px, 5vw, 48px)", fontWeight: 800, letterSpacing: "-0.035em", lineHeight: 1.02, textAlign: "center" }, children: text5(props, "heading", "Track an order") }),
|
|
1144
|
+
/* @__PURE__ */ jsxs4("form", { noValidate: true, onSubmit: submit, style: { display: "grid", gap: 14 }, children: [
|
|
1145
|
+
/* @__PURE__ */ jsx4("label", { htmlFor: inputId, style: { position: "absolute", width: 1, height: 1, padding: 0, margin: -1, overflow: "hidden", clip: "rect(0, 0, 0, 0)", whiteSpace: "nowrap", border: 0 }, children: "Tracking number" }),
|
|
1146
|
+
/* @__PURE__ */ jsx4("input", { id: inputId, "aria-describedby": description ? errorId : void 0, "aria-invalid": Boolean(inputError) || void 0, "aria-label": "Sales tracking number", value: trackingNumber, onChange: (event) => {
|
|
1147
|
+
setTrackingNumber(event.target.value);
|
|
1148
|
+
if (inputError) setInputError(null);
|
|
1149
|
+
}, inputMode: "text", autoComplete: "off", pattern: "[A-Za-z0-9-]{4,64}", minLength: 4, maxLength: 64, required: true, placeholder: "Enter your tracking number", style: { boxSizing: "border-box", width: "100%", minHeight: 58, padding: "12px 16px", border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.25)", background: "var(--pb-color-surface)", color: "var(--pb-color-text)", font: "inherit", fontSize: 17 } }),
|
|
1150
|
+
/* @__PURE__ */ jsx4("button", { type: "submit", disabled: runtime.phase === "loading", style: { width: "100%", minHeight: 58, padding: "12px 18px", border: 0, borderRadius: "calc(var(--pb-radius) / 1.25)", background: "var(--pb-color-text)", color: "var(--pb-color-surface)", font: "inherit", fontSize: 16, fontWeight: 700, cursor: runtime.phase === "loading" ? "wait" : "pointer" }, children: runtime.phase === "loading" ? "Checking\u2026" : text5(props, "submitLabel", "Track order") })
|
|
1151
|
+
] }),
|
|
1152
|
+
runtime.phase === "loading" ? /* @__PURE__ */ jsx4(Status, { children: "Checking your order\u2026" }) : null,
|
|
1153
|
+
inputError ? /* @__PURE__ */ jsx4("p", { id: errorId, role: "alert", children: inputError }) : null,
|
|
1154
|
+
!inputError && runtime.phase === "empty" ? /* @__PURE__ */ jsx4("p", { id: errorId, role: "status", children: "We couldn\u2019t find an order for that number." }) : null,
|
|
1155
|
+
!inputError && runtime.phase === "error" ? /* @__PURE__ */ jsx4("p", { id: errorId, role: "alert", children: "We couldn\u2019t retrieve this order right now. Please try again later." }) : null,
|
|
1156
|
+
/* @__PURE__ */ jsx4("small", { style: { display: "block", marginTop: 14, color: "var(--pb-color-muted)", fontSize: 11, textAlign: "right" }, children: "Powered by BestTrack" })
|
|
1157
|
+
] })
|
|
1008
1158
|
] });
|
|
1009
1159
|
}
|
|
1010
1160
|
function SalesOrderItemsBlock(props) {
|
|
1011
1161
|
const runtime = useSalesRuntime();
|
|
1012
1162
|
const title = text5(props, "heading", "Items in your order");
|
|
1013
1163
|
const items = runtime.result?.orderItems ?? [];
|
|
1014
|
-
return /* @__PURE__ */ jsx4(Section, { title, children: runtime.phase === "error" ? /* @__PURE__ */ jsx4(
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1164
|
+
return /* @__PURE__ */ jsx4(Section, { title, busy: runtime.phase === "loading", children: runtime.phase === "error" ? /* @__PURE__ */ jsx4(Status, { alert: true, children: "Order items are temporarily unavailable." }) : runtime.phase === "empty" ? /* @__PURE__ */ jsx4(Status, { children: "No order items are available for that number." }) : runtime.phase === "success" && items.length ? /* @__PURE__ */ jsx4("ul", { style: { display: "grid", gap: 12, margin: 0, padding: 0, listStyle: "none" }, children: items.map((item) => {
|
|
1165
|
+
const href = safeHref3(item.href);
|
|
1166
|
+
const itemTitle = text5(item, "title", "Order item");
|
|
1167
|
+
const itemContent = href ? /* @__PURE__ */ jsx4("a", { href, style: { color: "inherit" }, children: itemTitle }) : itemTitle;
|
|
1168
|
+
return /* @__PURE__ */ jsxs4("li", { style: { display: "flex", alignItems: "center", gap: 16, minWidth: 0, padding: 14, border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)" }, children: [
|
|
1169
|
+
/* @__PURE__ */ jsx4(ProductImage3, { src: item.imageUrl, alt: itemTitle }),
|
|
1170
|
+
/* @__PURE__ */ jsxs4("span", { style: { minWidth: 0 }, children: [
|
|
1171
|
+
/* @__PURE__ */ jsx4("strong", { children: itemContent }),
|
|
1172
|
+
/* @__PURE__ */ jsx4("br", {}),
|
|
1173
|
+
/* @__PURE__ */ jsxs4("small", { style: { color: "var(--pb-color-muted)" }, children: [
|
|
1174
|
+
"Qty ",
|
|
1175
|
+
Number.isFinite(item.quantity) && item.quantity > 0 ? item.quantity : 1
|
|
1176
|
+
] }),
|
|
1177
|
+
item.description ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1178
|
+
/* @__PURE__ */ jsx4("br", {}),
|
|
1179
|
+
/* @__PURE__ */ jsx4("small", { style: { color: "var(--pb-color-muted)" }, children: item.description })
|
|
1180
|
+
] }) : null
|
|
1181
|
+
] })
|
|
1182
|
+
] }, item.id);
|
|
1183
|
+
}) }) : /* @__PURE__ */ jsx4(Status, { children: runtime.phase === "loading" ? "Loading order items\u2026" : "Order items appear after a successful query." }) });
|
|
1019
1184
|
}
|
|
1020
1185
|
function SalesOtherTrackingBlock(props) {
|
|
1021
1186
|
const runtime = useSalesRuntime();
|
|
1022
1187
|
const title = text5(props, "heading", "Other shipments");
|
|
1023
|
-
|
|
1188
|
+
const shipments = (runtime.result?.shipments ?? []).filter((shipment) => shipment.trackingNumber !== runtime.result?.trackingNumber);
|
|
1189
|
+
return /* @__PURE__ */ jsx4(Section, { title, busy: runtime.phase === "loading", children: runtime.phase === "error" ? /* @__PURE__ */ jsx4(Status, { alert: true, children: "Additional shipments are unavailable." }) : runtime.phase === "empty" ? /* @__PURE__ */ jsx4(Status, { children: "No additional shipments are available for that number." }) : runtime.phase === "success" && shipments.length ? /* @__PURE__ */ jsx4("ul", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 220px), 1fr))", gap: 12, margin: 0, padding: 0, listStyle: "none" }, children: shipments.map((shipment) => /* @__PURE__ */ jsxs4("li", { style: { padding: 16, border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)" }, children: [
|
|
1190
|
+
/* @__PURE__ */ jsx4("strong", { children: text5(shipment, "label", "Shipment") }),
|
|
1191
|
+
shipment.status ? /* @__PURE__ */ jsx4("p", { style: { margin: "8px 0 0", color: "var(--pb-color-muted)" }, children: shipment.status }) : null,
|
|
1192
|
+
shipment.trackingNumber ? /* @__PURE__ */ jsx4("small", { style: { display: "block", marginTop: 8, color: "var(--pb-color-muted)" }, children: shipment.trackingNumber }) : null
|
|
1193
|
+
] }, shipment.id)) }) : runtime.phase === "success" ? /* @__PURE__ */ jsx4(Status, { children: text5(props, "emptyMessage", "No other shipments are linked to this order.") }) : /* @__PURE__ */ jsx4(Status, { children: runtime.phase === "loading" ? "Loading other shipments\u2026" : "Other tracking numbers appear with your order result." }) });
|
|
1024
1194
|
}
|
|
1025
1195
|
function SalesServiceCardsBlock(props) {
|
|
1026
1196
|
const title = text5(props, "heading", "Shop with confidence");
|
|
1027
1197
|
return /* @__PURE__ */ jsx4(Section, { title, children: /* @__PURE__ */ jsxs4("div", { style: gridStyle, children: [
|
|
1028
|
-
/* @__PURE__ */ jsxs4("article", { children: [
|
|
1198
|
+
/* @__PURE__ */ jsxs4("article", { style: { padding: 20, border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)" }, children: [
|
|
1029
1199
|
/* @__PURE__ */ jsx4("strong", { children: text5(props, "firstTitle", "Easy returns") }),
|
|
1030
|
-
/* @__PURE__ */ jsx4("p", { children: text5(props, "firstDescription", "Simple support when plans change.") })
|
|
1200
|
+
/* @__PURE__ */ jsx4("p", { style: { marginBottom: 0, color: "var(--pb-color-muted)" }, children: text5(props, "firstDescription", "Simple support when plans change.") })
|
|
1031
1201
|
] }),
|
|
1032
|
-
/* @__PURE__ */ jsxs4("article", { children: [
|
|
1202
|
+
/* @__PURE__ */ jsxs4("article", { style: { padding: 20, border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)" }, children: [
|
|
1033
1203
|
/* @__PURE__ */ jsx4("strong", { children: text5(props, "secondTitle", "Secure delivery") }),
|
|
1034
|
-
/* @__PURE__ */ jsx4("p", { children: text5(props, "secondDescription", "Follow every milestone in one place.") })
|
|
1204
|
+
/* @__PURE__ */ jsx4("p", { style: { marginBottom: 0, color: "var(--pb-color-muted)" }, children: text5(props, "secondDescription", "Follow every milestone in one place.") })
|
|
1035
1205
|
] })
|
|
1036
1206
|
] }) });
|
|
1037
1207
|
}
|
|
1038
1208
|
function SalesProductCategoriesBlock(props) {
|
|
1039
1209
|
const title = text5(props, "heading", "Shop by category");
|
|
1040
|
-
const
|
|
1041
|
-
const
|
|
1042
|
-
return /* @__PURE__ */ jsx4(Section, { title, children: state === "invalid" ? /* @__PURE__ */ jsx4(
|
|
1043
|
-
/* @__PURE__ */ jsx4("
|
|
1044
|
-
/* @__PURE__ */
|
|
1045
|
-
|
|
1046
|
-
collectionId
|
|
1047
|
-
] })
|
|
1048
|
-
] }) });
|
|
1210
|
+
const state = resourceState(props.collectionId);
|
|
1211
|
+
const href = safeHref3(props.collectionHref);
|
|
1212
|
+
return /* @__PURE__ */ jsx4(Section, { title, children: state === "invalid" ? /* @__PURE__ */ jsx4(Status, { alert: true, children: "Collection reference is invalid." }) : state === "empty" ? /* @__PURE__ */ jsx4(Status, { children: "No collection selected. Choose a collection through an authorized resource integration." }) : href ? /* @__PURE__ */ jsxs4("a", { href, style: { display: "flex", alignItems: "center", justifyContent: "space-between", minHeight: 74, boxSizing: "border-box", padding: "14px 18px", border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)", color: "var(--pb-color-text)", fontWeight: 700, textDecoration: "none" }, children: [
|
|
1213
|
+
/* @__PURE__ */ jsx4("span", { children: text5(props, "collectionLabel", "Featured collection") }),
|
|
1214
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: "\u2192" })
|
|
1215
|
+
] }) : /* @__PURE__ */ jsx4(Status, { alert: true, children: "Collection link is unavailable." }) });
|
|
1049
1216
|
}
|
|
1050
1217
|
function SalesRecommendationsBlock(props) {
|
|
1051
1218
|
const runtime = useSalesRuntime();
|
|
1052
1219
|
const title = text5(props, "heading", "Complete your order");
|
|
1053
1220
|
const recommendations = runtime.result?.recommendations ?? [];
|
|
1054
|
-
return /* @__PURE__ */ jsx4(Section, { title, children: runtime.phase === "error" ? /* @__PURE__ */ jsx4(
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1221
|
+
return /* @__PURE__ */ jsx4(Section, { title, busy: runtime.phase === "loading", children: runtime.phase === "error" ? /* @__PURE__ */ jsx4(Status, { alert: true, children: "Recommendations are temporarily unavailable." }) : runtime.phase === "empty" ? /* @__PURE__ */ jsx4(Status, { children: "No recommendations are available for that number." }) : runtime.phase === "success" && recommendations.length ? /* @__PURE__ */ jsx4("div", { style: gridStyle, children: recommendations.map((item) => {
|
|
1222
|
+
const href = safeHref3(item.href);
|
|
1223
|
+
const itemTitle = text5(item, "title", "Recommended product");
|
|
1224
|
+
return /* @__PURE__ */ jsxs4("article", { style: { display: "grid", gap: 14, minWidth: 0, padding: 18, border: "1px solid var(--pb-color-border)", borderRadius: "calc(var(--pb-radius) / 1.5)", background: "var(--pb-color-background)" }, children: [
|
|
1225
|
+
/* @__PURE__ */ jsx4(ProductImage3, { src: item.imageUrl, alt: itemTitle }),
|
|
1226
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1227
|
+
/* @__PURE__ */ jsx4("strong", { children: href ? /* @__PURE__ */ jsx4("a", { href, style: { color: "inherit" }, children: itemTitle }) : itemTitle }),
|
|
1228
|
+
item.price ? /* @__PURE__ */ jsx4("small", { style: { display: "block", marginTop: 5, color: "var(--pb-color-muted)" }, children: item.price }) : null,
|
|
1229
|
+
item.description ? /* @__PURE__ */ jsx4("p", { style: { marginBottom: 0, color: "var(--pb-color-muted)" }, children: item.description }) : null
|
|
1230
|
+
] })
|
|
1231
|
+
] }, item.id);
|
|
1232
|
+
}) }) : /* @__PURE__ */ jsx4(Status, { children: runtime.phase === "success" ? "No recommendations are available for this order." : runtime.phase === "loading" ? "Loading recommendations\u2026" : "Recommended products appear with your order result." }) });
|
|
1058
1233
|
}
|
|
1059
1234
|
|
|
1060
1235
|
// src/sales-definition.ts
|
|
1061
|
-
var
|
|
1236
|
+
var trackingNumberPattern2 = /^[A-Za-z0-9-]{4,64}$/;
|
|
1237
|
+
var text6 = (label, options = {}) => ({ field: "besttrack.sales.text", label, control: "text", required: true, ...options });
|
|
1238
|
+
var shortText = (label, description) => text6(label, { description, group: "Content" });
|
|
1239
|
+
var longText = (label, description) => text6(label, { control: "textarea", description, group: "Content" });
|
|
1240
|
+
var link = (label, description) => text6(label, { control: "url", description: description ?? "Use a site-relative path or HTTPS URL.", group: "Links" });
|
|
1241
|
+
function safeLink(value) {
|
|
1242
|
+
if (typeof value !== "string") return false;
|
|
1243
|
+
if (value.startsWith("/") && !value.startsWith("//") && !value.startsWith("/\\") && !value.includes("\\") && !hasControlCharacter2(value)) return true;
|
|
1244
|
+
try {
|
|
1245
|
+
return new URL(value).protocol === "https:";
|
|
1246
|
+
} catch {
|
|
1247
|
+
return false;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
function hasControlCharacter2(value) {
|
|
1251
|
+
return [...value].some((character) => character.charCodeAt(0) < 32);
|
|
1252
|
+
}
|
|
1253
|
+
function requiredString(props, key, issues, maxLength = 160) {
|
|
1254
|
+
const value = props[key];
|
|
1255
|
+
if (typeof value !== "string" || !value.trim()) issues.push({ path: `props.${key}`, message: "A non-empty value is required." });
|
|
1256
|
+
else if (value.length > maxLength) issues.push({ path: `props.${key}`, message: `Must be at most ${maxLength} characters.` });
|
|
1257
|
+
}
|
|
1258
|
+
function textProps(keys) {
|
|
1259
|
+
return (props) => {
|
|
1260
|
+
const issues = [];
|
|
1261
|
+
keys.forEach(([key, maxLength]) => requiredString(props, key, issues, maxLength));
|
|
1262
|
+
return issues;
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
function validateQuery(props) {
|
|
1266
|
+
const issues = textProps([["heading", 120], ["submitLabel", 80]])(props);
|
|
1267
|
+
const trackingNumber = props.defaultTrackingNumber;
|
|
1268
|
+
if (typeof trackingNumber !== "string" || !trackingNumberPattern2.test(trackingNumber)) issues.push({ path: "props.defaultTrackingNumber", message: "Use 4\u201364 letters, numbers, or hyphens. Use a non-sensitive preview placeholder only." });
|
|
1269
|
+
if (props.heroImageUrl !== void 0 && !safeImage(props.heroImageUrl)) issues.push({ path: "props.heroImageUrl", message: "Use an HTTPS URL for the merchant-configured hero image." });
|
|
1270
|
+
return issues;
|
|
1271
|
+
}
|
|
1272
|
+
function safeImage(value) {
|
|
1273
|
+
if (typeof value !== "string") return false;
|
|
1274
|
+
try {
|
|
1275
|
+
return new URL(value).protocol === "https:";
|
|
1276
|
+
} catch {
|
|
1277
|
+
return false;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
function validateCategories(props) {
|
|
1281
|
+
const issues = textProps([["heading", 120], ["collectionId", 256], ["collectionLabel", 120]])(props);
|
|
1282
|
+
if (!safeLink(props.collectionHref)) issues.push({ path: "props.collectionHref", message: "Use a site-relative path or HTTPS URL." });
|
|
1283
|
+
return issues;
|
|
1284
|
+
}
|
|
1062
1285
|
var salesBlocks = [
|
|
1063
|
-
{ type: "besttrack.sales.announcement", version: 1, label: "Announcement", category: "BestTrack Sales", targets: ["web"], defaultProps: { message: "Free delivery on orders over $50" }, defaultVariant: "
|
|
1064
|
-
{ type: "besttrack.sales.query", version: 1, label: "Order query", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Track
|
|
1065
|
-
{ type: "besttrack.sales.order-items", version: 1, label: "Order items", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Items in your order" }, defaultVariant: "
|
|
1066
|
-
{ type: "besttrack.sales.other-tracking", version: 1, label: "Other tracking", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Other shipments", emptyMessage: "No other shipments are linked to this order." }, defaultVariant: "
|
|
1067
|
-
{ type: "besttrack.sales.service-cards", version: 1, label: "Service cards", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Shop with confidence", firstTitle: "Easy returns", firstDescription: "Simple support when plans change.", secondTitle: "Secure delivery", secondDescription: "Follow every milestone in one place." }, defaultVariant: "
|
|
1068
|
-
{ type: "besttrack.sales.product-categories", version: 1, label: "Product categories", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Shop by category", collectionId: "gid://shopify/Collection/featured", collectionLabel: "Featured collection", collectionHref: "/collections/featured" }, defaultVariant: "
|
|
1069
|
-
{ type: "besttrack.sales.recommendations", version: 1, label: "Recommended products", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Complete your order" }, defaultVariant: "
|
|
1286
|
+
{ type: "besttrack.sales.announcement", version: 1, label: "Announcement", category: "BestTrack Sales", targets: ["web"], defaultProps: { message: "Free delivery on orders over $50" }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }, { id: "minimal", label: "Minimal", theme: { "color.primary": "#202223" } }], fields: { message: longText("Announcement", "Short, customer-facing promotion copy.") }, validate: textProps([["message", 280]]), render: { web: SalesAnnouncementBlock, editor: SalesAnnouncementEditor } },
|
|
1287
|
+
{ type: "besttrack.sales.query", version: 1, label: "Order query", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Track your order", submitLabel: "Track order", defaultTrackingNumber: "BT-2048-DEMO", heroImageUrl: "https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?auto=format&fit=crop&w=1800&q=85" }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }, { id: "compact", label: "Compact", theme: { spacing: "12px" } }], fields: { heading: shortText("Heading"), submitLabel: shortText("Button label"), defaultTrackingNumber: text6("Default tracking number", { group: "Tracking settings", description: "Preview-only placeholder; never save a customer's tracking number." }), heroImageUrl: text6("Hero image URL", { control: "url", group: "Hero asset", description: "Merchant-configured HTTPS image. It is rendered as an image element, never as CSS." }) }, validate: validateQuery, render: { web: SalesQueryBlock, editor: SalesQueryEditor } },
|
|
1288
|
+
{ type: "besttrack.sales.order-items", version: 1, label: "Order items", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Items in your order" }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }], fields: { heading: shortText("Heading") }, validate: textProps([["heading", 120]]), render: { web: SalesOrderItemsBlock, editor: SalesOrderItemsEditor } },
|
|
1289
|
+
{ type: "besttrack.sales.other-tracking", version: 1, label: "Other tracking", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Other shipments", emptyMessage: "No other shipments are linked to this order." }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }], fields: { heading: shortText("Heading"), emptyMessage: longText("Empty message") }, validate: textProps([["heading", 120], ["emptyMessage", 280]]), render: { web: SalesOtherTrackingBlock, editor: SalesOtherTrackingEditor } },
|
|
1290
|
+
{ type: "besttrack.sales.service-cards", version: 1, label: "Service cards", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Shop with confidence", firstTitle: "Easy returns", firstDescription: "Simple support when plans change.", secondTitle: "Secure delivery", secondDescription: "Follow every milestone in one place." }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }], fields: { heading: shortText("Heading"), firstTitle: shortText("First card title"), firstDescription: longText("First card description"), secondTitle: shortText("Second card title"), secondDescription: longText("Second card description") }, validate: textProps([["heading", 120], ["firstTitle", 120], ["firstDescription", 280], ["secondTitle", 120], ["secondDescription", 280]]), render: { web: SalesServiceCardsBlock, editor: SalesServiceCardsEditor } },
|
|
1291
|
+
{ type: "besttrack.sales.product-categories", version: 1, label: "Product categories", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Shop by category", collectionId: "gid://shopify/Collection/featured", collectionLabel: "Featured collection", collectionHref: "/collections/featured" }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }, { id: "grid", label: "Grid", theme: { "color.surface": "#f8fafc" } }], fields: { heading: shortText("Heading"), collectionId: text6("Collection ID", { group: "Resource", description: "JSON-only reference selected by an authorized integration." }), collectionLabel: shortText("Collection label"), collectionHref: link("Collection URL") }, validate: validateCategories, render: { web: SalesProductCategoriesBlock, editor: SalesProductCategoriesEditor } },
|
|
1292
|
+
{ type: "besttrack.sales.recommendations", version: 1, label: "Recommended products", category: "BestTrack Sales", targets: ["web"], defaultProps: { heading: "Complete your order" }, defaultVariant: "hero", variants: [{ id: "hero", label: "Sales Hero" }, { id: "commerce", label: "Commerce" }, { id: "grid", label: "Product grid", theme: { "color.surface": "#f8fafc" } }], fields: { heading: shortText("Heading") }, validate: textProps([["heading", 120]]), render: { web: SalesRecommendationsBlock, editor: SalesRecommendationsEditor } }
|
|
1070
1293
|
];
|
|
1071
1294
|
function createSalesTemplate() {
|
|
1072
|
-
return { id: "besttrack.sales", version: 1, name: "Sales", target: "web", source: "built-in", requiredBlocks: salesBlocks.map((block) => block.type), theme: { "color.primary": "#
|
|
1295
|
+
return { id: "besttrack.sales", version: 1, name: "Sales", target: "web", source: "built-in", requiredBlocks: salesBlocks.map((block) => block.type), theme: { "color.primary": "#000000", "color.background": "#f7f5f0", "color.surface": "#ffffff", "color.text": "#0a0a0a", "color.muted": "#6b6b6b", "color.border": "#dfddd7", "font.family": "Arial, Helvetica, sans-serif", radius: "10px", spacing: "24px" }, create: () => createPageDocument3({ pageId: "besttrack-sales", target: "web", templateId: "besttrack.sales", templateVersion: 1, settings: { locale: "en", seoTitle: "Shop and track your order" }, blocks: salesBlocks.map((block, index) => ({ id: "sales-" + (index + 1), type: block.type, version: block.version, props: block.defaultProps, variant: block.defaultVariant, style: {} })) }) };
|
|
1073
1296
|
}
|
|
1074
1297
|
var bestTrackSalesExtension = Object.freeze({ name: "besttrack.sales", version: "0.7.2", fields: [{ type: "besttrack.sales.text", component: SalesTextField }], blocks: salesBlocks, templates: [createSalesTemplate()] });
|
|
1075
1298
|
export {
|
|
@@ -1081,5 +1304,6 @@ export {
|
|
|
1081
1304
|
bestTrackSalesExtension,
|
|
1082
1305
|
createBrandedTemplate,
|
|
1083
1306
|
createReadyToGoTemplate,
|
|
1084
|
-
createSalesTemplate
|
|
1307
|
+
createSalesTemplate,
|
|
1308
|
+
isEmptyTrackingPageResult
|
|
1085
1309
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standhigher/besttrack-page-extension",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "BestTrack business extension entry point for @standhigher/puck-page-builder.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@standhigher/puck-page-builder": "0.
|
|
19
|
+
"@standhigher/puck-page-builder": "0.9.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsup": "^8.5.1",
|