@zerocost/sdk 0.14.0 → 0.15.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.
@@ -1,2 +1,3 @@
1
1
  export declare const EDGE_FUNCTION_BASE = "https://mwbgzpbuoojqsuxduieo.supabase.co/functions/v1";
2
+ export { ZEROCOST_BASE_URL } from './constants';
2
3
  export declare function getBaseUrl(custom?: string): string;
@@ -1,12 +1,3 @@
1
- /**
2
- * consent-ui.ts — Pure DOM consent popup for the Zerocost SDK.
3
- *
4
- * - Desktop: centered card modal (max 480px)
5
- * - Mobile (≤640px): bottom-sheet modal
6
- * - Themes: light / dark / auto
7
- * - Non-dismissable (no Escape, no backdrop click)
8
- * - Returns a Promise that resolves with the user's toggle selections
9
- */
10
1
  export interface ConsentUIOptions {
11
2
  appName: string;
12
3
  theme: 'light' | 'dark' | 'auto';
@@ -34,4 +34,6 @@ export declare class ConsentManager {
34
34
  private getOrCreateUserId;
35
35
  private generateUUID;
36
36
  private submitToServer;
37
+ private injectSettingsButton;
38
+ private removeSettingsButton;
37
39
  }
@@ -0,0 +1,6 @@
1
+ export declare const ZEROCOST_DOMAINS: {
2
+ MAIN: string;
3
+ APP: string;
4
+ DOCS: string;
5
+ };
6
+ export declare const ZEROCOST_BASE_URL: string;
package/dist/index.cjs CHANGED
@@ -28,6 +28,14 @@ __export(index_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(index_exports);
30
30
 
31
+ // src/core/constants.ts
32
+ var ZEROCOST_DOMAINS = {
33
+ MAIN: "https://zerocost.lovable.app",
34
+ APP: "https://app.zerocost.com",
35
+ DOCS: "https://docs.zerocost.com"
36
+ };
37
+ var ZEROCOST_BASE_URL = ZEROCOST_DOMAINS.MAIN;
38
+
31
39
  // src/core/config.ts
32
40
  var EDGE_FUNCTION_BASE = "https://mwbgzpbuoojqsuxduieo.supabase.co/functions/v1";
33
41
  function getBaseUrl(custom) {
@@ -70,7 +78,7 @@ var ZerocostClient = class {
70
78
  ...body || {},
71
79
  app_id: this.config.appId
72
80
  };
73
- this.log(`\u2192 ${url}`, payload);
81
+ this.log(`\u2192 ${path}`, payload);
74
82
  const res = await fetch(url, {
75
83
  method: "POST",
76
84
  headers: {
@@ -89,7 +97,8 @@ var ZerocostClient = class {
89
97
  }
90
98
  log(message, data) {
91
99
  if (this.config.debug) {
92
- console.log(`[Zerocost] ${message}`, data ?? "");
100
+ const sanitizedMessage = typeof message === "string" ? message.replace(/https:\/\/[a-z0-9.-]+\.supabase\.co/gi, "[INFRA]") : message;
101
+ console.log(`[Zerocost] ${sanitizedMessage}`, data ?? "");
93
102
  }
94
103
  }
95
104
  };
@@ -1589,6 +1598,44 @@ function injectStyles(theme) {
1589
1598
  .zc-consent-confirm:active {
1590
1599
  opacity: 0.75;
1591
1600
  }
1601
+
1602
+ /* Floating settings button */
1603
+ .zc-settings-btn {
1604
+ position: fixed;
1605
+ width: 44px;
1606
+ height: 44px;
1607
+ border-radius: 50%;
1608
+ background: var(--zc-bg);
1609
+ border: 1px solid var(--zc-border);
1610
+ color: var(--zc-text);
1611
+ display: flex;
1612
+ align-items: center;
1613
+ justify-content: center;
1614
+ cursor: pointer;
1615
+ z-index: 999998;
1616
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1617
+ transition: transform 200ms, border-color 200ms;
1618
+ }
1619
+
1620
+ .zc-settings-btn:hover {
1621
+ transform: scale(1.05);
1622
+ border-color: var(--zc-text-secondary);
1623
+ }
1624
+
1625
+ .zc-settings-btn svg {
1626
+ width: 20px;
1627
+ height: 20px;
1628
+ }
1629
+
1630
+ .zc-settings-bottom-left { bottom: 20px; left: 20px; }
1631
+ .zc-settings-bottom-right { bottom: 20px; right: 20px; }
1632
+ .zc-settings-top-left { top: 20px; left: 20px; }
1633
+ .zc-settings-top-right { top: 20px; right: 20px; }
1634
+
1635
+ @media (max-width: 640px) {
1636
+ .zc-settings-btn { width: 40px; height: 40px; }
1637
+ .zc-settings-bottom-left, .zc-settings-bottom-right { bottom: 16px; }
1638
+ }
1592
1639
  `;
1593
1640
  const style = document.createElement("style");
1594
1641
  style.id = STYLE_ID;
@@ -1671,33 +1718,33 @@ function showConsentUI(options) {
1671
1718
  card.appendChild(subtitle);
1672
1719
  const toggles = document.createElement("div");
1673
1720
  toggles.className = "zc-consent-toggles";
1674
- const baseUrl = typeof window !== "undefined" ? window.location.origin : "";
1721
+ const zerocostBaseUrl = ZEROCOST_BASE_URL;
1675
1722
  toggles.appendChild(createToggleCard(
1676
1723
  "zc-toggle-ads",
1677
1724
  "Ads",
1678
1725
  "Contextual, non-intrusive ads. No cookies or browsing history used.",
1679
- `${baseUrl}/consent/ads`,
1726
+ `${zerocostBaseUrl}/consent/ads`,
1680
1727
  defaults.ads
1681
1728
  ));
1682
1729
  toggles.appendChild(createToggleCard(
1683
1730
  "zc-toggle-usage",
1684
1731
  "Usage data",
1685
1732
  "Anonymized usage patterns. No personal information is shared.",
1686
- `${baseUrl}/consent/usage-data`,
1733
+ `${zerocostBaseUrl}/consent/usage-data`,
1687
1734
  defaults.usageData
1688
1735
  ));
1689
1736
  toggles.appendChild(createToggleCard(
1690
1737
  "zc-toggle-ai",
1691
1738
  "AI interactions",
1692
1739
  "Anonymized conversation data used for AI research.",
1693
- `${baseUrl}/consent/ai-interactions`,
1740
+ `${zerocostBaseUrl}/consent/ai-interactions`,
1694
1741
  defaults.aiInteractions
1695
1742
  ));
1696
1743
  card.appendChild(toggles);
1697
1744
  const footer = document.createElement("div");
1698
1745
  footer.className = "zc-consent-footer";
1699
1746
  const ppLink = document.createElement("a");
1700
- ppLink.href = privacyPolicyUrl || `${baseUrl}/privacy`;
1747
+ ppLink.href = privacyPolicyUrl || `${zerocostBaseUrl}/privacy`;
1701
1748
  ppLink.target = "_blank";
1702
1749
  ppLink.rel = "noopener noreferrer";
1703
1750
  ppLink.textContent = "Privacy Policy";
@@ -1707,7 +1754,7 @@ function showConsentUI(options) {
1707
1754
  sep1.textContent = "\xB7";
1708
1755
  footer.appendChild(sep1);
1709
1756
  const termsLink = document.createElement("a");
1710
- termsLink.href = `${baseUrl}/terms`;
1757
+ termsLink.href = `${zerocostBaseUrl}/terms`;
1711
1758
  termsLink.target = "_blank";
1712
1759
  termsLink.rel = "noopener noreferrer";
1713
1760
  termsLink.textContent = "Terms";
@@ -1717,7 +1764,7 @@ function showConsentUI(options) {
1717
1764
  sep2.textContent = "\xB7";
1718
1765
  footer.appendChild(sep2);
1719
1766
  const dnsLink = document.createElement("a");
1720
- dnsLink.href = `${baseUrl}/do-not-sell`;
1767
+ dnsLink.href = `${zerocostBaseUrl}/do-not-sell`;
1721
1768
  dnsLink.target = "_blank";
1722
1769
  dnsLink.rel = "noopener noreferrer";
1723
1770
  dnsLink.textContent = "Do Not Sell My Data";
@@ -1761,6 +1808,9 @@ var ConsentManager = class {
1761
1808
  this.appName = opts.appName ?? "";
1762
1809
  this.theme = opts.theme ?? "dark";
1763
1810
  this.hydrateFromStorage();
1811
+ if (this.consentConfig.showSettingsButton) {
1812
+ this.injectSettingsButton();
1813
+ }
1764
1814
  }
1765
1815
  // ── Public API (per spec §6.3) ───────────────────────────────────
1766
1816
  /** Returns the current consent record, or null if none exists. */
@@ -1826,6 +1876,9 @@ var ConsentManager = class {
1826
1876
  };
1827
1877
  this.record = record;
1828
1878
  this.writeStorage(record);
1879
+ if (this.consentConfig.showSettingsButton) {
1880
+ this.injectSettingsButton();
1881
+ }
1829
1882
  if (this.consentConfig.onConsentChange) {
1830
1883
  try {
1831
1884
  this.consentConfig.onConsentChange(record);
@@ -1904,6 +1957,23 @@ var ConsentManager = class {
1904
1957
  this.client.log(`Failed to submit consent to server: ${err}`);
1905
1958
  }
1906
1959
  }
1960
+ injectSettingsButton() {
1961
+ if (typeof document === "undefined") return;
1962
+ const existing = document.getElementById("zerocost-privacy-settings-btn");
1963
+ if (existing) return;
1964
+ const btn = document.createElement("button");
1965
+ btn.id = "zerocost-privacy-settings-btn";
1966
+ btn.setAttribute("aria-label", "Privacy Settings");
1967
+ btn.title = "Privacy Settings";
1968
+ const pos = this.consentConfig.buttonPosition || "bottom-left";
1969
+ btn.className = `zc-settings-btn zc-settings-${pos}`;
1970
+ btn.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>`;
1971
+ btn.addEventListener("click", () => this.open());
1972
+ document.body.appendChild(btn);
1973
+ }
1974
+ removeSettingsButton() {
1975
+ document.getElementById("zerocost-privacy-settings-btn")?.remove();
1976
+ }
1907
1977
  };
1908
1978
 
1909
1979
  // src/index.ts
@@ -1937,21 +2007,15 @@ var ZerocostSDK = class {
1937
2007
  });
1938
2008
  }
1939
2009
  async init() {
1940
- this.core.init();
1941
2010
  if (typeof document === "undefined") {
1942
- this.core.log("Running in non-browser environment; skipping DOM injection.");
1943
2011
  return;
1944
2012
  }
1945
2013
  if (window !== window.top) {
1946
- this.core.log("Running inside an iframe. Ads render if permissions allow.");
1947
2014
  }
1948
- this.core.log("Initializing Zerocost SDK.");
1949
2015
  if (this.consent.shouldPrompt()) {
1950
- this.core.log("Consent required \u2014 showing prompt.");
1951
2016
  await this.consent.promptAndWait();
1952
2017
  }
1953
2018
  if (!this.consent.has("ads")) {
1954
- this.core.log("Ads consent not granted \u2014 skipping ad injection.");
1955
2019
  return;
1956
2020
  }
1957
2021
  const cachedConfig = this.readCachedConfig();
@@ -1959,12 +2023,11 @@ var ZerocostSDK = class {
1959
2023
  this.lastConfigHash = this.configToHash(cachedConfig);
1960
2024
  this.syncDataCollection(cachedConfig.dataCollection);
1961
2025
  await this.widget.autoInjectWithConfig(cachedConfig.display, cachedConfig.widget);
1962
- this.core.log("Applied cached config immediately.");
1963
2026
  }
1964
2027
  this.startConfigSync();
1965
2028
  try {
1966
2029
  await this.refreshConfig({ force: true, reason: "init" });
1967
- this.core.log("SDK fully initialized. Ads are rendering automatically.");
2030
+ this.core.log(`Zerocost SDK initialized (${this.core.getConfig().appId})`);
1968
2031
  } catch (err) {
1969
2032
  this.core.log(`Init error: ${err}. Attempting fallback ad injection.`);
1970
2033
  await this.widget.autoInject();
@@ -2138,6 +2201,10 @@ var ZerocostSDK = class {
2138
2201
  return { valid: false, error: err.message };
2139
2202
  }
2140
2203
  }
2204
+ /** Open the consent/privacy settings popup. */
2205
+ async showSettings() {
2206
+ return this.consent.open();
2207
+ }
2141
2208
  };
2142
2209
  // Annotate the CommonJS export names for ESM import in node:
2143
2210
  0 && (module.exports = {
package/dist/index.d.ts CHANGED
@@ -39,6 +39,8 @@ export declare class ZerocostSDK {
39
39
  valid: boolean;
40
40
  error?: string;
41
41
  }>;
42
+ /** Open the consent/privacy settings popup. */
43
+ showSettings(): Promise<void>;
42
44
  }
43
45
  export * from './types';
44
46
  export { ZerocostClient } from './core/client';
package/dist/index.js CHANGED
@@ -1,3 +1,11 @@
1
+ // src/core/constants.ts
2
+ var ZEROCOST_DOMAINS = {
3
+ MAIN: "https://zerocost.lovable.app",
4
+ APP: "https://app.zerocost.com",
5
+ DOCS: "https://docs.zerocost.com"
6
+ };
7
+ var ZEROCOST_BASE_URL = ZEROCOST_DOMAINS.MAIN;
8
+
1
9
  // src/core/config.ts
2
10
  var EDGE_FUNCTION_BASE = "https://mwbgzpbuoojqsuxduieo.supabase.co/functions/v1";
3
11
  function getBaseUrl(custom) {
@@ -40,7 +48,7 @@ var ZerocostClient = class {
40
48
  ...body || {},
41
49
  app_id: this.config.appId
42
50
  };
43
- this.log(`\u2192 ${url}`, payload);
51
+ this.log(`\u2192 ${path}`, payload);
44
52
  const res = await fetch(url, {
45
53
  method: "POST",
46
54
  headers: {
@@ -59,7 +67,8 @@ var ZerocostClient = class {
59
67
  }
60
68
  log(message, data) {
61
69
  if (this.config.debug) {
62
- console.log(`[Zerocost] ${message}`, data ?? "");
70
+ const sanitizedMessage = typeof message === "string" ? message.replace(/https:\/\/[a-z0-9.-]+\.supabase\.co/gi, "[INFRA]") : message;
71
+ console.log(`[Zerocost] ${sanitizedMessage}`, data ?? "");
63
72
  }
64
73
  }
65
74
  };
@@ -1559,6 +1568,44 @@ function injectStyles(theme) {
1559
1568
  .zc-consent-confirm:active {
1560
1569
  opacity: 0.75;
1561
1570
  }
1571
+
1572
+ /* Floating settings button */
1573
+ .zc-settings-btn {
1574
+ position: fixed;
1575
+ width: 44px;
1576
+ height: 44px;
1577
+ border-radius: 50%;
1578
+ background: var(--zc-bg);
1579
+ border: 1px solid var(--zc-border);
1580
+ color: var(--zc-text);
1581
+ display: flex;
1582
+ align-items: center;
1583
+ justify-content: center;
1584
+ cursor: pointer;
1585
+ z-index: 999998;
1586
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1587
+ transition: transform 200ms, border-color 200ms;
1588
+ }
1589
+
1590
+ .zc-settings-btn:hover {
1591
+ transform: scale(1.05);
1592
+ border-color: var(--zc-text-secondary);
1593
+ }
1594
+
1595
+ .zc-settings-btn svg {
1596
+ width: 20px;
1597
+ height: 20px;
1598
+ }
1599
+
1600
+ .zc-settings-bottom-left { bottom: 20px; left: 20px; }
1601
+ .zc-settings-bottom-right { bottom: 20px; right: 20px; }
1602
+ .zc-settings-top-left { top: 20px; left: 20px; }
1603
+ .zc-settings-top-right { top: 20px; right: 20px; }
1604
+
1605
+ @media (max-width: 640px) {
1606
+ .zc-settings-btn { width: 40px; height: 40px; }
1607
+ .zc-settings-bottom-left, .zc-settings-bottom-right { bottom: 16px; }
1608
+ }
1562
1609
  `;
1563
1610
  const style = document.createElement("style");
1564
1611
  style.id = STYLE_ID;
@@ -1641,33 +1688,33 @@ function showConsentUI(options) {
1641
1688
  card.appendChild(subtitle);
1642
1689
  const toggles = document.createElement("div");
1643
1690
  toggles.className = "zc-consent-toggles";
1644
- const baseUrl = typeof window !== "undefined" ? window.location.origin : "";
1691
+ const zerocostBaseUrl = ZEROCOST_BASE_URL;
1645
1692
  toggles.appendChild(createToggleCard(
1646
1693
  "zc-toggle-ads",
1647
1694
  "Ads",
1648
1695
  "Contextual, non-intrusive ads. No cookies or browsing history used.",
1649
- `${baseUrl}/consent/ads`,
1696
+ `${zerocostBaseUrl}/consent/ads`,
1650
1697
  defaults.ads
1651
1698
  ));
1652
1699
  toggles.appendChild(createToggleCard(
1653
1700
  "zc-toggle-usage",
1654
1701
  "Usage data",
1655
1702
  "Anonymized usage patterns. No personal information is shared.",
1656
- `${baseUrl}/consent/usage-data`,
1703
+ `${zerocostBaseUrl}/consent/usage-data`,
1657
1704
  defaults.usageData
1658
1705
  ));
1659
1706
  toggles.appendChild(createToggleCard(
1660
1707
  "zc-toggle-ai",
1661
1708
  "AI interactions",
1662
1709
  "Anonymized conversation data used for AI research.",
1663
- `${baseUrl}/consent/ai-interactions`,
1710
+ `${zerocostBaseUrl}/consent/ai-interactions`,
1664
1711
  defaults.aiInteractions
1665
1712
  ));
1666
1713
  card.appendChild(toggles);
1667
1714
  const footer = document.createElement("div");
1668
1715
  footer.className = "zc-consent-footer";
1669
1716
  const ppLink = document.createElement("a");
1670
- ppLink.href = privacyPolicyUrl || `${baseUrl}/privacy`;
1717
+ ppLink.href = privacyPolicyUrl || `${zerocostBaseUrl}/privacy`;
1671
1718
  ppLink.target = "_blank";
1672
1719
  ppLink.rel = "noopener noreferrer";
1673
1720
  ppLink.textContent = "Privacy Policy";
@@ -1677,7 +1724,7 @@ function showConsentUI(options) {
1677
1724
  sep1.textContent = "\xB7";
1678
1725
  footer.appendChild(sep1);
1679
1726
  const termsLink = document.createElement("a");
1680
- termsLink.href = `${baseUrl}/terms`;
1727
+ termsLink.href = `${zerocostBaseUrl}/terms`;
1681
1728
  termsLink.target = "_blank";
1682
1729
  termsLink.rel = "noopener noreferrer";
1683
1730
  termsLink.textContent = "Terms";
@@ -1687,7 +1734,7 @@ function showConsentUI(options) {
1687
1734
  sep2.textContent = "\xB7";
1688
1735
  footer.appendChild(sep2);
1689
1736
  const dnsLink = document.createElement("a");
1690
- dnsLink.href = `${baseUrl}/do-not-sell`;
1737
+ dnsLink.href = `${zerocostBaseUrl}/do-not-sell`;
1691
1738
  dnsLink.target = "_blank";
1692
1739
  dnsLink.rel = "noopener noreferrer";
1693
1740
  dnsLink.textContent = "Do Not Sell My Data";
@@ -1731,6 +1778,9 @@ var ConsentManager = class {
1731
1778
  this.appName = opts.appName ?? "";
1732
1779
  this.theme = opts.theme ?? "dark";
1733
1780
  this.hydrateFromStorage();
1781
+ if (this.consentConfig.showSettingsButton) {
1782
+ this.injectSettingsButton();
1783
+ }
1734
1784
  }
1735
1785
  // ── Public API (per spec §6.3) ───────────────────────────────────
1736
1786
  /** Returns the current consent record, or null if none exists. */
@@ -1796,6 +1846,9 @@ var ConsentManager = class {
1796
1846
  };
1797
1847
  this.record = record;
1798
1848
  this.writeStorage(record);
1849
+ if (this.consentConfig.showSettingsButton) {
1850
+ this.injectSettingsButton();
1851
+ }
1799
1852
  if (this.consentConfig.onConsentChange) {
1800
1853
  try {
1801
1854
  this.consentConfig.onConsentChange(record);
@@ -1874,6 +1927,23 @@ var ConsentManager = class {
1874
1927
  this.client.log(`Failed to submit consent to server: ${err}`);
1875
1928
  }
1876
1929
  }
1930
+ injectSettingsButton() {
1931
+ if (typeof document === "undefined") return;
1932
+ const existing = document.getElementById("zerocost-privacy-settings-btn");
1933
+ if (existing) return;
1934
+ const btn = document.createElement("button");
1935
+ btn.id = "zerocost-privacy-settings-btn";
1936
+ btn.setAttribute("aria-label", "Privacy Settings");
1937
+ btn.title = "Privacy Settings";
1938
+ const pos = this.consentConfig.buttonPosition || "bottom-left";
1939
+ btn.className = `zc-settings-btn zc-settings-${pos}`;
1940
+ btn.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>`;
1941
+ btn.addEventListener("click", () => this.open());
1942
+ document.body.appendChild(btn);
1943
+ }
1944
+ removeSettingsButton() {
1945
+ document.getElementById("zerocost-privacy-settings-btn")?.remove();
1946
+ }
1877
1947
  };
1878
1948
 
1879
1949
  // src/index.ts
@@ -1907,21 +1977,15 @@ var ZerocostSDK = class {
1907
1977
  });
1908
1978
  }
1909
1979
  async init() {
1910
- this.core.init();
1911
1980
  if (typeof document === "undefined") {
1912
- this.core.log("Running in non-browser environment; skipping DOM injection.");
1913
1981
  return;
1914
1982
  }
1915
1983
  if (window !== window.top) {
1916
- this.core.log("Running inside an iframe. Ads render if permissions allow.");
1917
1984
  }
1918
- this.core.log("Initializing Zerocost SDK.");
1919
1985
  if (this.consent.shouldPrompt()) {
1920
- this.core.log("Consent required \u2014 showing prompt.");
1921
1986
  await this.consent.promptAndWait();
1922
1987
  }
1923
1988
  if (!this.consent.has("ads")) {
1924
- this.core.log("Ads consent not granted \u2014 skipping ad injection.");
1925
1989
  return;
1926
1990
  }
1927
1991
  const cachedConfig = this.readCachedConfig();
@@ -1929,12 +1993,11 @@ var ZerocostSDK = class {
1929
1993
  this.lastConfigHash = this.configToHash(cachedConfig);
1930
1994
  this.syncDataCollection(cachedConfig.dataCollection);
1931
1995
  await this.widget.autoInjectWithConfig(cachedConfig.display, cachedConfig.widget);
1932
- this.core.log("Applied cached config immediately.");
1933
1996
  }
1934
1997
  this.startConfigSync();
1935
1998
  try {
1936
1999
  await this.refreshConfig({ force: true, reason: "init" });
1937
- this.core.log("SDK fully initialized. Ads are rendering automatically.");
2000
+ this.core.log(`Zerocost SDK initialized (${this.core.getConfig().appId})`);
1938
2001
  } catch (err) {
1939
2002
  this.core.log(`Init error: ${err}. Attempting fallback ad injection.`);
1940
2003
  await this.widget.autoInject();
@@ -2108,6 +2171,10 @@ var ZerocostSDK = class {
2108
2171
  return { valid: false, error: err.message };
2109
2172
  }
2110
2173
  }
2174
+ /** Open the consent/privacy settings popup. */
2175
+ async showSettings() {
2176
+ return this.consent.open();
2177
+ }
2111
2178
  };
2112
2179
  export {
2113
2180
  ConsentManager,
@@ -11,6 +11,8 @@ export interface ZerocostConsentRecord {
11
11
  }
12
12
  export interface ConsentConfig {
13
13
  privacyPolicyUrl?: string;
14
+ showSettingsButton?: boolean;
15
+ buttonPosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
14
16
  onConsentChange?: (preferences: ZerocostConsentRecord) => void;
15
17
  }
16
18
  export type ConsentFeature = 'ads' | 'usageData' | 'aiInteractions';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerocost/sdk",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",