@aranova/tracking-next 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -10,24 +10,20 @@ function buildConsentPayload(state) {
10
10
  };
11
11
  }
12
12
  function getConsentState() {
13
- if (typeof window === "undefined")
14
- return "pending";
13
+ if (typeof window === "undefined") return "pending";
15
14
  const storedState = window.localStorage.getItem(CONSENT_STATE_KEY);
16
- if (storedState === "granted" || storedState === "denied")
17
- return storedState;
15
+ if (storedState === "granted" || storedState === "denied") return storedState;
18
16
  return "pending";
19
17
  }
20
18
  function setConsentState(state) {
21
- if (typeof window === "undefined")
22
- return;
19
+ if (typeof window === "undefined") return;
23
20
  window.localStorage.setItem(CONSENT_STATE_KEY, state);
24
21
  window.localStorage.setItem(CONSENT_TIMESTAMP_KEY, (/* @__PURE__ */ new Date()).toISOString());
25
22
  if (typeof window.gtag === "function")
26
23
  window.gtag("consent", "update", buildConsentPayload(state));
27
24
  }
28
25
  function resetConsent() {
29
- if (typeof window === "undefined")
30
- return;
26
+ if (typeof window === "undefined") return;
31
27
  window.localStorage.removeItem(CONSENT_STATE_KEY);
32
28
  window.localStorage.removeItem(CONSENT_TIMESTAMP_KEY);
33
29
  }
@@ -168,18 +164,15 @@ function getTrackingQueryValues(searchParams) {
168
164
  }, {});
169
165
  }
170
166
  function getCookieValueFromDocument(key) {
171
- if (typeof document === "undefined")
172
- return null;
167
+ if (typeof document === "undefined") return null;
173
168
  const cookies = document.cookie ? document.cookie.split("; ") : [];
174
169
  const match = cookies.find((cookie) => cookie.startsWith(`${key}=`));
175
- if (!match)
176
- return null;
170
+ if (!match) return null;
177
171
  const [, rawValue = ""] = match.split("=");
178
172
  return normalizeTrackingCookieValue(decodeURIComponent(rawValue));
179
173
  }
180
174
  function setTrackingCookie(key, value, maxAgeSeconds = TRACKING_COOKIE_MAX_AGE_SECONDS) {
181
- if (typeof document === "undefined")
182
- return;
175
+ if (typeof document === "undefined") return;
183
176
  const encodedValue = encodeURIComponent(value);
184
177
  document.cookie = `${key}=${encodedValue}; Max-Age=${maxAgeSeconds}; Path=/; SameSite=Lax`;
185
178
  }
@@ -219,18 +212,15 @@ function writeLocalStorage(key, value) {
219
212
  }
220
213
  }
221
214
  function getVisitorId() {
222
- if (typeof window === "undefined")
223
- return safeUuid();
215
+ if (typeof window === "undefined") return safeUuid();
224
216
  const existing = readLocalStorage(VISITOR_STORAGE_KEY);
225
- if (existing && existing.length > 0)
226
- return existing;
217
+ if (existing && existing.length > 0) return existing;
227
218
  const fresh = safeUuid();
228
219
  writeLocalStorage(VISITOR_STORAGE_KEY, fresh);
229
220
  return fresh;
230
221
  }
