Skip to content

Commit a642dd7

Browse files
committed
BsNotification:
- Add feature to enable hiding the notification icon. - Improves initializing and removes unnecessary html element. - Improves the notification provider in handling and processing notification items. - Improves css variables and classes. - Update CHANGELOG.md - Bump to version 2.1.3
1 parent d62e717 commit a642dd7

File tree

9 files changed

+269
-209
lines changed

9 files changed

+269
-209
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33
> All notable changes to this project will be documented in this file.
44
55

6+
## v2.1.3
7+
8+
Released: December 10, 2024
9+
10+
### Features & Improvements
11+
12+
- **BsNotification**:
13+
- Add feature to enable hiding the notification icon.
14+
- Improves initializing and removes unnecessary html element.
15+
- Improves the notification provider in handling and processing notification items.
16+
- Improves css variables and classes.
17+
18+
619
## v2.1.2
720

821
Released: December 08, 2024

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-mdbootstrap",
3-
"version": "2.1.2",
3+
"version": "2.1.3",
44
"description": "Bootstrap5 Material Design Components for Vue.js",
55
"author": {
66
"name": "Ahmad Fajar",

scss/banner.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* Vue MDBootstrap v2.1.2
2+
* Vue MDBootstrap v2.1.3
33
* Released under the BSD-3 License.
44
* Copyright Ahmad Fajar (https://ahmadfajar.github.io).
55
*/

src/components/Notification/BsNotificationBar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default defineComponent<TBsNotificationBar>({
5757

5858
return () =>
5959
h('div', {
60-
class: `${cssPrefix}notification-bar`,
60+
class: `${cssPrefix}dialog-progressbar`,
6161
style: { width: barWidth.value + '%' },
6262
});
6363
},
Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
1-
import { useRenderNotificationItem } from '@/components/Notification/mixins/notificationApi.ts';
1+
import {
2+
useDeferHideNotification,
3+
useRenderNotificationItem,
4+
} from '@/components/Notification/mixins/notificationApi.ts';
25
import type {
3-
INotificationProvider,
46
TBsNotificationItem,
57
TNotificationItemOptionProps,
6-
TNotificationOption,
8+
TNotificationVariant,
79
} from '@/components/Notification/types';
8-
import { useVueMdbNotification } from '@/mixins/CommonApi.ts';
9-
import Helper from '@/utils/Helper';
10+
import {
11+
booleanProp,
12+
booleanTrueProp,
13+
numberProp,
14+
stringMandatoryProp,
15+
stringProp,
16+
} from '@/mixins/CommonProps.ts';
1017
import type { Prop } from 'vue';
11-
import { defineComponent, onMounted, ref, shallowRef } from 'vue';
18+
import { defineComponent, onMounted, ref } from 'vue';
1219

1320
export default defineComponent<TBsNotificationItem>({
1421
name: 'BsNotificationItem',
1522
props: {
16-
options: {
17-
type: Object,
18-
default: undefined,
19-
} as Prop<TNotificationOption>,
23+
message: stringMandatoryProp,
24+
title: stringProp,
25+
timeout: numberProp,
26+
clickClose: booleanProp,
27+
closeButton: booleanTrueProp,
28+
iconOff: booleanProp,
29+
progressBar: booleanProp,
30+
variant: stringMandatoryProp as Prop<TNotificationVariant>,
2031
},
21-
setup(props) {
32+
emits: ['dismiss'],
33+
setup(props, { emit }) {
2234
const thisProps = props as Readonly<TNotificationItemOptionProps>;
23-
const provider = shallowRef<INotificationProvider>();
2435
const timerId = ref<number>();
2536

2637
onMounted(() => {
27-
provider.value = useVueMdbNotification();
28-
timerId.value = Helper.defer(() => {
29-
provider.value?.remove(<TNotificationOption>thisProps.options);
30-
}, thisProps.options?.timeout as number);
38+
useDeferHideNotification(emit, timerId, thisProps.timeout);
3139
});
3240

33-
return () => useRenderNotificationItem(thisProps, provider, timerId);
41+
return () => useRenderNotificationItem(emit, thisProps, timerId);
3442
},
3543
});

src/components/Notification/mixins/NotificationProvider.ts

Lines changed: 57 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,122 @@
11
import type {
22
INotificationProvider,
3-
TNotificationItem,
43
TNotificationOption,
54
TNotificationPosition,
65
TNotificationVariant,
76
} from '@/components/Notification/types';
87
import Helper from '@/utils/Helper';
9-
import { reactive } from 'vue';
8+
import { type Reactive, reactive } from 'vue';
109

1110
export default class NotificationProvider implements INotificationProvider {
12-
private readonly _item: TNotificationItem;
13-
private readonly _positions: TNotificationPosition[] = [
14-
'top-right',
15-
'top-left',
16-
'top-center',
17-
'top-full-width',
18-
'bottom-right',
19-
'bottom-left',
20-
'bottom-center',
21-
'bottom-full-width',
22-
];
11+
private readonly _collection: Reactive<Map<TNotificationPosition, TNotificationOption[]>>;
2312

2413
constructor() {
25-
const item = {} as TNotificationItem;
26-
27-
for (let i = 0; i <= this._positions.length - 1; i++) {
28-
item[this._positions[i]] = [];
29-
}
30-
31-
this._item = reactive(item);
14+
this._collection = reactive(new Map<TNotificationPosition, TNotificationOption[]>());
3215
}
3316

34-
get notification() {
35-
return this._item;
17+
get collection(): Map<TNotificationPosition, TNotificationOption[]> {
18+
return this._collection;
3619
}
3720

3821
add(data: string | TNotificationOption): TNotificationOption | null {
39-
const option = this._createOption(data);
40-
const position = option.position as TNotificationPosition;
41-
42-
if (option.preventDuplicates) {
43-
const keys = this.notification[position].keys();
44-
45-
for (const index of keys) {
46-
if (
47-
this._item[position][index].title === option.title &&
48-
this._item[position][index].message === option.message
49-
) {
50-
console.warn('Duplicate notification', option);
51-
return null;
22+
const toastOption = this._createOption(data);
23+
const placement = toastOption.position as TNotificationPosition;
24+
const toastItems = this._collection.get(placement);
25+
26+
if (!toastItems) {
27+
this._collection.set(placement, [toastOption]);
28+
} else {
29+
if (toastOption.preventDuplicates) {
30+
for (const toast of toastItems) {
31+
if (
32+
toast.message === toastOption.message &&
33+
toast.title === toastOption.title
34+
) {
35+
console.warn('Duplicate notification', toastOption);
36+
return null;
37+
}
5238
}
5339
}
40+
41+
toastItems.push(toastOption);
42+
this._collection.set(placement, toastItems);
5443
}
55-
this._item[position].push(option);
5644

57-
return option;
45+
return toastOption;
5846
}
5947

6048
clearAll() {
61-
for (let i = 0; i < this._positions.length; i++) {
62-
this._item[this._positions[i]] = [];
63-
}
49+
this._collection.clear();
6450
}
6551

6652
close(item: TNotificationOption) {
6753
this.remove(item);
6854
}
6955

56+
private _deleteIfEmpty(placement: TNotificationPosition, data?: TNotificationOption[]): void {
57+
if (Helper.isEmpty(data)) {
58+
this._collection.delete(placement);
59+
} else {
60+
this._collection.set(placement, data ?? []);
61+
}
62+
}
63+
7064
remove(item: TNotificationOption) {
7165
const oid = item.oid as string;
7266
const position = item.position as TNotificationPosition;
73-
this._item[position] = this.notification[position].filter((it) => it.oid !== oid);
67+
const toastItems = this._collection.get(position);
68+
const results = toastItems?.filter((it) => it.oid !== oid);
69+
70+
this._deleteIfEmpty(position, results);
7471
}
7572

7673
removeByType(variant: TNotificationVariant) {
77-
for (let i = 0; i < this._positions.length; i++) {
78-
const keys = this.notification[this._positions[i]].keys();
79-
80-
for (const index of keys) {
81-
if (this.notification[this._positions[i]][index].variant === variant) {
82-
this.remove(this.notification[this._positions[i]][index]);
83-
}
84-
}
85-
}
74+
this._collection.forEach((values, placement) => {
75+
const results = values.filter((it) => it.variant !== variant);
76+
this._deleteIfEmpty(placement, results);
77+
});
8678
}
8779

88-
error(option: string | TNotificationOption, title?: string): TNotificationOption | null {
89-
return this._doAdd(option, 'error', title);
80+
error(data: string | TNotificationOption, title?: string): TNotificationOption | null {
81+
return this._doAdd(data, 'error', title);
9082
}
9183

92-
info(option: string | TNotificationOption, title?: string): TNotificationOption | null {
93-
return this._doAdd(option, 'info', title);
84+
info(data: string | TNotificationOption, title?: string): TNotificationOption | null {
85+
return this._doAdd(data, 'info', title);
9486
}
9587

96-
success(option: string | TNotificationOption, title?: string): TNotificationOption | null {
97-
return this._doAdd(option, 'success', title);
88+
success(data: string | TNotificationOption, title?: string): TNotificationOption | null {
89+
return this._doAdd(data, 'success', title);
9890
}
9991

100-
warning(option: string | TNotificationOption, title?: string): TNotificationOption | null {
101-
return this._doAdd(option, 'warning', title);
92+
warning(data: string | TNotificationOption, title?: string): TNotificationOption | null {
93+
return this._doAdd(data, 'warning', title);
10294
}
10395

10496
private _doAdd(
105-
option: string | TNotificationOption,
97+
data: string | TNotificationOption,
10698
variant: TNotificationVariant,
10799
title?: string
108100
): TNotificationOption | null {
109-
const data = this._createOption(option);
110-
data.variant = variant;
111-
data.title = title;
101+
const option = Helper.isObject(data) ? data : ({ message: data } as TNotificationOption);
102+
option.variant = variant;
103+
option.title = title || option.title;
112104

113-
return this.add(data);
105+
return this.add(option);
114106
}
115107

116108
private _createOption(option: string | TNotificationOption): TNotificationOption {
117109
const defaultOption = {
118110
oid: Helper.uuid(true),
119111
clickClose: false,
120112
closeButton: true,
121-
// closeOnHover: false,
113+
iconOff: false,
122114
progressBar: false,
123115
preventDuplicates: false,
124116
position: 'bottom-right' as TNotificationPosition,
125117
variant: 'default' as TNotificationVariant,
126118
timeout: 6000,
127-
};
119+
} as TNotificationOption;
128120

129121
if (Helper.isObject(option) && !Helper.isEmpty(option.message)) {
130122
return {

0 commit comments

Comments
 (0)