From 6df5c30fa46ccffaef9e2a7aa2c242c9b6a98efa Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Fri, 24 Jan 2025 17:34:05 +0500 Subject: [PATCH 01/13] feat(services): add pub-sub --- services/pub-sub/.npmignore | 1 + services/pub-sub/README.md | 137 +++++++++++++++++++++++++++ services/pub-sub/package.json | 34 +++++++ services/pub-sub/src/index.ts | 3 + services/pub-sub/src/pubSub.tests.ts | 87 +++++++++++++++++ services/pub-sub/src/pubSub.ts | 108 +++++++++++++++++++++ services/pub-sub/tsconfig.build.json | 4 + services/pub-sub/tsconfig.json | 11 +++ 8 files changed, 385 insertions(+) create mode 100644 services/pub-sub/.npmignore create mode 100644 services/pub-sub/README.md create mode 100644 services/pub-sub/package.json create mode 100644 services/pub-sub/src/index.ts create mode 100644 services/pub-sub/src/pubSub.tests.ts create mode 100644 services/pub-sub/src/pubSub.ts create mode 100644 services/pub-sub/tsconfig.build.json create mode 100644 services/pub-sub/tsconfig.json diff --git a/services/pub-sub/.npmignore b/services/pub-sub/.npmignore new file mode 100644 index 00000000..85de9cf9 --- /dev/null +++ b/services/pub-sub/.npmignore @@ -0,0 +1 @@ +src diff --git a/services/pub-sub/README.md b/services/pub-sub/README.md new file mode 100644 index 00000000..0713649d --- /dev/null +++ b/services/pub-sub/README.md @@ -0,0 +1,137 @@ +# `@byndyusoft-ui/pub-sub` + +> A performant Pub/Sub interface with controlled instance management + +### Installation + +```bash +npm i @byndyusoft-ui/pub-sub +``` + +## Usage + +#### Import the class + +```ts +import PubSub from '@byndyusoft-ui/pub-sub'; +``` + +#### Define your channels +Create a type that defines the channels and their corresponding callback signatures. + +```ts +type ChannelsType = { + addTodo: (data: TodoType) => void; + removeTodo: (todoId: number) => void; + removeAll: () => void; +}; +``` + +#### Create an instance +Use the `getInstance` method to create or retrieve a singleton instance of `PubSub`. + +```ts +const pubSubInstance = PubSub.getInstance(); +``` + +#### Subscribe and unsubscribe to a channel +Remove a specific callback from a channel to stop receiving notifications. + +```ts +const addTodoCallback = (data: TodoType) => { + console.log('Added new todo:', data); +}; + +const removeTodoCallback = (todoId: number) => { + console.log(`Removed todo: ${todoId}`); +}; + +const removeAllCallback = () => { + console.log('All todos deleted'); +}; + +// subscribe +pubSubInstance.subscribe('addTodo', addTodoCallback); +pubSubInstance.subscribe('removeTodo', removeTodoCallback); +pubSubInstance.subscribe('removeAll', removeAllCallback); + +// unsubscribe +pubSubInstance.unsubscribe('addTodo', addTodoCallback); +pubSubInstance.unsubscribe('removeTodo', removeTodoCallback); +pubSubInstance.unsubscribe('removeAll', removeAllCallback); + +``` + +#### Publish to a channel + +```ts +pubSubInstance.publish('addTodo', { id: 1, text: 'Some todo'}); +pubSubInstance.publish('removeTodo', 1); +pubSubInstance.publish('removeAll'); +``` + +#### Publish asynchronously +Use publishAsync to publish data and handle asynchronous subscribers. + +```ts + +pubSubInstance.subscribe('asyncMessage', async (data) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + console.log(`Async received: ${data}`); +}); + +await pubSubInstance.publishAsync('asyncMessage', 'This is asynchronous!'); +``` + +#### Reset all subscriptions +Clear all channels and their associated subscribers. + +```ts +pubSubInstance.reset(); +``` + +#### Singleton Instances +`PubSub` supports multiple named singleton instances using instanceKey. +This allows you to create isolated instances for different parts of your application. + +> Note: If instanceKey is not provided, the instance with the default name `"_default"` will be used. + +Usage example: +```ts +import PubSub from '@byndyusoft-ui/pub-sub'; + +// Get the instance with the default name "_default" +const defaultPubSub = PubSub.getInstance(); + +// Get an instance with a custom name +const customPubSub = PubSub.getInstance('custom'); + +// Instances are isolated from each other +defaultPubSub.subscribe('event', (data) => { + console.log(`Default instance: ${data}`); +}); + +customPubSub.subscribe('event', (data) => { + console.log(`Custom instance: ${data}`); +}); + +// Publish events in different instances +defaultPubSub.publish('event', 'Hello from default!'); +customPubSub.publish('event', 'Hello from custom!'); +``` + +#### Adapter for Interfaces +If you're using `interface` instead of `type`, you can use the helper type +`ChannelsRecordAdapter` to ensure compatibility with the index signature: + +```ts +import { type ChannelsRecordAdapter } from '@byndyusoft-ui/pub-sub' + +interface TodoChannels { + addTodo: (data: TodoType) => void; + removeTodo: (todoId: number) => void; + removeAll: () => void; +} + +const pubSubInstance = PubSub.getInstance>(); +``` diff --git a/services/pub-sub/package.json b/services/pub-sub/package.json new file mode 100644 index 00000000..b6ccbb9e --- /dev/null +++ b/services/pub-sub/package.json @@ -0,0 +1,34 @@ +{ + "name": "@byndyusoft-ui/pub-sub", + "version": "0.0.1", + "description": "Byndyusoft UI Service", + "keywords": [ + "byndyusoft", + "byndyusoft-ui", + "channels", + "publish", + "subscribe", + "Pub/Sub" + ], + "author": "Gleb Fomin ", + "homepage": "https://github.com/Byndyusoft/ui/tree/master/services/pub-sub#readme", + "license": "Apache-2.0", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/Byndyusoft/ui.git" + }, + "scripts": { + "build": "tsc --project tsconfig.build.json", + "clean": "rimraf dist", + "lint": "eslint src --config ../../eslint.config.js", + "test": "jest --config ../../jest.config.js --roots services/pub-sub/src" + }, + "bugs": { + "url": "https://github.com/Byndyusoft/ui/issues" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/services/pub-sub/src/index.ts b/services/pub-sub/src/index.ts new file mode 100644 index 00000000..71ac867a --- /dev/null +++ b/services/pub-sub/src/index.ts @@ -0,0 +1,3 @@ +export { default } from './pubSub'; + +export type { ChannelsRecordAdapter } from './pubSub'; diff --git a/services/pub-sub/src/pubSub.tests.ts b/services/pub-sub/src/pubSub.tests.ts new file mode 100644 index 00000000..caccc734 --- /dev/null +++ b/services/pub-sub/src/pubSub.tests.ts @@ -0,0 +1,87 @@ +import PubSub from './pubSub'; + +type TChannels = { + testChannel: (data?: string) => void; + asyncChannel: (data?: string) => Promise; +}; + +describe('services/pub-sub', () => { + let pubSub: PubSub; + + beforeEach(() => { + pubSub = PubSub.getInstance(); + }); + + afterEach(() => { + pubSub.reset(); + }); + + test('should create a new instance and get the same instance for the same key', () => { + const instance1 = PubSub.getInstance('instance1'); + const instance2 = PubSub.getInstance('instance1'); + const instance3 = PubSub.getInstance('instance2'); + + expect(instance1).toBe(instance2); + expect(instance1).not.toBe(instance3); + }); + + test('should subscribe and publish to a channel', () => { + const callback = jest.fn(); + pubSub.subscribe('testChannel', callback); + + pubSub.publish('testChannel', 'Hello, World!'); + + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith('Hello, World!'); + }); + + test('should not call callback if no subscribers', () => { + const callback = jest.fn(); + pubSub.publish('testChannel'); + + expect(callback).not.toHaveBeenCalled(); + }); + + test('should unsubscribe from a channel', () => { + const callback = jest.fn(); + pubSub.subscribe('testChannel', callback); + pubSub.unsubscribe('testChannel', callback); + + pubSub.publish('testChannel'); + + expect(callback).not.toHaveBeenCalled(); + }); + + test('should warn if no subscribers are present for a channel', () => { + console.warn = jest.fn(); + + pubSub.publish('testChannel', 'No one is listening'); + + expect(console.warn).toHaveBeenCalledWith('No subscribers for channel: testChannel'); + }); + + test('should handle async subscribe callbacks', async () => { + const asyncCallback = jest.fn().mockResolvedValue(undefined); + pubSub.subscribe('asyncChannel', asyncCallback); + + await pubSub.publishAsync('asyncChannel', 'Async data'); + + expect(asyncCallback).toHaveBeenCalledTimes(1); + expect(asyncCallback).toHaveBeenCalledWith('Async data'); + }); + + test('should reset all subscriptions', () => { + const callback1 = jest.fn(); + const callback2 = jest.fn(); + + pubSub.subscribe('testChannel', callback1); + pubSub.subscribe('testChannel', callback2); + + pubSub.reset(); + + pubSub.publish('testChannel'); + + expect(callback1).not.toHaveBeenCalled(); + expect(callback2).not.toHaveBeenCalled(); + }); +}); diff --git a/services/pub-sub/src/pubSub.ts b/services/pub-sub/src/pubSub.ts new file mode 100644 index 00000000..35a9030e --- /dev/null +++ b/services/pub-sub/src/pubSub.ts @@ -0,0 +1,108 @@ +type TDefaultChannels = Record void>; + +type TChannelMap = Map< + keyof ChannelsRecord, + Set +>; + +type TPubSubInstances = Map; + +type TChannelData = Parameters< + ChannelsRecord[ChannelKey] +>[0]; + +type ChannelsRecordAdapter = { [K in keyof T]: T[K] }; + +const DEFAULT_NAME_INSTANCE = '_default'; + +class PubSub { + private static instances: TPubSubInstances = new Map(); + private channels: TChannelMap = new Map(); + + private constructor() {} + + /** + * Getting an instance of a class. + */ + static getInstance( + instanceKey: string = DEFAULT_NAME_INSTANCE + ): PubSub { + if (!this.instances.get(instanceKey)) { + this.instances.set(instanceKey, new PubSub()); + } + + return this.instances.get(instanceKey) as PubSub; + } + + /** + * Subscribe to the channel. + */ + subscribe( + channel: ChannelKey, + callback: ChannelsRecord[ChannelKey] + ): void { + if (!this.channels.has(channel)) { + this.channels.set(channel, new Set()); + } + (this.channels.get(channel) as Set).add(callback); + } + + /** + * Unsubscribe from the channel. + */ + unsubscribe( + channel: ChannelKey, + callback: ChannelsRecord[ChannelKey] + ): void { + const channelSet = this.channels.get(channel); + if (channelSet) { + channelSet.delete(callback); + if (channelSet.size === 0) { + this.channels.delete(channel); + } + } + } + + /** + * Publishing to the channel. + */ + publish( + channel: ChannelKey, + data?: TChannelData + ): void { + const channelSet = this.channels.get(channel); + if (channelSet) { + for (const callback of channelSet) { + callback(data); + } + } else { + console.warn(`No subscribers for channel: ${channel as string}`); + } + } + + async publishAsync( + channel: ChannelKey, + data?: TChannelData + ): Promise { + const channelSet = this.channels.get(channel); + if (channelSet) { + for (const callback of channelSet) { + if (callback) { + await callback(data); + } + } + } else { + console.warn(`No subscribers for channel: ${channel as string}`); + } + } + + /** + * Reset all subscriptions. + */ + reset(): void { + this.channels.clear(); + } +} + +export type { ChannelsRecordAdapter }; +export default PubSub; diff --git a/services/pub-sub/tsconfig.build.json b/services/pub-sub/tsconfig.build.json new file mode 100644 index 00000000..b4b36060 --- /dev/null +++ b/services/pub-sub/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["src/*.tests.ts"] +} diff --git a/services/pub-sub/tsconfig.json b/services/pub-sub/tsconfig.json new file mode 100644 index 00000000..5b7870da --- /dev/null +++ b/services/pub-sub/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "dist", + "outDir": "dist", + "module": "commonjs", + "target": "es6" + }, + "include": ["src"] +} From 9140df76d75d2ffa6d47aeb44d0816603e3092b8 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Mon, 27 Jan 2025 09:42:24 +0500 Subject: [PATCH 02/13] chore(pub-sub): move types to a separate file --- services/pub-sub/src/index.ts | 2 +- services/pub-sub/src/pubSub.ts | 16 +--------------- services/pub-sub/src/pubSub.types.ts | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 services/pub-sub/src/pubSub.types.ts diff --git a/services/pub-sub/src/index.ts b/services/pub-sub/src/index.ts index 71ac867a..ebf70700 100644 --- a/services/pub-sub/src/index.ts +++ b/services/pub-sub/src/index.ts @@ -1,3 +1,3 @@ export { default } from './pubSub'; -export type { ChannelsRecordAdapter } from './pubSub'; +export type { ChannelsRecordAdapter } from './pubSub.types'; diff --git a/services/pub-sub/src/pubSub.ts b/services/pub-sub/src/pubSub.ts index 35a9030e..a2b83178 100644 --- a/services/pub-sub/src/pubSub.ts +++ b/services/pub-sub/src/pubSub.ts @@ -1,17 +1,4 @@ -type TDefaultChannels = Record void>; - -type TChannelMap = Map< - keyof ChannelsRecord, - Set ->; - -type TPubSubInstances = Map; - -type TChannelData = Parameters< - ChannelsRecord[ChannelKey] ->[0]; - -type ChannelsRecordAdapter = { [K in keyof T]: T[K] }; +import { TChannelData, TChannelMap, TDefaultChannels, TPubSubInstances } from './pubSub.types'; const DEFAULT_NAME_INSTANCE = '_default'; @@ -104,5 +91,4 @@ class PubSub { } } -export type { ChannelsRecordAdapter }; export default PubSub; diff --git a/services/pub-sub/src/pubSub.types.ts b/services/pub-sub/src/pubSub.types.ts new file mode 100644 index 00000000..df78ebb8 --- /dev/null +++ b/services/pub-sub/src/pubSub.types.ts @@ -0,0 +1,14 @@ +export type TDefaultChannels = Record void>; + +export type TChannelMap = Map< + keyof ChannelsRecord, + Set +>; + +export type TPubSubInstances = Map; + +export type TChannelData = Parameters< + ChannelsRecord[ChannelKey] +>[0]; + +export type ChannelsRecordAdapter = { [K in keyof T]: T[K] }; From 3ad7636140655aa4c68091e4e8baca1bf80e57e1 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Wed, 29 Jan 2025 16:36:06 +0500 Subject: [PATCH 03/13] feat(components): add notifications, update readme and stories --- components/notifications/.npmignore | 3 + components/notifications/README.md | 234 ++ components/notifications/package.json | 40 + components/notifications/rollup.config.js | 15 + .../notifications/src/Notifications.types.ts | 106 + .../src/NotificationsManager.css | 78 + .../src/NotificationsManager.tsx | 107 + .../Notifications.stories.module.css | 93 + .../src/__stories__/Notifications.stories.tsx | 273 ++ .../src/components/NotificationsItem.css | 170 ++ .../components/NotificationsItem.module.css | 170 ++ .../src/components/NotificationsItem.tsx | 100 + components/notifications/src/constants.ts | 6 + .../src/hooks/use-document-visibility.ts | 15 + .../src/hooks/useNotificationsActions.ts | 14 + .../src/hooks/useNotificationsManager.ts | 134 + components/notifications/src/index.ts | 5 + .../src/services/notifications.service.ts | 110 + .../services/notificationsPubSub.service.ts | 10 + components/notifications/src/utilities.ts | 21 + components/notifications/tsconfig.json | 10 + package-lock.json | 2192 ++++++++++++++--- 22 files changed, 3616 insertions(+), 290 deletions(-) create mode 100644 components/notifications/.npmignore create mode 100644 components/notifications/README.md create mode 100644 components/notifications/package.json create mode 100644 components/notifications/rollup.config.js create mode 100644 components/notifications/src/Notifications.types.ts create mode 100644 components/notifications/src/NotificationsManager.css create mode 100644 components/notifications/src/NotificationsManager.tsx create mode 100644 components/notifications/src/__stories__/Notifications.stories.module.css create mode 100644 components/notifications/src/__stories__/Notifications.stories.tsx create mode 100644 components/notifications/src/components/NotificationsItem.css create mode 100644 components/notifications/src/components/NotificationsItem.module.css create mode 100644 components/notifications/src/components/NotificationsItem.tsx create mode 100644 components/notifications/src/constants.ts create mode 100644 components/notifications/src/hooks/use-document-visibility.ts create mode 100644 components/notifications/src/hooks/useNotificationsActions.ts create mode 100644 components/notifications/src/hooks/useNotificationsManager.ts create mode 100644 components/notifications/src/index.ts create mode 100644 components/notifications/src/services/notifications.service.ts create mode 100644 components/notifications/src/services/notificationsPubSub.service.ts create mode 100644 components/notifications/src/utilities.ts create mode 100644 components/notifications/tsconfig.json diff --git a/components/notifications/.npmignore b/components/notifications/.npmignore new file mode 100644 index 00000000..2b07fde8 --- /dev/null +++ b/components/notifications/.npmignore @@ -0,0 +1,3 @@ +src +rollup.config.js +tsconfig.json diff --git a/components/notifications/README.md b/components/notifications/README.md new file mode 100644 index 00000000..8d647ee6 --- /dev/null +++ b/components/notifications/README.md @@ -0,0 +1,234 @@ +# `@byndyusoft-ui/notifications` + +The `Nptofications` component is a ... + +## Installation + +```sh +npm i @byndyusoft-ui/notifications +# or +yarn add @byndyusoft-ui/notifications +``` + + +## Usage + +```tsx +import React from 'react'; +import NotificationsManager, {useNotifications, INotificationData} from '@byndyusoft-ui/notifications'; + + +const SomeComponent = () => { + const {success} = useNotifications(); + + const onShowSuccess = () => { + success({ + title: 'Some string', + message: 'Some ReactNode...', + footer: 'Some ReactNode...', + }) + } + + return ( + + ) +} + +const NotificationComponent = ({data}: INotificationData) => ( +
+ {data.title} + {data?.message &&
{data.message}
} + {data?.footer &&
{data.footer}
} + {data?.isClosable && ( + + )} +
+) + +const App = () => { + return ( +
+ + +
+ ) +} + +export default App; +``` + +# API + +## NotificationsManager + +### Props + +| Props | Type | Default | Description | +|------------------------------|-------------------------------|----------------|--------------------------------------------------------------------------------------| +| position | `TNotificationPosition` | "top-right" | One of top-right, top-center, top-left, bottom-right, bottom-center, bottom-left | +| duration | number | 5000 | Duration in ms to close the notification. | +| isClosable | boolean | true | Allows manual closing of the notification. | +| isAutoClosable | boolean | true | Automatically closes the notification after the specified duration. | +| isPauseWhenPageHidden | boolean | true | Pauses the notification timer when the page is hidden. | +| isPauseOnHover | boolean | true | Pauses the notification timer on hover. | +| isCloseOnClick | boolean | false | Closes the notification when clicked. | +| isNewestOnTop | boolean | false | Displays new notifications on top of older ones. | +| limit | number | - | The maximum number of notifications displayed simultaneously at a specific position. | +| renderNotification | `TNotificationRender` | - | Component for rendering notifications. | +| renderNotificationComponents | `TNotificationRecordRender` | - | Object with components for rendering different types of notifications. | +| offset | `TPlatformValue` | 24 | Offset for web and mobile versions. | +| gap | `TPlatformValue` | 8 | Gap between notifications for web and mobile versions. | +| width | string \| number | 356 | Width of the notifications. | +| className | string | - | Class for the notification list container. | +| classNameItem | string | - | Class for each notification item. | +| style | CSSProperties | - | Style object for the notification list container. | +| styleItem | CSSProperties | - | Style object for each notification item. | + +### Usages + +```tsx +import NotificationsManager from '@byndyusoft-ui/notifications'; + + + JSX + renderNotificationComponents={{ + success: SuccessNotification, + danger: DangerNotification, + info: InfoNotification, + warning: WarningNotification, + ordinary: OrdinaryNotification, + }} +/> +``` + +> #### Notes +> - `renderNotificationComponents` allows you to set a component personally for each `theme` of notification (e.g., `success`, `danger`, `info`, `warning`, `ordinary`). +> - If you use `renderNotification`, then `renderNotificationComponents` will override the components for all notification themes. + +## Emitter (useNotifications) + +### Params create + +> When displaying a notification , the options are inherited from the container. Notification options supersede Notifications Manager props + +| Options | Type | Description | +|----------------|-------------------------|---------------------------------------------------------------------| +| id | string \| number | Identifier for the notification. | +| position | `TNotificationPosition` | Position of the notification. | +| duration | number | Duration in ms to close notification | +| title | string | Title of the notification. | +| message | ReactNode | Main content of the notification. | +| footer | ReactNode | Footer content of the notification. | +| isClosable | boolean | Allows manual closing of the notification. | +| isAutoClosable | boolean | Automatically closes the notification after the specified duration. | +| isCloseOnClick | boolean | Closes the notification when clicked. | +| render | `TNotificationRender` | Component for rendering the notification. | +| theme | `TNotificationTheme` | Theme of the notification. | +| afterClose | () => void | Callback function to be executed after the notification is closed. | +| className | string | Class for the notification container. | +| style | CSSProperties | Style object for the notification container. | + +### Usages + +```ts +import { useNotifications } from '@byndyusoft-ui/notifications'; + + +const options = { + position: "top-left", + duration: 3000, + title: 'Some string', + message: 'Some ReactNode...', + footer: 'Some ReactNode...', + isClosable: true, + isAutoClosable: true, + isCloseOnClick: false, + className: 'some-class', + style: { + // ...styles + }, + afterClose: () => console.log("afterClose"), +}; + +const notifications = useNotifications() + +notifications.success(options) +notifications.danger(options) +notifications.info(options) +notifications.warning(options) +notifications.ordinary(options) +``` + +### Types + +#### TNotificationPosition + +```ts +type TNotificationPosition = + | 'top-left' + | 'top-right' + | 'bottom-left' + | 'bottom-right' + | 'top-center' + | 'bottom-center'; +``` + +#### TNotificationRender + +```ts +interface INotificationData { + data: INotificationsItem; + index: number; +} + +type TNotificationRender = ((params: INotificationData) => ReactNode) | ReactNode; +``` + +#### TNotificationRecordRender + +```ts +type TNotificationRecordRender = Partial, TNotificationRender>>; +``` + +#### TPlatformValue + +```ts +type TPlatformValue = + | string + | number + | { + web: string | number; + mobile: string | number; +}; +``` + +#### TNotificationTheme +```ts +type TNotificationTheme = 'success' | 'info' | 'warning' | 'danger' | 'custom' | 'ordinary'; +``` diff --git a/components/notifications/package.json b/components/notifications/package.json new file mode 100644 index 00000000..a4d2a1a2 --- /dev/null +++ b/components/notifications/package.json @@ -0,0 +1,40 @@ +{ + "name": "@byndyusoft-ui/notifications", + "version": "1.0.0", + "description": "Byndyusoft UI Portal React Component", + "keywords": [ + "byndyusoft", + "byndyusoft-ui", + "react", + "notifications" + ], + "author": "", + "homepage": "", + "license": "ISC", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/Byndyusoft/ui.git" + }, + "scripts": { + "build": "rollup --config", + "clean": "rimraf dist", + "lint": "eslint src --config ../../eslint.config.js", + "test": "jest --config ../../jest.config.js --roots components/notifications/src" + }, + "bugs": { + "url": "https://github.com/Byndyusoft/ui/issues" + }, + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "@byndyusoft-ui/types": "^0.1.0" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17", + "@byndyusoft-ui/pub-sub": "^0.0.1" + } +} diff --git a/components/notifications/rollup.config.js b/components/notifications/rollup.config.js new file mode 100644 index 00000000..231a2aca --- /dev/null +++ b/components/notifications/rollup.config.js @@ -0,0 +1,15 @@ +import typescript from '@rollup/plugin-typescript'; +import baseConfig from '../../rollup.base.config'; + +export default { + ...baseConfig, + input: ['src/index.ts'], + plugins: [ + ...baseConfig.plugins, + typescript({ + tsconfig: './tsconfig.json', + module: 'ESNext', + exclude: ['src/**/*.stories.tsx', 'src/__tests__/*', 'node_modules'] + }) + ] +}; diff --git a/components/notifications/src/Notifications.types.ts b/components/notifications/src/Notifications.types.ts new file mode 100644 index 00000000..0864db5b --- /dev/null +++ b/components/notifications/src/Notifications.types.ts @@ -0,0 +1,106 @@ +import { CSSProperties, ReactNode } from 'react'; +import { Callback } from '@byndyusoft-ui/types'; + +export type TNotificationItemId = string | number; + +export type TNotificationTheme = 'success' | 'info' | 'warning' | 'danger' | 'custom' | 'ordinary'; + +export type TNotificationPosition = + | 'top-left' + | 'top-right' + | 'bottom-left' + | 'bottom-right' + | 'top-center' + | 'bottom-center'; + +export interface INotification { + theme?: TNotificationTheme; + title?: string; + message?: ReactNode; + footer?: ReactNode; + isClosable?: boolean; + onClose?: Callback; + afterClose?: Callback; + className?: string; + style?: CSSProperties; +} + +export interface INotificationData { + data: INotificationsItem; + index: number; +} + +export type TNotificationRender = ((params: INotificationData) => ReactNode) | ReactNode; + +export type TNotificationRecordRender = Partial, TNotificationRender>>; + +export interface INotificationsItem extends INotification { + id: TNotificationItemId; + position?: TNotificationPosition; + duration?: number; + isClosable?: boolean; + isAutoClosable?: boolean; + dismiss?: boolean; + isCloseOnClick?: boolean; + render?: TNotificationRender; +} + +export type TCreateNotificationParams = Partial>; + +export type TThemedNotificationParams = Omit, 'theme' | 'render' | 'onClose' | 'dismiss'>; + +export type TCustomNotificationParams = Partial< + Omit +>; + +export type TPlatformValue = + | string + | number + | { + web: string | number; + mobile: string | number; + }; + +export interface INotificationsManagerProps { + position?: TNotificationPosition; + duration?: number; + isClosable?: boolean; + isAutoClosable?: boolean; + isPauseWhenPageHidden?: boolean; + isPauseOnHover?: boolean; + isCloseOnClick?: boolean; + isNewestOnTop?: boolean; + limit?: number; + renderNotification?: TNotificationRender; + renderNotificationComponents?: TNotificationRecordRender; + offset?: TPlatformValue; + gap?: TPlatformValue; + width?: string | number; + className?: string; + classNameItem?: string; + style?: CSSProperties; + styleItem?: CSSProperties; +} + +export interface IUseNotificationsStateParams { + position: TNotificationPosition; + isCloseOnClick: boolean; + isClosable: boolean; + limit?: number; + isNewestOnTop?: boolean; + renderNotification?: TNotificationRender; + renderNotificationComponents?: TNotificationRecordRender; +} + +export interface INotificationsItemProps { + children: ReactNode; + duration: number; + position: TNotificationPosition; + removeNotification: () => void; + isAutoClosable?: boolean; + dismiss?: boolean; + isPauseToRemove?: boolean; + onClick?: () => void; + className?: string; + style?: CSSProperties; +} diff --git a/components/notifications/src/NotificationsManager.css b/components/notifications/src/NotificationsManager.css new file mode 100644 index 00000000..31857fff --- /dev/null +++ b/components/notifications/src/NotificationsManager.css @@ -0,0 +1,78 @@ +.notifications { + margin: 0; + padding: 0; + position: fixed; + z-index: 99999; + display: flex; + flex-direction: column; + gap: var(--gap-mobile); + width: calc(100% - var(--offset-mobile) * 2); + list-style-type: none; +} + +.notifications__top-left, +.notifications__top-right, +.notifications__top-center { + top: var(--offset-mobile); + left: var(--offset-mobile); + right: var(--offset-mobile); + transform: none; +} + +.notifications__bottom-left, +.notifications__bottom-right, +.notifications__bottom-center { + bottom: var(--offset-mobile); + left: var(--offset-mobile); + right: var(--offset-mobile); + transform: none; +} + +@media (min-width: 768px) { + .notifications { + width: var(--width); + gap: var(--gap); + } + + .notifications__top-left { + top: var(--offset); + left: var(--offset); + right: auto; + transform: none; + } + + .notifications__top-right { + top: var(--offset); + right: var(--offset); + left: auto; + transform: none; + } + + .notifications__bottom-left { + bottom: var(--offset); + left: var(--offset); + right: auto; + transform: none; + } + + .notifications__bottom-right { + bottom: var(--offset); + right: var(--offset); + left: auto; + transform: none; + } + + .notifications__top-center { + top: var(--offset); + left: 50%; + right: auto; + transform: translateX(-50%); + } + + .notifications__bottom-center { + bottom: var(--offset); + left: 50%; + right: auto; + transform: translateX(-50%); + } +} diff --git a/components/notifications/src/NotificationsManager.tsx b/components/notifications/src/NotificationsManager.tsx new file mode 100644 index 00000000..140bd589 --- /dev/null +++ b/components/notifications/src/NotificationsManager.tsx @@ -0,0 +1,107 @@ +import React, { CSSProperties, useState } from 'react'; +import Portal from '@byndyusoft-ui/portal'; +import { normalizeCssValue, normalizePlatformValue } from './utilities'; +import { NotificationsItem } from './components/NotificationsItem'; +import { useIsDocumentHidden } from './hooks/use-document-visibility'; +import { INotificationsManagerProps, TNotificationPosition } from './Notifications.types'; +import { useNotificationsManager } from './hooks/useNotificationsManager'; +import { cn } from './utilities'; +import { NOTIFICATION_LIFETIME, OFFSET, POSITION, NOTIFICATION_WIDTH, GAP } from './constants'; +import './NotificationsManager.css'; + +const NotificationsManager = (props: INotificationsManagerProps) => { + const { + position = POSITION, + duration = NOTIFICATION_LIFETIME, + limit, + renderNotification, + renderNotificationComponents, + isPauseWhenPageHidden = true, + isPauseOnHover = true, + isClosable = true, + isAutoClosable = true, + isCloseOnClick = false, + isNewestOnTop = false, + gap, + offset, + width, + className, + classNameItem, + style, + styleItem + } = props; + + const [focusedPosition, setFocusedPosition] = useState(null); // Хранение текущей позиции + + const { + notifications, + possiblePositions, + onClickAndClose, + removeNotification, + renderNotificationItem, + prepareNotifications + } = useNotificationsManager({ + position, + isCloseOnClick, + isClosable, + isNewestOnTop, + limit, + renderNotification, + renderNotificationComponents + }); + + const isDocumentHidden = useIsDocumentHidden(); + + if (!notifications?.length) return null; + + return ( + + {possiblePositions?.map((position, positionIndex) => { + const preparedNotifications = prepareNotifications(position, positionIndex); + + if (!preparedNotifications?.length) return null; + + return ( +
    setFocusedPosition(position)} + onMouseLeave={() => setFocusedPosition(null)} + > + {preparedNotifications?.map((item, itemIndex) => ( + + {renderNotificationItem(item, itemIndex)} + + ))} +
+ ); + })} +
+ ); +}; + +export default NotificationsManager; diff --git a/components/notifications/src/__stories__/Notifications.stories.module.css b/components/notifications/src/__stories__/Notifications.stories.module.css new file mode 100644 index 00000000..76c6c0b0 --- /dev/null +++ b/components/notifications/src/__stories__/Notifications.stories.module.css @@ -0,0 +1,93 @@ +.container { + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; +} + +.row { + display: flex; + align-items: center; + gap: 8px; +} + +.col { + display: flex; + flex-direction: column; + gap: 8px; +} + +.row > button { + border-radius: 8px; + border: 1px solid transparent; + padding: 6px 12px; + font-size: 1em; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: border-color 0.25s; + white-space: nowrap; +} +.row > button:hover { + border-color: #646cff; +} + +.row > .button_active { + background: #646cff; + color: white; +} + +.notification{ + box-sizing: border-box; + position: relative; + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; + padding: 8px; + border-radius: 6px; + color: black; +} + +.notification.success { + background: #48ffc8; +} + +.notification.danger { + background: #ff484e; +} + +.notification.info { + background: #48b9ff; +} + +.notification.warning { + background: #ff8b48; +} + +.notification.ordinary { + background: #d7d7d7; +} + +.notification_close_btn { + box-sizing: border-box; + position: absolute; + top: 4px; + right: 4px; + border: none; + background: none; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: center; +} + +.code { + background-color: #f0eded; + color: #333; + padding: 10px; + border-radius: 5px; + overflow-x: auto; + font-family: 'Courier New, Courier, monospace', serif; + font-size: 14px; +} diff --git a/components/notifications/src/__stories__/Notifications.stories.tsx b/components/notifications/src/__stories__/Notifications.stories.tsx new file mode 100644 index 00000000..1a5d3abb --- /dev/null +++ b/components/notifications/src/__stories__/Notifications.stories.tsx @@ -0,0 +1,273 @@ +import React, { ChangeEvent, Dispatch, SetStateAction, useState } from 'react'; +import { StoryObj } from '@storybook/react'; +import NotificationsManager, { useNotifications, INotificationData } from '..'; +import { TNotificationPosition, TNotificationTheme } from '../Notifications.types'; +import styles from './Notifications.stories.module.css'; +import { NotificationsItem } from '../components/NotificationsItem'; + +const positions: TNotificationPosition[] = [ + 'top-right', + 'top-left', + 'top-center', + 'bottom-right', + 'bottom-left', + 'bottom-center' +]; +const themes: TNotificationTheme[] = ['success', 'danger', 'info', 'warning', 'ordinary', 'custom']; + +const NotificationComponent = ({ data }: INotificationData): JSX.Element => { + return ( +
+ {data.title} + {data?.message &&
{data.message}
} + {data?.footer &&
{data.footer}
} + {data?.isClosable && ( + + )} +
+ ); +}; + +const Template = (): JSX.Element => { + const [activePosition, setActivePosition] = useState('top-right'); + const [activeTheme, setActiveTheme] = useState('ordinary'); + const [duration, setDuration] = useState(5000); + const [limit, setLimit] = useState(0); + const [isCloseOnClick, setIsCloseOnClick] = useState(false); + const [isPauseWhenPageHidden, setIsPauseWhenPageHidden] = useState(true); + const [isPauseOnHover, setIsPauseOnHover] = useState(true); + const [isNewestOnTop, setIsNewestOnTop] = useState(false); + const [isClosable, setIsClosable] = useState(true); + const [isAutoClosable, setIsAutoClosable] = useState(true); + + const { custom, create, dismissAll } = useNotifications(); + + const handleChangeInputNumber = (set: Dispatch>) => (e: ChangeEvent) => { + const numericValue = e.target.value.replace(/[^0-9]/g, ''); + set(Number(numericValue)); + }; + + const onShowNotification = () => { + if (activeTheme === 'custom') { + custom(({ index }) =>
{index} | Custom notification
, { + position: activePosition, + duration, + isCloseOnClick, + isAutoClosable + }); + } else { + create({ + position: activePosition, + theme: activeTheme, + title: `🔔 Notification ${activeTheme}`, + message: 'Notification message', + footer: new Date().toDateString(), + duration, + isCloseOnClick, + isClosable, + isAutoClosable + }); + } + }; + + const renderEmitterCode = () => { + const baseCode = (type?: string) => ` +${type}({ + title: \`🔔 Notification ${activeTheme}\`, + message: 'Notification message', + footer: new Date().toDateString(), + position: ${activePosition}, + delay: ${duration}, + isCloseOnClick: ${isCloseOnClick} + isClosable: ${isClosable} + isAutoClosable: ${isAutoClosable} +});`; + + if (activeTheme === 'custom') { + return ` +custom(({data}) =>
{data.id} | Custom notification
, + { + position: ${activePosition}, + duration: ${duration}, + isCloseOnClick: ${isCloseOnClick} + isAutoClosable: ${isAutoClosable} + } +);`; + } + + return baseCode(activeTheme); + }; + + return ( +
+

Notifications

+ + + +
+
+

Notifications Container

+
+                        
+                            {``}
+                        
+                    
+
+
+

Notification Emitter

+
+                        {renderEmitterCode()}
+                    
+
+
+ +
+
+

Position

+
+ {positions.map(position => ( + + ))} +
+
+
+

Theme

+
+ {themes.map(theme => ( + + ))} +
+
+
+

Options

+ + + + + + + + + +
+
+ + + +
+
+
+
+ ); +}; + +export const NotificationsStory: StoryObj = { + name: 'Notifications tory', + render: Template, + args: {} +}; + +export default { + title: 'components/Notifications' + // parameters: { + // layout: 'fullscreen' + // } +}; diff --git a/components/notifications/src/components/NotificationsItem.css b/components/notifications/src/components/NotificationsItem.css new file mode 100644 index 00000000..332bb26f --- /dev/null +++ b/components/notifications/src/components/NotificationsItem.css @@ -0,0 +1,170 @@ +.notifications__item { + overflow: hidden; + position: relative; + opacity: 1; + height: auto; +} + +.notifications__item--clickable { + cursor: pointer; +} + +/* Мобильная версия (по умолчанию) */ +.notifications__animation--bottom-left, +.notifications__animation--bottom-right, +.notifications__animation--bottom-center { + animation: slideInTop 0.3s ease-out forwards; +} + +.notifications__animation--bottom-left.notifications__item--hidden, +.notifications__animation--bottom-right.notifications__item--hidden, +.notifications__animation--bottom-center.notifications__item--hidden { + animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + +.notifications__animation--top-left, +.notifications__animation--top-right, +.notifications__animation--top-center { + animation: slideInBottom 0.2s ease-out forwards; +} + +.notifications__animation--top-left.notifications__item--hidden, +.notifications__animation--top-right.notifications__item--hidden, +.notifications__animation--top-center.notifications__item--hidden { + animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + +@keyframes collapseHeight { + 0% { + max-height: 800px; + } + 100% { + max-height: 0; + } +} + +@keyframes slideInLeft { + 0% { + transform: translateX(100%); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes slideOutRight { + 0% { + transform: translateX(0); + opacity: 1; + } + 100% { + transform: translateX(100%); + opacity: 0; + } +} + +@keyframes slideInRight { + 0% { + transform: translateX(-100%); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes slideOutLeft { + 0% { + transform: translateX(0); + opacity: 1; + } + 100% { + transform: translateX(-100%); + opacity: 0; + } +} + +@keyframes slideInBottom { + 0% { + transform: translateY(-100%); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes slideOutTop { + 0% { + transform: translateY(0); + opacity: 1; + } + 100% { + transform: translateY(-100%); + opacity: 0; + } +} + +@keyframes slideInTop { + 0% { + transform: translateY(100%); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes slideOutBottom { + 0% { + transform: translateY(0); + opacity: 1; + } + 100% { + transform: translateY(100%); + opacity: 0; + } +} + +@media (min-width: 768px) { + .notifications__animation--bottom-left, + .notifications__animation--top-left { + animation: slideInRight 0.3s ease-out forwards; + } + + .notifications__animation--bottom-left.notifications__item--hidden, + .notifications__animation--top-left.notifications__item--hidden { + animation: slideOutLeft 0.2s ease-in forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .notifications__animation--bottom-right, + .notifications__animation--top-right { + animation: slideInLeft 0.3s ease-out forwards; + } + + .notifications__animation--bottom-right.notifications__item--hidden, + .notifications__animation--top-right.notifications__item--hidden { + animation: slideOutRight 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .notifications__animation--top-center { + animation: slideInBottom 0.2s ease-out forwards; + } + + .notifications__animation--top-center.notifications__item--hidden { + animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .notifications__animation--bottom-center { + animation: slideInTop 0.3s ease-out forwards; + } + + .notifications__animation--bottom-center.notifications__item--hidden { + animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } +} diff --git a/components/notifications/src/components/NotificationsItem.module.css b/components/notifications/src/components/NotificationsItem.module.css new file mode 100644 index 00000000..9d15858c --- /dev/null +++ b/components/notifications/src/components/NotificationsItem.module.css @@ -0,0 +1,170 @@ +.notification-item { + overflow: hidden; + position: relative; + opacity: 1; + height: auto; +} + +.notification-item.pointer { + cursor: pointer; +} + +/* Мобильная версия (по умолчанию) */ +.animation_bottom_left, +.animation_bottom_right, +.animation_bottom_center { + animation: slideInTop 0.3s ease-out forwards; +} + +.animation_bottom_left.hidden, +.animation_bottom_right.hidden, +.animation_bottom_center.hidden { + animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + +.animation_top_left, +.animation_top_right, +.animation_top_center { + animation: slideInBottom 0.2s ease-out forwards; +} + +.animation_top_left.hidden, +.animation_top_right.hidden, +.animation_top_center.hidden { + animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + +@keyframes collapseHeight { + 0% { + max-height: 800px; + } + 100% { + max-height: 0; + } +} + +@keyframes slideInLeft { + 0% { + transform: translateX(100%); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes slideOutRight { + 0% { + transform: translateX(0); + opacity: 1; + } + 100% { + transform: translateX(100%); + opacity: 0; + } +} + +@keyframes slideInRight { + 0% { + transform: translateX(-100%); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes slideOutLeft { + 0% { + transform: translateX(0); + opacity: 1; + } + 100% { + transform: translateX(-100%); + opacity: 0; + } +} + +@keyframes slideInBottom { + 0% { + transform: translateY(-100%); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes slideOutTop { + 0% { + transform: translateY(0); + opacity: 1; + } + 100% { + transform: translateY(-100%); + opacity: 0; + } +} + +@keyframes slideInTop { + 0% { + transform: translateY(100%); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes slideOutBottom { + 0% { + transform: translateY(0); + opacity: 1; + } + 100% { + transform: translateY(100%); + opacity: 0; + } +} + +@media (min-width: 768px) { + .animation_bottom_left, + .animation_top_left { + animation: slideInRight 0.3s ease-out forwards; + } + + .animation_bottom_left.hidden, + .animation_top_left.hidden { + animation: slideOutLeft 0.2s ease-in forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .animation_bottom_right, + .animation_top_right { + animation: slideInLeft 0.3s ease-out forwards; + } + + .animation_bottom_right.hidden, + .animation_top_right.hidden { + animation: slideOutRight 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .animation_top_center { + animation: slideInBottom 0.2s ease-out forwards; + } + + .animation_top_center.hidden { + animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } + + .animation_bottom_center { + animation: slideInTop 0.3s ease-out forwards; + } + + .animation_bottom_center.hidden { + animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; + } +} diff --git a/components/notifications/src/components/NotificationsItem.tsx b/components/notifications/src/components/NotificationsItem.tsx new file mode 100644 index 00000000..f46ab8a1 --- /dev/null +++ b/components/notifications/src/components/NotificationsItem.tsx @@ -0,0 +1,100 @@ +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { TIME_BEFORE_UNMOUNT } from '../constants'; +import { cn } from '../utilities'; +import { INotificationsItemProps, TNotificationPosition } from '../Notifications.types'; +import './NotificationsItem.css'; + +const animationClasses: Record = { + 'bottom-left': 'notifications__animation--bottom-left', + 'top-left': 'notifications__animation--top-left', + 'bottom-right': 'notifications__animation--bottom-right', + 'top-right': 'notifications__animation--top-right', + 'top-center': 'notifications__animation--top-center', + 'bottom-center': 'notifications__animation--bottom-center' +}; + +export const NotificationsItem = (props: INotificationsItemProps) => { + const { + dismiss, + children, + position, + duration, + isAutoClosable, + isPauseToRemove, + removeNotification, + onClick, + className, + style + } = props; + + const [isFadingOut, setIsFadingOut] = useState(false); + + const timerStartRef = useRef(0); + const lastStartRef = useRef(0); + const remainingTime = useRef(duration); + + const closeNotification = useCallback(() => { + setIsFadingOut(true); + + setTimeout(() => { + removeNotification(); + }, TIME_BEFORE_UNMOUNT); + }, []); + + useEffect(() => { + if (!isAutoClosable) return; + remainingTime.current = duration; + }, [isAutoClosable, duration]); + + useEffect(() => { + if (!isAutoClosable || duration === Infinity) return; + + let timeoutId: ReturnType; + + const pauseTimer = () => { + if (timerStartRef.current) { + const elapsedTime = new Date().getTime() - timerStartRef.current; + + remainingTime.current -= elapsedTime; + } + + lastStartRef.current = new Date().getTime(); + }; + + const startTimer = () => { + if (remainingTime.current === Infinity) return; + + timerStartRef.current = new Date().getTime(); + + timeoutId = setTimeout(closeNotification, remainingTime.current); + }; + + if (isPauseToRemove) { + pauseTimer(); + } else { + startTimer(); + } + + return () => clearTimeout(timeoutId); + }, [isPauseToRemove, closeNotification, isAutoClosable]); + + useEffect(() => { + if (dismiss) { + closeNotification(); + } + }, [dismiss]); + + const classes = cn( + 'notifications__item', + animationClasses[position], + isFadingOut ? 'notifications__item--hidden' : '', + onClick ? 'notifications__item--clickable' : '', + className + ); + + return ( +
  • + {children} +
  • + ); +}; diff --git a/components/notifications/src/constants.ts b/components/notifications/src/constants.ts new file mode 100644 index 00000000..5f6d74f5 --- /dev/null +++ b/components/notifications/src/constants.ts @@ -0,0 +1,6 @@ +export const POSITION = 'top-right' +export const GAP = 8; +export const OFFSET = 24; +export const NOTIFICATION_WIDTH = 356; +export const NOTIFICATION_LIFETIME = 5000; +export const TIME_BEFORE_UNMOUNT = 300; diff --git a/components/notifications/src/hooks/use-document-visibility.ts b/components/notifications/src/hooks/use-document-visibility.ts new file mode 100644 index 00000000..ef0d5244 --- /dev/null +++ b/components/notifications/src/hooks/use-document-visibility.ts @@ -0,0 +1,15 @@ +import React from 'react'; + +export const useIsDocumentHidden = () => { + const [isDocumentHidden, setIsDocumentHidden] = React.useState(document.hidden); + + React.useEffect(() => { + const callback = () => { + setIsDocumentHidden(document.hidden); + }; + document.addEventListener('visibilitychange', callback); + return () => window.removeEventListener('visibilitychange', callback); + }, []); + + return isDocumentHidden; +}; diff --git a/components/notifications/src/hooks/useNotificationsActions.ts b/components/notifications/src/hooks/useNotificationsActions.ts new file mode 100644 index 00000000..1326b48c --- /dev/null +++ b/components/notifications/src/hooks/useNotificationsActions.ts @@ -0,0 +1,14 @@ +import { notificationService } from '../services/notifications.service'; + +export const useNotificationsActions = () => ({ + create: notificationService.create, + update: notificationService.update, + success: notificationService.success, + danger: notificationService.danger, + info: notificationService.info, + warning: notificationService.warning, + ordinary: notificationService.ordinary, + custom: notificationService.custom, + dismiss: notificationService.dismiss, + dismissAll: notificationService.dismissAll +}); diff --git a/components/notifications/src/hooks/useNotificationsManager.ts b/components/notifications/src/hooks/useNotificationsManager.ts new file mode 100644 index 00000000..8bf50558 --- /dev/null +++ b/components/notifications/src/hooks/useNotificationsManager.ts @@ -0,0 +1,134 @@ +import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import { Callback } from '@byndyusoft-ui/types'; +import { + INotificationsItem, + TNotificationItemId, + TNotificationPosition, + IUseNotificationsStateParams, + TNotificationRender +} from '../Notifications.types'; +import { notificationsPubSub } from '../services/notificationsPubSub.service'; +import { notificationService } from '../services/notifications.service'; + +export const useNotificationsManager = (params: IUseNotificationsStateParams) => { + const { + position, + limit, + isCloseOnClick, + isClosable, + isNewestOnTop, + renderNotification, + renderNotificationComponents + } = params; + + const [notifications, setNotifications] = useState>([]); + + const possiblePositions: Array = useMemo(() => { + const currentPositions = [position].concat( + notifications + .filter((n): n is INotificationsItem & { position: TNotificationPosition } => Boolean(n?.position)) + .map(n => n.position) + ); + return Array.from(new Set(currentPositions)); + }, [notifications, position]); + + const cuttingByLimit = (items: Array, isNewestOnTop?: boolean): Array => { + if (!limit) return items; + + return isNewestOnTop ? items.slice(-limit) : items.slice(0, limit); + }; + + const onClickAndClose = (itemId: TNotificationItemId, isCloseOnClickItem?: boolean): Callback | undefined => { + if (isCloseOnClickItem === false || !isCloseOnClick) return undefined; + + return () => notificationService.dismiss(itemId); + }; + + const removeNotification = (itemId: TNotificationItemId) => () => { + notificationService.remove(itemId); + }; + + const executeRender = ( + render: TNotificationRender | undefined, + data: INotificationsItem, + index: number + ): ReactNode | null => { + return typeof render === 'function' ? render({ data, index }) : render || null; + }; + + const prepareNotificationProps = (item: INotificationsItem): INotificationsItem => { + return { + ...item, + isClosable: item?.isClosable || isClosable, + onClose: () => { + notificationService.dismiss(item.id); + item?.afterClose?.(); + } + }; + }; + + const renderNotificationItem = (notificationItem: INotificationsItem, index: number): ReactNode | null => { + const prepareItem = prepareNotificationProps(notificationItem); + + if (prepareItem.render) { + return executeRender(prepareItem.render, prepareItem, index); + } + + if ( + typeof renderNotificationComponents === 'object' && + prepareItem.theme && + prepareItem.theme !== 'custom' && + renderNotificationComponents[prepareItem.theme] + ) { + return executeRender(renderNotificationComponents[prepareItem.theme], prepareItem, index); + } + + if (renderNotification) { + return executeRender(renderNotification, prepareItem, index); + } + + return null; + }; + + const getNotificationsByPosition = useCallback( + (positionItem: TNotificationPosition, positionIndex: number): Array => + notifications.filter( + notification => + (!notification.position && positionIndex === 0) || notification.position === positionItem + ), + [notifications] + ); + + const prepareNotifications = ( + position: TNotificationPosition, + positionIndex: number + ): Array => { + const notificationsByPosition = getNotificationsByPosition(position, positionIndex); + + return cuttingByLimit( + isNewestOnTop ? notificationsByPosition.reverse() : notificationsByPosition, + isNewestOnTop + ); + }; + + useEffect(() => { + const listener = (newNotifications: Array) => { + setNotifications([...newNotifications]); + }; + + notificationsPubSub.subscribe('updateState', listener); + + return () => { + notificationsPubSub.unsubscribe('updateState', listener); + }; + }, [setNotifications]); + + return { + possiblePositions, + notifications, + onClickAndClose, + removeNotification, + renderNotificationItem, + prepareNotifications + }; +}; diff --git a/components/notifications/src/index.ts b/components/notifications/src/index.ts new file mode 100644 index 00000000..21f93202 --- /dev/null +++ b/components/notifications/src/index.ts @@ -0,0 +1,5 @@ +export { default } from './NotificationsManager'; + +export type { INotificationData } from './Notifications.types'; +export { default as NotificationsManager } from './NotificationsManager'; +export { useNotificationsActions as useNotifications } from './hooks/useNotificationsActions'; diff --git a/components/notifications/src/services/notifications.service.ts b/components/notifications/src/services/notifications.service.ts new file mode 100644 index 00000000..40250253 --- /dev/null +++ b/components/notifications/src/services/notifications.service.ts @@ -0,0 +1,110 @@ +import { + INotificationsItem, + TCreateNotificationParams, + TCustomNotificationParams, + TNotificationItemId, + TNotificationRender, + TThemedNotificationParams +} from '../Notifications.types'; +import { notificationsPubSub } from './notificationsPubSub.service'; + +let notificationCounter = 1; + +class NotificationsService { + private notifications: Array = []; + private readonly notify: () => void; + + constructor(publisher: (data: Array) => void) { + this.notify = () => publisher(this.notifications); + } + + create = (partial: TCreateNotificationParams): TNotificationItemId => { + const id = partial?.id || notificationCounter++; + const theme = partial?.theme || 'ordinary'; + + const index = this.notifications.findIndex(item => item.id === id); + const updatedItem = { + ...this.notifications[index], + ...partial, + id, + theme + }; + + if (index !== -1) { + this.notifications[index] = updatedItem; + } else { + this.notifications.push(updatedItem); + } + + this.notify(); + + return id; + }; + + update = (notificationId: TNotificationItemId, patch: Partial): void => { + const index = this.notifications.findIndex(notification => notification.id === notificationId); + + if (index === -1) return; + + Object.assign(this.notifications[index], patch); + + this.notify(); + }; + + ordinary = (params: TThemedNotificationParams): TNotificationItemId => { + return this.create({ ...params, theme: 'ordinary' }); + }; + + success = (params: TThemedNotificationParams): TNotificationItemId => { + return this.create({ ...params, theme: 'success' }); + }; + + danger = (params: TThemedNotificationParams): TNotificationItemId => { + return this.create({ ...params, theme: 'danger' }); + }; + + warning = (params: TThemedNotificationParams): TNotificationItemId => { + return this.create({ ...params, theme: 'warning' }); + }; + + info = (params: TThemedNotificationParams): TNotificationItemId => { + return this.create({ ...params, theme: 'info' }); + }; + + custom = (render: TNotificationRender, params: TCustomNotificationParams = {}): TNotificationItemId => { + return this.create({ ...params, render, theme: 'custom' }); + }; + + remove = (id: TNotificationItemId): void => { + const index = this.notifications.findIndex(notification => notification.id === id); + + this.notifications = [...this.notifications.slice(0, index), ...this.notifications.slice(index + 1)]; + + this.notify(); + }; + + dismiss = (id: TNotificationItemId): void => { + this.notifications = this.notifications.map(notification => { + if (id === notification.id) { + return { ...notification, dismiss: true }; + } + return notification; + }); + + this.notify(); + }; + + dismissAll = (): void => { + this.notifications = this.notifications.map(notification => { + return { ...notification, dismiss: true }; + }); + + this.notify(); + }; +} + +const publisher = (dataItems: Array): void => { + notificationsPubSub.publish('updateState', dataItems); +}; + +export const notificationService = new NotificationsService(publisher); diff --git a/components/notifications/src/services/notificationsPubSub.service.ts b/components/notifications/src/services/notificationsPubSub.service.ts new file mode 100644 index 00000000..7c5c5df8 --- /dev/null +++ b/components/notifications/src/services/notificationsPubSub.service.ts @@ -0,0 +1,10 @@ +import PubSub from '@byndyusoft-ui/pub-sub'; +import { INotificationsItem } from '../Notifications.types'; + +type TNotificationsPubSubInstance = { + updateState: (data: Array) => void; +}; + +const INSTANCE_NAME = 'notifications'; + +export const notificationsPubSub = PubSub.getInstance(INSTANCE_NAME); diff --git a/components/notifications/src/utilities.ts b/components/notifications/src/utilities.ts new file mode 100644 index 00000000..e407a502 --- /dev/null +++ b/components/notifications/src/utilities.ts @@ -0,0 +1,21 @@ +import { TPlatformValue } from './Notifications.types'; + +export function cn(...classes: Array) { + return classes.filter(Boolean).join(' '); +} + +export const normalizeCssValue = (value: number | string): number | string => { + return typeof value === 'number' ? `${value}px` : value; +}; + +export const normalizePlatformValue = ( + type: 'web' | 'mobile', + defaultValue: number, + platformValue?: TPlatformValue +): string | number => { + if (typeof platformValue === 'number' || typeof platformValue === 'string') { + return normalizeCssValue(platformValue ?? defaultValue); + } + + return normalizeCssValue(platformValue?.[type] ?? defaultValue); +}; diff --git a/components/notifications/tsconfig.json b/components/notifications/tsconfig.json new file mode 100644 index 00000000..98f42aee --- /dev/null +++ b/components/notifications/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "dist", + "outDir": "dist", + "module": "commonjs" + }, + "include": ["../../types.d.ts", "src"] +} diff --git a/package-lock.json b/package-lock.json index 84f34f2d..8b0ffea3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,7 @@ "rollup": "^2.79.0", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-peer-deps-external": "^2.2.4", + "rollup-plugin-postcss": "^4.0.2", "storybook": "^7.6.17", "storybook-css-modules": "^1.0.8", "stylelint": "^13.0.0", @@ -100,6 +101,19 @@ "react-dom": ">=17" } }, + "components/notifications": { + "name": "@byndyusoft-ui/notifications", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@byndyusoft-ui/types": "^0.1.0" + }, + "peerDependencies": { + "@byndyusoft-ui/pub-sub": "^0.0.1", + "react": ">=17", + "react-dom": ">=17" + } + }, "components/portal": { "name": "@byndyusoft-ui/portal", "version": "1.0.0", @@ -2422,10 +2436,18 @@ "resolved": "components/modals-provider", "link": true }, + "node_modules/@byndyusoft-ui/notifications": { + "resolved": "components/notifications", + "link": true + }, "node_modules/@byndyusoft-ui/portal": { "resolved": "components/portal", "link": true }, + "node_modules/@byndyusoft-ui/pub-sub": { + "resolved": "services/pub-sub", + "link": true + }, "node_modules/@byndyusoft-ui/reset-css": { "resolved": "styles/reset-css", "link": true @@ -14894,6 +14916,29 @@ "url": "https://tidelift.com/funding/github/npm/autoprefixer" } }, + "node_modules/autoprefixer/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/autoprefixer/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -15788,6 +15833,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001577", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", @@ -16285,6 +16342,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -16449,6 +16512,15 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, "node_modules/confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -17490,6 +17562,18 @@ "source-map-resolve": "^0.6.0" } }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -17525,105 +17609,6 @@ } } }, - "node_modules/css-loader/node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/css-loader/node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/css-loader/node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/css-loader/node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/css-loader/node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/css-loader/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -17706,6 +17691,82 @@ "node": ">=4" } }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dev": true, + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -20925,6 +20986,24 @@ "node": ">=0.10.0" } }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "dependencies": { + "loader-utils": "^3.2.0" + } + }, + "node_modules/generic-names/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -22664,6 +22743,24 @@ "node": ">=0.10.0" } }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", + "dev": true + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -22720,6 +22817,18 @@ "minimatch": "^3.0.4" } }, + "node_modules/import-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", + "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", + "dev": true, + "dependencies": { + "import-from": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -22745,6 +22854,18 @@ "node": ">=4" } }, + "node_modules/import-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -25715,6 +25836,12 @@ "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -28011,9 +28138,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -29199,6 +29326,18 @@ "node": ">=4" } }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -29611,21 +29750,126 @@ } }, "node_modules/postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", "dev": true, "dependencies": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.0.0" + "node": "^10 || ^12 || >=14.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, "node_modules/postcss-html": { @@ -29743,12 +29987,447 @@ "node": ">=6.14.4" } }, + "node_modules/postcss-less/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-less/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", "dev": true }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", + "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", + "dev": true, + "dependencies": { + "generic-names": "^4.0.0", + "icss-replace-symbols": "^1.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", @@ -29767,6 +30446,29 @@ "node": ">=6.0.0" } }, + "node_modules/postcss-safe-parser/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-safe-parser/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/postcss-sass": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.4.4.tgz", @@ -29777,6 +30479,29 @@ "postcss": "^7.0.21" } }, + "node_modules/postcss-sass/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-sass/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/postcss-scss": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", @@ -29789,6 +30514,29 @@ "node": ">=6.0.0" } }, + "node_modules/postcss-scss/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-scss/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.10", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", @@ -29802,95 +30550,119 @@ "node": ">=4" } }, - "node_modules/postcss-syntax": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", - "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, "peerDependencies": { - "postcss": ">=5.0.0" + "postcss": "^8.2.15" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/postcss/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { - "node": ">=4" + "node": ">= 10" } }, - "node_modules/postcss/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "mdn-data": "2.0.14", + "source-map": "^0.6.1" }, "engines": { - "node": ">=4" + "node": ">=8.0.0" } }, - "node_modules/postcss/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/postcss-svgo/node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "css-tree": "^1.1.2" }, "engines": { - "node": ">=4" + "node": ">=8.0.0" } }, - "node_modules/postcss/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/postcss/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/postcss/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/postcss-syntax": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", + "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", "dev": true, - "engines": { - "node": ">=4" + "peerDependencies": { + "postcss": ">=5.0.0" } }, - "node_modules/postcss/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "postcss-selector-parser": "^6.0.5" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/postcss/node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -30032,6 +30804,15 @@ "node": ">=0.12" } }, + "node_modules/promise.series": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", + "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, "node_modules/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -31409,6 +32190,82 @@ "rollup": "*" } }, + "node_modules/rollup-plugin-postcss": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", + "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "concat-with-sourcemaps": "^1.1.0", + "cssnano": "^5.0.1", + "import-cwd": "^3.0.0", + "p-queue": "^6.6.2", + "pify": "^5.0.0", + "postcss-load-config": "^3.0.0", + "postcss-modules": "^4.0.0", + "promise.series": "^0.2.0", + "resolve": "^1.19.0", + "rollup-pluginutils": "^2.8.2", + "safe-identifier": "^0.4.2", + "style-inject": "^0.3.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "8.x" + } + }, + "node_modules/rollup-plugin-postcss/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/rollup-plugin-postcss/node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rollup-plugin-postcss/node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -31486,6 +32343,12 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", + "dev": true + }, "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -32287,6 +33150,13 @@ "figgy-pudding": "^3.5.1" } }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true + }, "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -32423,6 +33293,12 @@ "node": ">=0.6.19" } }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -32611,6 +33487,12 @@ "node": ">=4" } }, + "node_modules/style-inject": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", + "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", + "dev": true + }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -32633,6 +33515,22 @@ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", "dev": true }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, "node_modules/stylelint": { "version": "13.13.1", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz", @@ -32717,6 +33615,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylelint/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/stylelint/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/sugarss": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz", @@ -32726,6 +33647,29 @@ "postcss": "^7.0.2" } }, + "node_modules/sugarss/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/sugarss/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -35306,6 +36250,11 @@ "version": "0.1.0", "license": "Apache-2.0" }, + "services/pub-sub": { + "name": "@byndyusoft-ui/pub-sub", + "version": "0.0.1", + "license": "Apache-2.0" + }, "styles/keyframes-css": { "name": "@byndyusoft-ui/keyframes-css", "version": "0.0.1", @@ -36885,10 +37834,19 @@ "version": "file:components/modals-provider", "requires": {} }, + "@byndyusoft-ui/notifications": { + "version": "file:components/notifications", + "requires": { + "@byndyusoft-ui/types": "^0.1.0" + } + }, "@byndyusoft-ui/portal": { "version": "file:components/portal", "requires": {} }, + "@byndyusoft-ui/pub-sub": { + "version": "file:services/pub-sub" + }, "@byndyusoft-ui/reset-css": { "version": "file:styles/reset-css" }, @@ -46276,6 +47234,24 @@ "num2fraction": "^1.2.2", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "available-typed-arrays": { @@ -46967,6 +47943,18 @@ "quick-lru": "^4.0.1" } }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, "caniuse-lite": { "version": "1.0.30001577", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", @@ -47316,6 +48304,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, "colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -47457,6 +48451,15 @@ "typedarray": "^0.0.6" } }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, "confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -48267,6 +49270,13 @@ } } }, + "css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "dev": true, + "requires": {} + }, "css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -48283,60 +49293,6 @@ "semver": "^7.5.4" }, "dependencies": { - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - } - }, - "postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -48386,6 +49342,61 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dev": true, + "requires": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dev": true, + "requires": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "requires": {} + }, "csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -50877,6 +51888,23 @@ } } }, + "generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dev": true, + "requires": { + "loader-utils": "^3.2.0" + }, + "dependencies": { + "loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "dev": true + } + } + }, "genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -52172,6 +53200,19 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", + "dev": true + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, "identity-obj-proxy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", @@ -52208,6 +53249,15 @@ "minimatch": "^3.0.4" } }, + "import-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", + "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", + "dev": true, + "requires": { + "import-from": "^3.0.0" + } + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -52226,6 +53276,15 @@ } } }, + "import-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, "import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -54465,6 +55524,12 @@ "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -56117,9 +57182,9 @@ } }, "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true }, "nanomatch": { @@ -57011,6 +58076,15 @@ "integrity": "sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==", "dev": true }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -57350,79 +58424,84 @@ "dev": true }, "postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "requires": {} + }, "postcss-html": { "version": "0.36.0", "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz", @@ -57521,6 +58600,34 @@ "dev": true, "requires": { "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" } }, "postcss-media-query-parser": { @@ -57529,6 +58636,254 @@ "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", "dev": true }, + "postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + } + }, + "postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", + "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", + "dev": true, + "requires": { + "generic-names": "^4.0.0", + "icss-replace-symbols": "^1.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + } + }, + "postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + } + } + }, + "postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^7.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + } + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, "postcss-resolve-nested-selector": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", @@ -57542,6 +58897,24 @@ "dev": true, "requires": { "postcss": "^7.0.26" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-sass": { @@ -57552,6 +58925,24 @@ "requires": { "gonzales-pe": "^4.3.0", "postcss": "^7.0.21" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-scss": { @@ -57561,6 +58952,24 @@ "dev": true, "requires": { "postcss": "^7.0.6" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "postcss-selector-parser": { @@ -57573,6 +58982,64 @@ "util-deprecate": "^1.0.2" } }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } + } + }, "postcss-syntax": { "version": "0.36.2", "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", @@ -57580,6 +59047,15 @@ "dev": true, "requires": {} }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -57693,6 +59169,12 @@ "retry": "^0.10.0" } }, + "promise.series": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", + "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", + "dev": true + }, "prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -58731,6 +60213,68 @@ "dev": true, "requires": {} }, + "rollup-plugin-postcss": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", + "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "concat-with-sourcemaps": "^1.1.0", + "cssnano": "^5.0.1", + "import-cwd": "^3.0.0", + "p-queue": "^6.6.2", + "pify": "^5.0.0", + "postcss-load-config": "^3.0.0", + "postcss-modules": "^4.0.0", + "promise.series": "^0.2.0", + "resolve": "^1.19.0", + "rollup-pluginutils": "^2.8.2", + "safe-identifier": "^0.4.2", + "style-inject": "^0.3.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + } + }, + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true + } + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } + } + }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -58787,6 +60331,12 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", + "dev": true + }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -59455,6 +61005,12 @@ "figgy-pudding": "^3.5.1" } }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, "stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -59563,6 +61119,12 @@ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "dev": true }, + "string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "dev": true + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -59701,6 +61263,12 @@ "through": "^2.3.4" } }, + "style-inject": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", + "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", + "dev": true + }, "style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -59714,6 +61282,16 @@ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", "dev": true }, + "stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + } + }, "stylelint": { "version": "13.13.1", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz", @@ -59781,6 +61359,22 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } } } }, @@ -59791,6 +61385,24 @@ "dev": true, "requires": { "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } } }, "supports-color": { From cadba568154797ea95711c6df31663b3c5b28988 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Wed, 29 Jan 2025 16:38:10 +0500 Subject: [PATCH 04/13] fix: dependencies --- package-lock.json | 1394 --------------------------------------------- 1 file changed, 1394 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8b0ffea3..ea965bf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,6 @@ "rollup": "^2.79.0", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-postcss": "^4.0.2", "storybook": "^7.6.17", "storybook-css-modules": "^1.0.8", "stylelint": "^13.0.0", @@ -15833,18 +15832,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001577", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", @@ -16342,12 +16329,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -16512,15 +16493,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, "node_modules/confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -17562,18 +17534,6 @@ "source-map-resolve": "^0.6.0" } }, - "node_modules/css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -17691,82 +17651,6 @@ "node": ">=4" } }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dev": true, - "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -20986,24 +20870,6 @@ "node": ">=0.10.0" } }, - "node_modules/generic-names": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", - "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", - "dev": true, - "dependencies": { - "loader-utils": "^3.2.0" - } - }, - "node_modules/generic-names/node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - } - }, "node_modules/genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -22743,12 +22609,6 @@ "node": ">=0.10.0" } }, - "node_modules/icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", - "dev": true - }, "node_modules/icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", @@ -22817,18 +22677,6 @@ "minimatch": "^3.0.4" } }, - "node_modules/import-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", - "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", - "dev": true, - "dependencies": { - "import-from": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -22854,18 +22702,6 @@ "node": ">=4" } }, - "node_modules/import-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", - "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -25836,12 +25672,6 @@ "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", "dev": true }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -29326,18 +29156,6 @@ "node": ">=4" } }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -29777,101 +29595,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, "node_modules/postcss-html": { "version": "0.36.0", "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz", @@ -30010,158 +29733,12 @@ "url": "https://opencollective.com/postcss/" } }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", "dev": true }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", - "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", - "dev": true, - "dependencies": { - "generic-names": "^4.0.0", - "icss-replace-symbols": "^1.1.0", - "lodash.camelcase": "^4.3.0", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "string-hash": "^1.1.1" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, "node_modules/postcss-modules-extract-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", @@ -30247,187 +29824,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", @@ -30550,83 +29946,6 @@ "node": ">=4" } }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/postcss-svgo/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/postcss-svgo/node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/postcss-svgo/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/postcss-svgo/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/postcss-syntax": { "version": "0.36.2", "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", @@ -30636,21 +29955,6 @@ "postcss": ">=5.0.0" } }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -30804,15 +30108,6 @@ "node": ">=0.12" } }, - "node_modules/promise.series": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", - "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -32190,82 +31485,6 @@ "rollup": "*" } }, - "node_modules/rollup-plugin-postcss": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", - "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "concat-with-sourcemaps": "^1.1.0", - "cssnano": "^5.0.1", - "import-cwd": "^3.0.0", - "p-queue": "^6.6.2", - "pify": "^5.0.0", - "postcss-load-config": "^3.0.0", - "postcss-modules": "^4.0.0", - "promise.series": "^0.2.0", - "resolve": "^1.19.0", - "rollup-pluginutils": "^2.8.2", - "safe-identifier": "^0.4.2", - "style-inject": "^0.3.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "postcss": "8.x" - } - }, - "node_modules/rollup-plugin-postcss/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/rollup-plugin-postcss/node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rollup-plugin-postcss/node_modules/pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -32343,12 +31562,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/safe-identifier": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", - "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", - "dev": true - }, "node_modules/safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -33150,13 +32363,6 @@ "figgy-pudding": "^3.5.1" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -33293,12 +32499,6 @@ "node": ">=0.6.19" } }, - "node_modules/string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", - "dev": true - }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -33487,12 +32687,6 @@ "node": ">=4" } }, - "node_modules/style-inject": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", - "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", - "dev": true - }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -33515,22 +32709,6 @@ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", "dev": true }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, "node_modules/stylelint": { "version": "13.13.1", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz", @@ -47943,18 +47121,6 @@ "quick-lru": "^4.0.1" } }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, "caniuse-lite": { "version": "1.0.30001577", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", @@ -48304,12 +47470,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, "colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -48451,15 +47611,6 @@ "typedarray": "^0.0.6" } }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, "confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -49270,13 +48421,6 @@ } } }, - "css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "dev": true, - "requires": {} - }, "css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -49342,61 +48486,6 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, - "cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dev": true, - "requires": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - } - }, - "cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dev": true, - "requires": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - } - }, - "cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true, - "requires": {} - }, "csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -51888,23 +50977,6 @@ } } }, - "generic-names": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", - "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", - "dev": true, - "requires": { - "loader-utils": "^3.2.0" - }, - "dependencies": { - "loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "dev": true - } - } - }, "genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -53200,12 +52272,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", - "dev": true - }, "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", @@ -53249,15 +52315,6 @@ "minimatch": "^3.0.4" } }, - "import-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", - "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", - "dev": true, - "requires": { - "import-from": "^3.0.0" - } - }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -53276,15 +52333,6 @@ } } }, - "import-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", - "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, "import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -55524,12 +54572,6 @@ "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", "dev": true }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -58076,15 +57118,6 @@ "integrity": "sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==", "dev": true }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -58442,66 +57475,6 @@ } } }, - "postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "dev": true, - "requires": {} - }, - "postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true, - "requires": {} - }, - "postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true, - "requires": {} - }, - "postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true, - "requires": {} - }, "postcss-html": { "version": "0.36.0", "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz", @@ -58620,100 +57593,12 @@ } } }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } - }, "postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", "dev": true }, - "postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - } - }, - "postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dev": true, - "requires": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, - "postcss-modules": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", - "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", - "dev": true, - "requires": { - "generic-names": "^4.0.0", - "icss-replace-symbols": "^1.1.0", - "lodash.camelcase": "^4.3.0", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "string-hash": "^1.1.1" - } - }, "postcss-modules-extract-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", @@ -58774,116 +57659,6 @@ "icss-utils": "^5.0.0" } }, - "postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true, - "requires": {} - }, - "postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dev": true, - "requires": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dev": true, - "requires": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, "postcss-resolve-nested-selector": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", @@ -58982,64 +57757,6 @@ "util-deprecate": "^1.0.2" } }, - "postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - } - } - } - }, "postcss-syntax": { "version": "0.36.2", "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", @@ -59047,15 +57764,6 @@ "dev": true, "requires": {} }, - "postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.5" - } - }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -59169,12 +57877,6 @@ "retry": "^0.10.0" } }, - "promise.series": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", - "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", - "dev": true - }, "prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -60213,68 +58915,6 @@ "dev": true, "requires": {} }, - "rollup-plugin-postcss": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", - "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "concat-with-sourcemaps": "^1.1.0", - "cssnano": "^5.0.1", - "import-cwd": "^3.0.0", - "p-queue": "^6.6.2", - "pify": "^5.0.0", - "postcss-load-config": "^3.0.0", - "postcss-modules": "^4.0.0", - "promise.series": "^0.2.0", - "resolve": "^1.19.0", - "rollup-pluginutils": "^2.8.2", - "safe-identifier": "^0.4.2", - "style-inject": "^0.3.0" - }, - "dependencies": { - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - } - }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true - } - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } - } - }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -60331,12 +58971,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "safe-identifier": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", - "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", - "dev": true - }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", @@ -61005,12 +59639,6 @@ "figgy-pudding": "^3.5.1" } }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, "stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -61119,12 +59747,6 @@ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "dev": true }, - "string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", - "dev": true - }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -61263,12 +59885,6 @@ "through": "^2.3.4" } }, - "style-inject": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", - "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", - "dev": true - }, "style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -61282,16 +59898,6 @@ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", "dev": true }, - "stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - } - }, "stylelint": { "version": "13.13.1", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz", From 00284723e045fb40d0c00a6f22067f35cc24e78b Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Thu, 30 Jan 2025 15:38:16 +0500 Subject: [PATCH 05/13] feat(notifications): add tests --- .../notifications/src/Notifications.types.ts | 1 + ...er.css => NotificationsManager.module.css} | 24 +- .../src/NotificationsManager.tsx | 7 +- .../Notifications.stories.module.css | 12 +- .../src/__stories__/Notifications.stories.tsx | 13 +- .../__tests__/NotificationsManager.tests.tsx | 245 ++++++++++++++++++ .../src/components/NotificationsItem.css | 170 ------------ .../src/hooks/useNotificationsActions.ts | 2 + .../src/hooks/useNotificationsManager.ts | 23 +- .../NotificationsItem.module.css | 5 +- .../NotificationsItem.tsx | 29 ++- .../src/services/notifications.service.ts | 12 +- .../services/notificationsPubSub.service.ts | 13 +- components/notifications/src/utilities.ts | 2 +- 14 files changed, 319 insertions(+), 239 deletions(-) rename components/notifications/src/{NotificationsManager.css => NotificationsManager.module.css} (77%) create mode 100644 components/notifications/src/__tests__/NotificationsManager.tests.tsx delete mode 100644 components/notifications/src/components/NotificationsItem.css rename components/notifications/src/{components => partials}/NotificationsItem.module.css (96%) rename components/notifications/src/{components => partials}/NotificationsItem.tsx (78%) diff --git a/components/notifications/src/Notifications.types.ts b/components/notifications/src/Notifications.types.ts index 0864db5b..dba7abe2 100644 --- a/components/notifications/src/Notifications.types.ts +++ b/components/notifications/src/Notifications.types.ts @@ -97,6 +97,7 @@ export interface INotificationsItemProps { duration: number; position: TNotificationPosition; removeNotification: () => void; + theme?: TNotificationTheme; isAutoClosable?: boolean; dismiss?: boolean; isPauseToRemove?: boolean; diff --git a/components/notifications/src/NotificationsManager.css b/components/notifications/src/NotificationsManager.module.css similarity index 77% rename from components/notifications/src/NotificationsManager.css rename to components/notifications/src/NotificationsManager.module.css index 31857fff..26ee5367 100644 --- a/components/notifications/src/NotificationsManager.css +++ b/components/notifications/src/NotificationsManager.module.css @@ -10,18 +10,18 @@ list-style-type: none; } -.notifications__top-left, -.notifications__top-right, -.notifications__top-center { +.top-left, +.top-right, +.top-center { top: var(--offset-mobile); left: var(--offset-mobile); right: var(--offset-mobile); transform: none; } -.notifications__bottom-left, -.notifications__bottom-right, -.notifications__bottom-center { +.bottom-left, +.bottom-right, +.bottom-center { bottom: var(--offset-mobile); left: var(--offset-mobile); right: var(--offset-mobile); @@ -34,42 +34,42 @@ gap: var(--gap); } - .notifications__top-left { + .top-left { top: var(--offset); left: var(--offset); right: auto; transform: none; } - .notifications__top-right { + .top-right { top: var(--offset); right: var(--offset); left: auto; transform: none; } - .notifications__bottom-left { + .bottom-left { bottom: var(--offset); left: var(--offset); right: auto; transform: none; } - .notifications__bottom-right { + .bottom-right { bottom: var(--offset); right: var(--offset); left: auto; transform: none; } - .notifications__top-center { + .top-center { top: var(--offset); left: 50%; right: auto; transform: translateX(-50%); } - .notifications__bottom-center { + .bottom-center { bottom: var(--offset); left: 50%; right: auto; diff --git a/components/notifications/src/NotificationsManager.tsx b/components/notifications/src/NotificationsManager.tsx index 140bd589..cd802b75 100644 --- a/components/notifications/src/NotificationsManager.tsx +++ b/components/notifications/src/NotificationsManager.tsx @@ -1,13 +1,13 @@ import React, { CSSProperties, useState } from 'react'; import Portal from '@byndyusoft-ui/portal'; import { normalizeCssValue, normalizePlatformValue } from './utilities'; -import { NotificationsItem } from './components/NotificationsItem'; +import { NotificationsItem } from './partials/NotificationsItem'; import { useIsDocumentHidden } from './hooks/use-document-visibility'; import { INotificationsManagerProps, TNotificationPosition } from './Notifications.types'; import { useNotificationsManager } from './hooks/useNotificationsManager'; import { cn } from './utilities'; import { NOTIFICATION_LIFETIME, OFFSET, POSITION, NOTIFICATION_WIDTH, GAP } from './constants'; -import './NotificationsManager.css'; +import styles from './NotificationsManager.module.css'; const NotificationsManager = (props: INotificationsManagerProps) => { const { @@ -64,7 +64,7 @@ const NotificationsManager = (props: INotificationsManagerProps) => { return (
      { style={styleItem} duration={item?.duration ?? duration} position={item?.position || position} + theme={item.theme} dismiss={item.dismiss} isAutoClosable={item.isAutoClosable ?? isAutoClosable} isPauseToRemove={ diff --git a/components/notifications/src/__stories__/Notifications.stories.module.css b/components/notifications/src/__stories__/Notifications.stories.module.css index 76c6c0b0..2fa3e89d 100644 --- a/components/notifications/src/__stories__/Notifications.stories.module.css +++ b/components/notifications/src/__stories__/Notifications.stories.module.css @@ -1,8 +1,9 @@ .container { - height: 100vh; display: flex; + align-items: center; flex-direction: column; justify-content: center; + height: 100vh; } .row { @@ -37,7 +38,7 @@ color: white; } -.notification{ +.notification { box-sizing: border-box; position: relative; width: 100%; @@ -83,11 +84,12 @@ } .code { - background-color: #f0eded; - color: #333; padding: 10px; + height: 230px; border-radius: 5px; overflow-x: auto; font-family: 'Courier New, Courier, monospace', serif; - font-size: 14px; + font-size: 16px; + background-color: #e6e6e6; + color: #333; } diff --git a/components/notifications/src/__stories__/Notifications.stories.tsx b/components/notifications/src/__stories__/Notifications.stories.tsx index 1a5d3abb..efb7ca95 100644 --- a/components/notifications/src/__stories__/Notifications.stories.tsx +++ b/components/notifications/src/__stories__/Notifications.stories.tsx @@ -3,7 +3,7 @@ import { StoryObj } from '@storybook/react'; import NotificationsManager, { useNotifications, INotificationData } from '..'; import { TNotificationPosition, TNotificationTheme } from '../Notifications.types'; import styles from './Notifications.stories.module.css'; -import { NotificationsItem } from '../components/NotificationsItem'; +import { NotificationsItem } from '../partials/NotificationsItem'; const positions: TNotificationPosition[] = [ 'top-right', @@ -240,17 +240,6 @@ custom(({data}) =>
      {data.id} | Custom notification
      ,
      -
      diff --git a/components/notifications/src/__tests__/NotificationsManager.tests.tsx b/components/notifications/src/__tests__/NotificationsManager.tests.tsx new file mode 100644 index 00000000..8c532469 --- /dev/null +++ b/components/notifications/src/__tests__/NotificationsManager.tests.tsx @@ -0,0 +1,245 @@ +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import { render, waitFor } from '@testing-library/react'; +import { INotificationData, INotificationsManagerProps, TThemedNotificationParams } from '../Notifications.types'; +import NotificationsManager, { useNotifications } from '../index'; +import { TIME_BEFORE_UNMOUNT } from '../constants'; + +const BUTTON_NAMES = { + CREATE: 'Create notification', + UPDATE: 'Update notification', + SUCCESS: 'Show success', + DANGER: 'Show danger', + INFO: 'Show info', + WARNING: 'Show warning', + ORDINARY: 'Show ordinary', + CUSTOM: 'Show custom', + REMOVE: 'Remove notification', + REMOVE_ALL: 'Remove all notifications', + DISMISS: 'Dismiss notification', + DISMISS_ALL: 'Dismiss all notifications' +}; + +const NotificationComponent = ({ data }: INotificationData) => ( +
      +

      {data.title}

      + {data?.message &&
      {data.message}
      } + {data?.isClosable && ( + + )} +
      +); + +const ActionsComponent = (paramsEmitter: TThemedNotificationParams = {}) => { + const { create, update, success, danger, info, warning, ordinary, custom, remove, removeAll, dismiss, dismissAll } = + useNotifications(); + return ( +
      + + + + + + + + + + + + +
      + ); +}; + +const setup = (props: INotificationsManagerProps = {}, paramsEmitter: TThemedNotificationParams = {}) => { + return render( +
      + + +
      + ); +}; + +describe('NotificationsManager', () => { + afterEach(() => { + jest.clearAllTimers(); + }); + + describe('actions', () => { + test('create notification', async () => { + const { getByRole, getByTestId } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + + expect(getByTestId('notification-item')).toBeInTheDocument(); + expect(getByRole('status')).toBeInTheDocument(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('updates notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + + expect(getByRole('heading', { level: 3 })).toHaveTextContent('Title'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.UPDATE })); + + expect(getByRole('heading', { level: 3 })).toHaveTextContent('New title'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `success` notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Success'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `info` notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.INFO })); + + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Info'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `warning` notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Warning'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `ordinary` notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.ORDINARY })); + + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Ordinary'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `danger` notification', async () => { + const { getByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + + expect(getByRole('alert')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Danger'); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('adds `custom` notification', async () => { + const { getByRole, getByText, queryByTestId } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CUSTOM })); + + expect(getByText('Custom')).toBeInTheDocument(); + expect(queryByTestId('notification-item')).not.toBeInTheDocument(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('dismiss notification', async () => { + const { getByRole, queryByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + + expect(getByRole('status')).toBeInTheDocument(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS })); + + await waitFor( + () => { + expect(queryByRole('status')).not.toBeInTheDocument(); + }, + { timeout: TIME_BEFORE_UNMOUNT + 1 } + ); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('dismiss all notifications', async () => { + const { getByRole, getAllByRole, queryAllByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + + expect(getAllByRole('status')).toHaveLength(2); + expect(getAllByRole('alert')).toHaveLength(3); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS_ALL })); + + await waitFor( + () => { + expect(queryAllByRole('status')).toHaveLength(0); + expect(queryAllByRole('alert')).toHaveLength(0); + }, + { timeout: TIME_BEFORE_UNMOUNT + 1 } + ); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('remove notification', async () => { + const { getByRole, queryByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE })); + + expect(queryByRole('status')).not.toBeInTheDocument(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('remove all notifications', async () => { + const { getByRole, getAllByRole, queryAllByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + + expect(getAllByRole('status')).toHaveLength(2); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + + expect(queryAllByRole('status')).toHaveLength(0); + }); + }); +}); diff --git a/components/notifications/src/components/NotificationsItem.css b/components/notifications/src/components/NotificationsItem.css deleted file mode 100644 index 332bb26f..00000000 --- a/components/notifications/src/components/NotificationsItem.css +++ /dev/null @@ -1,170 +0,0 @@ -.notifications__item { - overflow: hidden; - position: relative; - opacity: 1; - height: auto; -} - -.notifications__item--clickable { - cursor: pointer; -} - -/* Мобильная версия (по умолчанию) */ -.notifications__animation--bottom-left, -.notifications__animation--bottom-right, -.notifications__animation--bottom-center { - animation: slideInTop 0.3s ease-out forwards; -} - -.notifications__animation--bottom-left.notifications__item--hidden, -.notifications__animation--bottom-right.notifications__item--hidden, -.notifications__animation--bottom-center.notifications__item--hidden { - animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; -} - -.notifications__animation--top-left, -.notifications__animation--top-right, -.notifications__animation--top-center { - animation: slideInBottom 0.2s ease-out forwards; -} - -.notifications__animation--top-left.notifications__item--hidden, -.notifications__animation--top-right.notifications__item--hidden, -.notifications__animation--top-center.notifications__item--hidden { - animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; -} - -@keyframes collapseHeight { - 0% { - max-height: 800px; - } - 100% { - max-height: 0; - } -} - -@keyframes slideInLeft { - 0% { - transform: translateX(100%); - opacity: 0; - } - 100% { - transform: translateX(0); - opacity: 1; - } -} - -@keyframes slideOutRight { - 0% { - transform: translateX(0); - opacity: 1; - } - 100% { - transform: translateX(100%); - opacity: 0; - } -} - -@keyframes slideInRight { - 0% { - transform: translateX(-100%); - opacity: 0; - } - 100% { - transform: translateX(0); - opacity: 1; - } -} - -@keyframes slideOutLeft { - 0% { - transform: translateX(0); - opacity: 1; - } - 100% { - transform: translateX(-100%); - opacity: 0; - } -} - -@keyframes slideInBottom { - 0% { - transform: translateY(-100%); - opacity: 0; - } - 100% { - transform: translateY(0); - opacity: 1; - } -} - -@keyframes slideOutTop { - 0% { - transform: translateY(0); - opacity: 1; - } - 100% { - transform: translateY(-100%); - opacity: 0; - } -} - -@keyframes slideInTop { - 0% { - transform: translateY(100%); - opacity: 0; - } - 100% { - transform: translateY(0); - opacity: 1; - } -} - -@keyframes slideOutBottom { - 0% { - transform: translateY(0); - opacity: 1; - } - 100% { - transform: translateY(100%); - opacity: 0; - } -} - -@media (min-width: 768px) { - .notifications__animation--bottom-left, - .notifications__animation--top-left { - animation: slideInRight 0.3s ease-out forwards; - } - - .notifications__animation--bottom-left.notifications__item--hidden, - .notifications__animation--top-left.notifications__item--hidden { - animation: slideOutLeft 0.2s ease-in forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .notifications__animation--bottom-right, - .notifications__animation--top-right { - animation: slideInLeft 0.3s ease-out forwards; - } - - .notifications__animation--bottom-right.notifications__item--hidden, - .notifications__animation--top-right.notifications__item--hidden { - animation: slideOutRight 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .notifications__animation--top-center { - animation: slideInBottom 0.2s ease-out forwards; - } - - .notifications__animation--top-center.notifications__item--hidden { - animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .notifications__animation--bottom-center { - animation: slideInTop 0.3s ease-out forwards; - } - - .notifications__animation--bottom-center.notifications__item--hidden { - animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } -} diff --git a/components/notifications/src/hooks/useNotificationsActions.ts b/components/notifications/src/hooks/useNotificationsActions.ts index 1326b48c..a8e67c34 100644 --- a/components/notifications/src/hooks/useNotificationsActions.ts +++ b/components/notifications/src/hooks/useNotificationsActions.ts @@ -9,6 +9,8 @@ export const useNotificationsActions = () => ({ warning: notificationService.warning, ordinary: notificationService.ordinary, custom: notificationService.custom, + remove: notificationService.remove, + removeAll: notificationService.removeAll, dismiss: notificationService.dismiss, dismissAll: notificationService.dismissAll }); diff --git a/components/notifications/src/hooks/useNotificationsManager.ts b/components/notifications/src/hooks/useNotificationsManager.ts index 8bf50558..f5e4de0d 100644 --- a/components/notifications/src/hooks/useNotificationsManager.ts +++ b/components/notifications/src/hooks/useNotificationsManager.ts @@ -7,7 +7,7 @@ import { IUseNotificationsStateParams, TNotificationRender } from '../Notifications.types'; -import { notificationsPubSub } from '../services/notificationsPubSub.service'; +import { subscriber } from '../services/notificationsPubSub.service'; import { notificationService } from '../services/notifications.service'; export const useNotificationsManager = (params: IUseNotificationsStateParams) => { @@ -90,14 +90,13 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => return null; }; - const getNotificationsByPosition = useCallback( - (positionItem: TNotificationPosition, positionIndex: number): Array => - notifications.filter( - notification => - (!notification.position && positionIndex === 0) || notification.position === positionItem - ), - [notifications] - ); + const getNotificationsByPosition = ( + positionItem: TNotificationPosition, + positionIndex: number + ): Array => + notifications.filter( + notification => (!notification.position && positionIndex === 0) || notification.position === positionItem + ); const prepareNotifications = ( position: TNotificationPosition, @@ -116,11 +115,7 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => setNotifications([...newNotifications]); }; - notificationsPubSub.subscribe('updateState', listener); - - return () => { - notificationsPubSub.unsubscribe('updateState', listener); - }; + return subscriber(listener); }, [setNotifications]); return { diff --git a/components/notifications/src/components/NotificationsItem.module.css b/components/notifications/src/partials/NotificationsItem.module.css similarity index 96% rename from components/notifications/src/components/NotificationsItem.module.css rename to components/notifications/src/partials/NotificationsItem.module.css index 9d15858c..3cdf43b3 100644 --- a/components/notifications/src/components/NotificationsItem.module.css +++ b/components/notifications/src/partials/NotificationsItem.module.css @@ -1,15 +1,14 @@ -.notification-item { +.notification_item { overflow: hidden; position: relative; opacity: 1; height: auto; } -.notification-item.pointer { +.notification_item.pointer { cursor: pointer; } -/* Мобильная версия (по умолчанию) */ .animation_bottom_left, .animation_bottom_right, .animation_bottom_center { diff --git a/components/notifications/src/components/NotificationsItem.tsx b/components/notifications/src/partials/NotificationsItem.tsx similarity index 78% rename from components/notifications/src/components/NotificationsItem.tsx rename to components/notifications/src/partials/NotificationsItem.tsx index f46ab8a1..fd79a6fc 100644 --- a/components/notifications/src/components/NotificationsItem.tsx +++ b/components/notifications/src/partials/NotificationsItem.tsx @@ -2,22 +2,25 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { TIME_BEFORE_UNMOUNT } from '../constants'; import { cn } from '../utilities'; import { INotificationsItemProps, TNotificationPosition } from '../Notifications.types'; -import './NotificationsItem.css'; +import styles from './NotificationsItem.module.css'; const animationClasses: Record = { - 'bottom-left': 'notifications__animation--bottom-left', - 'top-left': 'notifications__animation--top-left', - 'bottom-right': 'notifications__animation--bottom-right', - 'top-right': 'notifications__animation--top-right', - 'top-center': 'notifications__animation--top-center', - 'bottom-center': 'notifications__animation--bottom-center' + 'bottom-left': styles.animation_bottom_left, + 'top-left': styles.animation_top_left, + 'bottom-right': styles.animation_bottom_right, + 'top-right': styles.animation_top_right, + 'top-center': styles.animation_top_center, + 'bottom-center': styles.animation_bottom_center }; export const NotificationsItem = (props: INotificationsItemProps) => { + const [isFadingOut, setIsFadingOut] = useState(false); + const { dismiss, children, position, + theme, duration, isAutoClosable, isPauseToRemove, @@ -27,8 +30,6 @@ export const NotificationsItem = (props: INotificationsItemProps) => { style } = props; - const [isFadingOut, setIsFadingOut] = useState(false); - const timerStartRef = useRef(0); const lastStartRef = useRef(0); const remainingTime = useRef(duration); @@ -85,15 +86,17 @@ export const NotificationsItem = (props: INotificationsItemProps) => { }, [dismiss]); const classes = cn( - 'notifications__item', + styles.notification_item, animationClasses[position], - isFadingOut ? 'notifications__item--hidden' : '', - onClick ? 'notifications__item--clickable' : '', + isFadingOut ? styles.hidden : '', + onClick ? styles.pointer : '', className ); + const containerRole = theme === 'danger' ? 'alert' : 'status'; + return ( -
    • +
    • {children}
    • ); diff --git a/components/notifications/src/services/notifications.service.ts b/components/notifications/src/services/notifications.service.ts index 40250253..09c89314 100644 --- a/components/notifications/src/services/notifications.service.ts +++ b/components/notifications/src/services/notifications.service.ts @@ -6,7 +6,7 @@ import { TNotificationRender, TThemedNotificationParams } from '../Notifications.types'; -import { notificationsPubSub } from './notificationsPubSub.service'; +import { publisher } from './notificationsPubSub.service'; let notificationCounter = 1; @@ -83,6 +83,12 @@ class NotificationsService { this.notify(); }; + removeAll = (): void => { + this.notifications = []; + + this.notify(); + }; + dismiss = (id: TNotificationItemId): void => { this.notifications = this.notifications.map(notification => { if (id === notification.id) { @@ -103,8 +109,4 @@ class NotificationsService { }; } -const publisher = (dataItems: Array): void => { - notificationsPubSub.publish('updateState', dataItems); -}; - export const notificationService = new NotificationsService(publisher); diff --git a/components/notifications/src/services/notificationsPubSub.service.ts b/components/notifications/src/services/notificationsPubSub.service.ts index 7c5c5df8..906a2948 100644 --- a/components/notifications/src/services/notificationsPubSub.service.ts +++ b/components/notifications/src/services/notificationsPubSub.service.ts @@ -1,4 +1,5 @@ import PubSub from '@byndyusoft-ui/pub-sub'; +import { Callback } from '@byndyusoft-ui/types'; import { INotificationsItem } from '../Notifications.types'; type TNotificationsPubSubInstance = { @@ -7,4 +8,14 @@ type TNotificationsPubSubInstance = { const INSTANCE_NAME = 'notifications'; -export const notificationsPubSub = PubSub.getInstance(INSTANCE_NAME); +const notificationsPubSubInstance = PubSub.getInstance(INSTANCE_NAME); + +export const publisher = (dataItems: Array): void => { + notificationsPubSubInstance.publish('updateState', dataItems); +}; + +export const subscriber = (listener: Callback>): Callback => { + notificationsPubSubInstance.subscribe('updateState', listener); + + return () => notificationsPubSubInstance.unsubscribe('updateState', listener); +}; diff --git a/components/notifications/src/utilities.ts b/components/notifications/src/utilities.ts index e407a502..73d40bde 100644 --- a/components/notifications/src/utilities.ts +++ b/components/notifications/src/utilities.ts @@ -1,6 +1,6 @@ import { TPlatformValue } from './Notifications.types'; -export function cn(...classes: Array) { +export function cn(...classes: Array): string { return classes.filter(Boolean).join(' '); } From 3241cdfb6b135163cd9254856e2394993131c3b8 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Thu, 30 Jan 2025 15:39:02 +0500 Subject: [PATCH 06/13] fix(notifications): scripts --- components/notifications/package.json | 4 ++-- components/notifications/tsconfig.build.json | 4 ++++ package-lock.json | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 components/notifications/tsconfig.build.json diff --git a/components/notifications/package.json b/components/notifications/package.json index a4d2a1a2..0d2fca0b 100644 --- a/components/notifications/package.json +++ b/components/notifications/package.json @@ -1,6 +1,6 @@ { "name": "@byndyusoft-ui/notifications", - "version": "1.0.0", + "version": "0.0.1", "description": "Byndyusoft UI Portal React Component", "keywords": [ "byndyusoft", @@ -18,7 +18,7 @@ "url": "git+https://github.com/Byndyusoft/ui.git" }, "scripts": { - "build": "rollup --config", + "build": "tsc --project tsconfig.build.json", "clean": "rimraf dist", "lint": "eslint src --config ../../eslint.config.js", "test": "jest --config ../../jest.config.js --roots components/notifications/src" diff --git a/components/notifications/tsconfig.build.json b/components/notifications/tsconfig.build.json new file mode 100644 index 00000000..8623abd9 --- /dev/null +++ b/components/notifications/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["src/*.tests.ts", "src/*.stories.*"] +} diff --git a/package-lock.json b/package-lock.json index ea965bf1..aba8b913 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,7 +102,7 @@ }, "components/notifications": { "name": "@byndyusoft-ui/notifications", - "version": "1.0.0", + "version": "0.0.1", "license": "ISC", "devDependencies": { "@byndyusoft-ui/types": "^0.1.0" From 658c35e6ae2d88209fa287f92d55ad111d78ee0f Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Fri, 31 Jan 2025 10:16:39 +0500 Subject: [PATCH 07/13] chore(notifications): add docs, minor refactor --- components/notifications/README.md | 23 +++++++++++++------ .../src/__stories__/Notifications.docs.mdx | 11 +++++++++ .../Notifications.stories.module.css | 6 ++--- .../src/__stories__/Notifications.stories.tsx | 7 +++--- .../src/hooks/useNotificationsManager.ts | 4 ++-- 5 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 components/notifications/src/__stories__/Notifications.docs.mdx diff --git a/components/notifications/README.md b/components/notifications/README.md index 8d647ee6..e50bc20b 100644 --- a/components/notifications/README.md +++ b/components/notifications/README.md @@ -1,6 +1,5 @@ # `@byndyusoft-ui/notifications` -The `Nptofications` component is a ... ## Installation @@ -156,7 +155,7 @@ import NotificationsManager from '@byndyusoft-ui/notifications'; ### Usages -```ts +```js import { useNotifications } from '@byndyusoft-ui/notifications'; @@ -178,11 +177,21 @@ const options = { const notifications = useNotifications() -notifications.success(options) -notifications.danger(options) -notifications.info(options) -notifications.warning(options) -notifications.ordinary(options) +// create new +notifications.success(options); +notifications.danger(options); +notifications.info(options); +notifications.warning(options); +notifications.ordinary(options); +notifications.custom(({ data, index }) =>
      {data.title}
      , { /* ...options */ }); +// update by id +notifications.update('id', options); +// deleting with animation +notifications.dismiss('id'); +notifications.dismissAll(); +// deleting without animation +notifications.remove('id'); +notifications.removeAll(); ``` ### Types diff --git a/components/notifications/src/__stories__/Notifications.docs.mdx b/components/notifications/src/__stories__/Notifications.docs.mdx new file mode 100644 index 00000000..9549f4f4 --- /dev/null +++ b/components/notifications/src/__stories__/Notifications.docs.mdx @@ -0,0 +1,11 @@ +import { Meta, Markdown, Canvas, Source, ArgsTable } from '@storybook/blocks'; +import Readme from '../../README.md'; +import * as NotificationsStories from './Notifications.stories'; + + + +{Readme} + +# Story + + diff --git a/components/notifications/src/__stories__/Notifications.stories.module.css b/components/notifications/src/__stories__/Notifications.stories.module.css index 2fa3e89d..6d9a384f 100644 --- a/components/notifications/src/__stories__/Notifications.stories.module.css +++ b/components/notifications/src/__stories__/Notifications.stories.module.css @@ -2,8 +2,6 @@ display: flex; align-items: center; flex-direction: column; - justify-content: center; - height: 100vh; } .row { @@ -15,7 +13,7 @@ .col { display: flex; flex-direction: column; - gap: 8px; + gap: 6px; } .row > button { @@ -85,7 +83,7 @@ .code { padding: 10px; - height: 230px; + height: 250px; border-radius: 5px; overflow-x: auto; font-family: 'Courier New, Courier, monospace', serif; diff --git a/components/notifications/src/__stories__/Notifications.stories.tsx b/components/notifications/src/__stories__/Notifications.stories.tsx index efb7ca95..e0893c4c 100644 --- a/components/notifications/src/__stories__/Notifications.stories.tsx +++ b/components/notifications/src/__stories__/Notifications.stories.tsx @@ -3,7 +3,6 @@ import { StoryObj } from '@storybook/react'; import NotificationsManager, { useNotifications, INotificationData } from '..'; import { TNotificationPosition, TNotificationTheme } from '../Notifications.types'; import styles from './Notifications.stories.module.css'; -import { NotificationsItem } from '../partials/NotificationsItem'; const positions: TNotificationPosition[] = [ 'top-right', @@ -76,7 +75,8 @@ const Template = (): JSX.Element => { }; const renderEmitterCode = () => { - const baseCode = (type?: string) => ` + const baseCode = (type?: string) => `const { ${type} } = useNotifications(); + ${type}({ title: \`🔔 Notification ${activeTheme}\`, message: 'Notification message', @@ -89,7 +89,8 @@ ${type}({ });`; if (activeTheme === 'custom') { - return ` + return `const { custom } = useNotifications(); + custom(({data}) =>
      {data.id} | Custom notification
      , { position: ${activePosition}, diff --git a/components/notifications/src/hooks/useNotificationsManager.ts b/components/notifications/src/hooks/useNotificationsManager.ts index f5e4de0d..bd53434a 100644 --- a/components/notifications/src/hooks/useNotificationsManager.ts +++ b/components/notifications/src/hooks/useNotificationsManager.ts @@ -1,4 +1,4 @@ -import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import { ReactNode, useEffect, useMemo, useState } from 'react'; import { Callback } from '@byndyusoft-ui/types'; import { INotificationsItem, @@ -44,7 +44,7 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => return () => notificationService.dismiss(itemId); }; - const removeNotification = (itemId: TNotificationItemId) => () => { + const removeNotification = (itemId: TNotificationItemId) => (): void => { notificationService.remove(itemId); }; From 02df91d494ef0c2bad05b41b054585af0ebdc160 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Mon, 3 Feb 2025 12:19:02 +0500 Subject: [PATCH 08/13] chore(notifications): update tests, css --- .../__tests__/NotificationsManager.tests.tsx | 255 ++++++++++-------- .../src/partials/NotificationsItem.module.css | 69 ++--- .../src/partials/NotificationsItem.tsx | 7 +- 3 files changed, 174 insertions(+), 157 deletions(-) diff --git a/components/notifications/src/__tests__/NotificationsManager.tests.tsx b/components/notifications/src/__tests__/NotificationsManager.tests.tsx index 8c532469..74f0de37 100644 --- a/components/notifications/src/__tests__/NotificationsManager.tests.tsx +++ b/components/notifications/src/__tests__/NotificationsManager.tests.tsx @@ -24,8 +24,9 @@ const NotificationComponent = ({ data }: INotificationData) => (

      {data.title}

      {data?.message &&
      {data.message}
      } + {data?.footer &&
      {data.footer}
      } {data?.isClosable && ( - )} @@ -81,165 +82,209 @@ describe('NotificationsManager', () => { jest.clearAllTimers(); }); - describe('actions', () => { - test('create notification', async () => { - const { getByRole, getByTestId } = setup(); + test('create notification', async () => { + const { getByRole, getByTestId } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); - expect(getByTestId('notification-item')).toBeInTheDocument(); - expect(getByRole('status')).toBeInTheDocument(); + expect(getByTestId('notification-item')).toBeInTheDocument(); + expect(getByRole('status')).toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('updates notification', async () => { - const { getByRole } = setup(); + test('updates notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); - expect(getByRole('heading', { level: 3 })).toHaveTextContent('Title'); + expect(getByRole('heading', { level: 3 })).toHaveTextContent('Title'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.UPDATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.UPDATE })); - expect(getByRole('heading', { level: 3 })).toHaveTextContent('New title'); + expect(getByRole('heading', { level: 3 })).toHaveTextContent('New title'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `success` notification', async () => { - const { getByRole } = setup(); + test('adds `success` notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); - expect(getByRole('status')).toBeInTheDocument(); - expect(getByRole('heading')).toHaveTextContent('Success'); + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Success'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `info` notification', async () => { - const { getByRole } = setup(); + test('adds `info` notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.INFO })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.INFO })); - expect(getByRole('status')).toBeInTheDocument(); - expect(getByRole('heading')).toHaveTextContent('Info'); + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Info'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `warning` notification', async () => { - const { getByRole } = setup(); + test('adds `warning` notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); - expect(getByRole('status')).toBeInTheDocument(); - expect(getByRole('heading')).toHaveTextContent('Warning'); + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Warning'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `ordinary` notification', async () => { - const { getByRole } = setup(); + test('adds `ordinary` notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.ORDINARY })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.ORDINARY })); - expect(getByRole('status')).toBeInTheDocument(); - expect(getByRole('heading')).toHaveTextContent('Ordinary'); + expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Ordinary'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `danger` notification', async () => { - const { getByRole } = setup(); + test('adds `danger` notification', async () => { + const { getByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); - expect(getByRole('alert')).toBeInTheDocument(); - expect(getByRole('heading')).toHaveTextContent('Danger'); + expect(getByRole('alert')).toBeInTheDocument(); + expect(getByRole('heading')).toHaveTextContent('Danger'); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('adds `custom` notification', async () => { - const { getByRole, getByText, queryByTestId } = setup(); + test('adds `custom` notification', async () => { + const { getByRole, getByText, queryByTestId } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CUSTOM })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CUSTOM })); - expect(getByText('Custom')).toBeInTheDocument(); - expect(queryByTestId('notification-item')).not.toBeInTheDocument(); + expect(getByText('Custom')).toBeInTheDocument(); + expect(queryByTestId('notification-item')).not.toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('dismiss notification', async () => { - const { getByRole, queryByRole } = setup(); + test('dismiss notification', async () => { + const { getByRole, queryByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); - expect(getByRole('status')).toBeInTheDocument(); + expect(getByRole('status')).toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS })); - await waitFor( - () => { - expect(queryByRole('status')).not.toBeInTheDocument(); - }, - { timeout: TIME_BEFORE_UNMOUNT + 1 } - ); + await waitFor( + () => { + expect(queryByRole('status')).not.toBeInTheDocument(); + }, + { timeout: TIME_BEFORE_UNMOUNT + 1 } + ); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('dismiss all notifications', async () => { - const { getByRole, getAllByRole, queryAllByRole } = setup(); + test('dismiss all notifications', async () => { + const { getByRole, getAllByRole, queryAllByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); - expect(getAllByRole('status')).toHaveLength(2); - expect(getAllByRole('alert')).toHaveLength(3); + expect(getAllByRole('status')).toHaveLength(2); + expect(getAllByRole('alert')).toHaveLength(3); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS_ALL })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DISMISS_ALL })); - await waitFor( - () => { - expect(queryAllByRole('status')).toHaveLength(0); - expect(queryAllByRole('alert')).toHaveLength(0); - }, - { timeout: TIME_BEFORE_UNMOUNT + 1 } - ); + await waitFor( + () => { + expect(queryAllByRole('status')).toHaveLength(0); + expect(queryAllByRole('alert')).toHaveLength(0); + }, + { timeout: TIME_BEFORE_UNMOUNT + 1 } + ); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); - test('remove notification', async () => { - const { getByRole, queryByRole } = setup(); + test('remove notification', async () => { + const { getByRole, queryByRole } = setup(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE })); - expect(queryByRole('status')).not.toBeInTheDocument(); + expect(queryByRole('status')).not.toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); - }); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + }); + + test('remove all notifications', async () => { + const { getByRole, getAllByRole, queryAllByRole } = setup(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + + expect(getAllByRole('status')).toHaveLength(2); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + + expect(queryAllByRole('status')).toHaveLength(0); + }); - test('remove all notifications', async () => { - const { getByRole, getAllByRole, queryAllByRole } = setup(); + test('creates and closes custom notification', async () => { + const { getByRole, getByText, queryByRole, getByLabelText } = setup( + {}, + { + title: 'test-title', + message: 'test-message', + footer: 'test-footer', + isClosable: true + } + ); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.WARNING })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.SUCCESS })); - expect(getAllByRole('status')).toHaveLength(2); + expect(getByRole('status')).toBeInTheDocument(); + expect(getByText('test-title')).toBeInTheDocument(); + expect(getByText('test-message')).toBeInTheDocument(); + expect(getByText('test-footer')).toBeInTheDocument(); + expect(getByLabelText('close-notification')).toBeInTheDocument(); - await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE_ALL })); + await userEvent.click(getByRole('button', { name: 'close-notification' })); - expect(queryAllByRole('status')).toHaveLength(0); + await waitFor(() => { + expect(queryByRole('status')).not.toBeInTheDocument(); }); }); + test('limits the number of notifications displayed', async () => { + const limit = 2; + const { getByRole, getAllByRole, queryByRole } = setup({ limit }); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.CREATE })); + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.ORDINARY })); + + expect(getAllByRole('status')).toHaveLength(2); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.DANGER })); + + expect(getAllByRole('status')).toHaveLength(2); + expect(queryByRole('alert')).not.toBeInTheDocument(); + + await userEvent.click(getByRole('button', { name: BUTTON_NAMES.REMOVE })); + + expect(getAllByRole('status')).toHaveLength(1); + expect(getAllByRole('alert')).toHaveLength(1); + expect(queryByRole('alert')).toBeInTheDocument(); + }); }); diff --git a/components/notifications/src/partials/NotificationsItem.module.css b/components/notifications/src/partials/NotificationsItem.module.css index 3cdf43b3..347f7eaa 100644 --- a/components/notifications/src/partials/NotificationsItem.module.css +++ b/components/notifications/src/partials/NotificationsItem.module.css @@ -10,29 +10,42 @@ } .animation_bottom_left, -.animation_bottom_right, -.animation_bottom_center { - animation: slideInTop 0.3s ease-out forwards; +.animation_top_left { + animation: slideInRight 0.3s ease-out forwards; } .animation_bottom_left.hidden, +.animation_top_left.hidden { + animation: slideOutLeft 0.2s ease-in forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + +.animation_bottom_right, +.animation_top_right { + animation: slideInLeft 0.3s ease-out forwards; +} + .animation_bottom_right.hidden, -.animation_bottom_center.hidden { - animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +.animation_top_right.hidden { + animation: slideOutRight 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; } -.animation_top_left, -.animation_top_right, .animation_top_center { animation: slideInBottom 0.2s ease-out forwards; } -.animation_top_left.hidden, -.animation_top_right.hidden, .animation_top_center.hidden { animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; } +.animation_bottom_center { + animation: slideInTop 0.3s ease-out forwards; +} + +.animation_bottom_center.hidden { + animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; +} + + @keyframes collapseHeight { 0% { max-height: 800px; @@ -129,41 +142,3 @@ opacity: 0; } } - -@media (min-width: 768px) { - .animation_bottom_left, - .animation_top_left { - animation: slideInRight 0.3s ease-out forwards; - } - - .animation_bottom_left.hidden, - .animation_top_left.hidden { - animation: slideOutLeft 0.2s ease-in forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .animation_bottom_right, - .animation_top_right { - animation: slideInLeft 0.3s ease-out forwards; - } - - .animation_bottom_right.hidden, - .animation_top_right.hidden { - animation: slideOutRight 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .animation_top_center { - animation: slideInBottom 0.2s ease-out forwards; - } - - .animation_top_center.hidden { - animation: slideOutTop 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } - - .animation_bottom_center { - animation: slideInTop 0.3s ease-out forwards; - } - - .animation_bottom_center.hidden { - animation: slideOutBottom 0.2s ease-out forwards, collapseHeight 0.2s ease-out 0.1s forwards; - } -} diff --git a/components/notifications/src/partials/NotificationsItem.tsx b/components/notifications/src/partials/NotificationsItem.tsx index fd79a6fc..0cd03764 100644 --- a/components/notifications/src/partials/NotificationsItem.tsx +++ b/components/notifications/src/partials/NotificationsItem.tsx @@ -31,7 +31,6 @@ export const NotificationsItem = (props: INotificationsItemProps) => { } = props; const timerStartRef = useRef(0); - const lastStartRef = useRef(0); const remainingTime = useRef(duration); const closeNotification = useCallback(() => { @@ -48,7 +47,7 @@ export const NotificationsItem = (props: INotificationsItemProps) => { }, [isAutoClosable, duration]); useEffect(() => { - if (!isAutoClosable || duration === Infinity) return; + if (!isAutoClosable || duration === Infinity || duration < 0) return; let timeoutId: ReturnType; @@ -58,8 +57,6 @@ export const NotificationsItem = (props: INotificationsItemProps) => { remainingTime.current -= elapsedTime; } - - lastStartRef.current = new Date().getTime(); }; const startTimer = () => { @@ -96,7 +93,7 @@ export const NotificationsItem = (props: INotificationsItemProps) => { const containerRole = theme === 'danger' ? 'alert' : 'status'; return ( -
    • +
    • {children}
    • ); From 7eda16c7adb59aa4e9e5f2c83920af49d53784c9 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Mon, 3 Feb 2025 13:58:06 +0500 Subject: [PATCH 09/13] fix(notifications): readme, option afterClose for emitter --- components/notifications/README.md | 22 ++++++++++--------- .../notifications/src/Notifications.types.ts | 5 ++++- .../src/NotificationsManager.tsx | 5 +++-- .../src/__stories__/Notifications.stories.tsx | 5 +---- .../src/hooks/useNotificationsManager.ts | 1 - .../src/partials/NotificationsItem.tsx | 6 +++-- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/components/notifications/README.md b/components/notifications/README.md index e50bc20b..349d0710 100644 --- a/components/notifications/README.md +++ b/components/notifications/README.md @@ -20,7 +20,7 @@ import NotificationsManager, {useNotifications, INotificationData} from '@byndyu const SomeComponent = () => { const {success} = useNotifications(); - const onShowSuccess = () => { + const onShowSuccessNotification = () => { success({ title: 'Some string', message: 'Some ReactNode...', @@ -29,7 +29,7 @@ const SomeComponent = () => { } return ( - ) @@ -115,7 +115,7 @@ import NotificationsManager from '@byndyusoft-ui/notifications'; isPauseWhenPageHidden isCloseOnClick={false} isPauseOnHover - renderNotification={Notification} // or ({ data, index }) => JSX + renderNotification={Notification} // or ({ data, index }) => renderNotificationComponents={{ success: SuccessNotification, danger: DangerNotification, @@ -130,7 +130,7 @@ import NotificationsManager from '@byndyusoft-ui/notifications'; > - `renderNotificationComponents` allows you to set a component personally for each `theme` of notification (e.g., `success`, `danger`, `info`, `warning`, `ordinary`). > - If you use `renderNotification`, then `renderNotificationComponents` will override the components for all notification themes. -## Emitter (useNotifications) +## Emitter (actions from useNotifications) ### Params create @@ -150,8 +150,10 @@ import NotificationsManager from '@byndyusoft-ui/notifications'; | render | `TNotificationRender` | Component for rendering the notification. | | theme | `TNotificationTheme` | Theme of the notification. | | afterClose | () => void | Callback function to be executed after the notification is closed. | -| className | string | Class for the notification container. | -| style | CSSProperties | Style object for the notification container. | +| className | string | Class name for the notifications component. | +| classNameItem | CSSProperties | Class for the notification container. | +| style | CSSProperties | Style object for the notifications component. | +| styleItem | CSSProperties | Style object for the notification container. | ### Usages @@ -168,10 +170,10 @@ const options = { isClosable: true, isAutoClosable: true, isCloseOnClick: false, - className: 'some-class', - style: { - // ...styles - }, + className: 'notification', + style: {/* ...styles notification */ }, + classNameItem: 'contaider-item', + styleItem: {/* ...styles contaider*/ }, afterClose: () => console.log("afterClose"), }; diff --git a/components/notifications/src/Notifications.types.ts b/components/notifications/src/Notifications.types.ts index dba7abe2..2dd959ea 100644 --- a/components/notifications/src/Notifications.types.ts +++ b/components/notifications/src/Notifications.types.ts @@ -20,7 +20,6 @@ export interface INotification { footer?: ReactNode; isClosable?: boolean; onClose?: Callback; - afterClose?: Callback; className?: string; style?: CSSProperties; } @@ -43,6 +42,9 @@ export interface INotificationsItem extends INotification { dismiss?: boolean; isCloseOnClick?: boolean; render?: TNotificationRender; + afterClose?: Callback; + classNameItem?: string; + styleItem?: CSSProperties; } export type TCreateNotificationParams = Partial>; @@ -102,6 +104,7 @@ export interface INotificationsItemProps { dismiss?: boolean; isPauseToRemove?: boolean; onClick?: () => void; + afterClose?: () => void; className?: string; style?: CSSProperties; } diff --git a/components/notifications/src/NotificationsManager.tsx b/components/notifications/src/NotificationsManager.tsx index cd802b75..9bc3c09b 100644 --- a/components/notifications/src/NotificationsManager.tsx +++ b/components/notifications/src/NotificationsManager.tsx @@ -81,8 +81,8 @@ const NotificationsManager = (props: INotificationsManagerProps) => { {preparedNotifications?.map((item, itemIndex) => ( { } removeNotification={removeNotification(item.id)} onClick={onClickAndClose(item.id, item.isCloseOnClick)} + afterClose={item?.afterClose} > {renderNotificationItem(item, itemIndex)} diff --git a/components/notifications/src/__stories__/Notifications.stories.tsx b/components/notifications/src/__stories__/Notifications.stories.tsx index e0893c4c..34457877 100644 --- a/components/notifications/src/__stories__/Notifications.stories.tsx +++ b/components/notifications/src/__stories__/Notifications.stories.tsx @@ -250,14 +250,11 @@ custom(({data}) =>
      {data.id} | Custom notification
      , }; export const NotificationsStory: StoryObj = { - name: 'Notifications tory', + name: 'Notifications story', render: Template, args: {} }; export default { title: 'components/Notifications' - // parameters: { - // layout: 'fullscreen' - // } }; diff --git a/components/notifications/src/hooks/useNotificationsManager.ts b/components/notifications/src/hooks/useNotificationsManager.ts index bd53434a..eb01ed38 100644 --- a/components/notifications/src/hooks/useNotificationsManager.ts +++ b/components/notifications/src/hooks/useNotificationsManager.ts @@ -62,7 +62,6 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => isClosable: item?.isClosable || isClosable, onClose: () => { notificationService.dismiss(item.id); - item?.afterClose?.(); } }; }; diff --git a/components/notifications/src/partials/NotificationsItem.tsx b/components/notifications/src/partials/NotificationsItem.tsx index 0cd03764..3bf9c2d8 100644 --- a/components/notifications/src/partials/NotificationsItem.tsx +++ b/components/notifications/src/partials/NotificationsItem.tsx @@ -25,9 +25,10 @@ export const NotificationsItem = (props: INotificationsItemProps) => { isAutoClosable, isPauseToRemove, removeNotification, - onClick, className, - style + style, + onClick, + afterClose } = props; const timerStartRef = useRef(0); @@ -35,6 +36,7 @@ export const NotificationsItem = (props: INotificationsItemProps) => { const closeNotification = useCallback(() => { setIsFadingOut(true); + afterClose?.(); setTimeout(() => { removeNotification(); From b4d28a44717e8beaa65241d7250d227ffd4e9917 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Mon, 3 Feb 2025 18:32:27 +0500 Subject: [PATCH 10/13] fix(notifications): action dismissAll --- components/notifications/src/Notifications.types.ts | 1 + components/notifications/src/NotificationsManager.tsx | 4 +++- .../notifications/src/hooks/useNotificationsManager.ts | 5 +++++ components/notifications/src/partials/NotificationsItem.tsx | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/components/notifications/src/Notifications.types.ts b/components/notifications/src/Notifications.types.ts index 2dd959ea..2cdadcb2 100644 --- a/components/notifications/src/Notifications.types.ts +++ b/components/notifications/src/Notifications.types.ts @@ -99,6 +99,7 @@ export interface INotificationsItemProps { duration: number; position: TNotificationPosition; removeNotification: () => void; + dismissNotification: () => void; theme?: TNotificationTheme; isAutoClosable?: boolean; dismiss?: boolean; diff --git a/components/notifications/src/NotificationsManager.tsx b/components/notifications/src/NotificationsManager.tsx index 9bc3c09b..3bdd6830 100644 --- a/components/notifications/src/NotificationsManager.tsx +++ b/components/notifications/src/NotificationsManager.tsx @@ -37,6 +37,7 @@ const NotificationsManager = (props: INotificationsManagerProps) => { notifications, possiblePositions, onClickAndClose, + dismissNotification, removeNotification, renderNotificationItem, prepareNotifications @@ -80,7 +81,7 @@ const NotificationsManager = (props: INotificationsManagerProps) => { > {preparedNotifications?.map((item, itemIndex) => ( { (isPauseOnHover && focusedPosition === position) || (isPauseWhenPageHidden && isDocumentHidden) } + dismissNotification={dismissNotification(item.id)} removeNotification={removeNotification(item.id)} onClick={onClickAndClose(item.id, item.isCloseOnClick)} afterClose={item?.afterClose} diff --git a/components/notifications/src/hooks/useNotificationsManager.ts b/components/notifications/src/hooks/useNotificationsManager.ts index eb01ed38..49c02c7f 100644 --- a/components/notifications/src/hooks/useNotificationsManager.ts +++ b/components/notifications/src/hooks/useNotificationsManager.ts @@ -44,6 +44,10 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => return () => notificationService.dismiss(itemId); }; + const dismissNotification = (itemId: TNotificationItemId) => (): void => { + notificationService.dismiss(itemId); + }; + const removeNotification = (itemId: TNotificationItemId) => (): void => { notificationService.remove(itemId); }; @@ -121,6 +125,7 @@ export const useNotificationsManager = (params: IUseNotificationsStateParams) => possiblePositions, notifications, onClickAndClose, + dismissNotification, removeNotification, renderNotificationItem, prepareNotifications diff --git a/components/notifications/src/partials/NotificationsItem.tsx b/components/notifications/src/partials/NotificationsItem.tsx index 3bf9c2d8..b1015f2d 100644 --- a/components/notifications/src/partials/NotificationsItem.tsx +++ b/components/notifications/src/partials/NotificationsItem.tsx @@ -24,6 +24,7 @@ export const NotificationsItem = (props: INotificationsItemProps) => { duration, isAutoClosable, isPauseToRemove, + dismissNotification, removeNotification, className, style, @@ -66,7 +67,7 @@ export const NotificationsItem = (props: INotificationsItemProps) => { timerStartRef.current = new Date().getTime(); - timeoutId = setTimeout(closeNotification, remainingTime.current); + timeoutId = setTimeout(dismissNotification, remainingTime.current); }; if (isPauseToRemove) { From d6f1380e10799882492189eacb81f224fef2bd87 Mon Sep 17 00:00:00 2001 From: Gleb <114739540+glebfomin28@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:36:57 +0500 Subject: [PATCH 11/13] chore(notifications): `use-document-visibility.ts` Co-authored-by: Dmitry --- components/notifications/src/hooks/use-document-visibility.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/notifications/src/hooks/use-document-visibility.ts b/components/notifications/src/hooks/use-document-visibility.ts index ef0d5244..ee79b013 100644 --- a/components/notifications/src/hooks/use-document-visibility.ts +++ b/components/notifications/src/hooks/use-document-visibility.ts @@ -8,7 +8,7 @@ export const useIsDocumentHidden = () => { setIsDocumentHidden(document.hidden); }; document.addEventListener('visibilitychange', callback); - return () => window.removeEventListener('visibilitychange', callback); + return () => document.removeEventListener('visibilitychange', callback); }, []); return isDocumentHidden; From f3326de09fa0445d2425a09755bb3d0270993f71 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Wed, 5 Feb 2025 16:37:32 +0500 Subject: [PATCH 12/13] chore(notifications): file name --- components/notifications/src/NotificationsManager.tsx | 2 +- .../{use-document-visibility.ts => useDocumentVisibility.ts} | 0 components/notifications/src/services/notifications.service.ts | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) rename components/notifications/src/hooks/{use-document-visibility.ts => useDocumentVisibility.ts} (100%) diff --git a/components/notifications/src/NotificationsManager.tsx b/components/notifications/src/NotificationsManager.tsx index 3bdd6830..a631cde1 100644 --- a/components/notifications/src/NotificationsManager.tsx +++ b/components/notifications/src/NotificationsManager.tsx @@ -2,7 +2,7 @@ import React, { CSSProperties, useState } from 'react'; import Portal from '@byndyusoft-ui/portal'; import { normalizeCssValue, normalizePlatformValue } from './utilities'; import { NotificationsItem } from './partials/NotificationsItem'; -import { useIsDocumentHidden } from './hooks/use-document-visibility'; +import { useIsDocumentHidden } from './hooks/useDocumentVisibility'; import { INotificationsManagerProps, TNotificationPosition } from './Notifications.types'; import { useNotificationsManager } from './hooks/useNotificationsManager'; import { cn } from './utilities'; diff --git a/components/notifications/src/hooks/use-document-visibility.ts b/components/notifications/src/hooks/useDocumentVisibility.ts similarity index 100% rename from components/notifications/src/hooks/use-document-visibility.ts rename to components/notifications/src/hooks/useDocumentVisibility.ts diff --git a/components/notifications/src/services/notifications.service.ts b/components/notifications/src/services/notifications.service.ts index 09c89314..62e3b5af 100644 --- a/components/notifications/src/services/notifications.service.ts +++ b/components/notifications/src/services/notifications.service.ts @@ -21,7 +21,6 @@ class NotificationsService { create = (partial: TCreateNotificationParams): TNotificationItemId => { const id = partial?.id || notificationCounter++; const theme = partial?.theme || 'ordinary'; - const index = this.notifications.findIndex(item => item.id === id); const updatedItem = { ...this.notifications[index], From 9129d214f35f1618d7dd019f4d065d988bcd1c05 Mon Sep 17 00:00:00 2001 From: Gleb Fomin Date: Thu, 6 Feb 2025 10:44:18 +0500 Subject: [PATCH 13/13] fix(notifications): conflict in `package-lock.json` --- package-lock.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8833650e..96f6540f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,24 @@ "react-dom": ">=17" } }, + "components/notifications": { + "version": "0.0.1", + "license": "ISC", + "devDependencies": { + "@byndyusoft-ui/types": "^0.1.0" + }, + "peerDependencies": { + "@byndyusoft-ui/pub-sub": "^0.0.1", + "react": ">=17", + "react-dom": ">=17" + } + }, + "components/notifications/node_modules/@byndyusoft-ui/types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@byndyusoft-ui/types/-/types-0.1.1.tgz", + "integrity": "sha512-hRQbyzPbz1pdcLbYtgUnnk5pOlUY2yNpJ/o28NX4vQwmg2hNyPgifaK8STT77rhMEL5btcETYkD7YrMSz11EDA==", + "dev": true + }, "components/portal": { "name": "@byndyusoft-ui/portal", "version": "1.0.0", @@ -2294,10 +2312,18 @@ "resolved": "components/modals-provider", "link": true }, + "node_modules/@byndyusoft-ui/notifications": { + "resolved": "components/notifications", + "link": true + }, "node_modules/@byndyusoft-ui/portal": { "resolved": "components/portal", "link": true }, + "node_modules/@byndyusoft-ui/pub-sub": { + "resolved": "services/pub-sub", + "link": true + }, "node_modules/@byndyusoft-ui/reset-css": { "resolved": "styles/reset-css", "link": true @@ -32115,6 +32141,10 @@ "version": "0.2.0", "license": "Apache-2.0" }, + "services/pub-sub": { + "version": "0.0.1", + "license": "Apache-2.0" + }, "styles/keyframes-css": { "name": "@byndyusoft-ui/keyframes-css", "version": "0.0.1",