@thebase/ui 1.1.0 → 1.1.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [v1.1.1] - 2026-10-04
6
+
7
+ ### Added
8
+ - Analytics: `visitorContext()` export from `@thebase/ui/analytics` (and `window.thebase.analytics.visitorContext`). It returns the visitor's timezone (`tz`), browser language (`lang`) and a coarse screen bucket (`screen`: Mobile/Tablet/Laptop/Desktop). Pass it as `customProperties` to attach them to every event. Types are included as `BaseUIVisitorContext`. It's an additive export released as a patch by maintainer decision; nothing existing changed.
9
+ - Docs: `docs/analytics.md` covers receiving events on your own backend (payload reference, Go Fiber v3 and FastAPI receivers), a "Sample dashboard" section, and "Visitor context". README has an Analytics section.
10
+ - Examples: `examples/analytics/` contains a BaseUI analytics dashboard plus runnable Go Fiber and FastAPI sample backends (in-memory store, `GET /api/stats`, `DEMO_SEED=1` demo data). The landing page has an Analytics section, and the docs nav lists the Analytics guide.
11
+
12
+ ### Changed
13
+ - Docs and examples: production pin examples now use `@1.1.1`.
14
+ - `npm run dev` server: folder URLs serve their `index.html`, and `.go`/`.py`/`.mod` sources are served as text.
15
+
5
16
  ## [v1.1.0] - 2026-10-04
6
17
 
7
18
  ### Added
package/README.md CHANGED
@@ -4,7 +4,7 @@ The Base UI is a CDN-installable UI kit built with Bootstrap 5 styling and Owl-e
4
4
 
5
5
  Its strong points: **no build step** — every component runs straight from a CDN `<script>`/import map, nothing to compile; **modular component design** — each component is a self-contained unit you import or mark up individually, not a monolith; **vanilla JavaScript/TypeScript** — no framework lock-in, no JSX, no compiler-specific syntax to learn; and this combination makes it well suited to building **WYSIWYG website builders**, where components must mount, unmount, and re-render dynamically from user-driven markup or drag-and-drop edits rather than a fixed build-time component tree.
6
6
 
7
- Both APIs load straight from a CDN — jsDelivr or unpkg — no build step, no self-hosting required. The snippets below use the `@latest` tag for readability; pin an exact version instead (e.g. `@1.1.0`, or `@1` to take only non-breaking updates) for any production page, since `@latest` can change what your page loads the moment a new version ships. Pure Owl usage:
7
+ Both APIs load straight from a CDN — jsDelivr or unpkg — no build step, no self-hosting required. The snippets below use the `@latest` tag for readability; pin an exact version instead (e.g. `@1.1.1`, or `@1` to take only non-breaking updates) for any production page, since `@latest` can change what your page loads the moment a new version ships. Pure Owl usage:
8
8
 
9
9
  ```html
10
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.css">
@@ -56,9 +56,23 @@ For app-level theme controls, import `createThemeController`/`BaseUITheme` as `@
56
56
 
57
57
  Every component ships both APIs from `src/components/<name>/`: the static `b-ui` adapter (`<name>.js`, using `b-att-*` attributes and `baseui:*` events) and a pure Owl component class (`<name>.component.js`, exported from `@thebase/ui/components`). A few components' pure Owl treatment is intentionally lighter or reshaped versus their static markup-driven adapter — most notably `chart` (a slotted container; static Chart.js bootstrapping stays a `b-ui`-only concern) and the data-driven `data-table`/`combobox`/`command`/`calendar` (props-driven instead of slot/markup-driven). See each component's doc page under `docs/components/` for specifics.
58
58
 
59
+ ## Analytics
60
+
61
+ BaseUI also ships an optional, cookieless web-analytics service (from 1.1.0). It is a standalone bundle — not part of `dist/baseui.min.js`/`baseui.esm.js`, with no Owl, Bootstrap, or component runtime dependency (~5.6 KB minified) — so you can load it with or without the rest of BaseUI. Nothing is collected until the page calls `init()`:
62
+
63
+ ```html
64
+ <script type="module">
65
+ import { init, track } from "https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.analytics.esm.js";
66
+ init({ backendUrl: "https://stats.example.com" }); // events POST to <backendUrl>/api/event
67
+ track("Signup", { props: { plan: "pro" } });
68
+ </script>
69
+ ```
70
+
71
+ From npm, use `import { init, track } from "@thebase/ui/analytics"`; for a classic `<script>` tag, `dist/baseui.analytics.min.js` sets `window.thebase.analytics`. It covers automatic and SPA pageviews, engagement (time on page and scroll depth), outbound links, file downloads, form submissions, and `thebase-event-*` class tagging. See [Analytics](docs/analytics.md) for every option, the payload format, opt-out, and sample Go Fiber / FastAPI backends. [`examples/analytics/`](examples/analytics/) holds a ready-to-run BaseUI dashboard for the collected data.
72
+
59
73
  ## Release notes
