@nok-integration/storefront-react 0.20.5 → 0.20.6
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/dist/index.d.ts +8 -6
- package/dist/index.mjs +70 -5
- package/dist/standalone/storefront.mjs +70 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4272,8 +4272,8 @@ declare type OrderDetail = z.infer<typeof OrderDetail>;
|
|
|
4272
4272
|
/**
|
|
4273
4273
|
* The fan's orders (Figma `mobile/order/list`).
|
|
4274
4274
|
*
|
|
4275
|
-
* Read-only, like the detail screen it links to.
|
|
4276
|
-
*
|
|
4275
|
+
* Read-only, like the detail screen it links to. A return is a row of its own beside the
|
|
4276
|
+
* order it came from, and opens its own progress — see {@link ReturnStatusBadge}.
|
|
4277
4277
|
*
|
|
4278
4278
|
* Scoped to the session at the engine: `GET /v1/orders` takes no customer parameter, so
|
|
4279
4279
|
* there is no identifier a caller could supply to read somebody else's history.
|
|
@@ -4284,11 +4284,13 @@ export declare interface OrderListViewProps {
|
|
|
4284
4284
|
/** Opens one order. Without it the rows render as static cards rather than dead links. */
|
|
4285
4285
|
onOpenOrder?: (orderRef: string) => void;
|
|
4286
4286
|
/**
|
|
4287
|
-
*
|
|
4287
|
+
* Open one return on a route of your own.
|
|
4288
4288
|
*
|
|
4289
|
-
*
|
|
4290
|
-
*
|
|
4291
|
-
*
|
|
4289
|
+
* Optional, and optional in the way every handler here is: it customises where the row
|
|
4290
|
+
* goes, it does not decide whether the row opens. Omit it and the return's progress opens
|
|
4291
|
+
* in place of the list, the way the order screen opens one. It is deliberately not
|
|
4292
|
+
* defaulted to `onOpenOrder`: a fan tapping a return is asking about the return, and
|
|
4293
|
+
* landing them on the order is a different answer to the question they asked.
|
|
4292
4294
|
*/
|
|
4293
4295
|
onOpenReturn?: (returnRef: string) => void;
|
|
4294
4296
|
/** The empty state's call to action — the design's "Continue shopping" button. */
|
package/dist/index.mjs
CHANGED
|
@@ -5189,8 +5189,8 @@ function resolveAssetUrl(src, base) {
|
|
|
5189
5189
|
const MAX_AGE_MS = 5 * 6e4;
|
|
5190
5190
|
const CAPACITY = 60;
|
|
5191
5191
|
class ProductCache {
|
|
5192
|
-
constructor(
|
|
5193
|
-
this.now =
|
|
5192
|
+
constructor(now2 = () => Date.now()) {
|
|
5193
|
+
this.now = now2;
|
|
5194
5194
|
}
|
|
5195
5195
|
now;
|
|
5196
5196
|
entries = /* @__PURE__ */ new Map();
|
|
@@ -5702,8 +5702,63 @@ function useTopOffset(ref, property, enabled = true) {
|
|
|
5702
5702
|
};
|
|
5703
5703
|
}, [ref, property, enabled]);
|
|
5704
5704
|
}
|
|
5705
|
+
const HOLD_MS = 1e3;
|
|
5706
|
+
const RELEASES = ["touchstart", "wheel", "keydown", "pointerdown"];
|
|
5707
|
+
function anchorTop(shouldHold = () => true) {
|
|
5708
|
+
let released = false;
|
|
5709
|
+
const top2 = () => {
|
|
5710
|
+
if (released) return;
|
|
5711
|
+
const scrolled2 = window.scrollY || document.documentElement.scrollTop || 0;
|
|
5712
|
+
if (scrolled2 > 0 && shouldHold()) window.scrollTo(0, 0);
|
|
5713
|
+
};
|
|
5714
|
+
const release = () => {
|
|
5715
|
+
if (released) return;
|
|
5716
|
+
released = true;
|
|
5717
|
+
if (frame2 !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame2);
|
|
5718
|
+
clearTimeout(timer2);
|
|
5719
|
+
window.removeEventListener("scroll", top2);
|
|
5720
|
+
for (const type of RELEASES) window.removeEventListener(type, release);
|
|
5721
|
+
};
|
|
5722
|
+
top2();
|
|
5723
|
+
const frame2 = typeof requestAnimationFrame === "function" ? requestAnimationFrame(top2) : null;
|
|
5724
|
+
const timer2 = setTimeout(release, HOLD_MS);
|
|
5725
|
+
window.addEventListener("scroll", top2, {
|
|
5726
|
+
passive: true
|
|
5727
|
+
});
|
|
5728
|
+
for (const type of RELEASES) window.addEventListener(type, release, {
|
|
5729
|
+
passive: true
|
|
5730
|
+
});
|
|
5731
|
+
return release;
|
|
5732
|
+
}
|
|
5733
|
+
const TRAVERSAL_WINDOW_MS = 1e3;
|
|
5734
|
+
const now = () => typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
5735
|
+
let lastTraversal = -Infinity;
|
|
5736
|
+
if (typeof window !== "undefined") {
|
|
5737
|
+
window.addEventListener("popstate", () => {
|
|
5738
|
+
lastTraversal = now();
|
|
5739
|
+
});
|
|
5740
|
+
}
|
|
5741
|
+
function documentTop(el) {
|
|
5742
|
+
let top2 = 0;
|
|
5743
|
+
for (let node = el; node; node = node.offsetParent) {
|
|
5744
|
+
top2 += node.offsetTop;
|
|
5745
|
+
}
|
|
5746
|
+
return top2;
|
|
5747
|
+
}
|
|
5748
|
+
function beginsOnTheFirstViewport(el) {
|
|
5749
|
+
return documentTop(el) < window.innerHeight;
|
|
5750
|
+
}
|
|
5751
|
+
function useScreenAnchor(ref, enabled = true) {
|
|
5752
|
+
useEffect(() => {
|
|
5753
|
+
const el = ref.current;
|
|
5754
|
+
if (!el || !enabled) return;
|
|
5755
|
+
if (now() - lastTraversal < TRAVERSAL_WINDOW_MS) return;
|
|
5756
|
+
return anchorTop(() => beginsOnTheFirstViewport(el));
|
|
5757
|
+
}, [ref, enabled]);
|
|
5758
|
+
}
|
|
5705
5759
|
const ShopSurface = forwardRef(function ShopSurface2({ tone, fill: fill2 = false, children, className, ...rest }, ref) {
|
|
5706
5760
|
const own = useRef(null);
|
|
5761
|
+
useScreenAnchor(own, fill2);
|
|
5707
5762
|
useTopOffset(own, "--surface-top", fill2);
|
|
5708
5763
|
const attach = useCallback((node) => {
|
|
5709
5764
|
own.current = node;
|
|
@@ -8297,11 +8352,19 @@ function Chevron() {
|
|
|
8297
8352
|
});
|
|
8298
8353
|
}
|
|
8299
8354
|
function OrderListView(props) {
|
|
8355
|
+
const [opened, setOpened] = useState(null);
|
|
8356
|
+
if (opened !== null) {
|
|
8357
|
+
return jsx(ReturnFlowView, {
|
|
8358
|
+
returnRef: opened,
|
|
8359
|
+
onDone: () => setOpened(null)
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8300
8362
|
return jsx(ShopSurface, {
|
|
8301
8363
|
tone: "light",
|
|
8302
8364
|
fill: true,
|
|
8303
8365
|
children: jsx(OrderListContent, {
|
|
8304
|
-
...props
|
|
8366
|
+
...props,
|
|
8367
|
+
onOpenReturn: props.onOpenReturn ?? setOpened
|
|
8305
8368
|
})
|
|
8306
8369
|
});
|
|
8307
8370
|
}
|
|
@@ -10295,14 +10358,14 @@ function formatRemaining(ms) {
|
|
|
10295
10358
|
return `${hh}:${mm}:${ss}`;
|
|
10296
10359
|
}
|
|
10297
10360
|
function PromoBanner({ promo: promo2 }) {
|
|
10298
|
-
const [
|
|
10361
|
+
const [now2, setNow] = useState(null);
|
|
10299
10362
|
useEffect(() => {
|
|
10300
10363
|
if (!promo2.ends_at) return;
|
|
10301
10364
|
setNow(Date.now());
|
|
10302
10365
|
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
10303
10366
|
return () => clearInterval(id);
|
|
10304
10367
|
}, [promo2.ends_at]);
|
|
10305
|
-
const remaining = promo2.ends_at &&
|
|
10368
|
+
const remaining = promo2.ends_at && now2 !== null ? new Date(promo2.ends_at).getTime() - now2 : null;
|
|
10306
10369
|
const showTimer = remaining !== null && remaining > 0;
|
|
10307
10370
|
return jsxs("div", {
|
|
10308
10371
|
className: styles$b.banner,
|
|
@@ -11223,6 +11286,7 @@ function useDocumentSnap(ref, enabled = true) {
|
|
|
11223
11286
|
const top2 = () => window.scrollTo(0, 0);
|
|
11224
11287
|
top2();
|
|
11225
11288
|
const frame2 = typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame(top2) : null;
|
|
11289
|
+
const release = anchorTop();
|
|
11226
11290
|
const history = window.history;
|
|
11227
11291
|
const previousRestoration = history && "scrollRestoration" in history ? history.scrollRestoration : null;
|
|
11228
11292
|
if (previousRestoration !== null) history.scrollRestoration = "manual";
|
|
@@ -11231,6 +11295,7 @@ function useDocumentSnap(ref, enabled = true) {
|
|
|
11231
11295
|
};
|
|
11232
11296
|
window.addEventListener("pageshow", onPageShow);
|
|
11233
11297
|
return () => {
|
|
11298
|
+
release();
|
|
11234
11299
|
if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
|
|
11235
11300
|
window.cancelAnimationFrame(frame2);
|
|
11236
11301
|
}
|
|
@@ -5189,8 +5189,8 @@ function resolveAssetUrl(src, base) {
|
|
|
5189
5189
|
const MAX_AGE_MS = 5 * 6e4;
|
|
5190
5190
|
const CAPACITY = 60;
|
|
5191
5191
|
class ProductCache {
|
|
5192
|
-
constructor(
|
|
5193
|
-
this.now =
|
|
5192
|
+
constructor(now2 = () => Date.now()) {
|
|
5193
|
+
this.now = now2;
|
|
5194
5194
|
}
|
|
5195
5195
|
now;
|
|
5196
5196
|
entries = /* @__PURE__ */ new Map();
|
|
@@ -5702,8 +5702,63 @@ function useTopOffset(ref, property, enabled = true) {
|
|
|
5702
5702
|
};
|
|
5703
5703
|
}, [ref, property, enabled]);
|
|
5704
5704
|
}
|
|
5705
|
+
const HOLD_MS = 1e3;
|
|
5706
|
+
const RELEASES = ["touchstart", "wheel", "keydown", "pointerdown"];
|
|
5707
|
+
function anchorTop(shouldHold = () => true) {
|
|
5708
|
+
let released = false;
|
|
5709
|
+
const top2 = () => {
|
|
5710
|
+
if (released) return;
|
|
5711
|
+
const scrolled2 = window.scrollY || document.documentElement.scrollTop || 0;
|
|
5712
|
+
if (scrolled2 > 0 && shouldHold()) window.scrollTo(0, 0);
|
|
5713
|
+
};
|
|
5714
|
+
const release = () => {
|
|
5715
|
+
if (released) return;
|
|
5716
|
+
released = true;
|
|
5717
|
+
if (frame2 !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame2);
|
|
5718
|
+
clearTimeout(timer2);
|
|
5719
|
+
window.removeEventListener("scroll", top2);
|
|
5720
|
+
for (const type of RELEASES) window.removeEventListener(type, release);
|
|
5721
|
+
};
|
|
5722
|
+
top2();
|
|
5723
|
+
const frame2 = typeof requestAnimationFrame === "function" ? requestAnimationFrame(top2) : null;
|
|
5724
|
+
const timer2 = setTimeout(release, HOLD_MS);
|
|
5725
|
+
window.addEventListener("scroll", top2, {
|
|
5726
|
+
passive: true
|
|
5727
|
+
});
|
|
5728
|
+
for (const type of RELEASES) window.addEventListener(type, release, {
|
|
5729
|
+
passive: true
|
|
5730
|
+
});
|
|
5731
|
+
return release;
|
|
5732
|
+
}
|
|
5733
|
+
const TRAVERSAL_WINDOW_MS = 1e3;
|
|
5734
|
+
const now = () => typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
5735
|
+
let lastTraversal = -Infinity;
|
|
5736
|
+
if (typeof window !== "undefined") {
|
|
5737
|
+
window.addEventListener("popstate", () => {
|
|
5738
|
+
lastTraversal = now();
|
|
5739
|
+
});
|
|
5740
|
+
}
|
|
5741
|
+
function documentTop(el) {
|
|
5742
|
+
let top2 = 0;
|
|
5743
|
+
for (let node = el; node; node = node.offsetParent) {
|
|
5744
|
+
top2 += node.offsetTop;
|
|
5745
|
+
}
|
|
5746
|
+
return top2;
|
|
5747
|
+
}
|
|
5748
|
+
function beginsOnTheFirstViewport(el) {
|
|
5749
|
+
return documentTop(el) < window.innerHeight;
|
|
5750
|
+
}
|
|
5751
|
+
function useScreenAnchor(ref, enabled = true) {
|
|
5752
|
+
useEffect(() => {
|
|
5753
|
+
const el = ref.current;
|
|
5754
|
+
if (!el || !enabled) return;
|
|
5755
|
+
if (now() - lastTraversal < TRAVERSAL_WINDOW_MS) return;
|
|
5756
|
+
return anchorTop(() => beginsOnTheFirstViewport(el));
|
|
5757
|
+
}, [ref, enabled]);
|
|
5758
|
+
}
|
|
5705
5759
|
const ShopSurface = forwardRef(function ShopSurface2({ tone, fill: fill2 = false, children, className, ...rest }, ref) {
|
|
5706
5760
|
const own = useRef(null);
|
|
5761
|
+
useScreenAnchor(own, fill2);
|
|
5707
5762
|
useTopOffset(own, "--surface-top", fill2);
|
|
5708
5763
|
const attach = useCallback((node) => {
|
|
5709
5764
|
own.current = node;
|
|
@@ -8297,11 +8352,19 @@ function Chevron() {
|
|
|
8297
8352
|
});
|
|
8298
8353
|
}
|
|
8299
8354
|
function OrderListView(props) {
|
|
8355
|
+
const [opened, setOpened] = useState(null);
|
|
8356
|
+
if (opened !== null) {
|
|
8357
|
+
return jsx(ReturnFlowView, {
|
|
8358
|
+
returnRef: opened,
|
|
8359
|
+
onDone: () => setOpened(null)
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8300
8362
|
return jsx(ShopSurface, {
|
|
8301
8363
|
tone: "light",
|
|
8302
8364
|
fill: true,
|
|
8303
8365
|
children: jsx(OrderListContent, {
|
|
8304
|
-
...props
|
|
8366
|
+
...props,
|
|
8367
|
+
onOpenReturn: props.onOpenReturn ?? setOpened
|
|
8305
8368
|
})
|
|
8306
8369
|
});
|
|
8307
8370
|
}
|
|
@@ -10295,14 +10358,14 @@ function formatRemaining(ms) {
|
|
|
10295
10358
|
return `${hh}:${mm}:${ss}`;
|
|
10296
10359
|
}
|
|
10297
10360
|
function PromoBanner({ promo: promo2 }) {
|
|
10298
|
-
const [
|
|
10361
|
+
const [now2, setNow] = useState(null);
|
|
10299
10362
|
useEffect(() => {
|
|
10300
10363
|
if (!promo2.ends_at) return;
|
|
10301
10364
|
setNow(Date.now());
|
|
10302
10365
|
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
10303
10366
|
return () => clearInterval(id);
|
|
10304
10367
|
}, [promo2.ends_at]);
|
|
10305
|
-
const remaining = promo2.ends_at &&
|
|
10368
|
+
const remaining = promo2.ends_at && now2 !== null ? new Date(promo2.ends_at).getTime() - now2 : null;
|
|
10306
10369
|
const showTimer = remaining !== null && remaining > 0;
|
|
10307
10370
|
return jsxs("div", {
|
|
10308
10371
|
className: styles$b.banner,
|
|
@@ -11223,6 +11286,7 @@ function useDocumentSnap(ref, enabled = true) {
|
|
|
11223
11286
|
const top2 = () => window.scrollTo(0, 0);
|
|
11224
11287
|
top2();
|
|
11225
11288
|
const frame2 = typeof window.requestAnimationFrame === "function" ? window.requestAnimationFrame(top2) : null;
|
|
11289
|
+
const release = anchorTop();
|
|
11226
11290
|
const history = window.history;
|
|
11227
11291
|
const previousRestoration = history && "scrollRestoration" in history ? history.scrollRestoration : null;
|
|
11228
11292
|
if (previousRestoration !== null) history.scrollRestoration = "manual";
|
|
@@ -11231,6 +11295,7 @@ function useDocumentSnap(ref, enabled = true) {
|
|
|
11231
11295
|
};
|
|
11232
11296
|
window.addEventListener("pageshow", onPageShow);
|
|
11233
11297
|
return () => {
|
|
11298
|
+
release();
|
|
11234
11299
|
if (frame2 !== null && typeof window.cancelAnimationFrame === "function") {
|
|
11235
11300
|
window.cancelAnimationFrame(frame2);
|
|
11236
11301
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nok-integration/storefront-react",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.6",
|
|
4
4
|
"description": "Mountable React storefront components: catalogue, product detail and cart, mounted directly into a host DOM tree. No iframe.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|