@genesislcap/foundation-notifications 14.400.0 → 14.401.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.
Files changed (43) hide show
  1. package/dist/dts/container/index.d.ts +3 -0
  2. package/dist/dts/container/index.d.ts.map +1 -0
  3. package/dist/dts/container/notify-container-builder.d.ts +9 -0
  4. package/dist/dts/container/notify-container-builder.d.ts.map +1 -0
  5. package/dist/dts/container/notify-container.d.ts +41 -0
  6. package/dist/dts/container/notify-container.d.ts.map +1 -0
  7. package/dist/dts/container/notify-container.styles.d.ts +2 -0
  8. package/dist/dts/container/notify-container.styles.d.ts.map +1 -0
  9. package/dist/dts/container/notify-container.template.d.ts +3 -0
  10. package/dist/dts/container/notify-container.template.d.ts.map +1 -0
  11. package/dist/dts/index.d.ts +1 -0
  12. package/dist/dts/index.d.ts.map +1 -1
  13. package/dist/dts/toast/toast-launcher.d.ts.map +1 -1
  14. package/dist/esm/container/index.js +2 -0
  15. package/dist/esm/container/notify-container-builder.js +29 -0
  16. package/dist/esm/container/notify-container.js +129 -0
  17. package/dist/esm/container/notify-container.styles.js +211 -0
  18. package/dist/esm/container/notify-container.template.js +33 -0
  19. package/dist/esm/index.js +1 -0
  20. package/dist/esm/toast/toast-launcher.js +39 -30
  21. package/dist/foundation-notifications.api.json +559 -0
  22. package/dist/foundation-notifications.d.ts +49 -0
  23. package/docs/api/foundation-notifications.configurenotifications.md +52 -0
  24. package/docs/api/foundation-notifications.md +29 -0
  25. package/docs/api/foundation-notifications.notifycontainer.allowcloseall.md +11 -0
  26. package/docs/api/foundation-notifications.notifycontainer.allowmanualcollapse.md +11 -0
  27. package/docs/api/foundation-notifications.notifycontainer.designsystemprefix.md +11 -0
  28. package/docs/api/foundation-notifications.notifycontainer.disconnectedcallback.md +15 -0
  29. package/docs/api/foundation-notifications.notifycontainer.md +208 -0
  30. package/docs/api/foundation-notifications.notifycontainer.position.md +11 -0
  31. package/docs/api/foundation-notifications.notifycontainer.showcount.md +11 -0
  32. package/docs/api/foundation-notifications.notifycontainer.slottednodes.md +11 -0
  33. package/docs/api/foundation-notifications.notifycontainer.stackcollapsed.md +11 -0
  34. package/docs/api/foundation-notifications.notifycontainer.stackthreshold.md +11 -0
  35. package/docs/api/foundation-notifications.notifycontainerconfig.allowcloseall.md +11 -0
  36. package/docs/api/foundation-notifications.notifycontainerconfig.allowmanualcollapse.md +11 -0
  37. package/docs/api/foundation-notifications.notifycontainerconfig.designsystemprefix.md +11 -0
  38. package/docs/api/foundation-notifications.notifycontainerconfig.md +139 -0
  39. package/docs/api/foundation-notifications.notifycontainerconfig.position.md +11 -0
  40. package/docs/api/foundation-notifications.notifycontainerconfig.showcount.md +11 -0
  41. package/docs/api/foundation-notifications.notifycontainerconfig.stackthreshold.md +11 -0
  42. package/docs/api-report.md.api.md +52 -0
  43. package/package.json +12 -11
