@aranova/tracking-next 0.10.0 → 0.12.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/index.mjs CHANGED
@@ -1127,21 +1127,40 @@ function createSalesClient(config) {
1127
1127
  return salesRequest(config, "POST", "/sales", body);
1128
1128
  },
1129
1129
  async list(query) {
1130
- const { cursor, limit, ...filters } = query ?? {};
1130
+ const { cursor, limit, sort, order, want_total, ...filters } = query ?? {};
1131
1131
  return salesRequest(config, "POST", "/sales/query", {
1132
1132
  filters,
1133
1133
  ...limit !== void 0 ? { limit } : {},
1134
- ...cursor !== void 0 ? { cursor } : {}
1134
+ ...cursor !== void 0 ? { cursor } : {},
1135
+ ...sort !== void 0 ? { sort } : {},
1136
+ ...order !== void 0 ? { order } : {},
1137
+ ...want_total !== void 0 ? { want_total } : {}
1135
1138
  });
1136
1139
  },
1137
1140
  async summary(query) {
1138
- const { range, include_categories, include_deleted_services, top_n, ...filters } = query;
1141
+ const {
1142
+ range,
1143
+ include_categories,
1144
+ include_deleted_services,
1145
+ top_n,
1146
+ since,
1147
+ until,
1148
+ timezone,
1149
+ granularity,
1150
+ compare_to,
1151
+ ...filters
1152
+ } = query;
1139
1153
  return salesRequest(config, "POST", "/sales/summary", {
1140
1154
  filters,
1141
- range,
1155
+ ...range !== void 0 ? { range } : {},
1142
1156
  ...include_categories !== void 0 ? { include_categories } : {},
1143
1157
  ...include_deleted_services !== void 0 ? { include_deleted_services } : {},
1144
- ...top_n !== void 0 ? { top_n } : {}
1158
+ ...top_n !== void 0 ? { top_n } : {},
1159
+ ...since !== void 0 ? { since } : {},
1160
+ ...until !== void 0 ? { until } : {},
1161
+ ...timezone !== void 0 ? { timezone } : {},
1162
+ ...granularity !== void 0 ? { granularity } : {},
1163
+ ...compare_to !== void 0 ? { compare_to } : {}
1145
1164
  });
1146
1165
  },
1147
1166
  async get(id) {
@@ -1152,6 +1171,49 @@ function createSalesClient(config) {
1152
1171
  },
1153
1172
  async delete(id) {
1154
1173
  await salesRequest(config, "DELETE", `/sales/${id}`);
1174
+ },
1175
+ customers: {
1176
+ async list(query) {
1177
+ const { segment, sort, order, cursor, limit, want_total, ...filters } = query ?? {};
1178
+ return salesRequest(config, "POST", "/customers/query", {
1179
+ filters,
1180
+ ...segment !== void 0 ? { segment } : {},
1181
+ ...sort !== void 0 ? { sort } : {},
1182
+ ...order !== void 0 ? { order } : {},
1183
+ ...cursor !== void 0 ? { cursor } : {},
1184
+ ...limit !== void 0 ? { limit } : {},
1185
+ ...want_total !== void 0 ? { want_total } : {}
1186
+ });
1187
+ },
1188
+ async get(id, options) {
1189
+ const params = new URLSearchParams();
1190
+ if (options?.include_sales !== void 0)
1191
+ params.set("include_sales", String(options.include_sales));
1192
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
1193
+ if (options?.cursor != null) params.set("cursor", options.cursor);
1194
+ const qs = params.toString();
1195
+ return salesRequest(
1196
+ config,
1197
+ "GET",
1198
+ `/customers/${encodeURIComponent(id)}${qs ? `?${qs}` : ""}`
1199
+ );
1200
+ },
1201
+ async summary(query) {
1202
+ const { range, since, until, timezone, compare_to, ...filters } = query ?? {};
1203
+ return salesRequest(config, "POST", "/customers/summary", {
1204
+ filters,
1205
+ ...range !== void 0 ? { range } : {},
1206
+ ...since !== void 0 ? { since } : {},
1207
+ ...until !== void 0 ? { until } : {},
1208
+ ...timezone !== void 0 ? { timezone } : {},
1209
+ ...compare_to !== void 0 ? { compare_to } : {}
1210
+ });
1211
+ }
1212
+ },
1213
+ business: {
1214
+ async config() {
1215
+ return salesRequest(config, "GET", "/business/config");
1216
+ }
1155
1217
  }
1156
1218
  };
