@cimplify/sdk 0.90.0 → 0.93.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/dist/advanced.d.mts +3 -3
- package/dist/advanced.d.ts +3 -3
- package/dist/advanced.js +20 -20
- package/dist/advanced.mjs +1 -1
- package/dist/{chunk-KJP4U6L3.js → chunk-6Y7KC5YZ.js} +23 -0
- package/dist/{chunk-JVWFIFQ7.js → chunk-AWNWP5J3.js} +4 -4
- package/dist/{chunk-2UDEWILL.mjs → chunk-FKARGZK3.mjs} +307 -90
- package/dist/{chunk-T7Z25EY4.js → chunk-HKN3YG76.js} +84 -0
- package/dist/{chunk-BN4V4ONE.js → chunk-QLGZIBRO.js} +348 -128
- package/dist/{chunk-NGE37REW.mjs → chunk-QXWX7CD2.mjs} +2 -2
- package/dist/{chunk-OZDDHSIB.mjs → chunk-RRBY35TJ.mjs} +80 -1
- package/dist/{chunk-GHFDYM5K.js → chunk-VEOAMBEX.js} +11 -4
- package/dist/{chunk-ZU4ZRYUR.mjs → chunk-VUSHG3HA.mjs} +11 -4
- package/dist/{chunk-NNGKC3MM.mjs → chunk-X36FZZT6.mjs} +23 -0
- package/dist/{client-YiSelM7x.d.mts → client-BTL9d_nN.d.mts} +117 -11
- package/dist/{client-CR1f94wY.d.ts → client-BX30FAWZ.d.ts} +117 -11
- package/dist/{client-DMttx1xk.d.mts → client-Bhe2TnFW.d.mts} +2 -2
- package/dist/{client-CqpOcbin.d.ts → client-DrkuEK_I.d.ts} +2 -2
- package/dist/{index-DD9z396M.d.mts → index-BuNjyfaV.d.mts} +3 -3
- package/dist/{index-CxTVu0HZ.d.ts → index-D-w5h82t.d.ts} +3 -3
- package/dist/index.d.mts +49 -7
- package/dist/index.d.ts +49 -7
- package/dist/index.js +103 -83
- package/dist/index.mjs +5 -5
- package/dist/mock/cli.mjs +23 -0
- package/dist/mock/library.js +23 -0
- package/dist/mock/library.mjs +23 -0
- package/dist/mock/msw.js +23 -0
- package/dist/mock/msw.mjs +23 -0
- package/dist/{payment-BX7ccIKY.d.ts → payment-By0JidTe.d.ts} +1 -1
- package/dist/{payment-5d8FTA1q.d.mts → payment-pKPpaORI.d.mts} +1 -1
- package/dist/{price-DtfP_Xfq.d.ts → price-23RNXftz.d.ts} +1 -1
- package/dist/{price-arl_4Rzn.d.mts → price-BvRtp6ak.d.mts} +1 -1
- package/dist/{product-DZX4QuKS.d.ts → product-O8-wcHSe.d.mts} +49 -0
- package/dist/{product-DZX4QuKS.d.mts → product-O8-wcHSe.d.ts} +49 -0
- package/dist/react.d.mts +79 -6
- package/dist/react.d.ts +79 -6
- package/dist/react.js +607 -379
- package/dist/react.mjs +539 -315
- package/dist/{server-BceZMxcK.d.mts → server-BN9ZCAKT.d.mts} +5 -1
- package/dist/{server-DoJGSC7L.d.ts → server-DDGbfW_S.d.ts} +5 -1
- package/dist/server.d.mts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +7 -7
- package/dist/server.mjs +2 -2
- package/dist/styles.css +1 -1
- package/dist/testing/msw.d.mts +2 -2
- package/dist/testing/msw.d.ts +2 -2
- package/dist/testing/msw.js +2 -2
- package/dist/testing/msw.mjs +1 -1
- package/dist/testing/suite.d.mts +6 -6
- package/dist/testing/suite.d.ts +6 -6
- package/dist/testing/suite.js +23 -23
- package/dist/testing/suite.mjs +4 -4
- package/dist/testing.d.mts +5 -5
- package/dist/testing.d.ts +5 -5
- package/dist/testing.js +79 -79
- package/dist/testing.mjs +5 -5
- package/dist/utils.d.mts +4 -4
- package/dist/utils.d.ts +4 -4
- package/package.json +1 -1
- package/registry/booking-page.json +1 -1
- package/registry/chat-widget.json +1 -1
- package/registry/customer-input-fields.json +1 -1
- package/registry/date-slot-picker.json +1 -1
- package/registry/product-customizer.json +1 -1
- package/registry/rental-service-card.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkHKN3YG76_js = require('./chunk-HKN3YG76.js');
|
|
5
5
|
var chunkXREIZ56K_js = require('./chunk-XREIZ56K.js');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var chunkQLGZIBRO_js = require('./chunk-QLGZIBRO.js');
|
|
7
|
+
var chunkVEOAMBEX_js = require('./chunk-VEOAMBEX.js');
|
|
8
8
|
var chunkPTPOQVXS_js = require('./chunk-PTPOQVXS.js');
|
|
9
9
|
var chunkAETVRBKI_js = require('./chunk-AETVRBKI.js');
|
|
10
10
|
require('./chunk-OWW5GUSB.js');
|
|
@@ -747,6 +747,7 @@ function mapServerCart(serverCart, fallbackCurrency) {
|
|
|
747
747
|
scheduledStart: item.scheduled_start || void 0,
|
|
748
748
|
scheduledEnd: item.scheduled_end || void 0,
|
|
749
749
|
staffId: item.staff_id || void 0,
|
|
750
|
+
units: item.units || void 0,
|
|
750
751
|
lineType: item.line_type,
|
|
751
752
|
confirmationCode: item.confirmation_code || void 0,
|
|
752
753
|
serviceStatus: item.service_status || void 0,
|
|
@@ -805,7 +806,7 @@ async function syncFromServer(entry) {
|
|
|
805
806
|
return next;
|
|
806
807
|
}
|
|
807
808
|
function emitMutationError(entry, operation, opId, idempotencyKey, error) {
|
|
808
|
-
entry.client.events.emit(
|
|
809
|
+
entry.client.events.emit(chunkQLGZIBRO_js.MUTATION_ERROR, {
|
|
809
810
|
service: "cart",
|
|
810
811
|
operation,
|
|
811
812
|
opId,
|
|
@@ -845,6 +846,12 @@ function getOrCreateStore(params) {
|
|
|
845
846
|
syncTail: Promise.resolve(),
|
|
846
847
|
failedOpRemovers: /* @__PURE__ */ new Set()
|
|
847
848
|
};
|
|
849
|
+
client.events.on(chunkQLGZIBRO_js.SESSION_CLAIMED, () => {
|
|
850
|
+
if (entry.initialized) void syncFromServer(entry);
|
|
851
|
+
});
|
|
852
|
+
client.events.on(chunkQLGZIBRO_js.SESSION_CLEARED, () => {
|
|
853
|
+
if (entry.initialized) void syncFromServer(entry);
|
|
854
|
+
});
|
|
848
855
|
cartStores.set(storeKey, entry);
|
|
849
856
|
return entry;
|
|
850
857
|
}
|
|
@@ -903,7 +910,8 @@ async function performAddItem(entry, product, quantity, options) {
|
|
|
903
910
|
specialInstructions: normalizedOptions.specialInstructions,
|
|
904
911
|
scheduledStart: normalizedOptions.scheduledStart,
|
|
905
912
|
scheduledEnd: normalizedOptions.scheduledEnd,
|
|
906
|
-
staffId: normalizedOptions.staffId
|
|
913
|
+
staffId: normalizedOptions.staffId,
|
|
914
|
+
units: normalizedOptions.units
|
|
907
915
|
});
|
|
908
916
|
const idempotencyKey = `idem_${typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`}`;
|
|
909
917
|
const patch = { kind: "add_item", tempItem, lineKey };
|
|
@@ -925,6 +933,7 @@ async function performAddItem(entry, product, quantity, options) {
|
|
|
925
933
|
scheduled_end: normalizedOptions.scheduledEnd,
|
|
926
934
|
staff_id: normalizedOptions.staffId,
|
|
927
935
|
resource_id: normalizedOptions.resourceId,
|
|
936
|
+
units: normalizedOptions.units,
|
|
928
937
|
customer_inputs: normalizedOptions.customerInputs
|
|
929
938
|
},
|
|
930
939
|
{ idempotencyKey }
|
|
@@ -1136,7 +1145,7 @@ var DEFAULT_COUNTRY = "US";
|
|
|
1136
1145
|
function createDefaultClient() {
|
|
1137
1146
|
const processRef = globalThis.process;
|
|
1138
1147
|
const envPublicKey = processRef?.env?.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY || "";
|
|
1139
|
-
return
|
|
1148
|
+
return chunkQLGZIBRO_js.createCimplifyClient({ publicKey: envPublicKey });
|
|
1140
1149
|
}
|
|
1141
1150
|
function getStoredLocationId() {
|
|
1142
1151
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
@@ -1289,7 +1298,7 @@ function CimplifyProvider({
|
|
|
1289
1298
|
const apiCredentials = resolvedClient.getCredentialsMode() === "include" ? "use-credentials" : "anonymous";
|
|
1290
1299
|
preconnectOrigin(resolvedClient.getBaseUrl(), apiCredentials);
|
|
1291
1300
|
preconnectOrigin(resolvedClient.getLinkApiUrl(), apiCredentials);
|
|
1292
|
-
preconnectOrigin(
|
|
1301
|
+
preconnectOrigin(chunkHKN3YG76_js.DEFAULT_CDN_BASE_URL);
|
|
1293
1302
|
}
|
|
1294
1303
|
const setCurrentLocation = React14.useCallback(
|
|
1295
1304
|
(location) => {
|
|
@@ -3448,7 +3457,7 @@ function CimplifySignInButton({
|
|
|
3448
3457
|
const onClick = async () => {
|
|
3449
3458
|
if (busy || disabled || !signInOpts.clientId) return;
|
|
3450
3459
|
setBusy(true);
|
|
3451
|
-
await
|
|
3460
|
+
await chunkVEOAMBEX_js.startSignIn({
|
|
3452
3461
|
...signInOpts,
|
|
3453
3462
|
onSuccess: () => {
|
|
3454
3463
|
setBusy(false);
|
|
@@ -5478,14 +5487,24 @@ function useServices(options = {}) {
|
|
|
5478
5487
|
}
|
|
5479
5488
|
|
|
5480
5489
|
// src/react/hooks/use-available-slots.ts
|
|
5490
|
+
function narrowingUnits(units) {
|
|
5491
|
+
return units != null && units > 1 ? units : void 0;
|
|
5492
|
+
}
|
|
5481
5493
|
var slotsQuery = createCachedQuery({
|
|
5482
5494
|
name: "useAvailableSlots",
|
|
5483
|
-
key: (client, options) => cacheKey(
|
|
5495
|
+
key: (client, options) => cacheKey(
|
|
5496
|
+
client.getPublicKey(),
|
|
5497
|
+
options.serviceId,
|
|
5498
|
+
options.date,
|
|
5499
|
+
options.participantCount,
|
|
5500
|
+
narrowingUnits(options.units)
|
|
5501
|
+
),
|
|
5484
5502
|
fetch: async (client, options) => {
|
|
5485
5503
|
const result = await client.scheduling.getAvailableSlots({
|
|
5486
5504
|
service_id: options.serviceId,
|
|
5487
5505
|
date: options.date,
|
|
5488
|
-
participant_count: options.participantCount
|
|
5506
|
+
participant_count: options.participantCount,
|
|
5507
|
+
units: narrowingUnits(options.units)
|
|
5489
5508
|
});
|
|
5490
5509
|
if (!result.ok) throw result.error;
|
|
5491
5510
|
return result.value;
|
|
@@ -5502,6 +5521,9 @@ function useAvailableSlots(serviceId, date, options = {}) {
|
|
|
5502
5521
|
}
|
|
5503
5522
|
|
|
5504
5523
|
// src/react/hooks/use-service-availability.ts
|
|
5524
|
+
function narrowingUnits2(units) {
|
|
5525
|
+
return units != null && units > 1 ? units : void 0;
|
|
5526
|
+
}
|
|
5505
5527
|
var serviceAvailabilityQuery = createCachedQuery({
|
|
5506
5528
|
name: "useServiceAvailability",
|
|
5507
5529
|
key: (client, options) => cacheKey(
|
|
@@ -5509,7 +5531,8 @@ var serviceAvailabilityQuery = createCachedQuery({
|
|
|
5509
5531
|
options.serviceId,
|
|
5510
5532
|
options.startDate,
|
|
5511
5533
|
options.endDate,
|
|
5512
|
-
options.participantCount
|
|
5534
|
+
options.participantCount,
|
|
5535
|
+
narrowingUnits2(options.units)
|
|
5513
5536
|
),
|
|
5514
5537
|
fetch: async (client, options) => {
|
|
5515
5538
|
const result = await client.scheduling.getServiceAvailability({
|
|
@@ -5517,7 +5540,8 @@ var serviceAvailabilityQuery = createCachedQuery({
|
|
|
5517
5540
|
start_date: options.startDate,
|
|
5518
5541
|
end_date: options.endDate,
|
|
5519
5542
|
location_id: options.locationId,
|
|
5520
|
-
participant_count: options.participantCount
|
|
5543
|
+
participant_count: options.participantCount,
|
|
5544
|
+
units: narrowingUnits2(options.units)
|
|
5521
5545
|
});
|
|
5522
5546
|
if (!result.ok) throw result.error;
|
|
5523
5547
|
return result.value.availability;
|
|
@@ -5889,6 +5913,20 @@ var IDLE_TIMEOUT_MS = 6e4;
|
|
|
5889
5913
|
var WS_MAX_RECONNECT_ATTEMPTS = 10;
|
|
5890
5914
|
var WS_PATH = "/api/v1/support/conversation/ws";
|
|
5891
5915
|
var AWAIT_REPLY_TIMEOUT_MS = 3e4;
|
|
5916
|
+
function mergeMessages(prev, incoming) {
|
|
5917
|
+
const ids = new Set(prev.map((m) => m.id));
|
|
5918
|
+
const fresh = incoming.filter((m) => !ids.has(m.id));
|
|
5919
|
+
if (fresh.length === 0) return prev;
|
|
5920
|
+
const merged = [...prev, ...fresh].sort(
|
|
5921
|
+
(a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
|
|
5922
|
+
);
|
|
5923
|
+
const confirmed = new Set(
|
|
5924
|
+
merged.filter((m) => !m.id.startsWith("opt_") && m.client_id).map((m) => m.client_id)
|
|
5925
|
+
);
|
|
5926
|
+
return merged.filter(
|
|
5927
|
+
(m) => !(m.id.startsWith("opt_") && m.client_id && confirmed.has(m.client_id))
|
|
5928
|
+
);
|
|
5929
|
+
}
|
|
5892
5930
|
function useChat(options = {}) {
|
|
5893
5931
|
const context = useOptionalCimplifyClient();
|
|
5894
5932
|
const client = options.client ?? context?.client;
|
|
@@ -5901,6 +5939,9 @@ function useChat(options = {}) {
|
|
|
5901
5939
|
const [awaitingReply, setAwaitingReply] = React14.useState(false);
|
|
5902
5940
|
const [seenAt, setSeenAt] = React14.useState(null);
|
|
5903
5941
|
const [mayHaveOlder, setMayHaveOlder] = React14.useState(false);
|
|
5942
|
+
const [claimedAs, setClaimedAs] = React14.useState(
|
|
5943
|
+
() => client?.support.claimedCustomerName ?? null
|
|
5944
|
+
);
|
|
5904
5945
|
const pollRef = React14.useRef(null);
|
|
5905
5946
|
const lastActivityRef = React14.useRef(Date.now());
|
|
5906
5947
|
const openedRef = React14.useRef(false);
|
|
@@ -5912,6 +5953,7 @@ function useChat(options = {}) {
|
|
|
5912
5953
|
const aiEnabledRef = React14.useRef(false);
|
|
5913
5954
|
const humanRequestedRef = React14.useRef(false);
|
|
5914
5955
|
const awaitReplyTimerRef = React14.useRef(null);
|
|
5956
|
+
const claimUnsubRef = React14.useRef(null);
|
|
5915
5957
|
messagesRef.current = messages;
|
|
5916
5958
|
clientRef.current = client;
|
|
5917
5959
|
humanRequestedRef.current = humanRequested;
|
|
@@ -5937,18 +5979,22 @@ function useChat(options = {}) {
|
|
|
5937
5979
|
if (incoming.some((m) => m.sender_type === "bot" || m.sender_type === "agent")) {
|
|
5938
5980
|
stopAwaitingReply();
|
|
5939
5981
|
}
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
const fresh = incoming.filter((m) => !ids.has(m.id));
|
|
5943
|
-
return fresh.length > 0 ? [...prev, ...fresh] : prev;
|
|
5944
|
-
});
|
|
5982
|
+
if (incoming.length > 0) lastActivityRef.current = Date.now();
|
|
5983
|
+
setMessages((prev) => mergeMessages(prev, incoming));
|
|
5945
5984
|
},
|
|
5946
5985
|
[stopAwaitingReply]
|
|
5947
5986
|
);
|
|
5987
|
+
const lastConfirmedMessage = React14.useCallback(() => {
|
|
5988
|
+
const list = messagesRef.current;
|
|
5989
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
5990
|
+
if (!list[i].id.startsWith("opt_")) return list[i];
|
|
5991
|
+
}
|
|
5992
|
+
return void 0;
|
|
5993
|
+
}, []);
|
|
5948
5994
|
const fetchNewMessages = React14.useCallback(async () => {
|
|
5949
5995
|
const c = clientRef.current;
|
|
5950
5996
|
if (!c) return;
|
|
5951
|
-
const last =
|
|
5997
|
+
const last = lastConfirmedMessage();
|
|
5952
5998
|
const result = await c.support.getMessages({
|
|
5953
5999
|
after: last?.created_at,
|
|
5954
6000
|
limit: 50
|
|
@@ -5956,29 +6002,61 @@ function useChat(options = {}) {
|
|
|
5956
6002
|
if (result.ok && result.value.length > 0) {
|
|
5957
6003
|
appendMessages(result.value);
|
|
5958
6004
|
}
|
|
5959
|
-
}, [appendMessages]);
|
|
5960
|
-
const pollMessages = React14.useCallback(async () => {
|
|
5961
|
-
if (Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS) return;
|
|
5962
|
-
await fetchNewMessages();
|
|
5963
|
-
}, [fetchNewMessages]);
|
|
6005
|
+
}, [appendMessages, lastConfirmedMessage]);
|
|
5964
6006
|
const startPolling = React14.useCallback(() => {
|
|
5965
6007
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
5966
|
-
const
|
|
5967
|
-
|
|
5968
|
-
|
|
6008
|
+
const idle = () => Date.now() - lastActivityRef.current > IDLE_TIMEOUT_MS;
|
|
6009
|
+
let current = idle() ? pollIdleInterval : pollInterval;
|
|
6010
|
+
const tick = () => {
|
|
6011
|
+
void fetchNewMessages().then(() => {
|
|
6012
|
+
const desired = idle() ? pollIdleInterval : pollInterval;
|
|
6013
|
+
if (desired !== current && pollRef.current) {
|
|
6014
|
+
current = desired;
|
|
6015
|
+
clearInterval(pollRef.current);
|
|
6016
|
+
pollRef.current = setInterval(tick, current);
|
|
6017
|
+
}
|
|
6018
|
+
});
|
|
6019
|
+
};
|
|
6020
|
+
pollRef.current = setInterval(tick, current);
|
|
6021
|
+
}, [fetchNewMessages, pollInterval, pollIdleInterval]);
|
|
5969
6022
|
const stopPolling = React14.useCallback(() => {
|
|
5970
6023
|
if (pollRef.current) {
|
|
5971
6024
|
clearInterval(pollRef.current);
|
|
5972
6025
|
pollRef.current = null;
|
|
5973
6026
|
}
|
|
5974
6027
|
}, []);
|
|
6028
|
+
const resyncConversation = React14.useCallback(async () => {
|
|
6029
|
+
const c = clientRef.current;
|
|
6030
|
+
if (!c || !openedRef.current) return;
|
|
6031
|
+
const result = await c.support.openConversation();
|
|
6032
|
+
if (!result.ok) return;
|
|
6033
|
+
const snapshot = result.value.messages;
|
|
6034
|
+
setMessages((prev) => {
|
|
6035
|
+
const snapshotIds = new Set(snapshot.map((m) => m.id));
|
|
6036
|
+
const tail = snapshot.length > 0 ? new Date(snapshot[snapshot.length - 1].created_at).getTime() : 0;
|
|
6037
|
+
const extras = prev.filter(
|
|
6038
|
+
(m) => !snapshotIds.has(m.id) && (m.id.startsWith("opt_") || new Date(m.created_at).getTime() > tail)
|
|
6039
|
+
);
|
|
6040
|
+
return mergeMessages(snapshot, extras);
|
|
6041
|
+
});
|
|
6042
|
+
aiEnabledRef.current = result.value.conversation.ai_enabled;
|
|
6043
|
+
setHumanRequested(result.value.conversation.needs_human_review ?? false);
|
|
6044
|
+
setSeenAt(result.value.conversation.team_read_at ?? null);
|
|
6045
|
+
setMayHaveOlder(result.value.messages.length >= 50);
|
|
6046
|
+
}, []);
|
|
5975
6047
|
const connectWebSocket = React14.useCallback(() => {
|
|
5976
6048
|
const c = clientRef.current;
|
|
5977
6049
|
if (!c || typeof WebSocket === "undefined") {
|
|
5978
6050
|
startPolling();
|
|
5979
6051
|
return;
|
|
5980
6052
|
}
|
|
6053
|
+
if (wsReconnectTimerRef.current) {
|
|
6054
|
+
clearTimeout(wsReconnectTimerRef.current);
|
|
6055
|
+
wsReconnectTimerRef.current = null;
|
|
6056
|
+
}
|
|
5981
6057
|
if (wsRef.current) {
|
|
6058
|
+
wsRef.current.onclose = null;
|
|
6059
|
+
wsRef.current.onmessage = null;
|
|
5982
6060
|
wsRef.current.close();
|
|
5983
6061
|
wsRef.current = null;
|
|
5984
6062
|
}
|
|
@@ -6002,10 +6080,12 @@ function useChat(options = {}) {
|
|
|
6002
6080
|
else stopAwaitingReply();
|
|
6003
6081
|
} else if (envelope.type === "resync") {
|
|
6004
6082
|
const latest = envelope.latest_message_at;
|
|
6005
|
-
const last =
|
|
6083
|
+
const last = lastConfirmedMessage();
|
|
6006
6084
|
if (latest && (!last || new Date(last.created_at).getTime() < new Date(latest).getTime())) {
|
|
6007
6085
|
fetchNewMessages();
|
|
6008
6086
|
}
|
|
6087
|
+
} else if (envelope.type === "rekey") {
|
|
6088
|
+
void resyncConversation();
|
|
6009
6089
|
}
|
|
6010
6090
|
} catch {
|
|
6011
6091
|
}
|
|
@@ -6017,6 +6097,7 @@ function useChat(options = {}) {
|
|
|
6017
6097
|
if (wsReconnectAttemptRef.current < WS_MAX_RECONNECT_ATTEMPTS) {
|
|
6018
6098
|
const attempt = wsReconnectAttemptRef.current++;
|
|
6019
6099
|
const delay = Math.min(1e3 * Math.pow(2, attempt) + Math.random() * 500, 3e4);
|
|
6100
|
+
if (wsReconnectTimerRef.current) clearTimeout(wsReconnectTimerRef.current);
|
|
6020
6101
|
wsReconnectTimerRef.current = setTimeout(connectWebSocket, delay);
|
|
6021
6102
|
} else {
|
|
6022
6103
|
startPolling();
|
|
@@ -6025,14 +6106,91 @@ function useChat(options = {}) {
|
|
|
6025
6106
|
ws.onerror = () => {
|
|
6026
6107
|
};
|
|
6027
6108
|
wsRef.current = ws;
|
|
6028
|
-
}, [appendMessages, startPolling, stopPolling, fetchNewMessages]);
|
|
6109
|
+
}, [appendMessages, startPolling, stopPolling, fetchNewMessages, resyncConversation, lastConfirmedMessage]);
|
|
6110
|
+
const resetConversation = React14.useCallback(() => {
|
|
6111
|
+
stopPolling();
|
|
6112
|
+
if (wsReconnectTimerRef.current) {
|
|
6113
|
+
clearTimeout(wsReconnectTimerRef.current);
|
|
6114
|
+
wsReconnectTimerRef.current = null;
|
|
6115
|
+
}
|
|
6116
|
+
if (wsRef.current) {
|
|
6117
|
+
wsRef.current.onclose = null;
|
|
6118
|
+
wsRef.current.close();
|
|
6119
|
+
wsRef.current = null;
|
|
6120
|
+
}
|
|
6121
|
+
wsReconnectAttemptRef.current = 0;
|
|
6122
|
+
openedRef.current = false;
|
|
6123
|
+
stopAwaitingReply();
|
|
6124
|
+
setMessages([]);
|
|
6125
|
+
setConversationOpened(false);
|
|
6126
|
+
setHumanRequested(false);
|
|
6127
|
+
setSeenAt(null);
|
|
6128
|
+
setMayHaveOlder(false);
|
|
6129
|
+
setError(null);
|
|
6130
|
+
setClaimedAs(null);
|
|
6131
|
+
}, [stopPolling, stopAwaitingReply]);
|
|
6132
|
+
const hydrateConversation = React14.useCallback(
|
|
6133
|
+
(value) => {
|
|
6134
|
+
const c = clientRef.current;
|
|
6135
|
+
setMessages(value.messages);
|
|
6136
|
+
setConversationOpened(true);
|
|
6137
|
+
aiEnabledRef.current = value.conversation.ai_enabled;
|
|
6138
|
+
setHumanRequested(value.conversation.needs_human_review ?? false);
|
|
6139
|
+
setSeenAt(value.conversation.team_read_at ?? null);
|
|
6140
|
+
setMayHaveOlder(value.messages.length >= 50);
|
|
6141
|
+
setClaimedAs(c?.support.claimedCustomerName ?? null);
|
|
6142
|
+
connectWebSocket();
|
|
6143
|
+
},
|
|
6144
|
+
[connectWebSocket]
|
|
6145
|
+
);
|
|
6146
|
+
const openIfExisting = React14.useCallback(async () => {
|
|
6147
|
+
const c = clientRef.current;
|
|
6148
|
+
if (!c || openedRef.current) return;
|
|
6149
|
+
openedRef.current = true;
|
|
6150
|
+
setIsLoading(true);
|
|
6151
|
+
const result = await c.support.peekConversation();
|
|
6152
|
+
if (result.ok && result.value) {
|
|
6153
|
+
hydrateConversation(result.value);
|
|
6154
|
+
} else {
|
|
6155
|
+
openedRef.current = false;
|
|
6156
|
+
}
|
|
6157
|
+
setIsLoading(false);
|
|
6158
|
+
}, [hydrateConversation]);
|
|
6159
|
+
const watchSessionClaims = React14.useCallback(() => {
|
|
6160
|
+
const c = clientRef.current;
|
|
6161
|
+
if (!c || claimUnsubRef.current) return;
|
|
6162
|
+
const unsubClaimed = c.events.on(chunkQLGZIBRO_js.SESSION_CLAIMED, (event) => {
|
|
6163
|
+
setClaimedAs(event.customerName || c.support.claimedCustomerName || null);
|
|
6164
|
+
if (!openedRef.current) {
|
|
6165
|
+
void openIfExisting();
|
|
6166
|
+
return;
|
|
6167
|
+
}
|
|
6168
|
+
connectWebSocket();
|
|
6169
|
+
void resyncConversation();
|
|
6170
|
+
});
|
|
6171
|
+
const unsubCleared = c.events.on(chunkQLGZIBRO_js.SESSION_CLEARED, resetConversation);
|
|
6172
|
+
claimUnsubRef.current = () => {
|
|
6173
|
+
unsubClaimed();
|
|
6174
|
+
unsubCleared();
|
|
6175
|
+
};
|
|
6176
|
+
}, [connectWebSocket, resyncConversation, resetConversation, openIfExisting]);
|
|
6177
|
+
const signOut = React14.useCallback(async () => {
|
|
6178
|
+
const c = clientRef.current;
|
|
6179
|
+
if (!c) return false;
|
|
6180
|
+
const result = await c.link.logout();
|
|
6181
|
+
return result.ok;
|
|
6182
|
+
}, []);
|
|
6029
6183
|
React14.useEffect(() => {
|
|
6184
|
+
watchSessionClaims();
|
|
6030
6185
|
return () => {
|
|
6031
6186
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
6032
6187
|
if (wsReconnectTimerRef.current) clearTimeout(wsReconnectTimerRef.current);
|
|
6033
6188
|
if (awaitReplyTimerRef.current) clearTimeout(awaitReplyTimerRef.current);
|
|
6189
|
+
claimUnsubRef.current?.();
|
|
6190
|
+
claimUnsubRef.current = null;
|
|
6034
6191
|
if (wsRef.current) {
|
|
6035
6192
|
wsRef.current.onclose = null;
|
|
6193
|
+
wsRef.current.onmessage = null;
|
|
6036
6194
|
wsRef.current.close();
|
|
6037
6195
|
}
|
|
6038
6196
|
};
|
|
@@ -6044,19 +6202,13 @@ function useChat(options = {}) {
|
|
|
6044
6202
|
setError(null);
|
|
6045
6203
|
const result = await client.support.openConversation();
|
|
6046
6204
|
if (result.ok) {
|
|
6047
|
-
|
|
6048
|
-
setConversationOpened(true);
|
|
6049
|
-
aiEnabledRef.current = result.value.conversation.ai_enabled;
|
|
6050
|
-
setHumanRequested(result.value.conversation.needs_human_review ?? false);
|
|
6051
|
-
setSeenAt(result.value.conversation.team_read_at ?? null);
|
|
6052
|
-
setMayHaveOlder(result.value.messages.length >= 50);
|
|
6053
|
-
connectWebSocket();
|
|
6205
|
+
hydrateConversation(result.value);
|
|
6054
6206
|
} else {
|
|
6055
6207
|
openedRef.current = false;
|
|
6056
6208
|
setError(result.error);
|
|
6057
6209
|
}
|
|
6058
6210
|
setIsLoading(false);
|
|
6059
|
-
}, [client,
|
|
6211
|
+
}, [client, hydrateConversation]);
|
|
6060
6212
|
const send = React14.useCallback(
|
|
6061
6213
|
async (content, opts) => {
|
|
6062
6214
|
const attachments = opts?.attachments ?? [];
|
|
@@ -6068,7 +6220,8 @@ function useChat(options = {}) {
|
|
|
6068
6220
|
if (!openedRef.current) return false;
|
|
6069
6221
|
}
|
|
6070
6222
|
const replyTo = opts?.replyTo;
|
|
6071
|
-
const
|
|
6223
|
+
const clientId = chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
6224
|
+
const optimisticId = `opt_${clientId}`;
|
|
6072
6225
|
const optimistic = {
|
|
6073
6226
|
id: optimisticId,
|
|
6074
6227
|
sender_type: "customer",
|
|
@@ -6076,6 +6229,7 @@ function useChat(options = {}) {
|
|
|
6076
6229
|
content_type: attachments.length > 0 ? "image" : "text",
|
|
6077
6230
|
attachments,
|
|
6078
6231
|
metadata: {},
|
|
6232
|
+
client_id: clientId,
|
|
6079
6233
|
// Same shape the server echoes back, so the bubble doesn't reflow
|
|
6080
6234
|
// when the confirmed message replaces it.
|
|
6081
6235
|
reply_to: replyTo ? {
|
|
@@ -6088,6 +6242,7 @@ function useChat(options = {}) {
|
|
|
6088
6242
|
setMessages((prev) => [...prev, optimistic]);
|
|
6089
6243
|
setIsSending(true);
|
|
6090
6244
|
const result = await client.support.sendMessage(content.trim(), {
|
|
6245
|
+
idempotencyKey: clientId,
|
|
6091
6246
|
replyToMessageId: replyTo?.id,
|
|
6092
6247
|
attachments: attachments.length > 0 ? attachments : void 0
|
|
6093
6248
|
});
|
|
@@ -6158,11 +6313,7 @@ function useChat(options = {}) {
|
|
|
6158
6313
|
const older = result.value;
|
|
6159
6314
|
setMayHaveOlder(older.length >= 50);
|
|
6160
6315
|
if (older.length === 0) return false;
|
|
6161
|
-
setMessages((prev) =>
|
|
6162
|
-
const ids = new Set(prev.map((m) => m.id));
|
|
6163
|
-
const fresh = older.filter((m) => !ids.has(m.id));
|
|
6164
|
-
return fresh.length > 0 ? [...fresh, ...prev] : prev;
|
|
6165
|
-
});
|
|
6316
|
+
setMessages((prev) => mergeMessages(prev, older));
|
|
6166
6317
|
return true;
|
|
6167
6318
|
}, []);
|
|
6168
6319
|
const agentArrived = messages.some((m) => m.sender_type === "agent");
|
|
@@ -6176,11 +6327,14 @@ function useChat(options = {}) {
|
|
|
6176
6327
|
awaitingReply,
|
|
6177
6328
|
seenAt,
|
|
6178
6329
|
mayHaveOlder,
|
|
6330
|
+
claimedAs,
|
|
6331
|
+
signOut,
|
|
6179
6332
|
send,
|
|
6180
6333
|
startConversation,
|
|
6181
6334
|
react,
|
|
6182
6335
|
requestHuman,
|
|
6183
|
-
loadOlder
|
|
6336
|
+
loadOlder,
|
|
6337
|
+
openIfExisting
|
|
6184
6338
|
};
|
|
6185
6339
|
}
|
|
6186
6340
|
var ElementsContext = React14.createContext({
|
|
@@ -6255,15 +6409,15 @@ function AuthElement({
|
|
|
6255
6409
|
}, [onReady, onAuthenticated, onError]);
|
|
6256
6410
|
React14.useEffect(() => {
|
|
6257
6411
|
if (!elements || !containerRef.current) return;
|
|
6258
|
-
const element = elements.create(
|
|
6412
|
+
const element = elements.create(chunkVEOAMBEX_js.ELEMENT_TYPES.AUTH, { prefillEmail });
|
|
6259
6413
|
elementRef.current = element;
|
|
6260
|
-
element.on(
|
|
6414
|
+
element.on(chunkVEOAMBEX_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
|
|
6261
6415
|
element.on(
|
|
6262
|
-
|
|
6416
|
+
chunkVEOAMBEX_js.EVENT_TYPES.AUTHENTICATED,
|
|
6263
6417
|
(data) => onAuthenticatedRef.current?.(data)
|
|
6264
6418
|
);
|
|
6265
6419
|
element.on(
|
|
6266
|
-
|
|
6420
|
+
chunkVEOAMBEX_js.EVENT_TYPES.ERROR,
|
|
6267
6421
|
(data) => onErrorRef.current?.(data)
|
|
6268
6422
|
);
|
|
6269
6423
|
element.mount(containerRef.current);
|
|
@@ -6292,15 +6446,15 @@ function AddressElement({
|
|
|
6292
6446
|
}, [onReady, onChange, onError]);
|
|
6293
6447
|
React14.useEffect(() => {
|
|
6294
6448
|
if (!elements || !containerRef.current) return;
|
|
6295
|
-
const element = elements.create(
|
|
6449
|
+
const element = elements.create(chunkVEOAMBEX_js.ELEMENT_TYPES.ADDRESS, { mode });
|
|
6296
6450
|
elementRef.current = element;
|
|
6297
|
-
element.on(
|
|
6451
|
+
element.on(chunkVEOAMBEX_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
|
|
6298
6452
|
element.on(
|
|
6299
|
-
|
|
6453
|
+
chunkVEOAMBEX_js.EVENT_TYPES.CHANGE,
|
|
6300
6454
|
(data) => onChangeRef.current?.(data)
|
|
6301
6455
|
);
|
|
6302
6456
|
element.on(
|
|
6303
|
-
|
|
6457
|
+
chunkVEOAMBEX_js.EVENT_TYPES.ERROR,
|
|
6304
6458
|
(data) => onErrorRef.current?.(data)
|
|
6305
6459
|
);
|
|
6306
6460
|
element.mount(containerRef.current);
|
|
@@ -6330,15 +6484,15 @@ function PaymentElement({
|
|
|
6330
6484
|
}, [onReady, onChange, onError]);
|
|
6331
6485
|
React14.useEffect(() => {
|
|
6332
6486
|
if (!elements || !containerRef.current) return;
|
|
6333
|
-
const element = elements.create(
|
|
6487
|
+
const element = elements.create(chunkVEOAMBEX_js.ELEMENT_TYPES.PAYMENT, { amount, currency });
|
|
6334
6488
|
elementRef.current = element;
|
|
6335
|
-
element.on(
|
|
6489
|
+
element.on(chunkVEOAMBEX_js.EVENT_TYPES.READY, () => onReadyRef.current?.());
|
|
6336
6490
|
element.on(
|
|
6337
|
-
|
|
6491
|
+
chunkVEOAMBEX_js.EVENT_TYPES.CHANGE,
|
|
6338
6492
|
(data) => onChangeRef.current?.(data)
|
|
6339
6493
|
);
|
|
6340
6494
|
element.on(
|
|
6341
|
-
|
|
6495
|
+
chunkVEOAMBEX_js.EVENT_TYPES.ERROR,
|
|
6342
6496
|
(data) => onErrorRef.current?.(data)
|
|
6343
6497
|
);
|
|
6344
6498
|
element.mount(containerRef.current);
|
|
@@ -6629,7 +6783,7 @@ function VariantSelector({
|
|
|
6629
6783
|
{
|
|
6630
6784
|
"data-cimplify-variant-name": true,
|
|
6631
6785
|
className: cn("flex-1 min-w-0 text-sm", classNames?.name),
|
|
6632
|
-
children:
|
|
6786
|
+
children: chunkHKN3YG76_js.getVariantDisplayName(variant, productName)
|
|
6633
6787
|
}
|
|
6634
6788
|
),
|
|
6635
6789
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { "data-cimplify-variant-pricing": true, className: cn("text-sm text-muted-foreground", classNames?.pricing), children: [
|
|
@@ -7910,6 +8064,177 @@ function VolumePricing({
|
|
|
7910
8064
|
}
|
|
7911
8065
|
);
|
|
7912
8066
|
}
|
|
8067
|
+
function createPlacesSessionToken() {
|
|
8068
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
8069
|
+
return crypto.randomUUID();
|
|
8070
|
+
}
|
|
8071
|
+
return `places_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
8072
|
+
}
|
|
8073
|
+
var MIN_QUERY_LENGTH = 3;
|
|
8074
|
+
var DEBOUNCE_MS = 300;
|
|
8075
|
+
var BLUR_CLOSE_MS = 120;
|
|
8076
|
+
function AddressAutocomplete({
|
|
8077
|
+
value,
|
|
8078
|
+
onSelect,
|
|
8079
|
+
onDirty,
|
|
8080
|
+
placeholder,
|
|
8081
|
+
required,
|
|
8082
|
+
autoFocus,
|
|
8083
|
+
id,
|
|
8084
|
+
className,
|
|
8085
|
+
classNames
|
|
8086
|
+
}) {
|
|
8087
|
+
const clientContext = useOptionalCimplifyClient();
|
|
8088
|
+
const [inputText, setInputText] = React14__default.default.useState(value?.formatted_address ?? "");
|
|
8089
|
+
const [suggestions, setSuggestions] = React14__default.default.useState([]);
|
|
8090
|
+
const [isOpen, setIsOpen] = React14__default.default.useState(false);
|
|
8091
|
+
const [highlightedIndex, setHighlightedIndex] = React14__default.default.useState(-1);
|
|
8092
|
+
const debounceRef = React14__default.default.useRef(null);
|
|
8093
|
+
const seqRef = React14__default.default.useRef(0);
|
|
8094
|
+
const sessionTokenRef = React14__default.default.useRef(createPlacesSessionToken());
|
|
8095
|
+
const blurTimeoutRef = React14__default.default.useRef(null);
|
|
8096
|
+
React14__default.default.useEffect(() => {
|
|
8097
|
+
return () => {
|
|
8098
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8099
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8100
|
+
seqRef.current += 1;
|
|
8101
|
+
};
|
|
8102
|
+
}, []);
|
|
8103
|
+
const fetchSuggestions = React14__default.default.useCallback(
|
|
8104
|
+
async (query) => {
|
|
8105
|
+
const client = clientContext?.client;
|
|
8106
|
+
if (!client || query.length < MIN_QUERY_LENGTH) {
|
|
8107
|
+
setSuggestions([]);
|
|
8108
|
+
setIsOpen(false);
|
|
8109
|
+
return;
|
|
8110
|
+
}
|
|
8111
|
+
const seq = ++seqRef.current;
|
|
8112
|
+
const result = await client.places.autocomplete(query, sessionTokenRef.current);
|
|
8113
|
+
if (seqRef.current !== seq) return;
|
|
8114
|
+
if (result.ok && result.value.predictions.length > 0) {
|
|
8115
|
+
setSuggestions(result.value.predictions);
|
|
8116
|
+
setHighlightedIndex(0);
|
|
8117
|
+
setIsOpen(true);
|
|
8118
|
+
} else {
|
|
8119
|
+
setSuggestions([]);
|
|
8120
|
+
setIsOpen(false);
|
|
8121
|
+
}
|
|
8122
|
+
},
|
|
8123
|
+
[clientContext]
|
|
8124
|
+
);
|
|
8125
|
+
const handleInputChange = (nextValue) => {
|
|
8126
|
+
setInputText(nextValue);
|
|
8127
|
+
onDirty?.();
|
|
8128
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8129
|
+
debounceRef.current = setTimeout(() => void fetchSuggestions(nextValue.trim()), DEBOUNCE_MS);
|
|
8130
|
+
};
|
|
8131
|
+
const selectSuggestion = React14__default.default.useCallback(
|
|
8132
|
+
async (suggestion) => {
|
|
8133
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8134
|
+
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8135
|
+
const fallback = suggestion.description.split(",")[0]?.trim() || suggestion.description;
|
|
8136
|
+
setInputText(fallback);
|
|
8137
|
+
setSuggestions([]);
|
|
8138
|
+
setIsOpen(false);
|
|
8139
|
+
const client = clientContext?.client;
|
|
8140
|
+
if (!client) return;
|
|
8141
|
+
const result = await client.places.details(suggestion.place_id, sessionTokenRef.current);
|
|
8142
|
+
sessionTokenRef.current = createPlacesSessionToken();
|
|
8143
|
+
if (result.ok) {
|
|
8144
|
+
const d = result.value;
|
|
8145
|
+
const address = {
|
|
8146
|
+
formatted_address: d.formatted_address || fallback,
|
|
8147
|
+
street_address: d.street_address,
|
|
8148
|
+
apartment: d.apartment,
|
|
8149
|
+
city: d.city,
|
|
8150
|
+
region: d.region,
|
|
8151
|
+
postal_code: d.postal_code,
|
|
8152
|
+
country: d.country,
|
|
8153
|
+
latitude: d.latitude,
|
|
8154
|
+
longitude: d.longitude,
|
|
8155
|
+
place_id: d.place_id
|
|
8156
|
+
};
|
|
8157
|
+
setInputText(address.formatted_address);
|
|
8158
|
+
onSelect(address);
|
|
8159
|
+
}
|
|
8160
|
+
},
|
|
8161
|
+
[clientContext, onSelect]
|
|
8162
|
+
);
|
|
8163
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-address-autocomplete": true, className: cn("relative", className, classNames?.root), children: [
|
|
8164
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8165
|
+
"input",
|
|
8166
|
+
{
|
|
8167
|
+
id,
|
|
8168
|
+
type: "text",
|
|
8169
|
+
value: inputText,
|
|
8170
|
+
onChange: (e) => handleInputChange(e.target.value),
|
|
8171
|
+
onFocus: () => {
|
|
8172
|
+
if (suggestions.length > 0) setIsOpen(true);
|
|
8173
|
+
},
|
|
8174
|
+
onBlur: () => {
|
|
8175
|
+
blurTimeoutRef.current = setTimeout(() => setIsOpen(false), BLUR_CLOSE_MS);
|
|
8176
|
+
},
|
|
8177
|
+
onKeyDown: (e) => {
|
|
8178
|
+
if (e.key === "Escape") {
|
|
8179
|
+
setIsOpen(false);
|
|
8180
|
+
return;
|
|
8181
|
+
}
|
|
8182
|
+
if (!isOpen || suggestions.length === 0) return;
|
|
8183
|
+
if (e.key === "ArrowDown") {
|
|
8184
|
+
e.preventDefault();
|
|
8185
|
+
setHighlightedIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
|
|
8186
|
+
} else if (e.key === "ArrowUp") {
|
|
8187
|
+
e.preventDefault();
|
|
8188
|
+
setHighlightedIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
|
|
8189
|
+
} else if (e.key === "Enter" && highlightedIndex >= 0) {
|
|
8190
|
+
e.preventDefault();
|
|
8191
|
+
void selectSuggestion(suggestions[highlightedIndex]);
|
|
8192
|
+
}
|
|
8193
|
+
},
|
|
8194
|
+
placeholder: placeholder ?? "Search for an address...",
|
|
8195
|
+
required,
|
|
8196
|
+
autoFocus,
|
|
8197
|
+
autoComplete: "off",
|
|
8198
|
+
"aria-autocomplete": "list",
|
|
8199
|
+
"aria-expanded": isOpen && suggestions.length > 0,
|
|
8200
|
+
"data-cimplify-address-input": true,
|
|
8201
|
+
className: classNames?.input
|
|
8202
|
+
}
|
|
8203
|
+
),
|
|
8204
|
+
isOpen && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8205
|
+
"div",
|
|
8206
|
+
{
|
|
8207
|
+
role: "listbox",
|
|
8208
|
+
"data-cimplify-address-list": true,
|
|
8209
|
+
className: cn(
|
|
8210
|
+
"absolute left-0 right-0 top-full z-20 mt-1 overflow-hidden rounded-md border border-border bg-background shadow-lg",
|
|
8211
|
+
classNames?.list
|
|
8212
|
+
),
|
|
8213
|
+
children: suggestions.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8214
|
+
"button",
|
|
8215
|
+
{
|
|
8216
|
+
type: "button",
|
|
8217
|
+
role: "option",
|
|
8218
|
+
"aria-selected": i === highlightedIndex,
|
|
8219
|
+
onMouseDown: (e) => {
|
|
8220
|
+
e.preventDefault();
|
|
8221
|
+
void selectSuggestion(s);
|
|
8222
|
+
},
|
|
8223
|
+
"data-cimplify-address-option": true,
|
|
8224
|
+
className: cn(
|
|
8225
|
+
"block w-full px-3 py-2.5 text-left text-sm transition-colors",
|
|
8226
|
+
i === highlightedIndex ? "bg-muted text-foreground" : "text-foreground hover:bg-muted/70",
|
|
8227
|
+
classNames?.option,
|
|
8228
|
+
i === highlightedIndex && classNames?.activeOption
|
|
8229
|
+
),
|
|
8230
|
+
children: s.description
|
|
8231
|
+
},
|
|
8232
|
+
s.place_id
|
|
8233
|
+
))
|
|
8234
|
+
}
|
|
8235
|
+
)
|
|
8236
|
+
] });
|
|
8237
|
+
}
|
|
7913
8238
|
function parseValue(value) {
|
|
7914
8239
|
if (!value) return void 0;
|
|
7915
8240
|
const date = dateFns.parseISO(value);
|
|
@@ -8251,12 +8576,12 @@ function FieldInput({
|
|
|
8251
8576
|
classNames?.input
|
|
8252
8577
|
);
|
|
8253
8578
|
switch (field.field_type) {
|
|
8254
|
-
case
|
|
8255
|
-
case
|
|
8579
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Text:
|
|
8580
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Url:
|
|
8256
8581
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8257
8582
|
"input",
|
|
8258
8583
|
{
|
|
8259
|
-
type: field.field_type ===
|
|
8584
|
+
type: field.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.Url ? "url" : "text",
|
|
8260
8585
|
value: typeof value === "string" ? value : "",
|
|
8261
8586
|
onChange: (e) => onValueChange(e.target.value),
|
|
8262
8587
|
placeholder: field.placeholder,
|
|
@@ -8265,7 +8590,7 @@ function FieldInput({
|
|
|
8265
8590
|
className: inputClass
|
|
8266
8591
|
}
|
|
8267
8592
|
);
|
|
8268
|
-
case
|
|
8593
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Textarea:
|
|
8269
8594
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8270
8595
|
"textarea",
|
|
8271
8596
|
{
|
|
@@ -8278,7 +8603,7 @@ function FieldInput({
|
|
|
8278
8603
|
className: cn(inputClass, "resize-none", classNames?.textarea)
|
|
8279
8604
|
}
|
|
8280
8605
|
);
|
|
8281
|
-
case
|
|
8606
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Number:
|
|
8282
8607
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8283
8608
|
"input",
|
|
8284
8609
|
{
|
|
@@ -8292,7 +8617,7 @@ function FieldInput({
|
|
|
8292
8617
|
className: inputClass
|
|
8293
8618
|
}
|
|
8294
8619
|
);
|
|
8295
|
-
case
|
|
8620
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Select:
|
|
8296
8621
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8297
8622
|
"select",
|
|
8298
8623
|
{
|
|
@@ -8306,7 +8631,7 @@ function FieldInput({
|
|
|
8306
8631
|
]
|
|
8307
8632
|
}
|
|
8308
8633
|
);
|
|
8309
|
-
case
|
|
8634
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Radio:
|
|
8310
8635
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.radioGroup), children: (field.options || []).map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8311
8636
|
"label",
|
|
8312
8637
|
{
|
|
@@ -8331,7 +8656,7 @@ function FieldInput({
|
|
|
8331
8656
|
},
|
|
8332
8657
|
opt
|
|
8333
8658
|
)) });
|
|
8334
|
-
case
|
|
8659
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Checkbox:
|
|
8335
8660
|
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cn("flex items-center gap-2 text-sm cursor-pointer", classNames?.checkboxLabel), children: [
|
|
8336
8661
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8337
8662
|
"input",
|
|
@@ -8344,7 +8669,7 @@ function FieldInput({
|
|
|
8344
8669
|
),
|
|
8345
8670
|
field.placeholder || field.name
|
|
8346
8671
|
] });
|
|
8347
|
-
case
|
|
8672
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Color:
|
|
8348
8673
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8349
8674
|
"input",
|
|
8350
8675
|
{
|
|
@@ -8354,7 +8679,7 @@ function FieldInput({
|
|
|
8354
8679
|
className: cn("w-12 h-10 rounded-md border border-input cursor-pointer", classNames?.colorInput)
|
|
8355
8680
|
}
|
|
8356
8681
|
);
|
|
8357
|
-
case
|
|
8682
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Date:
|
|
8358
8683
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8359
8684
|
DatePicker,
|
|
8360
8685
|
{
|
|
@@ -8365,8 +8690,8 @@ function FieldInput({
|
|
|
8365
8690
|
"aria-label": field.name
|
|
8366
8691
|
}
|
|
8367
8692
|
);
|
|
8368
|
-
case
|
|
8369
|
-
case
|
|
8693
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.File:
|
|
8694
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Image:
|
|
8370
8695
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8371
8696
|
FileUploadInput,
|
|
8372
8697
|
{
|
|
@@ -8377,7 +8702,7 @@ function FieldInput({
|
|
|
8377
8702
|
classNames
|
|
8378
8703
|
}
|
|
8379
8704
|
);
|
|
8380
|
-
case
|
|
8705
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Email:
|
|
8381
8706
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8382
8707
|
"input",
|
|
8383
8708
|
{
|
|
@@ -8389,7 +8714,7 @@ function FieldInput({
|
|
|
8389
8714
|
className: inputClass
|
|
8390
8715
|
}
|
|
8391
8716
|
);
|
|
8392
|
-
case
|
|
8717
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.DateTime: {
|
|
8393
8718
|
const stringValue = typeof value === "string" ? value : "";
|
|
8394
8719
|
const [datePart, timePartRaw] = stringValue.includes("T") ? stringValue.split("T", 2) : [stringValue, ""];
|
|
8395
8720
|
const timePart = (timePartRaw ?? "").slice(0, 5);
|
|
@@ -8428,7 +8753,7 @@ function FieldInput({
|
|
|
8428
8753
|
)
|
|
8429
8754
|
] });
|
|
8430
8755
|
}
|
|
8431
|
-
case
|
|
8756
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Time:
|
|
8432
8757
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8433
8758
|
TimePicker,
|
|
8434
8759
|
{
|
|
@@ -8439,7 +8764,7 @@ function FieldInput({
|
|
|
8439
8764
|
"aria-label": field.name
|
|
8440
8765
|
}
|
|
8441
8766
|
);
|
|
8442
|
-
case
|
|
8767
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.MultiSelect:
|
|
8443
8768
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8444
8769
|
MultiSelectInput,
|
|
8445
8770
|
{
|
|
@@ -8449,7 +8774,7 @@ function FieldInput({
|
|
|
8449
8774
|
classNames
|
|
8450
8775
|
}
|
|
8451
8776
|
);
|
|
8452
|
-
case
|
|
8777
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.DateRange:
|
|
8453
8778
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8454
8779
|
DateRangeInput,
|
|
8455
8780
|
{
|
|
@@ -8459,7 +8784,7 @@ function FieldInput({
|
|
|
8459
8784
|
classNames
|
|
8460
8785
|
}
|
|
8461
8786
|
);
|
|
8462
|
-
case
|
|
8787
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Address:
|
|
8463
8788
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8464
8789
|
AddressInput,
|
|
8465
8790
|
{
|
|
@@ -8470,7 +8795,7 @@ function FieldInput({
|
|
|
8470
8795
|
inputClass
|
|
8471
8796
|
}
|
|
8472
8797
|
);
|
|
8473
|
-
case
|
|
8798
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Location:
|
|
8474
8799
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8475
8800
|
LocationInput,
|
|
8476
8801
|
{
|
|
@@ -8481,7 +8806,7 @@ function FieldInput({
|
|
|
8481
8806
|
inputClass
|
|
8482
8807
|
}
|
|
8483
8808
|
);
|
|
8484
|
-
case
|
|
8809
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Phone:
|
|
8485
8810
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8486
8811
|
PhoneInput,
|
|
8487
8812
|
{
|
|
@@ -8492,7 +8817,7 @@ function FieldInput({
|
|
|
8492
8817
|
inputClass
|
|
8493
8818
|
}
|
|
8494
8819
|
);
|
|
8495
|
-
case
|
|
8820
|
+
case chunkHKN3YG76_js.INPUT_FIELD_TYPE.Signature:
|
|
8496
8821
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8497
8822
|
SignatureInput,
|
|
8498
8823
|
{
|
|
@@ -8525,7 +8850,7 @@ function FileUploadInput({
|
|
|
8525
8850
|
const [isUploading, setIsUploading] = React14__default.default.useState(false);
|
|
8526
8851
|
const fileUrl = typeof value === "string" ? value : void 0;
|
|
8527
8852
|
const acceptedFormats = field.validation?.accepted_formats;
|
|
8528
|
-
const accept = acceptedFormats ? acceptedFormats.map((f) => `.${f}`).join(",") : field.field_type ===
|
|
8853
|
+
const accept = acceptedFormats ? acceptedFormats.map((f) => `.${f}`).join(",") : field.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.Image ? "image/*" : void 0;
|
|
8529
8854
|
const handleFile = async (file) => {
|
|
8530
8855
|
if (!onFileUpload) return;
|
|
8531
8856
|
if (field.validation?.max_size_mb) {
|
|
@@ -8543,7 +8868,7 @@ function FileUploadInput({
|
|
|
8543
8868
|
}
|
|
8544
8869
|
};
|
|
8545
8870
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", classNames?.fileInput), children: fileUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
8546
|
-
field.field_type ===
|
|
8871
|
+
field.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.Image && /* @__PURE__ */ jsxRuntime.jsx("img", { src: fileUrl, alt: "Uploaded", className: "w-16 h-16 object-cover rounded-md border border-border" }),
|
|
8547
8872
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground truncate", children: fileUrl.split("/").pop() }) }),
|
|
8548
8873
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8549
8874
|
"button",
|
|
@@ -8569,7 +8894,7 @@ function FileUploadInput({
|
|
|
8569
8894
|
}
|
|
8570
8895
|
),
|
|
8571
8896
|
isUploading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Uploading..." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8572
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: field.placeholder || `Upload ${field.field_type ===
|
|
8897
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: field.placeholder || `Upload ${field.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.Image ? "image" : "file"}` }),
|
|
8573
8898
|
acceptedFormats && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground/60 mt-1", children: [
|
|
8574
8899
|
acceptedFormats.map((f) => f.toUpperCase()).join(", "),
|
|
8575
8900
|
field.validation?.max_size_mb && ` \xB7 Max ${field.validation.max_size_mb}MB`
|
|
@@ -8670,129 +8995,18 @@ function AddressInput({
|
|
|
8670
8995
|
classNames,
|
|
8671
8996
|
inputClass
|
|
8672
8997
|
}) {
|
|
8673
|
-
const clientContext = useOptionalCimplifyClient();
|
|
8674
8998
|
const addr = value && typeof value === "object" ? value : null;
|
|
8675
|
-
|
|
8676
|
-
const [suggestions, setSuggestions] = React14__default.default.useState([]);
|
|
8677
|
-
const [isOpen, setIsOpen] = React14__default.default.useState(false);
|
|
8678
|
-
const [highlightedIndex, setHighlightedIndex] = React14__default.default.useState(-1);
|
|
8679
|
-
const debounceRef = React14__default.default.useRef(null);
|
|
8680
|
-
const seqRef = React14__default.default.useRef(0);
|
|
8681
|
-
const sessionTokenRef = React14__default.default.useRef(createSessionToken());
|
|
8682
|
-
const blurTimeoutRef = React14__default.default.useRef(null);
|
|
8683
|
-
React14__default.default.useEffect(() => {
|
|
8684
|
-
return () => {
|
|
8685
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8686
|
-
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8687
|
-
seqRef.current += 1;
|
|
8688
|
-
};
|
|
8689
|
-
}, []);
|
|
8690
|
-
const fetchSuggestions = React14__default.default.useCallback(async (query) => {
|
|
8691
|
-
const client = clientContext?.client;
|
|
8692
|
-
if (!client || query.length < 3) {
|
|
8693
|
-
setSuggestions([]);
|
|
8694
|
-
setIsOpen(false);
|
|
8695
|
-
return;
|
|
8696
|
-
}
|
|
8697
|
-
const seq = ++seqRef.current;
|
|
8698
|
-
const result = await client.places.autocomplete(query, sessionTokenRef.current);
|
|
8699
|
-
if (seqRef.current !== seq) return;
|
|
8700
|
-
if (result.ok && result.value.predictions.length > 0) {
|
|
8701
|
-
setSuggestions(result.value.predictions);
|
|
8702
|
-
setHighlightedIndex(0);
|
|
8703
|
-
setIsOpen(true);
|
|
8704
|
-
} else {
|
|
8705
|
-
setSuggestions([]);
|
|
8706
|
-
setIsOpen(false);
|
|
8707
|
-
}
|
|
8708
|
-
}, [clientContext]);
|
|
8709
|
-
const handleInputChange = (nextValue) => {
|
|
8710
|
-
setInputText(nextValue);
|
|
8711
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8712
|
-
debounceRef.current = setTimeout(() => void fetchSuggestions(nextValue.trim()), 300);
|
|
8713
|
-
};
|
|
8714
|
-
const selectSuggestion = React14__default.default.useCallback(async (suggestion) => {
|
|
8715
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8716
|
-
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8717
|
-
const fallback = suggestion.description.split(",")[0]?.trim() || suggestion.description;
|
|
8718
|
-
setInputText(fallback);
|
|
8719
|
-
setSuggestions([]);
|
|
8720
|
-
setIsOpen(false);
|
|
8721
|
-
const client = clientContext?.client;
|
|
8722
|
-
if (!client) return;
|
|
8723
|
-
const result = await client.places.details(suggestion.place_id, sessionTokenRef.current);
|
|
8724
|
-
sessionTokenRef.current = createSessionToken();
|
|
8725
|
-
if (result.ok) {
|
|
8726
|
-
const d = result.value;
|
|
8727
|
-
const addressValue = {
|
|
8728
|
-
formatted_address: d.formatted_address || fallback,
|
|
8729
|
-
street_address: d.street_address,
|
|
8730
|
-
apartment: d.apartment,
|
|
8731
|
-
city: d.city,
|
|
8732
|
-
region: d.region,
|
|
8733
|
-
postal_code: d.postal_code,
|
|
8734
|
-
country: d.country,
|
|
8735
|
-
latitude: d.latitude,
|
|
8736
|
-
longitude: d.longitude,
|
|
8737
|
-
place_id: d.place_id
|
|
8738
|
-
};
|
|
8739
|
-
setInputText(addressValue.formatted_address);
|
|
8740
|
-
onValueChange(addressValue);
|
|
8741
|
-
}
|
|
8742
|
-
}, [clientContext, onValueChange]);
|
|
8743
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2 relative", classNames?.addressInput), children: [
|
|
8999
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", classNames?.addressInput), children: [
|
|
8744
9000
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8745
|
-
|
|
9001
|
+
AddressAutocomplete,
|
|
8746
9002
|
{
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
onChange: (e) => handleInputChange(e.target.value),
|
|
8750
|
-
onFocus: () => {
|
|
8751
|
-
if (suggestions.length > 0) setIsOpen(true);
|
|
8752
|
-
},
|
|
8753
|
-
onBlur: () => {
|
|
8754
|
-
blurTimeoutRef.current = setTimeout(() => setIsOpen(false), 120);
|
|
8755
|
-
},
|
|
8756
|
-
onKeyDown: (e) => {
|
|
8757
|
-
if (e.key === "Escape") {
|
|
8758
|
-
setIsOpen(false);
|
|
8759
|
-
return;
|
|
8760
|
-
}
|
|
8761
|
-
if (!isOpen || suggestions.length === 0) return;
|
|
8762
|
-
if (e.key === "ArrowDown") {
|
|
8763
|
-
e.preventDefault();
|
|
8764
|
-
setHighlightedIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
|
|
8765
|
-
} else if (e.key === "ArrowUp") {
|
|
8766
|
-
e.preventDefault();
|
|
8767
|
-
setHighlightedIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
|
|
8768
|
-
} else if (e.key === "Enter" && highlightedIndex >= 0) {
|
|
8769
|
-
e.preventDefault();
|
|
8770
|
-
void selectSuggestion(suggestions[highlightedIndex]);
|
|
8771
|
-
}
|
|
8772
|
-
},
|
|
9003
|
+
value: addr,
|
|
9004
|
+
onSelect: onValueChange,
|
|
8773
9005
|
placeholder: field.placeholder || "Search for an address...",
|
|
8774
9006
|
required: field.is_required,
|
|
8775
|
-
|
|
8776
|
-
"aria-autocomplete": "list",
|
|
8777
|
-
"aria-expanded": isOpen && suggestions.length > 0,
|
|
8778
|
-
className: inputClass
|
|
9007
|
+
classNames: { input: inputClass }
|
|
8779
9008
|
}
|
|
8780
9009
|
),
|
|
8781
|
-
isOpen && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", className: "absolute left-0 right-0 top-full z-20 mt-1 overflow-hidden rounded-md border border-border bg-background shadow-lg", children: suggestions.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8782
|
-
"button",
|
|
8783
|
-
{
|
|
8784
|
-
type: "button",
|
|
8785
|
-
role: "option",
|
|
8786
|
-
"aria-selected": i === highlightedIndex,
|
|
8787
|
-
onMouseDown: (e) => {
|
|
8788
|
-
e.preventDefault();
|
|
8789
|
-
void selectSuggestion(s);
|
|
8790
|
-
},
|
|
8791
|
-
className: cn("block w-full px-3 py-2.5 text-left text-sm transition-colors", i === highlightedIndex ? "bg-muted text-foreground" : "text-foreground hover:bg-muted/70"),
|
|
8792
|
-
children: s.description
|
|
8793
|
-
},
|
|
8794
|
-
s.place_id
|
|
8795
|
-
)) }),
|
|
8796
9010
|
addr && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8797
9011
|
"input",
|
|
8798
9012
|
{
|
|
@@ -8812,121 +9026,22 @@ function LocationInput({
|
|
|
8812
9026
|
classNames,
|
|
8813
9027
|
inputClass
|
|
8814
9028
|
}) {
|
|
8815
|
-
const clientContext = useOptionalCimplifyClient();
|
|
8816
9029
|
const loc = value && typeof value === "object" ? value : null;
|
|
8817
|
-
|
|
8818
|
-
const [suggestions, setSuggestions] = React14__default.default.useState([]);
|
|
8819
|
-
const [isOpen, setIsOpen] = React14__default.default.useState(false);
|
|
8820
|
-
const [highlightedIndex, setHighlightedIndex] = React14__default.default.useState(-1);
|
|
8821
|
-
const debounceRef = React14__default.default.useRef(null);
|
|
8822
|
-
const seqRef = React14__default.default.useRef(0);
|
|
8823
|
-
const sessionTokenRef = React14__default.default.useRef(createSessionToken());
|
|
8824
|
-
const blurTimeoutRef = React14__default.default.useRef(null);
|
|
8825
|
-
React14__default.default.useEffect(() => {
|
|
8826
|
-
return () => {
|
|
8827
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8828
|
-
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8829
|
-
seqRef.current += 1;
|
|
8830
|
-
};
|
|
8831
|
-
}, []);
|
|
8832
|
-
const fetchSuggestions = React14__default.default.useCallback(async (query) => {
|
|
8833
|
-
const client = clientContext?.client;
|
|
8834
|
-
if (!client || query.length < 3) {
|
|
8835
|
-
setSuggestions([]);
|
|
8836
|
-
setIsOpen(false);
|
|
8837
|
-
return;
|
|
8838
|
-
}
|
|
8839
|
-
const seq = ++seqRef.current;
|
|
8840
|
-
const result = await client.places.autocomplete(query, sessionTokenRef.current);
|
|
8841
|
-
if (seqRef.current !== seq) return;
|
|
8842
|
-
if (result.ok && result.value.predictions.length > 0) {
|
|
8843
|
-
setSuggestions(result.value.predictions);
|
|
8844
|
-
setHighlightedIndex(0);
|
|
8845
|
-
setIsOpen(true);
|
|
8846
|
-
} else {
|
|
8847
|
-
setSuggestions([]);
|
|
8848
|
-
setIsOpen(false);
|
|
8849
|
-
}
|
|
8850
|
-
}, [clientContext]);
|
|
8851
|
-
const handleInputChange = (nextValue) => {
|
|
8852
|
-
setInputText(nextValue);
|
|
8853
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8854
|
-
debounceRef.current = setTimeout(() => void fetchSuggestions(nextValue.trim()), 300);
|
|
8855
|
-
};
|
|
8856
|
-
const selectSuggestion = React14__default.default.useCallback(async (suggestion) => {
|
|
8857
|
-
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
8858
|
-
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
|
|
8859
|
-
const label = suggestion.description.split(",")[0]?.trim() || suggestion.description;
|
|
8860
|
-
setInputText(label);
|
|
8861
|
-
setSuggestions([]);
|
|
8862
|
-
setIsOpen(false);
|
|
8863
|
-
const client = clientContext?.client;
|
|
8864
|
-
if (!client) return;
|
|
8865
|
-
const result = await client.places.details(suggestion.place_id, sessionTokenRef.current);
|
|
8866
|
-
sessionTokenRef.current = createSessionToken();
|
|
8867
|
-
if (result.ok) {
|
|
8868
|
-
const d = result.value;
|
|
8869
|
-
onValueChange({
|
|
8870
|
-
latitude: d.latitude,
|
|
8871
|
-
longitude: d.longitude,
|
|
8872
|
-
label: d.formatted_address || label
|
|
8873
|
-
});
|
|
8874
|
-
setInputText(d.formatted_address || label);
|
|
8875
|
-
}
|
|
8876
|
-
}, [clientContext, onValueChange]);
|
|
8877
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", classNames?.locationInput), children: [
|
|
9030
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(classNames?.locationInput), children: [
|
|
8878
9031
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8879
|
-
|
|
9032
|
+
AddressAutocomplete,
|
|
8880
9033
|
{
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
},
|
|
8887
|
-
onBlur: () => {
|
|
8888
|
-
blurTimeoutRef.current = setTimeout(() => setIsOpen(false), 120);
|
|
8889
|
-
},
|
|
8890
|
-
onKeyDown: (e) => {
|
|
8891
|
-
if (e.key === "Escape") {
|
|
8892
|
-
setIsOpen(false);
|
|
8893
|
-
return;
|
|
8894
|
-
}
|
|
8895
|
-
if (!isOpen || suggestions.length === 0) return;
|
|
8896
|
-
if (e.key === "ArrowDown") {
|
|
8897
|
-
e.preventDefault();
|
|
8898
|
-
setHighlightedIndex((i) => i < suggestions.length - 1 ? i + 1 : 0);
|
|
8899
|
-
} else if (e.key === "ArrowUp") {
|
|
8900
|
-
e.preventDefault();
|
|
8901
|
-
setHighlightedIndex((i) => i > 0 ? i - 1 : suggestions.length - 1);
|
|
8902
|
-
} else if (e.key === "Enter" && highlightedIndex >= 0) {
|
|
8903
|
-
e.preventDefault();
|
|
8904
|
-
void selectSuggestion(suggestions[highlightedIndex]);
|
|
8905
|
-
}
|
|
8906
|
-
},
|
|
9034
|
+
value: loc ? { formatted_address: loc.label ?? "", latitude: loc.latitude, longitude: loc.longitude } : null,
|
|
9035
|
+
onSelect: (address) => onValueChange({
|
|
9036
|
+
latitude: address.latitude,
|
|
9037
|
+
longitude: address.longitude,
|
|
9038
|
+
label: address.formatted_address
|
|
9039
|
+
}),
|
|
8907
9040
|
placeholder: field.placeholder || "Search for a location...",
|
|
8908
9041
|
required: field.is_required,
|
|
8909
|
-
|
|
8910
|
-
"aria-autocomplete": "list",
|
|
8911
|
-
"aria-expanded": isOpen && suggestions.length > 0,
|
|
8912
|
-
className: inputClass
|
|
9042
|
+
classNames: { input: inputClass }
|
|
8913
9043
|
}
|
|
8914
9044
|
),
|
|
8915
|
-
isOpen && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", className: "absolute left-0 right-0 top-full z-20 mt-1 overflow-hidden rounded-md border border-border bg-background shadow-lg", children: suggestions.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8916
|
-
"button",
|
|
8917
|
-
{
|
|
8918
|
-
type: "button",
|
|
8919
|
-
role: "option",
|
|
8920
|
-
"aria-selected": i === highlightedIndex,
|
|
8921
|
-
onMouseDown: (e) => {
|
|
8922
|
-
e.preventDefault();
|
|
8923
|
-
void selectSuggestion(s);
|
|
8924
|
-
},
|
|
8925
|
-
className: cn("block w-full px-3 py-2.5 text-left text-sm transition-colors", i === highlightedIndex ? "bg-muted text-foreground" : "text-foreground hover:bg-muted/70"),
|
|
8926
|
-
children: s.description
|
|
8927
|
-
},
|
|
8928
|
-
s.place_id
|
|
8929
|
-
)) }),
|
|
8930
9045
|
loc && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
8931
9046
|
loc.latitude.toFixed(4),
|
|
8932
9047
|
", ",
|
|
@@ -9057,12 +9172,6 @@ function SignatureInput({
|
|
|
9057
9172
|
!sig?.data_url && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: field.placeholder || "Draw your signature above" })
|
|
9058
9173
|
] });
|
|
9059
9174
|
}
|
|
9060
|
-
function createSessionToken() {
|
|
9061
|
-
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
9062
|
-
return crypto.randomUUID();
|
|
9063
|
-
}
|
|
9064
|
-
return `places_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
9065
|
-
}
|
|
9066
9175
|
function getTimeOfDay(timeStr) {
|
|
9067
9176
|
const hour = parseInt(timeStr.split("T").pop()?.split(":")[0] ?? timeStr.split(":")[0], 10);
|
|
9068
9177
|
if (hour < 12) return "morning";
|
|
@@ -9308,6 +9417,7 @@ function DateSlotPicker({
|
|
|
9308
9417
|
serviceId,
|
|
9309
9418
|
daysToShow = 7,
|
|
9310
9419
|
participantCount,
|
|
9420
|
+
units,
|
|
9311
9421
|
selectedSlot,
|
|
9312
9422
|
onSlotSelect,
|
|
9313
9423
|
availability: availabilityProp,
|
|
@@ -9342,6 +9452,7 @@ function DateSlotPicker({
|
|
|
9342
9452
|
dateRange.endDate,
|
|
9343
9453
|
{
|
|
9344
9454
|
participantCount,
|
|
9455
|
+
units,
|
|
9345
9456
|
enabled: availabilityProp === void 0
|
|
9346
9457
|
}
|
|
9347
9458
|
);
|
|
@@ -9499,6 +9610,7 @@ function ProductCustomizer({
|
|
|
9499
9610
|
const [specialInstructions, setSpecialInstructions] = React14.useState("");
|
|
9500
9611
|
const [selectedSlot, setSelectedSlot] = React14.useState(null);
|
|
9501
9612
|
const [selectedStaffId, setSelectedStaffId] = React14.useState(null);
|
|
9613
|
+
const [unitsCount, setUnitsCount] = React14.useState(1);
|
|
9502
9614
|
const cart = useCart();
|
|
9503
9615
|
const currency = chunkPTPOQVXS_js.getProductCurrency(product);
|
|
9504
9616
|
const productType = product.type || "product";
|
|
@@ -9506,6 +9618,7 @@ function ProductCustomizer({
|
|
|
9506
9618
|
const isBundle = productType === "bundle";
|
|
9507
9619
|
const isDigital = productType === "digital";
|
|
9508
9620
|
const isService = productType === "service";
|
|
9621
|
+
const offersUnits = isService && chunkHKN3YG76_js.isMultiDayService(product);
|
|
9509
9622
|
const isStandard = !isComposite && !isBundle;
|
|
9510
9623
|
const hasVariants = isStandard && product.variants && product.variants.length > 0;
|
|
9511
9624
|
const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;
|
|
@@ -9527,6 +9640,7 @@ function ProductCustomizer({
|
|
|
9527
9640
|
setSpecialInstructions("");
|
|
9528
9641
|
setSelectedSlot(null);
|
|
9529
9642
|
setSelectedStaffId(null);
|
|
9643
|
+
setUnitsCount(1);
|
|
9530
9644
|
}, [product.id, product.min_order_quantity]);
|
|
9531
9645
|
const slotStaff = React14.useMemo(
|
|
9532
9646
|
() => (selectedSlot?.available_staff ?? []).map((member) => ({
|
|
@@ -9616,7 +9730,17 @@ function ProductCustomizer({
|
|
|
9616
9730
|
if (perUnit === void 0 || perUnit === null) return void 0;
|
|
9617
9731
|
return chunkPTPOQVXS_js.parsePrice(perUnit) * quantity;
|
|
9618
9732
|
}, [quote, quantity]);
|
|
9619
|
-
const displayTotalPrice =
|
|
9733
|
+
const displayTotalPrice = React14.useMemo(() => {
|
|
9734
|
+
const total = quotedTotalPrice ?? localTotalPrice;
|
|
9735
|
+
const multiplier = chunkHKN3YG76_js.serviceBillingMultiplier(product, {
|
|
9736
|
+
quantity,
|
|
9737
|
+
units: unitsCount,
|
|
9738
|
+
scheduledStart: selectedSlot?.start_time,
|
|
9739
|
+
scheduledEnd: selectedSlot?.end_time
|
|
9740
|
+
});
|
|
9741
|
+
if (multiplier === null) return total;
|
|
9742
|
+
return total / Math.max(1, quantity) * multiplier;
|
|
9743
|
+
}, [quotedTotalPrice, localTotalPrice, product, quantity, unitsCount, selectedSlot]);
|
|
9620
9744
|
const handleVariantChange = React14.useCallback(
|
|
9621
9745
|
(variantId, variant) => {
|
|
9622
9746
|
setSelectedVariantId(variantId);
|
|
@@ -9648,7 +9772,8 @@ function ProductCustomizer({
|
|
|
9648
9772
|
scheduledStart: selectedSlot.start_time,
|
|
9649
9773
|
scheduledEnd: selectedSlot.end_time,
|
|
9650
9774
|
staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,
|
|
9651
|
-
resourceId: selectedSlot.available_resources?.[0]?.resource_id
|
|
9775
|
+
resourceId: selectedSlot.available_resources?.[0]?.resource_id,
|
|
9776
|
+
units: unitsCount > 1 ? unitsCount : void 0
|
|
9652
9777
|
} : {},
|
|
9653
9778
|
customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
|
|
9654
9779
|
specialInstructions: specialInstructions.trim() || void 0
|
|
@@ -9669,7 +9794,7 @@ function ProductCustomizer({
|
|
|
9669
9794
|
} finally {
|
|
9670
9795
|
setIsSubmitting(false);
|
|
9671
9796
|
}
|
|
9672
|
-
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);
|
|
9797
|
+
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, unitsCount, isSubmitting, onAddToCart, cart]);
|
|
9673
9798
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
|
|
9674
9799
|
isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9675
9800
|
CompositeSelector,
|
|
@@ -9706,9 +9831,17 @@ function ProductCustomizer({
|
|
|
9706
9831
|
setSelectedStaffId(null);
|
|
9707
9832
|
},
|
|
9708
9833
|
participantCount: quantity,
|
|
9709
|
-
|
|
9834
|
+
units: offersUnits ? unitsCount : void 0,
|
|
9835
|
+
currency,
|
|
9836
|
+
schedulingMode: product.scheduling_mode ?? (offersUnits ? "multi_day" : "intraday"),
|
|
9837
|
+
durationUnit: product.duration_unit,
|
|
9838
|
+
durationValue: product.duration_value
|
|
9710
9839
|
}
|
|
9711
9840
|
),
|
|
9841
|
+
offersUnits && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer-units": true, className: classNames?.units, children: [
|
|
9842
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Units" }),
|
|
9843
|
+
/* @__PURE__ */ jsxRuntime.jsx(QuantitySelector, { value: unitsCount, onChange: setUnitsCount, min: 1 })
|
|
9844
|
+
] }),
|
|
9712
9845
|
isService && slotStaff.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer-staff": true, children: [
|
|
9713
9846
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Choose your specialist" }),
|
|
9714
9847
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10313,7 +10446,7 @@ function CartLineItemRow({
|
|
|
10313
10446
|
const isOptimistic = item.isOptimistic === true;
|
|
10314
10447
|
const lineTotal = chunkPTPOQVXS_js.parsePrice(unitPrice) * item.quantity;
|
|
10315
10448
|
const imageUrl = item.product.image_url;
|
|
10316
|
-
const variantLabel2 = item.variant ?
|
|
10449
|
+
const variantLabel2 = item.variant ? chunkHKN3YG76_js.getVariantDisplayName(item.variant, item.product.name) : null;
|
|
10317
10450
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10318
10451
|
"div",
|
|
10319
10452
|
{
|
|
@@ -10413,7 +10546,7 @@ function CartLineItemRow({
|
|
|
10413
10546
|
input.field_name,
|
|
10414
10547
|
":"
|
|
10415
10548
|
] }),
|
|
10416
|
-
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-cimplify-cart-input-value": true, className: "text-foreground m-0 truncate", children: input.field_type ===
|
|
10549
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { "data-cimplify-cart-input-value": true, className: "text-foreground m-0 truncate", children: input.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.File || input.field_type === chunkHKN3YG76_js.INPUT_FIELD_TYPE.Image ? String(input.value).split("/").pop() || "Uploaded file" : String(input.value) })
|
|
10417
10550
|
] }, input.field_id)) }),
|
|
10418
10551
|
(item.lineType === "service" || item.product.type === "service") && item.scheduledStart && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-cart-service-info": true, className: cn("mt-1.5 flex items-center gap-1.5 text-xs text-muted-foreground", classNames?.serviceInfo), children: [
|
|
10419
10552
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
|
|
@@ -11298,7 +11431,7 @@ function FoodProductCard({
|
|
|
11298
11431
|
const tags = product.tags || [];
|
|
11299
11432
|
const isSignature = product.metadata?.is_signature === true;
|
|
11300
11433
|
const isNew = product.metadata?.is_new === true;
|
|
11301
|
-
const isComposite = product.type ===
|
|
11434
|
+
const isComposite = product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Composite;
|
|
11302
11435
|
return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
|
|
11303
11436
|
/* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "square", renderImage, children: [
|
|
11304
11437
|
isSignature && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 left-3 inline-flex items-center gap-1 text-[11px] font-semibold tracking-wide bg-amber-50 text-amber-700 border border-amber-200/60 px-2 py-0.5 rounded-md", children: [
|
|
@@ -11762,18 +11895,18 @@ function RentalServiceCard({
|
|
|
11762
11895
|
const currency = chunkPTPOQVXS_js.getProductCurrency(product);
|
|
11763
11896
|
const hasDeposit = product.deposit_type && product.deposit_type !== "none" && product.deposit_amount;
|
|
11764
11897
|
const unit = product.duration_unit ? UNIT_LABELS2[product.duration_unit] || product.duration_unit : "day";
|
|
11898
|
+
const priceUnit = product.price_basis === "per_person" ? "guest" : product.price_basis === "flat" ? "" : unit;
|
|
11765
11899
|
const status = product.inventory_status;
|
|
11766
11900
|
return /* @__PURE__ */ jsxRuntime.jsxs(CardShell, { product, renderLink, className, children: [
|
|
11767
11901
|
/* @__PURE__ */ jsxRuntime.jsxs(CardImage, { src: image, alt: product.name, aspectRatio: "16/9", renderImage, children: [
|
|
11768
11902
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/50 to-transparent pointer-events-none" }),
|
|
11769
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute bottom-3 left-3 inline-flex items-center text-[12px] font-semibold px-2.5 py-1 rounded-lg bg-background/92 backdrop-blur-xl text-foreground shadow-sm", children: [
|
|
11903
|
+
priceUnit && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute bottom-3 left-3 inline-flex items-center text-[12px] font-semibold px-2.5 py-1 rounded-lg bg-background/92 backdrop-blur-xl text-foreground shadow-sm", children: [
|
|
11770
11904
|
"Per ",
|
|
11771
|
-
|
|
11905
|
+
priceUnit
|
|
11772
11906
|
] }),
|
|
11773
11907
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute bottom-3 right-3 text-white font-bold text-lg drop-shadow-sm", children: [
|
|
11774
11908
|
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: product.default_price, currency }),
|
|
11775
|
-
|
|
11776
|
-
unit
|
|
11909
|
+
priceUnit && `/${priceUnit}`
|
|
11777
11910
|
] }),
|
|
11778
11911
|
product.general_service_capacity != null && product.general_service_capacity > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "absolute top-3 left-3 text-[11px] font-semibold tracking-wide bg-blue-50/90 text-blue-700 border border-blue-200/50 backdrop-blur px-2 py-0.5 rounded-md", children: [
|
|
11779
11912
|
"Up to ",
|
|
@@ -12065,36 +12198,36 @@ var BUILT_IN_CARDS = {
|
|
|
12065
12198
|
["composite" /* Composite */]: CompositeProductCard,
|
|
12066
12199
|
["subscription" /* Subscription */]: SubscriptionCard
|
|
12067
12200
|
};
|
|
12068
|
-
var RENTAL_UNITS = /* @__PURE__ */ new Set([
|
|
12069
|
-
var LEASE_UNITS = /* @__PURE__ */ new Set([
|
|
12201
|
+
var RENTAL_UNITS = /* @__PURE__ */ new Set([chunkHKN3YG76_js.DURATION_UNIT.Days, chunkHKN3YG76_js.DURATION_UNIT.Hours]);
|
|
12202
|
+
var LEASE_UNITS = /* @__PURE__ */ new Set([chunkHKN3YG76_js.DURATION_UNIT.Weeks, chunkHKN3YG76_js.DURATION_UNIT.Months, chunkHKN3YG76_js.DURATION_UNIT.Years]);
|
|
12070
12203
|
function resolveCardVariant(product) {
|
|
12071
|
-
if (product.type ===
|
|
12204
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Bundle) {
|
|
12072
12205
|
return "bundle" /* Bundle */;
|
|
12073
12206
|
}
|
|
12074
|
-
if (product.type ===
|
|
12207
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Composite) {
|
|
12075
12208
|
return "composite" /* Composite */;
|
|
12076
12209
|
}
|
|
12077
12210
|
if (product.quantity_pricing && product.quantity_pricing.length > 1) {
|
|
12078
12211
|
return "wholesale" /* Wholesale */;
|
|
12079
12212
|
}
|
|
12080
|
-
if (product.type ===
|
|
12213
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Digital) {
|
|
12081
12214
|
return "digital" /* Digital */;
|
|
12082
12215
|
}
|
|
12083
|
-
if (product.type ===
|
|
12216
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Service) {
|
|
12084
12217
|
switch (product.boundary_kind) {
|
|
12085
|
-
case
|
|
12218
|
+
case chunkHKN3YG76_js.BOUNDARY_KIND.CheckInOut:
|
|
12086
12219
|
return "accommodation" /* Accommodation */;
|
|
12087
|
-
case
|
|
12220
|
+
case chunkHKN3YG76_js.BOUNDARY_KIND.MoveInOut:
|
|
12088
12221
|
return "lease" /* Lease */;
|
|
12089
|
-
case
|
|
12090
|
-
case
|
|
12091
|
-
case
|
|
12222
|
+
case chunkHKN3YG76_js.BOUNDARY_KIND.PickupReturn:
|
|
12223
|
+
case chunkHKN3YG76_js.BOUNDARY_KIND.DeliveryCollection:
|
|
12224
|
+
case chunkHKN3YG76_js.BOUNDARY_KIND.AccessVacate:
|
|
12092
12225
|
return "rental" /* Rental */;
|
|
12093
12226
|
}
|
|
12094
12227
|
if (product.duration_unit && RENTAL_UNITS.has(product.duration_unit)) {
|
|
12095
12228
|
return "rental" /* Rental */;
|
|
12096
12229
|
}
|
|
12097
|
-
if (product.duration_unit ===
|
|
12230
|
+
if (product.duration_unit === chunkHKN3YG76_js.DURATION_UNIT.Nights) {
|
|
12098
12231
|
return "accommodation" /* Accommodation */;
|
|
12099
12232
|
}
|
|
12100
12233
|
if (product.duration_unit && LEASE_UNITS.has(product.duration_unit)) {
|
|
@@ -12105,10 +12238,10 @@ function resolveCardVariant(product) {
|
|
|
12105
12238
|
}
|
|
12106
12239
|
return "standard" /* Standard */;
|
|
12107
12240
|
}
|
|
12108
|
-
if (product.render_hint ===
|
|
12241
|
+
if (product.render_hint === chunkHKN3YG76_js.RENDER_HINT.Food) {
|
|
12109
12242
|
return "food" /* Food */;
|
|
12110
12243
|
}
|
|
12111
|
-
if (product.render_hint ===
|
|
12244
|
+
if (product.render_hint === chunkHKN3YG76_js.RENDER_HINT.Physical) {
|
|
12112
12245
|
return "retail" /* Retail */;
|
|
12113
12246
|
}
|
|
12114
12247
|
return "retail" /* Retail */;
|
|
@@ -12367,6 +12500,18 @@ function ProductGrid({
|
|
|
12367
12500
|
] });
|
|
12368
12501
|
}
|
|
12369
12502
|
|
|
12503
|
+
// src/react/utils/attachment.ts
|
|
12504
|
+
var IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp", ".svg"];
|
|
12505
|
+
function safeAttachmentUrl(url) {
|
|
12506
|
+
return /^https?:\/\//i.test(url) ? url : null;
|
|
12507
|
+
}
|
|
12508
|
+
function isImageAttachment(attachment) {
|
|
12509
|
+
if (attachment.mime_type?.startsWith("image/")) return true;
|
|
12510
|
+
if (attachment.mime_type) return false;
|
|
12511
|
+
const path = attachment.url.split("?")[0].split("#")[0].toLowerCase();
|
|
12512
|
+
return IMAGE_EXTENSIONS.some((extension) => path.endsWith(extension));
|
|
12513
|
+
}
|
|
12514
|
+
|
|
12370
12515
|
// src/react/utils/boundary-labels.ts
|
|
12371
12516
|
var PRESET_LABELS = {
|
|
12372
12517
|
check_in_out: { start: "Check-in", end: "Check-out" },
|
|
@@ -12376,14 +12521,14 @@ var PRESET_LABELS = {
|
|
|
12376
12521
|
move_in_out: { start: "Move-in", end: "Move-out" }
|
|
12377
12522
|
};
|
|
12378
12523
|
function defaultBoundaryKind(unit) {
|
|
12379
|
-
return unit ===
|
|
12524
|
+
return unit === chunkHKN3YG76_js.DURATION_UNIT.Nights ? chunkHKN3YG76_js.BOUNDARY_KIND.CheckInOut : chunkHKN3YG76_js.BOUNDARY_KIND.PickupReturn;
|
|
12380
12525
|
}
|
|
12381
12526
|
function resolveBoundaryKind(product) {
|
|
12382
12527
|
return product.boundary_kind ?? defaultBoundaryKind(product.duration_unit);
|
|
12383
12528
|
}
|
|
12384
12529
|
function getBoundaryLabels(product) {
|
|
12385
12530
|
const kind = resolveBoundaryKind(product);
|
|
12386
|
-
if (kind ===
|
|
12531
|
+
if (kind === chunkHKN3YG76_js.BOUNDARY_KIND.Custom) {
|
|
12387
12532
|
return {
|
|
12388
12533
|
start: product.boundary_start_label?.trim() || "Start",
|
|
12389
12534
|
end: product.boundary_end_label?.trim() || "End"
|
|
@@ -13548,6 +13693,7 @@ function BookingPage({
|
|
|
13548
13693
|
const [selectedDate, setSelectedDate] = React14.useState(null);
|
|
13549
13694
|
const [selectedStaffId, setSelectedStaffId] = React14.useState(null);
|
|
13550
13695
|
const [selectedResourceId, setSelectedResourceId] = React14.useState(null);
|
|
13696
|
+
const [bookingUnits, setBookingUnits] = React14.useState(1);
|
|
13551
13697
|
const [isSubmitting, setIsSubmitting] = React14.useState(false);
|
|
13552
13698
|
const [error, setError] = React14.useState(null);
|
|
13553
13699
|
const hasResourceStep = resources && resources.length > 0;
|
|
@@ -13641,7 +13787,8 @@ function BookingPage({
|
|
|
13641
13787
|
scheduledStart: selectedSlot.start_time,
|
|
13642
13788
|
scheduledEnd: selectedSlot.end_time,
|
|
13643
13789
|
staffId: selectedStaffId || void 0,
|
|
13644
|
-
resourceId: selectedResourceId || void 0
|
|
13790
|
+
resourceId: selectedResourceId || void 0,
|
|
13791
|
+
units: bookingUnits > 1 ? bookingUnits : void 0
|
|
13645
13792
|
});
|
|
13646
13793
|
onBooked?.(selectedSlot, selectedStaffId);
|
|
13647
13794
|
}
|
|
@@ -13737,6 +13884,31 @@ function BookingPage({
|
|
|
13737
13884
|
] }),
|
|
13738
13885
|
step === STEP.CONFIRM && selectedSlot && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-booking-step": "confirm", className: classNames?.step, children: [
|
|
13739
13886
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Confirm your booking" }),
|
|
13887
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-booking-units": true, className: classNames?.summaryRow, children: [
|
|
13888
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Units" }),
|
|
13889
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-booking-units-stepper": true, children: [
|
|
13890
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13891
|
+
"button",
|
|
13892
|
+
{
|
|
13893
|
+
type: "button",
|
|
13894
|
+
"data-cimplify-booking-units-decrement": true,
|
|
13895
|
+
onClick: () => setBookingUnits((current) => Math.max(1, current - 1)),
|
|
13896
|
+
disabled: bookingUnits <= 1,
|
|
13897
|
+
children: "\u2212"
|
|
13898
|
+
}
|
|
13899
|
+
),
|
|
13900
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-booking-units-value": true, children: bookingUnits }),
|
|
13901
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13902
|
+
"button",
|
|
13903
|
+
{
|
|
13904
|
+
type: "button",
|
|
13905
|
+
"data-cimplify-booking-units-increment": true,
|
|
13906
|
+
onClick: () => setBookingUnits((current) => current + 1),
|
|
13907
|
+
children: "+"
|
|
13908
|
+
}
|
|
13909
|
+
)
|
|
13910
|
+
] })
|
|
13911
|
+
] }),
|
|
13740
13912
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-booking-summary": true, className: classNames?.summary, children: [
|
|
13741
13913
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
|
|
13742
13914
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Service" }),
|
|
@@ -14444,7 +14616,7 @@ function DefaultProductLayout({
|
|
|
14444
14616
|
className
|
|
14445
14617
|
}) {
|
|
14446
14618
|
const [selectedVariantId, setSelectedVariantId] = React14__default.default.useState();
|
|
14447
|
-
const images =
|
|
14619
|
+
const images = chunkHKN3YG76_js.resolveGallery(product, selectedVariantId);
|
|
14448
14620
|
const currency = chunkPTPOQVXS_js.getProductCurrency(product);
|
|
14449
14621
|
const hasRange = product.quantity_pricing && product.quantity_pricing.length > 1 || product.variants && product.variants.length > 1;
|
|
14450
14622
|
const onSale = chunkPTPOQVXS_js.isOnSale(product);
|
|
@@ -15091,25 +15263,25 @@ function resolveTemplateKey(product) {
|
|
|
15091
15263
|
if (typeof metaTemplate === "string" && metaTemplate.trim()) {
|
|
15092
15264
|
return metaTemplate.trim();
|
|
15093
15265
|
}
|
|
15094
|
-
if (product.type ===
|
|
15266
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Bundle) {
|
|
15095
15267
|
return "bundle" /* Bundle */;
|
|
15096
15268
|
}
|
|
15097
|
-
if (product.type ===
|
|
15269
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Composite) {
|
|
15098
15270
|
return "composite" /* Composite */;
|
|
15099
15271
|
}
|
|
15100
15272
|
if (product.quantity_pricing && product.quantity_pricing.length > 1) {
|
|
15101
15273
|
return "wholesale" /* Wholesale */;
|
|
15102
15274
|
}
|
|
15103
|
-
if (product.type ===
|
|
15275
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Service) {
|
|
15104
15276
|
return "service" /* Service */;
|
|
15105
15277
|
}
|
|
15106
|
-
if (product.type ===
|
|
15278
|
+
if (product.type === chunkHKN3YG76_js.PRODUCT_TYPE.Digital) {
|
|
15107
15279
|
return "digital" /* Digital */;
|
|
15108
15280
|
}
|
|
15109
|
-
if (product.render_hint ===
|
|
15281
|
+
if (product.render_hint === chunkHKN3YG76_js.RENDER_HINT.Food) {
|
|
15110
15282
|
return "food" /* Food */;
|
|
15111
15283
|
}
|
|
15112
|
-
if (product.render_hint ===
|
|
15284
|
+
if (product.render_hint === chunkHKN3YG76_js.RENDER_HINT.Physical) {
|
|
15113
15285
|
return "physical" /* Physical */;
|
|
15114
15286
|
}
|
|
15115
15287
|
return "default" /* Default */;
|
|
@@ -16979,6 +17151,7 @@ function partitionMessages(messages) {
|
|
|
16979
17151
|
}
|
|
16980
17152
|
return { bubbles, reactionsByTarget };
|
|
16981
17153
|
}
|
|
17154
|
+
var MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
16982
17155
|
function ChatWidget({
|
|
16983
17156
|
client: clientProp,
|
|
16984
17157
|
businessName = "Support",
|
|
@@ -16995,7 +17168,8 @@ function ChatWidget({
|
|
|
16995
17168
|
const context = useOptionalCimplifyClient();
|
|
16996
17169
|
const client = clientProp ?? context?.client;
|
|
16997
17170
|
const [open, setOpen] = React14.useState(defaultOpen);
|
|
16998
|
-
const [
|
|
17171
|
+
const [readAt, setReadAt] = React14.useState(null);
|
|
17172
|
+
const [attachError, setAttachError] = React14.useState(null);
|
|
16999
17173
|
const {
|
|
17000
17174
|
messages,
|
|
17001
17175
|
isLoading,
|
|
@@ -17004,16 +17178,31 @@ function ChatWidget({
|
|
|
17004
17178
|
seenAt,
|
|
17005
17179
|
error,
|
|
17006
17180
|
isActive,
|
|
17181
|
+
claimedAs,
|
|
17182
|
+
signOut,
|
|
17007
17183
|
send,
|
|
17008
17184
|
react,
|
|
17009
|
-
startConversation
|
|
17185
|
+
startConversation,
|
|
17186
|
+
openIfExisting
|
|
17010
17187
|
} = useChat({ client, pollInterval });
|
|
17011
17188
|
const showTyping = isSending || awaitingReply;
|
|
17012
17189
|
const attachPhoto = React14.useCallback(
|
|
17013
17190
|
async (file) => {
|
|
17014
|
-
if (!client
|
|
17191
|
+
if (!client) return;
|
|
17192
|
+
setAttachError(null);
|
|
17193
|
+
if (!file.type.startsWith("image/")) {
|
|
17194
|
+
setAttachError(new chunkAETVRBKI_js.CimplifyError("invalid_attachment", "Only photos can be attached."));
|
|
17195
|
+
return;
|
|
17196
|
+
}
|
|
17197
|
+
if (file.size > MAX_ATTACHMENT_BYTES) {
|
|
17198
|
+
setAttachError(new chunkAETVRBKI_js.CimplifyError("attachment_too_large", "Photos must be under 5MB."));
|
|
17199
|
+
return;
|
|
17200
|
+
}
|
|
17015
17201
|
const uploaded = await client.uploads.upload(file);
|
|
17016
|
-
if (!uploaded.ok)
|
|
17202
|
+
if (!uploaded.ok) {
|
|
17203
|
+
setAttachError(uploaded.error);
|
|
17204
|
+
return;
|
|
17205
|
+
}
|
|
17017
17206
|
const attachment = {
|
|
17018
17207
|
upload_id: uploaded.value.id,
|
|
17019
17208
|
url: uploaded.value.url,
|
|
@@ -17025,22 +17214,28 @@ function ChatWidget({
|
|
|
17025
17214
|
},
|
|
17026
17215
|
[client, send]
|
|
17027
17216
|
);
|
|
17028
|
-
const
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17217
|
+
const handleSend = React14.useCallback(
|
|
17218
|
+
(content) => {
|
|
17219
|
+
setAttachError(null);
|
|
17220
|
+
return send(content);
|
|
17221
|
+
},
|
|
17222
|
+
[send]
|
|
17223
|
+
);
|
|
17224
|
+
const unread = open ? 0 : messages.filter(
|
|
17225
|
+
(m) => m.sender_type !== "customer" && (!readAt || m.created_at > readAt)
|
|
17226
|
+
).length;
|
|
17227
|
+
React14.useState(() => {
|
|
17228
|
+
if (defaultOpen) void openIfExisting();
|
|
17229
|
+
});
|
|
17039
17230
|
const handleOpen = React14.useCallback(() => {
|
|
17040
17231
|
setOpen(true);
|
|
17041
|
-
|
|
17042
|
-
}, []);
|
|
17043
|
-
const handleClose = React14.useCallback(() =>
|
|
17232
|
+
void openIfExisting();
|
|
17233
|
+
}, [openIfExisting]);
|
|
17234
|
+
const handleClose = React14.useCallback(() => {
|
|
17235
|
+
const newest = messages[messages.length - 1];
|
|
17236
|
+
setReadAt(newest?.created_at ?? null);
|
|
17237
|
+
setOpen(false);
|
|
17238
|
+
}, [messages]);
|
|
17044
17239
|
const isLeft = position === "bottom-left";
|
|
17045
17240
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17046
17241
|
"div",
|
|
@@ -17073,11 +17268,13 @@ function ChatWidget({
|
|
|
17073
17268
|
isSending,
|
|
17074
17269
|
isTyping: showTyping,
|
|
17075
17270
|
seenAt,
|
|
17076
|
-
error,
|
|
17271
|
+
error: error ?? attachError,
|
|
17077
17272
|
isActive,
|
|
17078
17273
|
isLeft,
|
|
17274
|
+
claimedAs,
|
|
17275
|
+
onSignOut: () => void signOut(),
|
|
17079
17276
|
onClose: handleClose,
|
|
17080
|
-
onSend:
|
|
17277
|
+
onSend: handleSend,
|
|
17081
17278
|
onReact: react,
|
|
17082
17279
|
onAttach: attachPhoto,
|
|
17083
17280
|
onStartConversation: startConversation,
|
|
@@ -17137,6 +17334,8 @@ function Panel({
|
|
|
17137
17334
|
error,
|
|
17138
17335
|
isActive,
|
|
17139
17336
|
isLeft,
|
|
17337
|
+
claimedAs,
|
|
17338
|
+
onSignOut,
|
|
17140
17339
|
onClose,
|
|
17141
17340
|
onSend,
|
|
17142
17341
|
onReact,
|
|
@@ -17160,6 +17359,8 @@ function Panel({
|
|
|
17160
17359
|
Header,
|
|
17161
17360
|
{
|
|
17162
17361
|
businessName,
|
|
17362
|
+
claimedAs,
|
|
17363
|
+
onSignOut,
|
|
17163
17364
|
onClose,
|
|
17164
17365
|
className: classNames?.header
|
|
17165
17366
|
}
|
|
@@ -17184,7 +17385,7 @@ function Panel({
|
|
|
17184
17385
|
className: classNames?.messages
|
|
17185
17386
|
}
|
|
17186
17387
|
),
|
|
17187
|
-
error != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-red-200 bg-red-50 px-4 py-2 text-xs text-red-600", children: "Something went wrong. Please try again." }),
|
|
17388
|
+
error != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-red-200 bg-red-50 px-4 py-2 text-xs text-red-600", children: error.userMessage || "Something went wrong. Please try again." }),
|
|
17188
17389
|
(isActive || isLoading) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17189
17390
|
ChatInput,
|
|
17190
17391
|
{
|
|
@@ -17206,6 +17407,8 @@ function Panel({
|
|
|
17206
17407
|
}
|
|
17207
17408
|
function Header({
|
|
17208
17409
|
businessName,
|
|
17410
|
+
claimedAs,
|
|
17411
|
+
onSignOut,
|
|
17209
17412
|
onClose,
|
|
17210
17413
|
className
|
|
17211
17414
|
}) {
|
|
@@ -17220,7 +17423,22 @@ function Header({
|
|
|
17220
17423
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-[10px] bg-white/15", children: /* @__PURE__ */ jsxRuntime.jsx(ChatIcon, { className: "h-5 w-5" }) }),
|
|
17221
17424
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
17222
17425
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-[15px] font-semibold leading-tight", children: businessName }),
|
|
17223
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1
|
|
17426
|
+
claimedAs ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 truncate text-xs text-white/60", children: [
|
|
17427
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate", children: [
|
|
17428
|
+
"Chatting as ",
|
|
17429
|
+
claimedAs
|
|
17430
|
+
] }),
|
|
17431
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
17432
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17433
|
+
"button",
|
|
17434
|
+
{
|
|
17435
|
+
type: "button",
|
|
17436
|
+
onClick: onSignOut,
|
|
17437
|
+
className: "flex-shrink-0 underline underline-offset-2 hover:text-white",
|
|
17438
|
+
children: "Not you?"
|
|
17439
|
+
}
|
|
17440
|
+
)
|
|
17441
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs text-white/60", children: [
|
|
17224
17442
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-[7px] w-[7px] flex-shrink-0 rounded-full bg-emerald-400" }),
|
|
17225
17443
|
"Online"
|
|
17226
17444
|
] })
|
|
@@ -17304,10 +17522,6 @@ function MessageList({
|
|
|
17304
17522
|
onReact,
|
|
17305
17523
|
className
|
|
17306
17524
|
}) {
|
|
17307
|
-
const bottomRef = React14.useRef(null);
|
|
17308
|
-
React14.useEffect(() => {
|
|
17309
|
-
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
17310
|
-
}, [messages.length, isSending]);
|
|
17311
17525
|
const { bubbles, reactionsByTarget } = partitionMessages(messages);
|
|
17312
17526
|
const seenMessageId = lastSeenCustomerMessageId(bubbles, seenAt);
|
|
17313
17527
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -17381,11 +17595,13 @@ function MessageList({
|
|
|
17381
17595
|
]
|
|
17382
17596
|
}
|
|
17383
17597
|
),
|
|
17384
|
-
msg.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap gap-1.5", msg.content && "mb-1.5"), children: msg.attachments.map(
|
|
17385
|
-
|
|
17598
|
+
msg.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap gap-1.5", msg.content && "mb-1.5"), children: msg.attachments.map((attachment, index) => {
|
|
17599
|
+
const url = safeAttachmentUrl(attachment.url);
|
|
17600
|
+
if (!url) return null;
|
|
17601
|
+
return attachment.mime_type?.startsWith("image/") ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17386
17602
|
"img",
|
|
17387
17603
|
{
|
|
17388
|
-
src:
|
|
17604
|
+
src: url,
|
|
17389
17605
|
alt: attachment.filename ?? "Photo",
|
|
17390
17606
|
loading: "lazy",
|
|
17391
17607
|
className: "max-h-48 max-w-full rounded-lg object-cover"
|
|
@@ -17393,15 +17609,15 @@ function MessageList({
|
|
|
17393
17609
|
) }, index) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17394
17610
|
"a",
|
|
17395
17611
|
{
|
|
17396
|
-
href:
|
|
17612
|
+
href: url,
|
|
17397
17613
|
target: "_blank",
|
|
17398
17614
|
rel: "noreferrer",
|
|
17399
17615
|
className: "truncate text-xs underline",
|
|
17400
17616
|
children: attachment.filename ?? "Attachment"
|
|
17401
17617
|
},
|
|
17402
17618
|
index
|
|
17403
|
-
)
|
|
17404
|
-
) }),
|
|
17619
|
+
);
|
|
17620
|
+
}) }),
|
|
17405
17621
|
isCustomer ? msg.content && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap", children: msg.content }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17406
17622
|
ChatMarkdown,
|
|
17407
17623
|
{
|
|
@@ -17427,7 +17643,15 @@ function MessageList({
|
|
|
17427
17643
|
] }, msg.id);
|
|
17428
17644
|
}),
|
|
17429
17645
|
isSending && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mr-auto mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(TypingDots, {}) }),
|
|
17430
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17646
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17647
|
+
"div",
|
|
17648
|
+
{
|
|
17649
|
+
ref: (node) => {
|
|
17650
|
+
node?.scrollIntoView({ behavior: "smooth" });
|
|
17651
|
+
}
|
|
17652
|
+
},
|
|
17653
|
+
`${messages.length}:${isSending}`
|
|
17654
|
+
)
|
|
17431
17655
|
]
|
|
17432
17656
|
}
|
|
17433
17657
|
);
|
|
@@ -19476,7 +19700,7 @@ async function genUIFingerprint(manifest) {
|
|
|
19476
19700
|
|
|
19477
19701
|
Object.defineProperty(exports, "getVariantDisplayName", {
|
|
19478
19702
|
enumerable: true,
|
|
19479
|
-
get: function () { return
|
|
19703
|
+
get: function () { return chunkHKN3YG76_js.getVariantDisplayName; }
|
|
19480
19704
|
});
|
|
19481
19705
|
Object.defineProperty(exports, "messagePreview", {
|
|
19482
19706
|
enumerable: true,
|
|
@@ -19505,6 +19729,7 @@ exports.AccountSubscriptionsPage = AccountSubscriptionsPage;
|
|
|
19505
19729
|
exports.Ad = Ad;
|
|
19506
19730
|
exports.AdProvider = AdProvider;
|
|
19507
19731
|
exports.AddOnSelector = AddOnSelector;
|
|
19732
|
+
exports.AddressAutocomplete = AddressAutocomplete;
|
|
19508
19733
|
exports.AddressElement = AddressElement;
|
|
19509
19734
|
exports.AuthElement = AuthElement;
|
|
19510
19735
|
exports.AvailabilityBadge = AvailabilityBadge;
|
|
@@ -19668,12 +19893,14 @@ exports.WholesaleProductLayout = WholesaleProductLayout;
|
|
|
19668
19893
|
exports.WishlistButton = WishlistButton;
|
|
19669
19894
|
exports.clearOrdersCache = clearOrdersCache;
|
|
19670
19895
|
exports.cn = cn;
|
|
19896
|
+
exports.createPlacesSessionToken = createPlacesSessionToken;
|
|
19671
19897
|
exports.defaultBoundaryKind = defaultBoundaryKind;
|
|
19672
19898
|
exports.genUICatalog = genUICatalog;
|
|
19673
19899
|
exports.genUIFingerprint = genUIFingerprint;
|
|
19674
19900
|
exports.genUIManifest = genUIManifest;
|
|
19675
19901
|
exports.genUIManifestJson = genUIManifestJson;
|
|
19676
19902
|
exports.getBoundaryLabels = getBoundaryLabels;
|
|
19903
|
+
exports.isImageAttachment = isImageAttachment;
|
|
19677
19904
|
exports.isTerminalOrderStatus = isTerminalOrderStatus;
|
|
19678
19905
|
exports.parseGenUIProgram = parse;
|
|
19679
19906
|
exports.partitionMessages = partitionMessages;
|
|
@@ -19681,6 +19908,7 @@ exports.prefetchProduct = prefetchProduct;
|
|
|
19681
19908
|
exports.prefetchProducts = prefetchProducts;
|
|
19682
19909
|
exports.resolveBoundaryKind = resolveBoundaryKind;
|
|
19683
19910
|
exports.roomToResource = roomToResource;
|
|
19911
|
+
exports.safeAttachmentUrl = safeAttachmentUrl;
|
|
19684
19912
|
exports.sanitizeRichTextHtml = sanitizeRichTextHtml;
|
|
19685
19913
|
exports.stripHtmlToText = stripHtmlToText;
|
|
19686
19914
|
exports.toAccountLineItem = toAccountLineItem;
|