@@ -0,0 +1,3 @@
1
+ export * from './notify-container';
2
+ export * from './notify-container-builder';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/container/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { NotifyContainerConfig } from './notify-container';
2
+ /**
3
+ * Configures a `notify-container` component used to opt-into new behaviours for toast notifications such as stacking
4
+ * You can have a `notify-container` in each of the four corners of the screen.
5
+ * If you call this function for a `ToastPosition` and it does not yet exist then this function
6
+ * will create one. If it already exists then this will override its config
7
+ */
8
+ export declare const configureNotifications: (config: Partial<NotifyContainerConfig>) => void;
9
+ //# sourceMappingURL=notify-container-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-container-builder.d.ts","sourceRoot":"","sources":["../../../src/container/notify-container-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI5E;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,QAAQ,OAAO,CAAC,qBAAqB,CAAC,KAAG,IAwB/E,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { GenesisElement } from '@genesislcap/web-core';
2
+ import { ToastPosition } from '../types';
3
+ export interface NotifyContainerConfig {
4
+ position: ToastPosition;
5
+ stackThreshold: number;
6
+ allowManualCollapse: boolean;
7
+ allowCloseAll: boolean;
8
+ designSystemPrefix: string;
9
+ showCount: boolean;
10
+ }
11
+ export declare class NotifyContainer extends GenesisElement implements NotifyContainerConfig {
12
+ position: ToastPosition;
13
+ stackThreshold: number;
14
+ allowManualCollapse: boolean;
15
+ allowCloseAll: boolean;
16
+ designSystemPrefix: string;
17
+ showCount: boolean;
18
+ stackCollapsed: boolean;
19
+ private manuallyExpanded;
20
+ private routeSubscriber;
21
+ /** @internal */
22
+ connectedCallback(): void;
23
+ disconnectedCallback(): void;
24
+ private checkRoute;
25
+ slottedNodes: Node[];
26
+ /** @internal */
27
+ slottedNodesChanged(): void;
28
+ /** @internal */
29
+ handleContainerClick(): void;
30
+ /** @internal */
31
+ handleToggleCollapse(): void;
32
+ /** @internal */
33
+ handleCloseAll(): void;
34
+ /**
35
+ * Manages the absolute positioning of notifications to enable smooth stack-to-list animations.
36
+ * Uses a batch read/write pattern to avoid layout thrashing.
37
+ * @internal
38
+ */
39
+ private handlePosition;
40
+ }
41
+ //# sourceMappingURL=notify-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-container.d.ts","sourceRoot":"","sources":["../../../src/container/notify-container.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,cAAc,EAA0B,MAAM,uBAAuB,CAAC;AAEpG,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;CACpB;AAID,qBAKa,eAAgB,SAAQ,cAAe,YAAW,qBAAqB;IAC5E,QAAQ,EAAE,aAAa,CAAe;IACJ,cAAc,EAAE,MAAM,CAAqB;IACpB,mBAAmB,EAAE,OAAO,CACpF;IACkD,aAAa,EAAE,OAAO,CAAQ;IAC1C,kBAAkB,EAAE,MAAM,CAAW;IAC9B,SAAS,EAAE,OAAO,CAAQ;IAErB,cAAc,EAAE,OAAO,CAAS;IAEzF,OAAO,CAAC,gBAAgB,CAAkB;IAE1C,OAAO,CAAC,eAAe,CAErB;IAEF,gBAAgB;IAChB,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;IAK5B,OAAO,CAAC,UAAU;IAMN,YAAY,EAAE,IAAI,EAAE,CAAM;IACtC,gBAAgB;IAChB,mBAAmB;IAiBnB,gBAAgB;IAChB,oBAAoB;IAOpB,gBAAgB;IAChB,oBAAoB;IAKpB,gBAAgB;IAChB,cAAc;IAQd;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAsBvB"}
@@ -0,0 +1,2 @@
1
+ export declare const styles: import("@microsoft/fast-element").ElementStyles;
2
+ //# sourceMappingURL=notify-container.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-container.styles.d.ts","sourceRoot":"","sources":["../../../src/container/notify-container.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,iDAiNlB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NotifyContainer } from './notify-container';
2
+ export declare const template: import("@microsoft/fast-element").ViewTemplate<NotifyContainer, any>;
3
+ //# sourceMappingURL=notify-container.template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-container.template.d.ts","sourceRoot":"","sources":["../../../src/container/notify-container.template.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAoCrD,eAAO,MAAM,QAAQ,sEAUpB,CAAC"}
@@ -3,6 +3,7 @@ export * from './banner';
3
3
  export * from './dialog';
4
4
  export * from './snackbar';
5
5
  export * from './toast';