1157
1219
  }
@@ -1180,6 +1242,64 @@ function formatMoney(cents, currency, locale) {
1180
1242
  fromMinor(cents, currency)
1181
1243
  );
1182
1244
  }
1245
+ function formatDateInTz(iso, timeZone, opts, locale) {
1246
+ const date = new Date(iso);
1247
+ if (Number.isNaN(date.getTime())) return iso;
1248
+ return new Intl.DateTimeFormat(locale, {
1249
+ year: "numeric",
1250
+ month: "short",
1251
+ day: "2-digit",
1252
+ hour: "2-digit",
1253
+ minute: "2-digit",
1254
+ ...opts,
1255
+ timeZone
1256
+ }).format(date);
1257
+ }
1258
+
1259
+ // ../tracking-core/src/phone.ts
1260
+ import { AsYouType, parsePhoneNumberFromString } from "libphonenumber-js";
1261
+ var DEFAULT_PHONE_COUNTRY = "CA";
1262
+ function parsePhone(raw, country) {
1263
+ const region = country ?? DEFAULT_PHONE_COUNTRY;
1264
+ const parsed = parsePhoneNumberFromString(raw ?? "", region);
1265
+ if (!parsed) {
1266
+ return { e164: null, national: "", international: "", country: region, isValid: false };
1267
+ }
1268
+ const isValid = parsed.isValid();
1269
+ return {
1270
+ // E.164 is only surfaced for a *valid* number — a possible-but-invalid input
1271
+ // (e.g. too few digits) still parses but must not be transmitted.
1272
+ e164: isValid ? parsed.number : null,
1273
+ national: parsed.formatNational(),
1274
+ international: parsed.formatInternational(),
1275
+ country: parsed.country ?? region,
1276
+ isValid
1277
+ };
1278
+ }
1279
+ function toE164(raw, country) {
1280
+ return parsePhone(raw, country).e164;
1281
+ }
1282
+ function formatPhone(value, format = "national", country) {
1283
+ const parsed = parsePhone(value, country);
1284
+ if (typeof format === "function") return format(parsed);
1285
+ switch (format) {
1286
+ case "international":
1287
+ return parsed.international || value;
1288
+ case "e164":
1289
+ return parsed.e164 ?? value;
1290
+ case "national":
1291
+ default:
1292
+ return parsed.national || value;
1293
+ }
1294
+ }
1295
+ function formatPhoneAsTyped(raw, country) {
1296
+ return new AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
1297
+ }
1298
+
1299
+ // ../tracking-core/src/phone-field.ts
1300
+ function phoneField(name, raw, country) {
1301
+ return { name, type: "phone", value: toE164(raw, country) };
1302
+ }
1183
1303
 
1184
1304
  // src/ConsentBanner.tsx
1185
1305
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -1448,19 +1568,104 @@ function GoogleAdsTracking(props) {
1448
1568
  import { usePathname, useSearchParams } from "next/navigation";
1449
1569
 
1450
1570
  // package.json
1451
- var version = "0.10.0";
1571
+ var version = "0.12.0";
1452
1572
 
1453
1573
  // src/factory.tsx
1574
+ import {
1575
+ createContext as createContext2,
1576
+ useContext as useContext2,
1577
+ useEffect as useEffect3,
1578
+ useMemo as useMemo2,
1579
+ useRef
1580
+ } from "react";
1581
+
1582
+ // ../tracking-core/src/phone-react.tsx
1454
1583
  import {
1455
1584
  createContext,
1585
+ forwardRef,
1586
+ useCallback as useCallback2,
1456
1587
  useContext,
1457
- useEffect as useEffect3,
1458
1588
  useMemo,
1459
- useRef
1589
+ useState as useState3
1460
1590
  } from "react";
1461
1591
  import { jsx as jsx3 } from "react/jsx-runtime";
1592
+ var PhoneConfigContext = createContext(null);
1593
+ function usePhoneConfig() {
1594
+ const ctx = useContext(PhoneConfigContext);
1595
+ return {
1596
+ defaultCountry: ctx?.defaultCountry ?? DEFAULT_PHONE_COUNTRY,
1597
+ display: ctx?.display ?? "national"
1598
+ };
1599
+ }
1600
+ function usePhoneField(opts = {}) {
1601
+ const cfg = usePhoneConfig();
1602
+ const country = opts.country ?? cfg.defaultCountry;
1603
+ const display = opts.display ?? cfg.display;
1604
+ const { onValueChange } = opts;
1605
+ const [value, setValue] = useState3(() => formatPhoneAsTyped(opts.defaultValue ?? "", country));
1606
+ const [touched, setTouched] = useState3(false);
1607
+ const parsed = useMemo(() => parsePhone(value, country), [value, country]);
1608
+ const onChange = useCallback2(
1609
+ (event) => {
1610
+ const next = formatPhoneAsTyped(event.target.value, country);
1611
+ setValue(next);
1612
+ onValueChange?.(parsePhone(next, country).e164);
1613
+ },
1614
+ [country, onValueChange]
1615
+ );
1616
+ const onBlur = useCallback2(
1617
+ (_event) => {
1618
+ setTouched(true);
1619
+ setValue((current) => {
1620
+ const p = parsePhone(current, country);
1621
+ return p.isValid ? formatPhone(current, display, country) : current;
1622
+ });
1623
+ },
1624
+ [country, display]
1625
+ );
1626
+ const error = touched && value.length > 0 && !parsed.isValid ? "Enter a valid phone number" : null;
1627
+ return {
1628
+ value,
1629
+ e164: parsed.e164,
1630
+ isValid: parsed.isValid,
1631
+ error,
1632
+ parsed,
1633
+ inputProps: { value, onChange, onBlur, type: "tel", inputMode: "tel", autoComplete: "tel" }
1634
+ };
1635
+ }
1636
+ var PhoneField = forwardRef(function PhoneField2({ country, value, defaultValue, onChange, onE164Change, ...rest }, ref) {
1637
+ const cfg = usePhoneConfig();
1638
+ const resolvedCountry = country ?? cfg.defaultCountry;
1639
+ const isControlled = value !== void 0;
1640
+ const [internal, setInternal] = useState3(
1641
+ () => formatPhoneAsTyped(defaultValue ?? "", resolvedCountry)
1642
+ );
1643
+ const handleChange = (event) => {
1644
+ const formatted = formatPhoneAsTyped(event.target.value, resolvedCountry);
1645
+ event.target.value = formatted;
1646
+ onE164Change?.(parsePhone(formatted, resolvedCountry).e164);
1647
+ if (!isControlled) setInternal(formatted);
1648
+ onChange?.(event);
1649
+ };
1650
+ const shown = isControlled ? formatPhoneAsTyped(value, resolvedCountry) : internal;
1651
+ return /* @__PURE__ */ jsx3(
1652
+ "input",
1653
+ {
1654
+ ...rest,
1655
+ ref,
1656
+ type: "tel",
1657
+ inputMode: "tel",
1658
+ autoComplete: "tel",
1659
+ value: shown,
1660
+ onChange: handleChange
1661
+ }
1662
+ );
1663
+ });
1664
+
1665
+ // src/factory.tsx
1666
+ import { jsx as jsx4 } from "react/jsx-runtime";
1462
1667
  function createTracking(options) {
1463
- const { apiKey, endpoint, triggers, environment, gtagIds, debug } = options;
1668
+ const { apiKey, endpoint, triggers, environment, gtagIds, debug, phone } = options;
1464
1669
  if (!apiKey || !endpoint) {
1465
1670
  if (apiKey || endpoint) {
1466
1671
  console.warn(
@@ -1476,17 +1681,17 @@ function createTracking(options) {
1476
1681
  getVisitorId: () => ""
1477
1682
  };
1478
1683
  return {
1479
- TrackingProvider: ({ children }) => children,
1684
+ TrackingProvider: ({ children }) => /* @__PURE__ */ jsx4(PhoneConfigContext.Provider, { value: phone ?? null, children }),
1480
1685
  useTracking: () => noopClient
1481
1686
  };
1482
1687
  }
1483
- const TrackingContext = createContext(null);
1688
+ const TrackingContext = createContext2(null);
1484
1689
  const specificPageVisitConfig = triggers.automatic.specific_page_visit ?? null;
1485
1690
  const timeOnSiteConfig = triggers.automatic.time_on_site ?? null;
1486
1691
  function TrackingProvider({ children }) {
1487
1692
  const pathname = usePathname();
1488
1693
  const searchParams = useSearchParams();
1489
- const client = useMemo(
1694
+ const client = useMemo2(
1490
1695
  () => createTypedClient(
1491
1696
  getOrCreateTrackingClient({
1492
1697
  apiKey,
@@ -1645,10 +1850,10 @@ function createTracking(options) {
1645
1850
  }
1646
1851
  };
1647
1852
  }, []);
1648
- return /* @__PURE__ */ jsx3(TrackingContext.Provider, { value: client, children });
1853
+ return /* @__PURE__ */ jsx4(TrackingContext.Provider, { value: client, children: /* @__PURE__ */ jsx4(PhoneConfigContext.Provider, { value: phone ?? null, children }) });
1649
1854
  }
1650
1855
  function useTracking() {
1651
- const client = useContext(TrackingContext);
1856
+ const client = useContext2(TrackingContext);
1652
1857
  if (client === null) {
1653
1858
  throw new Error(
1654
1859
  "useTracking must be called inside a <TrackingProvider> returned by createTracking()"
@@ -1661,7 +1866,10 @@ function createTracking(options) {
1661
1866
  export {
1662
1867
  AranovaApiError,
1663
1868
  ConsentBanner,
1869
+ DEFAULT_PHONE_COUNTRY,
1664
1870
  GoogleAdsTracking,
1871
+ PhoneConfigContext,
1872
+ PhoneField,
1665
1873
  TRACKING_PARAM_KEYS,
1666
1874
  captureTrackingParamsFromLocation,
1667
1875
  createSalesClient,
@@ -1670,15 +1878,23 @@ export {
1670
1878
  createTrackingEventCreatePayload,
1671
1879
  createTrackingSessionUpsertPayload,
1672
1880
  fetchServices,
1881
+ formatDateInTz,
1673
1882
  formatMoney,
1883
+ formatPhone,
1884
+ formatPhoneAsTyped,
1674
1885
  fromMinor,
1675
1886
  getConsentState,
1887
+ parsePhone,
1888
+ phoneField,
1676
1889
  resetConsent,
1677
1890
  setConsentState,
1891
+ toE164,
1678
1892
  toMinor,
1679
1893
  useConsent,
1680
1894
  useConsentState,
1681
1895
  useGclid,
1896
+ usePhoneConfig,
1897
+ usePhoneField,
1682
1898
  useTrackingParams
1683
1899
  };
1684
1900
  //# sourceMappingURL=index.mjs.map