60
74
 
61
- See [CHANGELOG.md](CHANGELOG.md) for the full version history. Current version: **1.1.0**.
75
+ See [CHANGELOG.md](CHANGELOG.md) for the full version history. Current version: **1.1.1**.
62
76
 
63
77
  ## Versioning policy
64
78
 
@@ -77,7 +91,7 @@ What each release type means:
77
91
 
78
92
  Anything prefixed `_`, undocumented internals, and the `docs/`/`examples/` sources are not part of the public API. Neither are the source-level authoring helpers described in [Component Authoring](docs/component-authoring.md) (`optional()`, `slotProps`, the `open-state.js` hooks, `bindBootstrapOverlay()`): they aren't exported from the package and may change in any release. Deprecated APIs keep working until the next major and are flagged in the CHANGELOG first.
79
93
 
80
- Pinning: use an exact version (`@1.1.0`) when you need byte-identical output, or the major range (`@1` on jsDelivr/unpkg, `^1.0.0` in npm) to receive fixes and features without breaking changes. Avoid `@latest` in production — it will move to the next major.
94
+ Pinning: use an exact version (`@1.1.1`) when you need byte-identical output, or the major range (`@1` on jsDelivr/unpkg, `^1.0.0` in npm) to receive fixes and features without breaking changes. Avoid `@latest` in production — it will move to the next major.
81
95
 
82
96
  ## Project Documents
83
97
 