231
222
  function getOrRotateSessionId(now = Date.now()) {
232
- if (typeof window === "undefined")
233
- return { id: safeUuid(), isNew: true };
223
+ if (typeof window === "undefined") return { id: safeUuid(), isNew: true };
234
224
  const raw = readLocalStorage(SESSION_STORAGE_KEY);
235
225
  if (raw) {
236
226
  try {
@@ -303,8 +293,7 @@ function setLastFiredUrl(url) {
303
293
  writeSessionStorage(LAST_FIRED_URL_STORAGE_KEY, url);
304
294
  }
305
295
  function buildPageViewMetadata(referrerOverride) {
306
- if (typeof window === "undefined" || typeof document === "undefined")
307
- return null;
296
+ if (typeof window === "undefined" || typeof document === "undefined") return null;
308
297
  return pageViewMetadataSchema.parse({
309
298
  page: {
310
299
  title: document.title || null,
@@ -317,8 +306,7 @@ function buildPageViewMetadata(referrerOverride) {
317
306
  });
318
307
  }
319
308
  function fireManualPageView(client) {
320
- if (typeof window === "undefined")
321
- return;
309
+ if (typeof window === "undefined") return;
322
310
  const currentHref = window.location.href;
323
311
  const previousFiredUrl = getLastFiredUrl();
324
312
  const internalReferrer = previousFiredUrl !== null && previousFiredUrl !== currentHref ? previousFiredUrl : null;
@@ -420,8 +408,7 @@ function buildContext(surface, sdkVersion, packageName, environment, activeGtagI
420
408
  };
421
409
  }
422
410
  function readTrackingParams() {
423
- if (typeof window === "undefined")
424
- return createEmptyTrackingParams();
411
+ if (typeof window === "undefined") return createEmptyTrackingParams();
425
412
  try {
426
413
  captureTrackingParamsFromLocation();
427
414
  } catch {
@@ -436,8 +423,7 @@ function consentSnapshot() {
436
423
  }
437
424
  }
438
425
  async function postWithFetch(url, body, apiKey, identity, keepalive) {
439
- if (typeof fetch !== "function")
440
- return;
426
+ if (typeof fetch !== "function") return;
441
427
  try {
442
428
  await fetch(url, {
443
429
  method: "POST",
@@ -497,8 +483,7 @@ function createTrackingClient(config) {
497
483
  const visitorId = getVisitorId();
498
484
  const initialSession = getOrRotateSessionId();
499
485
  let sessionId = initialSession.id;
500
- if (typeof window !== "undefined")
501
- firstPage = window.location.href;
486
+ if (typeof window !== "undefined") firstPage = window.location.href;
502
487
  function enqueueHeartbeat() {
503
488
  const metadata = buildHeartbeatMetadata(
504
489
  config.surface,
@@ -524,7 +509,13 @@ function createTrackingClient(config) {
524
509
  }
525
510
  sessionId = rotated.id;
526
511
  const params = readTrackingParams();
527
- const context = buildContext(config.surface, sdkVersion, packageName, environment, activeGtagIds);
512
+ const context = buildContext(
513
+ config.surface,
514
+ sdkVersion,
515
+ packageName,
516
+ environment,
517
+ activeGtagIds
518
+ );
528
519
  return {
529
520
  session_id: sessionId,
530
521
  visitor_id: visitorId,
@@ -541,8 +532,7 @@ function createTrackingClient(config) {
541
532
  };
542
533
  }
543
534
  function scheduleFlush() {
544
- if (flushTimer !== null || destroyed)
545
- return;
535
+ if (flushTimer !== null || destroyed) return;
546
536
  flushTimer = setTimeout(() => {
547
537
  flushTimer = null;
548
538
  void flush();
@@ -555,8 +545,7 @@ function createTrackingClient(config) {
555
545
  }
556
546
  }
557
547
  async function flush() {
558
- if (queue.length === 0)
559
- return;
548
+ if (queue.length === 0) return;
560
549
  const events = queue.slice(0, HARD_MAX_BATCH);
561
550
  queue = queue.slice(events.length);
562
551
  clearScheduledFlush();
@@ -568,10 +557,8 @@ function createTrackingClient(config) {
568
557
  await postWithFetch(eventsUrl, serialized, config.apiKey, identityHeaders2, false);
569
558
  }
570
559
  function trackEvent(input) {
571
- if (destroyed)
572
- return;
573
- if (!input || typeof input.eventType !== "string" || input.eventType.length === 0)
574
- return;
560
+ if (destroyed) return;
561
+ if (!input || typeof input.eventType !== "string" || input.eventType.length === 0) return;
575
562
  const occurredAt = input.occurredAt instanceof Date ? input.occurredAt.toISOString() : typeof input.occurredAt === "string" ? input.occurredAt : (/* @__PURE__ */ new Date()).toISOString();
576
563
  queue.push({
577
564
  event_type: input.eventType,
@@ -586,8 +573,7 @@ function createTrackingClient(config) {
586
573
  }
587
574
  }
588
575
  function flushOnUnload() {
589
- if (queue.length === 0)
590
- return;
576
+ if (queue.length === 0) return;
591
577
  const events = queue.slice(0, HARD_MAX_BATCH);
592
578
  queue = queue.slice(events.length);
593
579
  clearScheduledFlush();
@@ -1127,21 +1113,40 @@ function createSalesClient(config) {
1127
1113
  return salesRequest(config, "POST", "/sales", body);
1128
1114
  },
1129
1115
  async list(query) {
1130
- const { cursor, limit, ...filters } = query ?? {};
1116
+ const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
1131
1117
  return salesRequest(config, "POST", "/sales/query", {
1132
1118
  filters,
1133
1119
  ...limit !== void 0 ? { limit } : {},
1134
- ...cursor !== void 0 ? { cursor } : {}
1120
+ ...cursor !== void 0 ? { cursor } : {},
1121
+ ...sort !== void 0 ? { sort } : {},
1122
+ ...order !== void 0 ? { order } : {},
1123
+ ...want_total !== void 0 ? { want_total } : {}
1135
1124
  });
1136
1125
  },
1137
1126
  async summary(query) {
1138
- const { range, include_categories, include_deleted_services, top_n, ...filters } = query;
1127
+ const {
1128
+ range,
1129
+ include_categories,
1130
+ include_deleted_services,
1131
+ top_n,
1132
+ since,
1133
+ until,
1134
+ timezone,
1135
+ granularity,
1136
+ compare_to,
1137
+ ...filters
1138
+ } = query;
1139
1139
  return salesRequest(config, "POST", "/sales/summary", {
1140
1140
  filters,
1141
- range,
1141
+ ...range !== void 0 ? { range } : {},
1142
1142
  ...include_categories !== void 0 ? { include_categories } : {},
1143
1143
  ...include_deleted_services !== void 0 ? { include_deleted_services } : {},
1144
- ...top_n !== void 0 ? { top_n } : {}
1144
+ ...top_n !== void 0 ? { top_n } : {},
1145
+ ...since !== void 0 ? { since } : {},
1146
+ ...until !== void 0 ? { until } : {},
1147
+ ...timezone !== void 0 ? { timezone } : {},
1148
+ ...granularity !== void 0 ? { granularity } : {},
1149
+ ...compare_to !== void 0 ? { compare_to } : {}
1145
1150
  });
1146
1151
  },
1147
1152
  async get(id) {
@@ -1152,15 +1157,53 @@ function createSalesClient(config) {
1152
1157
  },
1153
1158
  async delete(id) {
1154
1159
  await salesRequest(config, "DELETE", `/sales/${id}`);
1160
+ },
1161
+ customers: {
1162
+ async list(query) {
1163
+ const { segment, sort, order, cursor, limit, want_total, ...filters } = query ?? {};
1164
+ return salesRequest(config, "POST", "/customers/query", {
1165
+ filters,
1166
+ ...segment !== void 0 ? { segment } : {},
1167
+ ...sort !== void 0 ? { sort } : {},
1168
+ ...order !== void 0 ? { order } : {},
1169
+ ...cursor !== void 0 ? { cursor } : {},
1170
+ ...limit !== void 0 ? { limit } : {},
1171
+ ...want_total !== void 0 ? { want_total } : {}
1172
+ });
1173
+ },
1174
+ async get(id, options) {
1175
+ const params = new URLSearchParams();
1176
+ if (options?.include_sales !== void 0)
1177
+ params.set("include_sales", String(options.include_sales));
1178
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1179
+ if (options?.cursor != null) params.set("cursor", options.cursor);
1180
+ const qs = params.toString();
1181
+ return salesRequest(
1182
+ config,
1183
+ "GET",
1184
+ `/customers/${encodeURIComponent(id)}${qs ? `?${qs}` : ""}`
1185
+ );
1186
+ },
1187
+ async summary(query) {
1188
+ const { range, since, until, timezone, compare_to, ...filters } = query ?? {};
1189
+ return salesRequest(config, "POST", "/customers/summary", {
1190
+ filters,
1191
+ ...range !== void 0 ? { range } : {},
1192
+ ...since !== void 0 ? { since } : {},
1193
+ ...until !== void 0 ? { until } : {},
1194
+ ...timezone !== void 0 ? { timezone } : {},
1195
+ ...compare_to !== void 0 ? { compare_to } : {}
1196
+ });
1197
+ }
1198
+ },
1199
+ business: {
1200
+ async config() {
1201
+ return salesRequest(config, "GET", "/business/config");
1202
+ }
1155
1203
  }
1156
1204
  };
1157
1205
  }
1158
1206
 
1159
- // ../tracking-core/src/resources/services.ts
1160
- async function fetchServices(config) {
1161
- return salesRequest(config, "GET", "/services");
1162
- }
1163
-
1164
1207
  // ../tracking-core/src/resources/sales/money.ts
1165
1208
  var MINOR_UNIT_EXPONENT = {
1166
1209
  USD: 2,
@@ -1180,6 +1223,181 @@ function formatMoney(cents, currency, locale) {
1180
1223
  fromMinor(cents, currency)
1181
1224
  );
1182
1225
  }
1226
+ function formatDateInTz(iso, timeZone, opts, locale) {
1227
+ const date = new Date(iso);
1228
+ if (Number.isNaN(date.getTime())) return iso;
1229
+ return new Intl.DateTimeFormat(locale, {
1230
+ year: "numeric",
1231
+ month: "short",
1232
+ day: "2-digit",
1233
+ hour: "2-digit",
1234
+ minute: "2-digit",
1235
+ ...opts,
1236
+ timeZone
1237
+ }).format(date);
1238
+ }
1239
+
1240
+ // ../tracking-core/src/resources/sales/schema.ts
1241
+ import { z as z11 } from "zod";
1242
+ var SUPPORTED_CURRENCIES = ["USD", "CAD"];
1243
+ var TRACKING_ENVIRONMENTS = ["production", "development"];
1244
+ var currencySchema = z11.enum(SUPPORTED_CURRENCIES);
1245
+ var centsSchema = z11.number().int().nonnegative();
1246
+ var quantitySchema = z11.string().regex(/^\d+(\.\d{1,3})?$/);
1247
+ var metadataSchema = z11.record(z11.unknown());
1248
+ var saleItemSchema = z11.object({
1249
+ external_item_id: z11.string().nullable().optional(),
1250
+ name: z11.string().nullable().optional(),
1251
+ category: z11.string().nullable().optional(),
1252
+ quantity: quantitySchema,
1253
+ unit_price_cents: centsSchema,
1254
+ // Non-negativity validated on the wire — same contract as the other cents
1255
+ // fields — and backstopped by the DB CHECK.
1256
+ unit_cost_cents: centsSchema.nullable().optional()
1257
+ }).strict();
1258
+ var saleServiceSchema = z11.object({
1259
+ service: z11.string(),
1260
+ amount_cents: centsSchema
1261
+ }).strict();
1262
+ var customerNameSchema = z11.string().max(200);
1263
+ var customerPhoneSchema = z11.string().max(64);
1264
+ var customerEmailSchema = z11.string().max(320).email();
1265
+ function refineServiceXor(val, ctx, { requireAmount }) {
1266
+ if (val.services != null) {
1267
+ if (val.service != null) {
1268
+ ctx.addIssue({
1269
+ code: z11.ZodIssueCode.custom,
1270
+ message: "pass either `service` or `services`, not both",
1271
+ path: ["services"]
1272
+ });
1273
+ }
1274
+ if (val.services.length === 0) {
1275
+ ctx.addIssue({
1276
+ code: z11.ZodIssueCode.custom,
1277
+ message: "`services` must not be empty",
1278
+ path: ["services"]
1279
+ });
1280
+ }
1281
+ const keys = val.services.map((s) => s.service);
1282
+ if (new Set(keys).size !== keys.length) {
1283
+ ctx.addIssue({
1284
+ code: z11.ZodIssueCode.custom,
1285
+ message: "`services` must not list the same service more than once",
1286
+ path: ["services"]
1287
+ });
1288
+ }
1289
+ if (val.amount_total_cents != null) {
1290
+ const sum = val.services.reduce((acc, s) => acc + s.amount_cents, 0);
1291
+ if (val.amount_total_cents !== sum) {
1292
+ ctx.addIssue({
1293
+ code: z11.ZodIssueCode.custom,
1294
+ message: "amount_total_cents must equal the sum of the services amounts (omit it to derive it automatically)",
1295
+ path: ["amount_total_cents"]
1296
+ });
1297
+ }
1298
+ }
1299
+ } else if (requireAmount && val.amount_total_cents == null) {
1300
+ ctx.addIssue({
1301
+ code: z11.ZodIssueCode.custom,
1302
+ message: "amount_total_cents is required unless `services` is provided",
1303
+ path: ["amount_total_cents"]
1304
+ });
1305
+ }
1306
+ }
1307
+ var saleCreateSchema = z11.object({
1308
+ external_id: z11.string().nullable().optional(),
1309
+ description: z11.string().nullable().optional(),
1310
+ service: z11.string().nullable().optional(),
1311
+ services: z11.array(saleServiceSchema).nullable().optional(),
1312
+ currency: currencySchema,
1313
+ // Optional only because the plural `services` form derives it from the sum
1314
+ // (see refineServiceXor); the singular/serviceless path still requires it.
1315
+ amount_total_cents: centsSchema.nullable().optional(),
1316
+ occurred_at: z11.string().datetime(),
1317
+ environment: z11.enum(TRACKING_ENVIRONMENTS).default("production"),
1318
+ items: z11.array(saleItemSchema).default([]),
1319
+ metadata: metadataSchema.nullable().optional(),
1320
+ customer_name: customerNameSchema.nullable().optional(),
1321
+ customer_phone: customerPhoneSchema.nullable().optional(),
1322
+ customer_email: customerEmailSchema.nullable().optional()
1323
+ }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
1324
+ var saleUpdateSchema = z11.object({
1325
+ description: z11.string().nullable().optional(),
1326
+ service: z11.string().nullable().optional(),
1327
+ services: z11.array(saleServiceSchema).nullable().optional(),
1328
+ currency: currencySchema.optional(),
1329
+ amount_total_cents: centsSchema.optional(),
1330
+ occurred_at: z11.string().datetime().optional(),
1331
+ items: z11.array(saleItemSchema).optional(),
1332
+ metadata: metadataSchema.nullable().optional(),
1333
+ customer_name: customerNameSchema.nullable().optional(),
1334
+ customer_phone: customerPhoneSchema.nullable().optional(),
1335
+ customer_email: customerEmailSchema.nullable().optional()
1336
+ }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: false }));
1337
+ var TRACKING_RANGES = ["24h", "7d", "30d"];
1338
+ var NAMED_RANGES = [
1339
+ "today",
1340
+ "yesterday",
1341
+ "wtd",
1342
+ "mtd",
1343
+ "qtd",
1344
+ "ytd",
1345
+ "24h",
1346
+ "7d",
1347
+ "30d",
1348
+ "90d",
1349
+ "custom"
1350
+ ];
1351
+
1352
+ // ../tracking-core/src/resources/services.ts
1353
+ async function fetchServices(config) {
1354
+ return salesRequest(config, "GET", "/services");
1355
+ }
1356
+
1357
+ // ../tracking-core/src/phone.ts
1358
+ import { AsYouType, parsePhoneNumberFromString } from "libphonenumber-js";
1359
+ var DEFAULT_PHONE_COUNTRY = "CA";
1360
+ function parsePhone(raw, country) {
1361
+ const region = country ?? DEFAULT_PHONE_COUNTRY;
1362
+ const parsed = parsePhoneNumberFromString(raw ?? "", region);
1363
+ if (!parsed) {
1364
+ return { e164: null, national: "", international: "", country: region, isValid: false };
1365
+ }
1366
+ const isValid = parsed.isValid();
1367
+ return {
1368
+ // E.164 is only surfaced for a *valid* number — a possible-but-invalid input
1369
+ // (e.g. too few digits) still parses but must not be transmitted.
1370
+ e164: isValid ? parsed.number : null,
1371
+ national: parsed.formatNational(),
1372
+ international: parsed.formatInternational(),
1373
+ country: parsed.country ?? region,
1374
+ isValid
1375
+ };
1376
+ }
1377
+ function toE164(raw, country) {
1378
+ return parsePhone(raw, country).e164;
1379
+ }
1380
+ function formatPhone(value, format = "national", country) {
1381
+ const parsed = parsePhone(value, country);
1382
+ if (typeof format === "function") return format(parsed);
1383
+ switch (format) {
1384
+ case "international":
1385
+ return parsed.international || value;
1386
+ case "e164":
1387
+ return parsed.e164 ?? value;
1388
+ case "national":
1389
+ default:
1390
+ return parsed.national || value;
1391
+ }
1392
+ }
1393
+ function formatPhoneAsTyped(raw, country) {
1394
+ return new AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
1395
+ }
1396
+
1397
+ // ../tracking-core/src/phone-field.ts
1398
+ function phoneField(name, raw, country) {
1399
+ return { name, type: "phone", value: toE164(raw, country) };
1400
+ }
1183
1401
 
1184
1402
  // src/ConsentBanner.tsx
1185
1403
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -1448,19 +1666,108 @@ function GoogleAdsTracking(props) {
1448
1666
  import { usePathname, useSearchParams } from "next/navigation";
1449
1667
 
1450
1668
  // package.json
1451
- var version = "0.11.0";
1669
+ var version = "0.12.1";
1452
1670
 
1453
1671
  // src/factory.tsx
1672
+ import { createContext as createContext2, useContext as useContext2, useEffect as useEffect3, useMemo as useMemo2, useRef } from "react";
1673
+
1674
+ // ../tracking-core/src/phone-react.tsx
1454
1675
  import {
1455
1676
  createContext,
1677
+ forwardRef,
1678
+ useCallback as useCallback2,
1456
1679
  useContext,
1457
- useEffect as useEffect3,
1458
1680
  useMemo,
1459
- useRef
1681
+ useState as useState3
1460
1682
  } from "react";
1461
1683
  import { jsx as jsx3 } from "react/jsx-runtime";
1684
+ var _phoneConfigContext;
1685
+ function phoneConfigContext() {
1686
+ return _phoneConfigContext ?? (_phoneConfigContext = createContext(null));
1687
+ }
1688
+ function PhoneConfigProvider({
1689
+ value,
1690
+ children
1691
+ }) {
1692
+ const Ctx = phoneConfigContext();
1693
+ return /* @__PURE__ */ jsx3(Ctx.Provider, { value, children });
1694
+ }
1695
+ function usePhoneConfig() {
1696
+ const ctx = useContext(phoneConfigContext());
1697
+ return {
1698
+ defaultCountry: ctx?.defaultCountry ?? DEFAULT_PHONE_COUNTRY,
1699
+ display: ctx?.display ?? "national"
1700
+ };
1701
+ }
1702
+ function usePhoneField(opts = {}) {
1703
+ const cfg = usePhoneConfig();
1704
+ const country = opts.country ?? cfg.defaultCountry;
1705
+ const display = opts.display ?? cfg.display;
1706
+ const { onValueChange } = opts;
1707
+ const [value, setValue] = useState3(() => formatPhoneAsTyped(opts.defaultValue ?? "", country));
1708
+ const [touched, setTouched] = useState3(false);
1709
+ const parsed = useMemo(() => parsePhone(value, country), [value, country]);
1710
+ const onChange = useCallback2(
1711
+ (event) => {
1712
+ const next = formatPhoneAsTyped(event.target.value, country);
1713
+ setValue(next);
1714
+ onValueChange?.(parsePhone(next, country).e164);
1715
+ },
1716
+ [country, onValueChange]
1717
+ );
1718
+ const onBlur = useCallback2(
1719
+ (_event) => {
1720
+ setTouched(true);
1721
+ setValue((current) => {
1722
+ const p = parsePhone(current, country);
1723
+ return p.isValid ? formatPhone(current, display, country) : current;
1724
+ });
1725
+ },
1726
+ [country, display]
1727
+ );
1728
+ const error = touched && value.length > 0 && !parsed.isValid ? "Enter a valid phone number" : null;
1729
+ return {
1730
+ value,
1731
+ e164: parsed.e164,
1732
+ isValid: parsed.isValid,
1733
+ error,
1734
+ parsed,
1735
+ inputProps: { value, onChange, onBlur, type: "tel", inputMode: "tel", autoComplete: "tel" }
1736
+ };
1737
+ }
1738
+ var PhoneField = forwardRef(function PhoneField2({ country, value, defaultValue, onChange, onE164Change, ...rest }, ref) {
1739
+ const cfg = usePhoneConfig();
1740
+ const resolvedCountry = country ?? cfg.defaultCountry;
1741
+ const isControlled = value !== void 0;
1742
+ const [internal, setInternal] = useState3(
1743
+ () => formatPhoneAsTyped(defaultValue ?? "", resolvedCountry)
1744
+ );
1745
+ const handleChange = (event) => {
1746
+ const formatted = formatPhoneAsTyped(event.target.value, resolvedCountry);
1747
+ event.target.value = formatted;
1748
+ onE164Change?.(parsePhone(formatted, resolvedCountry).e164);
1749
+ if (!isControlled) setInternal(formatted);
1750
+ onChange?.(event);
1751
+ };
1752
+ const shown = isControlled ? formatPhoneAsTyped(value, resolvedCountry) : internal;
1753
+ return /* @__PURE__ */ jsx3(
1754
+ "input",
1755
+ {
1756
+ ...rest,
1757
+ ref,
1758
+ type: "tel",
1759
+ inputMode: "tel",
1760
+ autoComplete: "tel",
1761
+ value: shown,
1762
+ onChange: handleChange
1763
+ }
1764
+ );
1765
+ });
1766
+
1767
+ // src/factory.tsx
1768
+ import { jsx as jsx4 } from "react/jsx-runtime";
1462
1769
  function createTracking(options) {
1463
- const { apiKey, endpoint, triggers, environment, gtagIds, debug } = options;
1770
+ const { apiKey, endpoint, triggers, environment, gtagIds, debug, phone } = options;
1464
1771
  if (!apiKey || !endpoint) {
1465
1772
  if (apiKey || endpoint) {
1466
1773
  console.warn(
@@ -1476,17 +1783,17 @@ function createTracking(options) {
1476
1783
  getVisitorId: () => ""
1477
1784
  };
1478
1785
  return {
1479
- TrackingProvider: ({ children }) => children,
1786
+ TrackingProvider: ({ children }) => /* @__PURE__ */ jsx4(PhoneConfigProvider, { value: phone ?? null, children }),
1480
1787
  useTracking: () => noopClient
1481
1788
  };
1482
1789
  }
1483
- const TrackingContext = createContext(null);
1790
+ const TrackingContext = createContext2(null);
1484
1791
  const specificPageVisitConfig = triggers.automatic.specific_page_visit ?? null;
1485
1792
  const timeOnSiteConfig = triggers.automatic.time_on_site ?? null;
1486
1793
  function TrackingProvider({ children }) {
1487
1794
  const pathname = usePathname();
1488
1795
  const searchParams = useSearchParams();
1489
- const client = useMemo(
1796
+ const client = useMemo2(
1490
1797
  () => createTypedClient(
1491
1798
  getOrCreateTrackingClient({
1492
1799
  apiKey,
@@ -1645,10 +1952,10 @@ function createTracking(options) {
1645
1952
  }
1646
1953
  };
1647
1954
  }, []);
1648
- return /* @__PURE__ */ jsx3(TrackingContext.Provider, { value: client, children });
1955
+ return /* @__PURE__ */ jsx4(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ jsx4(PhoneConfigProvider, { value: phone ?? null, children }) });
1649
1956
  }
1650
1957
  function useTracking() {
1651
- const client = useContext(TrackingContext);
1958
+ const client = useContext2(TrackingContext);
1652
1959
  if (client === null) {
1653
1960
  throw new Error(
1654
1961
  "useTracking must be called inside a <TrackingProvider> returned by createTracking()"
@@ -1661,8 +1968,13 @@ function createTracking(options) {
1661
1968
  export {
1662
1969
  AranovaApiError,
1663
1970
  ConsentBanner,
1971
+ DEFAULT_PHONE_COUNTRY,
1664
1972
  GoogleAdsTracking,
1973
+ NAMED_RANGES,
1974
+ PhoneField,
1975
+ SUPPORTED_CURRENCIES,
1665
1976
  TRACKING_PARAM_KEYS,
1977
+ TRACKING_RANGES,
1666
1978
  captureTrackingParamsFromLocation,
1667
1979
  createSalesClient,
1668
1980
  createTracking,
@@ -1670,15 +1982,28 @@ export {
1670
1982
  createTrackingEventCreatePayload,
1671
1983
  createTrackingSessionUpsertPayload,
1672
1984
  fetchServices,
1985
+ formatDateInTz,
1673
1986
  formatMoney,
1987
+ formatPhone,
1988
+ formatPhoneAsTyped,
1674
1989
  fromMinor,
1675
1990
  getConsentState,
1991
+ parsePhone,
1992
+ phoneField,
1676
1993
  resetConsent,
1994
+ saleCreateSchema,
1995
+ saleItemSchema,
1996
+ saleServiceSchema,
1997
+ saleUpdateSchema,
1998
+ salesRequest,
1677
1999
  setConsentState,
2000
+ toE164,
1678
2001
  toMinor,
1679
2002
  useConsent,
1680
2003
  useConsentState,
1681
2004
  useGclid,
2005
+ usePhoneConfig,
2006
+ usePhoneField,
1682
2007
  useTrackingParams
1683
2008
  };
1684
2009
  //# sourceMappingURL=index.mjs.map