@patientos/website-kit 0.2.9 → 0.2.10
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/{chunk-U6FJ6XYX.js → chunk-55W3KKJD.js} +5 -2
- package/dist/{chunk-DP2HJMVB.js → chunk-FW2X2SUZ.js} +3 -3
- package/dist/{chunk-BHF7S6UQ.js → chunk-LW2LLAL4.js} +26 -8
- package/dist/{chunk-ORGTP5GB.js → chunk-Q5DIBKWX.js} +9 -2
- package/dist/{chunk-4GKSSM5N.js → chunk-SYXA5WP7.js} +165 -97
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/islands-impl/cart-button.js +2 -2
- package/dist/islands-impl/cart.js +2 -2
- package/dist/islands-impl.js +4 -4
- package/dist/islands-registry.js +5 -5
- package/dist/website-kit.css +81 -7
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
UnsupportedCartLineList,
|
|
6
6
|
quoteSourceQuantities,
|
|
7
7
|
useCartQuote
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LW2LLAL4.js";
|
|
9
9
|
import {
|
|
10
10
|
createStoreClient
|
|
11
11
|
} from "./chunk-7BUDUYXN.js";
|
|
@@ -24,7 +24,8 @@ function CartClient({ storeApiOrigin }) {
|
|
|
24
24
|
);
|
|
25
25
|
const [cart, setCart] = React.useState(() => readCart());
|
|
26
26
|
const [mutationUnavailable, setMutationUnavailable] = React.useState(false);
|
|
27
|
-
const { quote, quoteSourceCart, failed } = useCartQuote(client, cart);
|
|
27
|
+
const { quote, quoteSourceCart, failed, pending } = useCartQuote(client, cart);
|
|
28
|
+
const liveQuantities = React.useMemo(() => quoteSourceQuantities(cart), [cart]);
|
|
28
29
|
async function runMutation(mutation) {
|
|
29
30
|
const result = await mutation;
|
|
30
31
|
setMutationUnavailable(result.status === "cart_storage_unavailable");
|
|
@@ -61,6 +62,8 @@ function CartClient({ storeApiOrigin }) {
|
|
|
61
62
|
{
|
|
62
63
|
lines: quote.lines,
|
|
63
64
|
sourceQuantities: quoteSourceQuantities(quoteSourceCart),
|
|
65
|
+
liveQuantities,
|
|
66
|
+
pending,
|
|
64
67
|
onMutate: (m) => void runMutation(m)
|
|
65
68
|
}
|
|
66
69
|
),
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
CertificateFunnelClient,
|
|
4
4
|
PortalAccountClient,
|
|
5
5
|
PortalPanelClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SYXA5WP7.js";
|
|
7
7
|
import {
|
|
8
8
|
mountIslandsWith
|
|
9
9
|
} from "./chunk-THMT43MV.js";
|
|
10
10
|
import {
|
|
11
11
|
CartClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-55W3KKJD.js";
|
|
13
13
|
import {
|
|
14
14
|
CartButtonClient
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-Q5DIBKWX.js";
|
|
16
16
|
import {
|
|
17
17
|
CheckoutClient
|
|
18
18
|
} from "./chunk-S3ZQQOQT.js";
|
|
@@ -50,9 +50,11 @@ function UnsupportedCartLineList({
|
|
|
50
50
|
function CartLineList({
|
|
51
51
|
lines,
|
|
52
52
|
sourceQuantities,
|
|
53
|
-
onMutate
|
|
53
|
+
onMutate,
|
|
54
|
+
liveQuantities,
|
|
55
|
+
pending
|
|
54
56
|
}) {
|
|
55
|
-
return /* @__PURE__ */ jsx("ul", { className: "sk-cart__lines", children: lines.map((line) => /* @__PURE__ */ jsxs("li", { className: "sk-cart__line", children: [
|
|
57
|
+
return /* @__PURE__ */ jsx("ul", { className: "sk-cart__lines", "aria-busy": pending || void 0, children: lines.map((line) => /* @__PURE__ */ jsxs("li", { className: "sk-cart__line", children: [
|
|
56
58
|
/* @__PURE__ */ jsx("a", { className: "sk-cart__line-title", href: `/store/${line.productHandle}`, children: line.title }),
|
|
57
59
|
/* @__PURE__ */ jsxs("span", { className: "sk-cart__line-unit", children: [
|
|
58
60
|
formatMoney(line.unitPrice),
|
|
@@ -75,7 +77,7 @@ function CartLineList({
|
|
|
75
77
|
children: "\u2212"
|
|
76
78
|
}
|
|
77
79
|
),
|
|
78
|
-
/* @__PURE__ */ jsx("span", { className: "sk-cart__qty-value", "aria-live": "polite", children: line.quantity }),
|
|
80
|
+
/* @__PURE__ */ jsx("span", { className: "sk-cart__qty-value", "aria-live": "polite", children: (pending ? liveQuantities?.get(line.variantId) : void 0) ?? line.quantity }),
|
|
79
81
|
/* @__PURE__ */ jsx(
|
|
80
82
|
"button",
|
|
81
83
|
{
|
|
@@ -125,22 +127,38 @@ function useCartQuote(client, cart, enabled = true) {
|
|
|
125
127
|
const [state, setState] = React.useState({
|
|
126
128
|
quote: null,
|
|
127
129
|
quoteSourceCart: null,
|
|
128
|
-
failed: false
|
|
130
|
+
failed: false,
|
|
131
|
+
pending: false
|
|
129
132
|
});
|
|
130
133
|
React.useEffect(() => {
|
|
131
134
|
if (!enabled || cart.lines.length === 0) {
|
|
132
|
-
setState({
|
|
135
|
+
setState({
|
|
136
|
+
quote: null,
|
|
137
|
+
quoteSourceCart: null,
|
|
138
|
+
failed: false,
|
|
139
|
+
pending: false
|
|
140
|
+
});
|
|
133
141
|
return;
|
|
134
142
|
}
|
|
135
143
|
let alive = true;
|
|
136
|
-
setState({
|
|
144
|
+
setState((previous) => ({ ...previous, failed: false, pending: true }));
|
|
137
145
|
void client.post("/api/store/quote", { lines: cartToWireLines(cart) }).then((result) => {
|
|
138
146
|
if (!alive) return;
|
|
139
147
|
if (!result.ok) {
|
|
140
|
-
setState({
|
|
148
|
+
setState({
|
|
149
|
+
quote: null,
|
|
150
|
+
quoteSourceCart: null,
|
|
151
|
+
failed: true,
|
|
152
|
+
pending: false
|
|
153
|
+
});
|
|
141
154
|
return;
|
|
142
155
|
}
|
|
143
|
-
setState({
|
|
156
|
+
setState({
|
|
157
|
+
quote: result.data,
|
|
158
|
+
quoteSourceCart: cart,
|
|
159
|
+
failed: false,
|
|
160
|
+
pending: false
|
|
161
|
+
});
|
|
144
162
|
});
|
|
145
163
|
return () => {
|
|
146
164
|
alive = false;
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
UnsupportedCartLineList,
|
|
6
6
|
quoteSourceQuantities,
|
|
7
7
|
useCartQuote
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LW2LLAL4.js";
|
|
9
9
|
import {
|
|
10
10
|
createStoreClient
|
|
11
11
|
} from "./chunk-7BUDUYXN.js";
|
|
@@ -87,7 +87,12 @@ function CartDrawer({
|
|
|
87
87
|
window.addEventListener("keydown", onKeyDown);
|
|
88
88
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
89
89
|
}, [open, onClose]);
|
|
90
|
-
const { quote, quoteSourceCart, failed } = useCartQuote(
|
|
90
|
+
const { quote, quoteSourceCart, failed, pending } = useCartQuote(
|
|
91
|
+
client,
|
|
92
|
+
cart,
|
|
93
|
+
open
|
|
94
|
+
);
|
|
95
|
+
const liveQuantities = React.useMemo(() => quoteSourceQuantities(cart), [cart]);
|
|
91
96
|
async function runMutation(mutation) {
|
|
92
97
|
const result = await mutation;
|
|
93
98
|
setMutationUnavailable(result.status === "cart_storage_unavailable");
|
|
@@ -144,6 +149,8 @@ function CartDrawer({
|
|
|
144
149
|
{
|
|
145
150
|
lines: quote.lines,
|
|
146
151
|
sourceQuantities: quoteSourceQuantities(quoteSourceCart),
|
|
152
|
+
liveQuantities,
|
|
153
|
+
pending,
|
|
147
154
|
onMutate: (m) => void runMutation(m)
|
|
148
155
|
}
|
|
149
156
|
),
|
|
@@ -11062,6 +11062,23 @@ function PortalConsultPanel({
|
|
|
11062
11062
|
] });
|
|
11063
11063
|
}
|
|
11064
11064
|
|
|
11065
|
+
// src/portal-account-cache.ts
|
|
11066
|
+
var snapshots = /* @__PURE__ */ new Map();
|
|
11067
|
+
function rememberPortalAccount(surface, state) {
|
|
11068
|
+
if (state.kind === "signed-in") {
|
|
11069
|
+
snapshots.set(surface, state);
|
|
11070
|
+
return;
|
|
11071
|
+
}
|
|
11072
|
+
if (state.kind === "loading" || state.kind === "link-sent") return;
|
|
11073
|
+
clearPortalAccountCache();
|
|
11074
|
+
}
|
|
11075
|
+
function recallPortalAccount(surface) {
|
|
11076
|
+
return snapshots.get(surface) ?? null;
|
|
11077
|
+
}
|
|
11078
|
+
function clearPortalAccountCache() {
|
|
11079
|
+
snapshots.clear();
|
|
11080
|
+
}
|
|
11081
|
+
|
|
11065
11082
|
// src/portal-account.client.tsx
|
|
11066
11083
|
import { Fragment as Fragment11, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
11067
11084
|
var APPOINTMENTS_URL = "/portal/api/appointments";
|
|
@@ -11220,21 +11237,36 @@ function PortalAccountSurfaceClient({
|
|
|
11220
11237
|
const portalClient = usePortalClient();
|
|
11221
11238
|
const fetchImpl = React21.useMemo(() => portalFetchForClient(portalClient), [portalClient]);
|
|
11222
11239
|
const [state, setState] = React21.useState(
|
|
11223
|
-
//
|
|
11240
|
+
// STALE-WHILE-REVALIDATE (PAT-949). Three ways to start, in falling order of how
|
|
11241
|
+
// much we already know:
|
|
11242
|
+
// 1. the caller drove it (tests, a future SSR seed);
|
|
11243
|
+
// 2. this document already resolved this surface — render that body NOW and
|
|
11244
|
+
// revalidate behind it, so returning to a surface is not a redraw. In-memory
|
|
11245
|
+
// only; see `./portal-account-cache` for the PHI rules;
|
|
11246
|
+
// 3. genuinely cold — a skeleton, shaped like the rows about to land.
|
|
11247
|
+
// `readPortalSignedInHint` stays in the initialiser (not an effect) on purpose: the
|
|
11224
11248
|
// whole point is that the FIRST paint already knows, so there is no placeholder
|
|
11225
11249
|
// swap. It reads one boolean out of sessionStorage — no PHI, no network.
|
|
11226
|
-
() => initialState ?? { kind: "loading", hinted: readPortalSignedInHint() }
|
|
11250
|
+
() => initialState ?? recallPortalAccount(surface) ?? { kind: "loading", hinted: readPortalSignedInHint() }
|
|
11227
11251
|
);
|
|
11228
11252
|
const [signingOut, setSigningOut] = React21.useState(false);
|
|
11229
|
-
const
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11253
|
+
const [revalidating, setRevalidating] = React21.useState(false);
|
|
11254
|
+
const commit = React21.useCallback(
|
|
11255
|
+
(next) => {
|
|
11256
|
+
writePortalSignedInHint(next.kind === "signed-in" || next.kind === "not-available");
|
|
11257
|
+
rememberPortalAccount(surface, next);
|
|
11258
|
+
setState(next);
|
|
11259
|
+
},
|
|
11260
|
+
[surface]
|
|
11261
|
+
);
|
|
11233
11262
|
React21.useEffect(() => {
|
|
11234
11263
|
if (initialState) return;
|
|
11235
11264
|
let live = true;
|
|
11265
|
+
setRevalidating(true);
|
|
11236
11266
|
void loadPortalAccount(surface, fetchImpl).then((next) => {
|
|
11237
|
-
if (live)
|
|
11267
|
+
if (!live) return;
|
|
11268
|
+
setRevalidating(false);
|
|
11269
|
+
commit(next);
|
|
11238
11270
|
});
|
|
11239
11271
|
return () => {
|
|
11240
11272
|
live = false;
|
|
@@ -11246,6 +11278,7 @@ function PortalAccountSurfaceClient({
|
|
|
11246
11278
|
async function onSignOut() {
|
|
11247
11279
|
if (signingOut) return;
|
|
11248
11280
|
setSigningOut(true);
|
|
11281
|
+
clearPortalAccountCache();
|
|
11249
11282
|
await signOutOfPortal(fetchImpl);
|
|
11250
11283
|
const next = await loadPortalAccount(surface, fetchImpl);
|
|
11251
11284
|
setSigningOut(false);
|
|
@@ -11253,91 +11286,119 @@ function PortalAccountSurfaceClient({
|
|
|
11253
11286
|
}
|
|
11254
11287
|
function replaceData(data) {
|
|
11255
11288
|
const refetched = refetchedGivenName(data);
|
|
11256
|
-
setState(
|
|
11257
|
-
(prev
|
|
11258
|
-
|
|
11289
|
+
setState((prev) => {
|
|
11290
|
+
if (prev.kind !== "signed-in") return prev;
|
|
11291
|
+
const next = {
|
|
11292
|
+
...prev,
|
|
11293
|
+
data,
|
|
11294
|
+
givenName: refetched === void 0 ? prev.givenName : refetched
|
|
11295
|
+
};
|
|
11296
|
+
rememberPortalAccount(surface, next);
|
|
11297
|
+
return next;
|
|
11298
|
+
});
|
|
11259
11299
|
}
|
|
11260
|
-
return /* @__PURE__ */ jsxs23(
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
11280
|
-
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
|
|
11284
|
-
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11300
|
+
return /* @__PURE__ */ jsxs23(
|
|
11301
|
+
"section",
|
|
11302
|
+
{
|
|
11303
|
+
className: "sk-portal-account__body",
|
|
11304
|
+
"aria-busy": state.kind === "loading" || revalidating,
|
|
11305
|
+
children: [
|
|
11306
|
+
/* @__PURE__ */ jsx26("h2", { className: "sk-portal-account__heading", children: heading2 }),
|
|
11307
|
+
state.kind === "loading" && !state.hinted ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", role: "status", children: "Checking your sign-in\u2026" }) : null,
|
|
11308
|
+
state.kind === "loading" && state.hinted ? /* @__PURE__ */ jsx26(PortalAccountSkeleton, { surface }) : null,
|
|
11309
|
+
state.kind === "link-out" ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", children: /* @__PURE__ */ jsx26("a", { className: "sk-portal-link", href: base2, children: "Sign in to your patient portal" }) }) : null,
|
|
11310
|
+
state.kind === "signed-out" ? /* @__PURE__ */ jsx26(
|
|
11311
|
+
PortalSignInRamp,
|
|
11312
|
+
{
|
|
11313
|
+
idSuffix: `account-${surface}`,
|
|
11314
|
+
submit: (email) => portalClient.requestMagicLink(email).then((ok) => ({ ok })),
|
|
11315
|
+
onResult: ({ ok, email }) => setState(ok ? { kind: "link-sent", email } : { kind: "link-out" })
|
|
11316
|
+
}
|
|
11317
|
+
) : null,
|
|
11318
|
+
state.kind === "link-sent" ? /* @__PURE__ */ jsx26(PortalLinkSentNotice, { email: state.email }) : null,
|
|
11319
|
+
state.kind === "not-available" || state.kind === "signed-in" ? /* @__PURE__ */ jsxs23("div", { className: "sk-portal-account__header", children: [
|
|
11320
|
+
/* @__PURE__ */ jsxs23("span", { className: "sk-portal-account__who", children: [
|
|
11321
|
+
"Signed in as ",
|
|
11322
|
+
state.givenName ?? "you"
|
|
11323
|
+
] }),
|
|
11324
|
+
/* @__PURE__ */ jsx26(
|
|
11325
|
+
"button",
|
|
11326
|
+
{
|
|
11327
|
+
type: "button",
|
|
11328
|
+
className: "sk-portal-button sk-portal-button--ghost",
|
|
11329
|
+
onClick: () => void onSignOut(),
|
|
11330
|
+
disabled: signingOut,
|
|
11331
|
+
children: signingOut ? "Signing out\u2026" : "Sign out"
|
|
11332
|
+
}
|
|
11333
|
+
)
|
|
11334
|
+
] }) : null,
|
|
11335
|
+
state.kind === "not-available" ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__note", role: "note", children: "This isn't available online at this clinic." }) : null,
|
|
11336
|
+
state.kind === "signed-in" && surface === "appointments" ? /* @__PURE__ */ jsx26(
|
|
11337
|
+
PortalAccountAppointments,
|
|
11338
|
+
{
|
|
11339
|
+
data: state.data,
|
|
11340
|
+
base: base2,
|
|
11341
|
+
bookHref: book,
|
|
11342
|
+
fetchImpl,
|
|
11343
|
+
onReloaded: replaceData
|
|
11344
|
+
}
|
|
11345
|
+
) : null,
|
|
11346
|
+
state.kind === "signed-in" && surface === "addresses" ? /* @__PURE__ */ jsx26(
|
|
11347
|
+
PortalAccountAddresses,
|
|
11348
|
+
{
|
|
11349
|
+
data: state.data,
|
|
11350
|
+
client: portalClient,
|
|
11351
|
+
fetchImpl,
|
|
11352
|
+
onReloaded: replaceData
|
|
11353
|
+
}
|
|
11354
|
+
) : null,
|
|
11355
|
+
state.kind === "signed-in" && surface === "documents" ? /* @__PURE__ */ jsx26(
|
|
11356
|
+
PortalAccountDocuments,
|
|
11357
|
+
{
|
|
11358
|
+
data: state.data,
|
|
11359
|
+
fetchImpl,
|
|
11360
|
+
openUrl
|
|
11361
|
+
}
|
|
11362
|
+
) : null,
|
|
11363
|
+
state.kind === "signed-in" && surface === "orders" ? /* @__PURE__ */ jsx26(
|
|
11364
|
+
PortalAccountOrders,
|
|
11365
|
+
{
|
|
11366
|
+
data: state.data,
|
|
11367
|
+
fetchImpl,
|
|
11368
|
+
openUrl
|
|
11369
|
+
}
|
|
11370
|
+
) : null,
|
|
11371
|
+
state.kind === "signed-in" && surface === "profile" ? /* @__PURE__ */ jsx26(
|
|
11372
|
+
PortalAccountProfile,
|
|
11373
|
+
{
|
|
11374
|
+
data: state.data,
|
|
11375
|
+
fetchImpl,
|
|
11376
|
+
onSaved: replaceData
|
|
11377
|
+
}
|
|
11378
|
+
) : null
|
|
11379
|
+
]
|
|
11380
|
+
}
|
|
11381
|
+
);
|
|
11335
11382
|
}
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11383
|
+
var SKELETON_ROWS = 3;
|
|
11384
|
+
function PortalAccountSkeleton({
|
|
11385
|
+
surface
|
|
11386
|
+
}) {
|
|
11387
|
+
const grouped = surface === "appointments";
|
|
11388
|
+
return /* @__PURE__ */ jsxs23(Fragment11, { children: [
|
|
11389
|
+
/* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder sk-portal-account__placeholder--sr", role: "status", children: "Loading your account\u2026" }),
|
|
11390
|
+
/* @__PURE__ */ jsxs23("div", { className: "sk-portal-account__skeleton", "aria-hidden": "true", children: [
|
|
11391
|
+
/* @__PURE__ */ jsxs23("div", { className: "sk-portal-account__header sk-portal-account__header--skeleton", children: [
|
|
11392
|
+
/* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--who" }),
|
|
11393
|
+
/* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--button" })
|
|
11394
|
+
] }),
|
|
11395
|
+
grouped ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__group-title sk-portal-account__group-title--skeleton", children: /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--group" }) }) : null,
|
|
11396
|
+
/* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__list", children: Array.from({ length: SKELETON_ROWS }, (_, index) => /* @__PURE__ */ jsxs23("li", { className: "sk-portal-account__item sk-portal-account__item--skeleton", children: [
|
|
11397
|
+
/* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--title" }),
|
|
11398
|
+
/* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--meta" }),
|
|
11399
|
+
grouped ? /* @__PURE__ */ jsx26("span", { className: "sk-portal-account__skeleton-line sk-portal-account__skeleton-line--meta" }) : null
|
|
11400
|
+
] }, index)) })
|
|
11401
|
+
] })
|
|
11341
11402
|
] });
|
|
11342
11403
|
}
|
|
11343
11404
|
function StatusBadge({ status }) {
|
|
@@ -11598,8 +11659,11 @@ function PortalAccountOrders({
|
|
|
11598
11659
|
initialUi
|
|
11599
11660
|
}) {
|
|
11600
11661
|
const [expandedId, setExpandedId] = React21.useState(initialUi?.expandedId ?? null);
|
|
11601
|
-
const [
|
|
11602
|
-
|
|
11662
|
+
const [details, setDetails] = React21.useState(
|
|
11663
|
+
() => initialUi?.detail && initialUi.expandedId ? { [initialUi.expandedId]: initialUi.detail } : {}
|
|
11664
|
+
);
|
|
11665
|
+
const [loadingId, setLoadingId] = React21.useState(null);
|
|
11666
|
+
const [failedIds, setFailedIds] = React21.useState([]);
|
|
11603
11667
|
const [error2, setError] = React21.useState(initialUi?.error ?? null);
|
|
11604
11668
|
async function toggle(id) {
|
|
11605
11669
|
if (expandedId === id) {
|
|
@@ -11607,12 +11671,13 @@ function PortalAccountOrders({
|
|
|
11607
11671
|
return;
|
|
11608
11672
|
}
|
|
11609
11673
|
setExpandedId(id);
|
|
11610
|
-
setDetail(null);
|
|
11611
11674
|
setError(null);
|
|
11612
|
-
|
|
11675
|
+
if (details[id]) return;
|
|
11676
|
+
setLoadingId(id);
|
|
11613
11677
|
const next = await loadPortalOrderDetail(id, fetchImpl);
|
|
11614
|
-
|
|
11615
|
-
|
|
11678
|
+
setLoadingId((current) => current === id ? null : current);
|
|
11679
|
+
if (next) setDetails((prev) => ({ ...prev, [id]: next }));
|
|
11680
|
+
else setFailedIds((prev) => prev.includes(id) ? prev : [...prev, id]);
|
|
11616
11681
|
}
|
|
11617
11682
|
async function receipt(id) {
|
|
11618
11683
|
setError(null);
|
|
@@ -11626,6 +11691,9 @@ function PortalAccountOrders({
|
|
|
11626
11691
|
/* @__PURE__ */ jsx26(ErrorNote, { message: error2 }),
|
|
11627
11692
|
/* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__list", children: data.items.map((order) => {
|
|
11628
11693
|
const open = expandedId === order.id;
|
|
11694
|
+
const detail = details[order.id] ?? null;
|
|
11695
|
+
const loading = loadingId === order.id && !detail;
|
|
11696
|
+
const failed = !detail && failedIds.includes(order.id);
|
|
11629
11697
|
return /* @__PURE__ */ jsxs23("li", { className: "sk-portal-account__item", children: [
|
|
11630
11698
|
/* @__PURE__ */ jsxs23(
|
|
11631
11699
|
"button",
|
|
@@ -11645,7 +11713,7 @@ function PortalAccountOrders({
|
|
|
11645
11713
|
]
|
|
11646
11714
|
}
|
|
11647
11715
|
),
|
|
11648
|
-
open ? /* @__PURE__ */ jsx26("div", { className: "sk-portal-account__detail", children: loading ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", role: "status", children: "Loading this order\u2026" }) : !detail ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__note", role: "note", children: "We couldn't load this order just now." }) : /* @__PURE__ */ jsxs23(Fragment11, { children: [
|
|
11716
|
+
open ? /* @__PURE__ */ jsx26("div", { className: "sk-portal-account__detail", "aria-busy": loading, children: loading ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__placeholder", role: "status", children: "Loading this order\u2026" }) : failed || !detail ? /* @__PURE__ */ jsx26("p", { className: "sk-portal-account__note", role: "note", children: "We couldn't load this order just now." }) : /* @__PURE__ */ jsxs23(Fragment11, { children: [
|
|
11649
11717
|
/* @__PURE__ */ jsx26("ul", { className: "sk-portal-account__lines", children: (detail.lines ?? []).map((line) => /* @__PURE__ */ jsxs23("li", { className: "sk-portal-account__line", children: [
|
|
11650
11718
|
/* @__PURE__ */ jsxs23("span", { children: [
|
|
11651
11719
|
line.title ?? "\u2014",
|
package/dist/index.d.ts
CHANGED
|
@@ -217,6 +217,6 @@ interface PortalSession {
|
|
|
217
217
|
*/
|
|
218
218
|
declare function usePortalSession(): PortalSession;
|
|
219
219
|
|
|
220
|
-
declare const WEBSITE_KIT_VERSION = "0.2.
|
|
220
|
+
declare const WEBSITE_KIT_VERSION = "0.2.10";
|
|
221
221
|
|
|
222
222
|
export { Button, type ButtonProps, type ButtonVariant, Container, type ContainerProps, FAQ, type FAQProps, type FaqItem, Hero, type HeroProps, Hours, type HoursProps, type HoursRow, MapEmbed, type MapEmbedProps, PortalClient, PortalPrefill, PortalProvider, type PortalProviderProps, type PortalSession, type PortalSessionStatus, PublicClaim, Row, type RowProps, Section, type SectionProps, type Service, ServiceGrid, type ServiceGridProps, Stack, type StackProps, TeamGrid, type TeamGridProps, type TeamMember, ThemeProvider, type ThemeProviderProps, WEBSITE_KIT_VERSION, WebsiteShell, type WebsiteShellProps, type WebsiteTheme, WhoAmI, defaultTheme, resolveTheme, themeToCssVars, usePortalClient, usePortalSession };
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
ISLANDS,
|
|
13
13
|
mountIslands
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-FW2X2SUZ.js";
|
|
15
15
|
import {
|
|
16
16
|
PortalAccount,
|
|
17
17
|
PortalPanel,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
getThemeTokens,
|
|
24
24
|
usePortalClient,
|
|
25
25
|
usePortalSession
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-SYXA5WP7.js";
|
|
27
27
|
import "./chunk-3T7UWKAH.js";
|
|
28
28
|
import {
|
|
29
29
|
evaluateShowWhen,
|
|
@@ -36,9 +36,9 @@ import {
|
|
|
36
36
|
mountIslandsWith,
|
|
37
37
|
readIslandProps
|
|
38
38
|
} from "./chunk-THMT43MV.js";
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
39
|
+
import "./chunk-55W3KKJD.js";
|
|
40
|
+
import "./chunk-Q5DIBKWX.js";
|
|
41
|
+
import "./chunk-LW2LLAL4.js";
|
|
42
42
|
import "./chunk-S3ZQQOQT.js";
|
|
43
43
|
import {
|
|
44
44
|
BPOINT_SCRIPT_ORIGIN,
|
|
@@ -511,7 +511,7 @@ function Checkout({
|
|
|
511
511
|
}
|
|
512
512
|
|
|
513
513
|
// src/index.ts
|
|
514
|
-
var WEBSITE_KIT_VERSION = "0.2.
|
|
514
|
+
var WEBSITE_KIT_VERSION = "0.2.10";
|
|
515
515
|
export {
|
|
516
516
|
BPOINT_SCRIPT_ORIGIN,
|
|
517
517
|
BPOINT_SCRIPT_URL,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CartButtonClient,
|
|
3
3
|
CartDrawer
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-Q5DIBKWX.js";
|
|
5
|
+
import "../chunk-LW2LLAL4.js";
|
|
6
6
|
import "../chunk-7BUDUYXN.js";
|
|
7
7
|
import "../chunk-4NF7SSIX.js";
|
|
8
8
|
import "../chunk-FZ4WKWIE.js";
|
package/dist/islands-impl.js
CHANGED
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
CertificateFunnelClient,
|
|
4
4
|
PortalAccountClient,
|
|
5
5
|
PortalPanelClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SYXA5WP7.js";
|
|
7
7
|
import "./chunk-3T7UWKAH.js";
|
|
8
8
|
import "./chunk-QDO3SJWR.js";
|
|
9
9
|
import "./chunk-THMT43MV.js";
|
|
10
10
|
import {
|
|
11
11
|
CartClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-55W3KKJD.js";
|
|
13
13
|
import {
|
|
14
14
|
CartButtonClient
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-Q5DIBKWX.js";
|
|
16
|
+
import "./chunk-LW2LLAL4.js";
|
|
17
17
|
import {
|
|
18
18
|
CheckoutClient
|
|
19
19
|
} from "./chunk-S3ZQQOQT.js";
|
package/dist/islands-registry.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ISLANDS,
|
|
3
3
|
mountIslands
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-FW2X2SUZ.js";
|
|
5
|
+
import "./chunk-SYXA5WP7.js";
|
|
6
6
|
import "./chunk-3T7UWKAH.js";
|
|
7
7
|
import "./chunk-QDO3SJWR.js";
|
|
8
8
|
import "./chunk-THMT43MV.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-55W3KKJD.js";
|
|
10
|
+
import "./chunk-Q5DIBKWX.js";
|
|
11
|
+
import "./chunk-LW2LLAL4.js";
|
|
12
12
|
import "./chunk-S3ZQQOQT.js";
|
|
13
13
|
import "./chunk-ZOF22TJA.js";
|
|
14
14
|
import "./chunk-UTAMB2SK.js";
|
package/dist/website-kit.css
CHANGED
|
@@ -2414,16 +2414,78 @@ select.sk-identity__input[data-empty] {
|
|
|
2414
2414
|
* to earn its keep, and it buys nothing here — this is on screen for a few hundred ms.
|
|
2415
2415
|
* This is NOT the no-JS fallback below; that one is real content and must stay real. */
|
|
2416
2416
|
.sk-portal-account__skeleton {
|
|
2417
|
-
display:
|
|
2418
|
-
|
|
2419
|
-
gap: var(--sk-space, 0.5rem);
|
|
2420
|
-
margin-bottom: calc(var(--sk-space, 0.5rem) * 2);
|
|
2417
|
+
display: block;
|
|
2418
|
+
margin-bottom: 0;
|
|
2421
2419
|
}
|
|
2422
2420
|
|
|
2423
|
-
|
|
2424
|
-
|
|
2421
|
+
/* PAT-949 — the skeleton borrows `__header` and `__item` for its boxes (see the
|
|
2422
|
+
* component), so the only thing defined here is the INK inside them and the two
|
|
2423
|
+
* differences a placeholder needs: it cannot be clicked, and its header carries no
|
|
2424
|
+
* text to give it height, so it gets the height back explicitly. */
|
|
2425
|
+
.sk-portal-account__header--skeleton {
|
|
2426
|
+
min-height: 2.25rem;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
.sk-portal-account__item--skeleton {
|
|
2430
|
+
pointer-events: none;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
.sk-portal-account__skeleton-line {
|
|
2434
|
+
display: block;
|
|
2435
|
+
height: 0.875rem;
|
|
2425
2436
|
border-radius: var(--sk-radius, 0.625rem);
|
|
2426
|
-
background: color-mix(in srgb, var(--sk-neutral-foreground, #1b2733)
|
|
2437
|
+
background: color-mix(in srgb, var(--sk-neutral-foreground, #1b2733) 12%, transparent);
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
/* Widths chosen to sit under the real strings they stand in for: "Signed in as Jane",
|
|
2441
|
+
* a "Sign out" ghost button, an item title and its date · clinician · amount line. */
|
|
2442
|
+
.sk-portal-account__skeleton-line--who {
|
|
2443
|
+
width: 10rem;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
.sk-portal-account__skeleton-line--button {
|
|
2447
|
+
width: 5.5rem;
|
|
2448
|
+
height: 2rem;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
.sk-portal-account__skeleton-line--title {
|
|
2452
|
+
width: 60%;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
.sk-portal-account__skeleton-line--meta {
|
|
2456
|
+
width: 40%;
|
|
2457
|
+
height: 0.75rem;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
/* Stands in for a group heading ("UPCOMING"), so the list does not slide up under one
|
|
2461
|
+
* when the real body lands. */
|
|
2462
|
+
.sk-portal-account__group-title--skeleton {
|
|
2463
|
+
display: block;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
.sk-portal-account__skeleton-line--group {
|
|
2467
|
+
width: 6rem;
|
|
2468
|
+
height: 0.75rem;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2472
|
+
.sk-portal-account__skeleton-line {
|
|
2473
|
+
animation: sk-skeleton-pulse 1.4s ease-in-out infinite;
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
/* The screen-reader-only status line the skeleton announces itself with — the bars
|
|
2478
|
+
* themselves are `aria-hidden`. Same recipe as the store block's (PAT-944). */
|
|
2479
|
+
.sk-portal-account__placeholder--sr {
|
|
2480
|
+
position: absolute;
|
|
2481
|
+
width: 1px;
|
|
2482
|
+
height: 1px;
|
|
2483
|
+
padding: 0;
|
|
2484
|
+
margin: -1px;
|
|
2485
|
+
overflow: hidden;
|
|
2486
|
+
clip-path: inset(50%);
|
|
2487
|
+
white-space: nowrap;
|
|
2488
|
+
border: 0;
|
|
2427
2489
|
}
|
|
2428
2490
|
|
|
2429
2491
|
/* The build-time no-JS fallback: REAL visible content, never a hidden skeleton. */
|
|
@@ -2887,6 +2949,18 @@ select.sk-identity__input[data-empty] {
|
|
|
2887
2949
|
border-radius: var(--sk-radius, 0.625rem);
|
|
2888
2950
|
font-size: 0.9375rem;
|
|
2889
2951
|
}
|
|
2952
|
+
.sk-cart__lines[aria-busy='true'] {
|
|
2953
|
+
/* A re-quote is in flight over prices that are still correct enough to read. Dim the
|
|
2954
|
+
money a touch rather than tearing the list down — the teardown is what read as the
|
|
2955
|
+
cart reloading (PAT-949). Steppers stay live: the cart write already succeeded. */
|
|
2956
|
+
opacity: 0.7;
|
|
2957
|
+
transition: opacity 120ms ease-out;
|
|
2958
|
+
}
|
|
2959
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2960
|
+
.sk-cart__lines[aria-busy='true'] {
|
|
2961
|
+
transition: none;
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2890
2964
|
.sk-cart__lines {
|
|
2891
2965
|
list-style: none;
|
|
2892
2966
|
margin: 0;
|