@shipfox/client-shell 24.0.0 → 25.0.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/components/main-layout.d.ts.map +1 -1
- package/dist/components/main-layout.js +59 -2
- package/dist/components/main-layout.js.map +1 -1
- package/dist/components/main-layout.stories.js +231 -0
- package/dist/components/main-layout.stories.js.map +1 -0
- package/dist/components/user-menu.d.ts.map +1 -1
- package/dist/components/user-menu.js +18 -23
- package/dist/components/user-menu.js.map +1 -1
- package/dist/runtime/chrome-context.d.ts +10 -0
- package/dist/runtime/chrome-context.d.ts.map +1 -1
- package/dist/runtime/chrome-context.js.map +1 -1
- package/dist/runtime/report-error-boundary.d.ts +34 -0
- package/dist/runtime/report-error-boundary.d.ts.map +1 -0
- package/dist/runtime/report-error-boundary.js +46 -0
- package/dist/runtime/report-error-boundary.js.map +1 -0
- package/dist/runtime/workspace-setup-dismissal.d.ts +1 -0
- package/dist/runtime/workspace-setup-dismissal.d.ts.map +1 -1
- package/dist/runtime/workspace-setup-dismissal.js +7 -0
- package/dist/runtime/workspace-setup-dismissal.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Component } from 'react';
|
|
2
|
+
function reportFailure(label, cause) {
|
|
3
|
+
const failure = new Error(label, {
|
|
4
|
+
cause
|
|
5
|
+
});
|
|
6
|
+
if (typeof globalThis.reportError === 'function') {
|
|
7
|
+
globalThis.reportError(failure);
|
|
8
|
+
} else {
|
|
9
|
+
// biome-ignore lint/suspicious/noConsole: Failure reporting keeps a console fallback where reportError is unavailable.
|
|
10
|
+
console.error(label, cause);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Isolates an optional chrome slot from the rest of the shell. A render
|
|
15
|
+
* failure reports the error and renders nothing instead of unmounting the
|
|
16
|
+
* shell; the owner retries the slot by passing a new `retryKey`, so a
|
|
17
|
+
* transient failure recovers without a reload.
|
|
18
|
+
*/ export class ReportErrorBoundary extends Component {
|
|
19
|
+
static getDerivedStateFromError() {
|
|
20
|
+
return {
|
|
21
|
+
hasError: true
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
componentDidCatch(error) {
|
|
25
|
+
reportFailure(this.props.label, error);
|
|
26
|
+
this.props.onError?.();
|
|
27
|
+
}
|
|
28
|
+
componentDidUpdate(prevProps) {
|
|
29
|
+
if (this.state.hasError && prevProps.retryKey !== this.props.retryKey) {
|
|
30
|
+
this.setState({
|
|
31
|
+
hasError: false
|
|
32
|
+
});
|
|
33
|
+
this.props.onRecovered?.();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
render() {
|
|
37
|
+
return this.state.hasError ? null : this.props.children;
|
|
38
|
+
}
|
|
39
|
+
constructor(...args){
|
|
40
|
+
super(...args), this.state = {
|
|
41
|
+
hasError: false
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=report-error-boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/report-error-boundary.tsx"],"sourcesContent":["import {Component, type PropsWithChildren} from 'react';\n\nexport interface ReportErrorBoundaryProps extends PropsWithChildren {\n /** Message reported when the guarded slot throws; names the slot in diagnostics. */\n label: string;\n /** Called after a render failure so an owner can collapse the reserved slot. */\n onError?: () => void;\n /** Called when the boundary clears the error to retry the slot. */\n onRecovered?: () => void;\n /**\n * Stable value the owner changes only when the guarded slot should be\n * retried. The boundary latches on failure and resets only when this value\n * changes, so owner rerenders triggered by `onError`/`onRecovered` never\n * retry the same failing slot in a loop.\n */\n retryKey?: unknown;\n}\n\ntype ReportErrorBoundaryState = {hasError: boolean};\n\nfunction reportFailure(label: string, cause: unknown): void {\n const failure = new Error(label, {cause});\n if (typeof globalThis.reportError === 'function') {\n globalThis.reportError(failure);\n } else {\n // biome-ignore lint/suspicious/noConsole: Failure reporting keeps a console fallback where reportError is unavailable.\n console.error(label, cause);\n }\n}\n\n/**\n * Isolates an optional chrome slot from the rest of the shell. A render\n * failure reports the error and renders nothing instead of unmounting the\n * shell; the owner retries the slot by passing a new `retryKey`, so a\n * transient failure recovers without a reload.\n */\nexport class ReportErrorBoundary extends Component<\n ReportErrorBoundaryProps,\n ReportErrorBoundaryState\n> {\n override state: ReportErrorBoundaryState = {hasError: false};\n\n static getDerivedStateFromError(): ReportErrorBoundaryState {\n return {hasError: true};\n }\n\n override componentDidCatch(error: unknown): void {\n reportFailure(this.props.label, error);\n this.props.onError?.();\n }\n\n override componentDidUpdate(prevProps: ReportErrorBoundaryProps): void {\n if (this.state.hasError && prevProps.retryKey !== this.props.retryKey) {\n this.setState({hasError: false});\n this.props.onRecovered?.();\n }\n }\n\n override render() {\n return this.state.hasError ? null : this.props.children;\n }\n}\n"],"names":["Component","reportFailure","label","cause","failure","Error","globalThis","reportError","console","error","ReportErrorBoundary","getDerivedStateFromError","hasError","componentDidCatch","props","onError","componentDidUpdate","prevProps","state","retryKey","setState","onRecovered","render","children"],"mappings":"AAAA,SAAQA,SAAS,QAA+B,QAAQ;AAoBxD,SAASC,cAAcC,KAAa,EAAEC,KAAc;IAClD,MAAMC,UAAU,IAAIC,MAAMH,OAAO;QAACC;IAAK;IACvC,IAAI,OAAOG,WAAWC,WAAW,KAAK,YAAY;QAChDD,WAAWC,WAAW,CAACH;IACzB,OAAO;QACL,uHAAuH;QACvHI,QAAQC,KAAK,CAACP,OAAOC;IACvB;AACF;AAEA;;;;;CAKC,GACD,OAAO,MAAMO,4BAA4BV;IAMvC,OAAOW,2BAAqD;QAC1D,OAAO;YAACC,UAAU;QAAI;IACxB;IAESC,kBAAkBJ,KAAc,EAAQ;QAC/CR,cAAc,IAAI,CAACa,KAAK,CAACZ,KAAK,EAAEO;QAChC,IAAI,CAACK,KAAK,CAACC,OAAO;IACpB;IAESC,mBAAmBC,SAAmC,EAAQ;QACrE,IAAI,IAAI,CAACC,KAAK,CAACN,QAAQ,IAAIK,UAAUE,QAAQ,KAAK,IAAI,CAACL,KAAK,CAACK,QAAQ,EAAE;YACrE,IAAI,CAACC,QAAQ,CAAC;gBAACR,UAAU;YAAK;YAC9B,IAAI,CAACE,KAAK,CAACO,WAAW;QACxB;IACF;IAESC,SAAS;QAChB,OAAO,IAAI,CAACJ,KAAK,CAACN,QAAQ,GAAG,OAAO,IAAI,CAACE,KAAK,CAACS,QAAQ;IACzD;;QAxBK,qBAIIL,QAAkC;YAACN,UAAU;QAAK;;AAqB7D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT = "shipfox.workspaceSetupChecklist.dismissalChanged";
|
|
1
2
|
/**
|
|
2
3
|
* Reads whether the checklist was dismissed on this device at call time.
|
|
3
4
|
* Consumers that mount the value as UI state own any re-read or subscription.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-setup-dismissal.d.ts","sourceRoot":"","sources":["../../src/runtime/workspace-setup-dismissal.ts"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"workspace-setup-dismissal.d.ts","sourceRoot":"","sources":["../../src/runtime/workspace-setup-dismissal.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,yCAAyC,qDACF,CAAC;AAErD;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAGxE;AAED,wBAAgB,qCAAqC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAG/E"}
|
|
@@ -13,6 +13,7 @@ const workspaceSetupChecklistDismissalKey = {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
+
export const WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT = 'shipfox.workspaceSetupChecklist.dismissalChanged';
|
|
16
17
|
/**
|
|
17
18
|
* Reads whether the checklist was dismissed on this device at call time.
|
|
18
19
|
* Consumers that mount the value as UI state own any re-read or subscription.
|
|
@@ -21,9 +22,15 @@ const workspaceSetupChecklistDismissalKey = {
|
|
|
21
22
|
}
|
|
22
23
|
export function dismissWorkspaceSetupChecklist(workspaceId) {
|
|
23
24
|
workspaceSetupChecklistDismissalStorage(workspaceId).write(true);
|
|
25
|
+
dispatchWorkspaceSetupChecklistDismissalChange();
|
|
24
26
|
}
|
|
25
27
|
export function clearWorkspaceSetupChecklistDismissal(workspaceId) {
|
|
26
28
|
workspaceSetupChecklistDismissalStorage(workspaceId).remove();
|
|
29
|
+
dispatchWorkspaceSetupChecklistDismissalChange();
|
|
30
|
+
}
|
|
31
|
+
function dispatchWorkspaceSetupChecklistDismissalChange() {
|
|
32
|
+
if (typeof window === 'undefined') return;
|
|
33
|
+
window.dispatchEvent(new Event(WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT));
|
|
27
34
|
}
|
|
28
35
|
function workspaceSetupChecklistDismissalStorage(workspaceId) {
|
|
29
36
|
return createTypedBrowserStorage(localStorageOrUndefined, workspaceSetupChecklistDismissalKey, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/workspace-setup-dismissal.ts"],"sourcesContent":["import {\n type BrowserStorageKey,\n createTypedBrowserStorage,\n localStorageOrUndefined,\n} from '@shipfox/client-ui';\n\nconst workspaceSetupChecklistDismissalKey = {\n key: 'shipfox.workspaceSetupChecklist.dismissed',\n lifetime: 'persistent',\n principalScope: 'workspace',\n serialize: (dismissed: boolean) => JSON.stringify(dismissed),\n parse: (raw: string) => {\n try {\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === 'boolean' ? parsed : undefined;\n } catch {\n return undefined;\n }\n },\n} satisfies BrowserStorageKey<boolean>;\n\n/**\n * Reads whether the checklist was dismissed on this device at call time.\n * Consumers that mount the value as UI state own any re-read or subscription.\n */\nexport function isWorkspaceSetupChecklistDismissed(workspaceId: string): boolean {\n return workspaceSetupChecklistDismissalStorage(workspaceId).read() === true;\n}\n\nexport function dismissWorkspaceSetupChecklist(workspaceId: string): void {\n workspaceSetupChecklistDismissalStorage(workspaceId).write(true);\n}\n\nexport function clearWorkspaceSetupChecklistDismissal(workspaceId: string): void {\n workspaceSetupChecklistDismissalStorage(workspaceId).remove();\n}\n\nfunction workspaceSetupChecklistDismissalStorage(workspaceId: string) {\n return createTypedBrowserStorage(localStorageOrUndefined, workspaceSetupChecklistDismissalKey, {\n workspaceId,\n });\n}\n"],"names":["createTypedBrowserStorage","localStorageOrUndefined","workspaceSetupChecklistDismissalKey","key","lifetime","principalScope","serialize","dismissed","JSON","stringify","parse","raw","parsed","undefined","isWorkspaceSetupChecklistDismissed","workspaceId","workspaceSetupChecklistDismissalStorage","read","dismissWorkspaceSetupChecklist","write","clearWorkspaceSetupChecklistDismissal","remove"],"mappings":"AAAA,SAEEA,yBAAyB,EACzBC,uBAAuB,QAClB,qBAAqB;AAE5B,MAAMC,sCAAsC;IAC1CC,KAAK;IACLC,UAAU;IACVC,gBAAgB;IAChBC,WAAW,CAACC,YAAuBC,KAAKC,SAAS,CAACF;IAClDG,OAAO,CAACC;QACN,IAAI;YACF,MAAMC,SAAkBJ,KAAKE,KAAK,CAACC;YACnC,OAAO,OAAOC,WAAW,YAAYA,SAASC;QAChD,EAAE,OAAM;YACN,OAAOA;QACT;IACF;AACF;AAEA;;;CAGC,GACD,OAAO,SAASC,mCAAmCC,WAAmB;IACpE,OAAOC,wCAAwCD,aAAaE,IAAI,OAAO;AACzE;AAEA,OAAO,SAASC,+BAA+BH,WAAmB;IAChEC,wCAAwCD,aAAaI,KAAK,CAAC;
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/workspace-setup-dismissal.ts"],"sourcesContent":["import {\n type BrowserStorageKey,\n createTypedBrowserStorage,\n localStorageOrUndefined,\n} from '@shipfox/client-ui';\n\nconst workspaceSetupChecklistDismissalKey = {\n key: 'shipfox.workspaceSetupChecklist.dismissed',\n lifetime: 'persistent',\n principalScope: 'workspace',\n serialize: (dismissed: boolean) => JSON.stringify(dismissed),\n parse: (raw: string) => {\n try {\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === 'boolean' ? parsed : undefined;\n } catch {\n return undefined;\n }\n },\n} satisfies BrowserStorageKey<boolean>;\n\nexport const WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT =\n 'shipfox.workspaceSetupChecklist.dismissalChanged';\n\n/**\n * Reads whether the checklist was dismissed on this device at call time.\n * Consumers that mount the value as UI state own any re-read or subscription.\n */\nexport function isWorkspaceSetupChecklistDismissed(workspaceId: string): boolean {\n return workspaceSetupChecklistDismissalStorage(workspaceId).read() === true;\n}\n\nexport function dismissWorkspaceSetupChecklist(workspaceId: string): void {\n workspaceSetupChecklistDismissalStorage(workspaceId).write(true);\n dispatchWorkspaceSetupChecklistDismissalChange();\n}\n\nexport function clearWorkspaceSetupChecklistDismissal(workspaceId: string): void {\n workspaceSetupChecklistDismissalStorage(workspaceId).remove();\n dispatchWorkspaceSetupChecklistDismissalChange();\n}\n\nfunction dispatchWorkspaceSetupChecklistDismissalChange(): void {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new Event(WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT));\n}\n\nfunction workspaceSetupChecklistDismissalStorage(workspaceId: string) {\n return createTypedBrowserStorage(localStorageOrUndefined, workspaceSetupChecklistDismissalKey, {\n workspaceId,\n });\n}\n"],"names":["createTypedBrowserStorage","localStorageOrUndefined","workspaceSetupChecklistDismissalKey","key","lifetime","principalScope","serialize","dismissed","JSON","stringify","parse","raw","parsed","undefined","WORKSPACE_SETUP_CHECKLIST_DISMISSAL_EVENT","isWorkspaceSetupChecklistDismissed","workspaceId","workspaceSetupChecklistDismissalStorage","read","dismissWorkspaceSetupChecklist","write","dispatchWorkspaceSetupChecklistDismissalChange","clearWorkspaceSetupChecklistDismissal","remove","window","dispatchEvent","Event"],"mappings":"AAAA,SAEEA,yBAAyB,EACzBC,uBAAuB,QAClB,qBAAqB;AAE5B,MAAMC,sCAAsC;IAC1CC,KAAK;IACLC,UAAU;IACVC,gBAAgB;IAChBC,WAAW,CAACC,YAAuBC,KAAKC,SAAS,CAACF;IAClDG,OAAO,CAACC;QACN,IAAI;YACF,MAAMC,SAAkBJ,KAAKE,KAAK,CAACC;YACnC,OAAO,OAAOC,WAAW,YAAYA,SAASC;QAChD,EAAE,OAAM;YACN,OAAOA;QACT;IACF;AACF;AAEA,OAAO,MAAMC,4CACX,mDAAmD;AAErD;;;CAGC,GACD,OAAO,SAASC,mCAAmCC,WAAmB;IACpE,OAAOC,wCAAwCD,aAAaE,IAAI,OAAO;AACzE;AAEA,OAAO,SAASC,+BAA+BH,WAAmB;IAChEC,wCAAwCD,aAAaI,KAAK,CAAC;IAC3DC;AACF;AAEA,OAAO,SAASC,sCAAsCN,WAAmB;IACvEC,wCAAwCD,aAAaO,MAAM;IAC3DF;AACF;AAEA,SAASA;IACP,IAAI,OAAOG,WAAW,aAAa;IACnCA,OAAOC,aAAa,CAAC,IAAIC,MAAMZ;AACjC;AAEA,SAASG,wCAAwCD,WAAmB;IAClE,OAAOhB,0BAA0BC,yBAAyBC,qCAAqC;QAC7Fc;IACF;AACF"}
|