@oxyhq/bloom 0.67.0 → 0.68.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/lib/commonjs/toast/Toaster.js +5 -0
- package/lib/commonjs/toast/Toaster.js.map +1 -1
- package/lib/commonjs/toast/use-single-outlet-guard.js +72 -0
- package/lib/commonjs/toast/use-single-outlet-guard.js.map +1 -0
- package/lib/module/toast/Toaster.js +5 -0
- package/lib/module/toast/Toaster.js.map +1 -1
- package/lib/module/toast/use-single-outlet-guard.js +65 -0
- package/lib/module/toast/use-single-outlet-guard.js.map +1 -0
- package/lib/typescript/commonjs/toast/Toaster.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/use-single-outlet-guard.d.ts +9 -0
- package/lib/typescript/commonjs/toast/use-single-outlet-guard.d.ts.map +1 -0
- package/lib/typescript/module/toast/Toaster.d.ts.map +1 -1
- package/lib/typescript/module/toast/use-single-outlet-guard.d.ts +9 -0
- package/lib/typescript/module/toast/use-single-outlet-guard.d.ts.map +1 -0
- package/package.json +347 -87
- package/src/__tests__/exports-map-contract.test.ts +112 -0
- package/src/__tests__/toast-single-outlet-guard.test.tsx +176 -0
- package/src/toast/Toaster.tsx +6 -0
- package/src/toast/use-single-outlet-guard.ts +72 -0
|
@@ -13,6 +13,7 @@ var _ToastHost = require("./ToastHost");
|
|
|
13
13
|
var _ToastRow = require("./ToastRow.js");
|
|
14
14
|
var _toastStore = require("./toast-store.js");
|
|
15
15
|
var _useAppState = require("./use-app-state.js");
|
|
16
|
+
var _useSingleOutletGuard = require("./use-single-outlet-guard.js");
|
|
16
17
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
17
18
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
18
19
|
/**
|
|
@@ -71,6 +72,10 @@ const Toaster = ({
|
|
|
71
72
|
style,
|
|
72
73
|
styles: styleOverrides
|
|
73
74
|
}) => {
|
|
75
|
+
// Before any early return, and independent of whether a toast is up: a second
|
|
76
|
+
// outlet duplicates every row from the moment it mounts, not from the first
|
|
77
|
+
// toast, so the warning must not wait for one.
|
|
78
|
+
(0, _useSingleOutletGuard.useSingleOutletGuard)();
|
|
74
79
|
const {
|
|
75
80
|
toasts,
|
|
76
81
|
shouldShowOverlay,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","_interopRequireWildcard","require","_constants","_context","_positionUtils","_Positioner","_ToastHost","_ToastRow","_toastStore","_useAppState","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ALL_POSITIONS","EMPTY_TOAST_OPTIONS","EMPTY_ICONS","EMPTY_ANIMATION","orderToastsFromPosition","toasts","position","slice","reverse","Toaster","ToasterOverlayWrapper","ToastWrapper","duration","toastDefaults","offset","visibleToasts","swipeToDismissDirection","closeButton","gap","theme","invert","richColors","enableStacking","autoWiggleOnUpdate","pauseWhenPageIsHidden","allowFontScaling","maxFontSizeMultiplier","toastOptions","icons","animation","unstyled","positionerStyle","style","styles","styleOverrides","shouldShowOverlay","toastHeights","isExpanded","useSyncExternalStore","toastStore","subscribe","getSnapshot","useEffect","setConfig","onBackground","useCallback","pauseAllTimers","onForeground","resumeAllTimers","useAppStateChange","stableValue","useMemo","dynamicValue","expand","collapse","toggleExpand","toastsByPosition","groups","Map","candidate","group","filter","toast","length","onDismiss","id","dismissToast","jsx","ToastHost","children","ToastContext","Provider","value","DynamicToastContext","Array","from","currentPosition","toastsForPosition","orderedToastIds","getOrderedToastIds","Positioner","map","index","row","ToastRow","numberOfToasts","ref","getToastRef","toastId","exports","displayName"],"sourceRoot":"../../../src","sources":["toast/Toaster.tsx"],"mappings":";;;;;;AAeA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AAEA,IAAAC,UAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AACA,IAAAG,cAAA,GAAAH,OAAA;AACA,IAAAI,WAAA,GAAAJ,OAAA;AACA,IAAAK,UAAA,GAAAL,OAAA;AACA,IAAAM,SAAA,GAAAN,OAAA;AACA,IAAAO,WAAA,GAAAP,OAAA;AAQA,IAAAQ,YAAA,GAAAR,OAAA;
|
|
1
|
+
{"version":3,"names":["React","_interopRequireWildcard","require","_constants","_context","_positionUtils","_Positioner","_ToastHost","_ToastRow","_toastStore","_useAppState","_useSingleOutletGuard","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ALL_POSITIONS","EMPTY_TOAST_OPTIONS","EMPTY_ICONS","EMPTY_ANIMATION","orderToastsFromPosition","toasts","position","slice","reverse","Toaster","ToasterOverlayWrapper","ToastWrapper","duration","toastDefaults","offset","visibleToasts","swipeToDismissDirection","closeButton","gap","theme","invert","richColors","enableStacking","autoWiggleOnUpdate","pauseWhenPageIsHidden","allowFontScaling","maxFontSizeMultiplier","toastOptions","icons","animation","unstyled","positionerStyle","style","styles","styleOverrides","useSingleOutletGuard","shouldShowOverlay","toastHeights","isExpanded","useSyncExternalStore","toastStore","subscribe","getSnapshot","useEffect","setConfig","onBackground","useCallback","pauseAllTimers","onForeground","resumeAllTimers","useAppStateChange","stableValue","useMemo","dynamicValue","expand","collapse","toggleExpand","toastsByPosition","groups","Map","candidate","group","filter","toast","length","onDismiss","id","dismissToast","jsx","ToastHost","children","ToastContext","Provider","value","DynamicToastContext","Array","from","currentPosition","toastsForPosition","orderedToastIds","getOrderedToastIds","Positioner","map","index","row","ToastRow","numberOfToasts","ref","getToastRef","toastId","exports","displayName"],"sourceRoot":"../../../src","sources":["toast/Toaster.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.resetSingleOutletGuardForTests = resetSingleOutletGuardForTests;
|
|
7
|
+
exports.useSingleOutletGuard = useSingleOutletGuard;
|
|
8
|
+
var React = _interopRequireWildcard(require("react"));
|
|
9
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
10
|
+
/**
|
|
11
|
+
* Bloom-original — the dev-only guard against a SECOND toast outlet.
|
|
12
|
+
*
|
|
13
|
+
* Every `Toaster` subscribes to the ONE module-level `toastStore`, which has no
|
|
14
|
+
* notion of an owning outlet, so N mounted outlets each render the full row set:
|
|
15
|
+
* a toast appears N times. Nothing in the engine can dedupe that — the outlets
|
|
16
|
+
* are legitimate, independent subscribers — so the contract is "mount exactly
|
|
17
|
+
* one" and this is what enforces it.
|
|
18
|
+
*
|
|
19
|
+
* WHY A WARNING IS WORTH ITS WEIGHT: the copies are not visually separated, so
|
|
20
|
+
* the defect does not look like duplication. Two bare outlets take identical
|
|
21
|
+
* defaults and land pixel-identical; two outlets whose `offset` differs by a
|
|
22
|
+
* point land 1px apart. Only counting the rendered rows reveals it, which is not
|
|
23
|
+
* something anyone thinks to do — the reports this guard comes from all read as
|
|
24
|
+
* "the toast looks wrong", never as "there are two of them". Stacking is on by
|
|
25
|
+
* default, so a duplicate outlet now doubles the rows INSIDE a stack.
|
|
26
|
+
*
|
|
27
|
+
* The counter is decremented on unmount, so a remount, a route change that moves
|
|
28
|
+
* the outlet, Fast Refresh and React's StrictMode double-invoke (setup, cleanup,
|
|
29
|
+
* setup) all pass through a count of 1 and stay silent. The latch keeps the
|
|
30
|
+
* warning to exactly one per module lifetime rather than one per extra outlet,
|
|
31
|
+
* and — because StrictMode replays the setups — one per app, not two.
|
|
32
|
+
*
|
|
33
|
+
* Gated on `process.env.NODE_ENV`, the same mechanism as
|
|
34
|
+
* `content-panel/nesting-context.ts`: Metro and Vite/Rolldown both fold it
|
|
35
|
+
* statically, so production keeps the counter, the branch and the message out of
|
|
36
|
+
* the bundle entirely. Deliberately NOT `__DEV__`, which is a Metro global that a
|
|
37
|
+
* plain web bundler does not define. It only ever warns — a duplicate outlet
|
|
38
|
+
* renders a redundant toast, it does not break the app, so it must never throw.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
let mountedOutlets = 0;
|
|
42
|
+
let hasWarned = false;
|
|
43
|
+
function useSingleOutletGuard() {
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
if (process.env.NODE_ENV === 'production') {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
mountedOutlets += 1;
|
|
49
|
+
if (mountedOutlets > 1 && !hasWarned) {
|
|
50
|
+
hasWarned = true;
|
|
51
|
+
// Internal Bloom diagnostic: the consumer's tree is the only place this
|
|
52
|
+
// can be fixed, so it names the usual cause rather than just the symptom.
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.warn(`[Bloom] Toaster: ${mountedOutlets} toast outlets are mounted, so every ` + 'toast renders once per outlet. The copies overlap almost exactly, so ' + 'this reads as a rendering glitch rather than as duplicate rows. Mount ' + "exactly one: @oxyhq/services' OxyProvider already renders a " + 'ToastOutlet, so an app that uses it must not render its own.');
|
|
55
|
+
}
|
|
56
|
+
return () => {
|
|
57
|
+
mountedOutlets -= 1;
|
|
58
|
+
};
|
|
59
|
+
}, []);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Test-only reset: both the counter and the one-shot latch are module state that
|
|
64
|
+
* outlives a render tree, so without this the first suite to mount two outlets
|
|
65
|
+
* would latch the warning and leave every later suite asserting against a guard
|
|
66
|
+
* that can no longer fire — passing whatever the implementation did.
|
|
67
|
+
*/
|
|
68
|
+
function resetSingleOutletGuardForTests() {
|
|
69
|
+
mountedOutlets = 0;
|
|
70
|
+
hasWarned = false;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=use-single-outlet-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","_interopRequireWildcard","require","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","mountedOutlets","hasWarned","useSingleOutletGuard","useEffect","process","env","NODE_ENV","console","warn","resetSingleOutletGuardForTests"],"sourceRoot":"../../../src","sources":["toast/use-single-outlet-guard.ts"],"mappings":";;;;;;;AA8BA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AAA+B,SAAAD,wBAAAE,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAJ,uBAAA,YAAAA,CAAAE,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AA9B/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,IAAIkB,cAAc,GAAG,CAAC;AACtB,IAAIC,SAAS,GAAG,KAAK;AAEd,SAASC,oBAAoBA,CAAA,EAAS;EAC3CxB,KAAK,CAACyB,SAAS,CAAC,MAAM;IACpB,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC;IACF;IAEAN,cAAc,IAAI,CAAC;IACnB,IAAIA,cAAc,GAAG,CAAC,IAAI,CAACC,SAAS,EAAE;MACpCA,SAAS,GAAG,IAAI;MAChB;MACA;MACA;MACAM,OAAO,CAACC,IAAI,CACV,oBAAoBR,cAAc,uCAAuC,GACvE,uEAAuE,GACvE,wEAAwE,GACxE,8DAA8D,GAC9D,8DACJ,CAAC;IACH;IAEA,OAAO,MAAM;MACXA,cAAc,IAAI,CAAC;IACrB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;AACR;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,SAASS,8BAA8BA,CAAA,EAAS;EACrDT,cAAc,GAAG,CAAC;EAClBC,SAAS,GAAG,KAAK;AACnB","ignoreList":[]}
|
|
@@ -24,6 +24,7 @@ import { ToastHost } from './ToastHost';
|
|
|
24
24
|
import { ToastRow } from "./ToastRow.js";
|
|
25
25
|
import { toastStore } from "./toast-store.js";
|
|
26
26
|
import { useAppStateChange } from "./use-app-state.js";
|
|
27
|
+
import { useSingleOutletGuard } from "./use-single-outlet-guard.js";
|
|
27
28
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
28
29
|
const ALL_POSITIONS = ['top-center', 'bottom-center', 'center'];
|
|
29
30
|
|
|
@@ -65,6 +66,10 @@ export const Toaster = ({
|
|
|
65
66
|
style,
|
|
66
67
|
styles: styleOverrides
|
|
67
68
|
}) => {
|
|
69
|
+
// Before any early return, and independent of whether a toast is up: a second
|
|
70
|
+
// outlet duplicates every row from the moment it mounts, not from the first
|
|
71
|
+
// toast, so the warning must not wait for one.
|
|
72
|
+
useSingleOutletGuard();
|
|
68
73
|
const {
|
|
69
74
|
toasts,
|
|
70
75
|
shouldShowOverlay,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","toastDefaults","DynamicToastContext","ToastContext","getOrderedToastIds","Positioner","ToastHost","ToastRow","toastStore","useAppStateChange","jsx","_jsx","ALL_POSITIONS","EMPTY_TOAST_OPTIONS","EMPTY_ICONS","EMPTY_ANIMATION","orderToastsFromPosition","toasts","position","slice","reverse","Toaster","ToasterOverlayWrapper","ToastWrapper","duration","offset","visibleToasts","swipeToDismissDirection","closeButton","gap","theme","invert","richColors","enableStacking","autoWiggleOnUpdate","pauseWhenPageIsHidden","allowFontScaling","maxFontSizeMultiplier","toastOptions","icons","animation","unstyled","positionerStyle","style","styles","styleOverrides","shouldShowOverlay","toastHeights","isExpanded","useSyncExternalStore","subscribe","getSnapshot","useEffect","setConfig","onBackground","useCallback","pauseAllTimers","onForeground","resumeAllTimers","stableValue","useMemo","dynamicValue","expand","collapse","toggleExpand","toastsByPosition","groups","Map","candidate","group","filter","toast","length","set","onDismiss","id","dismissToast","children","Provider","value","Array","from","currentPosition","toastsForPosition","orderedToastIds","map","index","row","numberOfToasts","ref","getToastRef","toastId","displayName"],"sourceRoot":"../../../src","sources":["toast/Toaster.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAASC,aAAa,QAAQ,gBAAa;AAC3C,SAASC,mBAAmB,EAAEC,YAAY,QAAQ,cAAW;AAC7D,SAASC,kBAAkB,QAAQ,qBAAkB;AACrD,SAASC,UAAU,QAAQ,iBAAc;AACzC,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,QAAQ,QAAQ,eAAY;AACrC,SAASC,UAAU,QAAQ,kBAAe;AAQ1C,SAASC,iBAAiB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;
|
|
1
|
+
{"version":3,"names":["React","toastDefaults","DynamicToastContext","ToastContext","getOrderedToastIds","Positioner","ToastHost","ToastRow","toastStore","useAppStateChange","useSingleOutletGuard","jsx","_jsx","ALL_POSITIONS","EMPTY_TOAST_OPTIONS","EMPTY_ICONS","EMPTY_ANIMATION","orderToastsFromPosition","toasts","position","slice","reverse","Toaster","ToasterOverlayWrapper","ToastWrapper","duration","offset","visibleToasts","swipeToDismissDirection","closeButton","gap","theme","invert","richColors","enableStacking","autoWiggleOnUpdate","pauseWhenPageIsHidden","allowFontScaling","maxFontSizeMultiplier","toastOptions","icons","animation","unstyled","positionerStyle","style","styles","styleOverrides","shouldShowOverlay","toastHeights","isExpanded","useSyncExternalStore","subscribe","getSnapshot","useEffect","setConfig","onBackground","useCallback","pauseAllTimers","onForeground","resumeAllTimers","stableValue","useMemo","dynamicValue","expand","collapse","toggleExpand","toastsByPosition","groups","Map","candidate","group","filter","toast","length","set","onDismiss","id","dismissToast","children","Provider","value","Array","from","currentPosition","toastsForPosition","orderedToastIds","map","index","row","numberOfToasts","ref","getToastRef","toastId","displayName"],"sourceRoot":"../../../src","sources":["toast/Toaster.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bloom-original — the dev-only guard against a SECOND toast outlet.
|
|
5
|
+
*
|
|
6
|
+
* Every `Toaster` subscribes to the ONE module-level `toastStore`, which has no
|
|
7
|
+
* notion of an owning outlet, so N mounted outlets each render the full row set:
|
|
8
|
+
* a toast appears N times. Nothing in the engine can dedupe that — the outlets
|
|
9
|
+
* are legitimate, independent subscribers — so the contract is "mount exactly
|
|
10
|
+
* one" and this is what enforces it.
|
|
11
|
+
*
|
|
12
|
+
* WHY A WARNING IS WORTH ITS WEIGHT: the copies are not visually separated, so
|
|
13
|
+
* the defect does not look like duplication. Two bare outlets take identical
|
|
14
|
+
* defaults and land pixel-identical; two outlets whose `offset` differs by a
|
|
15
|
+
* point land 1px apart. Only counting the rendered rows reveals it, which is not
|
|
16
|
+
* something anyone thinks to do — the reports this guard comes from all read as
|
|
17
|
+
* "the toast looks wrong", never as "there are two of them". Stacking is on by
|
|
18
|
+
* default, so a duplicate outlet now doubles the rows INSIDE a stack.
|
|
19
|
+
*
|
|
20
|
+
* The counter is decremented on unmount, so a remount, a route change that moves
|
|
21
|
+
* the outlet, Fast Refresh and React's StrictMode double-invoke (setup, cleanup,
|
|
22
|
+
* setup) all pass through a count of 1 and stay silent. The latch keeps the
|
|
23
|
+
* warning to exactly one per module lifetime rather than one per extra outlet,
|
|
24
|
+
* and — because StrictMode replays the setups — one per app, not two.
|
|
25
|
+
*
|
|
26
|
+
* Gated on `process.env.NODE_ENV`, the same mechanism as
|
|
27
|
+
* `content-panel/nesting-context.ts`: Metro and Vite/Rolldown both fold it
|
|
28
|
+
* statically, so production keeps the counter, the branch and the message out of
|
|
29
|
+
* the bundle entirely. Deliberately NOT `__DEV__`, which is a Metro global that a
|
|
30
|
+
* plain web bundler does not define. It only ever warns — a duplicate outlet
|
|
31
|
+
* renders a redundant toast, it does not break the app, so it must never throw.
|
|
32
|
+
*/
|
|
33
|
+
import * as React from 'react';
|
|
34
|
+
let mountedOutlets = 0;
|
|
35
|
+
let hasWarned = false;
|
|
36
|
+
export function useSingleOutletGuard() {
|
|
37
|
+
React.useEffect(() => {
|
|
38
|
+
if (process.env.NODE_ENV === 'production') {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
mountedOutlets += 1;
|
|
42
|
+
if (mountedOutlets > 1 && !hasWarned) {
|
|
43
|
+
hasWarned = true;
|
|
44
|
+
// Internal Bloom diagnostic: the consumer's tree is the only place this
|
|
45
|
+
// can be fixed, so it names the usual cause rather than just the symptom.
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.warn(`[Bloom] Toaster: ${mountedOutlets} toast outlets are mounted, so every ` + 'toast renders once per outlet. The copies overlap almost exactly, so ' + 'this reads as a rendering glitch rather than as duplicate rows. Mount ' + "exactly one: @oxyhq/services' OxyProvider already renders a " + 'ToastOutlet, so an app that uses it must not render its own.');
|
|
48
|
+
}
|
|
49
|
+
return () => {
|
|
50
|
+
mountedOutlets -= 1;
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Test-only reset: both the counter and the one-shot latch are module state that
|
|
57
|
+
* outlives a render tree, so without this the first suite to mount two outlets
|
|
58
|
+
* would latch the warning and leave every later suite asserting against a guard
|
|
59
|
+
* that can no longer fire — passing whatever the implementation did.
|
|
60
|
+
*/
|
|
61
|
+
export function resetSingleOutletGuardForTests() {
|
|
62
|
+
mountedOutlets = 0;
|
|
63
|
+
hasWarned = false;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=use-single-outlet-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","mountedOutlets","hasWarned","useSingleOutletGuard","useEffect","process","env","NODE_ENV","console","warn","resetSingleOutletGuardForTests"],"sourceRoot":"../../../src","sources":["toast/use-single-outlet-guard.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,IAAIC,cAAc,GAAG,CAAC;AACtB,IAAIC,SAAS,GAAG,KAAK;AAErB,OAAO,SAASC,oBAAoBA,CAAA,EAAS;EAC3CH,KAAK,CAACI,SAAS,CAAC,MAAM;IACpB,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;MACzC;IACF;IAEAN,cAAc,IAAI,CAAC;IACnB,IAAIA,cAAc,GAAG,CAAC,IAAI,CAACC,SAAS,EAAE;MACpCA,SAAS,GAAG,IAAI;MAChB;MACA;MACA;MACAM,OAAO,CAACC,IAAI,CACV,oBAAoBR,cAAc,uCAAuC,GACvE,uEAAuE,GACvE,wEAAwE,GACxE,8DAA8D,GAC9D,8DACJ,CAAC;IACH;IAEA,OAAO,MAAM;MACXA,cAAc,IAAI,CAAC;IACrB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;AACR;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASS,8BAA8BA,CAAA,EAAS;EACrDT,cAAc,GAAG,CAAC;EAClBC,SAAS,GAAG,KAAK;AACnB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../../src/toast/Toaster.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../../src/toast/Toaster.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,SAAS,CAAC;AA0BjB,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA8M1C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function useSingleOutletGuard(): void;
|
|
2
|
+
/**
|
|
3
|
+
* Test-only reset: both the counter and the one-shot latch are module state that
|
|
4
|
+
* outlives a render tree, so without this the first suite to mount two outlets
|
|
5
|
+
* would latch the warning and leave every later suite asserting against a guard
|
|
6
|
+
* that can no longer fire — passing whatever the implementation did.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resetSingleOutletGuardForTests(): void;
|
|
9
|
+
//# sourceMappingURL=use-single-outlet-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-single-outlet-guard.d.ts","sourceRoot":"","sources":["../../../../src/toast/use-single-outlet-guard.ts"],"names":[],"mappings":"AAmCA,wBAAgB,oBAAoB,IAAI,IAAI,CAyB3C;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../../src/toast/Toaster.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../../src/toast/Toaster.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,SAAS,CAAC;AA0BjB,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA8M1C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function useSingleOutletGuard(): void;
|
|
2
|
+
/**
|
|
3
|
+
* Test-only reset: both the counter and the one-shot latch are module state that
|
|
4
|
+
* outlives a render tree, so without this the first suite to mount two outlets
|
|
5
|
+
* would latch the warning and leave every later suite asserting against a guard
|
|
6
|
+
* that can no longer fire — passing whatever the implementation did.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resetSingleOutletGuardForTests(): void;
|
|
9
|
+
//# sourceMappingURL=use-single-outlet-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-single-outlet-guard.d.ts","sourceRoot":"","sources":["../../../../src/toast/use-single-outlet-guard.ts"],"names":[],"mappings":"AAmCA,wBAAgB,oBAAoB,IAAI,IAAI,CAyB3C;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD"}
|