@ttt-productions/ui-core 0.11.34 → 0.11.35
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 +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +0 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/reload-recovery-watch.d.ts +0 -4
- package/dist/browser/reload-recovery-watch.d.ts.map +1 -1
- package/dist/browser/reload-recovery-watch.js +0 -5
- package/dist/browser/reload-recovery-watch.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/format-numbers.d.ts +0 -6
- package/dist/lib/format-numbers.d.ts.map +1 -1
- package/dist/lib/format-numbers.js +0 -6
- package/dist/lib/format-numbers.js.map +1 -1
- package/dist/lib/reload-recovery.d.ts +1 -9
- package/dist/lib/reload-recovery.d.ts.map +1 -1
- package/dist/lib/reload-recovery.js +1 -11
- package/dist/lib/reload-recovery.js.map +1 -1
- package/dist/lib/utils.d.ts +0 -3
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +0 -3
- package/dist/lib/utils.js.map +1 -1
- package/dist/react/components/accordion.d.ts.map +1 -1
- package/dist/react/components/accordion.js.map +1 -1
- package/dist/react/components/action-row.d.ts +0 -7
- package/dist/react/components/action-row.d.ts.map +1 -1
- package/dist/react/components/action-row.js +1 -5
- package/dist/react/components/action-row.js.map +1 -1
- package/dist/react/components/button.d.ts +0 -10
- package/dist/react/components/button.d.ts.map +1 -1
- package/dist/react/components/button.js +2 -7
- package/dist/react/components/button.js.map +1 -1
- package/dist/react/components/consequence-dialog.d.ts +1 -48
- package/dist/react/components/consequence-dialog.d.ts.map +1 -1
- package/dist/react/components/consequence-dialog.js +3 -21
- package/dist/react/components/consequence-dialog.js.map +1 -1
- package/dist/react/components/date-picker.d.ts +0 -17
- package/dist/react/components/date-picker.d.ts.map +1 -1
- package/dist/react/components/date-picker.js +0 -32
- package/dist/react/components/date-picker.js.map +1 -1
- package/dist/react/components/date-time-picker.d.ts +0 -23
- package/dist/react/components/date-time-picker.d.ts.map +1 -1
- package/dist/react/components/date-time-picker.js +0 -19
- package/dist/react/components/date-time-picker.js.map +1 -1
- package/dist/react/components/dropdown-menu.d.ts +0 -8
- package/dist/react/components/dropdown-menu.d.ts.map +1 -1
- package/dist/react/components/dropdown-menu.js +1 -2
- package/dist/react/components/dropdown-menu.js.map +1 -1
- package/dist/react/components/format-control.d.ts +1 -21
- package/dist/react/components/format-control.d.ts.map +1 -1
- package/dist/react/components/format-control.js +1 -21
- package/dist/react/components/format-control.js.map +1 -1
- package/dist/react/components/input.d.ts +0 -17
- package/dist/react/components/input.d.ts.map +1 -1
- package/dist/react/components/input.js +1 -3
- package/dist/react/components/input.js.map +1 -1
- package/dist/react/components/layout/screen-adaptive-view.d.ts +0 -7
- package/dist/react/components/layout/screen-adaptive-view.d.ts.map +1 -1
- package/dist/react/components/layout/screen-adaptive-view.js +1 -2
- package/dist/react/components/layout/screen-adaptive-view.js.map +1 -1
- package/dist/react/components/list-pagination.d.ts +0 -30
- package/dist/react/components/list-pagination.d.ts.map +1 -1
- package/dist/react/components/list-pagination.js +0 -27
- package/dist/react/components/list-pagination.js.map +1 -1
- package/dist/react/components/opener-focus.d.ts +1 -7
- package/dist/react/components/opener-focus.d.ts.map +1 -1
- package/dist/react/components/opener-focus.js +1 -7
- package/dist/react/components/opener-focus.js.map +1 -1
- package/dist/react/components/pending-guard.d.ts +0 -6
- package/dist/react/components/pending-guard.d.ts.map +1 -1
- package/dist/react/components/pending-guard.js +0 -6
- package/dist/react/components/pending-guard.js.map +1 -1
- package/dist/react/components/relative-time.d.ts +0 -8
- package/dist/react/components/relative-time.d.ts.map +1 -1
- package/dist/react/components/relative-time.js +0 -4
- package/dist/react/components/relative-time.js.map +1 -1
- package/dist/react/components/reload-recovery-notice.d.ts +0 -14
- package/dist/react/components/reload-recovery-notice.d.ts.map +1 -1
- package/dist/react/components/reload-recovery-notice.js +0 -5
- package/dist/react/components/reload-recovery-notice.js.map +1 -1
- package/dist/react/components/scroll-to-top-button.d.ts +1 -25
- package/dist/react/components/scroll-to-top-button.d.ts.map +1 -1
- package/dist/react/components/scroll-to-top-button.js.map +1 -1
- package/dist/react/components/search-dropdown.d.ts +0 -53
- package/dist/react/components/search-dropdown.d.ts.map +1 -1
- package/dist/react/components/search-dropdown.js +2 -36
- package/dist/react/components/search-dropdown.js.map +1 -1
- package/dist/react/components/select.d.ts +0 -7
- package/dist/react/components/select.d.ts.map +1 -1
- package/dist/react/components/select.js +0 -2
- package/dist/react/components/select.js.map +1 -1
- package/dist/react/components/show-more-toggle.d.ts +0 -16
- package/dist/react/components/show-more-toggle.d.ts.map +1 -1
- package/dist/react/components/show-more-toggle.js +0 -5
- package/dist/react/components/show-more-toggle.js.map +1 -1
- package/dist/react/components/spinner.d.ts +0 -14
- package/dist/react/components/spinner.d.ts.map +1 -1
- package/dist/react/components/spinner.js +0 -8
- package/dist/react/components/spinner.js.map +1 -1
- package/dist/react/components/switch.d.ts +0 -7
- package/dist/react/components/switch.d.ts.map +1 -1
- package/dist/react/components/switch.js +0 -2
- package/dist/react/components/switch.js.map +1 -1
- package/dist/react/components/table.d.ts +0 -10
- package/dist/react/components/table.d.ts.map +1 -1
- package/dist/react/components/table.js +0 -6
- package/dist/react/components/table.js.map +1 -1
- package/dist/react/components/textarea.d.ts +0 -11
- package/dist/react/components/textarea.d.ts.map +1 -1
- package/dist/react/components/textarea.js +1 -3
- package/dist/react/components/textarea.js.map +1 -1
- package/dist/react/components/toast.d.ts +0 -4
- package/dist/react/components/toast.d.ts.map +1 -1
- package/dist/react/components/toast.js +3 -24
- package/dist/react/components/toast.js.map +1 -1
- package/dist/react/components/toaster.d.ts.map +1 -1
- package/dist/react/components/toaster.js.map +1 -1
- package/dist/react/hooks/use-async-action.d.ts +1 -21
- package/dist/react/hooks/use-async-action.d.ts.map +1 -1
- package/dist/react/hooks/use-async-action.js +1 -9
- package/dist/react/hooks/use-async-action.js.map +1 -1
- package/dist/react/hooks/use-cursor-page.d.ts +0 -62
- package/dist/react/hooks/use-cursor-page.d.ts.map +1 -1
- package/dist/react/hooks/use-cursor-page.js +1 -37
- package/dist/react/hooks/use-cursor-page.js.map +1 -1
- package/dist/react/hooks/use-paged-list.d.ts +0 -43
- package/dist/react/hooks/use-paged-list.d.ts.map +1 -1
- package/dist/react/hooks/use-paged-list.js +0 -15
- package/dist/react/hooks/use-paged-list.js.map +1 -1
- package/dist/react/hooks/use-return-scroll.d.ts +0 -9
- package/dist/react/hooks/use-return-scroll.d.ts.map +1 -1
- package/dist/react/hooks/use-return-scroll.js +2 -34
- package/dist/react/hooks/use-return-scroll.js.map +1 -1
- package/dist/react/hooks/use-toast.d.ts +0 -8
- package/dist/react/hooks/use-toast.d.ts.map +1 -1
- package/dist/react/hooks/use-toast.js +1 -4
- package/dist/react/hooks/use-toast.js.map +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +0 -6
- package/dist/react/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/browser/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC","sourcesContent":["export { createReloadRecoveryWatch } from './reload-recovery-watch.js';\nexport type { ReloadRecoveryTarget, ReloadRecoveryWatch } from './reload-recovery-watch.js';\n"]}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { type ReloadRecoveryKind } from '../lib/reload-recovery.js';
|
|
2
|
-
/** What the watch listens on: the page's window. */
|
|
3
2
|
export type ReloadRecoveryTarget = Pick<Window, 'addEventListener' | 'removeEventListener'>;
|
|
4
3
|
export interface ReloadRecoveryWatch {
|
|
5
|
-
/** The first failure only a reload repairs since the watch started, or `null` while there is none. */
|
|
6
4
|
current: () => ReloadRecoveryKind | null;
|
|
7
|
-
/** Calls `listener` once, when the first failure is recorded. Answers the unsubscribe. */
|
|
8
5
|
subscribe: (listener: () => void) => () => void;
|
|
9
|
-
/** Stops listening; a failure already recorded stays. */
|
|
10
6
|
stop: () => void;
|
|
11
7
|
}
|
|
12
8
|
export declare function createReloadRecoveryWatch(target?: ReloadRecoveryTarget): ReloadRecoveryWatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reload-recovery-watch.d.ts","sourceRoot":"","sources":["../../src/browser/reload-recovery-watch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reload-recovery-watch.d.ts","sourceRoot":"","sources":["../../src/browser/reload-recovery-watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE1F,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,EAAE,kBAAkB,GAAG,qBAAqB,CAAC,CAAC;AAE5F,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,kBAAkB,GAAG,IAAI,CAAC;IACzC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,GAAE,oBAA6B,GACpC,mBAAmB,CA4BrB"}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
// Watches the page for the first failure only a reload repairs. Started once at the app's client
|
|
2
|
-
// entry, before React mounts, so a failure raised during startup is recorded for the notice to show
|
|
3
|
-
// once it mounts. It only listens: it never calls `preventDefault`, so the app's monitoring still
|
|
4
|
-
// captures every event once, and it never reloads the page.
|
|
5
1
|
import { reloadRecoveryKindOf } from '../lib/reload-recovery.js';
|
|
6
2
|
export function createReloadRecoveryWatch(target = window) {
|
|
7
3
|
let recorded = null;
|
|
8
4
|
const listeners = new Set();
|
|
9
5
|
const record = (kind) => {
|
|
10
|
-
// The first failure stands: a repeat of it, or the other one after it, changes nothing.
|
|
11
6
|
if (kind === null || recorded !== null)
|
|
12
7
|
return;
|
|
13
8
|
recorded = kind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reload-recovery-watch.js","sourceRoot":"","sources":["../../src/browser/reload-recovery-watch.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"reload-recovery-watch.js","sourceRoot":"","sources":["../../src/browser/reload-recovery-watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAA2B,MAAM,2BAA2B,CAAC;AAU1F,MAAM,UAAU,yBAAyB,CACvC,SAA+B,MAAM;IAErC,IAAI,QAAQ,GAA8B,IAAI,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAExC,MAAM,MAAM,GAAG,CAAC,IAA+B,EAAE,EAAE;QACjD,IAAI,IAAI,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO;QAC/C,QAAQ,GAAG,IAAI,CAAC;QAChB,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,SAAS,CAAC;YAAE,QAAQ,EAAE,CAAC;IACpD,CAAC,CAAC;IACF,kGAAkG;IAClG,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAE,EAAE,CACpC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,oBAAoB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,WAAW,GAAG,CAAC,KAA4B,EAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjG,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;IAE3D,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ;QACvB,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;YACtB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { reloadRecoveryKindOf, type ReloadRecoveryKind } from '../lib/reload-recovery.js';\n\nexport type ReloadRecoveryTarget = Pick<Window, 'addEventListener' | 'removeEventListener'>;\n\nexport interface ReloadRecoveryWatch {\n current: () => ReloadRecoveryKind | null;\n subscribe: (listener: () => void) => () => void;\n stop: () => void;\n}\n\nexport function createReloadRecoveryWatch(\n target: ReloadRecoveryTarget = window,\n): ReloadRecoveryWatch {\n let recorded: ReloadRecoveryKind | null = null;\n const listeners = new Set<() => void>();\n\n const record = (kind: ReloadRecoveryKind | null) => {\n if (kind === null || recorded !== null) return;\n recorded = kind;\n for (const listener of [...listeners]) listener();\n };\n // An error event's `error` is the thrown value; a cross-origin script's carries only the message.\n const onError = (event: ErrorEvent) =>\n record(reloadRecoveryKindOf(event.error) ?? reloadRecoveryKindOf({ message: event.message }));\n const onRejection = (event: PromiseRejectionEvent) => record(reloadRecoveryKindOf(event.reason));\n\n target.addEventListener('error', onError);\n target.addEventListener('unhandledrejection', onRejection);\n\n return {\n current: () => recorded,\n subscribe: (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n stop: () => {\n target.removeEventListener('error', onError);\n target.removeEventListener('unhandledrejection', onRejection);\n },\n };\n}\n"]}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './lib/utils.js';\nexport * from './lib/format-numbers.js';\nexport * from './lib/reload-recovery.js';\n"]}
|
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compact number formatter:
|
|
3
|
-
* < 10,000 → "1234"
|
|
4
|
-
* 10,000 ≤ n < 1,000,000 → "12.3k" (trailing ".0" stripped)
|
|
5
|
-
* ≥ 1,000,000 → "1.2M" (trailing ".0" stripped)
|
|
6
|
-
*/
|
|
7
1
|
export declare function formatLargeNumber(num: number): string;
|
|
8
2
|
//# sourceMappingURL=format-numbers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-numbers.d.ts","sourceRoot":"","sources":["../../src/lib/format-numbers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"format-numbers.d.ts","sourceRoot":"","sources":["../../src/lib/format-numbers.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUrD"}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compact number formatter:
|
|
3
|
-
* < 10,000 → "1234"
|
|
4
|
-
* 10,000 ≤ n < 1,000,000 → "12.3k" (trailing ".0" stripped)
|
|
5
|
-
* ≥ 1,000,000 → "1.2M" (trailing ".0" stripped)
|
|
6
|
-
*/
|
|
7
1
|
export function formatLargeNumber(num) {
|
|
8
2
|
if (num >= 1_000_000) {
|
|
9
3
|
const formatted = (num / 1_000_000).toFixed(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-numbers.js","sourceRoot":"","sources":["../../src/lib/format-numbers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"format-numbers.js","sourceRoot":"","sources":["../../src/lib/format-numbers.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC;IAC/E,CAAC;IACD,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC;IAC/E,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC","sourcesContent":["export function formatLargeNumber(num: number): string {\n if (num >= 1_000_000) {\n const formatted = (num / 1_000_000).toFixed(1);\n return (formatted.endsWith('.0') ? formatted.slice(0, -2) : formatted) + 'M';\n }\n if (num >= 10_000) {\n const formatted = (num / 1000).toFixed(1);\n return (formatted.endsWith('.0') ? formatted.slice(0, -2) : formatted) + 'k';\n }\n return num.toString();\n}\n"]}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
/** Each failure only a reload repairs. */
|
|
2
1
|
export declare const RELOAD_RECOVERY_KINDS: readonly ["storageDisconnect", "staleChunk"];
|
|
3
2
|
export type ReloadRecoveryKind = (typeof RELOAD_RECOVERY_KINDS)[number];
|
|
4
|
-
/**
|
|
5
|
-
* WebKit dropping a page's IndexedDB connection when it reclaims a backgrounded tab: an
|
|
6
|
-
* `UnknownError` whose message says the connection to the Indexed Database server was lost. Every
|
|
7
|
-
* storage call after it fails until the page reloads. No other `UnknownError`, and no quota, blocked
|
|
8
|
-
* storage, or network failure, is this one.
|
|
9
|
-
*/
|
|
3
|
+
/** WebKit drops a backgrounded tab's IndexedDB connection; every storage call after it fails until the page reloads. */
|
|
10
4
|
export declare function isStorageDisconnectError(reason: unknown): boolean;
|
|
11
|
-
/** A code chunk the deployed build no longer serves: a `ChunkLoadError`, or "Failed to load chunk". */
|
|
12
5
|
export declare function isStaleChunkError(reason: unknown): boolean;
|
|
13
|
-
/** Which failure only a reload repairs `reason` is, or `null` for any other. */
|
|
14
6
|
export declare function reloadRecoveryKindOf(reason: unknown): ReloadRecoveryKind | null;
|
|
15
7
|
//# sourceMappingURL=reload-recovery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reload-recovery.d.ts","sourceRoot":"","sources":["../../src/lib/reload-recovery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reload-recovery.d.ts","sourceRoot":"","sources":["../../src/lib/reload-recovery.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,8CAA+C,CAAC;AAClF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAaxE,wHAAwH;AACxH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKjE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAK1D;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,kBAAkB,GAAG,IAAI,CAI/E"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// The failures that leave a page only a reload repairs, recognised narrowly. Server-safe: pure
|
|
2
|
-
// predicates over whatever an `error` or `unhandledrejection` event carries.
|
|
3
|
-
/** Each failure only a reload repairs. */
|
|
4
1
|
export const RELOAD_RECOVERY_KINDS = ['storageDisconnect', 'staleChunk'];
|
|
5
2
|
const STORAGE_DISCONNECT_NAME = 'UnknownError';
|
|
6
3
|
const STORAGE_DISCONNECT_MESSAGE = 'Connection to Indexed Database server lost';
|
|
@@ -12,22 +9,15 @@ function fieldOf(reason, field) {
|
|
|
12
9
|
const value = reason[field];
|
|
13
10
|
return typeof value === 'string' ? value : null;
|
|
14
11
|
}
|
|
15
|
-
/**
|
|
16
|
-
* WebKit dropping a page's IndexedDB connection when it reclaims a backgrounded tab: an
|
|
17
|
-
* `UnknownError` whose message says the connection to the Indexed Database server was lost. Every
|
|
18
|
-
* storage call after it fails until the page reloads. No other `UnknownError`, and no quota, blocked
|
|
19
|
-
* storage, or network failure, is this one.
|
|
20
|
-
*/
|
|
12
|
+
/** WebKit drops a backgrounded tab's IndexedDB connection; every storage call after it fails until the page reloads. */
|
|
21
13
|
export function isStorageDisconnectError(reason) {
|
|
22
14
|
return (fieldOf(reason, 'name') === STORAGE_DISCONNECT_NAME &&
|
|
23
15
|
(fieldOf(reason, 'message')?.includes(STORAGE_DISCONNECT_MESSAGE) ?? false));
|
|
24
16
|
}
|
|
25
|
-
/** A code chunk the deployed build no longer serves: a `ChunkLoadError`, or "Failed to load chunk". */
|
|
26
17
|
export function isStaleChunkError(reason) {
|
|
27
18
|
return (fieldOf(reason, 'name') === STALE_CHUNK_NAME ||
|
|
28
19
|
(fieldOf(reason, 'message')?.includes(STALE_CHUNK_MESSAGE) ?? false));
|
|
29
20
|
}
|
|
30
|
-
/** Which failure only a reload repairs `reason` is, or `null` for any other. */
|
|
31
21
|
export function reloadRecoveryKindOf(reason) {
|
|
32
22
|
if (isStorageDisconnectError(reason))
|
|
33
23
|
return 'storageDisconnect';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reload-recovery.js","sourceRoot":"","sources":["../../src/lib/reload-recovery.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reload-recovery.js","sourceRoot":"","sources":["../../src/lib/reload-recovery.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAU,CAAC;AAGlF,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAC/C,MAAM,0BAA0B,GAAG,4CAA4C,CAAC;AAChF,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAC1C,MAAM,mBAAmB,GAAG,sBAAsB,CAAC;AAEnD,SAAS,OAAO,CAAC,MAAe,EAAE,KAAyB;IACzD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/D,MAAM,KAAK,GAAI,MAAkC,CAAC,KAAK,CAAC,CAAC;IACzD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,wBAAwB,CAAC,MAAe;IACtD,OAAO,CACL,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,uBAAuB;QACnD,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,0BAA0B,CAAC,IAAI,KAAK,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,OAAO,CACL,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,gBAAgB;QAC5C,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,IAAI,KAAK,CAAC,CACrE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,IAAI,wBAAwB,CAAC,MAAM,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACjE,IAAI,iBAAiB,CAAC,MAAM,CAAC;QAAE,OAAO,YAAY,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["export const RELOAD_RECOVERY_KINDS = ['storageDisconnect', 'staleChunk'] as const;\nexport type ReloadRecoveryKind = (typeof RELOAD_RECOVERY_KINDS)[number];\n\nconst STORAGE_DISCONNECT_NAME = 'UnknownError';\nconst STORAGE_DISCONNECT_MESSAGE = 'Connection to Indexed Database server lost';\nconst STALE_CHUNK_NAME = 'ChunkLoadError';\nconst STALE_CHUNK_MESSAGE = 'Failed to load chunk';\n\nfunction fieldOf(reason: unknown, field: 'name' | 'message'): string | null {\n if (typeof reason !== 'object' || reason === null) return null;\n const value = (reason as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : null;\n}\n\n/** WebKit drops a backgrounded tab's IndexedDB connection; every storage call after it fails until the page reloads. */\nexport function isStorageDisconnectError(reason: unknown): boolean {\n return (\n fieldOf(reason, 'name') === STORAGE_DISCONNECT_NAME &&\n (fieldOf(reason, 'message')?.includes(STORAGE_DISCONNECT_MESSAGE) ?? false)\n );\n}\n\nexport function isStaleChunkError(reason: unknown): boolean {\n return (\n fieldOf(reason, 'name') === STALE_CHUNK_NAME ||\n (fieldOf(reason, 'message')?.includes(STALE_CHUNK_MESSAGE) ?? false)\n );\n}\n\nexport function reloadRecoveryKindOf(reason: unknown): ReloadRecoveryKind | null {\n if (isStorageDisconnectError(reason)) return 'storageDisconnect';\n if (isStaleChunkError(reason)) return 'staleChunk';\n return null;\n}\n"]}
|
package/dist/lib/utils.d.ts
CHANGED
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
package/dist/lib/utils.js
CHANGED
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/react/components/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAC;AAKhE,QAAA,MAAM,SAAS,8JAA0B,CAAC;AAE1C,QAAA,MAAM,aAAa,iKAKjB,CAAC;AAGH,QAAA,MAAM,gBAAgB,0KAiBpB,CAAC;AAGH,QAAA,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/react/components/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAC;AAKhE,QAAA,MAAM,SAAS,8JAA0B,CAAC;AAE1C,QAAA,MAAM,aAAa,iKAKjB,CAAC;AAGH,QAAA,MAAM,gBAAgB,0KAiBpB,CAAC;AAGH,QAAA,MAAM,gBAAgB,oKAapB,CAAC;AAGH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../src/react/components/accordion.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAExC,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC;AAE1C,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAGpC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,KAAC,kBAAkB,CAAC,IAAI,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KAAM,KAAK,GAAI,CAC3E,CAAC,CAAC;AACH,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC;AAE5C,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAC5C,KAAC,kBAAkB,CAAC,MAAM,IAAC,SAAS,EAAC,MAAM,YACzC,MAAC,kBAAkB,CAAC,OAAO,IACzB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,+GAA+G,EAC/G,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,WAAW,IAAC,SAAS,EAAC,+FAA+F,GAAG,IAC9F,GACH,CAC7B,CAAC,CAAC;AACH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC;AAEtE,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../src/react/components/accordion.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAExC,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC;AAE1C,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAGpC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,KAAC,kBAAkB,CAAC,IAAI,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KAAM,KAAK,GAAI,CAC3E,CAAC,CAAC;AACH,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC;AAE5C,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAC5C,KAAC,kBAAkB,CAAC,MAAM,IAAC,SAAS,EAAC,MAAM,YACzC,MAAC,kBAAkB,CAAC,OAAO,IACzB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,+GAA+G,EAC/G,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,WAAW,IAAC,SAAS,EAAC,+FAA+F,GAAG,IAC9F,GACH,CAC7B,CAAC,CAAC;AACH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC;AAEtE,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAG5C,KAAC,kBAAkB,CAAC,OAAO,IACzB,GAAG,EAAE,GAAG,EACR,SAAS,EAAC,yGAAyG,KAC/G,KAAK,YAET,cAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,YAAG,QAAQ,GAAO,GACjC,CAC9B,CAAC,CAAC;AACH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { ChevronDown } from 'lucide-react';\n\nimport { cn } from '../../lib/utils.js';\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item ref={ref} className={cn(className)} {...props} />\n));\nAccordionItem.displayName = 'AccordionItem';\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex flex-1 items-center justify-between py-4 font-medium hover:underline [&[data-state=open]>svg]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-[var(--motion-base)] ease-[var(--motion-ease)]\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n // `overflow-clip`, never `overflow-hidden`: a hidden box is still a scroll container, so a focus\n // mid-animation scrolls it and the content snaps back when the animation ends.\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-clip text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn('pb-4 pt-0', className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n"]}
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
/** What the app's link element must carry to be a row's link target. */
|
|
3
2
|
export interface ActionRowLinkTargetProps {
|
|
4
3
|
className: string;
|
|
5
4
|
'aria-labelledby': string;
|
|
6
5
|
}
|
|
7
6
|
interface ActionRowCommonProps {
|
|
8
|
-
/** Layout of the content (padding, flex, borders). */
|
|
9
7
|
className?: string;
|
|
10
8
|
children: React.ReactNode;
|
|
11
9
|
}
|
|
12
10
|
export interface ActionRowButtonProps extends ActionRowCommonProps {
|
|
13
11
|
onClick: () => void;
|
|
14
12
|
disabled?: boolean;
|
|
15
|
-
/** The row's own action is in flight. */
|
|
16
13
|
busy?: boolean;
|
|
17
14
|
renderLink?: never;
|
|
18
15
|
}
|
|
19
16
|
export interface ActionRowLinkProps extends ActionRowCommonProps {
|
|
20
|
-
/**
|
|
21
|
-
* Renders the row's target as the app's own link element (its guarded in-app link), spreading
|
|
22
|
-
* the given props onto it. The link takes no children: the row's content names it.
|
|
23
|
-
*/
|
|
24
17
|
renderLink: (target: ActionRowLinkTargetProps) => React.ReactElement;
|
|
25
18
|
onClick?: never;
|
|
26
19
|
disabled?: never;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-row.d.ts","sourceRoot":"","sources":["../../../src/react/components/action-row.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action-row.d.ts","sourceRoot":"","sources":["../../../src/react/components/action-row.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,UAAU,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,KAAK,CAAC,YAAY,CAAC;IACrE,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,IAAI,CAAC,EAAE,KAAK,CAAC;CACd;AAED,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;AAEvE,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAqB9C"}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
// A
|
|
4
|
-
// never be a single <button> or <a>: a control inside it would be nested in the row's target. So the
|
|
5
|
-
// target is a sibling laid over the row, named by the row's content, and the content sits above it
|
|
6
|
-
// letting clicks through everywhere but on its own controls. The target comes first in tab order,
|
|
7
|
-
// then any control inside the row.
|
|
3
|
+
// A row is never one <button> or <a>: a control inside it would be nested in the row's target.
|
|
8
4
|
import * as React from 'react';
|
|
9
5
|
import { cn } from '../../lib/utils.js';
|
|
10
6
|
const TARGET_CLASS = 'peer absolute inset-0 w-full cursor-pointer transition-colors duration-[var(--motion-fast)] ease-[var(--motion-ease)] group-hover/action-row:bg-accent disabled:cursor-default disabled:group-hover/action-row:bg-transparent';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-row.js","sourceRoot":"","sources":["../../../src/react/components/action-row.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb
|
|
1
|
+
{"version":3,"file":"action-row.js","sourceRoot":"","sources":["../../../src/react/components/action-row.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,+FAA+F;AAE/F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAExC,MAAM,YAAY,GAChB,+NAA+N,CAAC;AAElO,MAAM,aAAa,GACjB,iIAAiI,CAAC;AA4BpI,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAChC,OAAO,CACL,eAAK,SAAS,EAAC,yCAAyC,aACrD,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAClB,KAAK,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,CAC5E,CAAC,CAAC,CAAC,CACF,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,YAAY,EACvB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,eACtB,KAAK,CAAC,IAAI,IAAI,SAAS,qBACjB,SAAS,GAC1B,CACH,EACD,cAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,YAC9D,KAAK,CAAC,QAAQ,GACX,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\n// A row is never one <button> or <a>: a control inside it would be nested in the row's target.\n\nimport * as React from 'react';\nimport { cn } from '../../lib/utils.js';\n\nconst TARGET_CLASS =\n 'peer absolute inset-0 w-full cursor-pointer transition-colors duration-[var(--motion-fast)] ease-[var(--motion-ease)] group-hover/action-row:bg-accent disabled:cursor-default disabled:group-hover/action-row:bg-transparent';\n\nconst CONTENT_CLASS =\n 'relative pointer-events-none peer-disabled:opacity-70 [&_:is(a,button,input,select,textarea,[role=button])]:pointer-events-auto';\n\nexport interface ActionRowLinkTargetProps {\n className: string;\n 'aria-labelledby': string;\n}\n\ninterface ActionRowCommonProps {\n className?: string;\n children: React.ReactNode;\n}\n\nexport interface ActionRowButtonProps extends ActionRowCommonProps {\n onClick: () => void;\n disabled?: boolean;\n busy?: boolean;\n renderLink?: never;\n}\n\nexport interface ActionRowLinkProps extends ActionRowCommonProps {\n renderLink: (target: ActionRowLinkTargetProps) => React.ReactElement;\n onClick?: never;\n disabled?: never;\n busy?: never;\n}\n\nexport type ActionRowProps = ActionRowButtonProps | ActionRowLinkProps;\n\nexport function ActionRow(props: ActionRowProps) {\n const contentId = React.useId();\n return (\n <div className=\"ui-action-row group/action-row relative\">\n {props.renderLink ? (\n props.renderLink({ className: TARGET_CLASS, 'aria-labelledby': contentId })\n ) : (\n <button\n type=\"button\"\n className={TARGET_CLASS}\n onClick={props.onClick}\n disabled={props.disabled ?? false}\n aria-busy={props.busy || undefined}\n aria-labelledby={contentId}\n />\n )}\n <div id={contentId} className={cn(CONTENT_CLASS, props.className)}>\n {props.children}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -6,17 +6,7 @@ declare const buttonVariants: (props?: ({
|
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
8
|
asChild?: boolean;
|
|
9
|
-
/**
|
|
10
|
-
* Async work this button started is in flight. The button ignores activation — a
|
|
11
|
-
* click, a key press, a form's implicit submit — sets `aria-disabled` and
|
|
12
|
-
* `aria-busy`, and shows the canonical spinner: an icon button (`size="icon"`)
|
|
13
|
-
* swaps its icon for it; any other button shows it in place of its `icon`. It is
|
|
14
|
-
* never natively disabled while pending — a `disabled` passed alongside `pending`
|
|
15
|
-
* applies once pending ends — so the button the user just pressed keeps focus
|
|
16
|
-
* (FRONTEND-203).
|
|
17
|
-
*/
|
|
18
9
|
pending?: boolean;
|
|
19
|
-
/** Leading icon, rendered before the label. While `pending`, the spinner takes its place. */
|
|
20
10
|
icon?: React.ReactNode;
|
|
21
11
|
}
|
|
22
12
|
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/react/components/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/react/components/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAOlE,QAAA,MAAM,cAAc;;;8EAgCnB,CAAC;AAEF,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,YAAY,CAAC,OAAO,cAAc,CAAC;IAC1F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB;AAED,QAAA,MAAM,MAAM,uFAgEX,CAAC;AAIF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -6,8 +6,7 @@ import { cva } from 'class-variance-authority';
|
|
|
6
6
|
import { cn } from '../../lib/utils.js';
|
|
7
7
|
import { Spinner } from './spinner.js';
|
|
8
8
|
import { blockActivationKey, blockEvent } from './pending-guard.js';
|
|
9
|
-
// `ui-button` is the stable
|
|
10
|
-
// effect), so it never has to match this component's private utility string.
|
|
9
|
+
// `ui-button` is the stable class an app's stylesheet keys every button rule on.
|
|
11
10
|
const buttonVariants = cva('ui-button inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-bold ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50', {
|
|
12
11
|
variants: {
|
|
13
12
|
variant: {
|
|
@@ -40,9 +39,6 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, pe
|
|
|
40
39
|
'aria-busy': true,
|
|
41
40
|
'aria-disabled': true,
|
|
42
41
|
'data-pending': '',
|
|
43
|
-
// Stopped before any handler runs — the caller's, an `asChild` child's own, or a Radix
|
|
44
|
-
// trigger's — so a click submits nothing, a link goes nowhere, and neither a pointer
|
|
45
|
-
// press nor an activation key opens what the button triggers.
|
|
46
42
|
onClickCapture: blockEvent,
|
|
47
43
|
onPointerDownCapture: blockEvent,
|
|
48
44
|
onKeyDownCapture: blockActivationKey,
|
|
@@ -54,8 +50,7 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, pe
|
|
|
54
50
|
const spinner = _jsx(Spinner, { size: size === 'lg' ? 'sm' : 'xs' });
|
|
55
51
|
const leading = pending ? spinner : icon;
|
|
56
52
|
if (asChild) {
|
|
57
|
-
// Slot finds the Slottable among its
|
|
58
|
-
// Slottable must be siblings here — never wrapped in a fragment.
|
|
53
|
+
// Radix Slot finds the Slottable among its direct children, so these are siblings, never a fragment.
|
|
59
54
|
return leading ? (_jsxs(Slot, { ref: ref, ...shared, children: [leading, _jsx(Slottable, { children: children })] })) : (_jsx(Slot, { ref: ref, ...shared, children: children }));
|
|
60
55
|
}
|
|
61
56
|
return (_jsx("button", { ref: ref, ...shared, children: size === 'icon' ? (pending ? (spinner) : (children)) : (_jsxs(_Fragment, { children: [leading, children] })) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/react/components/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEpE,
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/react/components/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEpE,iFAAiF;AACjF,MAAM,cAAc,GAAG,GAAG,CACxB,mWAAmW,EACnW;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,wHAAwH;YAC1H,WAAW,EACT,qHAAqH;YACvH,OAAO,EACL,sKAAsK;YACxK,OAAO,EACL,mGAAmG;YACrG,SAAS,EACP,qFAAqF;YACvF,KAAK,EAAE,8CAA8C;YACrD,IAAI,EAAE,iDAAiD;YACvD,QAAQ,EACN,yKAAyK;SAC5K;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,gBAAgB;YACzB,EAAE,EAAE,qBAAqB;YACzB,EAAE,EAAE,sBAAsB;YAC1B,IAAI,EAAE,SAAS;SAChB;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAC;AASF,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAC7B,CACE,EACE,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,OAAO,GAAG,KAAK,EACf,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,MAAM,GAAG;QACb,GAAG,KAAK;QACR,GAAG,CAAC,OAAO;YACT,CAAC,CAAC;gBACE,WAAW,EAAE,IAAI;gBACjB,eAAe,EAAE,IAAI;gBACrB,cAAc,EAAE,EAAE;gBAClB,cAAc,EAAE,UAAU;gBAC1B,oBAAoB,EAAE,UAAU;gBAChC,gBAAgB,EAAE,kBAAkB;aACrC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,QAAQ,EAAE,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS;QAC7C,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;KAC5D,CAAC;IACF,MAAM,OAAO,GAAG,KAAC,OAAO,IAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAI,CAAC;IAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAEzC,IAAI,OAAO,EAAE,CAAC;QACZ,qGAAqG;QACrG,OAAO,OAAO,CAAC,CAAC,CAAC,CACf,MAAC,IAAI,IAAC,GAAG,EAAE,GAAG,KAAM,MAAM,aACvB,OAAO,EACR,KAAC,SAAS,cAAE,QAAQ,GAAa,IAC5B,CACR,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,IAAC,GAAG,EAAE,GAAG,KAAM,MAAM,YACvB,QAAQ,GACJ,CACR,CAAC;IACJ,CAAC;IAED,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,KAAM,MAAM,YACzB,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CACjB,OAAO,CAAC,CAAC,CAAC,CACR,OAAO,CACR,CAAC,CAAC,CAAC,CACF,QAAQ,CACT,CACF,CAAC,CAAC,CAAC,CACF,8BACG,OAAO,EACP,QAAQ,IACR,CACJ,GACM,CACV,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Slot, Slottable } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../lib/utils.js';\nimport { Spinner } from './spinner.js';\nimport { blockActivationKey, blockEvent } from './pending-guard.js';\n\n// `ui-button` is the stable class an app's stylesheet keys every button rule on.\nconst buttonVariants = cva(\n 'ui-button inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-bold ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50',\n {\n variants: {\n variant: {\n default:\n 'button-default bg-primary text-primary-foreground hover:bg-primary/90 border-2 border-[hsl(var(--brand-primary-deep))]',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90 border-2 border-[hsl(var(--destructive-border))]',\n success:\n 'bg-[color:var(--button-success)] text-[hsl(var(--success-foreground))] hover:bg-[color:var(--button-success)]/90 border-2 border-[hsl(var(--status-success-border))]',\n outline:\n 'border-2 border-border bg-background hover:bg-accent hover:text-accent-foreground text-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-2 border-border',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n inverted:\n 'bg-[hsl(var(--inverted-background))] text-[hsl(var(--inverted-foreground))] hover:bg-[hsl(var(--inverted-background))]/90 border-2 border-[hsl(var(--inverted-border))]',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n pending?: boolean;\n icon?: React.ReactNode;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n asChild = false,\n pending = false,\n icon,\n disabled,\n children,\n ...props\n },\n ref,\n ) => {\n const shared = {\n ...props,\n ...(pending\n ? {\n 'aria-busy': true,\n 'aria-disabled': true,\n 'data-pending': '',\n onClickCapture: blockEvent,\n onPointerDownCapture: blockEvent,\n onKeyDownCapture: blockActivationKey,\n }\n : {}),\n disabled: (disabled && !pending) || undefined,\n className: cn(buttonVariants({ variant, size, className })),\n };\n const spinner = <Spinner size={size === 'lg' ? 'sm' : 'xs'} />;\n const leading = pending ? spinner : icon;\n\n if (asChild) {\n // Radix Slot finds the Slottable among its direct children, so these are siblings, never a fragment.\n return leading ? (\n <Slot ref={ref} {...shared}>\n {leading}\n <Slottable>{children}</Slottable>\n </Slot>\n ) : (\n <Slot ref={ref} {...shared}>\n {children}\n </Slot>\n );\n }\n\n return (\n <button ref={ref} {...shared}>\n {size === 'icon' ? (\n pending ? (\n spinner\n ) : (\n children\n )\n ) : (\n <>\n {leading}\n {children}\n </>\n )}\n </button>\n );\n },\n);\n\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n"]}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { type DeclaredInputFormat } from '@ttt-productions/input-format-core';
|
|
2
|
-
/**
|
|
3
|
-
* The inline reason field. The caller OWNS the reason value/onChange (draft state lives at the call
|
|
4
|
-
* site) and the field's declaration — this component declares no business numbers and no copy.
|
|
5
|
-
* Confirm stays disabled until the value passes the declaration's check; `min: 0` makes the reason
|
|
6
|
-
* optional.
|
|
7
|
-
*/
|
|
8
2
|
export interface ConsequenceDialogReason {
|
|
9
3
|
inputFormat: DeclaredInputFormat;
|
|
10
4
|
placeholder?: string;
|
|
@@ -12,69 +6,28 @@ export interface ConsequenceDialogReason {
|
|
|
12
6
|
value: string;
|
|
13
7
|
onChange: (value: string) => void;
|
|
14
8
|
rows?: number;
|
|
15
|
-
/**
|
|
16
|
-
* A line rendered directly under the reason box, such as why its current text is refused. It is
|
|
17
|
-
* called with the id the box names in its `aria-describedby`, and the element it renders carries
|
|
18
|
-
* that id. The caller owns the words; this component adds none.
|
|
19
|
-
*/
|
|
20
9
|
hint?: (id: string) => React.ReactNode;
|
|
21
10
|
}
|
|
22
|
-
/**
|
|
23
|
-
* The exact-match typed-confirmation gate. `phrase` is business copy owned by the CALLER; the
|
|
24
|
-
* component only compares the typed value against it.
|
|
25
|
-
*/
|
|
26
11
|
export interface ConsequenceDialogTypedConfirmation {
|
|
27
12
|
phrase: string;
|
|
28
13
|
label?: React.ReactNode;
|
|
29
14
|
}
|
|
30
15
|
export interface ConsequenceDialogProps {
|
|
31
|
-
/** Uncontrolled open model: the element that opens the dialog (rendered `asChild`). */
|
|
32
16
|
trigger?: React.ReactNode;
|
|
33
|
-
/** Controlled open model. Provide with `onOpenChange`. */
|
|
34
17
|
open?: boolean;
|
|
35
18
|
onOpenChange?: (open: boolean) => void;
|
|
36
|
-
/** Heading — a string or node so callers can interpolate amounts / names. */
|
|
37
19
|
title: React.ReactNode;
|
|
38
|
-
/** SLOT 1 — what happens right now (e.g. "initiates a Stripe refund of $X now"). */
|
|
39
20
|
immediateEffect?: React.ReactNode;
|
|
40
|
-
/** SLOT 2 — what settles later, out of band (webhook / worker / async confirmation). */
|
|
41
21
|
delayedEffect?: React.ReactNode;
|
|
42
|
-
/** SLOT 3 — whether/how this can be undone or superseded. */
|
|
43
22
|
reversibility?: React.ReactNode;
|
|
44
|
-
/** Inline reason field. Optional. */
|
|
45
23
|
reason?: ConsequenceDialogReason;
|
|
46
|
-
/** Exact-phrase typed-confirmation gate. Optional. */
|
|
47
24
|
typedConfirmation?: ConsequenceDialogTypedConfirmation;
|
|
48
25
|
confirmLabel: React.ReactNode;
|
|
49
26
|
cancelLabel?: React.ReactNode;
|
|
50
|
-
/** `true` styles the confirm button with `bg-destructive`. */
|
|
51
27
|
destructive?: boolean;
|
|
52
|
-
/**
|
|
53
|
-
* Runs on confirm. May be async — while it is pending the dialog STAYS OPEN: the confirm button
|
|
54
|
-
* is `aria-disabled`, keeps focus, ignores further presses, and shows its pending spinner, and
|
|
55
|
-
* only Cancel is natively disabled. Closes on resolve. If it rejects the dialog
|
|
56
|
-
* stays open so the caller's own surface (error toast, TOTP step-up) can show and the operator can
|
|
57
|
-
* retry or cancel. This component takes no Sentry/monitoring dependency — every error path
|
|
58
|
-
* belongs to the caller's `onConfirm`.
|
|
59
|
-
*/
|
|
60
28
|
onConfirm: () => void | Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* Runs as the dialog closes, before Radix returns focus to the control that opened it. A confirmed
|
|
63
|
-
* action that removes that control moves focus to its own destination here and calls
|
|
64
|
-
* `event.preventDefault()`, so the restore does not pull focus back onto a control about to go.
|
|
65
|
-
*/
|
|
66
29
|
onCloseAutoFocus?: (event: Event) => void;
|
|
67
30
|
}
|
|
68
|
-
/**
|
|
69
|
-
* A reusable confirm-before-a-consequential-action dialog. Three optional, consistently-styled
|
|
70
|
-
* consequence slots (immediate / afterward / reversibility), an optional inline reason field,
|
|
71
|
-
* and an optional exact-phrase typed-confirmation gate. Composes the ui-core AlertDialog primitives
|
|
72
|
-
* (Radix) — it never re-implements them. Supports BOTH a `trigger` (uncontrolled) and `open` /
|
|
73
|
-
* `onOpenChange` (controlled).
|
|
74
|
-
*
|
|
75
|
-
* Pending model: the confirm button is a plain `Button` (NOT `AlertDialogAction`), so Radix does not
|
|
76
|
-
* auto-close on click; open state is managed here so the dialog stays open with a visible spinner
|
|
77
|
-
* until `onConfirm` resolves.
|
|
78
|
-
*/
|
|
31
|
+
/** The confirm is a plain `Button`, not `AlertDialogAction`, so Radix does not close the dialog on click. */
|
|
79
32
|
export declare function ConsequenceDialog({ trigger, open, onOpenChange, title, immediateEffect, delayedEffect, reversibility, reason, typedConfirmation, confirmLabel, cancelLabel, destructive, onConfirm, onCloseAutoFocus, }: ConsequenceDialogProps): import("react").JSX.Element;
|
|
80
33
|
//# sourceMappingURL=consequence-dialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consequence-dialog.d.ts","sourceRoot":"","sources":["../../../src/react/components/consequence-dialog.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,oCAAoC,CAAC;AAG5C
|
|
1
|
+
{"version":3,"file":"consequence-dialog.d.ts","sourceRoot":"","sources":["../../../src/react/components/consequence-dialog.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,oCAAoC,CAAC;AAG5C,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,mBAAmB,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,kCAAkC;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IAEvB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEhC,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,iBAAiB,CAAC,EAAE,kCAAkC,CAAC;IAEvD,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3C;AA2BD,6GAA6G;AAC7G,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,MAAM,EACN,iBAAiB,EACjB,YAAY,EACZ,WAAsB,EACtB,WAAmB,EACnB,SAAS,EACT,gBAAgB,GACjB,EAAE,sBAAsB,+BA6IxB"}
|
|
@@ -9,25 +9,11 @@ import { Label } from './label.js';
|
|
|
9
9
|
import { checkInputFormat, defineInputFormat, } from '@ttt-productions/input-format-core';
|
|
10
10
|
import { Zap, Clock, RotateCcw } from 'lucide-react';
|
|
11
11
|
const SLOT_ICON_CLASS = 'icon-xs mt-0.5 shrink-0 text-muted-foreground';
|
|
12
|
-
/**
|
|
13
|
-
* One consequence slot: the icon beside a block column whose label sits on its own line above
|
|
14
|
-
* the slot text. Every element is a block: the `stack-*` spacing is a vertical margin, which an
|
|
15
|
-
* inline element ignores.
|
|
16
|
-
*/
|
|
12
|
+
/** Every element is a block: the `stack-*` spacing is a vertical margin, which an inline element ignores. */
|
|
17
13
|
function ConsequenceRow({ icon: Icon, label, children, }) {
|
|
18
14
|
return (_jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Icon, { className: SLOT_ICON_CLASS, "aria-hidden": "true" }), _jsxs("div", { className: "stack-1 min-w-0", children: [_jsx("div", { className: "text-caption font-medium uppercase tracking-wide text-muted-foreground", children: label }), _jsx("div", { className: "text-small text-foreground", children: children })] })] }));
|
|
19
15
|
}
|
|
20
|
-
/**
|
|
21
|
-
* A reusable confirm-before-a-consequential-action dialog. Three optional, consistently-styled
|
|
22
|
-
* consequence slots (immediate / afterward / reversibility), an optional inline reason field,
|
|
23
|
-
* and an optional exact-phrase typed-confirmation gate. Composes the ui-core AlertDialog primitives
|
|
24
|
-
* (Radix) — it never re-implements them. Supports BOTH a `trigger` (uncontrolled) and `open` /
|
|
25
|
-
* `onOpenChange` (controlled).
|
|
26
|
-
*
|
|
27
|
-
* Pending model: the confirm button is a plain `Button` (NOT `AlertDialogAction`), so Radix does not
|
|
28
|
-
* auto-close on click; open state is managed here so the dialog stays open with a visible spinner
|
|
29
|
-
* until `onConfirm` resolves.
|
|
30
|
-
*/
|
|
16
|
+
/** The confirm is a plain `Button`, not `AlertDialogAction`, so Radix does not close the dialog on click. */
|
|
31
17
|
export function ConsequenceDialog({ trigger, open, onOpenChange, title, immediateEffect, delayedEffect, reversibility, reason, typedConfirmation, confirmLabel, cancelLabel = 'Cancel', destructive = false, onConfirm, onCloseAutoFocus, }) {
|
|
32
18
|
const isControlled = open !== undefined;
|
|
33
19
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
@@ -43,11 +29,10 @@ export function ConsequenceDialog({ trigger, open, onOpenChange, title, immediat
|
|
|
43
29
|
else
|
|
44
30
|
setInternalOpen(next);
|
|
45
31
|
}, [isControlled, onOpenChange]);
|
|
46
|
-
// Never allow an open-state change (Escape, cancel, controlled parent) to fight the pending action.
|
|
47
32
|
const handleOpenChange = useCallback((next) => {
|
|
48
33
|
if (pending)
|
|
49
34
|
return;
|
|
50
|
-
setTypedValue('');
|
|
35
|
+
setTypedValue('');
|
|
51
36
|
setOpenState(next);
|
|
52
37
|
}, [pending, setOpenState]);
|
|
53
38
|
const handleConfirm = useCallback(async () => {
|
|
@@ -60,8 +45,6 @@ export function ConsequenceDialog({ trigger, open, onOpenChange, title, immediat
|
|
|
60
45
|
setOpenState(false);
|
|
61
46
|
}
|
|
62
47
|
catch {
|
|
63
|
-
// Keep the dialog open — the caller's onConfirm surfaced the error (toast / step-up). The
|
|
64
|
-
// operator can retry or cancel. Never rethrow, never monitor here.
|
|
65
48
|
}
|
|
66
49
|
finally {
|
|
67
50
|
setPending(false);
|
|
@@ -69,7 +52,6 @@ export function ConsequenceDialog({ trigger, open, onOpenChange, title, immediat
|
|
|
69
52
|
}, [pending, onConfirm, setOpenState]);
|
|
70
53
|
const reasonOk = !reason || checkInputFormat(reason.value, reason.inputFormat).ok;
|
|
71
54
|
const typedOk = !typedConfirmation ? true : typedValue === typedConfirmation.phrase;
|
|
72
|
-
// The phrase is one line, and nothing longer than it can ever match it.
|
|
73
55
|
const phrase = typedConfirmation?.phrase ?? '';
|
|
74
56
|
const typedFormat = useMemo(() => phrase.length > 0
|
|
75
57
|
? defineInputFormat({ format: 'singleLine', min: 1, max: phrase.length })
|