@gardenfi/garden-book 0.3.2 → 0.3.4

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.
@@ -4,10 +4,14 @@ type BottomSheetProps = {
4
4
  children: ReactNode;
5
5
  open: boolean;
6
6
  onOpenChange?: (open: boolean) => void;
7
+ /** Classes for the sheet content panel (Drawer.Content). */
8
+ className?: string;
7
9
  overlayClassName?: string;
8
10
  dismissible?: boolean;
9
11
  /** When `false`, the page behind stays interactive */
10
12
  modal?: boolean;
13
+ /** When `true`, the page is NOT scroll-locked while open. */
14
+ disableScrollLock?: boolean;
11
15
  };
12
16
  export declare const BottomSheet: FC<BottomSheetProps>;
13
17
  export {};
@@ -1,39 +1,51 @@
1
- import { jsx as f, jsxs as e } from "react/jsx-runtime";
2
- import { Drawer as g } from "../node_modules/vaul/dist/index.js";
3
- import { ClientOnly as a } from "../ClientOnly/index.js";
4
- import { cn as s } from "../utils/index.js";
5
- const h = ({
6
- children: o,
7
- open: r,
8
- onOpenChange: t,
9
- overlayClassName: l,
10
- dismissible: i,
11
- modal: n
12
- }) => /* @__PURE__ */ f(a, { children: /* @__PURE__ */ f(
13
- g.Root,
1
+ import { jsx as f, jsxs as g } from "react/jsx-runtime";
2
+ import { Drawer as e } from "../node_modules/vaul/dist/index.js";
3
+ import { ClientOnly as m } from "../ClientOnly/index.js";
4
+ import { cn as o } from "../utils/index.js";
5
+ const u = ({
6
+ children: r,
7
+ open: t,
8
+ onOpenChange: l,
9
+ className: i,
10
+ overlayClassName: n,
11
+ dismissible: a,
12
+ modal: s,
13
+ disableScrollLock: c
14
+ }) => /* @__PURE__ */ f(m, { children: /* @__PURE__ */ f(
15
+ e.Root,
14
16
  {
15
- open: r,
16
- onOpenChange: t,
17
+ open: t,
18
+ onOpenChange: l,
17
19
  repositionInputs: !1,
18
- dismissible: i,
19
- modal: n,
20
- children: /* @__PURE__ */ e(g.Portal, { children: [
20
+ dismissible: a,
21
+ modal: s,
22
+ disablePreventScroll: c,
23
+ children: /* @__PURE__ */ g(e.Portal, { children: [
21
24
  /* @__PURE__ */ f(
22
- g.Overlay,
25
+ e.Overlay,
23
26
  {
24
- className: s(
27
+ className: o(
25
28
  "gf-fixed gf-inset-0 gf-z-50 gf-h-screen gf-w-screen gf-bg-dark-grey gf-bg-opacity-40 gf-transition-colors gf-duration-500 gf-ease-cubic-in-out",
26
- l
29
+ n
27
30
  )
28
31
  }
29
32
  ),
30
- /* @__PURE__ */ e(g.Content, { className: "gf-fixed gf-bottom-0 gf-left-0 gf-right-0 gf-z-50 gf-mt-24 gf-flex gf-max-h-[85vh] gf-flex-col gf-rounded-t-xl gf-bg-white/50 gf-px-4 gf-py-4 gf-outline-none gf-backdrop-blur-[20px]", children: [
31
- /* @__PURE__ */ f("div", { className: "gf-mx-auto gf-mb-3 gf-h-1 gf-w-[60px] gf-flex-shrink-0 gf-rounded-full gf-bg-white/30" }),
32
- /* @__PURE__ */ f("div", { className: "gf-scrollbar-hide gf-flex gf-flex-1 gf-flex-col gf-gap-5 gf-overflow-y-auto", children: o })
33
- ] })
33
+ /* @__PURE__ */ g(
34
+ e.Content,
35
+ {
36
+ className: o(
37
+ "gf-fixed gf-bottom-0 gf-left-0 gf-right-0 gf-z-50 gf-mt-24 gf-flex gf-max-h-[85vh] gf-flex-col gf-rounded-t-xl gf-bg-white/50 gf-px-4 gf-py-4 gf-outline-none gf-backdrop-blur-[20px]",
38
+ i
39
+ ),
40
+ children: [
41
+ /* @__PURE__ */ f("div", { className: "gf-mx-auto gf-mb-3 gf-h-1 gf-w-[60px] gf-flex-shrink-0 gf-rounded-full gf-bg-white/30" }),
42
+ /* @__PURE__ */ f("div", { className: "gf-scrollbar-hide gf-flex gf-flex-1 gf-flex-col gf-gap-5 gf-overflow-y-auto", children: r })
43
+ ]
44
+ }
45
+ )
34
46
  ] })
35
47
  }
36
48
  ) });
37
49
  export {
38
- h as BottomSheet
50
+ u as BottomSheet
39
51
  };
@@ -1,4 +1,5 @@
1
1
  import { FC } from 'react';
2
+ import { DesktopModalConfig, MobileBottomSheetConfig } from '../ResponsiveModal/ResponsiveModal';
2
3
  import { ConsentChoice, CookieCategory, UseCookieConsentOptions } from './utils';
3
4
 
4
5
  export type CookieConsentProps = {
@@ -12,6 +13,12 @@ export type CookieConsentProps = {
12
13
  onChange?: (choice: ConsentChoice) => void;
13
14
  /** Override cookie domain / version / expiry. */
14
15
  config?: UseCookieConsentOptions;
16
+ /** Desktop modal overrides — merged over the defaults
17
+ * (docked bottom-left, transparent click-through overlay, no X, no scroll-lock). */
18
+ desktopModal?: DesktopModalConfig;
19
+ /** Mobile bottom sheet overrides — defaults to a standard dismissible sheet
20
+ * (dim backdrop, tap-outside / drag to close). */
21
+ mobileBottomSheet?: MobileBottomSheetConfig;
15
22
  };
16
23
  /** Orchestrator: owns the consent store + responsive modal, and switches between
17
24
  * the two presentational screens. */
@@ -1,46 +1,70 @@
1
- import { jsx as t } from "react/jsx-runtime";
2
- import { ResponsiveModal as A } from "../ResponsiveModal/index.js";
3
- import { useCookieConsent as v } from "./useCookieConsent.js";
4
- import { CookieConsentNotice as g } from "./CookieConsentNotice.js";
5
- import { CookieConsentPreferences as k } from "./CookieConsentPreferences.js";
6
- import { DEFAULT_COOKIE_CATEGORIES as S } from "./utils.js";
7
- const I = ({
8
- privacyPolicyUrl: n,
9
- categories: s = S,
10
- defaultChecked: l = !0,
11
- onChange: e,
12
- config: i
1
+ import { jsx as c } from "react/jsx-runtime";
2
+ import { ResponsiveModal as S } from "../ResponsiveModal/index.js";
3
+ import { useCookieConsent as x } from "./useCookieConsent.js";
4
+ import { CookieConsentNotice as E } from "./CookieConsentNotice.js";
5
+ import { CookieConsentPreferences as N } from "./CookieConsentPreferences.js";
6
+ import { trackConsentEvent as r, DEFAULT_COOKIE_CATEGORIES as b, consentDecision as O } from "./utils.js";
7
+ import { cn as o } from "../utils/index.js";
8
+ const F = ({
9
+ privacyPolicyUrl: f,
10
+ categories: l = b,
11
+ defaultChecked: a = !0,
12
+ onChange: n,
13
+ config: m,
14
+ desktopModal: e,
15
+ mobileBottomSheet: u
13
16
  }) => {
14
- const { isOpen: c, view: f, ready: p, setView: a, close: m, acceptAll: u, save: d } = v(i);
17
+ const { isOpen: s, view: _, ready: p, setView: v, close: y, acceptAll: A, save: C } = x(m);
15
18
  if (!p) return null;
16
- const o = () => {
17
- u(), e == null || e({ analytics: !0, functional: !0 });
19
+ const g = {
20
+ preventClose: (e == null ? void 0 : e.preventClose) ?? !0,
21
+ disableScrollLock: (e == null ? void 0 : e.disableScrollLock) ?? !0,
22
+ overlayClassName: o(
23
+ "!gf-items-end !gf-justify-start gf-pl-[40px] !gf-bg-transparent !gf-pointer-events-none",
24
+ e == null ? void 0 : e.overlayClassName
25
+ ),
26
+ className: o(
27
+ s ? "!gf-pointer-events-auto" : "!gf-pointer-events-none",
28
+ "!gf-w-[420px] gf-gap-0 gf-px-3 gf-py-4 gf-rounded-t-4 gf-rounded-b-none",
29
+ e == null ? void 0 : e.className
30
+ )
31
+ }, i = () => {
32
+ A(), r("cookie_consent_set", {
33
+ consent_action: "accept_all",
34
+ consent_analytics: !0,
35
+ consent_functional: !0,
36
+ consent_decision: "accept_all"
37
+ }), n == null || n({ analytics: !0, functional: !0 });
18
38
  };
19
- return /* @__PURE__ */ t(
20
- A,
39
+ return /* @__PURE__ */ c(
40
+ S,
21
41
  {
22
- open: c,
23
- onClose: m,
24
- hideCloseBtn: !0,
25
- bottomSheetAllowBackgroundInteraction: !0,
26
- disableScrollLock: !0,
27
- overlayClassName: "!gf-items-end !gf-justify-start gf-pl-[40px] !gf-bg-transparent !gf-pointer-events-none",
28
- className: "!gf-pointer-events-auto gf-w-[420px] gf-gap-0 gf-px-3 gf-py-4 gf-rounded-t-4 gf-rounded-b-none",
29
- children: f === "notice" ? /* @__PURE__ */ t(
30
- g,
42
+ open: s,
43
+ onClose: y,
44
+ desktopModal: g,
45
+ mobileBottomSheet: u,
46
+ children: _ === "notice" ? /* @__PURE__ */ c(
47
+ E,
31
48
  {
32
- privacyPolicyUrl: n,
33
- onChangePreferences: () => a("preferences"),
34
- onAcceptAll: o
49
+ privacyPolicyUrl: f,
50
+ onChangePreferences: () => {
51
+ r("cookie_prefs_opened"), v("preferences");
52
+ },
53
+ onAcceptAll: i
35
54
  }
36
- ) : /* @__PURE__ */ t(
37
- k,
55
+ ) : /* @__PURE__ */ c(
56
+ N,
38
57
  {
39
- categories: s,
40
- defaultChecked: l,
41
- onAcceptAll: o,
42
- onSave: (r) => {
43
- d(r), e == null || e(r);
58
+ categories: l,
59
+ defaultChecked: a,
60
+ onAcceptAll: i,
61
+ onSave: (t) => {
62
+ C(t), r("cookie_consent_set", {
63
+ consent_action: "save",
64
+ consent_analytics: t.analytics,
65
+ consent_functional: t.functional,
66
+ consent_decision: O(t)
67
+ }), n == null || n(t);
44
68
  }
45
69
  }
46
70
  )
@@ -48,5 +72,5 @@ const I = ({
48
72
  );
49
73
  };
50
74
  export {
51
- I as CookieConsent
75
+ F as CookieConsent
52
76
  };
@@ -1,42 +1,42 @@
1
- import { readRaw as c, isValidConsent as l, applyConsent as t, hasTrackingCookies as u, isWithinAutoConsentWindow as f, writeConsent as d } from "./utils.js";
1
+ import { readRaw as l, isValidConsent as u, applyConsent as n, trackConsentEvent as a, hasTrackingCookies as f, isWithinAutoConsentWindow as d, writeConsent as p } from "./utils.js";
2
2
  let s = {
3
3
  isOpen: !1,
4
4
  view: "notice",
5
5
  consent: null,
6
6
  ready: !1
7
7
  };
8
- const p = {
8
+ const w = {
9
9
  isOpen: !1,
10
10
  view: "notice",
11
11
  consent: null,
12
12
  ready: !1
13
- }, o = /* @__PURE__ */ new Set(), w = () => o.forEach((e) => e()), n = (e) => {
14
- s = { ...s, ...e }, w();
15
- }, S = (e) => (o.add(e), () => o.delete(e)), O = () => s, h = () => p, a = { analytics: !1, functional: !1 };
16
- let i = !1;
13
+ }, o = /* @__PURE__ */ new Set(), y = () => o.forEach((e) => e()), t = (e) => {
14
+ s = { ...s, ...e }, y();
15
+ }, h = (e) => (o.add(e), () => o.delete(e)), O = () => s, b = () => w, i = { analytics: !1, functional: !1 };
16
+ let c = !1;
17
17
  function v() {
18
- if (i) return;
19
- i = !0;
20
- const e = c();
21
- if (l(e)) {
22
- t(e), n({ consent: e, ready: !0, isOpen: !1 });
18
+ if (c) return;
19
+ c = !0;
20
+ const e = l();
21
+ if (u(e)) {
22
+ n(e), t({ consent: e, ready: !0, isOpen: !1 });
23
23
  return;
24
24
  }
25
25
  if (e) {
26
- t(a), n({ consent: null, ready: !0, isOpen: !0, view: "notice" });
26
+ n(i), t({ consent: null, ready: !0, isOpen: !0, view: "notice" }), a("cookie_banner_shown");
27
27
  return;
28
28
  }
29
- if (u() && f()) {
30
- const r = d({ analytics: !0, functional: !0 });
31
- t(r), n({ consent: r, ready: !0, isOpen: !1 });
29
+ if (f() && d()) {
30
+ const r = p({ analytics: !0, functional: !0 });
31
+ n(r), t({ consent: r, ready: !0, isOpen: !1 });
32
32
  return;
33
33
  }
34
- t(a), n({ consent: null, ready: !0, isOpen: !0, view: "notice" });
34
+ n(i), t({ consent: null, ready: !0, isOpen: !0, view: "notice" }), a("cookie_banner_shown");
35
35
  }
36
36
  export {
37
37
  v as boot,
38
- h as getServerSnapshot,
38
+ b as getServerSnapshot,
39
39
  O as getSnapshot,
40
- n as setState,
41
- S as subscribe
40
+ t as setState,
41
+ h as subscribe
42
42
  };
@@ -55,4 +55,12 @@ export declare function hasTrackingCookies(): boolean;
55
55
  * clears (posthog.reset / Clarity consentv2) happen in the GTM tags. */
56
56
  export declare function clearDeniedCookies(choice: ConsentChoice): void;
57
57
  export declare function applyConsent(choice: ConsentChoice): void;
58
+ export type ConsentSurface = "app" | "www" | "localhost";
59
+ /** Which site fired the event — so app + www land in one GA4 property and segment by `surface`. */
60
+ export declare function consentSurface(): ConsentSurface;
61
+ /** One-field summary of a choice for easy reporting. */
62
+ export declare function consentDecision(choice: ConsentChoice): "accept_all" | "reject_all" | "partial";
63
+ /** Push a consent-funnel event to the dataLayer. Always tags `surface`. Fires
64
+ * regardless of consent state (GA4 cookieless pings collect it either way). */
65
+ export declare function trackConsentEvent(event: "cookie_banner_shown" | "cookie_prefs_opened" | "cookie_consent_set", props?: Record<string, unknown>): void;
58
66
  export {};
@@ -1,4 +1,4 @@
1
- const p = [
1
+ const g = [
2
2
  {
3
3
  id: "essential",
4
4
  title: "Essential",
@@ -15,21 +15,21 @@ const p = [
15
15
  title: "Performance & Functional",
16
16
  description: "Traffic sources to help us understand how people discover Garden."
17
17
  }
18
- ], d = "garden:consentchange", i = "garden_consent", a = {
18
+ ], u = "garden:consentchange", i = "garden_consent", o = {
19
19
  cookieDomain: ".garden.finance",
20
20
  storageVersion: 1,
21
21
  expiryMonths: 13,
22
22
  cookieMaxAgeDays: 400
23
23
  };
24
- function g(n) {
25
- n && Object.assign(a, n);
24
+ function y(n) {
25
+ n && Object.assign(o, n);
26
26
  }
27
- const u = "2026-06-12", l = 60;
27
+ const d = "2026-06-12", l = 60;
28
28
  function _() {
29
- const n = new Date(u).getTime();
29
+ const n = new Date(d).getTime();
30
30
  return Number.isNaN(n) ? !1 : Date.now() < n + l * 24 * 60 * 60 * 1e3;
31
31
  }
32
- function y() {
32
+ function w() {
33
33
  try {
34
34
  const n = document.cookie.match(
35
35
  new RegExp("(?:^|; )" + i + "=([^;]*)")
@@ -40,11 +40,11 @@ function y() {
40
40
  }
41
41
  }
42
42
  function h(n) {
43
- return !n || n.version !== a.storageVersion ? !1 : Date.now() - (n.timestamp || 0) <= a.expiryMonths * 30 * 24 * 60 * 60 * 1e3;
43
+ return !n || n.version !== o.storageVersion ? !1 : Date.now() - (n.timestamp || 0) <= o.expiryMonths * 30 * 24 * 60 * 60 * 1e3;
44
44
  }
45
45
  function f(n) {
46
- const t = encodeURIComponent(JSON.stringify(n)), e = a.cookieMaxAgeDays * 24 * 60 * 60;
47
- document.cookie = i + "=" + t + "; domain=" + a.cookieDomain + "; path=/; max-age=" + e + "; SameSite=Lax; Secure";
46
+ const t = encodeURIComponent(JSON.stringify(n)), e = o.cookieMaxAgeDays * 24 * 60 * 60;
47
+ document.cookie = i + "=" + t + "; domain=" + o.cookieDomain + "; path=/; max-age=" + e + "; SameSite=Lax; Secure";
48
48
  }
49
49
  function C(n) {
50
50
  const t = {
@@ -52,7 +52,7 @@ function C(n) {
52
52
  analytics: !!n.analytics,
53
53
  functional: !!n.functional,
54
54
  timestamp: Date.now(),
55
- version: a.storageVersion
55
+ version: o.storageVersion
56
56
  };
57
57
  return f(t), t;
58
58
  }
@@ -81,10 +81,10 @@ function E() {
81
81
  ];
82
82
  return r().some((t) => n.some((e) => e.test(t)));
83
83
  }
84
- function m(n) {
84
+ function p(n) {
85
85
  [
86
86
  "",
87
- "; domain=" + a.cookieDomain,
87
+ "; domain=" + o.cookieDomain,
88
88
  typeof location < "u" ? "; domain=" + location.hostname : ""
89
89
  ].forEach((e) => {
90
90
  document.cookie = n + "=; path=/; max-age=0" + e;
@@ -93,42 +93,58 @@ function m(n) {
93
93
  function k(n) {
94
94
  const t = [];
95
95
  n.analytics || t.push(...s), n.functional || t.push(...c), t.length && r().forEach((e) => {
96
- t.some((o) => o.test(e)) && m(e);
96
+ t.some((a) => a.test(e)) && p(e);
97
97
  });
98
98
  }
99
- function O(n) {
100
- const t = n.analytics ? "granted" : "denied", e = n.functional ? "granted" : "denied", o = window;
101
- typeof o.gtag == "function" && o.gtag("consent", "update", {
99
+ function D(n) {
100
+ const t = n.analytics ? "granted" : "denied", e = n.functional ? "granted" : "denied", a = window;
101
+ typeof a.gtag == "function" && a.gtag("consent", "update", {
102
102
  analytics_storage: t,
103
103
  personalization_storage: t,
104
104
  functionality_storage: e,
105
105
  ad_storage: "denied",
106
106
  ad_user_data: "denied",
107
107
  ad_personalization: "denied"
108
- }), o.dataLayer = o.dataLayer || [], o.dataLayer.push({
108
+ }), a.dataLayer = a.dataLayer || [], a.dataLayer.push({
109
109
  event: "consent_update",
110
110
  analytics_consent: t,
111
111
  functional_consent: e
112
112
  });
113
113
  try {
114
114
  window.dispatchEvent(
115
- new CustomEvent(d, {
115
+ new CustomEvent(u, {
116
116
  detail: { analytics: n.analytics, functional: n.functional }
117
117
  })
118
118
  );
119
119
  } catch {
120
120
  }
121
121
  }
122
+ function m() {
123
+ if (typeof window > "u") return "www";
124
+ const n = window.location.hostname;
125
+ return n.includes("localhost") || n.includes("127.0.0.1") ? "localhost" : n === "app.garden.finance" ? "app" : "www";
126
+ }
127
+ function O(n) {
128
+ return n.analytics && n.functional ? "accept_all" : !n.analytics && !n.functional ? "reject_all" : "partial";
129
+ }
130
+ function A(n, t = {}) {
131
+ if (typeof window > "u") return;
132
+ const e = window;
133
+ e.dataLayer = e.dataLayer || [], e.dataLayer.push({ event: n, consent_surface: m(), ...t });
134
+ }
122
135
  export {
123
- d as CONSENT_EVENT,
124
- p as DEFAULT_COOKIE_CATEGORIES,
125
- O as applyConsent,
136
+ u as CONSENT_EVENT,
137
+ g as DEFAULT_COOKIE_CATEGORIES,
138
+ D as applyConsent,
126
139
  k as clearDeniedCookies,
127
- a as config,
128
- g as configure,
140
+ o as config,
141
+ y as configure,
142
+ O as consentDecision,
143
+ m as consentSurface,
129
144
  E as hasTrackingCookies,
130
145
  h as isValidConsent,
131
146
  _ as isWithinAutoConsentWindow,
132
- y as readRaw,
147
+ w as readRaw,
148
+ A as trackConsentEvent,
133
149
  C as writeConsent
134
150
  };
@@ -19,9 +19,9 @@ const T = (t, i) => /* @__PURE__ */ e("a", { href: t, children: i }), Q = ({
19
19
  renderLink: h = T,
20
20
  className: N
21
21
  }) => {
22
- const [p, u] = v(!1), [w, l] = v(!1), I = () => {
22
+ const [p, u] = v(!1), [w, l] = v(!1), k = () => {
23
23
  u(!1), y ? l(!0) : m();
24
- }, k = () => {
24
+ }, I = () => {
25
25
  l(!1), s == null || s();
26
26
  };
27
27
  return /* @__PURE__ */ r(F, { children: [
@@ -95,7 +95,7 @@ const T = (t, i) => /* @__PURE__ */ e("a", { href: t, children: i }), Q = ({
95
95
  children: /* @__PURE__ */ r(
96
96
  O,
97
97
  {
98
- onSelect: I,
98
+ onSelect: k,
99
99
  className: "gf-flex gf-items-center gf-gap-1 gf-p-1 gf-cursor-pointer hover:gf-bg-[#EDF6FC] focus:gf-bg-[#EDF6FC] data-[highlighted]:gf-bg-[#EDF6FC] gf-rounded-md gf-transition-colors focus:gf-outline-none",
100
100
  children: [
101
101
  /* @__PURE__ */ e("div", { className: "gf-rounded-lg gf-flex gf-items-center gf-justify-center gf-shrink-0", children: /* @__PURE__ */ e(U, { className: "gf-h-4 gf-w-4 gf-text-primaryIris gf-ml-[14px] gf-mr-2" }) }),
@@ -113,9 +113,9 @@ const T = (t, i) => /* @__PURE__ */ e("a", { href: t, children: i }), Q = ({
113
113
  S,
114
114
  {
115
115
  open: w,
116
- onClose: k,
116
+ onClose: I,
117
117
  label: "Ready to sign out?",
118
- className: "gf-max-w-sm",
118
+ desktopModal: { className: "gf-max-w-sm" },
119
119
  children: [
120
120
  /* @__PURE__ */ e(o, { size: "h5", weight: "regular", children: "You'll be signed out and redirected to the login page." }),
121
121
  /* @__PURE__ */ e(