@broberg/pwa 0.7.0 → 0.8.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/raster.d.ts CHANGED
@@ -20,6 +20,63 @@ interface IconSet {
20
20
  icons: ManifestIcon[];
21
21
  }
22
22
 
23
+ interface NativeIconFile {
24
+ /** Path relative to the output directory, e.g. `ios/AppIcon.appiconset/AppIcon-1024.png`. */
25
+ path: string;
26
+ content: Uint8Array;
27
+ }
28
+ interface NativeIconOptions {
29
+ /** Hex colour behind the motif (`#RRGGBB`). Required — see the module comment. */
30
+ background: string;
31
+ /** Default: all three. */
32
+ platforms?: Array<"ios" | "android" | "desktop">;
33
+ }
34
+ declare const NATIVE_BACKGROUND_REQUIRED = "nativeIconSet needs `background` (#RRGGBB): a white symbol on a transparent canvas renders as an empty icon";
35
+ /** Android density → adaptive foreground px (108dp) and legacy launcher px (48dp). */
36
+ declare const ANDROID_DENSITIES: readonly [{
37
+ readonly dpi: "mdpi";
38
+ readonly foreground: 108;
39
+ readonly legacy: 48;
40
+ }, {
41
+ readonly dpi: "hdpi";
42
+ readonly foreground: 162;
43
+ readonly legacy: 72;
44
+ }, {
45
+ readonly dpi: "xhdpi";
46
+ readonly foreground: 216;
47
+ readonly legacy: 96;
48
+ }, {
49
+ readonly dpi: "xxhdpi";
50
+ readonly foreground: 324;
51
+ readonly legacy: 144;
52
+ }, {
53
+ readonly dpi: "xxxhdpi";
54
+ readonly foreground: 432;
55
+ readonly legacy: 192;
56
+ }];
57
+ /** Share of the 108dp adaptive canvas that every launcher mask keeps visible. */
58
+ declare const ANDROID_SAFE_ZONE: number;
59
+ declare const ICO_SIZES: readonly [16, 32, 48, 256];
60
+ /** ICNS chunk type → pixel size (PNG payloads). */
61
+ declare const ICNS_CHUNKS: readonly [readonly ["ic11", 32], readonly ["ic12", 64], readonly ["ic07", 128], readonly ["ic08", 256], readonly ["ic13", 256], readonly ["ic09", 512], readonly ["ic14", 512], readonly ["ic10", 1024]];
62
+ /** Encode RGBA pixels as an RGB PNG (colour type 2) — the alpha channel is dropped, not just made opaque. */
63
+ declare function encodeRgbPng(rgba: Uint8Array, width: number, height: number): Uint8Array;
64
+ /** An ICO holding PNG images (Vista+ format). */
65
+ declare function encodeIco(pngs: Array<{
66
+ size: number;
67
+ png: Uint8Array;
68
+ }>): Uint8Array;
69
+ /** An ICNS holding PNG chunks. */
70
+ declare function encodeIcns(chunks: Array<{
71
+ type: string;
72
+ png: Uint8Array;
73
+ }>): Uint8Array;
74
+ /**
75
+ * Every native icon file for `svg`. Requires the optional peer @resvg/resvg-js,
76
+ * like `rasterizeIconSet`.
77
+ */
78
+ declare function nativeIconSet(svg: string, opts: NativeIconOptions): Promise<NativeIconFile[]>;
79
+
23
80
  /**
24
81
  * @broberg/pwa/raster — F021.9: PNG icons, because iOS does not use an SVG
25
82
  * apple-touch-icon. «Add to Home Screen» on an iPhone with only SVG icons shows
@@ -60,4 +117,4 @@ declare const RESVG_MISSING = "rasterizeIconSet needs @resvg/resvg-js \u2014 ins
60
117
  /** Rasterise every SVG from `buildIconSet` to a PNG of the same size. */
61
118
  declare function rasterizeIconSet(set: IconSet, opts?: RasterizeOptions): Promise<RasterIconSet>;
62
119
 
