@pwa-platform/react 0.1.0-beta.1 → 0.1.0-beta.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.
package/README.md CHANGED
@@ -4,6 +4,20 @@ React 19 binding for PWA Platform.
4
4
 
5
5
  Use `PwaProvider` and `usePwa()` in a React 19 application. Also configure `@pwa-platform/vite` for build artifacts.
6
6
 
7
+ The current source adds an opt-in update notice (not present in the published `0.1.0-beta.1`):
8
+
9
+ ```tsx
10
+ import { PwaUpdateNotice } from "@pwa-platform/react/ui";
11
+ import "@pwa-platform/react/update-notice.css";
12
+
13
+ <PwaProvider config={config}>
14
+ <App />
15
+ <PwaUpdateNotice />
16
+ </PwaProvider>
17
+ ```
18
+
19
+ The default is a non-modal bottom-right card. `position` also accepts `bottom-center`, `top-right`, and `top-center`; `messages` overrides Chinese copy. Use `colors={{ primaryButtonBackground: "#006e52", primaryButtonText: "#ffffff" }}` for simple brand colors; `surface`, `text`, `mutedText`, and `border` are also available. Inherited `--pwa-update-*` CSS variables control the remaining appearance; `colors` takes precedence for values it sets. `reloadPage` can replace the final reload action when the application must protect unsaved work. Only a click on “刷新页面” calls it. The component does not register the worker; the application still calls `register()` and may configure `updateCheck` for long-lived pages.
20
+
7
21
  This is a `0.1.0` prerelease. It provides online use, installation integration, static precaching, a safe offline fallback, and controlled updates. It does not enable runtime business API caching, private data caching, automatic write replay, or Push for applications. Production deployment requires the application and infrastructure checks described in the PWA Platform release runbook.
8
22
 
9
23
  License: MIT.
