diff --git a/.storybook/preview.js b/.storybook/preview.js
index a5ce23df..0bfa5e10 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -5,6 +5,7 @@ import PrimeVue from 'primevue/config';
import { getPrimeVueConfig } from '@/plugins/prime';
import Tooltip from 'primevue/tooltip';
import ConfirmationService from 'primevue/confirmationservice';
+import ToastService from 'primevue/toastservice';
import '../src/tailwind.css';
import './themes/base.css';
@@ -45,6 +46,7 @@ setup((app) => {
registerToastification(app);
app.use(PrimeVue, mergedConfig);
app.use(ConfirmationService);
+ app.use(ToastService);
app.directive('tooltip', Tooltip);
});
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..2daf9a77
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 CDEK-IT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/src/plugins/prime/stories/Toast/Toast.mdx b/src/plugins/prime/stories/Toast/Toast.mdx
new file mode 100644
index 00000000..13fe793d
--- /dev/null
+++ b/src/plugins/prime/stories/Toast/Toast.mdx
@@ -0,0 +1,78 @@
+import { Meta, Canvas, Controls, Title, Description } from '@storybook/addon-docs/blocks';
+import * as ToastStories from './Toast.stories';
+
+
+
+
+
+
+## Варианты использования
+
+
+
+### Базовый
+Базовый вариант `Toast`. Используйте таблицу ниже для настройки пропсов. Кнопки внизу позволяют показать живые тосты.
+Иконки для каждого типа `Toast` уже "вшиты", но это поведение можно изменить (см. ниже).
+
+
+#### Полный список аргументов и событий компонента.
+
+
+
+
+### С кнопкой закрытия
+Базовый вариант `Toast` с кнопкой закрытия.
+
+
+### Кастомный контент
+`Toast` с кастомным контейнером.
+
+
+#### Аргументы и события
+
+
+
+
+### С кастомным контейнером и кнопкой закрытия
+`Toast` с кастомным контейнером и кнопкой закрытия.
+
+
+#### Аргументы и события
+
+
+
+
+### Ширина Toast
+Ширина `Toast` задаётся через `props` — `width`. Доступные значения:
+
+ Примеры кода
+
+ - `sm` (20rem)
+ ```html dark
+
+ ```
+ - `md` (25rem, по умолчанию)
+ ```html dark
+
+ ```
+ - `lg` (30rem)
+ ```html dark
+
+ ```
+ - `xlg` (45rem)
+ ```html dark
+
+ ```
+
+
+
+
+#### Аргументы и события
+
+
+### Позиция
+Демонстрация всех доступных позиций `Toast`. Каждая кнопка показывает уведомление в соответствующей позиции.
+
+
+#### Аргументы и события
+
diff --git a/src/plugins/prime/stories/Toast/Toast.stories.js b/src/plugins/prime/stories/Toast/Toast.stories.js
new file mode 100644
index 00000000..25ebc514
--- /dev/null
+++ b/src/plugins/prime/stories/Toast/Toast.stories.js
@@ -0,0 +1,364 @@
+import { PBlockToast } from '@/primeBlocks';
+
+import {
+ Template,
+ TemplateCloseButton,
+ TemplateCustomContentWithCloseButton,
+ TemplateWithContent,
+ TemplateWidth,
+ TemplatePosition,
+} from './Toast.template';
+
+const meta = {
+ title: 'Prime/Messages/Toast',
+ component: PBlockToast,
+ tags: ['autodocs'],
+ parameters: {
+ docs: {
+ description: {
+ component: `\`Toast\` используется для отображения всплывающих уведомлений поверх интерфейса.\n
+Требует подключения \`ToastService\`.\n\`\`\`ts dark \nimport { PBlockToast, usePBlockToast } from '@cdek-it/vue-ui-kit';\`\`\` `,
+ },
+ },
+ designToken: { disable: false },
+ designTokens: { prefix: '--p-toast' },
+ },
+ argTypes: {
+ position: {
+ control: 'select',
+ options: [
+ 'top-right',
+ 'top-left',
+ 'top-center',
+ 'bottom-right',
+ 'bottom-left',
+ 'bottom-center',
+ 'center',
+ ],
+ description: 'Позиция тоста на экране.',
+ table: {
+ category: 'Props',
+ type: {
+ summary:
+ "'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center' | 'center'",
+ },
+ },
+ },
+ group: {
+ control: 'text',
+ description:
+ 'Идентификатор группы тостов для адресной отправки сообщений.',
+ table: {
+ category: 'Props',
+ type: { summary: 'string' },
+ },
+ },
+ life: {
+ control: 'number',
+ description: 'Время (мс) до автоматического закрытия тоста.',
+ table: {
+ category: 'Props',
+ type: { summary: 'number' },
+ },
+ },
+ width: {
+ control: 'select',
+ options: ['sm', 'md', 'lg', 'xlg'],
+ description: 'Ширина тоста на экране.',
+ table: {
+ category: 'Props',
+ type: { summary: "'sm' | 'md' | 'lg' | 'xlg'" },
+ },
+ },
+ },
+ args: {
+ position: 'top-right',
+ group: 'basic',
+ life: 5000,
+ width: 'md',
+ },
+};
+
+export default meta;
+
+export const Default = {
+ name: 'Toast',
+ render: Template,
+ args: {
+ group: 'basic',
+ position: 'top-right',
+ life: 5_000,
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
+
+export const DefaultButton = {
+ name: 'Toast',
+ render: TemplateCloseButton,
+ args: {
+ group: 'basic-button',
+ position: 'top-right',
+ life: 5_000,
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
+
+export const WithContent = {
+ render: TemplateWithContent,
+ args: {
+ group: 'content',
+ position: 'top-right',
+ life: 5_000,
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ message.summary }}
+
{{ message.detail }}
+
+
Дополнительный контент
+
+
+
+
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
+
+export const WithContentAndCloseButton = {
+ render: TemplateCustomContentWithCloseButton,
+ args: {
+ group: 'content-close-button',
+ life: 5_000,
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+
+
+
+
+
+
{{ message.summary }}
+
{{ message.detail }}
+
+
+
+
+
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
+
+export const Width = {
+ render: TemplateWidth,
+ args: {
+ group: 'width-preview',
+ position: 'top-right',
+ life: 5_000,
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
+
+export const Position = {
+ render: TemplatePosition,
+ parameters: {
+ docs: {
+ source: {
+ language: 'html',
+ code: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ },
+ },
+ },
+};
diff --git a/src/plugins/prime/stories/Toast/Toast.template.js b/src/plugins/prime/stories/Toast/Toast.template.js
new file mode 100644
index 00000000..c69a8161
--- /dev/null
+++ b/src/plugins/prime/stories/Toast/Toast.template.js
@@ -0,0 +1,458 @@
+import { ref } from 'vue';
+import { PBlockToast, usePBlockToast } from '@/primeBlocks';
+import Button from 'primevue/button';
+
+const MessageIcons = {
+ success: 'ti-circle-check',
+ info: 'ti-info-circle',
+ warn: 'ti-alert-triangle',
+ error: 'ti-alert-circle',
+};
+
+const SEVERITIES = [
+ { type: 'success', icon: MessageIcons.success, label: 'Успех' },
+ { type: 'info', icon: MessageIcons.info, label: 'Информация' },
+ { type: 'warn', icon: MessageIcons.warn, label: 'Предупреждение' },
+ { type: 'error', icon: MessageIcons.error, label: 'Ошибка' },
+];
+
+const POSITIONS = [
+ { position: 'top-left', label: 'Вверх слева', group: 'pos-top-left' },
+ { position: 'top-center', label: 'Вверх по центру', group: 'pos-top-center' },
+ { position: 'top-right', label: 'Вверх справа', group: 'pos-top-right' },
+ { position: 'bottom-left', label: 'Вниз слева', group: 'pos-bottom-left' },
+ {
+ position: 'bottom-center',
+ label: 'Вниз по центру',
+ group: 'pos-bottom-center',
+ },
+ { position: 'bottom-right', label: 'Вниз справа', group: 'pos-bottom-right' },
+];
+
+const SIZES = [
+ {
+ key: 'sm',
+ label: 'Small (20rem)',
+ width: '20rem',
+ group: 'width-sm',
+ },
+ {
+ key: 'base',
+ label: 'Base (25rem)',
+ width: '25rem',
+ group: 'width-base',
+ },
+ {
+ key: 'lg',
+ label: 'Large (30rem)',
+ width: '30rem',
+ group: 'width-lg',
+ },
+ {
+ key: 'xlg',
+ label: 'X-Large (45rem)',
+ width: '45rem',
+ group: 'width-xlg',
+ },
+];
+
+const commonToastConfig = {
+ summary: 'Заголовок сообщения',
+ detail: 'Дополнительная информация',
+};
+
+export const Template = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+
+ const showToast = (severity, icon) => {
+ toast.add({
+ severity,
+ ...commonToastConfig,
+ life: args.life ?? 5_000,
+ icon,
+ group: args.group || `story_${Date.now()}`,
+ });
+ };
+
+ return {
+ args,
+ showToast,
+ severities: SEVERITIES,
+ };
+ },
+ template: `
+
+
+
+
+
+
+
+
+
+
+
Заголовок сообщения
+
Дополнительная информация
+
+
+
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const TemplateCloseButton = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+
+ const showToast = (severity, icon) => {
+ toast.add({
+ severity,
+ ...commonToastConfig,
+ life: args.life ?? 5_000,
+ icon,
+ group: args.group || `story_${Date.now()}`,
+ closable: true,
+ });
+ };
+
+ return {
+ args,
+ showToast,
+ severities: SEVERITIES,
+ };
+ },
+ template: `
+
+
+
+
+
+
+
+
+
+
+
Заголовок сообщения
+
Дополнительная информация
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const TemplateWithContent = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+
+ const showToast = (severity, icon) => {
+ toast.add({
+ severity,
+ ...commonToastConfig,
+ life: args.life ?? 5_000,
+ icon,
+ group: args.group || `story_${Date.now()}`,
+ });
+ };
+
+ return {
+ args,
+ severities: SEVERITIES,
+ showToast,
+ };
+ },
+ template: `
+
+
+
+
+
+
+
+
{{ message.summary }}
+
{{ message.detail }}
+
+
Дополнительный контент
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Заголовок сообщения
+
Дополнительная информация
+
+
Дополнительный контент
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const TemplateCustomContentWithCloseButton = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+
+ const showToast = (severity, icon) => {
+ toast.add({
+ severity,
+ ...commonToastConfig,
+ life: args.life ?? 5_000,
+ icon,
+ group: args.group,
+ });
+ };
+
+ return {
+ args,
+ showToast,
+ severities: SEVERITIES,
+ };
+ },
+ template: `
+
+
+
+
+
+
+
+
{{ message.summary }}
+
{{ message.detail }}
+
+
Дополнительный контент
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Заголовок сообщения
+
Дополнительная информация
+
+
Дополнительный контент
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const TemplateWidth = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+ const currentSize = ref(SIZES[1]);
+ const group = args?.group || 'width-preview';
+
+ const showToast = (size) => {
+ toast.removeGroup(group);
+ currentSize.value = size;
+
+ toast.add({
+ severity: 'info',
+ ...commonToastConfig,
+ detail: 'Ширина: ' + size.width,
+ life: args.life ?? 5_000,
+ group,
+ });
+ };
+
+ return {
+ currentSize,
+ sizes: SIZES,
+ showToast,
+ };
+ },
+ template: `
+
+
+
+
+
+
+
+
+
Заголовок сообщения
+
Ширина {{ key }}: {{ width }}
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const TemplatePosition = (args) => ({
+ components: { PBlockToast, Button },
+ setup() {
+ const toast = usePBlockToast();
+
+ const showToast = (group, position) => {
+ toast.add({
+ group,
+ severity: 'info',
+ ...commonToastConfig,
+ detail: 'Позиция: ' + position,
+ life: 5_000,
+ });
+ };
+
+ return {
+ args,
+ showToast,
+ positions: POSITIONS,
+ };
+ },
+ template: `
+
+ `,
+});
diff --git a/src/plugins/prime/theme3.0/components/css/toast.ts b/src/plugins/prime/theme3.0/components/css/toast.ts
new file mode 100644
index 00000000..9efd94fb
--- /dev/null
+++ b/src/plugins/prime/theme3.0/components/css/toast.ts
@@ -0,0 +1,205 @@
+const css = ({ dt }: { dt: (token: string) => string }) => `
+/* Основной контейнер toast-сообщения */
+.p-toast-message {
+ width: ${dt('toast.root.width')};
+ overflow: hidden;
+ border-width: ${dt('toast.root.borderWidth')};
+ border-radius: ${dt('toast.root.borderRadius')};
+ box-shadow: ${dt('toast.colorScheme.light.info.shadow')};
+ position: relative;
+}
+
+/* border-radius для контента toast-сообщения */
+.p-toast .p-toast-message .p-toast-message-content {
+ border-radius: ${dt('toast.root.borderRadius')};
+}
+
+/* svg-иконка */
+.p-toast .p-toast-message .p-toast-message-content .tabler-icon {
+ width: 2.25rem;
+ height: 2.25rem;
+ stroke: 1.5;
+}
+
+/* Заголовок toast */
+.p-toast-summary {
+ line-height: ${dt('fonts.lineHeight.250')};
+}
+
+/* Детальное описание toast */
+.p-toast-message .p-toast-detail {
+ line-height: ${dt('fonts.lineHeight.250')};
+}
+
+/* Кнопка закрытия toast-сообщения */
+.p-toast-message .p-toast-message-content .p-toast-close-button {
+ margin: 0;
+ padding: 0;
+ right: 0;
+}
+
+/* Общие стили border для кнопки закрытия всех типов toast */
+.p-toast-message-info .p-toast-close-button,
+.p-toast-message-success .p-toast-close-button,
+.p-toast-message-warn .p-toast-close-button,
+.p-toast-message-error .p-toast-close-button {
+ border: ${dt('toast.extend.extCloseButton.width')} solid;
+}
+
+/* Общие стили для акцентной линии всех типов toast */
+.p-toast-message-info .p-toast-accent-line,
+.p-toast-message-success .p-toast-accent-line,
+.p-toast-message-warn .p-toast-accent-line,
+.p-toast-message-error .p-toast-accent-line {
+ width: ${dt('toast.extend.extAccentLine.width')};
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ border-radius: ${dt('toast.root.borderRadius')} 0 0 ${dt(
+ 'toast.root.borderRadius'
+)};
+}
+
+.p-toast-close-button > i {
+ font-size: 1.25rem;
+}
+
+/* Размеры тоста через классы */
+.p-toast.p-toast-sm,
+.p-toast.p-toast-sm .p-toast-message {
+ width: ${dt('messages.sm.width')};
+}
+
+.p-toast.p-toast-lg,
+.p-toast.p-toast-lg .p-toast-message {
+ width: ${dt('messages.lg.width')};
+}
+
+.p-toast.p-toast-xlg,
+.p-toast.p-toast-xlg .p-toast-message {
+ width: ${dt('messages.xlg.width')};
+}
+
+/* Стили для toast типа Info */
+.p-toast-message-info .p-toast-message-icon,
+.p-toast-message-info .p-toast-message-content .tabler-icon {
+ color: ${dt('toast.extend.extInfo.color')};
+}
+
+.p-toast-message-info .p-toast-close-button {
+ color: ${dt('toast.extend.extInfo.closeButton.color')};
+ border-color: ${dt('toast.extend.extInfo.closeButton.borderColor')};
+}
+
+.p-toast-message.p-toast-message-info .p-toast-close-button.p-button-text:not(:disabled):hover {
+ background: ${dt('toast.colorScheme.light.info.closeButton.hoverBackground')};
+ border-color: ${dt('toast.extend.extInfo.closeButton.borderColor')};
+ color: ${dt('toast.extend.extInfo.closeButton.color')};
+}
+
+.p-toast-message-info .p-toast-accent-line {
+ background: ${dt('toast.extend.extInfo.color')};
+}
+
+.p-toast-message-info .p-toast-summary {
+ color: ${dt('toast.colorScheme.light.info.color')};
+}
+
+.p-toast-message-info .p-toast-detail {
+ color: ${dt('toast.colorScheme.light.info.detailColor')};
+}
+
+/* Стили для toast типа Success */
+.p-toast-message-success .p-toast-message-icon,
+.p-toast-message-success .p-toast-message-content .tabler-icon {
+ color: ${dt('toast.extend.extSuccess.color')};
+}
+
+.p-toast-message-success .p-toast-close-button {
+ color: ${dt('toast.extend.extSuccess.closeButton.color')};
+ border-color: ${dt('toast.extend.extSuccess.closeButton.borderColor')};
+}
+
+.p-toast-message.p-toast-message-success .p-toast-close-button.p-button-text:not(:disabled):hover {
+ background: ${dt(
+ 'toast.colorScheme.light.success.closeButton.hoverBackground'
+ )};
+ border-color: ${dt('toast.extend.extSuccess.closeButton.borderColor')};
+ color: ${dt('toast.extend.extSuccess.closeButton.color')};
+}
+
+.p-toast-message-success .p-toast-accent-line {
+ background: ${dt('toast.extend.extSuccess.color')};
+}
+
+.p-toast-message-success .p-toast-summary {
+ color: ${dt('toast.colorScheme.light.success.color')};
+}
+
+.p-toast-message-success .p-toast-detail {
+ color: ${dt('toast.colorScheme.light.success.detailColor')};
+}
+
+/* Стили для toast типа Warn */
+.p-toast-message-warn .p-toast-message-icon,
+.p-toast-message-warn .p-toast-message-content .tabler-icon {
+ color: ${dt('toast.extend.extWarn.color')};
+}
+
+.p-toast-message-warn .p-toast-close-button {
+ color: ${dt('toast.extend.extWarn.closeButton.color')};
+ border-color: ${dt('toast.extend.extWarn.closeButton.borderColor')};
+}
+
+.p-toast-message.p-toast-message-warn .p-toast-close-button.p-button-text:not(:disabled):hover {
+ background: ${dt('toast.colorScheme.light.warn.closeButton.hoverBackground')};
+ border-color: ${dt('toast.extend.extWarn.closeButton.borderColor')};
+ color: ${dt('toast.extend.extWarn.closeButton.color')};
+}
+
+.p-toast-message-warn .p-toast-accent-line {
+ background: ${dt('toast.extend.extWarn.color')};
+}
+
+.p-toast-message-warn .p-toast-summary {
+ color: ${dt('toast.colorScheme.light.warn.color')};
+}
+
+.p-toast-message-warn .p-toast-detail {
+ color: ${dt('toast.colorScheme.light.warn.detailColor')};
+}
+
+/* Стили для toast типа Error */
+.p-toast-message-error .p-toast-message-icon,
+.p-toast-message-error .p-toast-message-content .tabler-icon {
+ color: ${dt('toast.extend.extError.color')};
+}
+
+.p-toast-message-error .p-toast-close-button {
+ color: ${dt('toast.extend.extError.closeButton.color')};
+ border-color: ${dt('toast.extend.extError.closeButton.borderColor')};
+}
+
+.p-toast-message.p-toast-message-error .p-toast-close-button.p-button-text:not(:disabled):hover {
+ background: ${dt(
+ 'toast.colorScheme.light.error.closeButton.hoverBackground'
+ )};
+ border-color: ${dt('toast.extend.extError.closeButton.borderColor')};
+ color: ${dt('toast.extend.extError.closeButton.color')};
+}
+
+.p-toast-message-error .p-toast-accent-line {
+ background: ${dt('toast.extend.extError.color')};
+}
+
+.p-toast-message-error .p-toast-summary {
+ color: ${dt('toast.colorScheme.light.error.color')};
+}
+
+.p-toast-message-error .p-toast-detail {
+ color: ${dt('toast.colorScheme.light.error.detailColor')};
+}
+`;
+
+export default css;
diff --git a/src/plugins/prime/theme3.0/css.ts b/src/plugins/prime/theme3.0/css.ts
index 55362c06..93c5498d 100644
--- a/src/plugins/prime/theme3.0/css.ts
+++ b/src/plugins/prime/theme3.0/css.ts
@@ -1,5 +1,8 @@
-// const css = ({ dt }: { dt: (token: string) => string }) => `
-const css = () => `
+import toastCss from './components/css/toast';
+
+const css = ({ dt }: { dt: (token: string) => string }) => `
+ ${toastCss({ dt })}
+
.p-disabled, .p-component:disabled {
mix-blend-mode: luminosity;
}
diff --git a/src/plugins/prime/theme3.0/tokens.json b/src/plugins/prime/theme3.0/tokens.json
index a7d0103e..dc7530ad 100644
--- a/src/plugins/prime/theme3.0/tokens.json
+++ b/src/plugins/prime/theme3.0/tokens.json
@@ -672,6 +672,18 @@
"width": "{sizing.128x}"
}
},
+ "messages": {
+ "width": "{sizing.100x}",
+ "sm": {
+ "width": "{sizing.80x}"
+ },
+ "lg": {
+ "width": "{sizing.120x}"
+ },
+ "xlg": {
+ "width": "{sizing.128x}"
+ }
+ },
"feedback": {
"transitionDuration": "{transition.duration.200}",
"width": {
diff --git a/src/primeBlocks/PBlockToast/PBlockToast.vue b/src/primeBlocks/PBlockToast/PBlockToast.vue
new file mode 100644
index 00000000..9ff16ccb
--- /dev/null
+++ b/src/primeBlocks/PBlockToast/PBlockToast.vue
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ slotProps.message.summary }}
+
+
+ {{ slotProps.message.detail }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/primeBlocks/PBlockToast/usePBlockToast.ts b/src/primeBlocks/PBlockToast/usePBlockToast.ts
new file mode 100644
index 00000000..7a93254f
--- /dev/null
+++ b/src/primeBlocks/PBlockToast/usePBlockToast.ts
@@ -0,0 +1,42 @@
+import type { HintedString } from '@primevue/core';
+import { useToast } from 'primevue/usetoast';
+import type { ToastMessageOptions } from 'primevue/toast';
+
+export const PBlockToastMessageIcon = {
+ success: 'success',
+ info: 'info',
+ warn: 'warn',
+ error: 'error',
+} as const;
+
+export type PBlockToastMessageIconValues =
+ (typeof PBlockToastMessageIcon)[keyof typeof PBlockToastMessageIcon];
+
+export interface PBlockToastMessageOptions extends ToastMessageOptions {
+ severity?: HintedString;
+ icon?: string;
+}
+
+export function usePBlockToast() {
+ const toast = useToast();
+
+ const add = (config: PBlockToastMessageOptions) => {
+ const severity = config.severity || 'info';
+ const icon: string | PBlockToastMessageIconValues =
+ config?.icon || severity;
+
+ toast.add({
+ ...config,
+ closable: config?.closable || false,
+ // @ts-ignore
+ icon,
+ });
+ };
+
+ return {
+ add,
+ remove: toast.remove,
+ removeGroup: toast.removeGroup,
+ removeAllGroups: toast.removeAllGroups,
+ };
+}
diff --git a/src/primeBlocks/index.ts b/src/primeBlocks/index.ts
index c6023657..86606279 100644
--- a/src/primeBlocks/index.ts
+++ b/src/primeBlocks/index.ts
@@ -2,5 +2,16 @@ import PBlockPassword from './PBlockExample/PBlockPassword.vue';
import PBlockMenubar from './PBlockMenubar/PBlockMenubar.vue';
import PBlockMenuItem from './PBlockMenuItem/PBlockMenuItem.vue';
import PBlockToggleButton from './PBlockToggleButton/PBlockToggleButton.vue';
+import PBlockToast from './PBlockToast/PBlockToast.vue';
-export { PBlockPassword, PBlockMenubar, PBlockMenuItem, PBlockToggleButton };
+export {
+ PBlockPassword,
+ PBlockMenubar,
+ PBlockMenuItem,
+ PBlockToggleButton,
+ PBlockToast,
+};
+export {
+ usePBlockToast,
+ PBlockToastMessageIcon,
+} from './PBlockToast/usePBlockToast';
diff --git a/yarn.lock b/yarn.lock
index ec05e009..def5e514 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1294,6 +1294,13 @@
type-fest "~2.19"
vue-component-type-helpers latest
+"@tabler/icons-vue@3.22.0":
+ version "3.22.0"
+ resolved "https://registry.yarnpkg.com/@tabler/icons-vue/-/icons-vue-3.22.0.tgz#3919c344b22f9dfe7087be5d640a62262156dc4a"
+ integrity sha512-cgjvq+kjfqu7aJCAUmZByf+enUeLhSI7gVyWzBMCKNCehPoUHBmWNqM5zdnVJw/X2ogdvYL/H5arrSvKktH70Q==
+ dependencies:
+ "@tabler/icons" "3.22.0"
+
"@tabler/icons-webfont@^3.22.0":
version "3.34.1"
resolved "https://registry.npmjs.org/@tabler/icons-webfont/-/icons-webfont-3.34.1.tgz"
@@ -1302,6 +1309,11 @@
"@tabler/icons" "3.34.1"
sharp "^0.34.1"
+"@tabler/icons@3.22.0":
+ version "3.22.0"
+ resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.22.0.tgz#f937ec65d98710b891da6368559ea15cbcd87f91"
+ integrity sha512-IfgGzhFph5OBr2wTieWL/hyAs0FThnq9O155a6kfGYxqx7h5LQw91wnRswhEaGhXCcfmR7ZVDUr9H+x4b9Pb8g==
+
"@tabler/icons@3.34.1":
version "3.34.1"
resolved "https://registry.npmjs.org/@tabler/icons/-/icons-3.34.1.tgz"