@thebase/ui 1.1.1 → 1.1.2

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.
@@ -0,0 +1,53 @@
1
+ var u=[{src:"/icons/icon-192.png",sizes:"192x192",type:"image/png",purpose:"any"},{src:"/icons/icon-512.png",sizes:"512x512",type:"image/png",purpose:"any"},{src:"/icons/icon-512.png",sizes:"512x512",type:"image/png",purpose:"maskable"}],f=["/","/manifest.webmanifest","/favicon.svg"];function d(n){let{name:t,shortName:s=t,description:c="",startUrl:r="/",scope:e="/",display:a="standalone",orientation:i="portrait-primary",backgroundColor:o="#ffffff",themeColor:h="#0f172a",lang:l="en",icons:p=u}=n;return{name:t,short_name:s,description:c,start_url:r,scope:e,display:a,orientation:i,background_color:o,theme_color:h,lang:l,icons:p}}function m(n){let{cacheName:t,cdnVersion:s,appFiles:c=[],extraPrecacheUrls:r=[]}=n,e=`https://cdn.jsdelivr.net/npm/@thebase/ui@${s}/dist/`,a=[...f,...c,...r,`${e}baseui.min.css`,`${e}baseui.esm.js`,`${e}baseui.templates.xml`];return`const CACHE_NAME = ${JSON.stringify(t)};
2
+ const BASEUI_CDN = ${JSON.stringify(e)};
3
+
4
+ const PRECACHE_URLS = ${JSON.stringify(a,null,2)};
5
+
6
+ self.addEventListener("install", (event) => {
7
+ event.waitUntil(
8
+ caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_URLS)).then(() => self.skipWaiting())
9
+ );
10
+ });
11
+
12
+ self.addEventListener("activate", (event) => {
13
+ event.waitUntil(
14
+ caches
15
+ .keys()
16
+ .then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))))
17
+ .then(() => self.clients.claim())
18
+ );
19
+ });
20
+
21
+ async function fromCdnCache(request) {
22
+ const cache = await caches.open(CACHE_NAME);
23
+ const cached = await cache.match(request);
24
+ if (cached) return cached;
25
+ const response = await fetch(request);
26
+ if (response.ok) cache.put(request, response.clone());
27
+ return response;
28
+ }
29
+
30
+ self.addEventListener("fetch", (event) => {
31
+ const { request } = event;
32
+ if (request.method !== "GET") return;
33
+ if (request.url.startsWith(BASEUI_CDN)) {
34
+ event.respondWith(fromCdnCache(request));
35
+ return;
36
+ }
37
+ if (new URL(request.url).origin !== self.location.origin) return;
38
+
39
+ event.respondWith(
40
+ caches.open(CACHE_NAME).then(async (cache) => {
41
+ try {
42
+ const response = await fetch(request);
43
+ if (response.ok) cache.put(request, response.clone());
44
+ return response;
45
+ } catch {
46
+ const cached = await cache.match(request);
47
+ if (cached) return cached;
48
+ throw new Error(\`No cached response for \${request.url} and network unavailable\`);
49
+ }
50
+ })
51
+ );
52
+ });
53
+ `}export{d as buildManifest,m as buildServiceWorker};
@@ -1662,8 +1662,8 @@
1662
1662
  "integrity": {
1663
1663
  "baseui.min.css": "sha384-hYFwlV6T/ONYzawtDGDFUoruqgNwYl9AVvLDHx24IWgKSMXqwACo/nX04I3gnyT9",
1664
1664
  "bootstrap.bundle.min.js": "sha384-RMbllTJcplkCRnELNTOc5Kz/3AvFDE/rNlJqWqfgmRWruobClBdfwvl10akQZkR1",
1665
- "baseui.min.js": "sha384-m91LivkZ3FsaSmngFXfmaGHxfBokU/tEXFAuYz3PIjeXuKMcJjdRmOEk596O8S8u",
1666
- "baseui.esm.js": "sha384-v3JjyzSIh67awBXIDScUTR40lyCHyuOue1zwObQHjH4OjOj9Cg3mPMkto3LVcVO7",
1665
+ "baseui.min.js": "sha384-Qv1lpDLXQ3+gI0MGXGSdeOmq7tX+Hn6/TcsSsnWikLXQhi7BTAIKNWPUeIXP1LxF",
1666
+ "baseui.esm.js": "sha384-IkUDqUsC56aiRgXggGe2XGZM2chM148CB837Gh/mWPtjqUEq5qH9ve5eG5texJPT",
1667
1667
  "baseui.icons.esm.js": "sha384-hj39VMhzcFvmYnjob2hlioMOAqwAXCURGreF6s9RitXFp/iYi7rUdqtfCI+ICQeS",
1668
1668
  "baseui.templates.xml": "sha384-XkqmfurKcEF6WuIQHWAbnZfW6oz19n7SDVRDU3g0hc3qOr4kPd/qfNGcTmcDDIgQ",
1669
1669
  "baseui.block-viewer.esm.js": "sha384-XlIb3jDxt6Q75dbC4rLctTdPU6u0vJFcbxp9Gl6VKOkhjpz3wRBe0E3dWd80425L",
@@ -0,0 +1,37 @@
1
+ /** Optional PWA toolkit: builds manifest.webmanifest/sw.js content from a config object. */
2
+ export interface BaseUIManifestConfig {
3
+ name: string;
4
+ /** Defaults to `name`. */
5
+ shortName?: string;
6
+ description?: string;
7
+ /** Defaults to "/". */
8
+ startUrl?: string;
9
+ /** Defaults to "/". */
10
+ scope?: string;
11
+ /** Defaults to "standalone". */
12
+ display?: string;
13
+ /** Defaults to "portrait-primary". */
14
+ orientation?: string;
15
+ /** Defaults to "#ffffff". */
16
+ backgroundColor?: string;
17
+ /** Defaults to "#0f172a". */
18
+ themeColor?: string;
19
+ /** Defaults to "en". */
20
+ lang?: string;
21
+ /** Defaults to a 192/512 `/icons/icon-*.png` set. */
22
+ icons?: Array<{ src: string; sizes: string; type: string; purpose?: string }>;
23
+ }
24
+
25
+ export interface BaseUIServiceWorkerConfig {
26
+ /** Cache bucket name, e.g. "my-app-cache-v1" — bump the suffix to invalidate old caches. */
27
+ cacheName: string;
28
+ /** Pinned `@thebase/ui` version the generated sw.js precaches/serves from jsdelivr. */
29
+ cdnVersion: string;
30
+ /** Same-origin app-shell paths to precache (JS/CSS/XML/icons/etc). */
31
+ appFiles?: string[];
32
+ /** Extra same-origin or cross-origin URLs to precache alongside `appFiles`. */
33
+ extraPrecacheUrls?: string[];
34
+ }
35
+
36
+ export function buildManifest(config: BaseUIManifestConfig): Record<string, unknown>;
37
+ export function buildServiceWorker(config: BaseUIServiceWorkerConfig): string;
package/docs/analytics.md CHANGED
@@ -84,7 +84,7 @@ init({ backendUrl: "https://stats.example.com", customProperties: visitorContext
84
84
  | `lang` | `navigator.language`, e.g. `vi-VN`. |
85
85
  | `screen` | Viewport width bucket: `Mobile` (< 576 px), `Tablet` (< 992), `Laptop` (< 1440), `Desktop`. |
86
86
 
87
- The values are deliberately coarse: no exact pixels, nothing persistent. Backends can treat `tz`, `lang` and `screen` as visit dimensions instead of event props. To combine it with your own props, call it inside your function: `customProperties: (name) => ({ ...visitorContext(), plan: "pro" })`. The IP address and user agent never appear in the payload; the server reads them from the HTTP request (see [Receiving events](#receiving-events-backend)).
87
+ The values are deliberately coarse: no exact pixels, nothing persistent. Backends can treat `tz`, `lang` and `screen` as visit dimensions instead of event props. To combine it with your own props, call it inside your function: `customProperties: (name) => ({ ...visitorContext(), plan: "pro" })`. Don't use `tz`, `lang` or `screen` as your own event prop names: event props override custom properties with the same key, so the visitor's value would be lost. Use something like `uiLang` instead. The IP address and user agent never appear in the payload; the server reads them from the HTTP request (see [Receiving events](#receiving-events-backend)).
88
88
 
89
89
  ## Engagement
90
90
 
@@ -200,6 +200,42 @@ Full token list and the shadcn-aligned default palette: [Theming](theming.md).
200
200
 
201
201
  Icons ship with the normal BaseUI assets — no separate script tag, and every Lucide icon name is available by kebab-case (`panel-left`), camelCase, or snake_case. Sizing, color, accessibility rules, and self-hosting: [Built-in Icons](icons.md).
202
202
 
203
+ ## 5b. PWA toolkit (optional) — generate manifest.webmanifest + sw.js
204
+
205
+ Any BaseUI app can become an installable PWA without hand-writing a service worker. `@thebase/ui/pwa`
206
+ exports two pure functions, `buildManifest(config)` and `buildServiceWorker(config)`, that turn a
207
+ config object into the exact manifest JSON and service-worker source a hand-written PWA needs
208
+ (precache the app shell, network-first for same-origin requests, cache-first for the pinned CDN
209
+ build). Define the variables once, regenerate the files whenever they change:
210
+
211
+ ```js
212
+ // baseui.pwa.config.js
213
+ export default {
214
+ manifest: {
215
+ name: "My App",
216
+ shortName: "MyApp",
217
+ description: "One sentence about the app.",
218
+ themeColor: "#0f172a",
219
+ },
220
+ serviceWorker: {
221
+ cacheName: "my-app-cache-v1",
222
+ cdnVersion: "1.1.1", // pin to match the importmap in index.html
223
+ appFiles: ["/app.css", "/app.js", "/app.xml", "/favicon.svg", "/icons/icon-192.png", "/icons/icon-512.png"],
224
+ },
225
+ };
226
+ ```
227
+
228
+ ```sh
229
+ npx create-baseui-app pwa . --config baseui.pwa.config.js
230
+ # writes ./manifest.webmanifest and ./sw.js
231
+ ```
232
+
233
+ Re-run the command whenever `appFiles`, the CDN pin, or manifest fields change — both output files are
234
+ fully regenerated, never hand-patched. Only `manifest.name`, `serviceWorker.cacheName`, and
235
+ `serviceWorker.cdnVersion` are required; everything else (icons, theme/background color, display
236
+ mode, extra precache URLs) has the same defaults the `qr-page` example ships with. See
237
+ `dist/types/pwa.d.ts` for the full config shape.
238
+
203
239
  ## 6. Copy a block instead of assembling from primitives
204
240
 
205
241
  For common layouts (dashboard shells, sidebars, login/signup forms, charts), copy a ready-made block from the gallery instead of composing primitives by hand: [Blocks](blocks.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thebase/ui",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "CDN-installable Owl and Bootstrap 5 UI component library.",
5
5
  "type": "module",
6
6
  "main": "./dist/baseui.min.js",
@@ -25,6 +25,10 @@
25
25
  "import": "./dist/baseui.analytics.esm.js",
26
26
  "default": "./dist/baseui.analytics.min.js"
27
27
  },
28
+ "./pwa": {
29
+ "types": "./dist/types/pwa.d.ts",
30
+ "import": "./dist/baseui.pwa.esm.js"
31
+ },
28
32
  "./dist/baseui.templates.xml": "./dist/baseui.templates.xml"
29
33
  },
30
34
  "files": [
@@ -35,6 +39,7 @@
35
39
  "dist/baseui.icons.esm.js",
36
40
  "dist/baseui.analytics.esm.js",
37
41
  "dist/baseui.analytics.min.js",
42
+ "dist/baseui.pwa.esm.js",
38
43
  "dist/baseui.templates.xml",
39
44
  "dist/icons",
40
45
  "dist/baseui.registry.json",