@aranova/tracking-react 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/{bookings-B50X7GSG.d.ts → bookings-Bx7totlS.d.ts} +43 -1
- package/dist/{bookings-n8UUzrak.d.mts → bookings-DtcwdM_I.d.mts} +43 -1
- package/dist/client.d.mts +17 -3
- package/dist/client.d.ts +17 -3
- package/dist/client.js +46 -5
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +46 -5
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{ingest-typed-vP-DqpxO.d.ts → ingest-typed-B-BgEZdW.d.ts} +3 -1
- package/dist/{ingest-typed-ABH28Ips.d.mts → ingest-typed-C2OvZ7dp.d.mts} +3 -1
- package/dist/{sales-D4QRnpdz.d.ts → sales-DJJpMY_c.d.ts} +1 -1
- package/dist/{sales-DByfvgzT.d.mts → sales-Dil7TNV_.d.mts} +1 -1
- package/dist/sales.d.mts +2 -2
- package/dist/sales.d.ts +2 -2
- package/dist/sales.js +31 -2
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +31 -2
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -366,6 +366,11 @@ await submit({
|
|
|
366
366
|
form's own questions with `formSubmit.extraFields`; a name the booking already reports
|
|
367
367
|
(`phone`, `email`, ...) is dropped.
|
|
368
368
|
- Ask for the last name separately, and a mobile number (the shop's confirmation text goes to it).
|
|
369
|
+
- Details after booking (when `booking.rules.vehicleDeferred`, or for extra notes):
|
|
370
|
+
`updateBooking({ vehicle, notes })` from the same hook. It resolves `updated` / `queued` /
|
|
371
|
+
`notified_owner` (all saved) or `invalid`, `mismatch`, `conflict`, `not_found`, `failed`
|
|
372
|
+
(only `failed` is worth a retry). To survive a reload, save `booked` (`{ bookingId, attemptKey }`)
|
|
373
|
+
in `sessionStorage` and pass it back: `updateBooking(details, saved)`.
|
|
369
374
|
- Reports the `booking_integration` capability.
|
|
370
375
|
|
|
371
376
|
## On-site conversion firing
|
|
@@ -61,6 +61,8 @@ interface BookingRulesConfig {
|
|
|
61
61
|
/** `YYYY-MM-DD` shop dates whose start hours replace their weekday's; never also closed. */
|
|
62
62
|
special_hours: Record<string, BookingDayWindows>;
|
|
63
63
|
vehicle_required: boolean;
|
|
64
|
+
/** False from an API older than the deferred vehicle. */
|
|
65
|
+
vehicle_deferred: boolean;
|
|
64
66
|
/** Empty when the shop hides the drop-off question. */
|
|
65
67
|
drop_off_options: string[];
|
|
66
68
|
}
|
|
@@ -270,8 +272,43 @@ declare function uuidV4(): string;
|
|
|
270
272
|
/** Developer-only outcomes for a simulated create; the production API ignores them. */
|
|
271
273
|
declare const BOOKING_SIMULATIONS: readonly ["created", "rejected", "unknown", "failed"];
|
|
272
274
|
declare const BOOKING_DROP_OFF_OPTIONS: readonly ["waitForIt", "dropOff"];
|
|
275
|
+
declare const BOOKING_DETAILS_STATUSES: readonly ["updated", "queued", "notified_owner"];
|
|
273
276
|
type BookingDropOff = (typeof BOOKING_DROP_OFF_OPTIONS)[number];
|
|
274
277
|
type BookingSimulation = (typeof BOOKING_SIMULATIONS)[number];
|
|
278
|
+
type BookingDetailsStatus = (typeof BOOKING_DETAILS_STATUSES)[number];
|
|
279
|
+
/** Added after the booking: the vehicle (when the rules defer it), notes, or both. */
|
|
280
|
+
interface BookingDetailsInput {
|
|
281
|
+
vehicle?: {
|
|
282
|
+
year: number;
|
|
283
|
+
make: string;
|
|
284
|
+
model: string;
|
|
285
|
+
} | null;
|
|
286
|
+
notes?: string | null;
|
|
287
|
+
}
|
|
288
|
+
interface BookingDetailsOptions {
|
|
289
|
+
/** The `attemptKey` the booking was submitted with; only that submit may add to it. */
|
|
290
|
+
attemptKey: string;
|
|
291
|
+
}
|
|
292
|
+
type BookingDetailsOutcome =
|
|
293
|
+
/**
|
|
294
|
+
* `updated`: on the shop's request. `queued`: still on its way. `notified_owner`: the shop's
|
|
295
|
+
* request could no longer take them, so the owner was texted. All three mean "saved".
|
|
296
|
+
*/
|
|
297
|
+
{
|
|
298
|
+
status: BookingDetailsStatus;
|
|
299
|
+
id: string;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Not saved. `invalid`: a bad vehicle or note. `mismatch`: not this booking's attempt key.
|
|
303
|
+
* `conflict`: other details were already saved. `not_found`: no such booking for this key.
|
|
304
|
+
* `failed`: the network or the API failed; worth a retry.
|
|
305
|
+
*/
|
|
306
|
+
| {
|
|
307
|
+
status: BookingDetailsFailure;
|
|
308
|
+
id: string;
|
|
309
|
+
message: string;
|
|
310
|
+
};
|
|
311
|
+
type BookingDetailsFailure = "invalid" | "mismatch" | "conflict" | "not_found" | "failed";
|
|
275
312
|
/** What the booking form collected. Dates and hours are the shop's wall time. */
|
|
276
313
|
interface BookingInput {
|
|
277
314
|
/** `YYYY-MM-DD`, one of `bookableSlots(...)`'s dates. */
|
|
@@ -378,8 +415,13 @@ interface SalesBookingsClient {
|
|
|
378
415
|
submit(input: BookingInput, options: BookingSubmitOptions): Promise<BookingOutcome>;
|
|
379
416
|
/** A booking's current status by the id `submit` returned. */
|
|
380
417
|
status(id: string): Promise<BookingOutcome>;
|
|
418
|
+
/**
|
|
419
|
+
* Add the vehicle or notes after booking (e.g. `rules.vehicleDeferred`). Pass the booking's
|
|
420
|
+
* own `attemptKey`. Never rejects: they reach the shop's request, or the owner by text.
|
|
421
|
+
*/
|
|
422
|
+
updateBooking(bookingId: string, details: BookingDetailsInput, options: BookingDetailsOptions): Promise<BookingDetailsOutcome>;
|
|
381
423
|
}
|
|
382
424
|
/** A fresh per-submit key. Keep it for retries of the same submit; mint a new one after. */
|
|
383
425
|
declare const newBookingAttemptKey: typeof uuidV4;
|
|
384
426
|
|
|
385
|
-
export { type
|
|
427
|
+
export { type BookingDetailsFailure as B, type ConversionConfig as C, type FormSubmitField as F, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingDetailsInput as a, type BookingDetailsOptions as b, type BookingDetailsOutcome as c, type BookingDetailsStatus as d, type BookingDropOff as e, type BookingFormSubmit as f, type BookingInput as g, type BookingMode as h, type BookingOutcome as i, type BookingSimulation as j, type BookingSubmitOptions as k, type ConversionConfigStore as l, getTrackingConfigRuntime as m, newBookingAttemptKey as n, resolveTrackingConfigUrl as o, type BookingDayWindows as p, type ConversionIntegrations as q, resolveConversionConfig as r, TrackingConfigRuntime as s };
|
|
@@ -61,6 +61,8 @@ interface BookingRulesConfig {
|
|
|
61
61
|
/** `YYYY-MM-DD` shop dates whose start hours replace their weekday's; never also closed. */
|
|
62
62
|
special_hours: Record<string, BookingDayWindows>;
|
|
63
63
|
vehicle_required: boolean;
|
|
64
|
+
/** False from an API older than the deferred vehicle. */
|
|
65
|
+
vehicle_deferred: boolean;
|
|
64
66
|
/** Empty when the shop hides the drop-off question. */
|
|
65
67
|
drop_off_options: string[];
|
|
66
68
|
}
|
|
@@ -270,8 +272,43 @@ declare function uuidV4(): string;
|
|
|
270
272
|
/** Developer-only outcomes for a simulated create; the production API ignores them. */
|
|
271
273
|
declare const BOOKING_SIMULATIONS: readonly ["created", "rejected", "unknown", "failed"];
|
|
272
274
|
declare const BOOKING_DROP_OFF_OPTIONS: readonly ["waitForIt", "dropOff"];
|
|
275
|
+
declare const BOOKING_DETAILS_STATUSES: readonly ["updated", "queued", "notified_owner"];
|
|
273
276
|
type BookingDropOff = (typeof BOOKING_DROP_OFF_OPTIONS)[number];
|
|
274
277
|
type BookingSimulation = (typeof BOOKING_SIMULATIONS)[number];
|
|
278
|
+
type BookingDetailsStatus = (typeof BOOKING_DETAILS_STATUSES)[number];
|
|
279
|
+
/** Added after the booking: the vehicle (when the rules defer it), notes, or both. */
|
|
280
|
+
interface BookingDetailsInput {
|
|
281
|
+
vehicle?: {
|
|
282
|
+
year: number;
|
|
283
|
+
make: string;
|
|
284
|
+
model: string;
|
|
285
|
+
} | null;
|
|
286
|
+
notes?: string | null;
|
|
287
|
+
}
|
|
288
|
+
interface BookingDetailsOptions {
|
|
289
|
+
/** The `attemptKey` the booking was submitted with; only that submit may add to it. */
|
|
290
|
+
attemptKey: string;
|
|
291
|
+
}
|
|
292
|
+
type BookingDetailsOutcome =
|
|
293
|
+
/**
|
|
294
|
+
* `updated`: on the shop's request. `queued`: still on its way. `notified_owner`: the shop's
|
|
295
|
+
* request could no longer take them, so the owner was texted. All three mean "saved".
|
|
296
|
+
*/
|
|
297
|
+
{
|
|
298
|
+
status: BookingDetailsStatus;
|
|
299
|
+
id: string;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Not saved. `invalid`: a bad vehicle or note. `mismatch`: not this booking's attempt key.
|
|
303
|
+
* `conflict`: other details were already saved. `not_found`: no such booking for this key.
|
|
304
|
+
* `failed`: the network or the API failed; worth a retry.
|
|
305
|
+
*/
|
|
306
|
+
| {
|
|
307
|
+
status: BookingDetailsFailure;
|
|
308
|
+
id: string;
|
|
309
|
+
message: string;
|
|
310
|
+
};
|
|
311
|
+
type BookingDetailsFailure = "invalid" | "mismatch" | "conflict" | "not_found" | "failed";
|
|
275
312
|
/** What the booking form collected. Dates and hours are the shop's wall time. */
|
|
276
313
|
interface BookingInput {
|
|
277
314
|
/** `YYYY-MM-DD`, one of `bookableSlots(...)`'s dates. */
|
|
@@ -378,8 +415,13 @@ interface SalesBookingsClient {
|
|
|
378
415
|
submit(input: BookingInput, options: BookingSubmitOptions): Promise<BookingOutcome>;
|
|
379
416
|
/** A booking's current status by the id `submit` returned. */
|
|
380
417
|
status(id: string): Promise<BookingOutcome>;
|
|
418
|
+
/**
|
|
419
|
+
* Add the vehicle or notes after booking (e.g. `rules.vehicleDeferred`). Pass the booking's
|
|
420
|
+
* own `attemptKey`. Never rejects: they reach the shop's request, or the owner by text.
|
|
421
|
+
*/
|
|
422
|
+
updateBooking(bookingId: string, details: BookingDetailsInput, options: BookingDetailsOptions): Promise<BookingDetailsOutcome>;
|
|
381
423
|
}
|
|
382
424
|
/** A fresh per-submit key. Keep it for retries of the same submit; mint a new one after. */
|
|
383
425
|
declare const newBookingAttemptKey: typeof uuidV4;
|
|
384
426
|
|
|
385
|
-
export { type
|
|
427
|
+
export { type BookingDetailsFailure as B, type ConversionConfig as C, type FormSubmitField as F, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingDetailsInput as a, type BookingDetailsOptions as b, type BookingDetailsOutcome as c, type BookingDetailsStatus as d, type BookingDropOff as e, type BookingFormSubmit as f, type BookingInput as g, type BookingMode as h, type BookingOutcome as i, type BookingSimulation as j, type BookingSubmitOptions as k, type ConversionConfigStore as l, getTrackingConfigRuntime as m, newBookingAttemptKey as n, resolveTrackingConfigUrl as o, type BookingDayWindows as p, type ConversionIntegrations as q, resolveConversionConfig as r, TrackingConfigRuntime as s };
|
package/dist/client.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent, AnchorHTMLAttributes } from 'react';
|
|
3
3
|
import { G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, h as ConsentState, f as ConsentChoiceState, g as ConsentSource, T as TrackingParams, b as TrackingEnvironment, j as PhoneConfig, P as ParsedPhone, k as PhoneDisplayFormat } from './phone-utils-CM8eUPz8.mjs';
|
|
4
|
-
import { T as TrackingConfigReference, C as ConversionConfig,
|
|
5
|
-
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-
|
|
4
|
+
import { T as TrackingConfigReference, C as ConversionConfig, i as BookingOutcome, g as BookingInput, a as BookingDetailsInput, c as BookingDetailsOutcome, S as SalesBookingsClient, f as BookingFormSubmit, j as BookingSimulation } from './bookings-DtcwdM_I.mjs';
|
|
5
|
+
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-C2OvZ7dp.mjs';
|
|
6
6
|
import { CountryCode } from 'libphonenumber-js';
|
|
7
7
|
import './form-submit-BLb28aCk.mjs';
|
|
8
8
|
import 'zod/mini';
|
|
@@ -403,11 +403,25 @@ declare function BookingHandoffLink({ trackingConfig, fallbackUrl, prefill, chil
|
|
|
403
403
|
*/
|
|
404
404
|
declare function useBookingSlots(trackingConfig: TrackingConfigReference | undefined): BookableDay[];
|
|
405
405
|
type BookingSubmitStatus = "idle" | "submitting" | BookingOutcome["status"];
|
|
406
|
+
interface BookedAttempt {
|
|
407
|
+
bookingId: string;
|
|
408
|
+
attemptKey: string;
|
|
409
|
+
}
|
|
406
410
|
interface BookingSubmitState {
|
|
407
411
|
status: BookingSubmitStatus;
|
|
408
412
|
outcome: BookingOutcome | null;
|
|
409
413
|
/** Send the booking. A retry of an unanswered or refused submit reuses its attempt key. */
|
|
410
414
|
submit(input: BookingInput): Promise<BookingOutcome>;
|
|
415
|
+
/**
|
|
416
|
+
* The recorded booking and the key it was sent with; persist it (e.g. `sessionStorage`) to add
|
|
417
|
+
* details after a reload. Null until the server has the booking.
|
|
418
|
+
*/
|
|
419
|
+
booked: BookedAttempt | null;
|
|
420
|
+
/**
|
|
421
|
+
* Add the vehicle or notes to `booked`, or to `target` (a persisted one). Resolves `not_found`
|
|
422
|
+
* when there is neither.
|
|
423
|
+
*/
|
|
424
|
+
updateBooking(details: BookingDetailsInput, target?: BookedAttempt): Promise<BookingDetailsOutcome>;
|
|
411
425
|
/** Back to `idle` with a fresh attempt key, e.g. "book another car". */
|
|
412
426
|
reset(): void;
|
|
413
427
|
}
|
|
@@ -423,4 +437,4 @@ declare function useBookingSubmit(bookings: SalesBookingsClient, options?: {
|
|
|
423
437
|
simulate?: BookingSimulation;
|
|
424
438
|
}): BookingSubmitState;
|
|
425
439
|
|
|
426
|
-
export { AdPlatformTracking, type AdPlatformTrackingProps, BookingHandoffLink, type BookingHandoffLinkProps, type BookingHandoffOptions, type BookingSubmitState, type BookingSubmitStatus, ConsentBanner, type ConsentBannerProps, type CreateTrackingOptions, type CreateTrackingResult, GoogleAdsTracking, type GoogleAdsTrackingProps, PhoneField, type PhoneFieldApi, type PhoneFieldProps, type PhoneInputProps, type TrackingProviderProps, type UseConsentResult, type UseCookiePreferencesOptions, type UseCookiePreferencesResult, type UsePhoneFieldOptions, createTracking, useBookingHandoffUrl, useBookingIntegration, useBookingSlots, useBookingSubmit, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams };
|
|
440
|
+
export { AdPlatformTracking, type AdPlatformTrackingProps, type BookedAttempt, BookingHandoffLink, type BookingHandoffLinkProps, type BookingHandoffOptions, type BookingSubmitState, type BookingSubmitStatus, ConsentBanner, type ConsentBannerProps, type CreateTrackingOptions, type CreateTrackingResult, GoogleAdsTracking, type GoogleAdsTrackingProps, PhoneField, type PhoneFieldApi, type PhoneFieldProps, type PhoneInputProps, type TrackingProviderProps, type UseConsentResult, type UseCookiePreferencesOptions, type UseCookiePreferencesResult, type UsePhoneFieldOptions, createTracking, useBookingHandoffUrl, useBookingIntegration, useBookingSlots, useBookingSubmit, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent, AnchorHTMLAttributes } from 'react';
|
|
3
3
|
import { G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, h as ConsentState, f as ConsentChoiceState, g as ConsentSource, T as TrackingParams, b as TrackingEnvironment, j as PhoneConfig, P as ParsedPhone, k as PhoneDisplayFormat } from './phone-utils-l8ey3Zdm.js';
|
|
4
|
-
import { T as TrackingConfigReference, C as ConversionConfig,
|
|
5
|
-
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-
|
|
4
|
+
import { T as TrackingConfigReference, C as ConversionConfig, i as BookingOutcome, g as BookingInput, a as BookingDetailsInput, c as BookingDetailsOutcome, S as SalesBookingsClient, f as BookingFormSubmit, j as BookingSimulation } from './bookings-Bx7totlS.js';
|
|
5
|
+
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-B-BgEZdW.js';
|
|
6
6
|
import { CountryCode } from 'libphonenumber-js';
|
|
7
7
|
import './form-submit-BLb28aCk.js';
|
|
8
8
|
import 'zod/mini';
|
|
@@ -403,11 +403,25 @@ declare function BookingHandoffLink({ trackingConfig, fallbackUrl, prefill, chil
|
|
|
403
403
|
*/
|
|
404
404
|
declare function useBookingSlots(trackingConfig: TrackingConfigReference | undefined): BookableDay[];
|
|
405
405
|
type BookingSubmitStatus = "idle" | "submitting" | BookingOutcome["status"];
|
|
406
|
+
interface BookedAttempt {
|
|
407
|
+
bookingId: string;
|
|
408
|
+
attemptKey: string;
|
|
409
|
+
}
|
|
406
410
|
interface BookingSubmitState {
|
|
407
411
|
status: BookingSubmitStatus;
|
|
408
412
|
outcome: BookingOutcome | null;
|
|
409
413
|
/** Send the booking. A retry of an unanswered or refused submit reuses its attempt key. */
|
|
410
414
|
submit(input: BookingInput): Promise<BookingOutcome>;
|
|
415
|
+
/**
|
|
416
|
+
* The recorded booking and the key it was sent with; persist it (e.g. `sessionStorage`) to add
|
|
417
|
+
* details after a reload. Null until the server has the booking.
|
|
418
|
+
*/
|
|
419
|
+
booked: BookedAttempt | null;
|
|
420
|
+
/**
|
|
421
|
+
* Add the vehicle or notes to `booked`, or to `target` (a persisted one). Resolves `not_found`
|
|
422
|
+
* when there is neither.
|
|
423
|
+
*/
|
|
424
|
+
updateBooking(details: BookingDetailsInput, target?: BookedAttempt): Promise<BookingDetailsOutcome>;
|
|
411
425
|
/** Back to `idle` with a fresh attempt key, e.g. "book another car". */
|
|
412
426
|
reset(): void;
|
|
413
427
|
}
|
|
@@ -423,4 +437,4 @@ declare function useBookingSubmit(bookings: SalesBookingsClient, options?: {
|
|
|
423
437
|
simulate?: BookingSimulation;
|
|
424
438
|
}): BookingSubmitState;
|
|
425
439
|
|
|
426
|
-
export { AdPlatformTracking, type AdPlatformTrackingProps, BookingHandoffLink, type BookingHandoffLinkProps, type BookingHandoffOptions, type BookingSubmitState, type BookingSubmitStatus, ConsentBanner, type ConsentBannerProps, type CreateTrackingOptions, type CreateTrackingResult, GoogleAdsTracking, type GoogleAdsTrackingProps, PhoneField, type PhoneFieldApi, type PhoneFieldProps, type PhoneInputProps, type TrackingProviderProps, type UseConsentResult, type UseCookiePreferencesOptions, type UseCookiePreferencesResult, type UsePhoneFieldOptions, createTracking, useBookingHandoffUrl, useBookingIntegration, useBookingSlots, useBookingSubmit, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams };
|
|
440
|
+
export { AdPlatformTracking, type AdPlatformTrackingProps, type BookedAttempt, BookingHandoffLink, type BookingHandoffLinkProps, type BookingHandoffOptions, type BookingSubmitState, type BookingSubmitStatus, ConsentBanner, type ConsentBannerProps, type CreateTrackingOptions, type CreateTrackingResult, GoogleAdsTracking, type GoogleAdsTrackingProps, PhoneField, type PhoneFieldApi, type PhoneFieldProps, type PhoneInputProps, type TrackingProviderProps, type UseConsentResult, type UseCookiePreferencesOptions, type UseCookiePreferencesResult, type UsePhoneFieldOptions, createTracking, useBookingHandoffUrl, useBookingIntegration, useBookingSlots, useBookingSubmit, useConsent, useConsentState, useCookiePreferences, useGclid, usePhoneConfig, usePhoneField, useTrackingParams };
|
package/dist/client.js
CHANGED
|
@@ -1028,6 +1028,7 @@ function parseBookingRules(value) {
|
|
|
1028
1028
|
closed_dates: isStringList(r.closed_dates) ? r.closed_dates : [],
|
|
1029
1029
|
special_hours: parseWindowsMap(r.special_hours),
|
|
1030
1030
|
vehicle_required: r.vehicle_required === true,
|
|
1031
|
+
vehicle_deferred: r.vehicle_deferred === true,
|
|
1031
1032
|
drop_off_options: isStringList(r.drop_off_options) ? r.drop_off_options : []
|
|
1032
1033
|
};
|
|
1033
1034
|
}
|
|
@@ -1763,6 +1764,7 @@ function camelRules(rules) {
|
|
|
1763
1764
|
closedDates: rules.closed_dates,
|
|
1764
1765
|
specialHours: rules.special_hours,
|
|
1765
1766
|
vehicleRequired: rules.vehicle_required,
|
|
1767
|
+
vehicleDeferred: rules.vehicle_deferred,
|
|
1766
1768
|
dropOffOptions: rules.drop_off_options
|
|
1767
1769
|
};
|
|
1768
1770
|
}
|
|
@@ -3327,6 +3329,7 @@ function attachMultiPageSession(client, config) {
|
|
|
3327
3329
|
}
|
|
3328
3330
|
|
|
3329
3331
|
// ../tracking-core/src/triggers/form-start.ts
|
|
3332
|
+
var TAP_SLOP_PX = 10;
|
|
3330
3333
|
function attachFormStart(client, config) {
|
|
3331
3334
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
3332
3335
|
return () => {
|
|
@@ -3335,6 +3338,7 @@ function attachFormStart(client, config) {
|
|
|
3335
3338
|
const selector = config.selector ?? "form";
|
|
3336
3339
|
let firedForms = /* @__PURE__ */ new Set();
|
|
3337
3340
|
let currentPath2 = window.location.pathname;
|
|
3341
|
+
let pendingTap = null;
|
|
3338
3342
|
function getFormKey(form) {
|
|
3339
3343
|
if (form.id) return `id:${form.id}`;
|
|
3340
3344
|
const explicitAction = form.getAttribute("action");
|
|
@@ -3345,10 +3349,23 @@ function attachFormStart(client, config) {
|
|
|
3345
3349
|
function onFocusIn(event) {
|
|
3346
3350
|
startFrom(event.target);
|
|
3347
3351
|
}
|
|
3348
|
-
function
|
|
3352
|
+
function onClick(event) {
|
|
3349
3353
|
if (event.button !== 0) return;
|
|
3350
3354
|
startFrom(event.target);
|
|
3351
3355
|
}
|
|
3356
|
+
function onPointerDown(event) {
|
|
3357
|
+
pendingTap = event.button === 0 ? { pointerId: event.pointerId, x: event.clientX, y: event.clientY, target: event.target } : null;
|
|
3358
|
+
}
|
|
3359
|
+
function onPointerCancel() {
|
|
3360
|
+
pendingTap = null;
|
|
3361
|
+
}
|
|
3362
|
+
function onPointerUp(event) {
|
|
3363
|
+
const tap = pendingTap;
|
|
3364
|
+
pendingTap = null;
|
|
3365
|
+
if (!tap || tap.pointerId !== event.pointerId) return;
|
|
3366
|
+
if (Math.hypot(event.clientX - tap.x, event.clientY - tap.y) > TAP_SLOP_PX) return;
|
|
3367
|
+
startFrom(tap.target);
|
|
3368
|
+
}
|
|
3352
3369
|
function startFrom(target) {
|
|
3353
3370
|
if (!(target instanceof Element)) return;
|
|
3354
3371
|
const form = target.closest(selector);
|
|
@@ -3385,17 +3402,24 @@ function attachFormStart(client, config) {
|
|
|
3385
3402
|
originalReplaceState(...args);
|
|
3386
3403
|
setTimeout(resetIfPathChanged, 0);
|
|
3387
3404
|
}
|
|
3405
|
+
const passiveCapture = { capture: true, passive: true };
|
|
3388
3406
|
history.pushState = patchedPushState;
|
|
3389
3407
|
history.replaceState = patchedReplaceState;
|
|
3390
3408
|
window.addEventListener("popstate", resetIfPathChanged);
|
|
3391
3409
|
document.addEventListener("focusin", onFocusIn);
|
|
3392
|
-
document.addEventListener("
|
|
3410
|
+
document.addEventListener("click", onClick, passiveCapture);
|
|
3411
|
+
document.addEventListener("pointerdown", onPointerDown, passiveCapture);
|
|
3412
|
+
document.addEventListener("pointerup", onPointerUp, passiveCapture);
|
|
3413
|
+
document.addEventListener("pointercancel", onPointerCancel, passiveCapture);
|
|
3393
3414
|
return () => {
|
|
3394
3415
|
history.pushState = originalPushState;
|
|
3395
3416
|
history.replaceState = originalReplaceState;
|
|
3396
3417
|
window.removeEventListener("popstate", resetIfPathChanged);
|
|
3397
3418
|
document.removeEventListener("focusin", onFocusIn);
|
|
3419
|
+
document.removeEventListener("click", onClick, { capture: true });
|
|
3398
3420
|
document.removeEventListener("pointerdown", onPointerDown, { capture: true });
|
|
3421
|
+
document.removeEventListener("pointerup", onPointerUp, { capture: true });
|
|
3422
|
+
document.removeEventListener("pointercancel", onPointerCancel, { capture: true });
|
|
3399
3423
|
};
|
|
3400
3424
|
}
|
|
3401
3425
|
|
|
@@ -3985,7 +4009,7 @@ function GoogleAdsTracking(props) {
|
|
|
3985
4009
|
var import_react6 = require("react");
|
|
3986
4010
|
|
|
3987
4011
|
// package.json
|
|
3988
|
-
var version = "1.
|
|
4012
|
+
var version = "1.9.0";
|
|
3989
4013
|
|
|
3990
4014
|
// ../tracking-core/src/phone-react.tsx
|
|
3991
4015
|
var import_react5 = require("react");
|
|
@@ -4301,25 +4325,31 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4301
4325
|
const [outcome, setOutcome] = (0, import_react7.useState)(null);
|
|
4302
4326
|
const [submitting, setSubmitting] = (0, import_react7.useState)(false);
|
|
4303
4327
|
const attemptKey = (0, import_react7.useRef)(null);
|
|
4328
|
+
const [booked, setBooked] = (0, import_react7.useState)(null);
|
|
4304
4329
|
const inFlight = (0, import_react7.useRef)(null);
|
|
4305
4330
|
const { formSubmit, simulate } = options;
|
|
4306
4331
|
const submit = (0, import_react7.useCallback)(
|
|
4307
4332
|
(input) => {
|
|
4308
4333
|
if (inFlight.current) return inFlight.current;
|
|
4309
4334
|
attemptKey.current ?? (attemptKey.current = newBookingAttemptKey());
|
|
4335
|
+
const key = attemptKey.current;
|
|
4310
4336
|
setSubmitting(true);
|
|
4311
4337
|
const run = bookings.submit(input, {
|
|
4312
|
-
attemptKey:
|
|
4338
|
+
attemptKey: key,
|
|
4313
4339
|
formSubmit,
|
|
4314
4340
|
simulate,
|
|
4315
4341
|
// The server has it: show the pending success while the final answer is polled.
|
|
4316
4342
|
onPending: (pending) => {
|
|
4343
|
+
setBooked({ bookingId: pending.id, attemptKey: key });
|
|
4317
4344
|
setOutcome(pending);
|
|
4318
4345
|
setSubmitting(false);
|
|
4319
4346
|
}
|
|
4320
4347
|
}).then((result) => {
|
|
4321
4348
|
const unrecorded = result.status === "invalid" || result.status === "stale" || result.status === "failed" && result.id === null;
|
|
4322
4349
|
if (!unrecorded) attemptKey.current = null;
|
|
4350
|
+
if (result.status !== "invalid" && result.status !== "stale" && result.id) {
|
|
4351
|
+
setBooked({ bookingId: result.id, attemptKey: key });
|
|
4352
|
+
}
|
|
4323
4353
|
setOutcome(result);
|
|
4324
4354
|
return result;
|
|
4325
4355
|
}).finally(() => {
|
|
@@ -4331,12 +4361,23 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4331
4361
|
},
|
|
4332
4362
|
[bookings, formSubmit, simulate]
|
|
4333
4363
|
);
|
|
4364
|
+
const updateBooking = (0, import_react7.useCallback)(
|
|
4365
|
+
async (details, target) => {
|
|
4366
|
+
const attempt = target ?? booked;
|
|
4367
|
+
if (!attempt) return { status: "not_found", id: "", message: "Nothing has been booked yet." };
|
|
4368
|
+
return bookings.updateBooking(attempt.bookingId, details, {
|
|
4369
|
+
attemptKey: attempt.attemptKey
|
|
4370
|
+
});
|
|
4371
|
+
},
|
|
4372
|
+
[bookings, booked]
|
|
4373
|
+
);
|
|
4334
4374
|
const reset = (0, import_react7.useCallback)(() => {
|
|
4335
4375
|
attemptKey.current = null;
|
|
4376
|
+
setBooked(null);
|
|
4336
4377
|
setOutcome(null);
|
|
4337
4378
|
}, []);
|
|
4338
4379
|
const status = submitting ? "submitting" : outcome?.status ?? "idle";
|
|
4339
|
-
return { status, outcome, submit, reset };
|
|
4380
|
+
return { status, outcome, booked, submit, updateBooking, reset };
|
|
4340
4381
|
}
|
|
4341
4382
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4342
4383
|
0 && (module.exports = {
|