@aranova/tracking-react 1.12.0 → 1.14.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.
Files changed (36) hide show
  1. package/README.md +31 -3
  2. package/dist/{bookings-v_ucn93l.d.ts → bookings-Bw2ImtPd.d.ts} +3 -1
  3. package/dist/{bookings-Lmi0o_PA.d.mts → bookings-CDGNZUaH.d.mts} +3 -1
  4. package/dist/client.d.mts +5 -4
  5. package/dist/client.d.ts +5 -4
  6. package/dist/client.js +369 -40
  7. package/dist/client.js.map +1 -1
  8. package/dist/client.mjs +367 -39
  9. package/dist/client.mjs.map +1 -1
  10. package/dist/{form-submit-CX-CxJjQ.d.mts → form-submit-C_vJXCxh.d.mts} +11 -1
  11. package/dist/{form-submit-CX-CxJjQ.d.ts → form-submit-C_vJXCxh.d.ts} +11 -1
  12. package/dist/index.d.mts +9 -180
  13. package/dist/index.d.ts +9 -180
  14. package/dist/index.js +332 -285
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +329 -285
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/{phone-utils-D12FW8tT.d.ts → phone-utils-Cfdx474X.d.mts} +178 -3
  19. package/dist/{phone-utils-BNiSqeF7.d.mts → phone-utils-D2TGPCQW.d.ts} +178 -3
  20. package/dist/phone.d.mts +2 -2
  21. package/dist/phone.d.ts +2 -2
  22. package/dist/phone.js +2 -2
  23. package/dist/phone.js.map +1 -1
  24. package/dist/phone.mjs +2 -2
  25. package/dist/phone.mjs.map +1 -1
  26. package/dist/{sales-6vMEcopj.d.mts → sales-D4aU73mR.d.mts} +1 -1
  27. package/dist/{sales-DXLGjJQ6.d.ts → sales-DkdrGIUS.d.ts} +1 -1
  28. package/dist/sales.d.mts +3 -3
  29. package/dist/sales.d.ts +3 -3
  30. package/dist/sales.js +193 -171
  31. package/dist/sales.js.map +1 -1
  32. package/dist/sales.mjs +193 -171
  33. package/dist/sales.mjs.map +1 -1
  34. package/dist/{ingest-typed-B9I1c7jr.d.ts → submit-DuvP5AGN.d.ts} +161 -4
  35. package/dist/{ingest-typed-PKFEuJ8E.d.mts → submit-rqgXl-Wg.d.mts} +161 -4
  36. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -53,6 +53,7 @@ __export(src_exports, {
53
53
  buildBookingHandoffUrl: () => buildBookingHandoffUrl,
54
54
  captureTrackingParamsFromLocation: () => captureTrackingParamsFromLocation,
55
55
  clearStashedUserData: () => clearStashedUserData,
56
+ createLeadFormSubmit: () => import_client4.createLeadFormSubmit,
56
57
  createSalesClient: () => createSalesClient,
57
58
  createTracking: () => import_client.createTracking,
58
59
  createTrackingClientContext: () => createTrackingClientContext,
@@ -88,7 +89,9 @@ __export(src_exports, {
88
89
  salesRequest: () => salesRequest,
89
90
  setConsentState: () => setConsentState,
90
91
  shopToday: () => shopToday,
92
+ slotFields: () => slotFields,
91
93
  stashUserData: () => stashUserData,
94
+ timeWindow: () => timeWindow,
92
95
  toE164: () => toE164,
93
96
  toMinor: () => toMinor,
94
97
  useBookingHandoffUrl: () => import_client3.useBookingHandoffUrl,
@@ -327,7 +330,8 @@ var TRACKING_CAPABILITIES = [
327
330
  "cta_click_capture",
328
331
  "form_capture",
329
332
  "phone_click_capture",
330
- "phone_fields"
333
+ "phone_fields",
334
+ "typed_form_submit"
331
335
  ];
332
336
  var CAPABILITY_DOM_ATTRIBUTE = "data-aranova-capability";
333
337
  var registered = /* @__PURE__ */ new Set();
@@ -1419,6 +1423,10 @@ var TrackingConfigRuntime = class {
1419
1423
  integrations() {
1420
1424
  return this.current?.integrations ?? null;
1421
1425
  }
1426
+ /** The lead-form contracts, from the cached object like `integrations()`. */
1427
+ leadForms() {
1428
+ return this.current?.lead_forms ?? null;
1429
+ }
1422
1430
  async revalidateNow() {
1423
1431
  try {
1424
1432
  const headers = {};
@@ -1801,6 +1809,118 @@ var SDK_PACKAGE_HEADER = "X-Aranova-Sdk-Package";
1801
1809
  var SDK_SURFACE_HEADER = "X-Aranova-Sdk-Surface";
1802
1810
  var SDK_ENVIRONMENT_HEADER = "X-Aranova-Sdk-Environment";
1803
1811
 
1812
+ // ../tracking-core/src/lead-forms/lead-forms.gen.ts
1813
+ var z2 = __toESM(require("zod/mini"));
1814
+ var LEAD_FORM_REGISTRY_VERSION = 2;
1815
+ var LEAD_FORM_KINDS = ["booking", "quote", "contact", "consult", "callback"];
1816
+ var LEAD_FORM_ROLES = [
1817
+ "given_name",
1818
+ "family_name",
1819
+ "phone",
1820
+ "email",
1821
+ "service",
1822
+ "preferred_date",
1823
+ "preferred_time",
1824
+ "note",
1825
+ "visit",
1826
+ "intent",
1827
+ "vehicle",
1828
+ "drop_off",
1829
+ "address",
1830
+ "patient_type",
1831
+ "matter",
1832
+ "language",
1833
+ "products",
1834
+ "goal",
1835
+ "business_type",
1836
+ "lead_volume",
1837
+ "attribution"
1838
+ ];
1839
+ var LEAD_FORM_PRIMITIVES = [
1840
+ "string",
1841
+ "text",
1842
+ "enum",
1843
+ "multi_enum",
1844
+ "bool",
1845
+ "date",
1846
+ "time_window",
1847
+ "phone",
1848
+ "email",
1849
+ "address",
1850
+ "number"
1851
+ ];
1852
+ var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
1853
+ string: z2.string().check(z2.maxLength(120)),
1854
+ text: z2.string().check(z2.maxLength(2e3)),
1855
+ enum: z2.string().check(z2.regex(/^[a-z0-9-]{1,48}$/)),
1856
+ multi_enum: z2.array(z2.string().check(z2.regex(/^[a-z0-9-]{1,48}$/))).check(z2.maxLength(10)),
1857
+ bool: z2.boolean(),
1858
+ date: z2.string().check(z2.regex(/^\d{4}-\d{2}-\d{2}$/)),
1859
+ time_window: z2.strictObject({
1860
+ start: z2.string().check(z2.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
1861
+ end: z2.nullable(z2.string().check(z2.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
1862
+ label: z2.optional(z2.string().check(z2.maxLength(60)))
1863
+ }),
1864
+ phone: z2.string().check(z2.regex(/^\+[1-9]\d{6,14}$/)),
1865
+ email: z2.string().check(z2.maxLength(320), z2.regex(/^[^\s@]+@[^\s@]+$/)),
1866
+ address: z2.strictObject({
1867
+ line1: z2.string().check(z2.maxLength(120)),
1868
+ line2: z2.optional(z2.string().check(z2.maxLength(120))),
1869
+ city: z2.optional(z2.string().check(z2.maxLength(120))),
1870
+ region: z2.optional(z2.string().check(z2.maxLength(120))),
1871
+ postal_code: z2.optional(z2.string().check(z2.maxLength(120))),
1872
+ country: z2.optional(z2.string().check(z2.maxLength(120)))
1873
+ }),
1874
+ number: z2.number()
1875
+ }))();
1876
+ var LEAD_FORM_ROLE_SPECS = {
1877
+ given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
1878
+ family_name: { primitive: "string", smsLabel: "", contactIdentity: true },
1879
+ phone: { primitive: "phone", smsLabel: "", contactIdentity: true },
1880
+ email: { primitive: "email", smsLabel: "", contactIdentity: true },
1881
+ service: { primitive: "multi_enum", smsLabel: "Service" },
1882
+ preferred_date: { primitive: "date", smsLabel: "Date" },
1883
+ preferred_time: { primitive: "time_window", smsLabel: "Time" },
1884
+ note: { primitive: "text", smsLabel: "Note" },
1885
+ visit: {
1886
+ primitive: "enum",
1887
+ smsLabel: "Visit",
1888
+ options: [
1889
+ { key: "in-shop", label: "In shop" },
1890
+ { key: "in-home", label: "In home" },
1891
+ { key: "remote", label: "Remote" },
1892
+ { key: "on-site", label: "On site" }
1893
+ ]
1894
+ },
1895
+ intent: {
1896
+ primitive: "enum",
1897
+ smsLabel: "Wants",
1898
+ options: [
1899
+ { key: "book", label: "Book" },
1900
+ { key: "quote", label: "Quote" }
1901
+ ]
1902
+ },
1903
+ vehicle: { primitive: "string", smsLabel: "Vehicle" },
1904
+ drop_off: {
1905
+ primitive: "enum",
1906
+ smsLabel: "Drop-off",
1907
+ options: [
1908
+ { key: "wait-for-it", label: "Waiting" },
1909
+ { key: "drop-off", label: "Dropping off" }
1910
+ ]
1911
+ },
1912
+ address: { primitive: "address", smsLabel: "Address" },
1913
+ patient_type: { primitive: "enum", smsLabel: "Patient" },
1914
+ matter: { primitive: "enum", smsLabel: "Matter" },
1915
+ language: { primitive: "enum", smsLabel: "Language" },
1916
+ products: { primitive: "multi_enum", smsLabel: "Products" },
1917
+ goal: { primitive: "enum", smsLabel: "Goal" },
1918
+ business_type: { primitive: "enum", smsLabel: "Business" },
1919
+ lead_volume: { primitive: "enum", smsLabel: "Lead volume" },
1920
+ add_on: { primitive: "bool", smsLabel: "" },
1921
+ attribution: { primitive: "enum", smsLabel: "", uninteresting: true }
1922
+ };
1923
+
1804
1924
  // ../tracking-core/src/resources/http/errors.ts
1805
1925
  var AranovaApiError = class extends Error {
1806
1926
  constructor(message, options) {
@@ -1894,39 +2014,54 @@ function outcomeOf(body) {
1894
2014
  if (body.status === "pending") return { status: "pending", id: body.id, mode };
1895
2015
  return { status: "failed", id: body.id, fallbackUrl: body.fallback_url, mode };
1896
2016
  }
1897
- function formSubmitPayload(input, formSubmit, labels) {
1898
- const vehicle = input.vehicle ? `${input.vehicle.year} ${input.vehicle.make} ${input.vehicle.model}` : "";
1899
- const field = (name, type, label, value) => ({
1900
- name,
1901
- type,
1902
- label,
1903
- value
1904
- });
1905
- const fields = [
1906
- field("first_name", "text", "First name", input.firstName),
1907
- field("last_name", "text", "Last name", input.lastName),
2017
+ var DROP_OFF_KEYS = {
2018
+ waitForIt: "wait-for-it",
2019
+ dropOff: "drop-off"
2020
+ };
2021
+ function formSubmitPayload(input, formSubmit, contractHash) {
2022
+ const field = (role, name, type, label, value) => ({ name, type, label, value, role });
2023
+ const text = (value) => value?.trim() || void 0;
2024
+ const { vehicle, dropOff } = input;
2025
+ const entries = [
2026
+ field("given_name", "first_name", "text", "First name", text(input.firstName)),
2027
+ field("family_name", "last_name", "text", "Last name", text(input.lastName)),
1908
2028
  // E.164 on the wire: it keys the customer and enhanced-conversion matching.
1909
- field("phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
1910
- field("email", "email", "Email", input.email ?? ""),
2029
+ field("phone", "phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
2030
+ field("email", "email", "email", "Email", text(input.email)),
2031
+ field("service", "service", "select", "Service", input.services),
1911
2032
  field(
1912
- "service",
1913
- "select",
1914
- "Service",
1915
- input.services.map((key) => labels.get(key) ?? key).join(", ")
2033
+ "vehicle",
2034
+ "vehicle",
2035
+ "text",
2036
+ "Vehicle",
2037
+ vehicle ? `${vehicle.year} ${vehicle.make} ${vehicle.model}` : void 0
1916
2038
  ),
1917
- field("vehicle", "text", "Vehicle", vehicle),
1918
2039
  field(
1919
- "start",
1920
- "text",
1921
- "Requested time",
1922
- `${input.startDate} ${String(input.startHour).padStart(2, "0")}:00`
2040
+ "drop_off",
2041
+ "drop_off",
2042
+ "select",
2043
+ "Drop-off",
2044
+ dropOff ? DROP_OFF_KEYS[dropOff] : void 0
1923
2045
  ),
1924
- field("note", "textarea", "Notes", input.notes ?? "")
2046
+ field("preferred_date", "preferred_date", "date", "Date", input.startDate),
2047
+ field("preferred_time", "preferred_time", "time", "Time", {
2048
+ start: `${String(input.startHour).padStart(2, "0")}:00`,
2049
+ end: null
2050
+ }),
2051
+ field("note", "note", "textarea", "Notes", text(input.notes))
1925
2052
  ];
1926
- const reported = new Set(fields.map((item) => item.name));
2053
+ const reported = new Set(entries.map((item) => item.name));
2054
+ const fields = entries.filter((item) => item.value !== void 0);
1927
2055
  const extra = (formSubmit.extraFields ?? []).filter((item) => !reported.has(item.name));
1928
2056
  return {
1929
- form: { id: formSubmit.formId, action: "/tracking/bookings", fields: [...fields, ...extra] },
2057
+ form: {
2058
+ id: formSubmit.formId,
2059
+ action: "/tracking/bookings",
2060
+ fields: [...fields, ...extra],
2061
+ kind: "booking",
2062
+ contract_version: LEAD_FORM_REGISTRY_VERSION,
2063
+ ...contractHash ? { contract_hash: contractHash } : {}
2064
+ },
1930
2065
  page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
1931
2066
  };
1932
2067
  }
@@ -2024,8 +2159,11 @@ function createSalesBookingsClient(config, firing) {
2024
2159
  }
2025
2160
  if (formSubmit && !submittedForms.has(attemptKey)) {
2026
2161
  submittedForms.add(attemptKey);
2027
- const labels = new Map(booking.options.map((option) => [option.key, option.label]));
2028
- formSubmit.tracking.trackEvent("form_submit", formSubmitPayload(input, formSubmit, labels));
2162
+ const contract = runtime?.leadForms()?.contracts.find((c) => c.form_kind === "booking");
2163
+ formSubmit.tracking.trackEvent(
2164
+ "form_submit",
2165
+ formSubmitPayload(input, formSubmit, contract?.contract_hash ?? null)
2166
+ );
2029
2167
  }
2030
2168
  const body = {
2031
2169
  idempotency_key: attemptKey,
@@ -2275,17 +2413,17 @@ function createSalesClient(config) {
2275
2413
  }
2276
2414
 
2277
2415
  // ../tracking-core/src/resources/sales/schema.ts
2278
- var z3 = __toESM(require("zod/mini"));
2416
+ var z4 = __toESM(require("zod/mini"));
2279
2417
 
2280
2418
  // ../tracking-core/src/resources/sales/generated/zod.gen.ts
2281
- var z2 = __toESM(require("zod/mini"));
2282
- var zAutoLeapSaleFacts = z2.object({
2283
- first_order: z2.boolean(),
2284
- fleet_customer: z2.boolean(),
2285
- invoice_code: z2.string(),
2286
- invoice_id: z2.string()
2419
+ var z3 = __toESM(require("zod/mini"));
2420
+ var zAutoLeapSaleFacts = z3.object({
2421
+ first_order: z3.boolean(),
2422
+ fleet_customer: z3.boolean(),
2423
+ invoice_code: z3.string(),
2424
+ invoice_id: z3.string()
2287
2425
  });
2288
- var zErrorCode = z2.enum([
2426
+ var zErrorCode = z3.enum([
2289
2427
  "missing_credentials",
2290
2428
  "invalid_api_key",
2291
2429
  "not_authenticated",
@@ -2329,37 +2467,37 @@ var zErrorCode = z2.enum([
2329
2467
  "rate_limited",
2330
2468
  "internal_error"
2331
2469
  ]);
2332
- var zSaleItemEntitySchema = z2.object({
2333
- category: z2.nullable(z2.string()),
2334
- external_item_id: z2.nullable(z2.string()),
2335
- id: z2.uuid(),
2336
- name: z2.nullable(z2.string()),
2337
- quantity: z2.string().check(z2.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
2338
- unit_cost_cents: z2.nullable(z2.int()),
2339
- unit_price_cents: z2.int()
2470
+ var zSaleItemEntitySchema = z3.object({
2471
+ category: z3.nullable(z3.string()),
2472
+ external_item_id: z3.nullable(z3.string()),
2473
+ id: z3.uuid(),
2474
+ name: z3.nullable(z3.string()),
2475
+ quantity: z3.string().check(z3.regex(/^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$/)),
2476
+ unit_cost_cents: z3.nullable(z3.int()),
2477
+ unit_price_cents: z3.int()
2340
2478
  });
2341
- var zSaleItemInputSchema = z2.strictObject({
2342
- category: z2.nullish(z2.string()),
2343
- external_item_id: z2.nullish(z2.string()),
2344
- name: z2.nullish(z2.string()),
2345
- quantity: z2.string().check(z2.regex(/^\d+(\.\d{1,3})?$/)),
2346
- unit_cost_cents: z2.nullish(z2.int().check(z2.gte(0))),
2347
- unit_price_cents: z2.int().check(z2.gte(0))
2479
+ var zSaleItemInputSchema = z3.strictObject({
2480
+ category: z3.nullish(z3.string()),
2481
+ external_item_id: z3.nullish(z3.string()),
2482
+ name: z3.nullish(z3.string()),
2483
+ quantity: z3.string().check(z3.regex(/^\d+(\.\d{1,3})?$/)),
2484
+ unit_cost_cents: z3.nullish(z3.int().check(z3.gte(0))),
2485
+ unit_price_cents: z3.int().check(z3.gte(0))
2348
2486
  });
2349
- var zSaleServiceEntitySchema = z2.object({
2350
- amount_cents: z2.int(),
2351
- id: z2.uuid(),
2352
- mapped: z2.nullable(z2.boolean()),
2353
- service_id: z2.uuid(),
2354
- service_key: z2.string(),
2355
- service_label: z2.string()
2487
+ var zSaleServiceEntitySchema = z3.object({
2488
+ amount_cents: z3.int(),
2489
+ id: z3.uuid(),
2490
+ mapped: z3.nullable(z3.boolean()),
2491
+ service_id: z3.uuid(),
2492
+ service_key: z3.string(),
2493
+ service_label: z3.string()
2356
2494
  });
2357
- var zSaleServiceInputSchema = z2.strictObject({
2358
- amount_cents: z2.int().check(z2.gte(0)),
2359
- service: z2.string()
2495
+ var zSaleServiceInputSchema = z3.strictObject({
2496
+ amount_cents: z3.int().check(z3.gte(0)),
2497
+ service: z3.string()
2360
2498
  });
2361
- var zSaleSource = z2.enum(["api", "admin", "autoleap"]);
2362
- var zSmsAutomationState = z2.enum([
2499
+ var zSaleSource = z3.enum(["api", "admin", "autoleap"]);
2500
+ var zSmsAutomationState = z3.enum([
2363
2501
  "needs_check",
2364
2502
  "failed",
2365
2503
  "undelivered",
@@ -2371,7 +2509,7 @@ var zSmsAutomationState = z2.enum([
2371
2509
  "eligible",
2372
2510
  "not_applicable"
2373
2511
  ]);
2374
- var zSmsWithheldReason = z2.enum([
2512
+ var zSmsWithheldReason = z3.enum([
2375
2513
  "automation_disabled",
2376
2514
  "sms_disabled",
2377
2515
  "no_phone",
@@ -2399,75 +2537,75 @@ var zSmsWithheldReason = z2.enum([
2399
2537
  "invalid_phone",
2400
2538
  "recently_texted"
2401
2539
  ]);
2402
- var zSaleSmsStatusSchema = z2.object({
2403
- can_send_now: z2._default(z2.boolean(), false),
2404
- last_message_at: z2.nullable(z2.iso.datetime({ offset: true })),
2405
- reason_detail: z2.nullable(z2.string()),
2540
+ var zSaleSmsStatusSchema = z3.object({
2541
+ can_send_now: z3._default(z3.boolean(), false),
2542
+ last_message_at: z3.nullable(z3.iso.datetime({ offset: true })),
2543
+ reason_detail: z3.nullable(z3.string()),
2406
2544
  state: zSmsAutomationState,
2407
- suppressed_by_other_sale: z2._default(z2.boolean(), false),
2408
- withheld_reason: z2.nullable(zSmsWithheldReason)
2545
+ suppressed_by_other_sale: z3._default(z3.boolean(), false),
2546
+ withheld_reason: z3.nullable(zSmsWithheldReason)
2409
2547
  });
2410
- var zSupportedCurrency = z2.enum(["USD", "CAD"]);
2411
- var zTrackingEnvironment = z2.enum(["production", "development"]);
2412
- var zSaleCreateSchema = z2.strictObject({
2413
- amount_total_cents: z2.nullish(z2.int().check(z2.gte(0))),
2548
+ var zSupportedCurrency = z3.enum(["USD", "CAD"]);
2549
+ var zTrackingEnvironment = z3.enum(["production", "development"]);
2550
+ var zSaleCreateSchema = z3.strictObject({
2551
+ amount_total_cents: z3.nullish(z3.int().check(z3.gte(0))),
2414
2552
  currency: zSupportedCurrency,
2415
- customer_email: z2.nullish(z2.email().check(z2.maxLength(320))),
2416
- customer_name: z2.nullish(z2.string().check(z2.maxLength(200))),
2417
- customer_phone: z2.nullish(z2.string().check(z2.maxLength(64))),
2418
- description: z2.nullish(z2.string()),
2419
- environment: z2._default(z2.optional(zTrackingEnvironment), "production"),
2420
- external_id: z2.nullish(z2.string()),
2421
- items: z2.optional(z2.array(zSaleItemInputSchema)),
2422
- metadata: z2.nullish(z2.record(z2.string(), z2.unknown())),
2423
- occurred_at: z2.iso.datetime({ offset: true }),
2424
- service: z2.nullish(z2.string()),
2425
- services: z2.nullish(z2.array(zSaleServiceInputSchema)),
2426
- sms_consent: z2.nullish(z2.boolean())
2553
+ customer_email: z3.nullish(z3.email().check(z3.maxLength(320))),
2554
+ customer_name: z3.nullish(z3.string().check(z3.maxLength(200))),
2555
+ customer_phone: z3.nullish(z3.string().check(z3.maxLength(64))),
2556
+ description: z3.nullish(z3.string()),
2557
+ environment: z3._default(z3.optional(zTrackingEnvironment), "production"),
2558
+ external_id: z3.nullish(z3.string()),
2559
+ items: z3.optional(z3.array(zSaleItemInputSchema)),
2560
+ metadata: z3.nullish(z3.record(z3.string(), z3.unknown())),
2561
+ occurred_at: z3.iso.datetime({ offset: true }),
2562
+ service: z3.nullish(z3.string()),
2563
+ services: z3.nullish(z3.array(zSaleServiceInputSchema)),
2564
+ sms_consent: z3.nullish(z3.boolean())
2427
2565
  });
2428
- var zValidationError = z2.object({
2429
- ctx: z2.optional(z2.record(z2.string(), z2.unknown())),
2430
- input: z2.optional(z2.unknown()),
2431
- loc: z2.array(z2.union([z2.string(), z2.int()])),
2432
- msg: z2.string(),
2433
- type: z2.string()
2566
+ var zValidationError = z3.object({
2567
+ ctx: z3.optional(z3.record(z3.string(), z3.unknown())),
2568
+ input: z3.optional(z3.unknown()),
2569
+ loc: z3.array(z3.union([z3.string(), z3.int()])),
2570
+ msg: z3.string(),
2571
+ type: z3.string()
2434
2572
  });
2435
- var zHttpValidationError = z2.object({
2436
- detail: z2.optional(z2.array(zValidationError))
2573
+ var zHttpValidationError = z3.object({
2574
+ detail: z3.optional(z3.array(zValidationError))
2437
2575
  });
2438
- var zValidationErrorItem = z2.object({
2439
- loc: z2.array(z2.union([z2.string(), z2.int()])),
2440
- msg: z2.string(),
2441
- type: z2.string()
2576
+ var zValidationErrorItem = z3.object({
2577
+ loc: z3.array(z3.union([z3.string(), z3.int()])),
2578
+ msg: z3.string(),
2579
+ type: z3.string()
2442
2580
  });
2443
- var zApiErrorSchema = z2.object({
2581
+ var zApiErrorSchema = z3.object({
2444
2582
  code: zErrorCode,
2445
- context: z2._default(z2.nullish(z2.record(z2.string(), z2.unknown())), null),
2446
- detail: z2.string(),
2447
- errors: z2._default(z2.nullish(z2.array(zValidationErrorItem)), null),
2448
- request_id: z2._default(z2.nullish(z2.string()), null)
2583
+ context: z3._default(z3.nullish(z3.record(z3.string(), z3.unknown())), null),
2584
+ detail: z3.string(),
2585
+ errors: z3._default(z3.nullish(z3.array(zValidationErrorItem)), null),
2586
+ request_id: z3._default(z3.nullish(z3.string()), null)
2449
2587
  });
2450
- var zWritebackEmailSource = z2.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
2451
- var zWritebackEnrichmentStatus = z2.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
2452
- var zWritebackSaleUploadCounts = z2.object({
2453
- failed: z2._default(z2.int(), 0),
2454
- pending: z2._default(z2.int(), 0),
2455
- skipped: z2._default(z2.int(), 0),
2456
- submitted: z2._default(z2.int(), 0),
2457
- total: z2._default(z2.int(), 0),
2458
- uploaded: z2._default(z2.int(), 0)
2588
+ var zWritebackEmailSource = z3.enum(["NONE", "SALE", "CUSTOMER", "HARVESTED"]);
2589
+ var zWritebackEnrichmentStatus = z3.enum(["NONE", "MATCHED", "AMBIGUOUS"]);
2590
+ var zWritebackSaleUploadCounts = z3.object({
2591
+ failed: z3._default(z3.int(), 0),
2592
+ pending: z3._default(z3.int(), 0),
2593
+ skipped: z3._default(z3.int(), 0),
2594
+ submitted: z3._default(z3.int(), 0),
2595
+ total: z3._default(z3.int(), 0),
2596
+ uploaded: z3._default(z3.int(), 0)
2459
2597
  });
2460
- var zSaleWritebackStatusSchema = z2.object({
2461
- blocked_reason: z2.nullable(z2.string()),
2462
- can_dispatch: z2._default(z2.boolean(), false),
2463
- email_source: z2.nullable(zWritebackEmailSource),
2464
- enrichment_status: z2.nullable(zWritebackEnrichmentStatus),
2465
- gclid_attached: z2._default(z2.boolean(), false),
2466
- identifiers_sent: z2.nullable(z2.string()),
2467
- mapped_service_ids: z2.array(z2.uuid()),
2468
- matched_submit_count: z2.nullable(z2.int()),
2469
- needs_force: z2._default(z2.boolean(), false),
2470
- rollup: z2.enum([
2598
+ var zSaleWritebackStatusSchema = z3.object({
2599
+ blocked_reason: z3.nullable(z3.string()),
2600
+ can_dispatch: z3._default(z3.boolean(), false),
2601
+ email_source: z3.nullable(zWritebackEmailSource),
2602
+ enrichment_status: z3.nullable(zWritebackEnrichmentStatus),
2603
+ gclid_attached: z3._default(z3.boolean(), false),
2604
+ identifiers_sent: z3.nullable(z3.string()),
2605
+ mapped_service_ids: z3.array(z3.uuid()),
2606
+ matched_submit_count: z3.nullable(z3.int()),
2607
+ needs_force: z3._default(z3.boolean(), false),
2608
+ rollup: z3.enum([
2471
2609
  "failed",
2472
2610
  "skipped",
2473
2611
  "pending",
@@ -2477,39 +2615,39 @@ var zSaleWritebackStatusSchema = z2.object({
2477
2615
  "out_of_window",
2478
2616
  "blocked"
2479
2617
  ]),
2480
- stale: z2._default(z2.boolean(), false),
2481
- uncovered_service_ids: z2.array(z2.uuid()),
2618
+ stale: z3._default(z3.boolean(), false),
2619
+ uncovered_service_ids: z3.array(z3.uuid()),
2482
2620
  uploads: zWritebackSaleUploadCounts
2483
2621
  });
2484
- var zSaleEntitySchema = z2.object({
2485
- amount_total_cents: z2.int(),
2486
- business_id: z2.uuid(),
2487
- business_name: z2.nullable(z2.string()),
2488
- created_at: z2.iso.datetime({ offset: true }),
2489
- currency: z2.string(),
2490
- customer_email: z2.nullable(z2.string()),
2491
- customer_name: z2.nullable(z2.string()),
2492
- customer_name_placeholder_confirmed: z2._default(z2.boolean(), false),
2493
- customer_name_placeholder_confirmed_at: z2.nullable(z2.iso.datetime({ offset: true })),
2494
- customer_phone: z2.nullable(z2.string()),
2495
- description: z2.nullable(z2.string()),
2622
+ var zSaleEntitySchema = z3.object({
2623
+ amount_total_cents: z3.int(),
2624
+ business_id: z3.uuid(),
2625
+ business_name: z3.nullable(z3.string()),
2626
+ created_at: z3.iso.datetime({ offset: true }),
2627
+ currency: z3.string(),
2628
+ customer_email: z3.nullable(z3.string()),
2629
+ customer_name: z3.nullable(z3.string()),
2630
+ customer_name_placeholder_confirmed: z3._default(z3.boolean(), false),
2631
+ customer_name_placeholder_confirmed_at: z3.nullable(z3.iso.datetime({ offset: true })),
2632
+ customer_phone: z3.nullable(z3.string()),
2633
+ description: z3.nullable(z3.string()),
2496
2634
  environment: zTrackingEnvironment,
2497
- external_id: z2.nullable(z2.string()),
2498
- id: z2.uuid(),
2499
- items: z2.array(zSaleItemEntitySchema),
2500
- metadata: z2.nullable(z2.record(z2.string(), z2.unknown())),
2501
- occurred_at: z2.iso.datetime({ offset: true }),
2502
- service_id: z2.nullable(z2.uuid()),
2503
- service_key: z2.nullable(z2.string()),
2504
- service_label: z2.nullable(z2.string()),
2505
- services: z2.array(zSaleServiceEntitySchema),
2506
- sms_automation: z2.nullable(zSaleSmsStatusSchema),
2507
- sms_consent: z2._default(z2.boolean(), false),
2508
- sms_consent_granted_at: z2.nullable(z2.iso.datetime({ offset: true })),
2635
+ external_id: z3.nullable(z3.string()),
2636
+ id: z3.uuid(),
2637
+ items: z3.array(zSaleItemEntitySchema),
2638
+ metadata: z3.nullable(z3.record(z3.string(), z3.unknown())),
2639
+ occurred_at: z3.iso.datetime({ offset: true }),
2640
+ service_id: z3.nullable(z3.uuid()),
2641
+ service_key: z3.nullable(z3.string()),
2642
+ service_label: z3.nullable(z3.string()),
2643
+ services: z3.array(zSaleServiceEntitySchema),
2644
+ sms_automation: z3.nullable(zSaleSmsStatusSchema),
2645
+ sms_consent: z3._default(z3.boolean(), false),
2646
+ sms_consent_granted_at: z3.nullable(z3.iso.datetime({ offset: true })),
2509
2647
  source: zSaleSource,
2510
- source_facts: z2.nullable(zAutoLeapSaleFacts),
2511
- updated_at: z2.iso.datetime({ offset: true }),
2512
- writeback: z2.nullable(zSaleWritebackStatusSchema)
2648
+ source_facts: z3.nullable(zAutoLeapSaleFacts),
2649
+ updated_at: z3.iso.datetime({ offset: true }),
2650
+ writeback: z3.nullable(zSaleWritebackStatusSchema)
2513
2651
  });
2514
2652
 
2515
2653
  // ../tracking-core/src/resources/sales/schema.ts
@@ -2518,11 +2656,11 @@ var saleServiceSchema = zSaleServiceInputSchema;
2518
2656
  var currencySchema = zSupportedCurrency;
2519
2657
  var SUPPORTED_CURRENCIES = currencySchema.options;
2520
2658
  var SALE_SOURCES = zSaleSource.options;
2521
- var centsSchema = z3.int().check(z3.gte(0));
2522
- var metadataSchema = z3.record(z3.string(), z3.unknown());
2523
- var customerNameSchema = z3.string().check(z3.maxLength(200));
2524
- var customerPhoneSchema = z3.string().check(z3.maxLength(64));
2525
- var customerEmailSchema = z3.email().check(z3.maxLength(320));
2659
+ var centsSchema = z4.int().check(z4.gte(0));
2660
+ var metadataSchema = z4.record(z4.string(), z4.unknown());
2661
+ var customerNameSchema = z4.string().check(z4.maxLength(200));
2662
+ var customerPhoneSchema = z4.string().check(z4.maxLength(64));
2663
+ var customerEmailSchema = z4.email().check(z4.maxLength(320));
2526
2664
  function addIssue(ctx, path, message) {
2527
2665
  ctx.issues.push({ code: "custom", input: ctx.value, path, message });
2528
2666
  }
@@ -2556,24 +2694,24 @@ function refineServiceXor(val, ctx, { requireAmount }) {
2556
2694
  );
2557
2695
  }
2558
2696
  }
2559
- var saleCreateSchema = z3.extend(zSaleCreateSchema, { items: z3._default(z3.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
2560
- var saleUpdateSchema = z3.strictObject({
2561
- description: z3.nullish(z3.string()),
2562
- service: z3.nullish(z3.string()),
2563
- services: z3.nullish(z3.array(saleServiceSchema)),
2564
- currency: z3.optional(currencySchema),
2565
- amount_total_cents: z3.optional(centsSchema),
2566
- occurred_at: z3.optional(z3.iso.datetime()),
2567
- items: z3.optional(z3.array(saleItemSchema)),
2568
- metadata: z3.nullish(metadataSchema),
2569
- customer_name: z3.nullish(customerNameSchema),
2697
+ var saleCreateSchema = z4.extend(zSaleCreateSchema, { items: z4._default(z4.array(saleItemSchema), []) }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: true }));
2698
+ var saleUpdateSchema = z4.strictObject({
2699
+ description: z4.nullish(z4.string()),
2700
+ service: z4.nullish(z4.string()),
2701
+ services: z4.nullish(z4.array(saleServiceSchema)),
2702
+ currency: z4.optional(currencySchema),
2703
+ amount_total_cents: z4.optional(centsSchema),
2704
+ occurred_at: z4.optional(z4.iso.datetime()),
2705
+ items: z4.optional(z4.array(saleItemSchema)),
2706
+ metadata: z4.nullish(metadataSchema),
2707
+ customer_name: z4.nullish(customerNameSchema),
2570
2708
  // Re-attest when changing a filler-looking name; the server clears the
2571
2709
  // prior attestation whenever `customer_name` changes.
2572
- customer_name_placeholder_confirmed: z3.optional(z3.boolean()),
2573
- customer_phone: z3.nullish(customerPhoneSchema),
2574
- customer_email: z3.nullish(customerEmailSchema),
2710
+ customer_name_placeholder_confirmed: z4.optional(z4.boolean()),
2711
+ customer_phone: z4.nullish(customerPhoneSchema),
2712
+ customer_email: z4.nullish(customerEmailSchema),
2575
2713
  // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
2576
- sms_consent: z3.optional(z3.boolean())
2714
+ sms_consent: z4.optional(z4.boolean())
2577
2715
  }).check((ctx) => refineServiceXor(ctx.value, ctx, { requireAmount: false }));
2578
2716
  var TRACKING_RANGES = ["24h", "7d", "30d"];
2579
2717
  var NAMED_RANGES = [
@@ -2596,125 +2734,31 @@ async function fetchServices(config) {
2596
2734
  }
2597
2735
 
2598
2736
  // ../tracking-core/src/phone-field.ts
2599
- function phoneField(name, raw, country) {
2600
- return { name, type: "phone", value: toE164(raw, country) };
2737
+ function phoneField(name, raw, country, label = null) {
2738
+ return { name, type: "phone", label, value: toE164(raw, country) };
2601
2739
  }
2602
2740
 
2603
- // ../tracking-core/src/lead-forms/lead-forms.gen.ts
2604
- var z4 = __toESM(require("zod/mini"));
2605
- var LEAD_FORM_REGISTRY_VERSION = 1;
2606
- var LEAD_FORM_KINDS = ["booking", "quote", "contact", "consult", "callback"];
2607
- var LEAD_FORM_ROLES = [
2608
- "given_name",
2609
- "family_name",
2610
- "phone",
2611
- "email",
2612
- "service",
2613
- "preferred_date",
2614
- "preferred_time",
2615
- "note",
2616
- "visit",
2617
- "intent",
2618
- "vehicle",
2619
- "drop_off",
2620
- "address",
2621
- "patient_type",
2622
- "matter",
2623
- "language",
2624
- "products",
2625
- "goal",
2626
- "business_type",
2627
- "lead_volume",
2628
- "attribution"
2629
- ];
2630
- var LEAD_FORM_PRIMITIVES = [
2631
- "string",
2632
- "text",
2633
- "enum",
2634
- "multi_enum",
2635
- "bool",
2636
- "date",
2637
- "time_window",
2638
- "phone",
2639
- "email",
2640
- "address",
2641
- "number"
2642
- ];
2643
- var leadFormPrimitiveSchemas = {
2644
- string: z4.string().check(z4.maxLength(120)),
2645
- text: z4.string().check(z4.maxLength(2e3)),
2646
- enum: z4.string().check(z4.regex(/^[a-z0-9-]{1,48}$/)),
2647
- multi_enum: z4.array(z4.string().check(z4.regex(/^[a-z0-9-]{1,48}$/))).check(z4.maxLength(10)),
2648
- bool: z4.boolean(),
2649
- date: z4.string().check(z4.regex(/^\d{4}-\d{2}-\d{2}$/)),
2650
- time_window: z4.strictObject({
2651
- start: z4.string().check(z4.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
2652
- end: z4.nullable(z4.string().check(z4.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
2653
- label: z4.optional(z4.string().check(z4.maxLength(60)))
2654
- }),
2655
- phone: z4.string().check(z4.regex(/^\+[1-9]\d{6,14}$/)),
2656
- email: z4.string().check(z4.maxLength(320), z4.regex(/^[^\s@]+@[^\s@]+$/)),
2657
- address: z4.strictObject({
2658
- line1: z4.string().check(z4.maxLength(120)),
2659
- line2: z4.optional(z4.string().check(z4.maxLength(120))),
2660
- city: z4.optional(z4.string().check(z4.maxLength(120))),
2661
- region: z4.optional(z4.string().check(z4.maxLength(120))),
2662
- postal_code: z4.optional(z4.string().check(z4.maxLength(120))),
2663
- country: z4.optional(z4.string().check(z4.maxLength(120)))
2664
- }),
2665
- number: z4.number()
2666
- };
2667
- var LEAD_FORM_ROLE_SPECS = {
2668
- given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
2669
- family_name: { primitive: "string", smsLabel: "", contactIdentity: true },
2670
- phone: { primitive: "phone", smsLabel: "", contactIdentity: true },
2671
- email: { primitive: "email", smsLabel: "", contactIdentity: true },
2672
- service: { primitive: "enum", smsLabel: "Service" },
2673
- preferred_date: { primitive: "date", smsLabel: "Date" },
2674
- preferred_time: { primitive: "time_window", smsLabel: "Time" },
2675
- note: { primitive: "text", smsLabel: "Note" },
2676
- visit: {
2677
- primitive: "enum",
2678
- smsLabel: "Visit",
2679
- options: [
2680
- { key: "in-shop", label: "In shop" },
2681
- { key: "in-home", label: "In home" },
2682
- { key: "remote", label: "Remote" },
2683
- { key: "on-site", label: "On site" }
2684
- ]
2685
- },
2686
- intent: {
2687
- primitive: "enum",
2688
- smsLabel: "Wants",
2689
- options: [
2690
- { key: "book", label: "Book" },
2691
- { key: "quote", label: "Quote" }
2692
- ]
2693
- },
2694
- vehicle: { primitive: "string", smsLabel: "Vehicle" },
2695
- drop_off: {
2696
- primitive: "enum",
2697
- smsLabel: "Drop-off",
2698
- options: [
2699
- { key: "wait-for-it", label: "Waiting" },
2700
- { key: "drop-off", label: "Dropping off" }
2701
- ]
2702
- },
2703
- address: { primitive: "address", smsLabel: "Address" },
2704
- patient_type: { primitive: "enum", smsLabel: "Patient" },
2705
- matter: { primitive: "enum", smsLabel: "Matter" },
2706
- language: { primitive: "enum", smsLabel: "Language" },
2707
- products: { primitive: "multi_enum", smsLabel: "Products" },
2708
- goal: { primitive: "enum", smsLabel: "Goal" },
2709
- business_type: { primitive: "enum", smsLabel: "Business" },
2710
- lead_volume: { primitive: "enum", smsLabel: "Lead volume" },
2711
- add_on: { primitive: "bool", smsLabel: "" },
2712
- attribution: { primitive: "enum", smsLabel: "", uninteresting: true }
2713
- };
2741
+ // ../tracking-core/src/lead-forms/submit.ts
2742
+ var import_mini = require("zod/mini");
2743
+ var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
2744
+ var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
2745
+ function slotFields(dateTime) {
2746
+ const written = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(dateTime);
2747
+ if (!written) {
2748
+ throw new TypeError(
2749
+ `slotFields needs the slot's wall time without an offset ("2026-10-13T09:30"), got "${dateTime}"`
2750
+ );
2751
+ }
2752
+ return { preferred_date: written[1], preferred_time: { start: written[2], end: null } };
2753
+ }
2754
+ function timeWindow(start, end, label) {
2755
+ return { start, end: end ?? null, ...label ? { label } : {} };
2756
+ }
2714
2757
 
2715
2758
  // src/index.ts
2716
2759
  var import_client2 = require("@aranova/tracking-react/client");
2717
2760
  var import_client3 = require("@aranova/tracking-react/client");
2761
+ var import_client4 = require("@aranova/tracking-react/client");
2718
2762
  // Annotate the CommonJS export names for ESM import in node:
2719
2763
  0 && (module.exports = {
2720
2764
  AdPlatformTracking,
@@ -2740,6 +2784,7 @@ var import_client3 = require("@aranova/tracking-react/client");
2740
2784
  buildBookingHandoffUrl,
2741
2785
  captureTrackingParamsFromLocation,
2742
2786
  clearStashedUserData,
2787
+ createLeadFormSubmit,
2743
2788
  createSalesClient,
2744
2789
  createTracking,
2745
2790
  createTrackingClientContext,
@@ -2775,7 +2820,9 @@ var import_client3 = require("@aranova/tracking-react/client");
2775
2820
  salesRequest,
2776
2821
  setConsentState,
2777
2822
  shopToday,
2823
+ slotFields,
2778
2824
  stashUserData,
2825
+ timeWindow,
2779
2826
  toE164,
2780
2827
  toMinor,
2781
2828
  useBookingHandoffUrl,