no-frills-ui 0.0.14-alpha.0 → 0.0.14-alpha.10
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 +63 -24
- package/dist/index.js +3550 -4336
- package/dist/index.js.map +1 -1
- package/lib-esm/components/Accordion/Accordion.d.ts +11 -16
- package/lib-esm/components/Accordion/Accordion.js +25 -29
- package/lib-esm/components/Accordion/Accordion.js.map +1 -1
- package/lib-esm/components/Accordion/AccordionStep.d.ts +22 -22
- package/lib-esm/components/Accordion/AccordionStep.js +111 -109
- package/lib-esm/components/Accordion/AccordionStep.js.map +1 -1
- package/lib-esm/components/Badge/Badge.d.ts +13 -16
- package/lib-esm/components/Badge/Badge.js +31 -51
- package/lib-esm/components/Badge/Badge.js.map +1 -1
- package/lib-esm/components/Button/ActionButton.d.ts +9 -5
- package/lib-esm/components/Button/ActionButton.js +18 -38
- package/lib-esm/components/Button/ActionButton.js.map +1 -1
- package/lib-esm/components/Button/Button.d.ts +9 -5
- package/lib-esm/components/Button/Button.js +18 -40
- package/lib-esm/components/Button/Button.js.map +1 -1
- package/lib-esm/components/Button/IconButton.d.ts +9 -5
- package/lib-esm/components/Button/IconButton.js +18 -42
- package/lib-esm/components/Button/IconButton.js.map +1 -1
- package/lib-esm/components/Button/LinkButton.d.ts +9 -5
- package/lib-esm/components/Button/LinkButton.js +18 -32
- package/lib-esm/components/Button/LinkButton.js.map +1 -1
- package/lib-esm/components/Button/RaisedButton.d.ts +9 -5
- package/lib-esm/components/Button/RaisedButton.js +18 -46
- package/lib-esm/components/Button/RaisedButton.js.map +1 -1
- package/lib-esm/components/Card/Card.d.ts +4 -6
- package/lib-esm/components/Card/Card.js +18 -13
- package/lib-esm/components/Card/Card.js.map +1 -1
- package/lib-esm/components/Chip/Chip.d.ts +8 -3
- package/lib-esm/components/Chip/Chip.js +44 -42
- package/lib-esm/components/Chip/Chip.js.map +1 -1
- package/lib-esm/components/ChipInput/ChipInput.d.ts +31 -0
- package/lib-esm/components/ChipInput/ChipInput.js +198 -0
- package/lib-esm/components/ChipInput/ChipInput.js.map +1 -0
- package/lib-esm/components/ChipInput/index.d.ts +1 -0
- package/lib-esm/components/Dialog/AlertDialog.d.ts +11 -12
- package/lib-esm/components/Dialog/AlertDialog.js +44 -28
- package/lib-esm/components/Dialog/AlertDialog.js.map +1 -1
- package/lib-esm/components/Dialog/ConfirmDialog.d.ts +13 -14
- package/lib-esm/components/Dialog/ConfirmDialog.js +49 -33
- package/lib-esm/components/Dialog/ConfirmDialog.js.map +1 -1
- package/lib-esm/components/Dialog/Dialog.d.ts +40 -18
- package/lib-esm/components/Dialog/Dialog.js +125 -70
- package/lib-esm/components/Dialog/Dialog.js.map +1 -1
- package/lib-esm/components/Dialog/PromptDialog.d.ts +18 -19
- package/lib-esm/components/Dialog/PromptDialog.js +78 -49
- package/lib-esm/components/Dialog/PromptDialog.js.map +1 -1
- package/lib-esm/components/DragAndDrop/DragAndDrop.d.ts +43 -14
- package/lib-esm/components/DragAndDrop/DragAndDrop.js +128 -19
- package/lib-esm/components/DragAndDrop/DragAndDrop.js.map +1 -1
- package/lib-esm/components/DragAndDrop/DragItem.d.ts +41 -0
- package/lib-esm/components/DragAndDrop/DragItem.js +253 -36
- package/lib-esm/components/DragAndDrop/DragItem.js.map +1 -1
- package/lib-esm/components/DragAndDrop/types.d.ts +25 -3
- package/lib-esm/components/DragAndDrop/types.js +9 -6
- package/lib-esm/components/DragAndDrop/types.js.map +1 -1
- package/lib-esm/components/Drawer/Drawer.d.ts +86 -22
- package/lib-esm/components/Drawer/Drawer.js +176 -97
- package/lib-esm/components/Drawer/Drawer.js.map +1 -1
- package/lib-esm/components/Drawer/index.d.ts +1 -1
- package/lib-esm/components/Groups/Group.d.ts +5 -8
- package/lib-esm/components/Groups/Group.js +34 -79
- package/lib-esm/components/Groups/Group.js.map +1 -1
- package/lib-esm/components/Groups/GroupLabel.js +8 -17
- package/lib-esm/components/Groups/GroupLabel.js.map +1 -1
- package/lib-esm/components/Input/Checkbox.d.ts +12 -15
- package/lib-esm/components/Input/Checkbox.js +51 -118
- package/lib-esm/components/Input/Checkbox.js.map +1 -1
- package/lib-esm/components/Input/Dropdown.d.ts +11 -12
- package/lib-esm/components/Input/Dropdown.js +133 -52
- package/lib-esm/components/Input/Dropdown.js.map +1 -1
- package/lib-esm/components/Input/Input.d.ts +3 -3
- package/lib-esm/components/Input/Input.js +61 -109
- package/lib-esm/components/Input/Input.js.map +1 -1
- package/lib-esm/components/Input/Radio.d.ts +4 -8
- package/lib-esm/components/Input/Radio.js +35 -79
- package/lib-esm/components/Input/Radio.js.map +1 -1
- package/lib-esm/components/Input/RadioButton.d.ts +4 -8
- package/lib-esm/components/Input/RadioButton.js +34 -71
- package/lib-esm/components/Input/RadioButton.js.map +1 -1
- package/lib-esm/components/Input/Select.d.ts +6 -13
- package/lib-esm/components/Input/Select.js +75 -122
- package/lib-esm/components/Input/Select.js.map +1 -1
- package/lib-esm/components/Input/TextArea.d.ts +6 -13
- package/lib-esm/components/Input/TextArea.js +64 -108
- package/lib-esm/components/Input/TextArea.js.map +1 -1
- package/lib-esm/components/Input/Toggle.d.ts +4 -9
- package/lib-esm/components/Input/Toggle.js +31 -80
- package/lib-esm/components/Input/Toggle.js.map +1 -1
- package/lib-esm/components/Menu/Menu.d.ts +8 -6
- package/lib-esm/components/Menu/Menu.js +116 -31
- package/lib-esm/components/Menu/Menu.js.map +1 -1
- package/lib-esm/components/Menu/MenuContext.d.ts +11 -5
- package/lib-esm/components/Menu/MenuContext.js +6 -2
- package/lib-esm/components/Menu/MenuContext.js.map +1 -1
- package/lib-esm/components/Menu/MenuItem.d.ts +7 -4
- package/lib-esm/components/Menu/MenuItem.js +46 -47
- package/lib-esm/components/Menu/MenuItem.js.map +1 -1
- package/lib-esm/components/Modal/Modal.d.ts +75 -16
- package/lib-esm/components/Modal/Modal.js +150 -51
- package/lib-esm/components/Modal/Modal.js.map +1 -1
- package/lib-esm/components/Notification/Notification.d.ts +46 -39
- package/lib-esm/components/Notification/Notification.js +80 -87
- package/lib-esm/components/Notification/Notification.js.map +1 -1
- package/lib-esm/components/Notification/NotificationManager.d.ts +19 -5
- package/lib-esm/components/Notification/NotificationManager.js +177 -79
- package/lib-esm/components/Notification/NotificationManager.js.map +1 -1
- package/lib-esm/components/Notification/style.d.ts +6 -3
- package/lib-esm/components/Notification/style.js +64 -140
- package/lib-esm/components/Notification/style.js.map +1 -1
- package/lib-esm/components/Notification/types.d.ts +2 -0
- package/lib-esm/components/Notification/types.js +9 -10
- package/lib-esm/components/Notification/types.js.map +1 -1
- package/lib-esm/components/Popover/Popover.d.ts +21 -20
- package/lib-esm/components/Popover/Popover.js +159 -126
- package/lib-esm/components/Popover/Popover.js.map +1 -1
- package/lib-esm/components/Spinner/Spinner.d.ts +14 -12
- package/lib-esm/components/Spinner/Spinner.js +22 -27
- package/lib-esm/components/Spinner/Spinner.js.map +1 -1
- package/lib-esm/components/Stepper/Step.d.ts +15 -12
- package/lib-esm/components/Stepper/Step.js +18 -25
- package/lib-esm/components/Stepper/Step.js.map +1 -1
- package/lib-esm/components/Stepper/Stepper.d.ts +11 -17
- package/lib-esm/components/Stepper/Stepper.js +104 -102
- package/lib-esm/components/Stepper/Stepper.js.map +1 -1
- package/lib-esm/components/Tabs/Tab.d.ts +10 -16
- package/lib-esm/components/Tabs/Tab.js +9 -15
- package/lib-esm/components/Tabs/Tab.js.map +1 -1
- package/lib-esm/components/Tabs/Tabs.d.ts +11 -22
- package/lib-esm/components/Tabs/Tabs.js +97 -55
- package/lib-esm/components/Tabs/Tabs.js.map +1 -1
- package/lib-esm/components/Toast/Toast.d.ts +34 -7
- package/lib-esm/components/Toast/Toast.js +200 -109
- package/lib-esm/components/Toast/Toast.js.map +1 -1
- package/lib-esm/components/Toast/ToastStory.d.ts +21 -24
- package/lib-esm/components/Tooltip/Tooltip.d.ts +11 -14
- package/lib-esm/components/Tooltip/Tooltip.js +52 -67
- package/lib-esm/components/Tooltip/Tooltip.js.map +1 -1
- package/lib-esm/components/index.d.ts +1 -0
- package/lib-esm/components/index.js +43 -20
- package/lib-esm/components/index.js.map +1 -1
- package/lib-esm/icons/CheckCircle.d.ts +1 -1
- package/lib-esm/icons/CheckCircle.js +22 -4
- package/lib-esm/icons/CheckCircle.js.map +1 -1
- package/lib-esm/icons/Close.d.ts +1 -1
- package/lib-esm/icons/Close.js +22 -4
- package/lib-esm/icons/Close.js.map +1 -1
- package/lib-esm/icons/DragIndicator.d.ts +1 -1
- package/lib-esm/icons/DragIndicator.js +22 -4
- package/lib-esm/icons/DragIndicator.js.map +1 -1
- package/lib-esm/icons/ErrorOutline.d.ts +1 -1
- package/lib-esm/icons/ErrorOutline.js +16 -4
- package/lib-esm/icons/ErrorOutline.js.map +1 -1
- package/lib-esm/icons/ExpandMore.d.ts +1 -1
- package/lib-esm/icons/ExpandMore.js +22 -4
- package/lib-esm/icons/ExpandMore.js.map +1 -1
- package/lib-esm/icons/FiberManualRecord.d.ts +1 -1
- package/lib-esm/icons/FiberManualRecord.js +24 -4
- package/lib-esm/icons/FiberManualRecord.js.map +1 -1
- package/lib-esm/icons/Info.d.ts +1 -1
- package/lib-esm/icons/Info.js +22 -4
- package/lib-esm/icons/Info.js.map +1 -1
- package/lib-esm/icons/ReportProblem.d.ts +1 -1
- package/lib-esm/icons/ReportProblem.js +22 -4
- package/lib-esm/icons/ReportProblem.js.map +1 -1
- package/lib-esm/shared/LayerManager.d.ts +34 -4
- package/lib-esm/shared/LayerManager.js +248 -114
- package/lib-esm/shared/LayerManager.js.map +1 -1
- package/lib-esm/shared/constants.d.ts +58 -27
- package/lib-esm/shared/constants.js +62 -26
- package/lib-esm/shared/constants.js.map +1 -1
- package/lib-esm/shared/styles.d.ts +1 -1
- package/lib-esm/shared/styles.js +21 -24
- package/lib-esm/shared/styles.js.map +1 -1
- package/package.json +130 -72
- package/lib-esm/components/Accordion/index.js +0 -3
- package/lib-esm/components/Accordion/index.js.map +0 -1
- package/lib-esm/components/Badge/index.js +0 -2
- package/lib-esm/components/Badge/index.js.map +0 -1
- package/lib-esm/components/Button/index.js +0 -6
- package/lib-esm/components/Button/index.js.map +0 -1
- package/lib-esm/components/Card/index.js +0 -3
- package/lib-esm/components/Card/index.js.map +0 -1
- package/lib-esm/components/Chip/index.js +0 -2
- package/lib-esm/components/Chip/index.js.map +0 -1
- package/lib-esm/components/Dialog/index.js +0 -5
- package/lib-esm/components/Dialog/index.js.map +0 -1
- package/lib-esm/components/DragAndDrop/index.js +0 -3
- package/lib-esm/components/DragAndDrop/index.js.map +0 -1
- package/lib-esm/components/Drawer/index.js +0 -2
- package/lib-esm/components/Drawer/index.js.map +0 -1
- package/lib-esm/components/Groups/index.js +0 -3
- package/lib-esm/components/Groups/index.js.map +0 -1
- package/lib-esm/components/Input/index.js +0 -9
- package/lib-esm/components/Input/index.js.map +0 -1
- package/lib-esm/components/Menu/index.js +0 -3
- package/lib-esm/components/Menu/index.js.map +0 -1
- package/lib-esm/components/Modal/index.js +0 -2
- package/lib-esm/components/Modal/index.js.map +0 -1
- package/lib-esm/components/Notification/index.js +0 -3
- package/lib-esm/components/Notification/index.js.map +0 -1
- package/lib-esm/components/Popover/index.js +0 -2
- package/lib-esm/components/Popover/index.js.map +0 -1
- package/lib-esm/components/Spinner/index.js +0 -2
- package/lib-esm/components/Spinner/index.js.map +0 -1
- package/lib-esm/components/Stepper/index.js +0 -4
- package/lib-esm/components/Stepper/index.js.map +0 -1
- package/lib-esm/components/Tabs/index.js +0 -3
- package/lib-esm/components/Tabs/index.js.map +0 -1
- package/lib-esm/components/Toast/ToastStory.js +0 -35
- package/lib-esm/components/Toast/ToastStory.js.map +0 -1
- package/lib-esm/components/Toast/index.js +0 -2
- package/lib-esm/components/Toast/index.js.map +0 -1
- package/lib-esm/components/Tooltip/index.js +0 -2
- package/lib-esm/components/Tooltip/index.js.map +0 -1
- package/lib-esm/icons/index.js +0 -9
- package/lib-esm/icons/index.js.map +0 -1
- package/lib-esm/index.js +0 -2
- package/lib-esm/index.js.map +0 -1
|
@@ -1,111 +1,104 @@
|
|
|
1
|
-
import { jsx
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
export class StoryProps extends React.Component {
|
|
10
|
-
render() {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
StoryProps.propTypes = {
|
|
15
|
-
/** Title of the notification */
|
|
16
|
-
title: PropTypes.string.isRequired,
|
|
17
|
-
/** Body of the notification */
|
|
18
|
-
description: PropTypes.string.isRequired,
|
|
19
|
-
/** Id for the notification, helps in de-duplication. */
|
|
20
|
-
id: PropTypes.string,
|
|
21
|
-
/** Duration for the notification in milliseconds */
|
|
22
|
-
duration: PropTypes.number,
|
|
23
|
-
/** Creates sticky notification */
|
|
24
|
-
sticky: PropTypes.bool,
|
|
25
|
-
/** Type of notification */
|
|
26
|
-
type: PropTypes.oneOf([
|
|
27
|
-
NOTIFICATION_TYPE.INFO,
|
|
28
|
-
NOTIFICATION_TYPE.SUCCESS,
|
|
29
|
-
NOTIFICATION_TYPE.WARNING,
|
|
30
|
-
NOTIFICATION_TYPE.DANGER,
|
|
31
|
-
]),
|
|
32
|
-
/** Action button text */
|
|
33
|
-
buttonText: PropTypes.string,
|
|
34
|
-
/** Action button click callback */
|
|
35
|
-
buttonClick: PropTypes.func,
|
|
36
|
-
/** Notification close callback. */
|
|
37
|
-
onClose: PropTypes.func,
|
|
38
|
-
};
|
|
39
|
-
StoryProps.defaultProps = {
|
|
40
|
-
duration: 5000,
|
|
41
|
-
sticky: false,
|
|
42
|
-
type: NOTIFICATION_TYPE.INFO,
|
|
43
|
-
};
|
|
44
|
-
/** Maps notification position to layer position */
|
|
45
|
-
const positionMap = {
|
|
1
|
+
import { jsx } from '@emotion/react/jsx-runtime';
|
|
2
|
+
import { flushSync } from 'react-dom';
|
|
3
|
+
import { createRoot } from 'react-dom/client';
|
|
4
|
+
import LayerManager, { LAYER_POSITION } from '../../shared/LayerManager.js';
|
|
5
|
+
import NotificationManager from './NotificationManager.js';
|
|
6
|
+
import { NOTIFICATION_POSITION } from './types.js';
|
|
7
|
+
|
|
8
|
+
/** Maps notification position to layer position */ const positionMap = {
|
|
46
9
|
[NOTIFICATION_POSITION.TOP_LEFT]: LAYER_POSITION.TOP_LEFT,
|
|
47
10
|
[NOTIFICATION_POSITION.TOP_RIGHT]: LAYER_POSITION.TOP_RIGHT,
|
|
48
11
|
[NOTIFICATION_POSITION.BOTTOM_LEFT]: LAYER_POSITION.BOTTOM_LEFT,
|
|
49
|
-
[NOTIFICATION_POSITION.BOTTOM_RIGHT]: LAYER_POSITION.BOTTOM_RIGHT
|
|
12
|
+
[NOTIFICATION_POSITION.BOTTOM_RIGHT]: LAYER_POSITION.BOTTOM_RIGHT
|
|
50
13
|
};
|
|
51
|
-
/** Notification class */
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/** Helps in maintaining single instance for different positions. */
|
|
55
|
-
this.containers = new Map();
|
|
14
|
+
/** Notification class */ class Notification {
|
|
15
|
+
constructor(){
|
|
16
|
+
/** Helps in maintaining single instance for different positions. */ this.containers = new Map();
|
|
56
17
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let notification;
|
|
18
|
+
* Adds a notification
|
|
19
|
+
*
|
|
20
|
+
* @param position - The position where the notification should appear
|
|
21
|
+
* @param options - Configuration options for the notification
|
|
22
|
+
* @returns The notification ID or a promise that resolves to the notification ID
|
|
23
|
+
*/ this.add = (position, options, ariaLabel = 'Notifications')=>{
|
|
64
24
|
if (!this.containers.has(position)) {
|
|
65
|
-
|
|
66
|
-
|
|
25
|
+
/** Callback ref to capture the NotificationManager instance when it mounts */ const refCallback = (instance)=>{
|
|
26
|
+
if (instance) {
|
|
27
|
+
const container = this.containers.get(position);
|
|
28
|
+
if (container) {
|
|
29
|
+
container.manager = instance;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
67
33
|
const [Component] = LayerManager.renderLayer({
|
|
68
34
|
closeOnEsc: false,
|
|
69
35
|
closeOnOverlayClick: false,
|
|
70
36
|
position: positionMap[position],
|
|
71
37
|
alwaysOnTop: true,
|
|
72
|
-
component: (
|
|
38
|
+
component: /*#__PURE__*/ jsx(NotificationManager, {
|
|
39
|
+
ref: refCallback,
|
|
40
|
+
position: position,
|
|
41
|
+
onEmpty: ()=>this.destroy(position),
|
|
42
|
+
ariaLabel: ariaLabel
|
|
43
|
+
})
|
|
73
44
|
});
|
|
45
|
+
// Create a div to mount the Component
|
|
46
|
+
const div = document.createElement('div');
|
|
47
|
+
document.body.appendChild(div);
|
|
48
|
+
const root = createRoot(div);
|
|
74
49
|
this.containers.set(position, {
|
|
75
|
-
|
|
76
|
-
|
|
50
|
+
manager: null,
|
|
51
|
+
root,
|
|
52
|
+
div
|
|
53
|
+
});
|
|
54
|
+
// Render the Component which will trigger the LayerManager's useEffect
|
|
55
|
+
flushSync(()=>{
|
|
56
|
+
root.render(/*#__PURE__*/ jsx(Component, {}));
|
|
77
57
|
});
|
|
78
|
-
ReactDOM.render(_jsx(Component, {}), div);
|
|
79
|
-
notification = ref;
|
|
80
58
|
}
|
|
81
|
-
|
|
82
|
-
|
|
59
|
+
const container = this.containers.get(position);
|
|
60
|
+
if (container && container.manager) {
|
|
61
|
+
return container.manager.add(options);
|
|
83
62
|
}
|
|
84
|
-
|
|
63
|
+
// If manager is not ready yet, wait a bit and retry
|
|
64
|
+
return new Promise((resolve)=>{
|
|
65
|
+
setTimeout(()=>{
|
|
66
|
+
const container = this.containers.get(position);
|
|
67
|
+
if (container && container.manager) {
|
|
68
|
+
resolve(container.manager.add(options));
|
|
69
|
+
}
|
|
70
|
+
}, 10);
|
|
71
|
+
});
|
|
85
72
|
};
|
|
86
73
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
|
|
74
|
+
* Removes a notification
|
|
75
|
+
*
|
|
76
|
+
* @param position - The position of the notification container
|
|
77
|
+
* @param id - The unique ID of the notification to remove
|
|
78
|
+
*/ this.remove = (position, id)=>{
|
|
79
|
+
const container = this.containers.get(position);
|
|
80
|
+
if (container && container.manager) {
|
|
81
|
+
container.manager.remove(id);
|
|
95
82
|
}
|
|
96
83
|
};
|
|
97
84
|
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
85
|
+
* Destroys entire stack of notifications at a position.
|
|
86
|
+
* Unmounts the React root and cleans up DOM elements.
|
|
87
|
+
*
|
|
88
|
+
* @param position - The position of the notification container to destroy
|
|
89
|
+
*/ this.destroy = (position)=>{
|
|
90
|
+
const container = this.containers.get(position);
|
|
91
|
+
if (container) {
|
|
92
|
+
container.root.unmount();
|
|
93
|
+
if (document.body.contains(container.div)) {
|
|
94
|
+
document.body.removeChild(container.div);
|
|
95
|
+
}
|
|
96
|
+
this.containers.delete(position);
|
|
97
|
+
}
|
|
106
98
|
};
|
|
107
99
|
}
|
|
108
100
|
}
|
|
109
|
-
/** Export a singleton instance */
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
/** Export a singleton instance */ var Notification_default = new Notification();
|
|
102
|
+
|
|
103
|
+
export { Notification_default as default };
|
|
104
|
+
//# sourceMappingURL=Notification.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Notification.js","
|
|
1
|
+
{"version":3,"file":"Notification.js","sources":["../../../src/components/Notification/Notification.tsx"],"sourcesContent":["import { type RefCallback } from 'react';\nimport { flushSync } from 'react-dom';\nimport { createRoot, type Root } from 'react-dom/client';\nimport LayerManager, { LAYER_POSITION } from '../../shared/LayerManager';\nimport NotificationManager from './NotificationManager';\nimport { NOTIFICATION_POSITION, NOTIFICATION_TYPE, NotificationOptions } from './types';\n\ntype NotificationProps = {\n /** Title of the notification */\n title: string;\n /** Body of the notification */\n description: string;\n /** Id for the notification, helps in de-duplication. */\n id?: string;\n /**\n * Duration for the notification in milliseconds\n * @default 5000\n */\n duration?: number;\n /**\n * Creates sticky notification\n * @default false\n */\n sticky?: boolean;\n /**\n * Type of notification\n * @default NOTIFICATION_TYPE.INFO\n */\n type?: NOTIFICATION_TYPE;\n /** Action button text */\n buttonText?: string;\n /** Action button click callback */\n buttonClick?: () => void;\n /** Notification close callback. */\n onClose?: () => void;\n /** Aria label for the close button on the notification. Defaults to \"Close notification\" */\n closeButtonAriaLabel?: string;\n};\n\n/**\n * This dummy component is used to extract props for documentation in Storybook.\n * @param props\n * @returns\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function StoryProps(props: NotificationProps) {\n return null;\n}\n\n/** Maps notification position to layer position */\nconst positionMap = {\n [NOTIFICATION_POSITION.TOP_LEFT]: LAYER_POSITION.TOP_LEFT,\n [NOTIFICATION_POSITION.TOP_RIGHT]: LAYER_POSITION.TOP_RIGHT,\n [NOTIFICATION_POSITION.BOTTOM_LEFT]: LAYER_POSITION.BOTTOM_LEFT,\n [NOTIFICATION_POSITION.BOTTOM_RIGHT]: LAYER_POSITION.BOTTOM_RIGHT,\n};\n\n/** Notification class */\nclass Notification {\n /** Helps in maintaining single instance for different positions. */\n private containers: Map<\n NOTIFICATION_POSITION,\n {\n manager: NotificationManager | null;\n root: Root;\n div: HTMLDivElement;\n }\n > = new Map();\n\n /**\n * Adds a notification\n *\n * @param position - The position where the notification should appear\n * @param options - Configuration options for the notification\n * @returns The notification ID or a promise that resolves to the notification ID\n */\n public add = (\n position: NOTIFICATION_POSITION,\n options: NotificationOptions,\n ariaLabel: string = 'Notifications',\n ) => {\n if (!this.containers.has(position)) {\n /** Callback ref to capture the NotificationManager instance when it mounts */\n const refCallback: RefCallback<NotificationManager> = (instance) => {\n if (instance) {\n const container = this.containers.get(position);\n if (container) {\n container.manager = instance;\n }\n }\n };\n\n const [Component] = LayerManager.renderLayer({\n closeOnEsc: false,\n closeOnOverlayClick: false,\n position: positionMap[position],\n alwaysOnTop: true,\n component: (\n <NotificationManager\n ref={refCallback}\n position={position}\n onEmpty={() => this.destroy(position)}\n ariaLabel={ariaLabel}\n />\n ),\n });\n\n // Create a div to mount the Component\n const div = document.createElement('div');\n document.body.appendChild(div);\n const root = createRoot(div);\n\n this.containers.set(position, {\n manager: null,\n root,\n div,\n });\n\n // Render the Component which will trigger the LayerManager's useEffect\n flushSync(() => {\n root.render(<Component />);\n });\n }\n\n const container = this.containers.get(position);\n if (container && container.manager) {\n return container.manager.add(options);\n }\n\n // If manager is not ready yet, wait a bit and retry\n return new Promise<string>((resolve) => {\n setTimeout(() => {\n const container = this.containers.get(position);\n if (container && container.manager) {\n resolve(container.manager.add(options));\n }\n }, 10);\n });\n };\n\n /**\n * Removes a notification\n *\n * @param position - The position of the notification container\n * @param id - The unique ID of the notification to remove\n */\n public remove = (position: NOTIFICATION_POSITION, id: string) => {\n const container = this.containers.get(position);\n if (container && container.manager) {\n container.manager.remove(id);\n }\n };\n\n /**\n * Destroys entire stack of notifications at a position.\n * Unmounts the React root and cleans up DOM elements.\n *\n * @param position - The position of the notification container to destroy\n */\n public destroy = (position: NOTIFICATION_POSITION) => {\n const container = this.containers.get(position);\n if (container) {\n container.root.unmount();\n if (document.body.contains(container.div)) {\n document.body.removeChild(container.div);\n }\n this.containers.delete(position);\n }\n };\n}\n\n/** Export a singleton instance */\nexport default new Notification();\n"],"names":["positionMap","NOTIFICATION_POSITION","TOP_LEFT","LAYER_POSITION","TOP_RIGHT","BOTTOM_LEFT","BOTTOM_RIGHT","Notification","containers","Map","add","position","options","ariaLabel","has","refCallback","instance","container","get","manager","Component","LayerManager","renderLayer","closeOnEsc","closeOnOverlayClick","alwaysOnTop","component","_jsx","NotificationManager","ref","onEmpty","destroy","div","document","createElement","body","appendChild","root","createRoot","set","flushSync","render","Promise","resolve","setTimeout","remove","id","unmount","contains","removeChild","delete"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { NOTIFICATION_POSITION, NotificationOptions } from './types';
|
|
|
3
3
|
interface NotificationManagerProps {
|
|
4
4
|
position: NOTIFICATION_POSITION;
|
|
5
5
|
onEmpty: () => void;
|
|
6
|
+
ariaLabel?: string;
|
|
6
7
|
}
|
|
7
8
|
interface NoticeProp extends NotificationOptions {
|
|
8
9
|
leaving?: boolean;
|
|
@@ -17,36 +18,49 @@ declare class NotificationManager extends React.Component<NotificationManagerPro
|
|
|
17
18
|
state: NotificationManagerState;
|
|
18
19
|
private timeouts;
|
|
19
20
|
private set;
|
|
21
|
+
private politeRegionRef;
|
|
22
|
+
private assertiveRegionRef;
|
|
20
23
|
/**
|
|
21
24
|
* Removes a notification from stack if the notification with the given id is found.
|
|
22
25
|
*
|
|
23
26
|
* @param id
|
|
24
27
|
*/
|
|
25
|
-
remove: (id
|
|
28
|
+
remove: (id?: string) => void;
|
|
26
29
|
/**
|
|
27
30
|
* Adds a notification to stack.
|
|
28
31
|
*
|
|
29
32
|
* @param notice
|
|
30
33
|
*/
|
|
31
|
-
add: (notice: NotificationOptions) => string
|
|
34
|
+
add: (notice: NotificationOptions) => Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Update live region content with clear-then-set pattern for reliable VoiceOver announcements.
|
|
37
|
+
*
|
|
38
|
+
* @param content - The text content to announce
|
|
39
|
+
* @param isAssertive - Whether to use assertive (alert) or polite (log) live region
|
|
40
|
+
*/
|
|
41
|
+
private updateLiveRegion;
|
|
32
42
|
/**
|
|
33
43
|
* Handler for close button click.
|
|
34
44
|
*
|
|
35
45
|
* @param id
|
|
36
46
|
*/
|
|
37
|
-
closeClickHandler: (id
|
|
47
|
+
closeClickHandler: (id?: string) => () => void;
|
|
38
48
|
/**
|
|
39
49
|
* Pause notification when user is hovering over it.
|
|
40
50
|
*
|
|
41
51
|
* @param id
|
|
42
52
|
*/
|
|
43
|
-
pause: (id
|
|
53
|
+
pause: (id?: string) => () => void;
|
|
44
54
|
/**
|
|
45
55
|
* Restart the removal of notification.
|
|
46
56
|
*
|
|
47
57
|
* @param id
|
|
48
58
|
*/
|
|
49
|
-
resume: (id
|
|
59
|
+
resume: (id?: string) => () => void;
|
|
60
|
+
/**
|
|
61
|
+
* Clean up all pending timeouts when component unmounts
|
|
62
|
+
*/
|
|
63
|
+
componentWillUnmount(): void;
|
|
50
64
|
render(): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
51
65
|
}
|
|
52
66
|
export default NotificationManager;
|
|
@@ -1,52 +1,137 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs, jsx } from '@emotion/react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
3
|
+
import { Container, VisuallyHidden, Notice, IconContainer, FillParent, Title, Body, Footer, CloseButton } from './style.js';
|
|
4
|
+
import { NOTIFICATION_TYPE } from './types.js';
|
|
5
|
+
import CheckCircle from '../../icons/Info.js';
|
|
6
|
+
import CheckCircle$1 from '../../icons/CheckCircle.js';
|
|
7
|
+
import CheckCircle$2 from '../../icons/ReportProblem.js';
|
|
8
|
+
import CheckCircle$3 from '../../icons/ErrorOutline.js';
|
|
9
|
+
import ActionButton from '../Button/ActionButton.js';
|
|
10
|
+
import Close from '../../icons/Close.js';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_DURATION$1 = 5000;
|
|
8
13
|
/**
|
|
9
14
|
* Notification Manager class
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
*/ class NotificationManager extends React.Component {
|
|
16
|
+
/**
|
|
17
|
+
* Clean up all pending timeouts when component unmounts
|
|
18
|
+
*/ componentWillUnmount() {
|
|
19
|
+
// Clear all pending timeouts
|
|
20
|
+
Object.keys(this.timeouts).forEach((id)=>{
|
|
21
|
+
clearTimeout(this.timeouts[id]);
|
|
22
|
+
});
|
|
18
23
|
this.timeouts = {};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
this.set.clear();
|
|
25
|
+
}
|
|
26
|
+
render() {
|
|
27
|
+
return /*#__PURE__*/ jsxs(Container, {
|
|
28
|
+
position: this.props.position,
|
|
29
|
+
children: [
|
|
30
|
+
/*#__PURE__*/ jsx(VisuallyHidden, {
|
|
31
|
+
ref: this.politeRegionRef,
|
|
32
|
+
role: "log",
|
|
33
|
+
"aria-live": "polite",
|
|
34
|
+
"aria-atomic": "false",
|
|
35
|
+
"aria-relevant": "additions text"
|
|
36
|
+
}),
|
|
37
|
+
/*#__PURE__*/ jsx(VisuallyHidden, {
|
|
38
|
+
ref: this.assertiveRegionRef,
|
|
39
|
+
role: "alert",
|
|
40
|
+
"aria-live": "assertive",
|
|
41
|
+
"aria-atomic": "true"
|
|
42
|
+
}),
|
|
43
|
+
/*#__PURE__*/ jsx("div", {
|
|
44
|
+
role: "list",
|
|
45
|
+
"aria-label": this.props.ariaLabel,
|
|
46
|
+
children: this.state.notices.map((notice)=>{
|
|
47
|
+
const { id, title, description, leaving, type = NOTIFICATION_TYPE.INFO, buttonText, buttonClick, closeButtonAriaLabel } = notice;
|
|
48
|
+
return /*#__PURE__*/ jsxs(Notice, {
|
|
49
|
+
...notice,
|
|
50
|
+
position: this.props.position,
|
|
51
|
+
className: leaving ? 'leave' : '',
|
|
52
|
+
onMouseEnter: this.pause(id),
|
|
53
|
+
onMouseLeave: this.resume(id),
|
|
54
|
+
role: "listitem",
|
|
55
|
+
children: [
|
|
56
|
+
/*#__PURE__*/ jsxs(IconContainer, {
|
|
57
|
+
type: type,
|
|
58
|
+
"aria-hidden": "true",
|
|
59
|
+
children: [
|
|
60
|
+
type === NOTIFICATION_TYPE.INFO && /*#__PURE__*/ jsx(CheckCircle, {}),
|
|
61
|
+
type === NOTIFICATION_TYPE.SUCCESS && /*#__PURE__*/ jsx(CheckCircle$1, {}),
|
|
62
|
+
type === NOTIFICATION_TYPE.WARNING && /*#__PURE__*/ jsx(CheckCircle$2, {}),
|
|
63
|
+
type === NOTIFICATION_TYPE.DANGER && /*#__PURE__*/ jsx(CheckCircle$3, {})
|
|
64
|
+
]
|
|
65
|
+
}),
|
|
66
|
+
/*#__PURE__*/ jsxs(FillParent, {
|
|
67
|
+
children: [
|
|
68
|
+
/*#__PURE__*/ jsx(Title, {
|
|
69
|
+
type: type,
|
|
70
|
+
children: title
|
|
71
|
+
}),
|
|
72
|
+
/*#__PURE__*/ jsx(Body, {
|
|
73
|
+
children: description
|
|
74
|
+
}),
|
|
75
|
+
buttonText && /*#__PURE__*/ jsx(Footer, {
|
|
76
|
+
children: /*#__PURE__*/ jsx(ActionButton, {
|
|
77
|
+
onClick: ()=>{
|
|
78
|
+
buttonClick?.();
|
|
79
|
+
},
|
|
80
|
+
children: buttonText
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
]
|
|
84
|
+
}),
|
|
85
|
+
/*#__PURE__*/ jsx(CloseButton, {
|
|
86
|
+
onClick: this.closeClickHandler(id),
|
|
87
|
+
"aria-label": closeButtonAriaLabel || 'Close notification',
|
|
88
|
+
tabIndex: 0,
|
|
89
|
+
children: /*#__PURE__*/ jsx(Close, {})
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
}, id);
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
]
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
constructor(...args){
|
|
99
|
+
super(...args), this.state = {
|
|
100
|
+
notices: []
|
|
101
|
+
}, // bookkeeping for timeouts
|
|
102
|
+
this.timeouts = {}, // Set of notification ids
|
|
103
|
+
this.set = new Set(), // Refs for live regions to ensure they exist before updates
|
|
104
|
+
this.politeRegionRef = /*#__PURE__*/ React.createRef(), this.assertiveRegionRef = /*#__PURE__*/ React.createRef(), /**
|
|
105
|
+
* Removes a notification from stack if the notification with the given id is found.
|
|
106
|
+
*
|
|
107
|
+
* @param id
|
|
108
|
+
*/ this.remove = (id)=>{
|
|
109
|
+
if (!id) return;
|
|
27
110
|
// Trigger leaving animation.
|
|
28
111
|
this.setState({
|
|
29
|
-
notices: this.state.notices.map(notice
|
|
112
|
+
notices: this.state.notices.map((notice)=>({
|
|
113
|
+
...notice,
|
|
114
|
+
leaving: notice.id === id ? true : notice.leaving
|
|
115
|
+
}))
|
|
30
116
|
});
|
|
31
117
|
this.set.delete(id);
|
|
32
118
|
// Remove notification on animation completion.
|
|
33
|
-
setTimeout(()
|
|
34
|
-
const notice = this.state.notices.find(notice
|
|
119
|
+
setTimeout(()=>{
|
|
120
|
+
const notice = this.state.notices.find((notice)=>notice.id === id);
|
|
35
121
|
if (notice) {
|
|
36
122
|
// call close callback, ignore any errors in callback.
|
|
37
123
|
if (notice.onClose) {
|
|
38
124
|
try {
|
|
39
125
|
notice.onClose();
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
126
|
+
} catch (e) {
|
|
42
127
|
console.warn('Error in notification close callback', e.message);
|
|
43
128
|
}
|
|
44
129
|
}
|
|
45
130
|
// Remove the notification
|
|
46
131
|
this.setState({
|
|
47
|
-
notices: this.state.notices.filter(notice
|
|
48
|
-
}, ()
|
|
49
|
-
// Check if the stack is empty and then call the
|
|
132
|
+
notices: this.state.notices.filter((notice)=>notice.id !== id)
|
|
133
|
+
}, ()=>{
|
|
134
|
+
// Check if the stack is empty and then call the
|
|
50
135
|
// empty callback function.
|
|
51
136
|
if (this.state.notices.length === 0) {
|
|
52
137
|
this.props.onEmpty();
|
|
@@ -54,67 +139,80 @@ class NotificationManager extends React.Component {
|
|
|
54
139
|
});
|
|
55
140
|
}
|
|
56
141
|
}, 550);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*/
|
|
63
|
-
this.add = (notice) => {
|
|
142
|
+
}, /**
|
|
143
|
+
* Adds a notification to stack.
|
|
144
|
+
*
|
|
145
|
+
* @param notice
|
|
146
|
+
*/ this.add = async (notice)=>{
|
|
64
147
|
// Generate unique id if not provided.
|
|
65
|
-
const id = notice.id || (Math.random() *
|
|
148
|
+
const id = notice.id || (Math.random() * 10 ** 7).toFixed(0);
|
|
66
149
|
// De-dupe on id
|
|
67
150
|
if (!this.set.has(id)) {
|
|
151
|
+
const type = notice.type || NOTIFICATION_TYPE.INFO;
|
|
152
|
+
const isUrgent = type === NOTIFICATION_TYPE.WARNING || type === NOTIFICATION_TYPE.DANGER;
|
|
68
153
|
// Add notice to the top of stack.
|
|
69
|
-
this.setState({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
154
|
+
this.setState((prevState)=>({
|
|
155
|
+
notices: [
|
|
156
|
+
{
|
|
157
|
+
...notice,
|
|
158
|
+
id
|
|
159
|
+
},
|
|
160
|
+
...prevState.notices
|
|
161
|
+
]
|
|
162
|
+
}), ()=>{
|
|
163
|
+
// Update live region after state update
|
|
164
|
+
const announcement = `${notice.title} ${notice.description}`;
|
|
165
|
+
this.updateLiveRegion(announcement, isUrgent);
|
|
74
166
|
});
|
|
75
167
|
// set timeout for closing the notification.
|
|
76
168
|
if (!notice.sticky) {
|
|
77
|
-
this.timeouts[id] = setTimeout(()
|
|
169
|
+
this.timeouts[id] = setTimeout(()=>this.remove(id), notice.duration || DEFAULT_DURATION$1);
|
|
78
170
|
}
|
|
79
171
|
// Add id to the set.
|
|
80
172
|
this.set.add(id);
|
|
81
173
|
}
|
|
82
174
|
return id;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
this.pause = (id) => () => {
|
|
98
|
-
clearTimeout(this.timeouts[id]);
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Restart the removal of notification.
|
|
102
|
-
*
|
|
103
|
-
* @param id
|
|
104
|
-
*/
|
|
105
|
-
this.resume = (id) => () => {
|
|
106
|
-
const notice = this.state.notices.find(notice => notice.id === id);
|
|
107
|
-
if (!notice.sticky) {
|
|
108
|
-
this.timeouts[id] = setTimeout(() => this.remove(id), DEFAULT_DURATION);
|
|
175
|
+
}, /**
|
|
176
|
+
* Update live region content with clear-then-set pattern for reliable VoiceOver announcements.
|
|
177
|
+
*
|
|
178
|
+
* @param content - The text content to announce
|
|
179
|
+
* @param isAssertive - Whether to use assertive (alert) or polite (log) live region
|
|
180
|
+
*/ this.updateLiveRegion = (content, isAssertive)=>{
|
|
181
|
+
const region = isAssertive ? this.assertiveRegionRef.current : this.politeRegionRef.current;
|
|
182
|
+
if (region) {
|
|
183
|
+
// Add content after delay
|
|
184
|
+
setTimeout(()=>{
|
|
185
|
+
if (region) {
|
|
186
|
+
region.textContent = content;
|
|
187
|
+
}
|
|
188
|
+
}, 150);
|
|
109
189
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
190
|
+
}, /**
|
|
191
|
+
* Handler for close button click.
|
|
192
|
+
*
|
|
193
|
+
* @param id
|
|
194
|
+
*/ this.closeClickHandler = (id)=>()=>{
|
|
195
|
+
this.remove(id);
|
|
196
|
+
}, /**
|
|
197
|
+
* Pause notification when user is hovering over it.
|
|
198
|
+
*
|
|
199
|
+
* @param id
|
|
200
|
+
*/ this.pause = (id)=>()=>{
|
|
201
|
+
if (id && this.timeouts[id]) {
|
|
202
|
+
clearTimeout(this.timeouts[id]);
|
|
203
|
+
}
|
|
204
|
+
}, /**
|
|
205
|
+
* Restart the removal of notification.
|
|
206
|
+
*
|
|
207
|
+
* @param id
|
|
208
|
+
*/ this.resume = (id)=>()=>{
|
|
209
|
+
const notice = this.state.notices.find((notice)=>notice.id === id);
|
|
210
|
+
if (!notice?.sticky && id && !this.timeouts[id]) {
|
|
211
|
+
this.timeouts[id] = setTimeout(()=>this.remove(id), DEFAULT_DURATION$1);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
117
214
|
}
|
|
118
215
|
}
|
|
119
|
-
|
|
120
|
-
|
|
216
|
+
|
|
217
|
+
export { NotificationManager as default };
|
|
218
|
+
//# sourceMappingURL=NotificationManager.js.map
|