diff --git a/packages/frontend/.storybook/main.ts b/packages/frontend/.storybook/main.ts index 9d1c517ea4..b6b7a62726 100644 --- a/packages/frontend/.storybook/main.ts +++ b/packages/frontend/.storybook/main.ts @@ -5,9 +5,9 @@ import restart from 'vite-plugin-restart'; const config = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ - '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', + '@storybook/addon-links', '@storybook/addon-storysource', '../node_modules/storybook-addon-misskey-theme', ], @@ -21,6 +21,9 @@ const config = { core: { disableTelemetry: true, }, + features: { + interactionsDebugger: true, + }, async viteFinal(config, options) { return mergeConfig(config, { plugins: [ diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts index fb5065b360..85910f8ed0 100644 --- a/packages/frontend/.storybook/preview.ts +++ b/packages/frontend/.storybook/preview.ts @@ -90,7 +90,9 @@ const preview = { popups: misskeyOS.popups, }; }, - template: '<component :is="popup.component" v-for="popup in popups" :key="popup.id" v-bind="popup.props" v-on="popup.events"/><story />', + template: + '<component :is="popup.component" v-for="popup in popups" :key="popup.id" v-bind="popup.props" v-on="popup.events"/>' + + '<story />', }; }, ], diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 20463ac803..e4be6c13e3 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -79,11 +79,12 @@ "@storybook/addons": "7.0.0-rc.5", "@storybook/blocks": "7.0.0-rc.6", "@storybook/core-events": "7.0.0-rc.6", + "@storybook/jest": "0.0.10", "@storybook/manager-api": "7.0.0-rc.6", "@storybook/preview-api": "7.0.0-rc.6", "@storybook/react": "7.0.0-rc.6", "@storybook/react-vite": "7.0.0-rc.6", - "@storybook/testing-library": "^0.0.14-next.1", + "@storybook/testing-library": "0.0.14-next.1", "@storybook/theming": "7.0.0-rc.6", "@storybook/types": "7.0.0-rc.6", "@storybook/vue3": "7.0.0-rc.6", diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index 9e3022896c..e513a65a32 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -1,5 +1,5 @@ <template> -<div> +<div role="menu"> <div ref="itemsEl" v-hotkey="keymap" class="_popup _shadow" @@ -8,37 +8,37 @@ @contextmenu.self="e => e.preventDefault()" > <template v-for="(item, i) in items2"> - <div v-if="item === null" :class="$style.divider"></div> - <span v-else-if="item.type === 'label'" :class="[$style.label, $style.item]"> + <div v-if="item === null" role="separator" :class="$style.divider"></div> + <span v-else-if="item.type === 'label'" role="menuitem" :class="[$style.label, $style.item]"> <span>{{ item.text }}</span> </span> - <span v-else-if="item.type === 'pending'" :tabindex="i" :class="[$style.pending, $style.item]"> + <span v-else-if="item.type === 'pending'" role="menuitem" :tabindex="i" :class="[$style.pending, $style.item]"> <span><MkEllipsis/></span> </span> - <MkA v-else-if="item.type === 'link'" :to="item.to" :tabindex="i" class="_button" :class="$style.item" @click.passive="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <MkA v-else-if="item.type === 'link'" role="menuitem" :to="item.to" :tabindex="i" class="_button" :class="$style.item" @click.passive="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <span>{{ item.text }}</span> <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </MkA> - <a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" :tabindex="i" class="_button" :class="$style.item" @click="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <a v-else-if="item.type === 'a'" role="menuitem" :href="item.href" :target="item.target" :download="item.download" :tabindex="i" class="_button" :class="$style.item" @click="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <span>{{ item.text }}</span> <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </a> - <button v-else-if="item.type === 'user'" :tabindex="i" class="_button" :class="[$style.item, { [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <button v-else-if="item.type === 'user'" role="menuitem" :tabindex="i" class="_button" :class="[$style.item, { [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <MkAvatar :user="item.user" :class="$style.avatar"/><MkUserName :user="item.user"/> <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </button> - <span v-else-if="item.type === 'switch'" :tabindex="i" :class="$style.item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <span v-else-if="item.type === 'switch'" role="menuitemcheckbox" :tabindex="i" :class="$style.item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <MkSwitch v-model="item.ref" :disabled="item.disabled" class="form-switch">{{ item.text }}</MkSwitch> </span> - <button v-else-if="item.type === 'parent'" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)"> + <button v-else-if="item.type === 'parent'" role="menuitem" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)"> <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <span>{{ item.text }}</span> <span :class="$style.caret"><i class="ti ti-chevron-right ti-fw"></i></span> </button> - <button v-else :tabindex="i" class="_button" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <button v-else :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <span>{{ item.text }}</span> diff --git a/packages/frontend/src/components/global/MkA.stories.impl.ts b/packages/frontend/src/components/global/MkA.stories.impl.ts new file mode 100644 index 0000000000..b1a88be5a3 --- /dev/null +++ b/packages/frontend/src/components/global/MkA.stories.impl.ts @@ -0,0 +1,46 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { expect } from '@storybook/jest'; +import { userEvent, within } from '@storybook/testing-library'; +import { StoryObj } from '@storybook/vue3'; +import MkA from './MkA.vue'; +import { tick } from '@/scripts/test-utils'; +export const Default = { + render(args) { + return { + components: { + MkA, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...args, + }; + }, + }, + template: '<MkA v-bind="props">Text</MkA>', + }; + }, + args: { + to: '#test', + }, + parameters: { + layout: 'centered', + }, +} satisfies StoryObj<typeof MkA>; +export const ContextMenu = { + ...Default, + async play({ canvasElement }) { + const canvas = within(canvasElement); + const a = canvas.getByRole<HTMLAnchorElement>('link'); + await expect(a.href).toMatch(/^https?:\/\/.*#test$/); + await userEvent.click(a, { button: 2 }); + await tick(); + const menu = canvas.getByRole('menu'); + await expect(menu).toBeInTheDocument(); + }, +} satisfies StoryObj<typeof MkA>; diff --git a/packages/frontend/src/components/global/MkA.stories.ts b/packages/frontend/src/components/global/MkA.stories.ts index 91ea368263..ce648f2d57 100644 --- a/packages/frontend/src/components/global/MkA.stories.ts +++ b/packages/frontend/src/components/global/MkA.stories.ts @@ -1,11 +1,17 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable import/no-default-export */ -import { Meta, StoryObj } from '@storybook/vue3'; -import MkA from './MkA.vue'; +import { Meta } from '@storybook/vue3'; const meta = { title: 'components/global/MkA', component: MkA, } satisfies Meta<typeof MkA>; +export default meta; +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { expect } from '@storybook/jest'; +import { userEvent, within } from '@storybook/testing-library'; +import { StoryObj } from '@storybook/vue3'; +import MkA from './MkA.vue'; +import { tick } from '@/scripts/test-utils'; export const Default = { render(args) { return { @@ -24,11 +30,22 @@ export const Default = { }; }, }, - template: '<MkA v-bind="props" />', + template: '<MkA v-bind="props">Text</MkA>', }; }, + async play({ canvasElement }) { + const canvas = within(canvasElement); + const a = canvas.getByRole<HTMLAnchorElement>('link'); + await expect(a.href).toMatch(/^https?:\/\/.*#test$/); + await userEvent.click(a, { button: 2 }); + await tick(); + const menu = canvas.getByRole('menu'); + await expect(menu).toBeInTheDocument(); + }, + args: { + to: '#test', + }, parameters: { layout: 'centered', }, } satisfies StoryObj<typeof MkA>; -export default meta; diff --git a/packages/frontend/src/scripts/test-utils.ts b/packages/frontend/src/scripts/test-utils.ts new file mode 100644 index 0000000000..c526fc156a --- /dev/null +++ b/packages/frontend/src/scripts/test-utils.ts @@ -0,0 +1,4 @@ +export async function tick(): Promise<void> { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + await new Promise((globalThis.requestIdleCallback ?? setTimeout) as never); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe02e9e9d6..df273e26e7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -411,11 +411,12 @@ importers: '@storybook/addons': 7.0.0-rc.5 '@storybook/blocks': 7.0.0-rc.6 '@storybook/core-events': 7.0.0-rc.6 + '@storybook/jest': 0.0.10 '@storybook/manager-api': 7.0.0-rc.6 '@storybook/preview-api': 7.0.0-rc.6 '@storybook/react': 7.0.0-rc.6 '@storybook/react-vite': 7.0.0-rc.6 - '@storybook/testing-library': ^0.0.14-next.1 + '@storybook/testing-library': 0.0.14-next.1 '@storybook/theming': 7.0.0-rc.6 '@storybook/types': 7.0.0-rc.6 '@storybook/vue3': 7.0.0-rc.6 @@ -583,6 +584,7 @@ importers: '@storybook/addons': 7.0.0-rc.5_biqbaboplfbrettd7655fr4n2y '@storybook/blocks': 7.0.0-rc.6_biqbaboplfbrettd7655fr4n2y '@storybook/core-events': 7.0.0-rc.6 + '@storybook/jest': 0.0.10_biqbaboplfbrettd7655fr4n2y '@storybook/manager-api': 7.0.0-rc.6_biqbaboplfbrettd7655fr4n2y '@storybook/preview-api': 7.0.0-rc.6 '@storybook/react': 7.0.0-rc.6_ygqkwb4gg3aean7xjfdauovyqq @@ -656,6 +658,10 @@ importers: packages: + /@adobe/css-tools/4.2.0: + resolution: {integrity: sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==} + dev: true + /@ampproject/remapping/2.2.0: resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} engines: {node: '>=6.0.0'} @@ -3610,13 +3616,6 @@ packages: jest-mock: 29.5.0 dev: true - /@jest/expect-utils/29.3.1: - resolution: {integrity: sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.4.3 - dev: true - /@jest/expect-utils/29.5.0: resolution: {integrity: sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -3695,13 +3694,6 @@ packages: - supports-color dev: true - /@jest/schemas/29.4.2: - resolution: {integrity: sha512-ZrGzGfh31NtdVH8tn0mgJw4khQuNHiKqdzJAFbCaERbyCP9tHlxWuL/mnMu8P7e/+k4puWjI1NOzi/sFsjce/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.25.21 - dev: true - /@jest/schemas/29.4.3: resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4611,6 +4603,27 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true + /@storybook/addons/6.5.16_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@storybook/api': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@storybook/channels': 6.5.16 + '@storybook/client-logger': 6.5.16 + '@storybook/core-events': 6.5.16 + '@storybook/csf': 0.0.2--canary.4566f4d.1 + '@storybook/router': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@storybook/theming': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@types/webpack-env': 1.18.0 + core-js: 3.29.1 + global: 4.4.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + regenerator-runtime: 0.13.11 + dev: true + /@storybook/addons/7.0.0-rc.5_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-KDSoMW/y39eAMbeSmwmYEiYu3KomabJCYdsfmD65i0DqwuOFrkG3im3wPkF3F88rZDuzWzVZMl3Z15n56uVXKA==} peerDependencies: @@ -4624,6 +4637,33 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true + /@storybook/api/6.5.16_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@storybook/channels': 6.5.16 + '@storybook/client-logger': 6.5.16 + '@storybook/core-events': 6.5.16 + '@storybook/csf': 0.0.2--canary.4566f4d.1 + '@storybook/router': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@storybook/semver': 7.3.2 + '@storybook/theming': 6.5.16_biqbaboplfbrettd7655fr4n2y + core-js: 3.29.1 + fast-deep-equal: 3.1.3 + global: 4.4.0 + lodash: 4.17.21 + memoizerific: 1.11.3 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + regenerator-runtime: 0.13.11 + store2: 2.14.2 + telejson: 6.0.8 + ts-dedent: 2.2.0 + util-deprecate: 1.0.2 + dev: true + /@storybook/blocks/7.0.0-rc.6_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-3+9Aki5+tBqcTqZx+aDlQfVKdMflTwchr1DlBZODkd/dMKp8+sM7nHfH4hH0GipgppY8u+MxS0AmxsbwaF0xgA==} peerDependencies: @@ -4767,6 +4807,14 @@ packages: telejson: 7.0.4 dev: true + /@storybook/channels/6.5.16: + resolution: {integrity: sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==} + dependencies: + core-js: 3.29.1 + ts-dedent: 2.2.0 + util-deprecate: 1.0.2 + dev: true + /@storybook/channels/7.0.0-rc.5: resolution: {integrity: sha512-/T4iJQsTj42bs+d2sG8aLyInKh1IjZeK0vPoJRK9gvy3YfxTj3yodZ60s2yywKJCgGjg5zJMFxYMWqSVmHIdnw==} dev: true @@ -4828,6 +4876,13 @@ packages: - utf-8-validate dev: true + /@storybook/client-logger/6.5.16: + resolution: {integrity: sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==} + dependencies: + core-js: 3.29.1 + global: 4.4.0 + dev: true + /@storybook/client-logger/7.0.0-rc.5: resolution: {integrity: sha512-YkqjJb2jK6/jT4zm9cmdMVZeOyzoDxiyK3BedhoXKMRDMz+7+E7tcOZEXsuvTGekJe459TTnwYLfvUvObaXNKw==} dependencies: @@ -4918,6 +4973,12 @@ packages: - supports-color dev: true + /@storybook/core-events/6.5.16: + resolution: {integrity: sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==} + dependencies: + core-js: 3.29.1 + dev: true + /@storybook/core-events/7.0.0-rc.5: resolution: {integrity: sha512-n9+TqgrgkXN5V+mNdgdnojUVqhKOsyL3DNfOmAsbLEewhg5z6+QDYxOe/FBe1usGI2DV+ihwb/knMZzuYXN5ow==} dev: true @@ -5008,6 +5069,12 @@ packages: - supports-color dev: true + /@storybook/csf/0.0.2--canary.4566f4d.1: + resolution: {integrity: sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ==} + dependencies: + lodash: 4.17.21 + dev: true + /@storybook/csf/0.0.2-next.10: resolution: {integrity: sha512-m2PFgBP/xRIF85VrDhvesn9ktaD2pN3VUjvMqkAL/cINp/3qXsCyI81uw7N5VEOkQAbWrY2FcydnvEPDEdE8fA==} dependencies: @@ -5032,10 +5099,29 @@ packages: - supports-color dev: true + /@storybook/expect/27.5.2-0: + resolution: {integrity: sha512-cP99mhWN/JeCp7VSIiymvj5tmuMY050iFohvp8Zq+kewKsBSZ6/qpTJAGCCZk6pneTcp4S0Fm5BSqyxzbyJ3gw==} + dependencies: + '@types/jest': 29.4.0 + dev: true + /@storybook/global/5.0.0: resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} dev: true + /@storybook/instrumenter/6.5.16_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-q8/GaBk8PA/cL7m5OW+ec5t63+Zja9YvYSPGXrYtW17koSv7OnNPmk6RvI7tIHHO0mODBYnaHjF4zQfEGoyR5Q==} + dependencies: + '@storybook/addons': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@storybook/client-logger': 6.5.16 + '@storybook/core-events': 6.5.16 + core-js: 3.29.1 + global: 4.4.0 + transitivePeerDependencies: + - react + - react-dom + dev: true + /@storybook/instrumenter/7.0.0-rc.6: resolution: {integrity: sha512-hveboySEYxBtLYSgxHm2PI0Sa1DD/M6zkuCYqP4MXIoftRd437U1KzAtPrklnCoKrzUWPAXMJ8GUjwbM40RyGg==} dependencies: @@ -5056,6 +5142,18 @@ packages: '@storybook/preview-api': 7.0.0-rc.8 dev: true + /@storybook/jest/0.0.10_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-qeYLIplpcOUQXboJde5pRCjTvkGmF80jEszRUoNYCNcEPfC2sMK68Wq6Ct8EQj3CoEdJqsK54O2YYh+7D9S+ag==} + dependencies: + '@storybook/expect': 27.5.2-0 + '@storybook/instrumenter': 6.5.16_biqbaboplfbrettd7655fr4n2y + '@testing-library/jest-dom': 5.16.5 + jest-mock: 27.5.1 + transitivePeerDependencies: + - react + - react-dom + dev: true + /@storybook/manager-api/7.0.0-rc.5_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-MsNj/cPIOlL7HJ8ReYahUvJVfvZDtNfacUYSFuQjQwdnp0u3pbC5mGZPd32tAGj7lLaLzcqqo1yR+NAgwpZUBw==} peerDependencies: @@ -5270,6 +5368,21 @@ packages: - supports-color dev: true + /@storybook/router/6.5.16_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@storybook/client-logger': 6.5.16 + core-js: 3.29.1 + memoizerific: 1.11.3 + qs: 6.11.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + regenerator-runtime: 0.13.11 + dev: true + /@storybook/router/7.0.0-rc.5_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-s23O2OOQ4+CvySk3QC/PXhDJChc4jjyQu/h3gLMKF7bfWx0bd5KR4LnP3rCKLIMkxoJYFPUayPMgwEEeN/ENSw==} peerDependencies: @@ -5296,6 +5409,15 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true + /@storybook/semver/7.3.2: + resolution: {integrity: sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + core-js: 3.29.1 + find-up: 4.1.0 + dev: true + /@storybook/source-loader/7.0.0-rc.6_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-oEHEL26kOXRnTnBdZrMwUZAM2F8X9aFoqVmNIbLESx5QAlHGY04YLzKhi/tp31ZxoalxR7GveQ0GDzSDc62sCw==} peerDependencies: @@ -5338,6 +5460,20 @@ packages: ts-dedent: 2.2.0 dev: true + /@storybook/theming/6.5.16_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@storybook/client-logger': 6.5.16 + core-js: 3.29.1 + memoizerific: 1.11.3 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + regenerator-runtime: 0.13.11 + dev: true + /@storybook/theming/7.0.0-rc.5_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-OzwybDA2+4FWg85tcTNQkVI0JnHkwCRG9HM1qx9hOZJHNRfxmJFjJePOnBoXM6CjVlz0S1PJUwCmMHNH8OTvEw==} peerDependencies: @@ -5743,6 +5879,21 @@ packages: pretty-format: 27.5.1 dev: true + /@testing-library/jest-dom/5.16.5: + resolution: {integrity: sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==} + engines: {node: '>=8', npm: '>=6', yarn: '>=1'} + dependencies: + '@adobe/css-tools': 4.2.0 + '@babel/runtime': 7.20.7 + '@types/testing-library__jest-dom': 5.14.5 + aria-query: 5.1.3 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.5.16 + lodash: 4.17.21 + redent: 3.0.0 + dev: true + /@testing-library/user-event/13.5.0_yxlyej73nftwmh2fiao7paxmlm: resolution: {integrity: sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==} engines: {node: '>=10', npm: '>=6'} @@ -6020,6 +6171,10 @@ packages: '@types/node': 18.15.0 dev: true + /@types/is-function/1.0.1: + resolution: {integrity: sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==} + dev: true + /@types/istanbul-lib-coverage/2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: true @@ -6039,8 +6194,8 @@ packages: /@types/jest/29.4.0: resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==} dependencies: - expect: 29.3.1 - pretty-format: 29.3.1 + expect: 29.5.0 + pretty-format: 29.5.0 dev: true /@types/js-levenshtein/1.1.1: @@ -6308,6 +6463,12 @@ packages: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true + /@types/testing-library__jest-dom/5.14.5: + resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==} + dependencies: + '@types/jest': 29.4.0 + dev: true + /@types/throttle-debounce/5.0.0: resolution: {integrity: sha512-Pb7k35iCGFcGPECoNE4DYp3Oyf2xcTd3FbFQxXUI9hEYKUl6YX+KLf7HrBmgVcD05nl50LIH6i+80js4iYmWbw==} dev: true @@ -6380,6 +6541,10 @@ packages: resolution: {integrity: sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==} dev: false + /@types/webpack-env/1.18.0: + resolution: {integrity: sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==} + dev: true + /@types/websocket/1.0.5: resolution: {integrity: sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==} dependencies: @@ -8150,6 +8315,14 @@ packages: supports-color: 5.5.0 dev: true + /chalk/3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + /chalk/4.1.1: resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} engines: {node: '>=10'} @@ -8735,7 +8908,6 @@ packages: /core-js/3.29.1: resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==} requiresBuild: true - dev: false /core-util-is/1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -9361,6 +9533,10 @@ packages: domhandler: 5.0.3 entities: 4.4.0 + /dom-walk/0.1.2: + resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + dev: true + /domelementtype/2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} @@ -10426,17 +10602,6 @@ packages: homedir-polyfill: 1.0.3 dev: false - /expect/29.3.1: - resolution: {integrity: sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.3.1 - jest-get-type: 29.2.0 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-util: 29.5.0 - dev: true - /expect/29.5.0: resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -11438,6 +11603,13 @@ packages: which: 1.3.1 dev: false + /global/4.4.0: + resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} + dependencies: + min-document: 2.19.0 + process: 0.11.10 + dev: true + /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -12348,6 +12520,10 @@ packages: engines: {node: '>=12'} dev: true + /is-function/1.0.2: + resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==} + dev: true + /is-generator-fn/2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} @@ -12640,6 +12816,11 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + /isobject/4.0.0: + resolution: {integrity: sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==} + engines: {node: '>=0.10.0'} + dev: true + /isomorphic-unfetch/3.1.0: resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} dependencies: @@ -12864,11 +13045,6 @@ packages: jest-util: 29.5.0 dev: true - /jest-get-type/29.2.0: - resolution: {integrity: sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - /jest-get-type/29.4.3: resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -12901,16 +13077,6 @@ packages: pretty-format: 29.5.0 dev: true - /jest-matcher-utils/29.3.1: - resolution: {integrity: sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.5.0 - jest-get-type: 29.4.3 - pretty-format: 29.5.0 - dev: true - /jest-matcher-utils/29.5.0: resolution: {integrity: sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -12921,21 +13087,6 @@ packages: pretty-format: 29.5.0 dev: true - /jest-message-util/29.3.1: - resolution: {integrity: sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.18.6 - '@jest/types': 29.5.0 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - pretty-format: 29.5.0 - slash: 3.0.0 - stack-utils: 2.0.6 - dev: true - /jest-message-util/29.5.0: resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -14042,6 +14193,12 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /min-document/2.19.0: + resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + dependencies: + dom-walk: 0.1.2 + dev: true + /min-indent/1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -15687,15 +15844,6 @@ packages: react-is: 17.0.2 dev: true - /pretty-format/29.3.1: - resolution: {integrity: sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.4.2 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - /pretty-format/29.5.0: resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -16361,6 +16509,14 @@ packages: resolution: {integrity: sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==} dev: false + /redent/3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + /redis-commands/1.7.0: resolution: {integrity: sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==} dev: false @@ -17729,6 +17885,19 @@ packages: mkdirp: 1.0.4 yallist: 4.0.0 + /telejson/6.0.8: + resolution: {integrity: sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg==} + dependencies: + '@types/is-function': 1.0.1 + global: 4.4.0 + is-function: 1.0.2 + is-regex: 1.1.4 + is-symbol: 1.0.4 + isobject: 4.0.0 + lodash: 4.17.21 + memoizerific: 1.11.3 + dev: true + /telejson/7.0.4: resolution: {integrity: sha512-J4QEuCnYGXAI9KSN7RXK0a0cOW2ONpjc4IQbInGZ6c3stvplLAYyZjTnScrRd8deXVjNCFV1wXcLC7SObDuQYA==} dependencies: