@simpleapps-com/augur-web 0.2.14 → 0.2.16

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/gtm.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
 
4
- /** GTM script loading strategy. */
5
- type GtmStrategy = "default" | "afterInteractive" | "lazyOnload" | "worker";
4
+ /** Script loading strategy. */
5
+ type AnalyticsStrategy = "default" | "afterInteractive" | "lazyOnload";
6
6
  /** GA4 standard e-commerce event names. */
7
- type GtmEcommerceEvent = "view_item" | "view_item_list" | "select_item" | "add_to_cart" | "remove_from_cart" | "view_cart" | "begin_checkout" | "add_shipping_info" | "add_payment_info" | "purchase" | "refund";
7
+ type EcommerceEvent = "view_item" | "view_item_list" | "select_item" | "add_to_cart" | "remove_from_cart" | "view_cart" | "begin_checkout" | "add_shipping_info" | "add_payment_info" | "purchase" | "refund";
8
8
  /** GA4 e-commerce item shape. */
9
- interface GtmItem {
9
+ interface EcommerceItem {
10
10
  item_id: string;
11
11
  item_name?: string;
12
12
  item_brand?: string;
@@ -18,32 +18,32 @@ interface GtmItem {
18
18
  [key: string]: unknown;
19
19
  }
20
20
  /** Parameters for e-commerce events. */
21
- interface GtmEcommerceParams {
21
+ interface EcommerceParams {
22
22
  currency?: string;
23
23
  value?: number;
24
- items?: GtmItem[];
24
+ items?: EcommerceItem[];
25
25
  transaction_id?: string;
26
26
  shipping?: number;
27
27
  tax?: number;
28
28
  coupon?: string;
29
29
  [key: string]: unknown;
30
30
  }
31
- interface GtmProviderProps {
31
+ interface AnalyticsProviderProps {
32
32
  /** GTM container ID (e.g. "GTM-XXXXX"). */
33
33
  gtmId: string;
34
34
  /** Script loading strategy. Default: "afterInteractive". */
35
- strategy?: GtmStrategy;
35
+ strategy?: AnalyticsStrategy;
36
36
  /** Delay GTM loading until consent is granted. Default: false. */
37
37
  consentRequired?: boolean;
38
38
  /** Log dataLayer pushes to console. Default: false. */
39
39
  debug?: boolean;
40
40
  children: ReactNode;
41
41
  }
42
- interface GtmContextValue {
42
+ interface AnalyticsContextValue {
43
43
  /** Push a custom event to the dataLayer. */
44
- pushEvent: (event: string, params?: Record<string, unknown>) => void;
44
+ trackEvent: (event: string, params?: Record<string, unknown>) => void;
45
45
  /** Push a GA4 e-commerce event to the dataLayer. */
46
- pushEcommerceEvent: (event: GtmEcommerceEvent, params: GtmEcommerceParams) => void;
46
+ trackEcommerceEvent: (event: EcommerceEvent, params: EcommerceParams) => void;
47
47
  /** Grant consent — loads GTM if consentRequired was true. */
48
48
  grantConsent: () => void;
49
49
  /** Revoke consent. Does not unload GTM (scripts can't be unloaded). */
@@ -58,12 +58,32 @@ declare global {
58
58
  dataLayer?: Record<string, unknown>[];
59
59
  }
60
60
  }
61
- declare function GtmProvider({ gtmId, strategy, consentRequired, debug, children, }: GtmProviderProps): react_jsx_runtime.JSX.Element;
62
- declare function useGtm(): GtmContextValue;
63
- interface GtmNoscriptProps {
64
- /** GTM container ID (must match GtmProvider). */
61
+ declare function AnalyticsProvider({ gtmId, strategy, consentRequired, debug, children, }: AnalyticsProviderProps): react_jsx_runtime.JSX.Element;
62
+ declare function useAnalytics(): AnalyticsContextValue;
63
+ interface AnalyticsNoscriptProps {
64
+ /** GTM container ID (must match AnalyticsProvider). */
65
65
  gtmId: string;
66
66
  }
67
- declare function GtmNoscript({ gtmId }: GtmNoscriptProps): react_jsx_runtime.JSX.Element;
67
+ declare function AnalyticsNoscript({ gtmId }: AnalyticsNoscriptProps): react_jsx_runtime.JSX.Element;
68
+ /** @deprecated Use `AnalyticsStrategy` instead. */
69
+ type GtmStrategy = AnalyticsStrategy;
70
+ /** @deprecated Use `EcommerceEvent` instead. */
71
+ type GtmEcommerceEvent = EcommerceEvent;
72
+ /** @deprecated Use `EcommerceItem` instead. */
73
+ type GtmItem = EcommerceItem;
74
+ /** @deprecated Use `EcommerceParams` instead. */
75
+ type GtmEcommerceParams = EcommerceParams;
76
+ /** @deprecated Use `AnalyticsProviderProps` instead. */
77
+ type GtmProviderProps = AnalyticsProviderProps;
78
+ /** @deprecated Use `AnalyticsContextValue` instead. */
79
+ type GtmContextValue = AnalyticsContextValue;
80
+ /** @deprecated Use `AnalyticsNoscriptProps` instead. */
81
+ type GtmNoscriptProps = AnalyticsNoscriptProps;
82
+ /** @deprecated Use `AnalyticsProvider` instead. */
83
+ declare const GtmProvider: typeof AnalyticsProvider;
84
+ /** @deprecated Use `useAnalytics` instead. */
85
+ declare const useGtm: typeof useAnalytics;
86
+ /** @deprecated Use `AnalyticsNoscript` instead. */
87
+ declare const GtmNoscript: typeof AnalyticsNoscript;
68
88
 
69
- export { type GtmContextValue, type GtmEcommerceEvent, type GtmEcommerceParams, type GtmItem, GtmNoscript, type GtmNoscriptProps, GtmProvider, type GtmProviderProps, type GtmStrategy, useGtm };
89
+ export { type AnalyticsContextValue, AnalyticsNoscript, type AnalyticsNoscriptProps, AnalyticsProvider, type AnalyticsProviderProps, type AnalyticsStrategy, type EcommerceEvent, type EcommerceItem, type EcommerceParams, type GtmContextValue, type GtmEcommerceEvent, type GtmEcommerceParams, type GtmItem, GtmNoscript, type GtmNoscriptProps, GtmProvider, type GtmProviderProps, type GtmStrategy, useAnalytics, useGtm };
package/dist/gtm.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  useState
12
12
  } from "react";
13
13
  import { jsx } from "react/jsx-runtime";
14
- var GtmContext = createContext(null);
14
+ var AnalyticsContext = createContext(null);
15
15
  function getDataLayer() {
16
16
  if (typeof window === "undefined") return [];
17
17
  if (!window.dataLayer) window.dataLayer = [];
@@ -28,15 +28,12 @@ function injectGtmScript(gtmId, strategy) {
28
28
  if (strategy === "lazyOnload") {
29
29
  script.async = true;
30
30
  script.defer = true;
31
- } else if (strategy === "worker") {
32
- script.type = "text/partytown";
33
- script.async = true;
34
31
  } else {
35
32
  script.async = true;
36
33
  }
37
34
  document.head.appendChild(script);
38
35
  }
39
- function GtmProvider({
36
+ function AnalyticsProvider({
40
37
  gtmId,
41
38
  strategy = "afterInteractive",
42
39
  consentRequired = false,
@@ -67,22 +64,22 @@ function GtmProvider({
67
64
  if (hasConsent && !injectedRef.current && typeof window !== "undefined") {
68
65
  loadGtm();
69
66
  }
70
- const pushEvent = useCallback(
67
+ const trackEvent = useCallback(
71
68
  (event, params) => {
72
69
  const entry = { event, ...params };
73
70
  if (debug) {
74
- console.log("[GTM]", entry);
71
+ console.log("[Analytics]", entry);
75
72
  }
76
73
  getDataLayer().push(entry);
77
74
  },
78
75
  [debug]
79
76
  );
80
- const pushEcommerceEvent = useCallback(
77
+ const trackEcommerceEvent = useCallback(
81
78
  (event, params) => {
82
79
  getDataLayer().push({ ecommerce: null });
83
80
  const entry = { event, ecommerce: params };
84
81
  if (debug) {
85
- console.log("[GTM ecommerce]", entry);
82
+ console.log("[Analytics ecommerce]", entry);
86
83
  }
87
84
  getDataLayer().push(entry);
88
85
  },
@@ -97,32 +94,32 @@ function GtmProvider({
97
94
  }, []);
98
95
  const value = useMemo(
99
96
  () => ({
100
- pushEvent,
101
- pushEcommerceEvent,
97
+ trackEvent,
98
+ trackEcommerceEvent,
102
99
  grantConsent,
103
100
  revokeConsent,
104
101
  hasConsent,
105
102
  isLoaded
106
103
  }),
107
104
  [
108
- pushEvent,
109
- pushEcommerceEvent,
105
+ trackEvent,
106
+ trackEcommerceEvent,
110
107
  grantConsent,
111
108
  revokeConsent,
112
109
  hasConsent,
113
110
  isLoaded
114
111
  ]
115
112
  );
116
- return /* @__PURE__ */ jsx(GtmContext.Provider, { value, children });
113
+ return /* @__PURE__ */ jsx(AnalyticsContext.Provider, { value, children });
117
114
  }
118
- function useGtm() {
119
- const context = useContext(GtmContext);
115
+ function useAnalytics() {
116
+ const context = useContext(AnalyticsContext);
120
117
  if (!context) {
121
- throw new Error("useGtm must be used within a <GtmProvider>");
118
+ throw new Error("useAnalytics must be used within an <AnalyticsProvider>");
122
119
  }
123
120
  return context;
124
121
  }
125
- function GtmNoscript({ gtmId }) {
122
+ function AnalyticsNoscript({ gtmId }) {
126
123
  return /* @__PURE__ */ jsx("noscript", { children: /* @__PURE__ */ jsx(
127
124
  "iframe",
128
125
  {
@@ -134,9 +131,15 @@ function GtmNoscript({ gtmId }) {
134
131
  }
135
132
  ) });
136
133
  }
134
+ var GtmProvider = AnalyticsProvider;
135
+ var useGtm = useAnalytics;
136
+ var GtmNoscript = AnalyticsNoscript;
137
137
  export {
138
+ AnalyticsNoscript,
139
+ AnalyticsProvider,
138
140
  GtmNoscript,
139
141
  GtmProvider,
142
+ useAnalytics,
140
143
  useGtm
141
144
  };
142
145
  //# sourceMappingURL=gtm.js.map
package/dist/gtm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/gtm.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** GTM script loading strategy. */\nexport type GtmStrategy =\n | \"default\"\n | \"afterInteractive\"\n | \"lazyOnload\"\n | \"worker\";\n\n/** GA4 standard e-commerce event names. */\nexport type GtmEcommerceEvent =\n | \"view_item\"\n | \"view_item_list\"\n | \"select_item\"\n | \"add_to_cart\"\n | \"remove_from_cart\"\n | \"view_cart\"\n | \"begin_checkout\"\n | \"add_shipping_info\"\n | \"add_payment_info\"\n | \"purchase\"\n | \"refund\";\n\n/** GA4 e-commerce item shape. */\nexport interface GtmItem {\n item_id: string;\n item_name?: string;\n item_brand?: string;\n item_category?: string;\n item_variant?: string;\n price?: number;\n quantity?: number;\n index?: number;\n [key: string]: unknown;\n}\n\n/** Parameters for e-commerce events. */\nexport interface GtmEcommerceParams {\n currency?: string;\n value?: number;\n items?: GtmItem[];\n transaction_id?: string;\n shipping?: number;\n tax?: number;\n coupon?: string;\n [key: string]: unknown;\n}\n\nexport interface GtmProviderProps {\n /** GTM container ID (e.g. \"GTM-XXXXX\"). */\n gtmId: string;\n /** Script loading strategy. Default: \"afterInteractive\". */\n strategy?: GtmStrategy;\n /** Delay GTM loading until consent is granted. Default: false. */\n consentRequired?: boolean;\n /** Log dataLayer pushes to console. Default: false. */\n debug?: boolean;\n children: ReactNode;\n}\n\nexport interface GtmContextValue {\n /** Push a custom event to the dataLayer. */\n pushEvent: (event: string, params?: Record<string, unknown>) => void;\n /** Push a GA4 e-commerce event to the dataLayer. */\n pushEcommerceEvent: (\n event: GtmEcommerceEvent,\n params: GtmEcommerceParams,\n ) => void;\n /** Grant consent — loads GTM if consentRequired was true. */\n grantConsent: () => void;\n /** Revoke consent. Does not unload GTM (scripts can't be unloaded). */\n revokeConsent: () => void;\n /** Whether consent has been granted. */\n hasConsent: boolean;\n /** Whether the GTM script has been injected. */\n isLoaded: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst GtmContext = createContext<GtmContextValue | null>(null);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ndeclare global {\n interface Window {\n dataLayer?: Record<string, unknown>[];\n }\n}\n\nfunction getDataLayer(): Record<string, unknown>[] {\n if (typeof window === \"undefined\") return [];\n if (!window.dataLayer) window.dataLayer = [];\n return window.dataLayer;\n}\n\nfunction injectGtmScript(gtmId: string, strategy: GtmStrategy): void {\n if (typeof document === \"undefined\") return;\n\n // Prevent double-injection\n if (document.getElementById(\"gtm-script\")) return;\n\n const dataLayer = getDataLayer();\n dataLayer.push({ \"gtm.start\": new Date().getTime(), event: \"gtm.js\" });\n\n const script = document.createElement(\"script\");\n script.id = \"gtm-script\";\n script.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(gtmId)}`;\n\n if (strategy === \"lazyOnload\") {\n script.async = true;\n script.defer = true;\n } else if (strategy === \"worker\") {\n script.type = \"text/partytown\";\n script.async = true;\n } else {\n // \"default\" and \"afterInteractive\"\n script.async = true;\n }\n\n document.head.appendChild(script);\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport function GtmProvider({\n gtmId,\n strategy = \"afterInteractive\",\n consentRequired = false,\n debug = false,\n children,\n}: GtmProviderProps) {\n const [hasConsent, setHasConsent] = useState(!consentRequired);\n const [isLoaded, setIsLoaded] = useState(false);\n const injectedRef = useRef(false);\n\n const loadGtm = useCallback(() => {\n if (injectedRef.current) return;\n injectedRef.current = true;\n\n if (strategy === \"lazyOnload\" && typeof requestIdleCallback === \"function\") {\n requestIdleCallback(() => {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n });\n } else if (strategy === \"afterInteractive\") {\n // Defer to after hydration\n setTimeout(() => {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n }, 0);\n } else {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n }\n }, [gtmId, strategy]);\n\n // Auto-load when consent is not required or already granted\n if (hasConsent && !injectedRef.current && typeof window !== \"undefined\") {\n loadGtm();\n }\n\n const pushEvent = useCallback(\n (event: string, params?: Record<string, unknown>) => {\n const entry = { event, ...params };\n if (debug) {\n console.log(\"[GTM]\", entry);\n }\n getDataLayer().push(entry);\n },\n [debug],\n );\n\n const pushEcommerceEvent = useCallback(\n (event: GtmEcommerceEvent, params: GtmEcommerceParams) => {\n // Clear previous ecommerce data per GA4 best practices\n getDataLayer().push({ ecommerce: null });\n const entry = { event, ecommerce: params };\n if (debug) {\n console.log(\"[GTM ecommerce]\", entry);\n }\n getDataLayer().push(entry);\n },\n [debug],\n );\n\n const grantConsent = useCallback(() => {\n setHasConsent(true);\n loadGtm();\n }, [loadGtm]);\n\n const revokeConsent = useCallback(() => {\n setHasConsent(false);\n }, []);\n\n const value = useMemo<GtmContextValue>(\n () => ({\n pushEvent,\n pushEcommerceEvent,\n grantConsent,\n revokeConsent,\n hasConsent,\n isLoaded,\n }),\n [\n pushEvent,\n pushEcommerceEvent,\n grantConsent,\n revokeConsent,\n hasConsent,\n isLoaded,\n ],\n );\n\n return <GtmContext.Provider value={value}>{children}</GtmContext.Provider>;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useGtm(): GtmContextValue {\n const context = useContext(GtmContext);\n if (!context) {\n throw new Error(\"useGtm must be used within a <GtmProvider>\");\n }\n return context;\n}\n\n// ---------------------------------------------------------------------------\n// Noscript\n// ---------------------------------------------------------------------------\n\nexport interface GtmNoscriptProps {\n /** GTM container ID (must match GtmProvider). */\n gtmId: string;\n}\n\nexport function GtmNoscript({ gtmId }: GtmNoscriptProps) {\n return (\n <noscript>\n <iframe\n src={`https://www.googletagmanager.com/ns.html?id=${encodeURIComponent(gtmId)}`}\n height=\"0\"\n width=\"0\"\n style={{ display: \"none\", visibility: \"hidden\" }}\n title=\"Google Tag Manager\"\n />\n </noscript>\n );\n}\n"],"mappings":";;;;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAiOE;AA1IT,IAAM,aAAa,cAAsC,IAAI;AAY7D,SAAS,eAA0C;AACjD,MAAI,OAAO,WAAW,YAAa,QAAO,CAAC;AAC3C,MAAI,CAAC,OAAO,UAAW,QAAO,YAAY,CAAC;AAC3C,SAAO,OAAO;AAChB;AAEA,SAAS,gBAAgB,OAAe,UAA6B;AACnE,MAAI,OAAO,aAAa,YAAa;AAGrC,MAAI,SAAS,eAAe,YAAY,EAAG;AAE3C,QAAM,YAAY,aAAa;AAC/B,YAAU,KAAK,EAAE,cAAa,oBAAI,KAAK,GAAE,QAAQ,GAAG,OAAO,SAAS,CAAC;AAErE,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,KAAK;AACZ,SAAO,MAAM,8CAA8C,mBAAmB,KAAK,CAAC;AAEpF,MAAI,aAAa,cAAc;AAC7B,WAAO,QAAQ;AACf,WAAO,QAAQ;AAAA,EACjB,WAAW,aAAa,UAAU;AAChC,WAAO,OAAO;AACd,WAAO,QAAQ;AAAA,EACjB,OAAO;AAEL,WAAO,QAAQ;AAAA,EACjB;AAEA,WAAS,KAAK,YAAY,MAAM;AAClC;AAMO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR;AACF,GAAqB;AACnB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC,eAAe;AAC7D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,cAAc,OAAO,KAAK;AAEhC,QAAM,UAAU,YAAY,MAAM;AAChC,QAAI,YAAY,QAAS;AACzB,gBAAY,UAAU;AAEtB,QAAI,aAAa,gBAAgB,OAAO,wBAAwB,YAAY;AAC1E,0BAAoB,MAAM;AACxB,wBAAgB,OAAO,QAAQ;AAC/B,oBAAY,IAAI;AAAA,MAClB,CAAC;AAAA,IACH,WAAW,aAAa,oBAAoB;AAE1C,iBAAW,MAAM;AACf,wBAAgB,OAAO,QAAQ;AAC/B,oBAAY,IAAI;AAAA,MAClB,GAAG,CAAC;AAAA,IACN,OAAO;AACL,sBAAgB,OAAO,QAAQ;AAC/B,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,CAAC;AAGpB,MAAI,cAAc,CAAC,YAAY,WAAW,OAAO,WAAW,aAAa;AACvE,YAAQ;AAAA,EACV;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,OAAe,WAAqC;AACnD,YAAM,QAAQ,EAAE,OAAO,GAAG,OAAO;AACjC,UAAI,OAAO;AACT,gBAAQ,IAAI,SAAS,KAAK;AAAA,MAC5B;AACA,mBAAa,EAAE,KAAK,KAAK;AAAA,IAC3B;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,qBAAqB;AAAA,IACzB,CAAC,OAA0B,WAA+B;AAExD,mBAAa,EAAE,KAAK,EAAE,WAAW,KAAK,CAAC;AACvC,YAAM,QAAQ,EAAE,OAAO,WAAW,OAAO;AACzC,UAAI,OAAO;AACT,gBAAQ,IAAI,mBAAmB,KAAK;AAAA,MACtC;AACA,mBAAa,EAAE,KAAK,KAAK;AAAA,IAC3B;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,eAAe,YAAY,MAAM;AACrC,kBAAc,IAAI;AAClB,YAAQ;AAAA,EACV,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,gBAAgB,YAAY,MAAM;AACtC,kBAAc,KAAK;AAAA,EACrB,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,oBAAC,WAAW,UAAX,EAAoB,OAAe,UAAS;AACtD;AAMO,SAAS,SAA0B;AACxC,QAAM,UAAU,WAAW,UAAU;AACrC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AACT;AAWO,SAAS,YAAY,EAAE,MAAM,GAAqB;AACvD,SACE,oBAAC,cACC;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,+CAA+C,mBAAmB,KAAK,CAAC;AAAA,MAC7E,QAAO;AAAA,MACP,OAAM;AAAA,MACN,OAAO,EAAE,SAAS,QAAQ,YAAY,SAAS;AAAA,MAC/C,OAAM;AAAA;AAAA,EACR,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/gtm.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Script loading strategy. */\nexport type AnalyticsStrategy = \"default\" | \"afterInteractive\" | \"lazyOnload\";\n\n/** GA4 standard e-commerce event names. */\nexport type EcommerceEvent =\n | \"view_item\"\n | \"view_item_list\"\n | \"select_item\"\n | \"add_to_cart\"\n | \"remove_from_cart\"\n | \"view_cart\"\n | \"begin_checkout\"\n | \"add_shipping_info\"\n | \"add_payment_info\"\n | \"purchase\"\n | \"refund\";\n\n/** GA4 e-commerce item shape. */\nexport interface EcommerceItem {\n item_id: string;\n item_name?: string;\n item_brand?: string;\n item_category?: string;\n item_variant?: string;\n price?: number;\n quantity?: number;\n index?: number;\n [key: string]: unknown;\n}\n\n/** Parameters for e-commerce events. */\nexport interface EcommerceParams {\n currency?: string;\n value?: number;\n items?: EcommerceItem[];\n transaction_id?: string;\n shipping?: number;\n tax?: number;\n coupon?: string;\n [key: string]: unknown;\n}\n\nexport interface AnalyticsProviderProps {\n /** GTM container ID (e.g. \"GTM-XXXXX\"). */\n gtmId: string;\n /** Script loading strategy. Default: \"afterInteractive\". */\n strategy?: AnalyticsStrategy;\n /** Delay GTM loading until consent is granted. Default: false. */\n consentRequired?: boolean;\n /** Log dataLayer pushes to console. Default: false. */\n debug?: boolean;\n children: ReactNode;\n}\n\nexport interface AnalyticsContextValue {\n /** Push a custom event to the dataLayer. */\n trackEvent: (event: string, params?: Record<string, unknown>) => void;\n /** Push a GA4 e-commerce event to the dataLayer. */\n trackEcommerceEvent: (\n event: EcommerceEvent,\n params: EcommerceParams,\n ) => void;\n /** Grant consent — loads GTM if consentRequired was true. */\n grantConsent: () => void;\n /** Revoke consent. Does not unload GTM (scripts can't be unloaded). */\n revokeConsent: () => void;\n /** Whether consent has been granted. */\n hasConsent: boolean;\n /** Whether the GTM script has been injected. */\n isLoaded: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst AnalyticsContext = createContext<AnalyticsContextValue | null>(null);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ndeclare global {\n interface Window {\n dataLayer?: Record<string, unknown>[];\n }\n}\n\nfunction getDataLayer(): Record<string, unknown>[] {\n if (typeof window === \"undefined\") return [];\n if (!window.dataLayer) window.dataLayer = [];\n return window.dataLayer;\n}\n\nfunction injectGtmScript(\n gtmId: string,\n strategy: AnalyticsStrategy,\n): void {\n if (typeof document === \"undefined\") return;\n\n // Prevent double-injection\n if (document.getElementById(\"gtm-script\")) return;\n\n const dataLayer = getDataLayer();\n dataLayer.push({ \"gtm.start\": new Date().getTime(), event: \"gtm.js\" });\n\n const script = document.createElement(\"script\");\n script.id = \"gtm-script\";\n script.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(gtmId)}`;\n\n if (strategy === \"lazyOnload\") {\n script.async = true;\n script.defer = true;\n } else {\n // \"default\" and \"afterInteractive\"\n script.async = true;\n }\n\n document.head.appendChild(script);\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport function AnalyticsProvider({\n gtmId,\n strategy = \"afterInteractive\",\n consentRequired = false,\n debug = false,\n children,\n}: AnalyticsProviderProps) {\n const [hasConsent, setHasConsent] = useState(!consentRequired);\n const [isLoaded, setIsLoaded] = useState(false);\n const injectedRef = useRef(false);\n\n const loadGtm = useCallback(() => {\n if (injectedRef.current) return;\n injectedRef.current = true;\n\n if (strategy === \"lazyOnload\" && typeof requestIdleCallback === \"function\") {\n requestIdleCallback(() => {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n });\n } else if (strategy === \"afterInteractive\") {\n // Defer to after hydration\n setTimeout(() => {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n }, 0);\n } else {\n injectGtmScript(gtmId, strategy);\n setIsLoaded(true);\n }\n }, [gtmId, strategy]);\n\n // Auto-load when consent is not required or already granted\n if (hasConsent && !injectedRef.current && typeof window !== \"undefined\") {\n loadGtm();\n }\n\n const trackEvent = useCallback(\n (event: string, params?: Record<string, unknown>) => {\n const entry = { event, ...params };\n if (debug) {\n console.log(\"[Analytics]\", entry);\n }\n getDataLayer().push(entry);\n },\n [debug],\n );\n\n const trackEcommerceEvent = useCallback(\n (event: EcommerceEvent, params: EcommerceParams) => {\n // Clear previous ecommerce data per GA4 best practices\n getDataLayer().push({ ecommerce: null });\n const entry = { event, ecommerce: params };\n if (debug) {\n console.log(\"[Analytics ecommerce]\", entry);\n }\n getDataLayer().push(entry);\n },\n [debug],\n );\n\n const grantConsent = useCallback(() => {\n setHasConsent(true);\n loadGtm();\n }, [loadGtm]);\n\n const revokeConsent = useCallback(() => {\n setHasConsent(false);\n }, []);\n\n const value = useMemo<AnalyticsContextValue>(\n () => ({\n trackEvent,\n trackEcommerceEvent,\n grantConsent,\n revokeConsent,\n hasConsent,\n isLoaded,\n }),\n [\n trackEvent,\n trackEcommerceEvent,\n grantConsent,\n revokeConsent,\n hasConsent,\n isLoaded,\n ],\n );\n\n return (\n <AnalyticsContext.Provider value={value}>\n {children}\n </AnalyticsContext.Provider>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useAnalytics(): AnalyticsContextValue {\n const context = useContext(AnalyticsContext);\n if (!context) {\n throw new Error(\"useAnalytics must be used within an <AnalyticsProvider>\");\n }\n return context;\n}\n\n// ---------------------------------------------------------------------------\n// Noscript\n// ---------------------------------------------------------------------------\n\nexport interface AnalyticsNoscriptProps {\n /** GTM container ID (must match AnalyticsProvider). */\n gtmId: string;\n}\n\nexport function AnalyticsNoscript({ gtmId }: AnalyticsNoscriptProps) {\n return (\n <noscript>\n <iframe\n src={`https://www.googletagmanager.com/ns.html?id=${encodeURIComponent(gtmId)}`}\n height=\"0\"\n width=\"0\"\n style={{ display: \"none\", visibility: \"hidden\" }}\n title=\"Google Tag Manager\"\n />\n </noscript>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Backward-compatible aliases (from #59 GtmProvider)\n// ---------------------------------------------------------------------------\n\n/** @deprecated Use `AnalyticsStrategy` instead. */\nexport type GtmStrategy = AnalyticsStrategy;\n/** @deprecated Use `EcommerceEvent` instead. */\nexport type GtmEcommerceEvent = EcommerceEvent;\n/** @deprecated Use `EcommerceItem` instead. */\nexport type GtmItem = EcommerceItem;\n/** @deprecated Use `EcommerceParams` instead. */\nexport type GtmEcommerceParams = EcommerceParams;\n/** @deprecated Use `AnalyticsProviderProps` instead. */\nexport type GtmProviderProps = AnalyticsProviderProps;\n/** @deprecated Use `AnalyticsContextValue` instead. */\nexport type GtmContextValue = AnalyticsContextValue;\n/** @deprecated Use `AnalyticsNoscriptProps` instead. */\nexport type GtmNoscriptProps = AnalyticsNoscriptProps;\n\n/** @deprecated Use `AnalyticsProvider` instead. */\nexport const GtmProvider = AnalyticsProvider;\n/** @deprecated Use `useAnalytics` instead. */\nexport const useGtm = useAnalytics;\n/** @deprecated Use `AnalyticsNoscript` instead. */\nexport const GtmNoscript = AnalyticsNoscript;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
+
3
+
4
+ var _chunkVT4JLAIEcjs = require('./chunk-VT4JLAIE.cjs');
5
+
6
+
7
+ exports.createFormatPrice = _chunkVT4JLAIEcjs.createFormatPrice;
8
+ //# sourceMappingURL=price-format.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs"],"names":[],"mappings":"AAAA,qFAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,gEAAC","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs"}
@@ -0,0 +1,17 @@
1
+ interface PriceFormatConfig {
2
+ /** ISO 4217 currency code. Default: `"USD"`. */
3
+ currency?: string;
4
+ /** BCP 47 locale. Default: `"en-US"`. */
5
+ locale?: string;
6
+ /** Decimal places. Default: `2`. */
7
+ precision?: number;
8
+ }
9
+ interface FormatPriceOptions {
10
+ /** Override precision for this call. */
11
+ precision?: number;
12
+ /** Multiply value by quantity before formatting. */
13
+ quantity?: number;
14
+ }
15
+ declare function createFormatPrice(config?: PriceFormatConfig): (value: number, options?: FormatPriceOptions) => string;
16
+
17
+ export { type FormatPriceOptions, type PriceFormatConfig, createFormatPrice };
@@ -0,0 +1,17 @@
1
+ interface PriceFormatConfig {
2
+ /** ISO 4217 currency code. Default: `"USD"`. */
3
+ currency?: string;
4
+ /** BCP 47 locale. Default: `"en-US"`. */
5
+ locale?: string;
6
+ /** Decimal places. Default: `2`. */
7
+ precision?: number;
8
+ }
9
+ interface FormatPriceOptions {
10
+ /** Override precision for this call. */
11
+ precision?: number;
12
+ /** Multiply value by quantity before formatting. */
13
+ quantity?: number;
14
+ }
15
+ declare function createFormatPrice(config?: PriceFormatConfig): (value: number, options?: FormatPriceOptions) => string;
16
+
17
+ export { type FormatPriceOptions, type PriceFormatConfig, createFormatPrice };
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import {
3
+ createFormatPrice
4
+ } from "./chunk-PTAWV5SA.js";
5
+ export {
6
+ createFormatPrice
7
+ };
8
+ //# sourceMappingURL=price-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/price.cjs ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+ "use client";
3
+
4
+
5
+ var _chunkVT4JLAIEcjs = require('./chunk-VT4JLAIE.cjs');
6
+
7
+ // src/price.tsx
8
+ var _web = require('@simpleapps-com/augur-utils/web');
9
+ var _jsxruntime = require('react/jsx-runtime');
10
+ var defaults = {
11
+ currency: "USD",
12
+ locale: "en-US",
13
+ precision: 2,
14
+ zeroLabel: "Call for Price",
15
+ uomSeparator: "/"
16
+ };
17
+ function createPrice(config = {}) {
18
+ const {
19
+ currency,
20
+ locale,
21
+ precision,
22
+ zeroLabel,
23
+ uomSeparator,
24
+ classNames: factoryClassNames
25
+ } = { ...defaults, ...config };
26
+ const formatPrice = _chunkVT4JLAIEcjs.createFormatPrice.call(void 0, { currency, locale, precision });
27
+ const slotKeys = [
28
+ "amount",
29
+ "uom",
30
+ "separator",
31
+ "zero",
32
+ "skeleton",
33
+ "original"
34
+ ];
35
+ function mergeClassNames(instance) {
36
+ if (!factoryClassNames && !instance) return {};
37
+ const result = {};
38
+ for (const key of slotKeys) {
39
+ const merged = _web.cn.call(void 0, _optionalChain([factoryClassNames, 'optionalAccess', _ => _[key]]), _optionalChain([instance, 'optionalAccess', _2 => _2[key]]));
40
+ if (merged) result[key] = merged;
41
+ }
42
+ return result;
43
+ }
44
+ function Price(props) {
45
+ if ("loading" in props && props.loading) {
46
+ const slots2 = mergeClassNames(props.classNames);
47
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
48
+ "span",
49
+ {
50
+ className: _web.cn.call(void 0,
51
+ "inline-block h-4 w-16 animate-pulse rounded bg-muted",
52
+ slots2.skeleton,
53
+ props.className
54
+ )
55
+ }
56
+ );
57
+ }
58
+ const {
59
+ value = 0,
60
+ quantity,
61
+ uom,
62
+ precision: instancePrecision,
63
+ originalValue,
64
+ className,
65
+ classNames: instanceClassNames
66
+ } = props;
67
+ const slots = mergeClassNames(instanceClassNames);
68
+ if (value === 0 && originalValue === void 0) {
69
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _web.cn.call(void 0, "text-muted-foreground", slots.zero, className), children: zeroLabel });
70
+ }
71
+ const formatted = formatPrice(value, {
72
+ precision: instancePrecision,
73
+ quantity
74
+ });
75
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className, children: [
76
+ originalValue !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "s", { className: _web.cn.call(void 0, "mr-1 text-muted-foreground", slots.original), children: formatPrice(originalValue, { precision: instancePrecision }) }),
77
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: slots.amount, children: formatted }),
78
+ uom && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
79
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _web.cn.call(void 0, "ml-1", slots.separator), children: uomSeparator }),
80
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _web.cn.call(void 0, "ml-1 text-muted-foreground", slots.uom), children: uom })
81
+ ] })
82
+ ] });
83
+ }
84
+ Price.displayName = "Price";
85
+ return { Price, formatPrice };
86
+ }
87
+
88
+
89
+ exports.createPrice = createPrice;
90
+ //# sourceMappingURL=price.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","../src/price.tsx"],"names":["slots"],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","sourcesContent":[null,"\"use client\";\n\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { createFormatPrice } from \"./price-format\";\nimport type { FormatPriceOptions } from \"./price-format\";\n\n// Re-export server-safe types so client consumers get everything from one path\nexport type { PriceFormatConfig, FormatPriceOptions } from \"./price-format\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PriceClassNames {\n /** The formatted amount text. */\n amount?: string;\n /** The UOM label (e.g. \"EACH\"). */\n uom?: string;\n /** The separator between price and UOM (e.g. \"/\"). */\n separator?: string;\n /** The zero-price label (e.g. \"Call for Price\"). */\n zero?: string;\n /** The loading skeleton. */\n skeleton?: string;\n /** The strikethrough original price. */\n original?: string;\n}\n\nexport interface PriceConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n /** Label shown when value is 0. Default: `\"Call for Price\"`. */\n zeroLabel?: string;\n /** Separator between price and UOM. Default: `\"/\"`. */\n uomSeparator?: string;\n /** Default class names for sub-elements. */\n classNames?: PriceClassNames;\n}\n\ntype PricePropsBase = {\n /** Unit price. */\n value?: number;\n /** Quantity — multiplied by value for extended price. */\n quantity?: number;\n /** Unit of measure label (e.g. \"EACH\", \"FT\"). */\n uom?: string;\n /** Override precision for this instance. */\n precision?: number;\n /** Original price shown as strikethrough for sale display. */\n originalValue?: number;\n /** Additional class names for the root element. */\n className?: string;\n /** Class names for sub-elements, merged with factory defaults. */\n classNames?: PriceClassNames;\n};\n\nexport type PriceProps =\n | (PricePropsBase & { loading?: false })\n | { loading: true; className?: string; classNames?: PriceClassNames };\n\nexport interface CreatePriceResult {\n Price: React.FC<PriceProps>;\n formatPrice: (value: number, options?: FormatPriceOptions) => string;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nconst defaults = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n zeroLabel: \"Call for Price\",\n uomSeparator: \"/\",\n} as const;\n\nexport function createPrice(config: PriceConfig = {}): CreatePriceResult {\n const {\n currency,\n locale,\n precision,\n zeroLabel,\n uomSeparator,\n classNames: factoryClassNames,\n } = { ...defaults, ...config };\n\n const formatPrice = createFormatPrice({ currency, locale, precision });\n\n const slotKeys: (keyof PriceClassNames)[] = [\n \"amount\", \"uom\", \"separator\", \"zero\", \"skeleton\", \"original\",\n ];\n\n function mergeClassNames(\n instance?: PriceClassNames,\n ): PriceClassNames {\n if (!factoryClassNames && !instance) return {};\n const result: PriceClassNames = {};\n for (const key of slotKeys) {\n const merged = cn(factoryClassNames?.[key], instance?.[key]);\n if (merged) result[key] = merged;\n }\n return result;\n }\n\n function Price(props: PriceProps) {\n if (\"loading\" in props && props.loading) {\n const slots = mergeClassNames(props.classNames);\n return (\n <span\n className={cn(\n \"inline-block h-4 w-16 animate-pulse rounded bg-muted\",\n slots.skeleton,\n props.className,\n )}\n />\n );\n }\n\n const {\n value = 0,\n quantity,\n uom,\n precision: instancePrecision,\n originalValue,\n className,\n classNames: instanceClassNames,\n } = props as PricePropsBase;\n\n const slots = mergeClassNames(instanceClassNames);\n\n if (value === 0 && originalValue === undefined) {\n return (\n <span className={cn(\"text-muted-foreground\", slots.zero, className)}>\n {zeroLabel}\n </span>\n );\n }\n\n const formatted = formatPrice(value, {\n precision: instancePrecision,\n quantity,\n });\n\n return (\n <span className={className}>\n {originalValue !== undefined && (\n <s className={cn(\"mr-1 text-muted-foreground\", slots.original)}>\n {formatPrice(originalValue, { precision: instancePrecision })}\n </s>\n )}\n <span className={slots.amount}>{formatted}</span>\n {uom && (\n <>\n <span className={cn(\"ml-1\", slots.separator)}>\n {uomSeparator}\n </span>\n <span className={cn(\"ml-1 text-muted-foreground\", slots.uom)}>\n {uom}\n </span>\n </>\n )}\n </span>\n );\n }\n\n Price.displayName = \"Price\";\n\n return { Price, formatPrice };\n}\n"]}
@@ -0,0 +1,61 @@
1
+ import { FormatPriceOptions } from './price-format.cjs';
2
+ export { PriceFormatConfig } from './price-format.cjs';
3
+
4
+ interface PriceClassNames {
5
+ /** The formatted amount text. */
6
+ amount?: string;
7
+ /** The UOM label (e.g. "EACH"). */
8
+ uom?: string;
9
+ /** The separator between price and UOM (e.g. "/"). */
10
+ separator?: string;
11
+ /** The zero-price label (e.g. "Call for Price"). */
12
+ zero?: string;
13
+ /** The loading skeleton. */
14
+ skeleton?: string;
15
+ /** The strikethrough original price. */
16
+ original?: string;
17
+ }
18
+ interface PriceConfig {
19
+ /** ISO 4217 currency code. Default: `"USD"`. */
20
+ currency?: string;
21
+ /** BCP 47 locale. Default: `"en-US"`. */
22
+ locale?: string;
23
+ /** Decimal places. Default: `2`. */
24
+ precision?: number;
25
+ /** Label shown when value is 0. Default: `"Call for Price"`. */
26
+ zeroLabel?: string;
27
+ /** Separator between price and UOM. Default: `"/"`. */
28
+ uomSeparator?: string;
29
+ /** Default class names for sub-elements. */
30
+ classNames?: PriceClassNames;
31
+ }
32
+ type PricePropsBase = {
33
+ /** Unit price. */
34
+ value?: number;
35
+ /** Quantity — multiplied by value for extended price. */
36
+ quantity?: number;
37
+ /** Unit of measure label (e.g. "EACH", "FT"). */
38
+ uom?: string;
39
+ /** Override precision for this instance. */
40
+ precision?: number;
41
+ /** Original price shown as strikethrough for sale display. */
42
+ originalValue?: number;
43
+ /** Additional class names for the root element. */
44
+ className?: string;
45
+ /** Class names for sub-elements, merged with factory defaults. */
46
+ classNames?: PriceClassNames;
47
+ };
48
+ type PriceProps = (PricePropsBase & {
49
+ loading?: false;
50
+ }) | {
51
+ loading: true;
52
+ className?: string;
53
+ classNames?: PriceClassNames;
54
+ };
55
+ interface CreatePriceResult {
56
+ Price: React.FC<PriceProps>;
57
+ formatPrice: (value: number, options?: FormatPriceOptions) => string;
58
+ }
59
+ declare function createPrice(config?: PriceConfig): CreatePriceResult;
60
+
61
+ export { type CreatePriceResult, FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceProps, createPrice };
@@ -0,0 +1,61 @@
1
+ import { FormatPriceOptions } from './price-format.js';
2
+ export { PriceFormatConfig } from './price-format.js';
3
+
4
+ interface PriceClassNames {
5
+ /** The formatted amount text. */
6
+ amount?: string;
7
+ /** The UOM label (e.g. "EACH"). */
8
+ uom?: string;
9
+ /** The separator between price and UOM (e.g. "/"). */
10
+ separator?: string;
11
+ /** The zero-price label (e.g. "Call for Price"). */
12
+ zero?: string;
13
+ /** The loading skeleton. */
14
+ skeleton?: string;
15
+ /** The strikethrough original price. */
16
+ original?: string;
17
+ }
18
+ interface PriceConfig {
19
+ /** ISO 4217 currency code. Default: `"USD"`. */
20
+ currency?: string;
21
+ /** BCP 47 locale. Default: `"en-US"`. */
22
+ locale?: string;
23
+ /** Decimal places. Default: `2`. */
24
+ precision?: number;
25
+ /** Label shown when value is 0. Default: `"Call for Price"`. */
26
+ zeroLabel?: string;
27
+ /** Separator between price and UOM. Default: `"/"`. */
28
+ uomSeparator?: string;
29
+ /** Default class names for sub-elements. */
30
+ classNames?: PriceClassNames;
31
+ }
32
+ type PricePropsBase = {
33
+ /** Unit price. */
34
+ value?: number;
35
+ /** Quantity — multiplied by value for extended price. */
36
+ quantity?: number;
37
+ /** Unit of measure label (e.g. "EACH", "FT"). */
38
+ uom?: string;
39
+ /** Override precision for this instance. */
40
+ precision?: number;
41
+ /** Original price shown as strikethrough for sale display. */
42
+ originalValue?: number;
43
+ /** Additional class names for the root element. */
44
+ className?: string;
45
+ /** Class names for sub-elements, merged with factory defaults. */
46
+ classNames?: PriceClassNames;
47
+ };
48
+ type PriceProps = (PricePropsBase & {
49
+ loading?: false;
50
+ }) | {
51
+ loading: true;
52
+ className?: string;
53
+ classNames?: PriceClassNames;
54
+ };
55
+ interface CreatePriceResult {
56
+ Price: React.FC<PriceProps>;
57
+ formatPrice: (value: number, options?: FormatPriceOptions) => string;
58
+ }
59
+ declare function createPrice(config?: PriceConfig): CreatePriceResult;
60
+
61
+ export { type CreatePriceResult, FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceProps, createPrice };
package/dist/price.js ADDED
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ createFormatPrice
5
+ } from "./chunk-PTAWV5SA.js";
6
+
7
+ // src/price.tsx
8
+ import { cn } from "@simpleapps-com/augur-utils/web";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ var defaults = {
11
+ currency: "USD",
12
+ locale: "en-US",
13
+ precision: 2,
14
+ zeroLabel: "Call for Price",
15
+ uomSeparator: "/"
16
+ };
17
+ function createPrice(config = {}) {
18
+ const {
19
+ currency,
20
+ locale,
21
+ precision,
22
+ zeroLabel,
23
+ uomSeparator,
24
+ classNames: factoryClassNames
25
+ } = { ...defaults, ...config };
26
+ const formatPrice = createFormatPrice({ currency, locale, precision });
27
+ const slotKeys = [
28
+ "amount",
29
+ "uom",
30
+ "separator",
31
+ "zero",
32
+ "skeleton",
33
+ "original"
34
+ ];
35
+ function mergeClassNames(instance) {
36
+ if (!factoryClassNames && !instance) return {};
37
+ const result = {};
38
+ for (const key of slotKeys) {
39
+ const merged = cn(factoryClassNames?.[key], instance?.[key]);
40
+ if (merged) result[key] = merged;
41
+ }
42
+ return result;
43
+ }
44
+ function Price(props) {
45
+ if ("loading" in props && props.loading) {
46
+ const slots2 = mergeClassNames(props.classNames);
47
+ return /* @__PURE__ */ jsx(
48
+ "span",
49
+ {
50
+ className: cn(
51
+ "inline-block h-4 w-16 animate-pulse rounded bg-muted",
52
+ slots2.skeleton,
53
+ props.className
54
+ )
55
+ }
56
+ );
57
+ }
58
+ const {
59
+ value = 0,
60
+ quantity,
61
+ uom,
62
+ precision: instancePrecision,
63
+ originalValue,
64
+ className,
65
+ classNames: instanceClassNames
66
+ } = props;
67
+ const slots = mergeClassNames(instanceClassNames);
68
+ if (value === 0 && originalValue === void 0) {
69
+ return /* @__PURE__ */ jsx("span", { className: cn("text-muted-foreground", slots.zero, className), children: zeroLabel });
70
+ }
71
+ const formatted = formatPrice(value, {
72
+ precision: instancePrecision,
73
+ quantity
74
+ });
75
+ return /* @__PURE__ */ jsxs("span", { className, children: [
76
+ originalValue !== void 0 && /* @__PURE__ */ jsx("s", { className: cn("mr-1 text-muted-foreground", slots.original), children: formatPrice(originalValue, { precision: instancePrecision }) }),
77
+ /* @__PURE__ */ jsx("span", { className: slots.amount, children: formatted }),
78
+ uom && /* @__PURE__ */ jsxs(Fragment, { children: [
79
+ /* @__PURE__ */ jsx("span", { className: cn("ml-1", slots.separator), children: uomSeparator }),
80
+ /* @__PURE__ */ jsx("span", { className: cn("ml-1 text-muted-foreground", slots.uom), children: uom })
81
+ ] })
82
+ ] });
83
+ }
84
+ Price.displayName = "Price";
85
+ return { Price, formatPrice };
86
+ }
87
+ export {
88
+ createPrice
89
+ };
90
+ //# sourceMappingURL=price.js.map