63
- export { RESVG_MISSING, type RasterIcon, type RasterIconSet, type RasterizeOptions, rasterizeIconSet };
120
+ export { ANDROID_DENSITIES, ANDROID_SAFE_ZONE, ICNS_CHUNKS, ICO_SIZES, NATIVE_BACKGROUND_REQUIRED, type NativeIconFile, type NativeIconOptions, RESVG_MISSING, type RasterIcon, type RasterIconSet, type RasterizeOptions, encodeIcns, encodeIco, encodeRgbPng, nativeIconSet, rasterizeIconSet };
package/dist/raster.js CHANGED
@@ -1,3 +1,3 @@
1
- export { RESVG_MISSING, rasterizeIconSet } from './chunk-33GKPCTR.js';
1
+ export { ANDROID_DENSITIES, ANDROID_SAFE_ZONE, ICNS_CHUNKS, ICO_SIZES, NATIVE_BACKGROUND_REQUIRED, RESVG_MISSING, encodeIcns, encodeIco, encodeRgbPng, nativeIconSet, rasterizeIconSet } from './chunk-TZPDZ6IO.js';
2
2
  //# sourceMappingURL=raster.js.map
3
3
  //# sourceMappingURL=raster.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@broberg/pwa",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Fleet PWA primitive: a framework-agnostic service-worker update-detection controller (new-version-available lifecycle) + a React hook and unstyled banner skeleton + a service-worker skip-waiting helper. Zero runtime deps; ship-dark.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,26 +0,0 @@
1
- // src/raster.ts
2
- var RESVG_MISSING = "rasterizeIconSet needs @resvg/resvg-js \u2014 install it as a dev dependency: npm i -D @resvg/resvg-js";
3
- var toPng = (p) => p.replace(/\.svg$/, ".png");
4
- async function rasterizeIconSet(set, opts = {}) {
5
- let Resvg;
6
- try {
7
- ({ Resvg } = await import('@resvg/resvg-js'));
8
- } catch {
9
- throw new Error(RESVG_MISSING);
10
- }
11
- const files = set.files.map((f) => {
12
- const png = new Resvg(f.content, {
13
- fitTo: { mode: "width", value: f.size },
14
- font: { loadSystemFonts: true, fontFiles: opts.fontFiles ?? [] }
15
- }).render().asPng();
16
- return { path: toPng(f.path), content: new Uint8Array(png), type: "image/png", size: f.size, purpose: f.purpose };
17
- });
18
- const icons = set.icons.map((i) => ({ ...i, src: toPng(i.src), type: "image/png" }));
19
- const apple = files.find((f) => f.size === 180 && f.purpose === "any");
20
- const rootFiles = apple ? ["/apple-touch-icon.png", "/apple-touch-icon-precomposed.png"].map((path) => ({ ...apple, path })) : [];
21
- return { files, icons, appleTouchIcon: apple?.path, rootFiles };
22
- }
23
-
24
- export { RESVG_MISSING, rasterizeIconSet };
25
- //# sourceMappingURL=chunk-33GKPCTR.js.map
26
- //# sourceMappingURL=chunk-33GKPCTR.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/raster.ts"],"names":[],"mappings":";AAwCO,IAAM,aAAA,GACX;AAEF,IAAM,QAAQ,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,UAAU,MAAM,CAAA;AAGvD,eAAsB,gBAAA,CAAiB,GAAA,EAAc,IAAA,GAAyB,EAAC,EAA2B;AACxG,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAC,EAAE,KAAA,EAAM,GAAI,MAAM,OAAO,iBAAiB,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,aAAa,CAAA;AAAA,EAC/B;AACA,EAAA,MAAM,KAAA,GAAsB,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AAC/C,IAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS;AAAA,MAC/B,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAK;AAAA,MACtC,IAAA,EAAM,EAAE,eAAA,EAAiB,IAAA,EAAM,WAAW,IAAA,CAAK,SAAA,IAAa,EAAC;AAAE,KAChE,CAAA,CACE,MAAA,EAAO,CACP,KAAA,EAAM;AACT,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,CAAM,EAAE,IAAI,CAAA,EAAG,SAAS,IAAI,UAAA,CAAW,GAAG,CAAA,EAAG,MAAM,WAAA,EAAa,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,EAAE,OAAA,EAAQ;AAAA,EAClH,CAAC,CAAA;AACD,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,OAAO,EAAE,GAAG,CAAA,EAAG,GAAA,EAAK,MAAM,CAAA,CAAE,GAAG,CAAA,EAAG,IAAA,EAAM,aAAY,CAAE,CAAA;AACnF,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,GAAA,IAAO,CAAA,CAAE,OAAA,KAAY,KAAK,CAAA;AACrE,EAAA,MAAM,SAAA,GAA0B,KAAA,GAC5B,CAAC,uBAAA,EAAyB,mCAAmC,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,GAAG,KAAA,EAAO,IAAA,EAAK,CAAE,IACjG,EAAC;AACL,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,cAAA,EAAgB,KAAA,EAAO,MAAM,SAAA,EAAU;AAChE","file":"chunk-33GKPCTR.js","sourcesContent":["/**\n * @broberg/pwa/raster — F021.9: PNG icons, because iOS does not use an SVG\n * apple-touch-icon. «Add to Home Screen» on an iPhone with only SVG icons shows\n * a screenshot of the page instead of the logo (measured by sales, 10/10).\n *\n * Kept OUT of the core entries so `@broberg/pwa` and `/manifest` stay\n * dependency-free: the renderer, @resvg/resvg-js (prebuilt binaries, no system\n * libraries), is an optional peer loaded only when this runs.\n */\nimport type { IconSet, ManifestIcon } from \"./manifest.js\";\n\nexport interface RasterIcon {\n /** URL path, e.g. `/icons/icon-180.png`. */\n path: string;\n content: Uint8Array;\n type: \"image/png\";\n size: number;\n purpose: \"any\" | \"maskable\";\n}\n\nexport interface RasterIconSet {\n files: RasterIcon[];\n /** Manifest `icons[]` pointing at the PNGs. */\n icons: ManifestIcon[];\n /** Href for `<link rel=\"apple-touch-icon\">` — pass it to `pwaMetaTags({ appleTouchIcon })`. Undefined when 180 was not generated. */\n appleTouchIcon?: string;\n /**\n * F021.11 — the same 180 PNG at the two ROOT paths iOS asks for on its own\n * (`/apple-touch-icon.png`, `/apple-touch-icon-precomposed.png`). Write them to\n * your web root, NOT next to the other icons. Without them iOS fell back to a\n * letter («J») on a real home screen (jam, measured). Empty when 180 was not generated.\n */\n rootFiles: RasterIcon[];\n}\n\nexport interface RasterizeOptions {\n /** Extra font files for monogram text (system fonts are loaded too). */\n fontFiles?: string[];\n}\n\nexport const RESVG_MISSING =\n \"rasterizeIconSet needs @resvg/resvg-js — install it as a dev dependency: npm i -D @resvg/resvg-js\";\n\nconst toPng = (p: string) => p.replace(/\\.svg$/, \".png\");\n\n/** Rasterise every SVG from `buildIconSet` to a PNG of the same size. */\nexport async function rasterizeIconSet(set: IconSet, opts: RasterizeOptions = {}): Promise<RasterIconSet> {\n let Resvg: typeof import(\"@resvg/resvg-js\").Resvg;\n try {\n ({ Resvg } = await import(\"@resvg/resvg-js\"));\n } catch {\n throw new Error(RESVG_MISSING);\n }\n const files: RasterIcon[] = set.files.map((f) => {\n const png = new Resvg(f.content, {\n fitTo: { mode: \"width\", value: f.size },\n font: { loadSystemFonts: true, fontFiles: opts.fontFiles ?? [] },\n })\n .render()\n .asPng();\n return { path: toPng(f.path), content: new Uint8Array(png), type: \"image/png\", size: f.size, purpose: f.purpose };\n });\n const icons = set.icons.map((i) => ({ ...i, src: toPng(i.src), type: \"image/png\" }));\n const apple = files.find((f) => f.size === 180 && f.purpose === \"any\");\n const rootFiles: RasterIcon[] = apple\n ? [\"/apple-touch-icon.png\", \"/apple-touch-icon-precomposed.png\"].map((path) => ({ ...apple, path }))\n : [];\n return { files, icons, appleTouchIcon: apple?.path, rootFiles };\n}\n"]}