pne-ui 3.0.29 → 3.0.31
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 +81 -0
- package/cjs/component/overlay/OverlayHost.d.ts +14 -0
- package/cjs/component/overlay/OverlayHost.js +120 -0
- package/cjs/component/overlay/OverlayHost.js.map +1 -0
- package/cjs/component/overlay/PermanentOverlay.d.ts +14 -0
- package/cjs/component/overlay/PermanentOverlay.js +33 -0
- package/cjs/component/overlay/PermanentOverlay.js.map +1 -0
- package/cjs/component/overlay/PermanentOverlayContext.d.ts +7 -0
- package/cjs/component/overlay/PermanentOverlayContext.js +6 -0
- package/cjs/component/overlay/PermanentOverlayContext.js.map +1 -0
- package/cjs/component/overlay/types.d.ts +5 -3
- package/cjs/exports/overlay.d.ts +2 -1
- package/cjs/exports/overlay.js +5 -3
- package/cjs/exports/overlay.js.map +1 -1
- package/esm/component/overlay/OverlayHost.d.ts +14 -0
- package/esm/component/overlay/OverlayHost.js +115 -0
- package/esm/component/overlay/OverlayHost.js.map +1 -0
- package/esm/component/overlay/PermanentOverlay.d.ts +14 -0
- package/esm/component/overlay/PermanentOverlay.js +29 -0
- package/esm/component/overlay/PermanentOverlay.js.map +1 -0
- package/esm/component/overlay/PermanentOverlayContext.d.ts +7 -0
- package/esm/component/overlay/PermanentOverlayContext.js +3 -0
- package/esm/component/overlay/PermanentOverlayContext.js.map +1 -0
- package/esm/component/overlay/types.d.ts +5 -3
- package/esm/exports/overlay.d.ts +2 -1
- package/esm/exports/overlay.js +2 -1
- package/esm/exports/overlay.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -279,6 +279,87 @@ export const Dashboard = () => (
|
|
|
279
279
|
`WidgetBoard` сам обновляет выбранный лейаут, следит за состоянием виджетов и при изменениях дергает `saveLayouts`
|
|
280
280
|
с актуальным набором опций.
|
|
281
281
|
|
|
282
|
+
## OverlayHost и уведомления
|
|
283
|
+
|
|
284
|
+
`OverlayHost` рендерит snackbars из `overlayActions` и принимает декларативные постоянные оверлеи через `PermanentOverlay`
|
|
285
|
+
(по одному на слот: `top-left/top-right/bottom-left/bottom-right`).
|
|
286
|
+
```tsx
|
|
287
|
+
import React from 'react'
|
|
288
|
+
import { OverlayHost, PermanentOverlay, PneFloatingActionButtons, overlayActions } from 'pne-ui'
|
|
289
|
+
|
|
290
|
+
const AppShell = () => (
|
|
291
|
+
<OverlayHost>
|
|
292
|
+
<PermanentOverlay
|
|
293
|
+
id='page-fab'
|
|
294
|
+
slot='bottom-right'
|
|
295
|
+
render={() => (
|
|
296
|
+
<PneFloatingActionButtons
|
|
297
|
+
actions={[
|
|
298
|
+
{
|
|
299
|
+
id: 'save',
|
|
300
|
+
label: 'Save',
|
|
301
|
+
onClick: () => overlayActions.showSuccess({ message: 'Saved!' }),
|
|
302
|
+
},
|
|
303
|
+
{ id: 'divider', kind: 'divider' },
|
|
304
|
+
{
|
|
305
|
+
id: 'info',
|
|
306
|
+
label: 'Info',
|
|
307
|
+
onClick: () => overlayActions.showInfo({ message: 'Something happened' }),
|
|
308
|
+
},
|
|
309
|
+
]}
|
|
310
|
+
/>
|
|
311
|
+
)}
|
|
312
|
+
/>
|
|
313
|
+
{/* ваш layout, роутер, модалки и т.д. */}
|
|
314
|
+
</OverlayHost>
|
|
315
|
+
)
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
- Для уведомлений используйте `overlayActions.showSuccess/showError/showWarning/showInfo` или `showSnackbar`.
|
|
319
|
+
- `PermanentOverlay` можно размещать на любом уровне дерева под хостом; последний зарегистрированный в слоте заменяет предыдущий.
|
|
320
|
+
- Слоты фиксированы четырьмя углами; сместить позицию можно через `offset`/`zIndex` пропы на `PermanentOverlay`.
|
|
321
|
+
|
|
322
|
+
## PneFloatingActionButtons
|
|
323
|
+
|
|
324
|
+
Плавающее меню действий: на десктопе показывает стек FAB над триггером и параллельно меню, на мобильных все пункты уходят
|
|
325
|
+
в меню. Поддерживает экшены, произвольные блоки контента и разделители. По умолчанию мобильным считается ширина `<= 800px`
|
|
326
|
+
(`mobileBreakpoint`), на десктопе action-кнопки остаются доступны и в меню, и в стеке.
|
|
327
|
+
|
|
328
|
+
Ключевые пропы:
|
|
329
|
+
- `actions: PneFabItem[]` — массив элементов: action `{ id, label, onClick, icon?, disabled?, tooltip? }`,
|
|
330
|
+
divider `{ kind: 'divider' }`, content `{ kind: 'content', node }`.
|
|
331
|
+
- `mobileBreakpoint` (default `800`) — ширина, ниже которой показываем только меню.
|
|
332
|
+
- `position` (`{ bottom?: number; right?: number }`) — смещение от края.
|
|
333
|
+
- `fabLabel`/`fabIcon` — подпись и иконка триггера.
|
|
334
|
+
- `bannerText` — необязательный блок внизу меню.
|
|
335
|
+
|
|
336
|
+
Минимальный пример:
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
import { PneFloatingActionButtons, overlayActions } from 'pne-ui'
|
|
340
|
+
|
|
341
|
+
const actions = [
|
|
342
|
+
{ id: 'reset', label: 'Reset layout', onClick: () => overlayActions.showInfo({ message: 'Reset' }) },
|
|
343
|
+
{ id: 'save', label: 'Save', onClick: () => overlayActions.showSuccess({ message: 'Saved' }) },
|
|
344
|
+
{ id: 'divider', kind: 'divider' as const },
|
|
345
|
+
{ id: 'custom', kind: 'content' as const, node: <div style={{ padding: 8 }}>Any JSX here</div> },
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
export const FabDemo = () => (
|
|
349
|
+
<PneFloatingActionButtons
|
|
350
|
+
actions={actions}
|
|
351
|
+
fabLabel='Actions'
|
|
352
|
+
bannerText='Edit widgets'
|
|
353
|
+
position={{ bottom: 24, right: 24 }}
|
|
354
|
+
mobileBreakpoint={900} // считать мобильным до 900px, иначе поведение как на десктопе
|
|
355
|
+
/>
|
|
356
|
+
)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Поведение по размерам:
|
|
360
|
+
- Ширина > `mobileBreakpoint`: стек FAB над триггером + меню (все action-пункты дублируются в меню).
|
|
361
|
+
- Ширина <= `mobileBreakpoint`: только триггер + меню, стек FAB скрыт.
|
|
362
|
+
|
|
282
363
|
[npm-url]: https://www.npmjs.com/package/pne-ui
|
|
283
364
|
|
|
284
365
|
[npm-image]: https://img.shields.io/npm/v/pne-ui
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SnackbarOrigin } from '@mui/material';
|
|
3
|
+
type OverlayHostProps = {
|
|
4
|
+
anchorOrigin?: SnackbarOrigin;
|
|
5
|
+
maxSnack?: number;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Renders overlay elements (currently snackbars) driven by the shared overlay store.
|
|
10
|
+
* Mount this once near the root of the app and trigger notifications via `overlayActions`.
|
|
11
|
+
* Permanent overlays are registered declaratively via `<PermanentOverlay />` components.
|
|
12
|
+
*/
|
|
13
|
+
export declare function OverlayHost({ anchorOrigin, maxSnack, children, }: OverlayHostProps): React.JSX.Element;
|
|
14
|
+
export default OverlayHost;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OverlayHost = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const react_1 = tslib_1.__importStar(require("react"));
|
|
6
|
+
const material_1 = require("@mui/material");
|
|
7
|
+
const useBreakpoint_1 = require("../responsive/useBreakpoint");
|
|
8
|
+
const overlayStore_1 = require("./overlayStore");
|
|
9
|
+
const material_2 = require("@mui/material");
|
|
10
|
+
const PermanentOverlayContext_1 = require("./PermanentOverlayContext");
|
|
11
|
+
const STACK_GAP = 12;
|
|
12
|
+
const STACK_OFFSET = 24;
|
|
13
|
+
const PERMANENT_OFFSET = 24;
|
|
14
|
+
/**
|
|
15
|
+
* Renders overlay elements (currently snackbars) driven by the shared overlay store.
|
|
16
|
+
* Mount this once near the root of the app and trigger notifications via `overlayActions`.
|
|
17
|
+
* Permanent overlays are registered declaratively via `<PermanentOverlay />` components.
|
|
18
|
+
*/
|
|
19
|
+
function OverlayHost({ anchorOrigin = { vertical: 'bottom', horizontal: 'left' }, maxSnack = 10, children, }) {
|
|
20
|
+
const snackbars = (0, overlayStore_1.useOverlayStore)(state => state.snackbars);
|
|
21
|
+
const removeSnackbar = (0, overlayStore_1.useOverlayStore)(state => state.removeSnackbar);
|
|
22
|
+
const breakpoint = (0, useBreakpoint_1.useBreakpoint)();
|
|
23
|
+
const [permanentOverlays, setPermanentOverlays] = (0, react_1.useState)(() => new Map());
|
|
24
|
+
const registerPermanentOverlay = (0, react_1.useCallback)((overlay) => {
|
|
25
|
+
setPermanentOverlays(prev => {
|
|
26
|
+
const next = new Map(prev);
|
|
27
|
+
next.set(overlay.slot, overlay);
|
|
28
|
+
return next;
|
|
29
|
+
});
|
|
30
|
+
}, []);
|
|
31
|
+
const unregisterPermanentOverlay = (0, react_1.useCallback)((id, slot) => {
|
|
32
|
+
setPermanentOverlays(prev => {
|
|
33
|
+
const next = new Map(prev);
|
|
34
|
+
if (slot) {
|
|
35
|
+
const current = next.get(slot);
|
|
36
|
+
if (current?.id === id)
|
|
37
|
+
next.delete(slot);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
for (const [key, value] of next.entries()) {
|
|
41
|
+
if (value.id === id)
|
|
42
|
+
next.delete(key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
}, []);
|
|
48
|
+
const contextValue = (0, react_1.useMemo)(() => ({ register: registerPermanentOverlay, unregister: unregisterPermanentOverlay }), [registerPermanentOverlay, unregisterPermanentOverlay]);
|
|
49
|
+
const visibleSnackbars = (0, react_1.useMemo)(() => {
|
|
50
|
+
if (typeof maxSnack === 'number' && maxSnack > 0 && snackbars.length > maxSnack) {
|
|
51
|
+
return snackbars.slice(snackbars.length - maxSnack);
|
|
52
|
+
}
|
|
53
|
+
return snackbars;
|
|
54
|
+
}, [maxSnack, snackbars]);
|
|
55
|
+
const groupedSnackbars = (0, react_1.useMemo)(() => {
|
|
56
|
+
const groups = [];
|
|
57
|
+
const map = new Map();
|
|
58
|
+
visibleSnackbars.forEach(snack => {
|
|
59
|
+
const anchor = snack.anchorOrigin ?? anchorOrigin;
|
|
60
|
+
const key = `${anchor.vertical}-${anchor.horizontal}`;
|
|
61
|
+
if (!map.has(key)) {
|
|
62
|
+
const group = { anchor, items: [] };
|
|
63
|
+
map.set(key, group);
|
|
64
|
+
groups.push(group);
|
|
65
|
+
}
|
|
66
|
+
map.get(key).items.push(snack);
|
|
67
|
+
});
|
|
68
|
+
return groups;
|
|
69
|
+
}, [anchorOrigin, visibleSnackbars]);
|
|
70
|
+
const permanentContent = (0, react_1.useMemo)(() => {
|
|
71
|
+
const entries = Array.from(permanentOverlays.values());
|
|
72
|
+
return entries
|
|
73
|
+
.map(entry => {
|
|
74
|
+
const content = entry.render({ breakpoint });
|
|
75
|
+
if (!content)
|
|
76
|
+
return null;
|
|
77
|
+
const offset = entry.offset ?? PERMANENT_OFFSET;
|
|
78
|
+
const vertical = entry.slot.startsWith('top') ? 'top' : 'bottom';
|
|
79
|
+
const horizontal = entry.slot.endsWith('left') ? 'left' : 'right';
|
|
80
|
+
return (react_1.default.createElement(material_2.Box, { key: entry.slot, sx: {
|
|
81
|
+
position: 'fixed',
|
|
82
|
+
zIndex: entry.zIndex ?? 1300,
|
|
83
|
+
[vertical]: offset,
|
|
84
|
+
[horizontal]: offset,
|
|
85
|
+
} }, content));
|
|
86
|
+
})
|
|
87
|
+
.filter(Boolean);
|
|
88
|
+
}, [breakpoint, permanentOverlays]);
|
|
89
|
+
return (react_1.default.createElement(PermanentOverlayContext_1.PermanentOverlayContext.Provider, { value: contextValue },
|
|
90
|
+
children,
|
|
91
|
+
groupedSnackbars.map(group => {
|
|
92
|
+
const { anchor, items } = group;
|
|
93
|
+
const horizontalStyles = anchor.horizontal === 'left'
|
|
94
|
+
? { left: STACK_OFFSET, right: 'auto', transform: 'none' }
|
|
95
|
+
: anchor.horizontal === 'right'
|
|
96
|
+
? { right: STACK_OFFSET, left: 'auto', transform: 'none' }
|
|
97
|
+
: { left: '50%', transform: 'translateX(-50%)' };
|
|
98
|
+
const verticalStyles = anchor.vertical === 'top'
|
|
99
|
+
? { top: STACK_OFFSET, bottom: 'auto', flexDirection: 'column-reverse' }
|
|
100
|
+
: { bottom: STACK_OFFSET, top: 'auto', flexDirection: 'column-reverse' };
|
|
101
|
+
return (react_1.default.createElement(material_2.Box, { key: `${anchor.vertical}-${anchor.horizontal}`, sx: {
|
|
102
|
+
position: 'fixed',
|
|
103
|
+
zIndex: 1400,
|
|
104
|
+
display: 'flex',
|
|
105
|
+
gap: `${STACK_GAP}px`,
|
|
106
|
+
pointerEvents: 'none',
|
|
107
|
+
...horizontalStyles,
|
|
108
|
+
...verticalStyles,
|
|
109
|
+
} }, items.map(snack => (react_1.default.createElement(material_1.Snackbar, { key: snack.id, open: true, anchorOrigin: anchor, autoHideDuration: snack.autoHideMs, onClose: (_event, reason) => {
|
|
110
|
+
if (reason === 'clickaway')
|
|
111
|
+
return;
|
|
112
|
+
snack.id && removeSnackbar(snack.id);
|
|
113
|
+
}, sx: { position: 'static', transform: 'none', pointerEvents: 'auto', minWidth: 288 } },
|
|
114
|
+
react_1.default.createElement(material_1.Alert, { elevation: 1, onClose: () => snack.id && removeSnackbar(snack.id), severity: snack.variant ?? 'info', action: snack.action, sx: { alignItems: 'center' } }, snack.message))))));
|
|
115
|
+
}),
|
|
116
|
+
permanentContent));
|
|
117
|
+
}
|
|
118
|
+
exports.OverlayHost = OverlayHost;
|
|
119
|
+
exports.default = OverlayHost;
|
|
120
|
+
//# sourceMappingURL=OverlayHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverlayHost.js","sourceRoot":"","sources":["../../../src/component/overlay/OverlayHost.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PermanentOverlayRender, PermanentOverlaySlot } from './types';
|
|
2
|
+
type PermanentOverlayProps = {
|
|
3
|
+
id: string;
|
|
4
|
+
slot?: PermanentOverlaySlot;
|
|
5
|
+
render: PermanentOverlayRender;
|
|
6
|
+
offset?: number;
|
|
7
|
+
zIndex?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Declaratively registers a permanent overlay with the nearest `<OverlayHost />` in the tree.
|
|
11
|
+
* Only one overlay per slot is kept; the latest registered wins.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PermanentOverlay({ id, slot, render, offset, zIndex }: PermanentOverlayProps): null;
|
|
14
|
+
export default PermanentOverlay;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PermanentOverlay = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const PermanentOverlayContext_1 = require("./PermanentOverlayContext");
|
|
6
|
+
const DEFAULT_SLOT = 'bottom-right';
|
|
7
|
+
/**
|
|
8
|
+
* Declaratively registers a permanent overlay with the nearest `<OverlayHost />` in the tree.
|
|
9
|
+
* Only one overlay per slot is kept; the latest registered wins.
|
|
10
|
+
*/
|
|
11
|
+
function PermanentOverlay({ id, slot = DEFAULT_SLOT, render, offset, zIndex }) {
|
|
12
|
+
const ctx = (0, react_1.useContext)(PermanentOverlayContext_1.PermanentOverlayContext);
|
|
13
|
+
const renderRef = (0, react_1.useRef)(render);
|
|
14
|
+
(0, react_1.useEffect)(() => {
|
|
15
|
+
renderRef.current = render;
|
|
16
|
+
}, [render]);
|
|
17
|
+
(0, react_1.useEffect)(() => {
|
|
18
|
+
if (!ctx)
|
|
19
|
+
return;
|
|
20
|
+
ctx.register({
|
|
21
|
+
id,
|
|
22
|
+
slot,
|
|
23
|
+
offset,
|
|
24
|
+
zIndex,
|
|
25
|
+
render: context => renderRef.current(context),
|
|
26
|
+
});
|
|
27
|
+
return () => ctx.unregister(id, slot);
|
|
28
|
+
}, [ctx, id, slot, offset, zIndex]);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
exports.PermanentOverlay = PermanentOverlay;
|
|
32
|
+
exports.default = PermanentOverlay;
|
|
33
|
+
//# sourceMappingURL=PermanentOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermanentOverlay.js","sourceRoot":"","sources":["../../../src/component/overlay/PermanentOverlay.tsx"],"names":[],"mappings":";;;AAAA,iCAAqD;AACrD,uEAAmE;AAGnE,MAAM,YAAY,GAAyB,cAAc,CAAA;AAUzD;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAyB;IACvG,MAAM,GAAG,GAAG,IAAA,kBAAU,EAAC,iDAAuB,CAAC,CAAA;IAC/C,MAAM,SAAS,GAAG,IAAA,cAAM,EAAC,MAAM,CAAC,CAAA;IAEhC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,SAAS,CAAC,OAAO,GAAG,MAAM,CAAA;IAC9B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,IAAA,iBAAS,EAAC,GAAG,EAAE;QACX,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,GAAG,CAAC,QAAQ,CAAC;YACT,EAAE;YACF,IAAI;YACJ,MAAM;YACN,MAAM;YACN,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;SAChD,CAAC,CAAA;QACF,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IACzC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnC,OAAO,IAAI,CAAA;AACf,CAAC;AArBD,4CAqBC;AAED,kBAAe,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { PermanentOverlayInstance, PermanentOverlaySlot } from './types';
|
|
3
|
+
export type PermanentOverlayContextValue = {
|
|
4
|
+
register: (overlay: PermanentOverlayInstance) => void;
|
|
5
|
+
unregister: (id: string, slot?: PermanentOverlaySlot) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const PermanentOverlayContext: import("react").Context<PermanentOverlayContextValue | null>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PermanentOverlayContext = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
exports.PermanentOverlayContext = (0, react_1.createContext)(null);
|
|
6
|
+
//# sourceMappingURL=PermanentOverlayContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermanentOverlayContext.js","sourceRoot":"","sources":["../../../src/component/overlay/PermanentOverlayContext.ts"],"names":[],"mappings":";;;AAAA,iCAAqC;AAQxB,QAAA,uBAAuB,GAAG,IAAA,qBAAa,EAAsC,IAAI,CAAC,CAAA"}
|
|
@@ -18,9 +18,11 @@ export type OverlayState = {
|
|
|
18
18
|
export type PermanentOverlayRender = (context: {
|
|
19
19
|
breakpoint: number;
|
|
20
20
|
}) => React.ReactNode;
|
|
21
|
-
export type
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
export type PermanentOverlaySlot = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
22
|
+
export type PermanentOverlayInstance = {
|
|
23
|
+
id: string;
|
|
24
|
+
slot: PermanentOverlaySlot;
|
|
25
|
+
render: PermanentOverlayRender;
|
|
24
26
|
offset?: number;
|
|
25
27
|
zIndex?: number;
|
|
26
28
|
};
|
package/cjs/exports/overlay.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OverlayHost } from '../component/overlay/OverlayHost';
|
|
2
|
+
export { PermanentOverlay } from '../component/overlay/PermanentOverlay';
|
|
2
3
|
export { useOverlayStore, overlayActions } from '../component/overlay/overlayStore';
|
|
3
4
|
export * from '../component/overlay/types';
|
package/cjs/exports/overlay.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.overlayActions = exports.useOverlayStore = exports.
|
|
3
|
+
exports.overlayActions = exports.useOverlayStore = exports.PermanentOverlay = exports.OverlayHost = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
var
|
|
6
|
-
Object.defineProperty(exports, "
|
|
5
|
+
var OverlayHost_1 = require("../component/overlay/OverlayHost");
|
|
6
|
+
Object.defineProperty(exports, "OverlayHost", { enumerable: true, get: function () { return OverlayHost_1.OverlayHost; } });
|
|
7
|
+
var PermanentOverlay_1 = require("../component/overlay/PermanentOverlay");
|
|
8
|
+
Object.defineProperty(exports, "PermanentOverlay", { enumerable: true, get: function () { return PermanentOverlay_1.PermanentOverlay; } });
|
|
7
9
|
var overlayStore_1 = require("../component/overlay/overlayStore");
|
|
8
10
|
Object.defineProperty(exports, "useOverlayStore", { enumerable: true, get: function () { return overlayStore_1.useOverlayStore; } });
|
|
9
11
|
Object.defineProperty(exports, "overlayActions", { enumerable: true, get: function () { return overlayStore_1.overlayActions; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/exports/overlay.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/exports/overlay.ts"],"names":[],"mappings":";;;;AAAA,gEAA8D;AAArD,0GAAA,WAAW,OAAA;AACpB,0EAAwE;AAA/D,oHAAA,gBAAgB,OAAA;AACzB,kEAAmF;AAA1E,+GAAA,eAAe,OAAA;AAAE,8GAAA,cAAc,OAAA;AACxC,qEAA0C"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SnackbarOrigin } from '@mui/material';
|
|
3
|
+
type OverlayHostProps = {
|
|
4
|
+
anchorOrigin?: SnackbarOrigin;
|
|
5
|
+
maxSnack?: number;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Renders overlay elements (currently snackbars) driven by the shared overlay store.
|
|
10
|
+
* Mount this once near the root of the app and trigger notifications via `overlayActions`.
|
|
11
|
+
* Permanent overlays are registered declaratively via `<PermanentOverlay />` components.
|
|
12
|
+
*/
|
|
13
|
+
export declare function OverlayHost({ anchorOrigin, maxSnack, children, }: OverlayHostProps): React.JSX.Element;
|
|
14
|
+
export default OverlayHost;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import { Alert, Snackbar } from '@mui/material';
|
|
3
|
+
import { useBreakpoint } from '../responsive/useBreakpoint';
|
|
4
|
+
import { useOverlayStore } from './overlayStore';
|
|
5
|
+
import { Box } from '@mui/material';
|
|
6
|
+
import { PermanentOverlayContext } from './PermanentOverlayContext';
|
|
7
|
+
const STACK_GAP = 12;
|
|
8
|
+
const STACK_OFFSET = 24;
|
|
9
|
+
const PERMANENT_OFFSET = 24;
|
|
10
|
+
/**
|
|
11
|
+
* Renders overlay elements (currently snackbars) driven by the shared overlay store.
|
|
12
|
+
* Mount this once near the root of the app and trigger notifications via `overlayActions`.
|
|
13
|
+
* Permanent overlays are registered declaratively via `<PermanentOverlay />` components.
|
|
14
|
+
*/
|
|
15
|
+
export function OverlayHost({ anchorOrigin = { vertical: 'bottom', horizontal: 'left' }, maxSnack = 10, children, }) {
|
|
16
|
+
const snackbars = useOverlayStore(state => state.snackbars);
|
|
17
|
+
const removeSnackbar = useOverlayStore(state => state.removeSnackbar);
|
|
18
|
+
const breakpoint = useBreakpoint();
|
|
19
|
+
const [permanentOverlays, setPermanentOverlays] = useState(() => new Map());
|
|
20
|
+
const registerPermanentOverlay = useCallback((overlay) => {
|
|
21
|
+
setPermanentOverlays(prev => {
|
|
22
|
+
const next = new Map(prev);
|
|
23
|
+
next.set(overlay.slot, overlay);
|
|
24
|
+
return next;
|
|
25
|
+
});
|
|
26
|
+
}, []);
|
|
27
|
+
const unregisterPermanentOverlay = useCallback((id, slot) => {
|
|
28
|
+
setPermanentOverlays(prev => {
|
|
29
|
+
const next = new Map(prev);
|
|
30
|
+
if (slot) {
|
|
31
|
+
const current = next.get(slot);
|
|
32
|
+
if (current?.id === id)
|
|
33
|
+
next.delete(slot);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
for (const [key, value] of next.entries()) {
|
|
37
|
+
if (value.id === id)
|
|
38
|
+
next.delete(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return next;
|
|
42
|
+
});
|
|
43
|
+
}, []);
|
|
44
|
+
const contextValue = useMemo(() => ({ register: registerPermanentOverlay, unregister: unregisterPermanentOverlay }), [registerPermanentOverlay, unregisterPermanentOverlay]);
|
|
45
|
+
const visibleSnackbars = useMemo(() => {
|
|
46
|
+
if (typeof maxSnack === 'number' && maxSnack > 0 && snackbars.length > maxSnack) {
|
|
47
|
+
return snackbars.slice(snackbars.length - maxSnack);
|
|
48
|
+
}
|
|
49
|
+
return snackbars;
|
|
50
|
+
}, [maxSnack, snackbars]);
|
|
51
|
+
const groupedSnackbars = useMemo(() => {
|
|
52
|
+
const groups = [];
|
|
53
|
+
const map = new Map();
|
|
54
|
+
visibleSnackbars.forEach(snack => {
|
|
55
|
+
const anchor = snack.anchorOrigin ?? anchorOrigin;
|
|
56
|
+
const key = `${anchor.vertical}-${anchor.horizontal}`;
|
|
57
|
+
if (!map.has(key)) {
|
|
58
|
+
const group = { anchor, items: [] };
|
|
59
|
+
map.set(key, group);
|
|
60
|
+
groups.push(group);
|
|
61
|
+
}
|
|
62
|
+
map.get(key).items.push(snack);
|
|
63
|
+
});
|
|
64
|
+
return groups;
|
|
65
|
+
}, [anchorOrigin, visibleSnackbars]);
|
|
66
|
+
const permanentContent = useMemo(() => {
|
|
67
|
+
const entries = Array.from(permanentOverlays.values());
|
|
68
|
+
return entries
|
|
69
|
+
.map(entry => {
|
|
70
|
+
const content = entry.render({ breakpoint });
|
|
71
|
+
if (!content)
|
|
72
|
+
return null;
|
|
73
|
+
const offset = entry.offset ?? PERMANENT_OFFSET;
|
|
74
|
+
const vertical = entry.slot.startsWith('top') ? 'top' : 'bottom';
|
|
75
|
+
const horizontal = entry.slot.endsWith('left') ? 'left' : 'right';
|
|
76
|
+
return (React.createElement(Box, { key: entry.slot, sx: {
|
|
77
|
+
position: 'fixed',
|
|
78
|
+
zIndex: entry.zIndex ?? 1300,
|
|
79
|
+
[vertical]: offset,
|
|
80
|
+
[horizontal]: offset,
|
|
81
|
+
} }, content));
|
|
82
|
+
})
|
|
83
|
+
.filter(Boolean);
|
|
84
|
+
}, [breakpoint, permanentOverlays]);
|
|
85
|
+
return (React.createElement(PermanentOverlayContext.Provider, { value: contextValue },
|
|
86
|
+
children,
|
|
87
|
+
groupedSnackbars.map(group => {
|
|
88
|
+
const { anchor, items } = group;
|
|
89
|
+
const horizontalStyles = anchor.horizontal === 'left'
|
|
90
|
+
? { left: STACK_OFFSET, right: 'auto', transform: 'none' }
|
|
91
|
+
: anchor.horizontal === 'right'
|
|
92
|
+
? { right: STACK_OFFSET, left: 'auto', transform: 'none' }
|
|
93
|
+
: { left: '50%', transform: 'translateX(-50%)' };
|
|
94
|
+
const verticalStyles = anchor.vertical === 'top'
|
|
95
|
+
? { top: STACK_OFFSET, bottom: 'auto', flexDirection: 'column-reverse' }
|
|
96
|
+
: { bottom: STACK_OFFSET, top: 'auto', flexDirection: 'column-reverse' };
|
|
97
|
+
return (React.createElement(Box, { key: `${anchor.vertical}-${anchor.horizontal}`, sx: {
|
|
98
|
+
position: 'fixed',
|
|
99
|
+
zIndex: 1400,
|
|
100
|
+
display: 'flex',
|
|
101
|
+
gap: `${STACK_GAP}px`,
|
|
102
|
+
pointerEvents: 'none',
|
|
103
|
+
...horizontalStyles,
|
|
104
|
+
...verticalStyles,
|
|
105
|
+
} }, items.map(snack => (React.createElement(Snackbar, { key: snack.id, open: true, anchorOrigin: anchor, autoHideDuration: snack.autoHideMs, onClose: (_event, reason) => {
|
|
106
|
+
if (reason === 'clickaway')
|
|
107
|
+
return;
|
|
108
|
+
snack.id && removeSnackbar(snack.id);
|
|
109
|
+
}, sx: { position: 'static', transform: 'none', pointerEvents: 'auto', minWidth: 288 } },
|
|
110
|
+
React.createElement(Alert, { elevation: 1, onClose: () => snack.id && removeSnackbar(snack.id), severity: snack.variant ?? 'info', action: snack.action, sx: { alignItems: 'center' } }, snack.message))))));
|
|
111
|
+
}),
|
|
112
|
+
permanentContent));
|
|
113
|
+
}
|
|
114
|
+
export default OverlayHost;
|
|
115
|
+
//# sourceMappingURL=OverlayHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverlayHost.js","sourceRoot":"","sources":["../../../src/component/overlay/OverlayHost.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PermanentOverlayRender, PermanentOverlaySlot } from './types';
|
|
2
|
+
type PermanentOverlayProps = {
|
|
3
|
+
id: string;
|
|
4
|
+
slot?: PermanentOverlaySlot;
|
|
5
|
+
render: PermanentOverlayRender;
|
|
6
|
+
offset?: number;
|
|
7
|
+
zIndex?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Declaratively registers a permanent overlay with the nearest `<OverlayHost />` in the tree.
|
|
11
|
+
* Only one overlay per slot is kept; the latest registered wins.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PermanentOverlay({ id, slot, render, offset, zIndex }: PermanentOverlayProps): null;
|
|
14
|
+
export default PermanentOverlay;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useContext, useEffect, useRef } from 'react';
|
|
2
|
+
import { PermanentOverlayContext } from './PermanentOverlayContext';
|
|
3
|
+
const DEFAULT_SLOT = 'bottom-right';
|
|
4
|
+
/**
|
|
5
|
+
* Declaratively registers a permanent overlay with the nearest `<OverlayHost />` in the tree.
|
|
6
|
+
* Only one overlay per slot is kept; the latest registered wins.
|
|
7
|
+
*/
|
|
8
|
+
export function PermanentOverlay({ id, slot = DEFAULT_SLOT, render, offset, zIndex }) {
|
|
9
|
+
const ctx = useContext(PermanentOverlayContext);
|
|
10
|
+
const renderRef = useRef(render);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
renderRef.current = render;
|
|
13
|
+
}, [render]);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (!ctx)
|
|
16
|
+
return;
|
|
17
|
+
ctx.register({
|
|
18
|
+
id,
|
|
19
|
+
slot,
|
|
20
|
+
offset,
|
|
21
|
+
zIndex,
|
|
22
|
+
render: context => renderRef.current(context),
|
|
23
|
+
});
|
|
24
|
+
return () => ctx.unregister(id, slot);
|
|
25
|
+
}, [ctx, id, slot, offset, zIndex]);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
export default PermanentOverlay;
|
|
29
|
+
//# sourceMappingURL=PermanentOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermanentOverlay.js","sourceRoot":"","sources":["../../../src/component/overlay/PermanentOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAGnE,MAAM,YAAY,GAAyB,cAAc,CAAA;AAUzD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAyB;IACvG,MAAM,GAAG,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAA;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAEhC,SAAS,CAAC,GAAG,EAAE;QACX,SAAS,CAAC,OAAO,GAAG,MAAM,CAAA;IAC9B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,GAAG,CAAC,QAAQ,CAAC;YACT,EAAE;YACF,IAAI;YACJ,MAAM;YACN,MAAM;YACN,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;SAChD,CAAC,CAAA;QACF,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IACzC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnC,OAAO,IAAI,CAAA;AACf,CAAC;AAED,eAAe,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { PermanentOverlayInstance, PermanentOverlaySlot } from './types';
|
|
3
|
+
export type PermanentOverlayContextValue = {
|
|
4
|
+
register: (overlay: PermanentOverlayInstance) => void;
|
|
5
|
+
unregister: (id: string, slot?: PermanentOverlaySlot) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare const PermanentOverlayContext: import("react").Context<PermanentOverlayContextValue | null>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermanentOverlayContext.js","sourceRoot":"","sources":["../../../src/component/overlay/PermanentOverlayContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAQrC,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAsC,IAAI,CAAC,CAAA"}
|
|
@@ -18,9 +18,11 @@ export type OverlayState = {
|
|
|
18
18
|
export type PermanentOverlayRender = (context: {
|
|
19
19
|
breakpoint: number;
|
|
20
20
|
}) => React.ReactNode;
|
|
21
|
-
export type
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
export type PermanentOverlaySlot = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
22
|
+
export type PermanentOverlayInstance = {
|
|
23
|
+
id: string;
|
|
24
|
+
slot: PermanentOverlaySlot;
|
|
25
|
+
render: PermanentOverlayRender;
|
|
24
26
|
offset?: number;
|
|
25
27
|
zIndex?: number;
|
|
26
28
|
};
|
package/esm/exports/overlay.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OverlayHost } from '../component/overlay/OverlayHost';
|
|
2
|
+
export { PermanentOverlay } from '../component/overlay/PermanentOverlay';
|
|
2
3
|
export { useOverlayStore, overlayActions } from '../component/overlay/overlayStore';
|
|
3
4
|
export * from '../component/overlay/types';
|
package/esm/exports/overlay.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { OverlayHost } from '../component/overlay/OverlayHost';
|
|
2
|
+
export { PermanentOverlay } from '../component/overlay/PermanentOverlay';
|
|
2
3
|
export { useOverlayStore, overlayActions } from '../component/overlay/overlayStore';
|
|
3
4
|
export * from '../component/overlay/types';
|
|
4
5
|
//# sourceMappingURL=overlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/exports/overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/exports/overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AACxE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAA;AACnF,cAAc,4BAA4B,CAAA"}
|