@@ -131,6 +145,6 @@ BaseUI includes the full Lucide SVG icon set as a built-in icon library. Use `<s
131
145
 
132
146
  ## Distribution
133
147
 
134
- The npm package publishes the built `dist/` artifacts plus package metadata. The browser build bundles Bootstrap CSS, and `dist/baseui.min.js`/`baseui.esm.js` embed Bootstrap's JS bundle, the Owl runtime, every pure Owl component class, and the theme helper directly (Bootstrap then Owl then BaseUI, in that load order) — consumers install BaseUI with one stylesheet and one script tag for either API. Bootstrap's JS drives every component that has a Bootstrap JS equivalent (modal, dropdown, collapse, tab, toast, carousel, tooltip, popover, alert); BaseUI's `.behavior.js`/`runtime/*.js` helpers wrap Bootstrap's JS API instead of reimplementing it, for both the static and pure-Owl APIs. `dist/bootstrap.bundle.min.js` also ships standalone (unmodified) and `dist/baseui.icons.esm.js` stays a separate, deliberate exception (2000+ generated icon components would blow the main bundle's size budget) — everything else is one file. Every shipped CSS/JS artifact is minified — there are no unminified twins to keep in sync.
148
+ The npm package publishes the built `dist/` artifacts plus package metadata. The browser build bundles Bootstrap CSS, and `dist/baseui.min.js`/`baseui.esm.js` embed Bootstrap's JS bundle, the Owl runtime, every pure Owl component class, and the theme helper directly (Bootstrap then Owl then BaseUI, in that load order) — consumers install BaseUI with one stylesheet and one script tag for either API. Bootstrap's JS drives every component that has a Bootstrap JS equivalent (modal, dropdown, collapse, tab, toast, carousel, tooltip, popover, alert); BaseUI's `.behavior.js`/`runtime/*.js` helpers wrap Bootstrap's JS API instead of reimplementing it, for both the static and pure-Owl APIs. `dist/bootstrap.bundle.min.js` also ships standalone (unmodified) and `dist/baseui.icons.esm.js` stays a separate, deliberate exception (2000+ generated icon components would blow the main bundle's size budget), as does the opt-in analytics service (`dist/baseui.analytics.esm.js`/`.min.js`, so pages that don't track pay nothing for it) — everything else is one file. Every shipped CSS/JS artifact is minified — there are no unminified twins to keep in sync.
135
149
 
136
150
  The published tarball also carries `docs/*.md` and `docs/components/` (see the "Project Documents" section above), `README.md`, `CHANGELOG.md`, and `LICENSE` — `docs/v2/` and `docs/component-authoring.md` are deliberately excluded from `package.json`'s `files` list since they're development-time-only references for working inside this repo.
@@ -1 +1 @@
1
- var H=["pdf","xlsx","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpeg","wmv","midi","mp3","wav","wma","dmg"];var U=/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/,F=/thebase-event-name(=|--)(.+)/,B="/api/event",$=/^(https?:\/\/|\/)/,o={},P=H,p,A,w=!1,v,C,O={},E=-1,r=0,l=0,u,s;function z(e){if(o.isInitialized)throw Error("thebase.analytics.init() can only be called once");let t=e.apiPath||B,i=e.endpoint||e.backendUrl&&`${e.backendUrl.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`;if(!i)throw Error("thebase.analytics.init(): backendUrl (or endpoint) is required");if(!$.test(i))throw Error(`thebase.analytics.init(): "${i}" must be an http(s):// URL or a /path on this site`);Object.assign(o,e,{domain:e.domain||location.hostname,endpoint:i,autoCapturePageviews:e.autoCapturePageviews!==!1,logging:e.logging!==!1,bindToWindow:e.bindToWindow!==!1,isInitialized:!0})}function I(e,t,i){fetch(e,{method:"POST",headers:{"Content-Type":"text/plain"},keepalive:!0,body:JSON.stringify(t)}).then(n=>i?.callback?.({status:n.status})).catch(n=>i?.callback?.({error:n}))}function V(){w&&(N(),u=S(),s=L())}function q(e){v=!1,C=e.u,O=e.p,E=-1,l=0,r=Date.now(),G()}function N(){let e=M();if(v||E>=s&&e<3e3)return;E=s;let t={n:"engagement",sd:Math.round(s/u*100),d:o.domain,u:C,p:O,e,v:36};r=0,l=0,o.hashBasedRouting&&(t.h=1),I(o.endpoint,t)}function m(){document.visibilityState==="visible"&&document.hasFocus()&&r===0?r=Date.now():(document.visibilityState==="hidden"||!document.hasFocus())&&(l=M(),r=0,N())}function G(){w||(document.addEventListener("visibilitychange",m),window.addEventListener("blur",m),window.addEventListener("focus",m),w=!0)}function M(){return r?l+(Date.now()-r):l}function S(){let e=document.body,t=document.documentElement;return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight,t.scrollHeight,t.offsetHeight,t.clientHeight)}function L(){return u<=window.innerHeight?u:window.scrollY+window.innerHeight}function K(){u=S()}function W(){s=Math.max(s,L())}function j(){u=S(),s=L(),new window.ResizeObserver(K).observe(document.documentElement),document.addEventListener("scroll",W)}function g(e,t){if(!o.isInitialized)throw Error("thebase.analytics.track() can only be called after thebase.analytics.init()");let i=e==="pageview";if(i&&V(),!o.captureOnLocalhost){if(U.test(location.hostname)||location.protocol==="file:")return d(e,t,"localhost");if((window._phantom||window.__nightmare||navigator.webdriver||window.Cypress)&&!window.__thebase)return d(e,t)}try{if(localStorage.thebase_ignore==="true")return d(e,t,"localStorage flag")}catch{}let n={n:e,v:36,u:t?.u||t?.url||location.href,d:o.domain,r:document.referrer||null};if(t?.props&&(n.p=t.props),t?.interactive===!1&&(n.i=!1),t?.revenue&&(n.$=t.revenue),o.customProperties){let a=typeof o.customProperties=="function"?o.customProperties(e):o.customProperties;typeof a=="object"&&(n.p={...a,...n.p})}if(o.hashBasedRouting&&(n.h=1),typeof o.transformRequest=="function"&&(n=o.transformRequest(n),!n))return d(e,t,"transformRequest");i&&q(n),I(o.endpoint,n,t)}function d(e,t,i){i&&o.logging&&console.warn(`Ignoring Event: ${i}`),t?.callback?.(),e==="pageview"&&(v=!0)}function x(e){return e?.tagName?.toLowerCase()==="a"}function Y(e){for(;e&&(e.tagName===void 0||!x(e)||!e.href);)e=e.parentNode;return e}function J(e){return e&&typeof e.href=="string"&&e.host&&e.host!==location.host}function Q(e){return!!e&&P.includes(e.split(".").pop())}function T(e){return!!e?.classList&&[...e.classList].some(t=>F.test(t))}function y(e,t){return!!e&&t<=3&&(T(e)||y(e.parentNode,t+1))}function D(e){let t=T(e)?e:e?.parentNode,i={name:null,props:{},revenue:{}};if(!t?.classList)return i;for(let n of t.classList){let a=n.match(/thebase-event-(.+)(=|--)(.+)/);if(a){let _=a[3].replace(/\+/g," ");a[1].toLowerCase()==="name"?i.name=_:i.props[a[1]]=_}let c=n.match(/thebase-revenue-(.+)(=|--)(.+)/);c&&(i.revenue[c[1]]=c[3])}return i}function f(e){g(e.name,{props:e.props,revenue:e.revenue})}function k(e){if(e.type==="auxclick"&&e.button!==1)return;let t=Y(e.target);if(y(t,0))return;if(o.outboundLinks&&J(t))return f({name:"Outbound Link: Click",props:{url:t.href}});let i=t&&typeof t.href=="string"&&t.href.split("?")[0];o.fileDownloads&&Q(i)&&f({name:"File Download",props:{url:i}})}function R(e){if(e.type==="auxclick"&&e.button!==1)return;let t,i,n=e.target;for(let c=0;c<=3&&n;c++){if(n.tagName?.toLowerCase()==="form")return;x(n)&&(t=n),T(n)&&(i=n),n=n.parentNode}if(!i)return;let a=D(i);t&&(a.props.url=t.href),f(a)}function X(e){let t=e.target;(t.hasAttribute("novalidate")||t.checkValidity())&&!y(t,0)&&g("Form: Submission")}function Z(e){let t=D(e.target);t.name&&f(t)}function ee(){document.addEventListener("click",k),document.addEventListener("auxclick",k),Array.isArray(o.fileDownloads?.fileExtensions)&&(P=o.fileDownloads.fileExtensions),o.formSubmissions&&document.addEventListener("submit",X,!0),document.addEventListener("submit",Z),document.addEventListener("click",R),document.addEventListener("auxclick",R)}function h(e){!o.hashBasedRouting&&e&&p===location.pathname||(p=location.pathname,g("pageview"))}function b(){h(!0)}function te(...e){A.apply(this,e),b()}function ne(){!p&&document.visibilityState==="visible"&&h()}function ie(e){e.persisted&&h()}function oe(){o.hashBasedRouting?window.addEventListener("hashchange",b):(A=window.history.pushState,window.history.pushState=te,window.addEventListener("popstate",b)),document.visibilityState==="hidden"||document.visibilityState==="prerender"?document.addEventListener("visibilitychange",ne):h(),window.addEventListener("pageshow",ie)}function ae(e){z(e||{}),j(),o.autoCapturePageviews&&oe(),ee(),o.bindToWindow&&(window.thebase??(window.thebase={}),window.thebase.track=g,window.thebase.track.s="npm",window.thebase.track.v=36,window.thebase.track.l=!0)}export{H as DEFAULT_FILE_TYPES,ae as init,g as track};
1
+ var H=["pdf","xlsx","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpeg","wmv","midi","mp3","wav","wma","dmg"];var U=/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/,F=/thebase-event-name(=|--)(.+)/,B="/api/event",z=/^(https?:\/\/|\/)/,o={},P=H,m,C,w=!1,v,O,A={},E=-1,r=0,l=0,u,s;function $(e){if(o.isInitialized)throw Error("thebase.analytics.init() can only be called once");let t=e.apiPath||B,i=e.endpoint||e.backendUrl&&`${e.backendUrl.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`;if(!i)throw Error("thebase.analytics.init(): backendUrl (or endpoint) is required");if(!z.test(i))throw Error(`thebase.analytics.init(): "${i}" must be an http(s):// URL or a /path on this site`);Object.assign(o,e,{domain:e.domain||location.hostname,endpoint:i,autoCapturePageviews:e.autoCapturePageviews!==!1,logging:e.logging!==!1,bindToWindow:e.bindToWindow!==!1,isInitialized:!0})}function I(e,t,i){fetch(e,{method:"POST",headers:{"Content-Type":"text/plain"},keepalive:!0,body:JSON.stringify(t)}).then(n=>i?.callback?.({status:n.status})).catch(n=>i?.callback?.({error:n}))}function V(){w&&(M(),u=S(),s=L())}function q(e){v=!1,O=e.u,A=e.p,E=-1,l=0,r=Date.now(),G()}function M(){let e=N();if(v||E>=s&&e<3e3)return;E=s;let t={n:"engagement",sd:Math.round(s/u*100),d:o.domain,u:O,p:A,e,v:36};r=0,l=0,o.hashBasedRouting&&(t.h=1),I(o.endpoint,t)}function p(){document.visibilityState==="visible"&&document.hasFocus()&&r===0?r=Date.now():(document.visibilityState==="hidden"||!document.hasFocus())&&(l=N(),r=0,M())}function G(){w||(document.addEventListener("visibilitychange",p),window.addEventListener("blur",p),window.addEventListener("focus",p),w=!0)}function N(){return r?l+(Date.now()-r):l}function S(){let e=document.body,t=document.documentElement;return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight,t.scrollHeight,t.offsetHeight,t.clientHeight)}function L(){return u<=window.innerHeight?u:window.scrollY+window.innerHeight}function K(){u=S()}function W(){s=Math.max(s,L())}function j(){u=S(),s=L(),new window.ResizeObserver(K).observe(document.documentElement),document.addEventListener("scroll",W)}function ae(){let e=window.innerWidth;return{tz:Intl.DateTimeFormat().resolvedOptions().timeZone,lang:navigator.language,screen:e<576?"Mobile":e<992?"Tablet":e<1440?"Laptop":"Desktop"}}function g(e,t){if(!o.isInitialized)throw Error("thebase.analytics.track() can only be called after thebase.analytics.init()");let i=e==="pageview";if(i&&V(),!o.captureOnLocalhost){if(U.test(location.hostname)||location.protocol==="file:")return d(e,t,"localhost");if((window._phantom||window.__nightmare||navigator.webdriver||window.Cypress)&&!window.__thebase)return d(e,t)}try{if(localStorage.thebase_ignore==="true")return d(e,t,"localStorage flag")}catch{}let n={n:e,v:36,u:t?.u||t?.url||location.href,d:o.domain,r:document.referrer||null};if(t?.props&&(n.p=t.props),t?.interactive===!1&&(n.i=!1),t?.revenue&&(n.$=t.revenue),o.customProperties){let a=typeof o.customProperties=="function"?o.customProperties(e):o.customProperties;typeof a=="object"&&(n.p={...a,...n.p})}if(o.hashBasedRouting&&(n.h=1),typeof o.transformRequest=="function"&&(n=o.transformRequest(n),!n))return d(e,t,"transformRequest");i&&q(n),I(o.endpoint,n,t)}function d(e,t,i){i&&o.logging&&console.warn(`Ignoring Event: ${i}`),t?.callback?.(),e==="pageview"&&(v=!0)}function x(e){return e?.tagName?.toLowerCase()==="a"}function Y(e){for(;e&&(e.tagName===void 0||!x(e)||!e.href);)e=e.parentNode;return e}function J(e){return e&&typeof e.href=="string"&&e.host&&e.host!==location.host}function Z(e){return!!e&&P.includes(e.split(".").pop())}function T(e){return!!e?.classList&&[...e.classList].some(t=>F.test(t))}function y(e,t){return!!e&&t<=3&&(T(e)||y(e.parentNode,t+1))}function D(e){let t=T(e)?e:e?.parentNode,i={name:null,props:{},revenue:{}};if(!t?.classList)return i;for(let n of t.classList){let a=n.match(/thebase-event-(.+)(=|--)(.+)/);if(a){let k=a[3].replace(/\+/g," ");a[1].toLowerCase()==="name"?i.name=k:i.props[a[1]]=k}let c=n.match(/thebase-revenue-(.+)(=|--)(.+)/);c&&(i.revenue[c[1]]=c[3])}return i}function f(e){g(e.name,{props:e.props,revenue:e.revenue})}function _(e){if(e.type==="auxclick"&&e.button!==1)return;let t=Y(e.target);if(y(t,0))return;if(o.outboundLinks&&J(t))return f({name:"Outbound Link: Click",props:{url:t.href}});let i=t&&typeof t.href=="string"&&t.href.split("?")[0];o.fileDownloads&&Z(i)&&f({name:"File Download",props:{url:i}})}function R(e){if(e.type==="auxclick"&&e.button!==1)return;let t,i,n=e.target;for(let c=0;c<=3&&n;c++){if(n.tagName?.toLowerCase()==="form")return;x(n)&&(t=n),T(n)&&(i=n),n=n.parentNode}if(!i)return;let a=D(i);t&&(a.props.url=t.href),f(a)}function Q(e){let t=e.target;(t.hasAttribute("novalidate")||t.checkValidity())&&!y(t,0)&&g("Form: Submission")}function X(e){let t=D(e.target);t.name&&f(t)}function ee(){document.addEventListener("click",_),document.addEventListener("auxclick",_),Array.isArray(o.fileDownloads?.fileExtensions)&&(P=o.fileDownloads.fileExtensions),o.formSubmissions&&document.addEventListener("submit",Q,!0),document.addEventListener("submit",X),document.addEventListener("click",R),document.addEventListener("auxclick",R)}function h(e){!o.hashBasedRouting&&e&&m===location.pathname||(m=location.pathname,g("pageview"))}function b(){h(!0)}function te(...e){C.apply(this,e),b()}function ne(){!m&&document.visibilityState==="visible"&&h()}function ie(e){e.persisted&&h()}function oe(){o.hashBasedRouting?window.addEventListener("hashchange",b):(C=window.history.pushState,window.history.pushState=te,window.addEventListener("popstate",b)),document.visibilityState==="hidden"||document.visibilityState==="prerender"?document.addEventListener("visibilitychange",ne):h(),window.addEventListener("pageshow",ie)}function re(e){$(e||{}),j(),o.autoCapturePageviews&&oe(),ee(),o.bindToWindow&&(window.thebase??(window.thebase={}),window.thebase.track=g,window.thebase.track.s="npm",window.thebase.track.v=36,window.thebase.track.l=!0)}export{H as DEFAULT_FILE_TYPES,re as init,g as track,ae as visitorContext};
@@ -1 +1 @@
1
- (()=>{var F=Object.defineProperty;var B=(e,t)=>{for(var n in t)F(e,n,{get:t[n],enumerable:!0})};var _={};B(_,{DEFAULT_FILE_TYPES:()=>A,init:()=>ce,track:()=>d});var A=["pdf","xlsx","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpeg","wmv","midi","mp3","wav","wma","dmg"];var $=/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/,z=/thebase-event-name(=|--)(.+)/,V="/api/event",q=/^(https?:\/\/|\/)/,o={},C=A,p,O,w=!1,v,I,N={},E=-1,r=0,l=0,u,s;function G(e){if(o.isInitialized)throw Error("thebase.analytics.init() can only be called once");let t=e.apiPath||V,n=e.endpoint||e.backendUrl&&`${e.backendUrl.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`;if(!n)throw Error("thebase.analytics.init(): backendUrl (or endpoint) is required");if(!q.test(n))throw Error(`thebase.analytics.init(): "${n}" must be an http(s):// URL or a /path on this site`);Object.assign(o,e,{domain:e.domain||location.hostname,endpoint:n,autoCapturePageviews:e.autoCapturePageviews!==!1,logging:e.logging!==!1,bindToWindow:e.bindToWindow!==!1,isInitialized:!0})}function M(e,t,n){fetch(e,{method:"POST",headers:{"Content-Type":"text/plain"},keepalive:!0,body:JSON.stringify(t)}).then(i=>n?.callback?.({status:i.status})).catch(i=>n?.callback?.({error:i}))}function K(){w&&(x(),u=S(),s=L())}function W(e){v=!1,I=e.u,N=e.p,E=-1,l=0,r=Date.now(),j()}function x(){let e=D();if(v||E>=s&&e<3e3)return;E=s;let t={n:"engagement",sd:Math.round(s/u*100),d:o.domain,u:I,p:N,e,v:36};r=0,l=0,o.hashBasedRouting&&(t.h=1),M(o.endpoint,t)}function m(){document.visibilityState==="visible"&&document.hasFocus()&&r===0?r=Date.now():(document.visibilityState==="hidden"||!document.hasFocus())&&(l=D(),r=0,x())}function j(){w||(document.addEventListener("visibilitychange",m),window.addEventListener("blur",m),window.addEventListener("focus",m),w=!0)}function D(){return r?l+(Date.now()-r):l}function S(){let e=document.body,t=document.documentElement;return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight,t.scrollHeight,t.offsetHeight,t.clientHeight)}function L(){return u<=window.innerHeight?u:window.scrollY+window.innerHeight}function Y(){u=S()}function J(){s=Math.max(s,L())}function Q(){u=S(),s=L(),new window.ResizeObserver(Y).observe(document.documentElement),document.addEventListener("scroll",J)}function d(e,t){if(!o.isInitialized)throw Error("thebase.analytics.track() can only be called after thebase.analytics.init()");let n=e==="pageview";if(n&&K(),!o.captureOnLocalhost){if($.test(location.hostname)||location.protocol==="file:")return f(e,t,"localhost");if((window._phantom||window.__nightmare||navigator.webdriver||window.Cypress)&&!window.__thebase)return f(e,t)}try{if(localStorage.thebase_ignore==="true")return f(e,t,"localStorage flag")}catch{}let i={n:e,v:36,u:t?.u||t?.url||location.href,d:o.domain,r:document.referrer||null};if(t?.props&&(i.p=t.props),t?.interactive===!1&&(i.i=!1),t?.revenue&&(i.$=t.revenue),o.customProperties){let a=typeof o.customProperties=="function"?o.customProperties(e):o.customProperties;typeof a=="object"&&(i.p={...a,...i.p})}if(o.hashBasedRouting&&(i.h=1),typeof o.transformRequest=="function"&&(i=o.transformRequest(i),!i))return f(e,t,"transformRequest");n&&W(i),M(o.endpoint,i,t)}function f(e,t,n){n&&o.logging&&console.warn(`Ignoring Event: ${n}`),t?.callback?.(),e==="pageview"&&(v=!0)}function H(e){return e?.tagName?.toLowerCase()==="a"}function X(e){for(;e&&(e.tagName===void 0||!H(e)||!e.href);)e=e.parentNode;return e}function Z(e){return e&&typeof e.href=="string"&&e.host&&e.host!==location.host}function ee(e){return!!e&&C.includes(e.split(".").pop())}function T(e){return!!e?.classList&&[...e.classList].some(t=>z.test(t))}function y(e,t){return!!e&&t<=3&&(T(e)||y(e.parentNode,t+1))}function U(e){let t=T(e)?e:e?.parentNode,n={name:null,props:{},revenue:{}};if(!t?.classList)return n;for(let i of t.classList){let a=i.match(/thebase-event-(.+)(=|--)(.+)/);if(a){let k=a[3].replace(/\+/g," ");a[1].toLowerCase()==="name"?n.name=k:n.props[a[1]]=k}let c=i.match(/thebase-revenue-(.+)(=|--)(.+)/);c&&(n.revenue[c[1]]=c[3])}return n}function g(e){d(e.name,{props:e.props,revenue:e.revenue})}function R(e){if(e.type==="auxclick"&&e.button!==1)return;let t=X(e.target);if(y(t,0))return;if(o.outboundLinks&&Z(t))return g({name:"Outbound Link: Click",props:{url:t.href}});let n=t&&typeof t.href=="string"&&t.href.split("?")[0];o.fileDownloads&&ee(n)&&g({name:"File Download",props:{url:n}})}function P(e){if(e.type==="auxclick"&&e.button!==1)return;let t,n,i=e.target;for(let c=0;c<=3&&i;c++){if(i.tagName?.toLowerCase()==="form")return;H(i)&&(t=i),T(i)&&(n=i),i=i.parentNode}if(!n)return;let a=U(n);t&&(a.props.url=t.href),g(a)}function te(e){let t=e.target;(t.hasAttribute("novalidate")||t.checkValidity())&&!y(t,0)&&d("Form: Submission")}function ne(e){let t=U(e.target);t.name&&g(t)}function ie(){document.addEventListener("click",R),document.addEventListener("auxclick",R),Array.isArray(o.fileDownloads?.fileExtensions)&&(C=o.fileDownloads.fileExtensions),o.formSubmissions&&document.addEventListener("submit",te,!0),document.addEventListener("submit",ne),document.addEventListener("click",P),document.addEventListener("auxclick",P)}function h(e){!o.hashBasedRouting&&e&&p===location.pathname||(p=location.pathname,d("pageview"))}function b(){h(!0)}function oe(...e){O.apply(this,e),b()}function ae(){!p&&document.visibilityState==="visible"&&h()}function re(e){e.persisted&&h()}function se(){o.hashBasedRouting?window.addEventListener("hashchange",b):(O=window.history.pushState,window.history.pushState=oe,window.addEventListener("popstate",b)),document.visibilityState==="hidden"||document.visibilityState==="prerender"?document.addEventListener("visibilitychange",ae):h(),window.addEventListener("pageshow",re)}function ce(e){G(e||{}),Q(),o.autoCapturePageviews&&se(),ie(),o.bindToWindow&&(window.thebase??(window.thebase={}),window.thebase.track=d,window.thebase.track.s="npm",window.thebase.track.v=36,window.thebase.track.l=!0)}window.thebase??(window.thebase={});window.thebase.analytics=_;})();
1
+ (()=>{var F=Object.defineProperty;var B=(e,t)=>{for(var n in t)F(e,n,{get:t[n],enumerable:!0})};var k={};B(k,{DEFAULT_FILE_TYPES:()=>C,init:()=>ue,track:()=>d,visitorContext:()=>Q});var C=["pdf","xlsx","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpeg","wmv","midi","mp3","wav","wma","dmg"];var z=/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/,$=/thebase-event-name(=|--)(.+)/,V="/api/event",q=/^(https?:\/\/|\/)/,o={},O=C,m,A,w=!1,v,I,M={},E=-1,r=0,l=0,u,s;function G(e){if(o.isInitialized)throw Error("thebase.analytics.init() can only be called once");let t=e.apiPath||V,n=e.endpoint||e.backendUrl&&`${e.backendUrl.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`;if(!n)throw Error("thebase.analytics.init(): backendUrl (or endpoint) is required");if(!q.test(n))throw Error(`thebase.analytics.init(): "${n}" must be an http(s):// URL or a /path on this site`);Object.assign(o,e,{domain:e.domain||location.hostname,endpoint:n,autoCapturePageviews:e.autoCapturePageviews!==!1,logging:e.logging!==!1,bindToWindow:e.bindToWindow!==!1,isInitialized:!0})}function N(e,t,n){fetch(e,{method:"POST",headers:{"Content-Type":"text/plain"},keepalive:!0,body:JSON.stringify(t)}).then(i=>n?.callback?.({status:i.status})).catch(i=>n?.callback?.({error:i}))}function K(){w&&(x(),u=S(),s=L())}function W(e){v=!1,I=e.u,M=e.p,E=-1,l=0,r=Date.now(),j()}function x(){let e=D();if(v||E>=s&&e<3e3)return;E=s;let t={n:"engagement",sd:Math.round(s/u*100),d:o.domain,u:I,p:M,e,v:36};r=0,l=0,o.hashBasedRouting&&(t.h=1),N(o.endpoint,t)}function p(){document.visibilityState==="visible"&&document.hasFocus()&&r===0?r=Date.now():(document.visibilityState==="hidden"||!document.hasFocus())&&(l=D(),r=0,x())}function j(){w||(document.addEventListener("visibilitychange",p),window.addEventListener("blur",p),window.addEventListener("focus",p),w=!0)}function D(){return r?l+(Date.now()-r):l}function S(){let e=document.body,t=document.documentElement;return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight,t.scrollHeight,t.offsetHeight,t.clientHeight)}function L(){return u<=window.innerHeight?u:window.scrollY+window.innerHeight}function Y(){u=S()}function J(){s=Math.max(s,L())}function Z(){u=S(),s=L(),new window.ResizeObserver(Y).observe(document.documentElement),document.addEventListener("scroll",J)}function Q(){let e=window.innerWidth;return{tz:Intl.DateTimeFormat().resolvedOptions().timeZone,lang:navigator.language,screen:e<576?"Mobile":e<992?"Tablet":e<1440?"Laptop":"Desktop"}}function d(e,t){if(!o.isInitialized)throw Error("thebase.analytics.track() can only be called after thebase.analytics.init()");let n=e==="pageview";if(n&&K(),!o.captureOnLocalhost){if(z.test(location.hostname)||location.protocol==="file:")return f(e,t,"localhost");if((window._phantom||window.__nightmare||navigator.webdriver||window.Cypress)&&!window.__thebase)return f(e,t)}try{if(localStorage.thebase_ignore==="true")return f(e,t,"localStorage flag")}catch{}let i={n:e,v:36,u:t?.u||t?.url||location.href,d:o.domain,r:document.referrer||null};if(t?.props&&(i.p=t.props),t?.interactive===!1&&(i.i=!1),t?.revenue&&(i.$=t.revenue),o.customProperties){let a=typeof o.customProperties=="function"?o.customProperties(e):o.customProperties;typeof a=="object"&&(i.p={...a,...i.p})}if(o.hashBasedRouting&&(i.h=1),typeof o.transformRequest=="function"&&(i=o.transformRequest(i),!i))return f(e,t,"transformRequest");n&&W(i),N(o.endpoint,i,t)}function f(e,t,n){n&&o.logging&&console.warn(`Ignoring Event: ${n}`),t?.callback?.(),e==="pageview"&&(v=!0)}function H(e){return e?.tagName?.toLowerCase()==="a"}function X(e){for(;e&&(e.tagName===void 0||!H(e)||!e.href);)e=e.parentNode;return e}function ee(e){return e&&typeof e.href=="string"&&e.host&&e.host!==location.host}function te(e){return!!e&&O.includes(e.split(".").pop())}function T(e){return!!e?.classList&&[...e.classList].some(t=>$.test(t))}function y(e,t){return!!e&&t<=3&&(T(e)||y(e.parentNode,t+1))}function U(e){let t=T(e)?e:e?.parentNode,n={name:null,props:{},revenue:{}};if(!t?.classList)return n;for(let i of t.classList){let a=i.match(/thebase-event-(.+)(=|--)(.+)/);if(a){let _=a[3].replace(/\+/g," ");a[1].toLowerCase()==="name"?n.name=_:n.props[a[1]]=_}let c=i.match(/thebase-revenue-(.+)(=|--)(.+)/);c&&(n.revenue[c[1]]=c[3])}return n}function g(e){d(e.name,{props:e.props,revenue:e.revenue})}function R(e){if(e.type==="auxclick"&&e.button!==1)return;let t=X(e.target);if(y(t,0))return;if(o.outboundLinks&&ee(t))return g({name:"Outbound Link: Click",props:{url:t.href}});let n=t&&typeof t.href=="string"&&t.href.split("?")[0];o.fileDownloads&&te(n)&&g({name:"File Download",props:{url:n}})}function P(e){if(e.type==="auxclick"&&e.button!==1)return;let t,n,i=e.target;for(let c=0;c<=3&&i;c++){if(i.tagName?.toLowerCase()==="form")return;H(i)&&(t=i),T(i)&&(n=i),i=i.parentNode}if(!n)return;let a=U(n);t&&(a.props.url=t.href),g(a)}function ne(e){let t=e.target;(t.hasAttribute("novalidate")||t.checkValidity())&&!y(t,0)&&d("Form: Submission")}function ie(e){let t=U(e.target);t.name&&g(t)}function oe(){document.addEventListener("click",R),document.addEventListener("auxclick",R),Array.isArray(o.fileDownloads?.fileExtensions)&&(O=o.fileDownloads.fileExtensions),o.formSubmissions&&document.addEventListener("submit",ne,!0),document.addEventListener("submit",ie),document.addEventListener("click",P),document.addEventListener("auxclick",P)}function h(e){!o.hashBasedRouting&&e&&m===location.pathname||(m=location.pathname,d("pageview"))}function b(){h(!0)}function ae(...e){A.apply(this,e),b()}function re(){!m&&document.visibilityState==="visible"&&h()}function se(e){e.persisted&&h()}function ce(){o.hashBasedRouting?window.addEventListener("hashchange",b):(A=window.history.pushState,window.history.pushState=ae,window.addEventListener("popstate",b)),document.visibilityState==="hidden"||document.visibilityState==="prerender"?document.addEventListener("visibilitychange",re):h(),window.addEventListener("pageshow",se)}function ue(e){G(e||{}),Z(),o.autoCapturePageviews&&ce(),oe(),o.bindToWindow&&(window.thebase??(window.thebase={}),window.thebase.track=d,window.thebase.track.s="npm",window.thebase.track.v=36,window.thebase.track.l=!0)}window.thebase??(window.thebase={});window.thebase.analytics=k;})();