package/dist/ui.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { type ReactElement } from "react";
2
+ export type PwaUpdateNoticePosition = "bottom-right" | "bottom-center" | "top-right" | "top-center";
3
+ export type PwaUpdateNoticeMessages = {
4
+ readonly readyTitle: string;
5
+ readonly readyBody: string;
6
+ readonly update: string;
7
+ readonly later: string;
8
+ readonly updatingTitle: string;
9
+ readonly updatingBody: string;
10
+ readonly reloadTitle: string;
11
+ readonly reloadBody: string;
12
+ readonly reload: string;
13
+ readonly errorTitle: string;
14
+ readonly errorBody: string;
15
+ readonly retry: string;
16
+ };
17
+ export type PwaUpdateNoticeProps = {
18
+ readonly position?: PwaUpdateNoticePosition;
19
+ readonly messages?: Partial<PwaUpdateNoticeMessages>;
20
+ readonly colors?: Partial<PwaUpdateNoticeColors>;
21
+ readonly reloadPage?: () => void;
22
+ };
23
+ export type PwaUpdateNoticeColors = {
24
+ readonly surface: string;
25
+ readonly text: string;
26
+ readonly mutedText: string;
27
+ readonly border: string;
28
+ readonly primaryButtonBackground: string;
29
+ readonly primaryButtonText: string;
30
+ };
31
+ /** Opt-in, non-modal update notice. Import `@pwa-platform/react/update-notice.css` for its default appearance. */
32
+ export declare function PwaUpdateNotice({ position, messages: overrides, colors, reloadPage, }: PwaUpdateNoticeProps): ReactElement | null;
33
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1G,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,eAAe,GAAG,WAAW,GAAG,YAAY,CAAC;AAEpG,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACrD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC,CAAC;AAsBF,kHAAkH;AAClH,wBAAgB,eAAe,CAAC,EAC9B,QAAyB,EACzB,QAAQ,EAAE,SAAS,EACnB,MAAM,EACN,UAAU,GACX,EAAE,oBAAoB,GAAG,YAAY,GAAG,IAAI,CA6H5C"}
package/dist/ui.js ADDED
@@ -0,0 +1,147 @@
1
+ import { createElement, useEffect, useRef, useState } from "react";
2
+ import { usePwa } from "./index.js";
3
+ const DEFAULT_MESSAGES = {
4
+ readyTitle: "有可用更新",
5
+ readyBody: "新版离线资源已准备好,你可以在合适的时候更新。",
6
+ update: "更新",
7
+ later: "稍后",
8
+ updatingTitle: "正在更新",
9
+ updatingBody: "正在切换离线资源,请稍候。",
10
+ reloadTitle: "更新已完成",
11
+ reloadBody: "需要时刷新页面,以确保使用最新内容。",
12
+ reload: "刷新页面",
13
+ errorTitle: "更新未完成",
14
+ errorBody: "请检查连接后重试。",
15
+ retry: "重试",
16
+ };
17
+ const REMIND_AFTER_MS = 30 * 60_000;
18
+ const STABLE_WAITING_MS = 100;
19
+ /** Opt-in, non-modal update notice. Import `@pwa-platform/react/update-notice.css` for its default appearance. */
20
+ export function PwaUpdateNotice({ position = "bottom-right", messages: overrides, colors, reloadPage, }) {
21
+ const pwa = usePwa();
22
+ const waiting = pwa.state.updateWaiting;
23
+ const [phase, setPhase] = useState("ready");
24
+ const [dismissed, setDismissed] = useState(false);
25
+ const [stableWaiting, setStableWaiting] = useState(false);
26
+ const previousWaiting = useRef(false);
27
+ const stableWaitingRef = useRef(false);
28
+ const takeoverObserved = useRef(false);
29
+ const reminder = useRef(undefined);
30
+ const waitingTimer = useRef(undefined);
31
+ const mounted = useRef(true);
32
+ function clearReminder() {
33
+ if (reminder.current !== undefined)
34
+ clearTimeout(reminder.current);
35
+ reminder.current = undefined;
36
+ }
37
+ function clearWaitingTimer() {
38
+ if (waitingTimer.current !== undefined)
39
+ clearTimeout(waitingTimer.current);
40
+ waitingTimer.current = undefined;
41
+ }
42
+ function markStableWaiting(value) {
43
+ stableWaitingRef.current = value;
44
+ setStableWaiting(value);
45
+ }
46
+ useEffect(() => {
47
+ const wasWaiting = previousWaiting.current;
48
+ previousWaiting.current = waiting;
49
+ if (waiting && !wasWaiting) {
50
+ takeoverObserved.current = false;
51
+ setPhase("ready");
52
+ setDismissed(false);
53
+ markStableWaiting(false);
54
+ clearReminder();
55
+ clearWaitingTimer();
56
+ waitingTimer.current = setTimeout(() => {
57
+ waitingTimer.current = undefined;
58
+ if (previousWaiting.current)
59
+ markStableWaiting(true);
60
+ }, STABLE_WAITING_MS);
61
+ }
62
+ else if (!waiting && wasWaiting) {
63
+ const wasStable = stableWaitingRef.current;
64
+ clearWaitingTimer();
65
+ markStableWaiting(false);
66
+ takeoverObserved.current = wasStable;
67
+ setPhase(wasStable ? "reload" : "ready");
68
+ setDismissed(false);
69
+ clearReminder();
70
+ }
71
+ }, [waiting]);
72
+ useEffect(() => {
73
+ mounted.current = true;
74
+ return () => {
75
+ mounted.current = false;
76
+ clearReminder();
77
+ clearWaitingTimer();
78
+ previousWaiting.current = false;
79
+ };
80
+ }, []);
81
+ function later() {
82
+ setDismissed(true);
83
+ clearReminder();
84
+ reminder.current = setTimeout(() => {
85
+ reminder.current = undefined;
86
+ if (previousWaiting.current)
87
+ setDismissed(false);
88
+ }, REMIND_AFTER_MS);
89
+ }
90
+ async function apply() {
91
+ if (phase === "updating")
92
+ return;
93
+ setPhase("updating");
94
+ try {
95
+ const applied = await pwa.applyUpdate();
96
+ if (!mounted.current)
97
+ return;
98
+ setPhase(applied || takeoverObserved.current ? "reload" : "ready");
99
+ }
100
+ catch {
101
+ if (mounted.current)
102
+ setPhase(takeoverObserved.current ? "reload" : "error");
103
+ }
104
+ }
105
+ function reload() {
106
+ if (reloadPage !== undefined)
107
+ reloadPage();
108
+ else
109
+ window.location.reload();
110
+ }
111
+ const mode = phase === "ready" ? (waiting && stableWaiting && !dismissed ? "ready" : null) : phase;
112
+ if (mode === null)
113
+ return null;
114
+ const messages = { ...DEFAULT_MESSAGES, ...overrides };
115
+ const title = messages[`${mode}Title`];
116
+ const body = messages[`${mode}Body`];
117
+ const buttons = [];
118
+ if (mode === "ready") {
119
+ buttons.push(createElement("button", { key: "update", type: "button", className: "pwa-update-notice__button pwa-update-notice__button--primary", onClick: () => void apply() }, messages.update));
120
+ buttons.push(createElement("button", { key: "later", type: "button", className: "pwa-update-notice__button", onClick: later }, messages.later));
121
+ }
122
+ else if (mode === "updating") {
123
+ buttons.push(createElement("button", { key: "updating", type: "button", className: "pwa-update-notice__button pwa-update-notice__button--primary", disabled: true }, messages.updatingTitle));
124
+ }
125
+ else if (mode === "reload") {
126
+ buttons.push(createElement("button", { key: "reload", type: "button", className: "pwa-update-notice__button pwa-update-notice__button--primary", onClick: reload }, messages.reload));
127
+ }
128
+ else {
129
+ buttons.push(createElement("button", { key: "retry", type: "button", className: "pwa-update-notice__button pwa-update-notice__button--primary", onClick: () => void apply() }, messages.retry));
130
+ }
131
+ return createElement("section", {
132
+ className: "pwa-update-notice",
133
+ "data-position": position,
134
+ style: {
135
+ "--pwa-update-surface": colors?.surface,
136
+ "--pwa-update-text": colors?.text,
137
+ "--pwa-update-muted": colors?.mutedText,
138
+ "--pwa-update-border": colors?.border,
139
+ "--pwa-update-accent": colors?.primaryButtonBackground,
140
+ "--pwa-update-accent-text": colors?.primaryButtonText,
141
+ },
142
+ role: "status",
143
+ "aria-live": "polite",
144
+ "aria-busy": mode === "updating",
145
+ }, createElement("h2", { className: "pwa-update-notice__title" }, title), createElement("p", { className: "pwa-update-notice__body" }, body), createElement("div", { className: "pwa-update-notice__actions" }, buttons));
146
+ }
147
+ //# sourceMappingURL=ui.js.map
package/dist/ui.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ .pwa-update-notice {
2
+ --pwa-update-default-surface: #ffffff;
3
+ --pwa-update-default-text: #1f2328;
4
+ --pwa-update-default-muted: #57616d;
5
+ --pwa-update-default-border: #d0d7de;
6
+ --pwa-update-default-accent: #0b5cd5;
7
+ --pwa-update-default-accent-text: #ffffff;
8
+ position: fixed;
9
+ z-index: var(--pwa-update-z-index, 1200);
10
+ box-sizing: border-box;
11
+ width: min(24rem, calc(100vw - 2rem));
12
+ padding: 1rem;
13
+ border: 1px solid var(--pwa-update-border, var(--pwa-update-default-border));
14
+ border-radius: var(--pwa-update-radius, 0.5rem);
15
+ background: var(--pwa-update-surface, var(--pwa-update-default-surface));
16
+ color: var(--pwa-update-text, var(--pwa-update-default-text));
17
+ box-shadow: var(--pwa-update-shadow, 0 8px 24px rgb(15 23 42 / 12%));
18
+ font-family: var(--pwa-update-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
19
+ font-size: 0.875rem;
20
+ line-height: 1.5;
21
+ overflow-wrap: anywhere;
22
+ color-scheme: light;
23
+ }
24
+
25
+ .pwa-update-notice[data-position="bottom-right"] {
26
+ inset-block-end: calc(1rem + env(safe-area-inset-bottom));
27
+ inset-inline-end: calc(1rem + env(safe-area-inset-right));
28
+ }
29
+
30
+ .pwa-update-notice[data-position="bottom-center"] {
31
+ inset-block-end: calc(1rem + env(safe-area-inset-bottom));
32
+ inset-inline-start: 50%;
33
+ transform: translateX(-50%);
34
+ }
35
+
36
+ .pwa-update-notice[data-position="top-right"] {
37
+ inset-block-start: calc(1rem + env(safe-area-inset-top));
38
+ inset-inline-end: calc(1rem + env(safe-area-inset-right));
39
+ }
40
+
41
+ .pwa-update-notice[data-position="top-center"] {
42
+ inset-block-start: calc(1rem + env(safe-area-inset-top));
43
+ inset-inline-start: 50%;
44
+ transform: translateX(-50%);
45
+ }
46
+
47
+ .pwa-update-notice__title {
48
+ margin: 0;
49
+ font-size: 1rem;
50
+ font-weight: 650;
51
+ line-height: 1.4;
52
+ }
53
+
54
+ .pwa-update-notice__body {
55
+ margin: 0.375rem 0 0;
56
+ color: var(--pwa-update-muted, var(--pwa-update-default-muted));
57
+ }
58
+
59
+ .pwa-update-notice__actions {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 0.5rem;
63
+ margin-top: 0.875rem;
64
+ }
65
+
66
+ .pwa-update-notice__button {
67
+ min-height: 44px;
68
+ padding: 0.5rem 0.875rem;
69
+ border: 1px solid var(--pwa-update-border, var(--pwa-update-default-border));
70
+ border-radius: var(--pwa-update-radius, 0.5rem);
71
+ background: var(--pwa-update-surface, var(--pwa-update-default-surface));
72
+ color: var(--pwa-update-text, var(--pwa-update-default-text));
73
+ font: inherit;
74
+ font-weight: 600;
75
+ cursor: pointer;
76
+ }
77
+
78
+ .pwa-update-notice__button--primary {
79
+ border-color: var(--pwa-update-accent, var(--pwa-update-default-accent));
80
+ background: var(--pwa-update-accent, var(--pwa-update-default-accent));
81
+ color: var(--pwa-update-accent-text, var(--pwa-update-default-accent-text));
82
+ }
83
+
84
+ .pwa-update-notice__button:disabled {
85
+ cursor: wait;
86
+ opacity: 0.7;
87
+ }
88
+
89
+ .pwa-update-notice__button:focus-visible {
90
+ outline: 2px solid var(--pwa-update-accent, var(--pwa-update-default-accent));
91
+ outline-offset: 2px;
92
+ }
93
+
94
+ @media (prefers-color-scheme: dark) {
95
+ .pwa-update-notice {
96
+ --pwa-update-default-surface: #161b22;
97
+ --pwa-update-default-text: #e6e9ec;
98
+ --pwa-update-default-muted: #a6b0bd;
99
+ --pwa-update-default-border: #3d4652;
100
+ --pwa-update-default-accent: #4c93ff;
101
+ --pwa-update-default-accent-text: #0b1220;
102
+ color-scheme: dark;
103
+ }
104
+ }
105
+
106
+ @media (max-width: 480px) {
107
+ .pwa-update-notice[data-position] {
108
+ inset-inline-start: 1rem;
109
+ inset-inline-end: 1rem;
110
+ width: auto;
111
+ transform: none;
112
+ }
113
+ }
package/package.json CHANGED
@@ -1,15 +1,22 @@
1
1
  {
2
2
  "name": "@pwa-platform/react",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.2",
4
4
  "description": "React 19 binding for PWA Platform.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
- "sideEffects": false,
7
+ "sideEffects": [
8
+ "./dist/update-notice.css"
9
+ ],
8
10
  "exports": {
9
11
  ".": {
10
12
  "types": "./dist/index.d.ts",
11
13
  "import": "./dist/index.js"
12
- }
14
+ },
15
+ "./ui": {
16
+ "types": "./dist/ui.d.ts",
17
+ "import": "./dist/ui.js"
18
+ },
19
+ "./update-notice.css": "./dist/update-notice.css"
13
20
  },
14
21
  "types": "./dist/index.d.ts",
15
22
  "files": [
@@ -19,12 +26,12 @@
19
26
  "react": "^19.2.0"
20
27
  },
21
28
  "dependencies": {
22
- "@pwa-platform/client-runtime": "0.1.0-beta.1"
29
+ "@pwa-platform/client-runtime": "0.1.0-beta.2"
23
30
  },
24
31
  "devDependencies": {
25
32
  "@types/react": "19.3.0",
26
33
  "react": "19.3.0",
27
- "@pwa-platform/vue": "0.1.0-beta.1"
34
+ "@pwa-platform/vue": "0.1.0-beta.2"
28
35
  },
29
36
  "engines": {
30
37
  "node": ">=22.0.0"
@@ -35,7 +42,7 @@
35
42
  "tag": "next"
36
43
  },
37
44
  "scripts": {
38
- "build": "tsc --project tsconfig.build.json",
45
+ "build": "tsc --project tsconfig.build.json && node -e \"require('node:fs').copyFileSync('src/update-notice.css', 'dist/update-notice.css')\"",
39
46
  "test": "vitest run",
40
47
  "typecheck": "tsc --noEmit --project tsconfig.json"
41
48
  }