6
+ export * from './container';
6
7
  export * from './notification-builder';
7
8
  export * from './notification-launcher';
8
9
  export * from './notification-util';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"toast-launcher.d.ts","sourceRoot":"","sources":["../../../src/toast/toast-launcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;;;;;KAOK;AACL,eAAO,MAAM,SAAS,GACpB,uBAAuB,qBAAqB,EAC5C,SAAS,MAAM,EACf,wBAAwB,WAAW,KAClC,IA6FF,CAAC"}
1
+ {"version":3,"file":"toast-launcher.d.ts","sourceRoot":"","sources":["../../../src/toast/toast-launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAiB,MAAM,UAAU,CAAC;AAiChE;;;;;;;KAOK;AACL,eAAO,MAAM,SAAS,GACpB,uBAAuB,qBAAqB,EAC5C,SAAS,MAAM,EACf,wBAAwB,WAAW,KAClC,IAgFF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './notify-container';
2
+ export * from './notify-container-builder';
@@ -0,0 +1,29 @@
1
+ import { getCurrentDesignSystem } from '@genesislcap/foundation-utils';
2
+ import { NotifyContainer } from './notify-container';
3
+ NotifyContainer;
4
+ /**
5
+ * Configures a `notify-container` component used to opt-into new behaviours for toast notifications such as stacking
6
+ * You can have a `notify-container` in each of the four corners of the screen.
7
+ * If you call this function for a `ToastPosition` and it does not yet exist then this function
8
+ * will create one. If it already exists then this will override its config
9
+ */
10
+ export const configureNotifications = (config) => {
11
+ // TODO: we can support this later
12
+ if (config.position === 'bottom-left' || config.position === 'bottom-right') {
13
+ throw new Error("NotifyContainer doesn't currently support bottom corner placements");
14
+ }
15
+ const { element: providerElement } = getCurrentDesignSystem(document.body, 'rapid');
16
+ if (!providerElement) {
17
+ // TODO: later we can make this more robust
18
+ throw new Error('Cannot find design system provider');
19
+ }
20
+ const mExistingContainer = Array.from(providerElement.querySelectorAll('notify-container')).find((elem) => { var _a; return elem.position === ((_a = config === null || config === void 0 ? void 0 : config.position) !== null && _a !== void 0 ? _a : 'top-right'); });
21
+ const container = (() => {
22
+ if (mExistingContainer)
23
+ return mExistingContainer;
24
+ const newContainer = document.createElement('notify-container');
25
+ providerElement.appendChild(newContainer);
26
+ return newContainer;
27
+ })();
28
+ Object.entries(config).forEach(([k, v]) => (container[k] = v));
29
+ };
@@ -0,0 +1,129 @@
1
+ import { __decorate } from "tslib";
2
+ import { RouteUtil } from '@genesislcap/foundation-utils';
3
+ import { attr, customElement, GenesisElement, observable, Observable } from '@genesislcap/web-core';
4
+ import { logger } from '../logger';
5
+ import { styles } from './notify-container.styles';
6
+ import { template } from './notify-container.template';
7
+ const DEFAULT_THRESHOLD = 5;
8
+ let NotifyContainer = class NotifyContainer extends GenesisElement {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.position = 'top-right';
12
+ this.stackThreshold = DEFAULT_THRESHOLD;
13
+ this.allowManualCollapse = true;
14
+ this.allowCloseAll = true;
15
+ this.designSystemPrefix = 'rapid';
16
+ this.showCount = true;
17
+ this.stackCollapsed = false;
18
+ this.manuallyExpanded = false;
19
+ this.routeSubscriber = {
20
+ handleChange: () => this.checkRoute(RouteUtil.shared.pathName),
21
+ };
22
+ this.slottedNodes = [];
23
+ }
24
+ /** @internal */
25
+ connectedCallback() {
26
+ super.connectedCallback();
27
+ if (this.position === 'bottom-left' || this.position === 'bottom-right') {
28
+ logger.error("NotifyContainer doesn't currently support bottom corner placements");
29
+ }
30
+ Observable.getNotifier(RouteUtil.shared).subscribe(this.routeSubscriber, 'pathName');
31
+ this.checkRoute(RouteUtil.shared.pathName);
32
+ }
33
+ disconnectedCallback() {
34
+ super.disconnectedCallback();
35
+ Observable.getNotifier(RouteUtil.shared).unsubscribe(this.routeSubscriber, 'pathName');
36
+ }
37
+ checkRoute(path) {
38
+ if (path.includes('/login') || path.includes('/logout')) {
39
+ this.handleCloseAll();
40
+ }
41
+ }
42
+ /** @internal */
43
+ slottedNodesChanged() {
44
+ if (!this.manuallyExpanded &&
45
+ !this.stackCollapsed &&
46
+ this.slottedNodes.length > this.stackThreshold) {
47
+ this.stackCollapsed = true;
48
+ }
49
+ if (this.stackCollapsed && this.slottedNodes.length <= 1) {
50
+ this.stackCollapsed = false;
51
+ this.manuallyExpanded = false;
52
+ }
53
+ this.handlePosition();
54
+ }
55
+ /** @internal */
56
+ handleContainerClick() {
57
+ if (this.stackCollapsed) {
58
+ this.stackCollapsed = false;
59
+ this.manuallyExpanded = true;
60
+ }
61
+ }
62
+ /** @internal */
63
+ handleToggleCollapse() {
64
+ this.stackCollapsed = !this.stackCollapsed;
65
+ this.manuallyExpanded = !this.stackCollapsed;
66
+ }
67
+ /** @internal */
68
+ handleCloseAll() {
69
+ while (this.firstChild) {
70
+ this.removeChild(this.firstChild);
71
+ }
72
+ this.stackCollapsed = false;
73
+ this.manuallyExpanded = false;
74
+ }
75
+ /**
76
+ * Manages the absolute positioning of notifications to enable smooth stack-to-list animations.
77
+ * Uses a batch read/write pattern to avoid layout thrashing.
78
+ * @internal
79
+ */
80
+ handlePosition() {
81
+ const toasts = this.slottedNodes.filter((node) => node instanceof HTMLElement);
82
+ if (!toasts.length) {
83
+ return;
84
+ }
85
+ toasts.forEach((toast, index) => {
86
+ toast.style.position = 'absolute';
87
+ toast.style.transition = 'all 0.3s ease-in';
88
+ toast.style.right = '0px';
89
+ toast.style.zIndex = (toasts.length - index).toString();
90
+ });
91
+ const heights = toasts.map((toast) => toast.offsetHeight);
92
+ toasts.reduce((yOffset, toast, index) => {
93
+ toast.style.top = `${yOffset}px`;
94
+ return yOffset + heights[index];
95
+ }, 0);
96
+ }
97
+ };
98
+ __decorate([
99
+ attr
100
+ ], NotifyContainer.prototype, "position", void 0);
101
+ __decorate([
102
+ attr({ attribute: 'stack-threshold' })
103
+ ], NotifyContainer.prototype, "stackThreshold", void 0);
104
+ __decorate([
105
+ attr({ attribute: 'allow-manual-collapse', mode: 'boolean' })
106
+ ], NotifyContainer.prototype, "allowManualCollapse", void 0);
107
+ __decorate([
108
+ attr({ attribute: 'allow-close-all', mode: 'boolean' })
109
+ ], NotifyContainer.prototype, "allowCloseAll", void 0);
110
+ __decorate([
111
+ attr({ attribute: 'design-system-prefix' })
112
+ ], NotifyContainer.prototype, "designSystemPrefix", void 0);
113
+ __decorate([
114
+ attr({ attribute: 'show-count', mode: 'boolean' })
115
+ ], NotifyContainer.prototype, "showCount", void 0);
116
+ __decorate([
117
+ attr({ attribute: 'stack-collapsed', mode: 'boolean' })
118
+ ], NotifyContainer.prototype, "stackCollapsed", void 0);
119
+ __decorate([
120
+ observable
121
+ ], NotifyContainer.prototype, "slottedNodes", void 0);
122
+ NotifyContainer = __decorate([
123
+ customElement({
124
+ name: 'notify-container',
125
+ template,
126
+ styles,
127
+ })
128
+ ], NotifyContainer);
129
+ export { NotifyContainer };
@@ -0,0 +1,211 @@
1
+ import { css } from '@genesislcap/web-core';
2
+ export const styles = css `
3
+ :host {
4
+ position: fixed;
5
+ z-index: 9999;
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 4px;
9
+ box-sizing: border-box;
10
+ pointer-events: none; /* Allow clicks to pass through empty space */
11
+ width: 415px;
12
+ }
13
+
14
+ .toast-container {
15
+ padding: 0 8px 12px 12px;
16
+ position: relative;
17
+ }
18
+
19
+ /* Expanded / List State: Allow scrolling if too many items */
20
+
21
+ :host(:not([stack-collapsed])) {
22
+ max-height: calc(100% - var(--nav-height));
23
+ overflow: hidden;
24
+ pointer-events: auto; /* Enable pointer events for scrolling */
25
+
26
+ slot {
27
+ display: block;
28
+ height: calc(100vh - var(--nav-height) - 54px);
29
+ position: relative;
30
+ }
31
+
32
+ .toast-container {
33
+ flex: 1;
34
+ height: 100%;
35
+ overflow-y: auto;
36
+ overflow-x: hidden;
37
+ scrollbar-color: var(--neutral-layer-3) transparent;
38
+
39
+ &:hover {
40
+ scrollbar-color: var(--neutral-layer-4) transparent;
41
+ }
42
+ }
43
+ }
44
+
45
+ .header {
46
+ display: flex;
47
+ gap: 12px;
48
+ pointer-events: none;
49
+ margin: 5px 24px;
50
+ justify-content: space-between;
51
+ visibility: hidden;
52
+ align-items: center;
53
+ box-sizing: border-box;
54
+
55
+ .header-title {
56
+ text-shadow: 0 0 10px #000;
57
+ }
58
+
59
+ .notification-header-buttons {
60
+ display: flex;
61
+ gap: 4px;
62
+
63
+ rapid-icon {
64
+ color: var(--neutral-foreground-hint);
65
+ margin-left: 4px;
66
+ display: inline-flex;
67
+ font-size: 14px;
68
+
69
+ &.chevron-up.collapse {
70
+ transform: rotate(180deg);
71
+ transition: transform 0.3s ease;
72
+ }
73
+ }
74
+ }
75
+
76
+ --base-height-multiplier: 8;
77
+
78
+ *[appearance='neutral'] {
79
+ font-size: 11px;
80
+ cursor: pointer;
81
+ background: var(--neutral-fill-rest);
82
+ }
83
+ }
84
+
85
+ .header.visible {
86
+ visibility: visible;
87
+ pointer-events: auto; /* Enable clicks on header buttons */
88
+ }
89
+
90
+ :host([position$='left']) .header {
91
+ justify-content: space-between;
92
+ }
93
+
94
+ :host([position^='bottom']) .header {
95
+ margin-bottom: 0;
96
+ margin-top: 4px;
97
+ }
98
+
99
+ /* Ensure children (toasts) are clickable */
100
+
101
+ ::slotted(*) {
102
+ pointer-events: auto;
103
+ }
104
+
105
+ :host([position='top-right']) {
106
+ top: var(--nav-height, 0);
107
+ right: 0;
108
+ }
109
+
110
+ :host([position='top-left']) {
111
+ top: var(--nav-height, 0);
112
+ left: 0;
113
+ }
114
+
115
+ :host([position='bottom-right']) {
116
+ bottom: 0;
117
+ right: 0;
118
+ flex-direction: column-reverse;
119
+ }
120
+
121
+ :host([position='bottom-left']) {
122
+ bottom: 0;
123
+ left: 0;
124
+ flex-direction: column-reverse;
125
+ }
126
+
127
+ /* Stacked / Collapsed State */
128
+
129
+ :host([stack-collapsed]) {
130
+ height: min-content;
131
+
132
+ /* Host allows pointer events so they can reach the slot */
133
+ pointer-events: auto;
134
+ cursor: pointer;
135
+ }
136
+
137
+ /* Apply the grid layout to the slot itself so it acts as the container and click target */
138
+
139
+ :host([stack-collapsed]) slot {
140
+ display: grid;
141
+ grid-template-columns: auto;
142
+ grid-template-rows: auto;
143
+ align-items: end; /* Default to bottom-up stacking */
144
+ justify-items: center;
145
+
146
+ /* The slot catches the click */
147
+ pointer-events: auto;
148
+ }
149
+
150
+ /* Rotate when the collapse class is present */
151
+
152
+ :host([stack-collapsed][position^='top']) slot {
153
+ align-items: start;
154
+ }
155
+
156
+ :host([stack-collapsed][position$='right']) slot {
157
+ justify-items: end;
158
+ }
159
+
160
+ :host([stack-collapsed][position$='left']) slot {
161
+ justify-items: start;
162
+ }
163
+
164
+ :host([stack-collapsed]) ::slotted(*) {
165
+ grid-area: 1 / 1;
166
+ transition:
167
+ transform 0.3s ease,
168
+ top 0.3s ease,
169
+ opacity 0.3s ease;
170
+ opacity: 0%;
171
+ pointer-events: none !important; /* Disable interaction with toasts in collapsed state */
172
+ transform: scale(0.9);
173
+ top: 0 !important;
174
+ }
175
+
176
+ /* Show and offset the top 3 items in the stack */
177
+
178
+ :host([stack-collapsed]) ::slotted(:nth-child(1)) {
179
+ opacity: 100%;
180
+ pointer-events: auto;
181
+ transform: translateY(0) scale(1);
182
+ z-index: 3;
183
+ position: relative !important;
184
+ }
185
+
186
+ :host([stack-collapsed]) ::slotted(:nth-child(2)) {
187
+ opacity: 100%;
188
+ transform: translateY(var(--stack-offset-y, 8px)) scale(0.95);
189
+ z-index: 2;
190
+ position: relative !important;
191
+ }
192
+
193
+ :host([stack-collapsed]) ::slotted(:nth-child(3)) {
194
+ opacity: 100%;
195
+ transform: translateY(var(--stack-offset-y-2, 16px)) scale(0.9);
196
+ z-index: 1;
197
+ position: relative !important;
198
+ }
199
+
200
+ /* Adjust offset direction based on position */
201
+
202
+ :host([stack-collapsed][position^='top']) {
203
+ --stack-offset-y: 8px;
204
+ --stack-offset-y-2: 16px;
205
+ }
206
+
207
+ :host([stack-collapsed][position^='bottom']) {
208
+ --stack-offset-y: -8px;
209
+ --stack-offset-y-2: -16px;
210
+ }
211
+ `;
@@ -0,0 +1,33 @@
1
+ import { classNames, html, slotted, when } from '@genesislcap/web-core';
2
+ const headerTemplate = (prefix) => html `
3
+ <div class="header ${(x) => classNames(['visible', x.slottedNodes.length > 1])}">
4
+ ${when((x) => x.showCount, html `
5
+ <span class="header-title">${(x) => x.slottedNodes.length} Notifications</span>
6
+ `)}
7
+ <div class="notification-header-buttons">
8
+ ${when((x) => x.allowManualCollapse, html `
9
+ <${prefix}-button @click=${(x) => x.handleToggleCollapse()}>
10
+ ${(x) => (x.stackCollapsed ? 'Expand' : 'Collapse')}
11
+ <${prefix}-icon
12
+ class="chevron-up ${(x) => classNames(['collapse', x.stackCollapsed])}"
13
+ name="chevron-up"></${prefix}-icon>
14
+ </${prefix}-button>
15
+ `)}
16
+ ${when((x) => x.allowCloseAll, html `
17
+ <${prefix}-button @click=${(x) => x.handleCloseAll()}>
18
+ Close All
19
+ <${prefix}-icon name="xmark">
20
+ </${prefix}-icon>
21
+ </${prefix}-button>
22
+ `)}
23
+ </div>
24
+ </div>
25
+ `;
26
+ export const template = html `
27
+ ${when((x) => x.allowCloseAll || x.allowManualCollapse, html `
28
+ ${(x) => headerTemplate(x.designSystemPrefix)}
29
+ `)}
30
+ <div class="toast-container">
31
+ <slot ${slotted('slottedNodes')} @click="${(x) => x.handleContainerClick()}"></slot>
32
+ </div>
33
+ `;
package/dist/esm/index.js CHANGED
@@ -3,6 +3,7 @@ export * from './banner';
3
3
  export * from './dialog';
4
4
  export * from './snackbar';
5
5
  export * from './toast';
6
+ export * from './container';
6
7
  export * from './notification-builder';
7
8
  export * from './notification-launcher';
8
9
  export * from './notification-util';
@@ -1,4 +1,29 @@
1
+ import { getAllElements } from '@genesislcap/foundation-utils';
1
2
  import { getNotificationContainer, showLoggerLogLevel } from '../notification-util';
3
+ const findNotifyContainer = (position) => {
4
+ return getAllElements(document.body).find((element) => element.tagName.toLowerCase() === 'notify-container' && element.position === position);
5
+ };
6
+ function configureDivContainer(notificationStructure, container) {
7
+ var _a, _b;
8
+ container.style.position = 'fixed';
9
+ switch ((_b = (_a = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _a === void 0 ? void 0 : _a.toast) === null || _b === void 0 ? void 0 : _b.position) {
10
+ case 'top-left':
11
+ container.style.top = 'var(--nav-height, 0)';
12
+ container.style.left = '0';
13
+ break;
14
+ case 'bottom-left':
15
+ container.style.bottom = '0';
16
+ container.style.left = '0';
17
+ break;
18
+ case 'bottom-right':
19
+ container.style.bottom = '0';
20
+ container.style.right = '0';
21
+ break;
22
+ default:
23
+ container.style.top = 'var(--nav-height, 0)';
24
+ container.style.right = '0';
25
+ }
26
+ }
2
27
  /**
3
28
  * Shows the notificationStructure
4
29
  * @internal
@@ -8,29 +33,13 @@ import { getNotificationContainer, showLoggerLogLevel } from '../notification-ut
8
33
  * @returns
9
34
  * */
10
35
  export const showToast = (notificationStructure, tagName, notificationContainer) => {
11
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
36
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
12
37
  showLoggerLogLevel(notificationStructure);
13
38
  const tagPrefix = tagName.split('-')[0];
14
- const container = notificationContainer !== null && notificationContainer !== void 0 ? notificationContainer : getNotificationContainer('notify-container', tagName);
15
- if (container) {
16
- container.style.position = 'fixed';
17
- switch ((_b = (_a = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _a === void 0 ? void 0 : _a.toast) === null || _b === void 0 ? void 0 : _b.position) {
18
- case 'top-left':
19
- container.style.top = 'var(--nav-height, 0)';
20
- container.style.left = '0';
21
- break;
22
- case 'bottom-left':
23
- container.style.bottom = '0';
24
- container.style.left = '0';
25
- break;
26
- case 'bottom-right':
27
- container.style.bottom = '0';
28
- container.style.right = '0';
29
- break;
30
- default:
31
- container.style.top = 'var(--nav-height, 0)';
32
- container.style.right = '0';
33
- }
39
+ const position = ((_b = (_a = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _a === void 0 ? void 0 : _a.toast) === null || _b === void 0 ? void 0 : _b.position) || 'top-right';
40
+ const container = (_c = notificationContainer !== null && notificationContainer !== void 0 ? notificationContainer : findNotifyContainer(position)) !== null && _c !== void 0 ? _c : getNotificationContainer('notify-container', tagName);
41
+ if (container && container.tagName.toLowerCase() !== 'notify-container') {
42
+ configureDivContainer(notificationStructure, container);
34
43
  }
35
44
  const toastNotify = document.createElement(`${tagPrefix}-toast`);
36
45
  const toastTitle = document.createElement('div');
@@ -41,10 +50,10 @@ export const showToast = (notificationStructure, tagName, notificationContainer)
41
50
  toastDetails.textContent = (notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.body) || '';
42
51
  const toastDate = document.createElement('div');
43
52
  toastDate.setAttribute('slot', 'date');
44
- toastDate.textContent = ((_c = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.createdAt) === null || _c === void 0 ? void 0 : _c.toLocaleTimeString()) || '';
53
+ toastDate.textContent = ((_d = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.createdAt) === null || _d === void 0 ? void 0 : _d.toLocaleTimeString()) || '';
45
54
  let toastBottom;
46
- if (((_e = (_d = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _d === void 0 ? void 0 : _d.toast) === null || _e === void 0 ? void 0 : _e.buttons) &&
47
- ((_h = (_g = (_f = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _f === void 0 ? void 0 : _f.toast) === null || _g === void 0 ? void 0 : _g.buttons) === null || _h === void 0 ? void 0 : _h.length)) {
55
+ if (((_f = (_e = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _e === void 0 ? void 0 : _e.toast) === null || _f === void 0 ? void 0 : _f.buttons) &&
56
+ ((_j = (_h = (_g = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _g === void 0 ? void 0 : _g.toast) === null || _h === void 0 ? void 0 : _h.buttons) === null || _j === void 0 ? void 0 : _j.length)) {
48
57
  toastBottom = document.createElement('div');
49
58
  toastBottom.setAttribute('slot', 'bottom');
50
59
  notificationStructure.config.toast.buttons.forEach((button) => {
@@ -66,15 +75,15 @@ export const showToast = (notificationStructure, tagName, notificationContainer)
66
75
  toastBottom.appendChild(buttonElement);
67
76
  });
68
77
  }
69
- toastNotify.setAttribute('notify', ((_k = (_j = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _j === void 0 ? void 0 : _j.toast) === null || _k === void 0 ? void 0 : _k.type) || '');
78
+ toastNotify.setAttribute('notify', ((_l = (_k = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _k === void 0 ? void 0 : _k.toast) === null || _l === void 0 ? void 0 : _l.type) || '');
70
79
  if (notificationStructure.iconName) {
71
80
  toastNotify.setAttribute('notification-icon', notificationStructure.iconName);
72
81
  }
73
- ((_m = (_l = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _l === void 0 ? void 0 : _l.toast) === null || _m === void 0 ? void 0 : _m.autoClose)
74
- ? toastNotify.setAttribute('auto-close', `${(_p = (_o = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _o === void 0 ? void 0 : _o.toast) === null || _p === void 0 ? void 0 : _p.autoClose}`)
82
+ ((_o = (_m = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _m === void 0 ? void 0 : _m.toast) === null || _o === void 0 ? void 0 : _o.autoClose)
83
+ ? toastNotify.setAttribute('auto-close', `${(_q = (_p = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _p === void 0 ? void 0 : _p.toast) === null || _q === void 0 ? void 0 : _q.autoClose}`)
75
84
  : '';
76
- ((_r = (_q = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _q === void 0 ? void 0 : _q.toast) === null || _r === void 0 ? void 0 : _r.closeTimeout)
77
- ? toastNotify.setAttribute('close-timeout', `${(_t = (_s = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _s === void 0 ? void 0 : _s.toast) === null || _t === void 0 ? void 0 : _t.closeTimeout}`)
85
+ ((_s = (_r = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _r === void 0 ? void 0 : _r.toast) === null || _s === void 0 ? void 0 : _s.closeTimeout)
86
+ ? toastNotify.setAttribute('close-timeout', `${(_u = (_t = notificationStructure === null || notificationStructure === void 0 ? void 0 : notificationStructure.config) === null || _t === void 0 ? void 0 : _t.toast) === null || _u === void 0 ? void 0 : _u.closeTimeout}`)
78
87
  : '';
79
88
  toastNotify.appendChild(toastTitle);
80
89
  toastNotify.appendChild(toastDetails);
@@ -82,5 +91,5 @@ export const showToast = (notificationStructure, tagName, notificationContainer)
82
91
  if (toastBottom) {
83
92
  toastNotify.appendChild(toastBottom);
84
93
  }
85
- container.appendChild(toastNotify);
94
+ container.prepend(toastNotify);
86
95
  };