@jwiedeman/gtm-kit-svelte 1.1.6 → 1.2.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.cjs +94 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +85 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4,15 +4,100 @@ var store = require('svelte/store');
|
|
|
4
4
|
var svelte = require('svelte');
|
|
5
5
|
var gtmKit = require('@jwiedeman/gtm-kit');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// src/store.ts
|
|
8
|
+
var GTM_CONTEXT_KEY = Symbol("gtm-kit");
|
|
9
|
+
function createGtmStore(options) {
|
|
10
|
+
const { autoInit = true, onBeforeInit, ...clientOptions } = options;
|
|
11
|
+
const client = gtmKit.createGtmClient(clientOptions);
|
|
12
|
+
const initialValue = {
|
|
13
|
+
client,
|
|
14
|
+
push: (value) => client.push(value),
|
|
15
|
+
setConsentDefaults: (state, regionOptions) => client.setConsentDefaults(state, regionOptions),
|
|
16
|
+
updateConsent: (state, regionOptions) => client.updateConsent(state, regionOptions),
|
|
17
|
+
isReady: () => client.isReady(),
|
|
18
|
+
whenReady: () => client.whenReady(),
|
|
19
|
+
onReady: (callback) => client.onReady(callback),
|
|
20
|
+
initialized: false
|
|
21
|
+
};
|
|
22
|
+
const store$1 = store.writable(initialValue);
|
|
23
|
+
if (onBeforeInit) {
|
|
24
|
+
onBeforeInit(client);
|
|
25
|
+
}
|
|
26
|
+
if (autoInit) {
|
|
27
|
+
client.init();
|
|
28
|
+
store$1.update((s) => ({ ...s, initialized: true }));
|
|
29
|
+
}
|
|
30
|
+
return store$1;
|
|
31
|
+
}
|
|
32
|
+
function getGtmContext() {
|
|
33
|
+
const context = svelte.getContext(GTM_CONTEXT_KEY);
|
|
34
|
+
if (!context) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"[gtm-kit/svelte] getGtmContext() was called outside of a component tree with GTM context. Make sure to call setGtmContext() in a parent component."
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
41
|
+
function setGtmContext(store) {
|
|
42
|
+
try {
|
|
43
|
+
const existing = svelte.getContext(GTM_CONTEXT_KEY);
|
|
44
|
+
if (existing) {
|
|
45
|
+
if (process.env.NODE_ENV !== "production") {
|
|
46
|
+
console.warn(
|
|
47
|
+
"[gtm-kit/svelte] setGtmContext() was called when a GTM context already exists. You should only have one GTM context at the root of your app. The duplicate context will be ignored."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
}
|
|
54
|
+
svelte.setContext(GTM_CONTEXT_KEY, store);
|
|
55
|
+
}
|
|
56
|
+
var gtmContext = getGtmContext;
|
|
57
|
+
function gtmPush() {
|
|
58
|
+
const store$1 = getGtmContext();
|
|
59
|
+
return store.derived(store$1, ($store) => $store.push);
|
|
60
|
+
}
|
|
61
|
+
function gtmConsent() {
|
|
62
|
+
const store$1 = getGtmContext();
|
|
63
|
+
return store.derived(store$1, ($store) => ({
|
|
64
|
+
setConsentDefaults: $store.setConsentDefaults,
|
|
65
|
+
updateConsent: $store.updateConsent
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
function gtmClient() {
|
|
69
|
+
const store$1 = getGtmContext();
|
|
70
|
+
return store.derived(store$1, ($store) => $store.client);
|
|
71
|
+
}
|
|
72
|
+
function gtmReady() {
|
|
73
|
+
const store$1 = getGtmContext();
|
|
74
|
+
return store.derived(store$1, ($store) => $store.whenReady);
|
|
75
|
+
}
|
|
76
|
+
function gtmIsReady() {
|
|
77
|
+
const store$1 = getGtmContext();
|
|
78
|
+
return store.derived(store$1, ($store) => $store.isReady);
|
|
79
|
+
}
|
|
80
|
+
function destroyGtmStore(store) {
|
|
81
|
+
let storeValue = null;
|
|
82
|
+
const unsubscribe = store.subscribe((value) => {
|
|
83
|
+
storeValue = value;
|
|
84
|
+
});
|
|
85
|
+
unsubscribe();
|
|
86
|
+
if (storeValue !== null) {
|
|
87
|
+
storeValue.client.teardown();
|
|
88
|
+
store.update((s) => ({ ...s, initialized: false }));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
8
91
|
|
|
9
|
-
exports.createGtmStore =
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
92
|
+
exports.createGtmStore = createGtmStore;
|
|
93
|
+
exports.destroyGtmStore = destroyGtmStore;
|
|
94
|
+
exports.getGtmContext = getGtmContext;
|
|
95
|
+
exports.gtmClient = gtmClient;
|
|
96
|
+
exports.gtmConsent = gtmConsent;
|
|
97
|
+
exports.gtmContext = gtmContext;
|
|
98
|
+
exports.gtmIsReady = gtmIsReady;
|
|
99
|
+
exports.gtmPush = gtmPush;
|
|
100
|
+
exports.gtmReady = gtmReady;
|
|
101
|
+
exports.setGtmContext = setGtmContext;
|
|
17
102
|
//# sourceMappingURL=out.js.map
|
|
18
103
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts"],"names":["writable","derived","getContext","setContext","createGtmClient","GTM_CONTEXT_KEY","createGtmStore","options","autoInit","onBeforeInit","clientOptions","client","store","value","state","regionOptions","callback","s","getGtmContext","context","setGtmContext","gtmContext","gtmPush","$store","gtmConsent","gtmClient","gtmReady"],"mappings":"AAAA,OAAS,YAAAA,EAAU,WAAAC,MAA6C,eAChE,OAAS,cAAAC,EAAY,cAAAC,MAAkB,SACvC,OACE,mBAAAC,MAOK,qBAiDP,IAAMC,EAAkB,OAAO,SAAS,EAgBjC,SAASC,EAAeC,EAAmD,CAChF,GAAM,CAAE,SAAAC,EAAW,GAAM,aAAAC,EAAc,GAAGC,CAAc,EAAIH,EAEtDI,EAASP,EAAgBM,CAAa,EActCE,EAAQZ,EAZsB,CAClC,OAAAW,EACA,KAAOE,GAA0BF,EAAO,KAAKE,CAAK,EAClD,mBAAoB,CAACC,EAAqBC,IACxCJ,EAAO,mBAAmBG,EAAOC,CAAa,EAChD,cAAe,CAACD,EAAqBC,IACnCJ,EAAO,cAAcG,EAAOC,CAAa,EAC3C,UAAW,IAAMJ,EAAO,UAAU,EAClC,QAAUK,GAAiDL,EAAO,QAAQK,CAAQ,EAClF,YAAa,EACf,CAEkD,EAGlD,OAAIP,GACFA,EAAaE,CAAM,EAIjBH,IACFG,EAAO,KAAK,EACZC,EAAM,OAAQK,IAAO,CAAE,GAAGA,EAAG,YAAa,EAAK,EAAE,GAG5CL,CACT,CAgBO,SAASM,GAAyC,CACvD,IAAMC,EAAUjB,EAAoCG,CAAe,EACnE,GAAI,CAACc,EACH,MAAM,IAAI,MACR,6IAEF,EAEF,OAAOA,CACT,CAkBO,SAASC,EAAcR,EAAsC,CAClET,EAAWE,EAAiBO,CAAK,CACnC,CAKO,IAAMS,EAAaH,EAmBnB,SAASI,GAAqD,CACnE,IAAMV,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,IAAI,CAC/C,CAkBO,SAASC,GAAsC,CACpD,IAAMZ,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,IAAY,CACjC,mBAAoBA,EAAO,mBAC3B,cAAeA,EAAO,aACxB,EAAE,CACJ,CAcO,SAASE,GAAiC,CAC/C,IAAMb,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,MAAM,CACjD,CAoBO,SAASG,GAAuD,CACrE,IAAMd,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,SAAS,CACpD","sourcesContent":["import { writable, derived, type Writable, type Readable } from 'svelte/store';\nimport { getContext, setContext } from 'svelte';\nimport {\n createGtmClient,\n type ConsentRegionOptions,\n type ConsentState,\n type CreateGtmClientOptions,\n type DataLayerValue,\n type GtmClient,\n type ScriptLoadState\n} from '@jwiedeman/gtm-kit';\n\n/**\n * Options for creating a GTM store.\n * Extends CreateGtmClientOptions with Svelte-specific options.\n */\nexport interface GtmStoreOptions extends CreateGtmClientOptions {\n /**\n * Whether to automatically initialize GTM when the store is created.\n * @default true\n */\n autoInit?: boolean;\n\n /**\n * Callback executed before GTM initialization.\n * Use this to set consent defaults.\n */\n onBeforeInit?: (client: GtmClient) => void;\n}\n\n/**\n * The GTM store value containing all GTM functionality.\n */\nexport interface GtmStoreValue {\n /** The underlying GTM client instance */\n client: GtmClient;\n /** Push a value to the data layer */\n push: (value: DataLayerValue) => void;\n /** Set consent defaults (must be called before init) */\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Update consent state */\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Returns a promise that resolves when all GTM scripts are loaded */\n whenReady: () => Promise<ScriptLoadState[]>;\n /** Register a callback for when GTM scripts are ready */\n onReady: (callback: (state: ScriptLoadState[]) => void) => () => void;\n /** Whether GTM has been initialized */\n initialized: boolean;\n}\n\n/**\n * Consent-specific API subset.\n */\nexport interface GtmConsentApi {\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n}\n\n/** Context key for GTM store */\nconst GTM_CONTEXT_KEY = Symbol('gtm-kit');\n\n/**\n * Create a GTM store for Svelte.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n * ```\n */\nexport function createGtmStore(options: GtmStoreOptions): Writable<GtmStoreValue> {\n const { autoInit = true, onBeforeInit, ...clientOptions } = options;\n\n const client = createGtmClient(clientOptions);\n\n const initialValue: GtmStoreValue = {\n client,\n push: (value: DataLayerValue) => client.push(value),\n setConsentDefaults: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.setConsentDefaults(state, regionOptions),\n updateConsent: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.updateConsent(state, regionOptions),\n whenReady: () => client.whenReady(),\n onReady: (callback: (state: ScriptLoadState[]) => void) => client.onReady(callback),\n initialized: false\n };\n\n const store = writable<GtmStoreValue>(initialValue);\n\n // Call onBeforeInit hook if provided (for consent defaults)\n if (onBeforeInit) {\n onBeforeInit(client);\n }\n\n // Auto-initialize if enabled\n if (autoInit) {\n client.init();\n store.update((s) => ({ ...s, initialized: true }));\n }\n\n return store;\n}\n\n/**\n * Get the GTM context from a parent component.\n * Must be called during component initialization.\n *\n * @example\n * ```svelte\n * <script>\n * import { getGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = getGtmContext();\n * $: ({ push } = $gtm);\n * </script>\n * ```\n */\nexport function getGtmContext(): Writable<GtmStoreValue> {\n const context = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (!context) {\n throw new Error(\n '[gtm-kit] getGtmContext() was called outside of a component tree with GTM context. ' +\n 'Make sure to call setGtmContext() in a parent component.'\n );\n }\n return context;\n}\n\n/**\n * Set the GTM context for child components.\n * Call this in your root layout or App component.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n *\n * <slot />\n * ```\n */\nexport function setGtmContext(store: Writable<GtmStoreValue>): void {\n setContext(GTM_CONTEXT_KEY, store);\n}\n\n/**\n * Alias for getGtmContext() - get the full GTM store.\n */\nexport const gtmContext = getGtmContext;\n\n/**\n * Get a derived store that provides just the push function.\n * Use this when you only need to push events.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmPush } from '@jwiedeman/gtm-kit-svelte';\n *\n * const push = gtmPush();\n *\n * function handleClick() {\n * $push({ event: 'button_click' });\n * }\n * </script>\n * ```\n */\nexport function gtmPush(): Readable<(value: DataLayerValue) => void> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.push);\n}\n\n/**\n * Get a derived store that provides consent functions.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmConsent } from '@jwiedeman/gtm-kit-svelte';\n *\n * const consent = gtmConsent();\n *\n * function acceptAll() {\n * $consent.updateConsent({ analytics_storage: 'granted' });\n * }\n * </script>\n * ```\n */\nexport function gtmConsent(): Readable<GtmConsentApi> {\n const store = getGtmContext();\n return derived(store, ($store) => ({\n setConsentDefaults: $store.setConsentDefaults,\n updateConsent: $store.updateConsent\n }));\n}\n\n/**\n * Get a derived store that provides the raw GTM client.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmClient } from '@jwiedeman/gtm-kit-svelte';\n *\n * const client = gtmClient();\n * </script>\n * ```\n */\nexport function gtmClient(): Readable<GtmClient> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.client);\n}\n\n/**\n * Get a derived store that provides the whenReady function.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmReady } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const whenReady = gtmReady();\n *\n * onMount(async () => {\n * const states = await $whenReady();\n * console.log('GTM loaded:', states);\n * });\n * </script>\n * ```\n */\nexport function gtmReady(): Readable<() => Promise<ScriptLoadState[]>> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.whenReady);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store.ts"],"names":[],"mappings":";AAAA,SAAS,UAAU,eAA6C;AAChE,SAAS,YAAY,kBAAkB;AACvC;AAAA,EACE;AAAA,OAOK;AAmDP,IAAM,kBAAkB,OAAO,SAAS;AAgBjC,SAAS,eAAe,SAAmD;AAChF,QAAM,EAAE,WAAW,MAAM,cAAc,GAAG,cAAc,IAAI;AAE5D,QAAM,SAAS,gBAAgB,aAAa;AAE5C,QAAM,eAA8B;AAAA,IAClC;AAAA,IACA,MAAM,CAAC,UAA0B,OAAO,KAAK,KAAK;AAAA,IAClD,oBAAoB,CAAC,OAAqB,kBACxC,OAAO,mBAAmB,OAAO,aAAa;AAAA,IAChD,eAAe,CAAC,OAAqB,kBACnC,OAAO,cAAc,OAAO,aAAa;AAAA,IAC3C,SAAS,MAAM,OAAO,QAAQ;AAAA,IAC9B,WAAW,MAAM,OAAO,UAAU;AAAA,IAClC,SAAS,CAAC,aAAiD,OAAO,QAAQ,QAAQ;AAAA,IAClF,aAAa;AAAA,EACf;AAEA,QAAM,QAAQ,SAAwB,YAAY;AAGlD,MAAI,cAAc;AAChB,iBAAa,MAAM;AAAA,EACrB;AAGA,MAAI,UAAU;AACZ,WAAO,KAAK;AACZ,UAAM,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,aAAa,KAAK,EAAE;AAAA,EACnD;AAEA,SAAO;AACT;AAgBO,SAAS,gBAAyC;AACvD,QAAM,UAAU,WAAoC,eAAe;AACnE,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAkBO,SAAS,cAAc,OAAsC;AAElE,MAAI;AACF,UAAM,WAAW,WAAoC,eAAe;AACpE,QAAI,UAAU;AACZ,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,gBAAQ;AAAA,UACN;AAAA,QAGF;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF,SAAQ;AAAA,EAER;AACA,aAAW,iBAAiB,KAAK;AACnC;AAKO,IAAM,aAAa;AAmBnB,SAAS,UAAqD;AACnE,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,IAAI;AAC/C;AAkBO,SAAS,aAAsC;AACpD,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,YAAY;AAAA,IACjC,oBAAoB,OAAO;AAAA,IAC3B,eAAe,OAAO;AAAA,EACxB,EAAE;AACJ;AAcO,SAAS,YAAiC;AAC/C,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,MAAM;AACjD;AAoBO,SAAS,WAAuD;AACrE,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS;AACpD;AAoBO,SAAS,aAAsC;AACpD,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,OAAO;AAClD;AAqBO,SAAS,gBAAgB,OAAsC;AACpE,MAAI,aAAmC;AAGvC,QAAM,cAAc,MAAM,UAAU,CAAC,UAAU;AAC7C,iBAAa;AAAA,EACf,CAAC;AACD,cAAY;AAGZ,MAAI,eAAe,MAAM;AACvB,IAAC,WAA6B,OAAO,SAAS;AAC9C,UAAM,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,aAAa,MAAM,EAAE;AAAA,EACpD;AACF","sourcesContent":["import { writable, derived, type Writable, type Readable } from 'svelte/store';\nimport { getContext, setContext } from 'svelte';\nimport {\n createGtmClient,\n type ConsentRegionOptions,\n type ConsentState,\n type CreateGtmClientOptions,\n type DataLayerValue,\n type GtmClient,\n type ScriptLoadState\n} from '@jwiedeman/gtm-kit';\n\n/**\n * Options for creating a GTM store.\n * Extends CreateGtmClientOptions with Svelte-specific options.\n */\nexport interface GtmStoreOptions extends CreateGtmClientOptions {\n /**\n * Whether to automatically initialize GTM when the store is created.\n * @default true\n */\n autoInit?: boolean;\n\n /**\n * Callback executed before GTM initialization.\n * Use this to set consent defaults.\n */\n onBeforeInit?: (client: GtmClient) => void;\n}\n\n/**\n * The GTM store value containing all GTM functionality.\n */\nexport interface GtmStoreValue {\n /** The underlying GTM client instance */\n client: GtmClient;\n /** Push a value to the data layer */\n push: (value: DataLayerValue) => void;\n /** Set consent defaults (must be called before init) */\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Update consent state */\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Synchronously check if all GTM scripts have finished loading */\n isReady: () => boolean;\n /** Returns a promise that resolves when all GTM scripts are loaded */\n whenReady: () => Promise<ScriptLoadState[]>;\n /** Register a callback for when GTM scripts are ready */\n onReady: (callback: (state: ScriptLoadState[]) => void) => () => void;\n /** Whether GTM has been initialized */\n initialized: boolean;\n}\n\n/**\n * Consent-specific API subset.\n */\nexport interface GtmConsentApi {\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n}\n\n/** Context key for GTM store */\nconst GTM_CONTEXT_KEY = Symbol('gtm-kit');\n\n/**\n * Create a GTM store for Svelte.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n * ```\n */\nexport function createGtmStore(options: GtmStoreOptions): Writable<GtmStoreValue> {\n const { autoInit = true, onBeforeInit, ...clientOptions } = options;\n\n const client = createGtmClient(clientOptions);\n\n const initialValue: GtmStoreValue = {\n client,\n push: (value: DataLayerValue) => client.push(value),\n setConsentDefaults: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.setConsentDefaults(state, regionOptions),\n updateConsent: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.updateConsent(state, regionOptions),\n isReady: () => client.isReady(),\n whenReady: () => client.whenReady(),\n onReady: (callback: (state: ScriptLoadState[]) => void) => client.onReady(callback),\n initialized: false\n };\n\n const store = writable<GtmStoreValue>(initialValue);\n\n // Call onBeforeInit hook if provided (for consent defaults)\n if (onBeforeInit) {\n onBeforeInit(client);\n }\n\n // Auto-initialize if enabled\n if (autoInit) {\n client.init();\n store.update((s) => ({ ...s, initialized: true }));\n }\n\n return store;\n}\n\n/**\n * Get the GTM context from a parent component.\n * Must be called during component initialization.\n *\n * @example\n * ```svelte\n * <script>\n * import { getGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = getGtmContext();\n * $: ({ push } = $gtm);\n * </script>\n * ```\n */\nexport function getGtmContext(): Writable<GtmStoreValue> {\n const context = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (!context) {\n throw new Error(\n '[gtm-kit/svelte] getGtmContext() was called outside of a component tree with GTM context. ' +\n 'Make sure to call setGtmContext() in a parent component.'\n );\n }\n return context;\n}\n\n/**\n * Set the GTM context for child components.\n * Call this in your root layout or App component.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n *\n * <slot />\n * ```\n */\nexport function setGtmContext(store: Writable<GtmStoreValue>): void {\n // Check if a context already exists (nested context)\n try {\n const existing = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (existing) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[gtm-kit/svelte] setGtmContext() was called when a GTM context already exists. ' +\n 'You should only have one GTM context at the root of your app. ' +\n 'The duplicate context will be ignored.'\n );\n }\n return;\n }\n } catch {\n // getContext throws when called outside component initialization, which is fine\n }\n setContext(GTM_CONTEXT_KEY, store);\n}\n\n/**\n * Alias for getGtmContext() - get the full GTM store.\n */\nexport const gtmContext = getGtmContext;\n\n/**\n * Get a derived store that provides just the push function.\n * Use this when you only need to push events.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmPush } from '@jwiedeman/gtm-kit-svelte';\n *\n * const push = gtmPush();\n *\n * function handleClick() {\n * $push({ event: 'button_click' });\n * }\n * </script>\n * ```\n */\nexport function gtmPush(): Readable<(value: DataLayerValue) => void> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.push);\n}\n\n/**\n * Get a derived store that provides consent functions.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmConsent } from '@jwiedeman/gtm-kit-svelte';\n *\n * const consent = gtmConsent();\n *\n * function acceptAll() {\n * $consent.updateConsent({ analytics_storage: 'granted' });\n * }\n * </script>\n * ```\n */\nexport function gtmConsent(): Readable<GtmConsentApi> {\n const store = getGtmContext();\n return derived(store, ($store) => ({\n setConsentDefaults: $store.setConsentDefaults,\n updateConsent: $store.updateConsent\n }));\n}\n\n/**\n * Get a derived store that provides the raw GTM client.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmClient } from '@jwiedeman/gtm-kit-svelte';\n *\n * const client = gtmClient();\n * </script>\n * ```\n */\nexport function gtmClient(): Readable<GtmClient> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.client);\n}\n\n/**\n * Get a derived store that provides the whenReady function.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmReady } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const whenReady = gtmReady();\n *\n * onMount(async () => {\n * const states = await $whenReady();\n * console.log('GTM loaded:', states);\n * });\n * </script>\n * ```\n */\nexport function gtmReady(): Readable<() => Promise<ScriptLoadState[]>> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.whenReady);\n}\n\n/**\n * Get a derived store that provides the isReady function.\n * Use this to check synchronously if GTM scripts have finished loading.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmIsReady } from '@jwiedeman/gtm-kit-svelte';\n *\n * const isReady = gtmIsReady();\n *\n * // Check if GTM is ready\n * if ($isReady()) {\n * console.log('GTM is ready');\n * }\n * </script>\n * ```\n */\nexport function gtmIsReady(): Readable<() => boolean> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.isReady);\n}\n\n/**\n * Teardown the GTM client and clean up resources.\n * Call this in your component's onDestroy lifecycle hook.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext, destroyGtmStore } from '@jwiedeman/gtm-kit-svelte';\n * import { onDestroy } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n *\n * onDestroy(() => {\n * destroyGtmStore(gtm);\n * });\n * </script>\n * ```\n */\nexport function destroyGtmStore(store: Writable<GtmStoreValue>): void {\n let storeValue: GtmStoreValue | null = null;\n\n // Get the store value synchronously\n const unsubscribe = store.subscribe((value) => {\n storeValue = value;\n });\n unsubscribe();\n\n // Teardown the client\n if (storeValue !== null) {\n (storeValue as GtmStoreValue).client.teardown();\n store.update((s) => ({ ...s, initialized: false }));\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -29,6 +29,8 @@ interface GtmStoreValue {
|
|
|
29
29
|
setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;
|
|
30
30
|
/** Update consent state */
|
|
31
31
|
updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;
|
|
32
|
+
/** Synchronously check if all GTM scripts have finished loading */
|
|
33
|
+
isReady: () => boolean;
|
|
32
34
|
/** Returns a promise that resolves when all GTM scripts are loaded */
|
|
33
35
|
whenReady: () => Promise<ScriptLoadState[]>;
|
|
34
36
|
/** Register a callback for when GTM scripts are ready */
|
|
@@ -161,5 +163,44 @@ declare function gtmClient(): Readable<GtmClient>;
|
|
|
161
163
|
* ```
|
|
162
164
|
*/
|
|
163
165
|
declare function gtmReady(): Readable<() => Promise<ScriptLoadState[]>>;
|
|
166
|
+
/**
|
|
167
|
+
* Get a derived store that provides the isReady function.
|
|
168
|
+
* Use this to check synchronously if GTM scripts have finished loading.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```svelte
|
|
172
|
+
* <script>
|
|
173
|
+
* import { gtmIsReady } from '@jwiedeman/gtm-kit-svelte';
|
|
174
|
+
*
|
|
175
|
+
* const isReady = gtmIsReady();
|
|
176
|
+
*
|
|
177
|
+
* // Check if GTM is ready
|
|
178
|
+
* if ($isReady()) {
|
|
179
|
+
* console.log('GTM is ready');
|
|
180
|
+
* }
|
|
181
|
+
* </script>
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
declare function gtmIsReady(): Readable<() => boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Teardown the GTM client and clean up resources.
|
|
187
|
+
* Call this in your component's onDestroy lifecycle hook.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```svelte
|
|
191
|
+
* <script>
|
|
192
|
+
* import { createGtmStore, setGtmContext, destroyGtmStore } from '@jwiedeman/gtm-kit-svelte';
|
|
193
|
+
* import { onDestroy } from 'svelte';
|
|
194
|
+
*
|
|
195
|
+
* const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });
|
|
196
|
+
* setGtmContext(gtm);
|
|
197
|
+
*
|
|
198
|
+
* onDestroy(() => {
|
|
199
|
+
* destroyGtmStore(gtm);
|
|
200
|
+
* });
|
|
201
|
+
* </script>
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function destroyGtmStore(store: Writable<GtmStoreValue>): void;
|
|
164
205
|
|
|
165
|
-
export { GtmConsentApi, GtmStoreOptions, GtmStoreValue, createGtmStore, getGtmContext, gtmClient, gtmConsent, gtmContext, gtmPush, gtmReady, setGtmContext };
|
|
206
|
+
export { GtmConsentApi, GtmStoreOptions, GtmStoreValue, createGtmStore, destroyGtmStore, getGtmContext, gtmClient, gtmConsent, gtmContext, gtmIsReady, gtmPush, gtmReady, setGtmContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ interface GtmStoreValue {
|
|
|
29
29
|
setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;
|
|
30
30
|
/** Update consent state */
|
|
31
31
|
updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;
|
|
32
|
+
/** Synchronously check if all GTM scripts have finished loading */
|
|
33
|
+
isReady: () => boolean;
|
|
32
34
|
/** Returns a promise that resolves when all GTM scripts are loaded */
|
|
33
35
|
whenReady: () => Promise<ScriptLoadState[]>;
|
|
34
36
|
/** Register a callback for when GTM scripts are ready */
|
|
@@ -161,5 +163,44 @@ declare function gtmClient(): Readable<GtmClient>;
|
|
|
161
163
|
* ```
|
|
162
164
|
*/
|
|
163
165
|
declare function gtmReady(): Readable<() => Promise<ScriptLoadState[]>>;
|
|
166
|
+
/**
|
|
167
|
+
* Get a derived store that provides the isReady function.
|
|
168
|
+
* Use this to check synchronously if GTM scripts have finished loading.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```svelte
|
|
172
|
+
* <script>
|
|
173
|
+
* import { gtmIsReady } from '@jwiedeman/gtm-kit-svelte';
|
|
174
|
+
*
|
|
175
|
+
* const isReady = gtmIsReady();
|
|
176
|
+
*
|
|
177
|
+
* // Check if GTM is ready
|
|
178
|
+
* if ($isReady()) {
|
|
179
|
+
* console.log('GTM is ready');
|
|
180
|
+
* }
|
|
181
|
+
* </script>
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
declare function gtmIsReady(): Readable<() => boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Teardown the GTM client and clean up resources.
|
|
187
|
+
* Call this in your component's onDestroy lifecycle hook.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```svelte
|
|
191
|
+
* <script>
|
|
192
|
+
* import { createGtmStore, setGtmContext, destroyGtmStore } from '@jwiedeman/gtm-kit-svelte';
|
|
193
|
+
* import { onDestroy } from 'svelte';
|
|
194
|
+
*
|
|
195
|
+
* const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });
|
|
196
|
+
* setGtmContext(gtm);
|
|
197
|
+
*
|
|
198
|
+
* onDestroy(() => {
|
|
199
|
+
* destroyGtmStore(gtm);
|
|
200
|
+
* });
|
|
201
|
+
* </script>
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function destroyGtmStore(store: Writable<GtmStoreValue>): void;
|
|
164
205
|
|
|
165
|
-
export { GtmConsentApi, GtmStoreOptions, GtmStoreValue, createGtmStore, getGtmContext, gtmClient, gtmConsent, gtmContext, gtmPush, gtmReady, setGtmContext };
|
|
206
|
+
export { GtmConsentApi, GtmStoreOptions, GtmStoreValue, createGtmStore, destroyGtmStore, getGtmContext, gtmClient, gtmConsent, gtmContext, gtmIsReady, gtmPush, gtmReady, setGtmContext };
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,91 @@ import { writable, derived } from 'svelte/store';
|
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
3
|
import { createGtmClient } from '@jwiedeman/gtm-kit';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// src/store.ts
|
|
6
|
+
var GTM_CONTEXT_KEY = Symbol("gtm-kit");
|
|
7
|
+
function createGtmStore(options) {
|
|
8
|
+
const { autoInit = true, onBeforeInit, ...clientOptions } = options;
|
|
9
|
+
const client = createGtmClient(clientOptions);
|
|
10
|
+
const initialValue = {
|
|
11
|
+
client,
|
|
12
|
+
push: (value) => client.push(value),
|
|
13
|
+
setConsentDefaults: (state, regionOptions) => client.setConsentDefaults(state, regionOptions),
|
|
14
|
+
updateConsent: (state, regionOptions) => client.updateConsent(state, regionOptions),
|
|
15
|
+
isReady: () => client.isReady(),
|
|
16
|
+
whenReady: () => client.whenReady(),
|
|
17
|
+
onReady: (callback) => client.onReady(callback),
|
|
18
|
+
initialized: false
|
|
19
|
+
};
|
|
20
|
+
const store = writable(initialValue);
|
|
21
|
+
if (onBeforeInit) {
|
|
22
|
+
onBeforeInit(client);
|
|
23
|
+
}
|
|
24
|
+
if (autoInit) {
|
|
25
|
+
client.init();
|
|
26
|
+
store.update((s) => ({ ...s, initialized: true }));
|
|
27
|
+
}
|
|
28
|
+
return store;
|
|
29
|
+
}
|
|
30
|
+
function getGtmContext() {
|
|
31
|
+
const context = getContext(GTM_CONTEXT_KEY);
|
|
32
|
+
if (!context) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"[gtm-kit/svelte] getGtmContext() was called outside of a component tree with GTM context. Make sure to call setGtmContext() in a parent component."
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return context;
|
|
38
|
+
}
|
|
39
|
+
function setGtmContext(store) {
|
|
40
|
+
try {
|
|
41
|
+
const existing = getContext(GTM_CONTEXT_KEY);
|
|
42
|
+
if (existing) {
|
|
43
|
+
if (process.env.NODE_ENV !== "production") {
|
|
44
|
+
console.warn(
|
|
45
|
+
"[gtm-kit/svelte] setGtmContext() was called when a GTM context already exists. You should only have one GTM context at the root of your app. The duplicate context will be ignored."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
}
|
|
52
|
+
setContext(GTM_CONTEXT_KEY, store);
|
|
53
|
+
}
|
|
54
|
+
var gtmContext = getGtmContext;
|
|
55
|
+
function gtmPush() {
|
|
56
|
+
const store = getGtmContext();
|
|
57
|
+
return derived(store, ($store) => $store.push);
|
|
58
|
+
}
|
|
59
|
+
function gtmConsent() {
|
|
60
|
+
const store = getGtmContext();
|
|
61
|
+
return derived(store, ($store) => ({
|
|
62
|
+
setConsentDefaults: $store.setConsentDefaults,
|
|
63
|
+
updateConsent: $store.updateConsent
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
function gtmClient() {
|
|
67
|
+
const store = getGtmContext();
|
|
68
|
+
return derived(store, ($store) => $store.client);
|
|
69
|
+
}
|
|
70
|
+
function gtmReady() {
|
|
71
|
+
const store = getGtmContext();
|
|
72
|
+
return derived(store, ($store) => $store.whenReady);
|
|
73
|
+
}
|
|
74
|
+
function gtmIsReady() {
|
|
75
|
+
const store = getGtmContext();
|
|
76
|
+
return derived(store, ($store) => $store.isReady);
|
|
77
|
+
}
|
|
78
|
+
function destroyGtmStore(store) {
|
|
79
|
+
let storeValue = null;
|
|
80
|
+
const unsubscribe = store.subscribe((value) => {
|
|
81
|
+
storeValue = value;
|
|
82
|
+
});
|
|
83
|
+
unsubscribe();
|
|
84
|
+
if (storeValue !== null) {
|
|
85
|
+
storeValue.client.teardown();
|
|
86
|
+
store.update((s) => ({ ...s, initialized: false }));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
6
89
|
|
|
7
|
-
export {
|
|
90
|
+
export { createGtmStore, destroyGtmStore, getGtmContext, gtmClient, gtmConsent, gtmContext, gtmIsReady, gtmPush, gtmReady, setGtmContext };
|
|
8
91
|
//# sourceMappingURL=out.js.map
|
|
9
92
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts"],"names":["writable","derived","getContext","setContext","createGtmClient","GTM_CONTEXT_KEY","createGtmStore","options","autoInit","onBeforeInit","clientOptions","client","store","value","state","regionOptions","callback","s","getGtmContext","context","setGtmContext","gtmContext","gtmPush","$store","gtmConsent","gtmClient","gtmReady"],"mappings":"AAAA,OAAS,YAAAA,EAAU,WAAAC,MAA6C,eAChE,OAAS,cAAAC,EAAY,cAAAC,MAAkB,SACvC,OACE,mBAAAC,MAOK,qBAiDP,IAAMC,EAAkB,OAAO,SAAS,EAgBjC,SAASC,EAAeC,EAAmD,CAChF,GAAM,CAAE,SAAAC,EAAW,GAAM,aAAAC,EAAc,GAAGC,CAAc,EAAIH,EAEtDI,EAASP,EAAgBM,CAAa,EActCE,EAAQZ,EAZsB,CAClC,OAAAW,EACA,KAAOE,GAA0BF,EAAO,KAAKE,CAAK,EAClD,mBAAoB,CAACC,EAAqBC,IACxCJ,EAAO,mBAAmBG,EAAOC,CAAa,EAChD,cAAe,CAACD,EAAqBC,IACnCJ,EAAO,cAAcG,EAAOC,CAAa,EAC3C,UAAW,IAAMJ,EAAO,UAAU,EAClC,QAAUK,GAAiDL,EAAO,QAAQK,CAAQ,EAClF,YAAa,EACf,CAEkD,EAGlD,OAAIP,GACFA,EAAaE,CAAM,EAIjBH,IACFG,EAAO,KAAK,EACZC,EAAM,OAAQK,IAAO,CAAE,GAAGA,EAAG,YAAa,EAAK,EAAE,GAG5CL,CACT,CAgBO,SAASM,GAAyC,CACvD,IAAMC,EAAUjB,EAAoCG,CAAe,EACnE,GAAI,CAACc,EACH,MAAM,IAAI,MACR,6IAEF,EAEF,OAAOA,CACT,CAkBO,SAASC,EAAcR,EAAsC,CAClET,EAAWE,EAAiBO,CAAK,CACnC,CAKO,IAAMS,EAAaH,EAmBnB,SAASI,GAAqD,CACnE,IAAMV,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,IAAI,CAC/C,CAkBO,SAASC,GAAsC,CACpD,IAAMZ,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,IAAY,CACjC,mBAAoBA,EAAO,mBAC3B,cAAeA,EAAO,aACxB,EAAE,CACJ,CAcO,SAASE,GAAiC,CAC/C,IAAMb,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,MAAM,CACjD,CAoBO,SAASG,GAAuD,CACrE,IAAMd,EAAQM,EAAc,EAC5B,OAAOjB,EAAQW,EAAQW,GAAWA,EAAO,SAAS,CACpD","sourcesContent":["import { writable, derived, type Writable, type Readable } from 'svelte/store';\nimport { getContext, setContext } from 'svelte';\nimport {\n createGtmClient,\n type ConsentRegionOptions,\n type ConsentState,\n type CreateGtmClientOptions,\n type DataLayerValue,\n type GtmClient,\n type ScriptLoadState\n} from '@jwiedeman/gtm-kit';\n\n/**\n * Options for creating a GTM store.\n * Extends CreateGtmClientOptions with Svelte-specific options.\n */\nexport interface GtmStoreOptions extends CreateGtmClientOptions {\n /**\n * Whether to automatically initialize GTM when the store is created.\n * @default true\n */\n autoInit?: boolean;\n\n /**\n * Callback executed before GTM initialization.\n * Use this to set consent defaults.\n */\n onBeforeInit?: (client: GtmClient) => void;\n}\n\n/**\n * The GTM store value containing all GTM functionality.\n */\nexport interface GtmStoreValue {\n /** The underlying GTM client instance */\n client: GtmClient;\n /** Push a value to the data layer */\n push: (value: DataLayerValue) => void;\n /** Set consent defaults (must be called before init) */\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Update consent state */\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Returns a promise that resolves when all GTM scripts are loaded */\n whenReady: () => Promise<ScriptLoadState[]>;\n /** Register a callback for when GTM scripts are ready */\n onReady: (callback: (state: ScriptLoadState[]) => void) => () => void;\n /** Whether GTM has been initialized */\n initialized: boolean;\n}\n\n/**\n * Consent-specific API subset.\n */\nexport interface GtmConsentApi {\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n}\n\n/** Context key for GTM store */\nconst GTM_CONTEXT_KEY = Symbol('gtm-kit');\n\n/**\n * Create a GTM store for Svelte.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n * ```\n */\nexport function createGtmStore(options: GtmStoreOptions): Writable<GtmStoreValue> {\n const { autoInit = true, onBeforeInit, ...clientOptions } = options;\n\n const client = createGtmClient(clientOptions);\n\n const initialValue: GtmStoreValue = {\n client,\n push: (value: DataLayerValue) => client.push(value),\n setConsentDefaults: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.setConsentDefaults(state, regionOptions),\n updateConsent: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.updateConsent(state, regionOptions),\n whenReady: () => client.whenReady(),\n onReady: (callback: (state: ScriptLoadState[]) => void) => client.onReady(callback),\n initialized: false\n };\n\n const store = writable<GtmStoreValue>(initialValue);\n\n // Call onBeforeInit hook if provided (for consent defaults)\n if (onBeforeInit) {\n onBeforeInit(client);\n }\n\n // Auto-initialize if enabled\n if (autoInit) {\n client.init();\n store.update((s) => ({ ...s, initialized: true }));\n }\n\n return store;\n}\n\n/**\n * Get the GTM context from a parent component.\n * Must be called during component initialization.\n *\n * @example\n * ```svelte\n * <script>\n * import { getGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = getGtmContext();\n * $: ({ push } = $gtm);\n * </script>\n * ```\n */\nexport function getGtmContext(): Writable<GtmStoreValue> {\n const context = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (!context) {\n throw new Error(\n '[gtm-kit] getGtmContext() was called outside of a component tree with GTM context. ' +\n 'Make sure to call setGtmContext() in a parent component.'\n );\n }\n return context;\n}\n\n/**\n * Set the GTM context for child components.\n * Call this in your root layout or App component.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n *\n * <slot />\n * ```\n */\nexport function setGtmContext(store: Writable<GtmStoreValue>): void {\n setContext(GTM_CONTEXT_KEY, store);\n}\n\n/**\n * Alias for getGtmContext() - get the full GTM store.\n */\nexport const gtmContext = getGtmContext;\n\n/**\n * Get a derived store that provides just the push function.\n * Use this when you only need to push events.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmPush } from '@jwiedeman/gtm-kit-svelte';\n *\n * const push = gtmPush();\n *\n * function handleClick() {\n * $push({ event: 'button_click' });\n * }\n * </script>\n * ```\n */\nexport function gtmPush(): Readable<(value: DataLayerValue) => void> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.push);\n}\n\n/**\n * Get a derived store that provides consent functions.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmConsent } from '@jwiedeman/gtm-kit-svelte';\n *\n * const consent = gtmConsent();\n *\n * function acceptAll() {\n * $consent.updateConsent({ analytics_storage: 'granted' });\n * }\n * </script>\n * ```\n */\nexport function gtmConsent(): Readable<GtmConsentApi> {\n const store = getGtmContext();\n return derived(store, ($store) => ({\n setConsentDefaults: $store.setConsentDefaults,\n updateConsent: $store.updateConsent\n }));\n}\n\n/**\n * Get a derived store that provides the raw GTM client.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmClient } from '@jwiedeman/gtm-kit-svelte';\n *\n * const client = gtmClient();\n * </script>\n * ```\n */\nexport function gtmClient(): Readable<GtmClient> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.client);\n}\n\n/**\n * Get a derived store that provides the whenReady function.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmReady } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const whenReady = gtmReady();\n *\n * onMount(async () => {\n * const states = await $whenReady();\n * console.log('GTM loaded:', states);\n * });\n * </script>\n * ```\n */\nexport function gtmReady(): Readable<() => Promise<ScriptLoadState[]>> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.whenReady);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store.ts"],"names":[],"mappings":";AAAA,SAAS,UAAU,eAA6C;AAChE,SAAS,YAAY,kBAAkB;AACvC;AAAA,EACE;AAAA,OAOK;AAmDP,IAAM,kBAAkB,OAAO,SAAS;AAgBjC,SAAS,eAAe,SAAmD;AAChF,QAAM,EAAE,WAAW,MAAM,cAAc,GAAG,cAAc,IAAI;AAE5D,QAAM,SAAS,gBAAgB,aAAa;AAE5C,QAAM,eAA8B;AAAA,IAClC;AAAA,IACA,MAAM,CAAC,UAA0B,OAAO,KAAK,KAAK;AAAA,IAClD,oBAAoB,CAAC,OAAqB,kBACxC,OAAO,mBAAmB,OAAO,aAAa;AAAA,IAChD,eAAe,CAAC,OAAqB,kBACnC,OAAO,cAAc,OAAO,aAAa;AAAA,IAC3C,SAAS,MAAM,OAAO,QAAQ;AAAA,IAC9B,WAAW,MAAM,OAAO,UAAU;AAAA,IAClC,SAAS,CAAC,aAAiD,OAAO,QAAQ,QAAQ;AAAA,IAClF,aAAa;AAAA,EACf;AAEA,QAAM,QAAQ,SAAwB,YAAY;AAGlD,MAAI,cAAc;AAChB,iBAAa,MAAM;AAAA,EACrB;AAGA,MAAI,UAAU;AACZ,WAAO,KAAK;AACZ,UAAM,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,aAAa,KAAK,EAAE;AAAA,EACnD;AAEA,SAAO;AACT;AAgBO,SAAS,gBAAyC;AACvD,QAAM,UAAU,WAAoC,eAAe;AACnE,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAkBO,SAAS,cAAc,OAAsC;AAElE,MAAI;AACF,UAAM,WAAW,WAAoC,eAAe;AACpE,QAAI,UAAU;AACZ,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,gBAAQ;AAAA,UACN;AAAA,QAGF;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF,SAAQ;AAAA,EAER;AACA,aAAW,iBAAiB,KAAK;AACnC;AAKO,IAAM,aAAa;AAmBnB,SAAS,UAAqD;AACnE,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,IAAI;AAC/C;AAkBO,SAAS,aAAsC;AACpD,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,YAAY;AAAA,IACjC,oBAAoB,OAAO;AAAA,IAC3B,eAAe,OAAO;AAAA,EACxB,EAAE;AACJ;AAcO,SAAS,YAAiC;AAC/C,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,MAAM;AACjD;AAoBO,SAAS,WAAuD;AACrE,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS;AACpD;AAoBO,SAAS,aAAsC;AACpD,QAAM,QAAQ,cAAc;AAC5B,SAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,OAAO;AAClD;AAqBO,SAAS,gBAAgB,OAAsC;AACpE,MAAI,aAAmC;AAGvC,QAAM,cAAc,MAAM,UAAU,CAAC,UAAU;AAC7C,iBAAa;AAAA,EACf,CAAC;AACD,cAAY;AAGZ,MAAI,eAAe,MAAM;AACvB,IAAC,WAA6B,OAAO,SAAS;AAC9C,UAAM,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,aAAa,MAAM,EAAE;AAAA,EACpD;AACF","sourcesContent":["import { writable, derived, type Writable, type Readable } from 'svelte/store';\nimport { getContext, setContext } from 'svelte';\nimport {\n createGtmClient,\n type ConsentRegionOptions,\n type ConsentState,\n type CreateGtmClientOptions,\n type DataLayerValue,\n type GtmClient,\n type ScriptLoadState\n} from '@jwiedeman/gtm-kit';\n\n/**\n * Options for creating a GTM store.\n * Extends CreateGtmClientOptions with Svelte-specific options.\n */\nexport interface GtmStoreOptions extends CreateGtmClientOptions {\n /**\n * Whether to automatically initialize GTM when the store is created.\n * @default true\n */\n autoInit?: boolean;\n\n /**\n * Callback executed before GTM initialization.\n * Use this to set consent defaults.\n */\n onBeforeInit?: (client: GtmClient) => void;\n}\n\n/**\n * The GTM store value containing all GTM functionality.\n */\nexport interface GtmStoreValue {\n /** The underlying GTM client instance */\n client: GtmClient;\n /** Push a value to the data layer */\n push: (value: DataLayerValue) => void;\n /** Set consent defaults (must be called before init) */\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Update consent state */\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n /** Synchronously check if all GTM scripts have finished loading */\n isReady: () => boolean;\n /** Returns a promise that resolves when all GTM scripts are loaded */\n whenReady: () => Promise<ScriptLoadState[]>;\n /** Register a callback for when GTM scripts are ready */\n onReady: (callback: (state: ScriptLoadState[]) => void) => () => void;\n /** Whether GTM has been initialized */\n initialized: boolean;\n}\n\n/**\n * Consent-specific API subset.\n */\nexport interface GtmConsentApi {\n setConsentDefaults: (state: ConsentState, options?: ConsentRegionOptions) => void;\n updateConsent: (state: ConsentState, options?: ConsentRegionOptions) => void;\n}\n\n/** Context key for GTM store */\nconst GTM_CONTEXT_KEY = Symbol('gtm-kit');\n\n/**\n * Create a GTM store for Svelte.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n * ```\n */\nexport function createGtmStore(options: GtmStoreOptions): Writable<GtmStoreValue> {\n const { autoInit = true, onBeforeInit, ...clientOptions } = options;\n\n const client = createGtmClient(clientOptions);\n\n const initialValue: GtmStoreValue = {\n client,\n push: (value: DataLayerValue) => client.push(value),\n setConsentDefaults: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.setConsentDefaults(state, regionOptions),\n updateConsent: (state: ConsentState, regionOptions?: ConsentRegionOptions) =>\n client.updateConsent(state, regionOptions),\n isReady: () => client.isReady(),\n whenReady: () => client.whenReady(),\n onReady: (callback: (state: ScriptLoadState[]) => void) => client.onReady(callback),\n initialized: false\n };\n\n const store = writable<GtmStoreValue>(initialValue);\n\n // Call onBeforeInit hook if provided (for consent defaults)\n if (onBeforeInit) {\n onBeforeInit(client);\n }\n\n // Auto-initialize if enabled\n if (autoInit) {\n client.init();\n store.update((s) => ({ ...s, initialized: true }));\n }\n\n return store;\n}\n\n/**\n * Get the GTM context from a parent component.\n * Must be called during component initialization.\n *\n * @example\n * ```svelte\n * <script>\n * import { getGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = getGtmContext();\n * $: ({ push } = $gtm);\n * </script>\n * ```\n */\nexport function getGtmContext(): Writable<GtmStoreValue> {\n const context = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (!context) {\n throw new Error(\n '[gtm-kit/svelte] getGtmContext() was called outside of a component tree with GTM context. ' +\n 'Make sure to call setGtmContext() in a parent component.'\n );\n }\n return context;\n}\n\n/**\n * Set the GTM context for child components.\n * Call this in your root layout or App component.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext } from '@jwiedeman/gtm-kit-svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n * </script>\n *\n * <slot />\n * ```\n */\nexport function setGtmContext(store: Writable<GtmStoreValue>): void {\n // Check if a context already exists (nested context)\n try {\n const existing = getContext<Writable<GtmStoreValue>>(GTM_CONTEXT_KEY);\n if (existing) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n '[gtm-kit/svelte] setGtmContext() was called when a GTM context already exists. ' +\n 'You should only have one GTM context at the root of your app. ' +\n 'The duplicate context will be ignored.'\n );\n }\n return;\n }\n } catch {\n // getContext throws when called outside component initialization, which is fine\n }\n setContext(GTM_CONTEXT_KEY, store);\n}\n\n/**\n * Alias for getGtmContext() - get the full GTM store.\n */\nexport const gtmContext = getGtmContext;\n\n/**\n * Get a derived store that provides just the push function.\n * Use this when you only need to push events.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmPush } from '@jwiedeman/gtm-kit-svelte';\n *\n * const push = gtmPush();\n *\n * function handleClick() {\n * $push({ event: 'button_click' });\n * }\n * </script>\n * ```\n */\nexport function gtmPush(): Readable<(value: DataLayerValue) => void> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.push);\n}\n\n/**\n * Get a derived store that provides consent functions.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmConsent } from '@jwiedeman/gtm-kit-svelte';\n *\n * const consent = gtmConsent();\n *\n * function acceptAll() {\n * $consent.updateConsent({ analytics_storage: 'granted' });\n * }\n * </script>\n * ```\n */\nexport function gtmConsent(): Readable<GtmConsentApi> {\n const store = getGtmContext();\n return derived(store, ($store) => ({\n setConsentDefaults: $store.setConsentDefaults,\n updateConsent: $store.updateConsent\n }));\n}\n\n/**\n * Get a derived store that provides the raw GTM client.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmClient } from '@jwiedeman/gtm-kit-svelte';\n *\n * const client = gtmClient();\n * </script>\n * ```\n */\nexport function gtmClient(): Readable<GtmClient> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.client);\n}\n\n/**\n * Get a derived store that provides the whenReady function.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmReady } from '@jwiedeman/gtm-kit-svelte';\n * import { onMount } from 'svelte';\n *\n * const whenReady = gtmReady();\n *\n * onMount(async () => {\n * const states = await $whenReady();\n * console.log('GTM loaded:', states);\n * });\n * </script>\n * ```\n */\nexport function gtmReady(): Readable<() => Promise<ScriptLoadState[]>> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.whenReady);\n}\n\n/**\n * Get a derived store that provides the isReady function.\n * Use this to check synchronously if GTM scripts have finished loading.\n *\n * @example\n * ```svelte\n * <script>\n * import { gtmIsReady } from '@jwiedeman/gtm-kit-svelte';\n *\n * const isReady = gtmIsReady();\n *\n * // Check if GTM is ready\n * if ($isReady()) {\n * console.log('GTM is ready');\n * }\n * </script>\n * ```\n */\nexport function gtmIsReady(): Readable<() => boolean> {\n const store = getGtmContext();\n return derived(store, ($store) => $store.isReady);\n}\n\n/**\n * Teardown the GTM client and clean up resources.\n * Call this in your component's onDestroy lifecycle hook.\n *\n * @example\n * ```svelte\n * <script>\n * import { createGtmStore, setGtmContext, destroyGtmStore } from '@jwiedeman/gtm-kit-svelte';\n * import { onDestroy } from 'svelte';\n *\n * const gtm = createGtmStore({ containers: 'GTM-XXXXXX' });\n * setGtmContext(gtm);\n *\n * onDestroy(() => {\n * destroyGtmStore(gtm);\n * });\n * </script>\n * ```\n */\nexport function destroyGtmStore(store: Writable<GtmStoreValue>): void {\n let storeValue: GtmStoreValue | null = null;\n\n // Get the store value synchronously\n const unsubscribe = store.subscribe((value) => {\n storeValue = value;\n });\n unsubscribe();\n\n // Teardown the client\n if (storeValue !== null) {\n (storeValue as GtmStoreValue).client.teardown();\n store.update((s) => ({ ...s, initialized: false }));\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jwiedeman/gtm-kit-svelte",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Svelte stores and actions for GTM Kit - Google Tag Manager integration with SvelteKit SSR support.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"typecheck": "tsc --noEmit"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@jwiedeman/gtm-kit": "^1.
|
|
54
|
+
"@jwiedeman/gtm-kit": "^1.2.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"svelte": "^4.0.0 || ^5.0.0"
|