diff --git a/.eslintignore b/.eslintignore index e48e90452f..7d953d5640 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,4 +9,5 @@ scripts /angular.json docs/**/*.md lib/js-api/docs/**/*.md +.storybook webpack.config.js diff --git a/.eslintrc.js b/.eslintrc.js index 2aa81dcd2b..5b04759d09 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -207,5 +207,7 @@ module.exports = { 'comma-dangle': ['error', 'never'] } } - ] + ], + + extends: ['plugin:storybook/recommended'] }; diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 4cc6b1512a..9c7e87c24f 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -4,17 +4,17 @@ on: workflow_call: inputs: dry-run-flag: - description: 'enable dry-run on artifact push' + description: "enable dry-run on artifact push" required: false type: boolean default: true devel: - description: 'devel' + description: "devel" required: false type: boolean default: false cron-run: - description: 'disables jobs which should not run when cron runs e2es' + description: "disables jobs which should not run when cron runs e2es" required: false type: boolean default: false @@ -230,6 +230,21 @@ jobs: - run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npm run build:affected -- $NX_CALCULATION_FLAGS --prod - uses: ./.github/actions/upload-node-modules-and-artifacts + build-storybook: + timeout-minutes: 30 + name: "Build storybook" + runs-on: ubuntu-latest + needs: [setup] + steps: + - name: Checkout repository + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + - uses: ./.github/actions/setup + - uses: ./.github/actions/download-node-modules-and-artifacts + - run: npm run build-storybook + - uses: ./.github/actions/upload-node-modules-and-artifacts + PR-forbidden-labels: if: ${{ inputs.cron-run == '' || inputs.cron-run == 'false' }} runs-on: ubuntu-latest @@ -264,7 +279,16 @@ jobs: if: ${{ always() }} runs-on: ubuntu-latest name: Final Results - needs: [check-if-pr-is-approved, pre-checks, setup, unit-tests, lint, build-libs] + needs: + [ + check-if-pr-is-approved, + pre-checks, + setup, + unit-tests, + lint, + build-libs, + build-storybook, + ] steps: - name: Check job execution status if: >- diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 0000000000..3593f6f525 --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,21 @@ +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import type { StorybookConfig } from '@storybook/angular'; + +const config: StorybookConfig = { + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + }, + staticDirs: [], + stories: ['lib/**/*.stories.ts'], + features: { + backgrounds: false + } +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} diff --git a/.storybook/preview.ts b/.storybook/preview.ts new file mode 100644 index 0000000000..cf107c6e87 --- /dev/null +++ b/.storybook/preview.ts @@ -0,0 +1,11 @@ +import type { Preview } from '@storybook/angular'; + +const preview: Preview = { + parameters: { + docs: { inlineStories: true }, + controls: { expanded: true } + }, + tags: ['autodocs'] +}; + +export default preview; diff --git a/.storybook/tsconfig.json b/.storybook/tsconfig.json new file mode 100644 index 0000000000..54a658ae74 --- /dev/null +++ b/.storybook/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "exclude": [ + "../**/*.spec.js", + "../**/*.spec.ts", + "../**/*.spec.tsx", + "../**/*.spec.jsx" + ], + "include": ["../**/*"] +} diff --git a/README.md b/README.md index 2b7fae137b..f9ad6c21f3 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ ADF Libraries list: - [Insights](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/insights) - [Process Service Cloud](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/process-services-cloud) - [Process service](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/process-services) +- [Stories](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/stories) ## Browser Support diff --git a/docs/storybook/adding-new-story.md b/docs/storybook/adding-new-story.md new file mode 100644 index 0000000000..310f3f1888 --- /dev/null +++ b/docs/storybook/adding-new-story.md @@ -0,0 +1,81 @@ +# Adding a New Story + +This guide describes how to create and structure a new story for a component in the Alfresco Angular Components repository. + +## File Location + +Story files should be co-located with the component they are documenting. This keeps the stories close to the source code and makes them easier to find and maintain. + +## Naming Convention + +The file should be named using the pattern: +`[component-name].stories.ts` + +For example, if your component is `my-component.component.ts`, the story file should be `my-component.component.stories.ts`. + +## Basic Structure + +A typical story file includes: + +1. Imports for `Meta`, `Story`, `moduleMetadata` from `@storybook/angular`. +2. The component configuration using `applicationConfig` to provide necessary dependencies. +3. Usage of `provideStoryCore()` (or other library-specific providers) to set up the environment. + +### Example + +Here is an example of how to set up a basic story for a component. + +```typescript +import { Meta, StoryObj, moduleMetadata, applicationConfig } from '@storybook/angular'; +import { MyComponent } from './my.component'; +import { provideStoryCore } from '@alfresco/adf-core/testing'; // Adjust import based on your library location +import { CommonModule } from '@angular/common'; + +const meta: Meta = { + title: 'Core/My Component', + component: MyComponent, + decorators: [ + applicationConfig({ + providers: [...provideStoryCore()] + }), + moduleMetadata({ + imports: [MyComponent] + }) + ], + argTypes: { + // Define controls for your inputs here + label: { control: 'text' }, + isDisabled: { control: 'boolean' } + } +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Click me', + isDisabled: false + } +}; + +export const Disabled: Story = { + args: { + label: 'Disabled', + isDisabled: true + } +}; +``` + +### Dependencies + +The `provideStoryCore()` function helper is essential for setting up the common providers required by ADF components, such as translation services, authentication mocks, and app configuration. + +If your component requires specific services not included in `provideStoryCore()`, you should add them to the `providers` array in the `applicationConfig`. + +## Useful Links + +- [Writing Stories](https://storybook.js.org/docs/angular/writing-stories/introduction) +- [Args and Controls](https://storybook.js.org/docs/angular/writing-stories/args) +- [Decorators](https://storybook.js.org/docs/angular/writing-stories/decorators) +- [Naming Components and Hierarchy](https://storybook.js.org/docs/angular/writing-stories/naming-components-and-hierarchy) diff --git a/docs/storybook/configuring-new-lib.md b/docs/storybook/configuring-new-lib.md new file mode 100644 index 0000000000..b1517d719f --- /dev/null +++ b/docs/storybook/configuring-new-lib.md @@ -0,0 +1,112 @@ +# Configuring Storybook for a New Library + +This guide outlines the steps to configure Storybook for a newly created Nx library within the repository. + +## Prerequisites + +Ensure that the library has been created using the Nx generator. + +## Configuration Steps + +### 1. Generate Storybook Configuration + +Run the Nx generator to add Storybook configuration to your library: + +```bash +nx g @nx/angular:storybook-configuration [project-name] +``` + +Replace `[project-name]` with the name of your library (e.g., `my-new-lib`). + +### 2. Update `project.json` + +Verify that the `project.json` file of your library has the `storybook` and `build-storybook` targets correctly configured. + +### 3. Update `.storybook/main.ts` + +Update the `.storybook/main.ts` file in your library to extend the root configuration and handle static assets correctly. + +```typescript +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import type { StorybookConfig } from '@storybook/angular'; +import rootMain from '../../../.storybook/main'; // Adjust path to root + +const config: StorybookConfig = { + ...rootMain, + stories: ['../**/*.stories.@(js|jsx|ts|tsx)'], + staticDirs: [ + // Add static directories if needed, e.g., for i18n or assets + { from: '../src/lib/i18n', to: 'assets/adf-my-lib/i18n' } + ], + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + } +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} +``` + +### 4. Update `.storybook/preview.ts` + +Update `.storybook/preview.ts` to import the root preview configuration and add any library-specific tags. + +```typescript +import { type Preview } from '@storybook/angular'; +import rootPreview from '../../../.storybook/preview'; // Adjust path to root + +const preview: Preview = { + ...rootPreview, + tags: ['autodocs'] +}; + +export default preview; +``` + +### 5. Update `.storybook/tsconfig.json` + +Ensure the `tsconfig.json` in the `.storybook` directory extends the main `tsconfig.json` and includes/excludes the correct files. + +```json +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true + }, + "exclude": ["../**/*.spec.ts", "../**/*.mock.ts", "../**/test.ts", "../**/*.module.ts"], + "include": ["../src/**/*", "*.ts"] +} +``` + +### 6. Update Root `lib/stories` + +To include the new library's stories in the aggregated Storybook (`nx run stories:storybook`), you need to update the `lib/stories/.storybook/main.ts` file. + +1. **Add Stories Pattern**: Add the path to your new library's stories in the `stories` array. +2. **Add Static Assets**: If your library has static assets (like i18n files), add them to the `staticDirs` array. + +Example update in `lib/stories/.storybook/main.ts`: + +```typescript +// ... +stories: [ + // ... existing entries + '../../my-new-lib/**/*.stories.ts' +], +staticDirs: [ + // ... existing entries + { from: '../../my-new-lib/src/lib/i18n', to: 'assets/adf-my-lib/i18n' } +], +// ... +``` + +## Useful Links + +- [Configure Storybook](https://storybook.js.org/docs/angular/configure/overview) +- [Framework Configuration (main.ts)](https://storybook.js.org/docs/angular/configure/framework-config) +- [Story Rendering (preview.ts)](https://storybook.js.org/docs/angular/configure/story-rendering) diff --git a/docs/storybook/using-storybook.md b/docs/storybook/using-storybook.md new file mode 100644 index 0000000000..123ff2dadd --- /dev/null +++ b/docs/storybook/using-storybook.md @@ -0,0 +1,33 @@ +# Using Storybook + +This guide explains how to run and build Storybook for the entire repository and for individual libraries within the Alfresco Angular Components project. + +## Introduction + +Storybook is used in this repository to develop and showcase components in isolation. It provides a sandbox environment where you can interact with components and view their different states. + +## Running All Stories + +To run the aggregated Storybook that includes stories from all libraries (Core, Content Services, Process Services Cloud, etc.), use the following command: + +```bash +npm run storybook +``` + +Once started, you can access the Storybook interface at: +[http://localhost:4400/](http://localhost:4400/) + +## Building Storybook + +To build the static Storybook application (e.g., for deployment), use the following command: + +```bash +npm run build-storybook +``` + +The build artifacts will be output to `dist/storybook/stories`. + +## Useful Links + +- [Storybook CLI Options](https://storybook.js.org/docs/angular/api/cli-options) +- [Storybook for Angular Introduction](https://storybook.js.org/docs/angular/get-started/introduction) diff --git a/lib/.gitignore b/lib/.gitignore index 1944f87594..c71e8dd3f8 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -27,6 +27,7 @@ insights/**/*.js.map insights/**/*.d.ts process-services-cloud/**/*.js +!process-services-cloud/.storybook/*.js !process-services-cloud/karma.conf.js process-services-cloud/**/*.js.map process-services-cloud/**/*.d.ts diff --git a/lib/config/app.config.json b/lib/config/app.config.json index 729fb251d2..f8787f2460 100644 --- a/lib/config/app.config.json +++ b/lib/config/app.config.json @@ -3,5 +3,6 @@ "ecmHost": "http://{hostname}:{port}/ecm", "bpmHost": "http://{hostname}:{port}/bpm", "baseShareUrl": null, - "logLevel" : "silent" + "logLevel" : "silent", + "locale" : "en" } diff --git a/lib/content-services/.eslintrc.json b/lib/content-services/.eslintrc.json index 6e8c8cbb30..f9cf897315 100644 --- a/lib/content-services/.eslintrc.json +++ b/lib/content-services/.eslintrc.json @@ -6,7 +6,11 @@ "files": ["*.ts"], "extends": ["plugin:@nx/angular"], "parserOptions": { - "project": ["lib/content-services/tsconfig.lib.json", "lib/content-services/tsconfig.spec.json"], + "project": [ + "lib/content-services/tsconfig.lib.json", + "lib/content-services/tsconfig.spec.json", + "lib/content-services/.storybook/tsconfig.json" + ], "createDefaultProgram": true }, "rules": { diff --git a/lib/content-services/.storybook/main.ts b/lib/content-services/.storybook/main.ts new file mode 100644 index 0000000000..39b51f7720 --- /dev/null +++ b/lib/content-services/.storybook/main.ts @@ -0,0 +1,23 @@ +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import type { StorybookConfig } from '@storybook/angular'; +import rootMain from '../../../.storybook/main'; + +const config: StorybookConfig = { + ...rootMain, + stories: ['../**/*.stories.@(js|jsx|ts|tsx)'], + staticDirs: [ + { from: '../src/lib/i18n', to: 'assets/adf-core/i18n' }, + { from: '../src/lib/assets/images', to: 'assets/images' } + ], + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + } +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} diff --git a/lib/content-services/.storybook/preview.ts b/lib/content-services/.storybook/preview.ts new file mode 100644 index 0000000000..cf107c6e87 --- /dev/null +++ b/lib/content-services/.storybook/preview.ts @@ -0,0 +1,11 @@ +import type { Preview } from '@storybook/angular'; + +const preview: Preview = { + parameters: { + docs: { inlineStories: true }, + controls: { expanded: true } + }, + tags: ['autodocs'] +}; + +export default preview; diff --git a/lib/content-services/.storybook/tsconfig.json b/lib/content-services/.storybook/tsconfig.json new file mode 100644 index 0000000000..0d22811575 --- /dev/null +++ b/lib/content-services/.storybook/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "moduleResolution": "bundler" + }, + + "exclude": ["../**/*.spec.ts" ], + "include": ["../src/**/*", "*.ts"] +} diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss index 9bc175a570..72c4dc0b0b 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss @@ -3,15 +3,14 @@ adf-content-node-selector { .adf-upload-dialog { box-shadow: none; - - &__content { - max-height: 64%; - } - height: 100%; width: 100%; position: unset; bottom: unset; + + &__content { + max-height: 64%; + } } .adf-upload-dialog-container { diff --git a/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.component.ts b/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.component.ts new file mode 100644 index 0000000000..c28e862b62 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.component.ts @@ -0,0 +1,60 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, inject, Input, OnInit, OnChanges } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { DownloadZipDialogComponent } from './download-zip.dialog'; +import { zipNode, downloadEntry } from './mock/download-zip-data.mock'; +import { FileDownloadStatus } from '@alfresco/js-api'; +import { MatButtonModule } from '@angular/material/button'; + +@Component({ + selector: 'adf-download-zip-dialog-storybook', + template: ``, + imports: [MatButtonModule] +}) +export class DownloadZipDialogStorybookComponent implements OnInit, OnChanges { + @Input() + showLoading: boolean; + + private readonly dialog = inject(MatDialog); + + ngOnInit(): void { + this.setEntryStatus(); + } + + ngOnChanges(): void { + this.setEntryStatus(); + } + + setEntryStatus() { + if (this.showLoading) { + downloadEntry.entry.status = FileDownloadStatus.IN_PROGRESS; + } else { + downloadEntry.entry.status = FileDownloadStatus.DONE; + } + } + + openDialog() { + this.dialog.open(DownloadZipDialogComponent, { + minWidth: '50%', + data: { + nodeIds: [zipNode.entry.id] + } + }); + } +} diff --git a/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.ts b/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.ts new file mode 100644 index 0000000000..63bbb90d4e --- /dev/null +++ b/lib/content-services/src/lib/dialogs/download-zip/download-zip.dialog.stories.ts @@ -0,0 +1,86 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { MatButtonModule } from '@angular/material/button'; +import { DownloadZipDialogStorybookComponent } from './download-zip.dialog.stories.component'; +import { AlfrescoApiServiceMock, ContentApiMock, DownloadZipMockService, NodesApiMock } from './mock/download-zip-service.mock'; +import { DownloadZipService } from './services/download-zip.service'; +import { ContentService } from '../../common/services/content.service'; +import { NodesApiService } from '../../common/services/nodes-api.service'; +import { MatDialogModule } from '@angular/material/dialog'; +import { AlfrescoApiService } from '../../services/alfresco-api.service'; +import { provideStoryCore } from '@alfresco/adf-core'; + +const meta: Meta = { + component: DownloadZipDialogStorybookComponent, + title: 'Core/Dialog/Download ZIP Dialog', + decorators: [ + moduleMetadata({ + imports: [MatButtonModule, MatDialogModule, DownloadZipDialogStorybookComponent], + providers: [ + { + provide: AlfrescoApiService, + useClass: AlfrescoApiServiceMock + }, + { + provide: DownloadZipService, + useClass: DownloadZipMockService + }, + { + provide: ContentService, + useClass: ContentApiMock + }, + { + provide: NodesApiService, + useClass: NodesApiMock + } + ] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + showLoading: { + control: { + type: 'boolean' + }, + table: { + category: 'Story controls', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'false' + } + } + } + }, + args: { + showLoading: false + } +}; + +export default meta; +type Story = StoryObj; + +export const DownloadZIPDialog: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-data.mock.ts b/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-data.mock.ts new file mode 100644 index 0000000000..65a17e3830 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-data.mock.ts @@ -0,0 +1,33 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DownloadEntry } from '@alfresco/js-api'; + +export const zipNode = { + entry: { + name: 'files.zip', + contentUrl: './assets/files.zip', + id: 'files_in_zip' + } +}; + +export const downloadEntry: DownloadEntry = { + entry: { + id: 'entryId', + status: 'DONE' + } +}; diff --git a/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-service.mock.ts b/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-service.mock.ts new file mode 100644 index 0000000000..e6b65879ff --- /dev/null +++ b/lib/content-services/src/lib/dialogs/download-zip/mock/download-zip-service.mock.ts @@ -0,0 +1,82 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DownloadBodyCreate, DownloadEntry, DownloadsApi, Node } from '@alfresco/js-api'; +import { from, Observable, of, ReplaySubject, Subject } from 'rxjs'; +import { catchError } from 'rxjs/internal/operators/catchError'; +import { zipNode, downloadEntry } from './download-zip-data.mock'; +import { DownloadZipService } from '../services/download-zip.service'; +import { ContentService, AlfrescoApiService } from '../../../../..'; +import { inject } from '@angular/core'; + +export class AlfrescoApiServiceMock extends AlfrescoApiService { + nodeUpdated = new Subject(); + alfrescoApiInitialized = new ReplaySubject(1); + alfrescoApi = inject(AlfrescoApiMock) as any; + + async load() {} + getInstance = () => this.alfrescoApi; +} + +class AlfrescoApiMock extends AlfrescoApiService { + core = inject(CoreMock); + content = inject(ContentApiMock); + + isOauthConfiguration = () => true; + isLoggedIn = () => true; + isEcmConfiguration = () => true; +} + +export class ContentApiMock extends ContentService { + getContentUrl = (): string => zipNode.entry.contentUrl; +} + +class CoreMock { + downloadsApi = new DownloadsApiMock(); + nodesApi = new NodesApiMock(); +} + +export class NodesApiMock { + getNode = (): any => of(zipNode.entry); +} + +class DownloadsApiMock extends DownloadsApi { + createDownload = (): Promise => Promise.resolve(downloadEntry); + + getDownload = (): Promise => Promise.resolve(downloadEntry); + cancelDownload = () => Promise.resolve(true); +} + +export class DownloadZipMockService extends DownloadZipService { + private _mockDownloadsApi: DownloadsApi; + get downloadsApi(): DownloadsApi { + this._mockDownloadsApi = this._mockDownloadsApi ?? new DownloadsApiMock(); + return this._mockDownloadsApi; + } + + createDownload(payload: DownloadBodyCreate): Observable { + return from(this.downloadsApi.createDownload(payload)).pipe(catchError((err) => of(err))); + } + + getDownload(downloadId: string): Observable { + return from(this.downloadsApi.getDownload(downloadId)); + } + + cancelDownload(downloadId: string) { + this.downloadsApi.cancelDownload(downloadId); + } +} diff --git a/lib/content-services/tsconfig.json b/lib/content-services/tsconfig.json index 204cc68ba2..93cbd20d23 100644 --- a/lib/content-services/tsconfig.json +++ b/lib/content-services/tsconfig.json @@ -11,6 +11,9 @@ }, { "path": "./tsconfig.spec.json" + }, + { + "path": "./.storybook/tsconfig.json" } ], "compilerOptions": { diff --git a/lib/content-services/tsconfig.lib.json b/lib/content-services/tsconfig.lib.json index daf5cb68ce..d6ff2c899f 100644 --- a/lib/content-services/tsconfig.lib.json +++ b/lib/content-services/tsconfig.lib.json @@ -15,5 +15,6 @@ "target": "ES2022", "useDefineForClassFields": false }, + "exclude": ["./test.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.stories.ts", "**/*.mock.ts"], "include": ["src/**/*.ts", "index.ts"] } diff --git a/lib/core/.eslintignore b/lib/core/.eslintignore index 4ebc8aea50..16523ff94f 100644 --- a/lib/core/.eslintignore +++ b/lib/core/.eslintignore @@ -1 +1,2 @@ +.storybook coverage diff --git a/lib/core/.eslintrc.json b/lib/core/.eslintrc.json index b4a17a13df..c0244ac613 100644 --- a/lib/core/.eslintrc.json +++ b/lib/core/.eslintrc.json @@ -6,7 +6,7 @@ "files": ["*.ts"], "extends": ["plugin:@nx/angular"], "parserOptions": { - "project": ["lib/core/tsconfig.lib.json", "lib/core/tsconfig.spec.json"], + "project": ["lib/core/tsconfig.lib.json", "lib/core/tsconfig.spec.json", "lib/core/.storybook/tsconfig.json"], "createDefaultProgram": true }, "rules": { diff --git a/lib/core/.storybook/main.ts b/lib/core/.storybook/main.ts new file mode 100644 index 0000000000..4fcbeeb2b3 --- /dev/null +++ b/lib/core/.storybook/main.ts @@ -0,0 +1,23 @@ +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import type { StorybookConfig } from '@storybook/angular'; +import rootMain from '../../../.storybook/main'; + +const config: StorybookConfig = { + ...rootMain, + stories: ['../**/*.stories.@(js|jsx|ts|tsx)'], + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + }, + staticDirs: [ + { from: '../src/lib/i18n', to: 'assets/adf-core/i18n' }, + { from: '../src/lib/assets/images', to: 'assets/images' } + ] +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} diff --git a/lib/core/.storybook/preview.ts b/lib/core/.storybook/preview.ts new file mode 100644 index 0000000000..c72f949aad --- /dev/null +++ b/lib/core/.storybook/preview.ts @@ -0,0 +1,9 @@ +import type { Preview } from '@storybook/angular'; +import rootPreview from '../../../.storybook/preview'; + +const preview: Preview = { + ...rootPreview, + tags: ['autodocs'] +}; + +export default preview; diff --git a/lib/core/.storybook/tsconfig.json b/lib/core/.storybook/tsconfig.json new file mode 100644 index 0000000000..815e1814b2 --- /dev/null +++ b/lib/core/.storybook/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "moduleResolution": "bundler" + }, + + "exclude": ["../**/*.spec.ts" ], + "include": ["../**/*.ts", "*.ts"] +} diff --git a/lib/core/README.md b/lib/core/README.md index bc36e56b04..b263247345 100644 --- a/lib/core/README.md +++ b/lib/core/README.md @@ -9,6 +9,7 @@ Contains a variety of components, directives and services used throughout ADF - [Documentation](#documentation) - [Prerequisites](#prerequisites) - [Install](#install) +- [Storybook](#storybook) - [License](#license) @@ -33,6 +34,21 @@ necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng npm install @alfresco/adf-core ``` +## Storybook + +In case you would like to aggregate all the stories from core library use + +``` +nx run core:storybook +``` +And navigate to `http://localhost:4400/`. + +To create a Storybook core library build use + +``` +nx run core:build-storybook +``` + ## License [Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE) diff --git a/lib/core/breadcrumbs/src/_stories/breadcrumb.stories.ts b/lib/core/breadcrumbs/src/_stories/breadcrumb.stories.ts new file mode 100644 index 0000000000..561e868c14 --- /dev/null +++ b/lib/core/breadcrumbs/src/_stories/breadcrumb.stories.ts @@ -0,0 +1,69 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatIconModule } from '@angular/material/icon'; +import { BreadcrumbComponent } from '../components/breadcrumb/breadcrumb.component'; +import { BreadcrumbItemComponent } from '../components/breadcrumb-item/breadcrumb-item.component'; +import { DemoBreadcrumbComponent } from './demo-breadcrumb.component'; +import { NoopTranslateModule } from '@alfresco/adf-core'; + +const meta: Meta = { + title: 'Core/Breadcrumb', + component: DemoBreadcrumbComponent, + decorators: [ + moduleMetadata({ + imports: [BreadcrumbComponent, BreadcrumbItemComponent, MatButtonModule, MatMenuModule, MatIconModule, NoopTranslateModule] + }) + ], + args: { + compact: false, + showBreadcrumbItemWithMenu: false + }, + argTypes: { + compact: { control: 'boolean' }, + showBreadcrumbItemWithMenu: { control: 'boolean' } + } +}; +export default meta; +type Story = StoryObj; + +export const Breadcrumb: Story = { + render: (args) => ({ + props: args + }) +}; + +export const Compact: Story = { + render: (args) => ({ + props: args + }), + args: { + compact: true + } +}; + +export const WithMenu: Story = { + render: (args) => ({ + props: args + }), + args: { + showBreadcrumbItemWithMenu: true + } +}; diff --git a/lib/core/breadcrumbs/src/_stories/demo-breadcrumb.component.ts b/lib/core/breadcrumbs/src/_stories/demo-breadcrumb.component.ts new file mode 100644 index 0000000000..5095d4cd77 --- /dev/null +++ b/lib/core/breadcrumbs/src/_stories/demo-breadcrumb.component.ts @@ -0,0 +1,71 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatIconModule } from '@angular/material/icon'; +import { BreadcrumbItemComponent } from '../components/breadcrumb-item/breadcrumb-item.component'; +import { BreadcrumbComponent } from '../components/breadcrumb/breadcrumb.component'; +import { NgIf } from '@angular/common'; + +@Component({ + selector: 'adf-demo-breadcrumb', + template: ` + + + Home + + + + Alfresco + + + + External Link 1 + + + + External Link 2 + + + + External Link 3 + + + +
+ Current Page + + + + + + +
+
+
+ `, + standalone: true, + imports: [MatButtonModule, MatMenuModule, MatIconModule, BreadcrumbItemComponent, BreadcrumbComponent, NgIf] +}) +export class DemoBreadcrumbComponent { + compact = false; + showBreadcrumbItemWithMenu = false; +} diff --git a/lib/core/src/lib/about/about.component.stories.ts b/lib/core/src/lib/about/about.component.stories.ts new file mode 100644 index 0000000000..abcade3322 --- /dev/null +++ b/lib/core/src/lib/about/about.component.stories.ts @@ -0,0 +1,114 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { AboutComponent } from './about.component'; +import { AuthenticationService } from '../auth/services/authentication.service'; +import { AuthenticationMock } from '../auth/mock/authentication.service.mock'; +import { AppExtensionService, ExtensionRef, ViewerExtensionRef } from '@alfresco/adf-extensions'; +import { AppConfigService } from '../app-config/app-config.service'; +import { AppConfigServiceMock } from '../common/mock/app-config.service.mock'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class AppExtensionServiceMock { + references$: Observable; + private _references = new BehaviorSubject([]); + + constructor() { + this.references$ = this._references.asObservable(); + } + + getViewerExtensions(): ViewerExtensionRef[] { + return []; + } +} + +type AboutStoryArgs = AboutComponent & { + dev?: boolean; + pkg?: any; + regexp?: string; +}; + +const meta: Meta = { + component: AboutComponent, + title: 'Core/About/About', + decorators: [ + moduleMetadata({ + imports: [AboutComponent], + providers: [ + { provide: AuthenticationService, useClass: AuthenticationMock }, + { provide: AppExtensionService, useClass: AppExtensionServiceMock }, + { provide: AppConfigService, useClass: AppConfigServiceMock } + ] + }) + ], + argTypes: { + dev: { + control: 'boolean', + description: 'If active show more information about the app and the platform useful in debug.', + defaultValue: false, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + pkg: { + control: 'object', + description: 'pkg json.', + table: { + type: { summary: 'object' } + } + }, + regexp: { + control: 'text', + description: 'Regular expression for filtering dependencies packages.', + defaultValue: '^(@alfresco)', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '^(@alfresco)' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const About: Story = { + render: (args) => ({ + props: args + }), + args: { + pkg: { + name: 'My Storybook App', + commit: 'my-commit-value', + version: '1.0.0', + dependencies: { + '@alfresco/adf-content-services': '4.7.0', + '@alfresco/adf-core': '4.7.0', + '@alfresco/adf-extensions': '4.7.0', + '@alfresco/adf-process-services': '4.7.0', + '@alfresco/adf-process-services-cloud': '4.7.0', + '@alfresco/js-api': '4.7.0-3976' + } + } + } +}; diff --git a/lib/core/src/lib/auth/mock/authentication.service.mock.ts b/lib/core/src/lib/auth/mock/authentication.service.mock.ts new file mode 100644 index 0000000000..ca8dc239f0 --- /dev/null +++ b/lib/core/src/lib/auth/mock/authentication.service.mock.ts @@ -0,0 +1,57 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Observable, of, throwError } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { AuthenticationService } from '../services/authentication.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthenticationMock extends AuthenticationService { + login(username: string, password: string): Observable<{ type: string; ticket: any }> { + if (username === 'fake-username' && password === 'fake-password') { + return of({ type: 'type', ticket: 'ticket' }); + } + + if (username === 'fake-username-CORS-error' && password === 'fake-password') { + return throwError(() => ({ + error: { + crossDomain: true, + message: 'ERROR: the network is offline, Origin is not allowed by Access-Control-Allow-Origin' + } + })); + } + + if (username === 'fake-username-CSRF-error' && password === 'fake-password') { + return throwError(() => ({ message: 'ERROR: Invalid CSRF-token', status: 403 })); + } + + if (username === 'fake-username-ECM-access-error' && password === 'fake-password') { + return throwError(() => ({ + message: 'ERROR: 00170728 Access Denied. The system is currently in read-only mode', + status: 403 + })); + } + + return throwError(() => 'Fake server error'); + } + + logout(): Observable { + return of({}); + } +} diff --git a/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.stories.ts new file mode 100644 index 0000000000..f68c2e2ed7 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.stories.ts @@ -0,0 +1,61 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewArrayItemComponent } from './card-view-arrayitem.component'; +import { CardViewArrayItemModel } from '../../public-api'; +import { of } from 'rxjs'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewArrayItemComponent, + title: 'Core/Card View/Card View Array Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + property: { + description: 'Card View Item Model with data', + table: { + type: { summary: 'CardViewArrayItemModel' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const CardViewArrayItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewArrayItemModel({ + label: 'CardView Array of items', + value: of([ + { icon: 'directions_bike', value: 'Zlatan' }, + { icon: 'directions_bike', value: 'Lionel Messi' }, + { value: 'Mohamed', directions_bike: 'save' }, + { value: 'Ronaldo' } + ]), + key: 'array', + icon: 'edit', + default: 'Empty', + noOfItemsToDisplay: 2 + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.stories.ts new file mode 100644 index 0000000000..2b0f9d4dd4 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-boolitem/card-view-boolitem.component.stories.ts @@ -0,0 +1,54 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewBoolItemComponent } from './card-view-boolitem.component'; +import { CardViewBoolItemModel } from '../../public-api'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewBoolItemComponent, + title: 'Core/Card View/Card View Bool Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + property: { + description: 'Card View Item Model with data', + table: { + type: { summary: 'CardViewBoolItemModel' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const CardViewBoolItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewBoolItemModel({ + label: 'Agree to all terms and conditions', + value: true, + key: 'boolean', + default: false, + editable: true + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.stories.ts new file mode 100644 index 0000000000..4984359370 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.stories.ts @@ -0,0 +1,107 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewDateItemComponent } from './card-view-dateitem.component'; +import { CardViewDateItemModel, CardViewDatetimeItemModel } from '../../public-api'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewDateItemComponent, + title: 'Core/Card View/Card View Date Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + property: { + description: 'Card View Item Model with data', + table: { + type: { + summary: 'CardViewDateItemModel | CardViewDatetimeItemModel' + } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const SingleValuedDateItemCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewDateItemModel({ + label: 'CardView Date Item', + value: [new Date(1983, 11, 24, 10, 0, 30)], + key: 'date', + default: new Date(1983, 11, 24, 10, 0, 30), + format: 'shortDate', + editable: true + }) + } +}; + +export const MultiValuedDateItemCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewDateItemModel({ + label: 'CardView Date Item - Multivalue (chips)', + value: [new Date(1983, 11, 24, 10, 0, 30)], + key: 'date', + default: new Date(1983, 11, 24, 10, 0, 30), + format: 'shortDate', + editable: true, + multivalued: true + }) + } +}; + +export const SingleValuedDatetimeItemCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewDatetimeItemModel({ + label: 'CardView Datetime Item', + value: undefined, + key: 'datetime', + default: undefined, + format: 'short', + editable: true + }) + } +}; + +export const MultiValuedDatetimeItemCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewDatetimeItemModel({ + label: 'CardView Datetime Item - Multivalue (chips)', + value: undefined, + key: 'datetime', + default: undefined, + format: 'short', + editable: true, + multivalued: true + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.stories.ts new file mode 100644 index 0000000000..6cd65307b5 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.stories.ts @@ -0,0 +1,56 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewKeyValuePairsItemComponent } from './card-view-keyvaluepairsitem.component'; +import { CardViewKeyValuePairsItemModel } from '../../public-api'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewKeyValuePairsItemComponent, + title: 'Core/Card View/Card View Key Value Pairs Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + property: { + description: 'Card View Item Model with data', + table: { + type: { summary: 'CardViewKeyValuePairsItemModel' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const CardViewKeyValuePairsItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewKeyValuePairsItemModel({ + label: 'CardView Key-Value Pairs Item', + value: [ + { name: 'hey', value: 'you' }, + { name: 'hey', value: 'you' } + ], + key: 'key-value-pairs', + editable: true + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.stories.ts new file mode 100644 index 0000000000..b0d8c57785 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.stories.ts @@ -0,0 +1,67 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewMapItemComponent } from './card-view-mapitem.component'; +import { CardViewMapItemModel } from '../../public-api'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewMapItemComponent, + title: 'Core/Card View/Card View Map Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + property: { + description: 'Card View Item Model with data', + table: { + type: { summary: 'CardViewMapItemModel' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const CardViewMapItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewMapItemModel({ + label: 'My map', + value: new Map([['999', 'My Value']]), + key: 'map', + default: 'default map value' + }) + } +}; + +export const EmptyCardViewMapItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewMapItemModel({ + label: 'My map', + value: [], + key: 'map', + default: 'default map value' + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.stories.ts new file mode 100644 index 0000000000..86e2a78b80 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.stories.ts @@ -0,0 +1,71 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewSelectItemComponent } from './card-view-selectitem.component'; +import { CardViewSelectItemModel } from '../../public-api'; +import { of } from 'rxjs'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewSelectItemComponent, + title: 'Core/Card View/Card View Select Item', + argTypes: { + ...cardViewSharedMeta.argTypes, + options$: { + control: { disable: true }, + description: 'Data displayed in select element', + table: { + type: { + summary: 'Observable[]>' + } + } + }, + property: { + description: 'Card View Item Model with data', + table: { + type: { summary: 'CardViewSelectItemModel' } + } + } + }, + args: { + ...cardViewSharedMeta.args, + editable: false + } +}; + +export default meta; +type Story = StoryObj; + +export const CardViewSelectItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewSelectItemModel({ + label: 'CardView Select Item', + value: 'one', + options$: of([ + { key: 'one', label: 'One' }, + { key: 'two', label: 'Two' } + ]), + key: 'select', + editable: true + }) + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.stories.ts b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.stories.ts new file mode 100644 index 0000000000..85820f5c50 --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.stories.ts @@ -0,0 +1,128 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewTextItemComponent } from './card-view-textitem.component'; +import { CardViewTextItemModel } from '../../public-api'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewTextItemComponent, + title: 'Core/Card View/Card View Text Item', + argTypes: { + ...cardViewSharedMeta.argTypes + }, + args: { + ...cardViewSharedMeta.args, + editable: false + } +}; + +export default meta; +type Story = StoryObj; + +export const ClickableCardViewTextItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewTextItemModel({ + label: 'CardView Text Item - Clickable template', + value: 'click here', + key: 'click', + default: 'click here', + editable: true, + clickable: true, + icon: 'close' + }) + } +}; + +export const ChipsCardViewTextItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewTextItemModel({ + label: 'CardView Text Item - Chips template', + value: [1, 2, 3, 4], + key: 'name', + default: 'default bar', + multiline: true, + multivalued: true, + icon: 'icon', + editable: true + }), + displayLabelForChips: false + } +}; + +export const EmptyCardViewTextItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewTextItemModel({ + label: 'CardView Text Item - Empty template', + value: undefined, + key: 'empty', + default: '', + icon: 'icon', + editable: false + }), + editable: false, + displayEmpty: false + } +}; + +export const DefaultCardViewTextItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewTextItemModel({ + label: 'CardView Text Item - Default template', + value: 'input here', + key: 'default', + default: 'input here', + editable: true, + clickable: false, + icon: 'close', + multiline: false + }) + } +}; + +export const DisplayLabelForChipsCardTextItem: Story = { + render: (args) => ({ + props: args + }), + args: { + property: new CardViewTextItemModel({ + label: 'CardView Text Item - Multi-Valued Chips template', + value: ['Chip 1', 'Chip 2', 'Chip 3'], + key: 'multivalued', + default: 'default value', + multiline: true, + multivalued: true, + icon: 'icon', + editable: true + }), + displayLabelForChips: false + } +}; diff --git a/lib/core/src/lib/card-view/components/card-view/card-view.component.stories.ts b/lib/core/src/lib/card-view/components/card-view/card-view.component.stories.ts new file mode 100644 index 0000000000..c3bbc56dbc --- /dev/null +++ b/lib/core/src/lib/card-view/components/card-view/card-view.component.stories.ts @@ -0,0 +1,59 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj } from '@storybook/angular'; +import { CardViewComponent } from './card-view.component'; +import { cardViewDataSource, cardViewUndefinedValues } from '../../mock/card-view-content.mock'; +import { cardViewSharedMeta } from '../../stories/card-view-shared-meta'; + +const meta: Meta = { + ...cardViewSharedMeta, + component: CardViewComponent, + title: 'Core/Card View/Card View', + argTypes: { + ...cardViewSharedMeta.argTypes, + editable: { + ...cardViewSharedMeta.argTypes.editable, + table: { + ...cardViewSharedMeta.argTypes.editable.table, + defaultValue: { summary: 'true' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + properties: cardViewDataSource + } +}; + +export const EmptyCardView: Story = { + render: (args) => ({ + props: args + }), + args: { + properties: cardViewUndefinedValues, + editable: false + } +}; diff --git a/lib/core/src/lib/card-view/mock/card-view-content.mock.ts b/lib/core/src/lib/card-view/mock/card-view-content.mock.ts new file mode 100644 index 0000000000..9a26d4607c --- /dev/null +++ b/lib/core/src/lib/card-view/mock/card-view-content.mock.ts @@ -0,0 +1,185 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + CardViewArrayItemModel, + CardViewBoolItemModel, + CardViewDateItemModel, + CardViewDatetimeItemModel, + CardViewIntItemModel, + CardViewKeyValuePairsItemModel, + CardViewMapItemModel, + CardViewSelectItemModel, + CardViewTextItemModel +} from '../public-api'; +import { of } from 'rxjs'; + +export const cardViewDataSource = [ + new CardViewTextItemModel({ + label: 'CardView Text Item - Multivalue (chips)', + value: [1, 2, 3, 4], + key: 'name', + default: 'default bar', + multiline: true, + multivalued: true, + icon: 'icon', + editable: true + }), + new CardViewDateItemModel({ + label: 'CardView Date Item - Multivalue (chips)', + value: [new Date(1983, 11, 24, 10, 0, 30)], + key: 'date', + default: new Date(1983, 11, 24, 10, 0, 30), + format: 'shortDate', + editable: true, + multivalued: true + }), + new CardViewDatetimeItemModel({ + label: 'CardView Datetime Item - Multivalue (chips)', + value: [new Date(1983, 11, 24, 10, 0, 0)], + key: 'datetime', + default: new Date(1983, 11, 24, 10, 0, 0), + format: 'short', + editable: true, + multivalued: true + }), + new CardViewBoolItemModel({ + label: 'Agree to all terms and conditions', + value: true, + key: 'boolean', + default: false, + editable: true + }), + new CardViewIntItemModel({ + label: 'CardView Int Item', + value: 213, + key: 'int', + default: 1, + editable: true + }), + new CardViewKeyValuePairsItemModel({ + label: 'CardView Key-Value Pairs Item', + value: [ + { name: 'hey', value: 'you' }, + { name: 'hey', value: 'you' } + ], + key: 'key-value-pairs', + editable: true + }), + new CardViewSelectItemModel({ + label: 'CardView Select Item', + value: 'one', + options$: of([ + { key: 'one', label: 'One' }, + { key: 'two', label: 'Two' } + ]), + key: 'select', + editable: true + }), + new CardViewMapItemModel({ + label: 'My map', + value: new Map([['999', 'My Value']]), + key: 'map', + default: 'default map value' + }), + new CardViewTextItemModel({ + label: 'This is clickable ', + value: 'click here', + key: 'click', + default: 'click here', + editable: true, + clickable: true, + icon: 'close' + }), + new CardViewArrayItemModel({ + label: 'CardView Array of items', + value: of([ + { icon: 'directions_bike', value: 'Zlatan' }, + { icon: 'directions_bike', value: 'Lionel Messi' }, + { value: 'Mohamed', directions_bike: 'save' }, + { value: 'Ronaldo' } + ]), + key: 'array', + icon: 'edit', + default: 'Empty', + noOfItemsToDisplay: 2, + editable: true + }) +]; + +export const cardViewUndefinedValues = [ + new CardViewTextItemModel({ + label: 'CardView Text Item - Multivalue (chips)', + value: undefined, + key: 'name', + default: undefined, + multiline: true, + multivalued: true, + icon: 'icon', + editable: true + }), + new CardViewDateItemModel({ + label: 'CardView Date Item - Multivalue (chips)', + value: undefined, + key: 'date', + default: undefined, + format: 'shortDate', + editable: true, + multivalued: true + }), + new CardViewDatetimeItemModel({ + label: 'CardView Datetime Item - Multivalue (chips)', + value: undefined, + key: 'datetime', + default: undefined, + format: 'short', + editable: true, + multivalued: true + }), + new CardViewIntItemModel({ + label: 'CardView Int Item', + value: undefined, + key: 'int', + default: undefined, + editable: true + }), + new CardViewSelectItemModel({ + label: 'CardView Select Item', + value: undefined, + options$: of([ + { key: 'one', label: 'One' }, + { key: 'two', label: 'Two' } + ]), + key: 'select', + editable: true + }), + new CardViewMapItemModel({ + label: 'My map', + value: undefined, + key: 'map', + default: undefined + }), + new CardViewTextItemModel({ + label: 'This is clickable ', + value: undefined, + key: 'click', + default: undefined, + editable: true, + clickable: true, + icon: 'close' + }) +]; diff --git a/lib/core/src/lib/card-view/stories/card-view-shared-meta.ts b/lib/core/src/lib/card-view/stories/card-view-shared-meta.ts new file mode 100644 index 0000000000..d2052e34d6 --- /dev/null +++ b/lib/core/src/lib/card-view/stories/card-view-shared-meta.ts @@ -0,0 +1,132 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, moduleMetadata, Decorator, type ArgTypes } from '@storybook/angular'; +import { CARD_VIEW_DIRECTIVES } from '../public-api'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +/** + * Common decorators used across all Card View component stories. + * Includes module metadata with Card View directives and application config with core providers. + */ +export const cardViewDecorators: Decorator[] = [ + moduleMetadata({ + imports: [...CARD_VIEW_DIRECTIVES] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) +]; + +/** + * Common argTypes definitions shared across Card View component stories. + * These can be spread into component-specific meta configurations. + */ +export const cardViewArgTypes: ArgTypes = { + editable: { + control: 'boolean', + description: 'Defines if CardView item is editable', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + displayEmpty: { + control: 'boolean', + description: 'Defines if it should display CardView item when data is empty', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + displayNoneOption: { + control: 'boolean', + description: 'Shows None option inside select element', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + displayClearAction: { + control: 'boolean', + description: 'Defines if it should display clear input action (only with SingleValued components)', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + copyToClipboardAction: { + control: 'boolean', + description: 'Copy to clipboard action - default template in editable mode', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + useChipsForMultiValueProperty: { + control: 'boolean', + description: 'Split text for chips using defined separator', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + multiValueSeparator: { + control: 'text', + description: 'Separator used for text splitting', + table: { + type: { summary: 'string' }, + defaultValue: { summary: ', ' } + } + }, + displayLabelForChips: { + control: 'boolean', + description: 'Display label for chips property', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + } +}; + +/** + * Common default args shared across Card View component stories. + */ +export const cardViewDefaultArgs: Record = { + editable: true, + displayEmpty: true, + displayNoneOption: true, + displayClearAction: true, + copyToClipboardAction: true, + useChipsForMultiValueProperty: true, + multiValueSeparator: ', ', + displayLabelForChips: false +}; + +/** + * Shared metadata object that can be spread into component-specific meta configurations. + * Contains decorators, argTypes, and args commonly used across Card View stories. + */ +export const cardViewSharedMeta: { + decorators: Decorator[]; + argTypes: ArgTypes; + args: Record; +} = { + decorators: cardViewDecorators, + argTypes: cardViewArgTypes, + args: cardViewDefaultArgs +}; diff --git a/lib/core/src/lib/comments/comment-list/comment-list.component.stories.ts b/lib/core/src/lib/comments/comment-list/comment-list.component.stories.ts new file mode 100644 index 0000000000..7ffd7f8064 --- /dev/null +++ b/lib/core/src/lib/comments/comment-list/comment-list.component.stories.ts @@ -0,0 +1,82 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { CommentListComponent } from './comment-list.component'; +import { commentsTaskData, commentsNodeData } from '../mocks/comments.stories.mock'; +import { CommentsServiceStoriesMock } from '../mocks/comments.service.stories.mock'; +import { ADF_COMMENTS_SERVICE } from '../interfaces/comments.token'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +const meta: Meta = { + component: CommentListComponent, + title: 'Core/Comments/Comment List', + decorators: [ + moduleMetadata({ + imports: [CommentListComponent], + providers: [{ provide: ADF_COMMENTS_SERVICE, useClass: CommentsServiceStoriesMock }] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: 'Displays a list of comments from users involved in a specified task or node' + } + } + }, + argTypes: { + comments: { + control: 'object', + description: 'CommentModel array', + table: { + type: { summary: 'CommentModel[]' } + } + }, + clickRow: { + action: 'clickRow', + description: 'Emitted when the user clicks on one of the comment rows', + table: { + category: 'Actions', + type: { summary: 'EventEmitter ' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const TaskBased: Story = { + render: (args) => ({ + props: args + }), + args: { + comments: commentsTaskData + } +}; + +export const NodeBased: Story = { + render: (args) => ({ + props: args + }), + args: { + comments: commentsNodeData + } +}; diff --git a/lib/core/src/lib/comments/comments.component.stories.ts b/lib/core/src/lib/comments/comments.component.stories.ts new file mode 100644 index 0000000000..dbfcd37c0f --- /dev/null +++ b/lib/core/src/lib/comments/comments.component.stories.ts @@ -0,0 +1,122 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { CommentsComponent } from './comments.component'; +import { ADF_COMMENTS_SERVICE } from './interfaces/comments.token'; +import { commentsStoriesData } from './mocks/comments.stories.mock'; +import { CommentsServiceStoriesMock } from './mocks/comments.service.stories.mock'; +import { provideStoryCore } from '../stories/core-story.providers'; + +const meta: Meta = { + component: CommentsComponent, + title: 'Core/Comments/Comment', + decorators: [ + moduleMetadata({ + imports: [CommentsComponent], + providers: [ + { provide: CommentsServiceStoriesMock, useValue: { getUserProfileImage: () => '../assets/images/logo.png' } }, + { provide: ADF_COMMENTS_SERVICE, useClass: CommentsServiceStoriesMock } + ] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays comments from users involved in a specified environment. + Allows an involved user to add a comment to a environment.` + } + } + }, + argTypes: { + comments: { + control: 'object', + description: 'CommentModel array', + table: { type: { summary: 'CommentModel[]' } } + }, + readOnly: { + control: 'boolean', + description: 'Displays input area to add new comment', + defaultValue: false, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + id: { + control: 'text', + description: 'Necessary in order to add a new comment', + table: { + type: { summary: 'string' } + } + }, + error: { + action: 'error', + description: 'Emitted when an error occurs while displaying/adding a comment', + table: { + category: 'Actions', + type: { summary: 'EventEmitter ' } + } + } + }, + args: { + comments: commentsStoriesData, + id: '-fake-' + } +}; + +export default meta; +type Story = StoryObj; + +export const SingleCommentWithAvatar: Story = { + render: (args) => ({ + props: args + }), + args: { + comments: [commentsStoriesData[0]], + readOnly: true + } +}; + +export const SingleCommentWithoutAvatar: Story = { + render: (args) => ({ + props: args + }), + args: { + comments: [commentsStoriesData[1]], + readOnly: true + } +}; + +export const NoComments: Story = { + render: (args) => ({ + props: args + }), + args: { + comments: [], + readOnly: true + } +}; + +export const Comments: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/core/src/lib/comments/mocks/comments.service.stories.mock.ts b/lib/core/src/lib/comments/mocks/comments.service.stories.mock.ts new file mode 100644 index 0000000000..c12488d6c0 --- /dev/null +++ b/lib/core/src/lib/comments/mocks/comments.service.stories.mock.ts @@ -0,0 +1,79 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommentModel, User } from '../../models'; +import { Observable, of } from 'rxjs'; +import { CommentsService } from '../interfaces/comments-service.interface'; +import { testUser } from './comments.stories.mock'; + +export class CommentsServiceStoriesMock implements Partial { + get(_id: string): Observable { + return commentsResponseMock.getComments(); + } + add(_id: string, message = 'test comment'): Observable { + return commentsResponseMock.addComment(message); + } + + getUserImage(_userId: string): string { + return '../assets/images/logo.png'; + } +} + +const commentUser = new User({ + enabled: true, + firstName: 'hruser', + displayName: 'hruser', + id: 'hruser', + email: 'test' +}); + +export const commentsResponseMock = { + getComments: () => + of([ + new CommentModel({ + id: 1, + message: 'Test Comment', + created: new Date(), + createdBy: commentUser, + isSelected: false + }), + new CommentModel({ + id: 2, + message: 'Test Comment', + created: new Date(), + createdBy: commentUser, + isSelected: false + }), + new CommentModel({ + id: 3, + message: 'Test Comment', + created: new Date(), + createdBy: commentUser, + isSelected: false + }) + ]), + addComment: (message: string) => + of( + new CommentModel({ + id: 1, + message, + created: new Date(), + createdBy: testUser, + isSelected: false + }) + ) +}; diff --git a/lib/core/src/lib/comments/mocks/comments.stories.mock.ts b/lib/core/src/lib/comments/mocks/comments.stories.mock.ts new file mode 100644 index 0000000000..db790ed4ab --- /dev/null +++ b/lib/core/src/lib/comments/mocks/comments.stories.mock.ts @@ -0,0 +1,166 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommentModel } from '../../models'; + +const fakeCompany: any = { + organization: '', + address1: '', + address2: '', + address3: '', + postcode: '', + telephone: '', + fax: '', + email: '' +}; + +export const getDateXMinutesAgo = (minutes: number) => new Date(Date.now() - minutes * 60000); + +const johnDoe: any = { + id: '1', + email: 'john.doe@alfresco.com', + firstName: 'John', + lastName: 'Doe', + company: fakeCompany, + enabled: true, + isAdmin: undefined, + avatarId: '001' +}; + +const janeEod: any = { + id: '2', + email: 'jane.eod@alfresco.com', + firstName: 'Jane', + lastName: 'Eod', + company: fakeCompany, + enabled: true, + isAdmin: undefined +}; + +const robertSmith: any = { + id: '3', + email: 'robert.smith@alfresco.com', + firstName: 'Robert', + lastName: 'Smith', + company: fakeCompany, + enabled: true, + isAdmin: undefined +}; + +export const testUser: any = { + id: '44', + email: 'test.user@hyland.com', + firstName: 'Test', + lastName: 'User', + company: fakeCompany, + enabled: true, + isAdmin: undefined, + avatarId: '044' +}; + +export const commentsStoriesData: CommentModel[] = [ + new CommentModel({ + id: 1, + message: `I've done this task, what's next?`, + created: getDateXMinutesAgo(30), + createdBy: johnDoe, + isSelected: false + }), + new CommentModel({ + id: 2, + message: `I've assigned you another one 🤠`, + created: getDateXMinutesAgo(15), + createdBy: janeEod, + isSelected: false + }), + new CommentModel({ + id: 3, + message: '+1', + created: getDateXMinutesAgo(12), + createdBy: robertSmith, + isSelected: false + }), + new CommentModel({ + id: 4, + message: 'Cheers', + created: new Date(), + createdBy: johnDoe, + isSelected: false + }) +]; + +export const commentsNodeData: CommentModel[] = [ + new CommentModel({ + id: 1, + message: `I've done this component, is it cool?`, + created: getDateXMinutesAgo(30), + createdBy: johnDoe, + isSelected: false + }), + new CommentModel({ + id: 2, + message: 'Yeah', + created: getDateXMinutesAgo(15), + createdBy: janeEod, + isSelected: false + }), + new CommentModel({ + id: 3, + message: '+1', + created: getDateXMinutesAgo(12), + createdBy: robertSmith, + isSelected: false + }), + new CommentModel({ + id: 4, + message: 'ty', + created: new Date(), + createdBy: johnDoe, + isSelected: false + }) +]; + +export const commentsTaskData: CommentModel[] = [ + new CommentModel({ + id: 1, + message: `I've done this task, what's next?`, + created: getDateXMinutesAgo(30), + createdBy: johnDoe, + isSelected: false + }), + new CommentModel({ + id: 2, + message: `I've assigned you another one 🤠`, + created: getDateXMinutesAgo(15), + createdBy: janeEod, + isSelected: false + }), + new CommentModel({ + id: 3, + message: '+1', + created: getDateXMinutesAgo(12), + createdBy: robertSmith, + isSelected: false + }), + new CommentModel({ + id: 4, + message: 'Cheers', + created: new Date(), + createdBy: johnDoe, + isSelected: false + }) +]; diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.stories.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.stories.ts new file mode 100644 index 0000000000..0c803c6e14 --- /dev/null +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.stories.ts @@ -0,0 +1,514 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { DataTableComponent, ShowHeaderMode } from './datatable.component'; +import { ColumnsSelectorComponent } from '../columns-selector/columns-selector.component'; +import { EmptyListBodyDirective, EmptyListComponent, EmptyListFooterDirective, EmptyListHeaderDirective } from '../empty-list/empty-list.component'; +import { LoadingContentTemplateDirective } from '../../directives/loading-template.directive'; +import { NoContentTemplateDirective } from '../../directives/no-content-template.directive'; +import { NoPermissionTemplateDirective } from '../../directives/no-permission-template.directive'; +import { MainMenuDataTableTemplateDirective } from '../../directives/main-data-table-action-template.directive'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { mockPathInfos } from '../mocks/datatable.mock'; +import { provideStoryCore } from '../../../stories/core-story.providers'; + +const meta: Meta = { + component: DataTableComponent, + title: 'Core/Datatable/Datatable', + decorators: [ + moduleMetadata({ + imports: [ + ColumnsSelectorComponent, + EmptyListComponent, + EmptyListHeaderDirective, + EmptyListBodyDirective, + EmptyListFooterDirective, + NoContentTemplateDirective, + NoPermissionTemplateDirective, + LoadingContentTemplateDirective, + MainMenuDataTableTemplateDirective, + DataTableComponent, + MatProgressSpinnerModule + ] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + data: { + control: 'object', + description: 'Data source for the table', + table: { + category: 'Data', + type: { summary: 'DataTableAdapter' } + } + }, + rows: { + control: 'object', + description: 'The rows that the datatable will show.', + table: { + category: 'Data', + type: { summary: 'any[]' }, + defaultValue: { summary: '[]' } + } + }, + sorting: { + control: 'object', + description: 'A string array.\n\n' + 'First element describes the key to sort by.\n\n' + 'Second element describes the sorting order.', + table: { + type: { summary: 'any[]' }, + defaultValue: { summary: '[]' } + } + }, + columns: { + control: 'object', + description: 'The columns that the datatable will show.', + table: { + category: 'Data', + type: { summary: 'any[]' }, + defaultValue: { summary: '[]' } + } + }, + selectionMode: { + control: 'inline-radio', + description: 'Row selection mode.', + options: ['none', 'single', 'multiple'], + table: { + category: 'Selection', + type: { summary: 'string' }, + defaultValue: { summary: 'single' } + } + }, + multiselect: { + control: 'boolean', + description: 'Toggles multiple row selection, which renders checkboxes at the beginning of each row.', + table: { + category: 'Selection', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + mainTableAction: { + control: 'boolean', + description: 'Toggles main data table action column.', + table: { + category: 'Data Actions Column', + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + actions: { + control: 'boolean', + description: 'Toggles the data actions column.', + table: { + category: 'Data Actions Column', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + showMainDatatableActions: { + control: 'boolean', + description: 'Toggles the main datatable action.', + table: { + category: 'Data Actions Column', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + actionsPosition: { + control: 'inline-radio', + description: 'Position of the actions dropdown menu.', + options: ['right', 'left'], + table: { + category: 'Data Actions Column', + type: { summary: 'string' }, + defaultValue: { summary: 'right' } + } + }, + actionsVisibleOnHover: { + control: 'boolean', + description: 'Toggles whether the actions dropdown should only be visible if the row is hovered over or the dropdown menu is open.', + table: { + category: 'Data Actions Column', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + fallbackThumbnail: { + control: 'text', + description: 'Fallback image for rows where the thumbnail is missing.', + table: { + type: { summary: 'string' } + } + }, + contextMenu: { + control: 'boolean', + description: 'Toggles custom context menu for the component.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + rowStyle: { + control: 'object', + description: + 'The inline style to apply to every row. See [NgStyle](https://angular.io/docs/ts/latest/api/common/index/NgStyle-directive.html) docs for more details and usage examples.', + table: { + category: 'Custom Row Styles', + type: { summary: '{ [key: string]: any }' } + } + }, + rowStyleClass: { + control: 'text', + description: 'The CSS class to apply to every row.', + table: { + category: 'Custom Row Styles', + type: { summary: 'string' }, + defaultValue: { summary: '' } + } + }, + showHeader: { + control: 'inline-radio', + description: 'Toggles the header visibility mode.', + options: ['never', 'always', 'data'], + table: { + category: 'Header', + type: { summary: 'string' }, + defaultValue: { summary: 'data' } + } + }, + stickyHeader: { + control: 'boolean', + description: 'Toggles the sticky header mode.', + table: { + category: 'Header', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + loading: { + control: 'boolean', + table: { + category: 'Table Template', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + noPermission: { + control: 'boolean', + table: { + category: 'Table Template', + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + rowMenuCacheEnabled: { + control: 'boolean', + description: 'Should the items for the row actions menu be cached for reuse after they are loaded the first time?', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + allowFiltering: { + control: 'boolean', + description: 'Flag that indicate if the datatable allow the use facet widget search for filtering.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + rowClick: { + action: 'rowClick', + description: 'Emitted when the user clicks a row.', + table: { category: 'Actions' } + }, + rowDblClick: { + action: 'rowDblClick', + description: 'Emitted when the user double-clicks a row.', + table: { category: 'Actions' } + }, + /* commented until [AAE-10239] fixed + showRowContextMenu: { + action: 'showRowContextMenu', + description: 'Emitted before the context menu is displayed for a row.', + table: { category: 'Actions' } + }, + showRowActionsMenu: { + action: 'showRowActionsMenu', + description: 'Emitted before the actions menu is displayed for a row.', + table: { category: 'Actions' } + }, + */ + executeRowAction: { + action: 'executeRowAction', + description: 'Emitted when the user executes a row action.', + table: { category: 'Actions' } + }, + columnOrderChanged: { + action: 'columnOrderChanged', + description: 'Emitted when the order of columns changed.', + table: { category: 'Actions' } + } + }, + args: { + rows: [ + { + id: 1, + textCol: 'This is a very long text inside the text column to check if the hidden text will be displayed on hover.', + imageCol: 'material-icons://folder_open', + iconCol: 'folder_open', + dateCol: new Date(), + fileSizeCol: '536870912', + locationCol: mockPathInfos[0], + booleanCol: true, + amountCol: 100.55, + numberCol: 10000.31, + jsonCol: mockPathInfos[0] + }, + { + id: 2, + textCol: 'Text 2', + imageCol: 'material-icons://cloud_outline', + iconCol: 'cloud_outline', + dateCol: new Date().setDate(new Date().getDate() - 1), + fileSizeCol: '524288', + locationCol: mockPathInfos[1], + booleanCol: false, + amountCol: 1020.123, + numberCol: 240.3, + jsonCol: mockPathInfos[1] + }, + { + id: 3, + textCol: 'Text 3', + imageCol: 'material-icons://save', + iconCol: 'save', + dateCol: new Date().setDate(new Date().getDate() - 5), + fileSizeCol: '10737418240B', + locationCol: mockPathInfos[1], + booleanCol: 'true', + amountCol: -2020, + numberCol: 120, + jsonCol: mockPathInfos[1] + }, + { + id: 4, + textCol: 'Text 4', + imageCol: 'material-icons://delete', + iconCol: 'delete', + dateCol: new Date().setDate(new Date().getDate() - 6), + fileSizeCol: '512B', + locationCol: mockPathInfos[2], + booleanCol: 'false', + amountCol: 230.76, + numberCol: 3.032, + jsonCol: mockPathInfos[2] + }, + { + id: 5, + textCol: 'Text 5', + imageCol: 'material-icons://person_outline', + iconCol: 'person_outline', + dateCol: new Date().setDate(new Date().getDate() - 7), + fileSizeCol: '1073741824B', + locationCol: mockPathInfos[0], + booleanCol: 'false', + amountCol: 0.444, + numberCol: 2000, + jsonCol: mockPathInfos[0] + } + ], + sorting: ['id', 'asc'], + columns: [ + { type: 'text', key: 'id', title: 'Id', sortable: true }, + { + type: 'text', + key: 'textCol', + title: 'Text Column', + sortable: true, + draggable: true, + cssClass: 'adf-ellipsis-cell', + copyContent: true + }, + { type: 'image', key: 'imageCol', title: 'Image Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'icon', key: 'iconCol', title: 'Icon Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'date', key: 'dateCol', title: 'Date Column', sortable: true, draggable: true, cssClass: 'adf-ellipsis-cell' }, + { + type: 'date', + key: 'dateCol', + title: 'Date Time Ago Column', + sortable: true, + draggable: true, + cssClass: 'adf-ellipsis-cell', + dateConfig: { format: 'timeAgo' } + }, + { type: 'fileSize', key: 'fileSizeCol', title: 'File Size Column', sortable: true, draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'location', format: '/files', key: 'locationCol', title: 'Location Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'boolean', key: 'booleanCol', title: 'Boolean Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'amount', key: 'amountCol', title: 'Amount Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'number', key: 'numberCol', title: 'Number Column', draggable: true, cssClass: 'adf-ellipsis-cell' }, + { type: 'json', key: 'jsonCol', title: 'JSON Column', draggable: true, cssClass: 'adf-ellipsis-cell' } + ], + selectionMode: 'single', + multiselect: false, + mainTableAction: true, + actions: false, + showMainDatatableActions: false, + actionsPosition: 'right', + actionsVisibleOnHover: false, + contextMenu: false, + rowStyleClass: '', + showHeader: ShowHeaderMode.Data, + stickyHeader: false, + loading: false, + noPermission: false, + rowMenuCacheEnabled: false, + allowFiltering: false + } +}; + +export default meta; +type Story = StoryObj; + +const insertContentToTemplate = (content: string): string => + ` + ${content} + `; + +export const DefaultDatatable: Story = { + render: (args) => ({ + props: args, + template: insertContentToTemplate('') + }) +}; + +export const EmptyWithList: Story = { + render: (args) => ({ + props: { + ...args, + rows: [] + }, + template: insertContentToTemplate(` + +
Empty List Header
+
Empty List Body
+
Empty List Footer
+
+ `) + }) +}; + +export const EmptyWithTemplate: Story = { + render: (args) => ({ + props: { + ...args, + rows: [] + }, + template: insertContentToTemplate(` + + Sorry, no content + + `) + }) +}; + +export const LoadingWithTemplate: Story = { + render: (args) => ({ + props: { + ...args, + loading: true + }, + template: insertContentToTemplate(` + + + + + + + `) + }) +}; + +export const NoPermissionWithTemplate: Story = { + render: (args) => ({ + props: { + ...args, + noPermission: true + }, + template: insertContentToTemplate(` + + +
You don't have permission to this content.
+
+
+ `) + }) +}; + +export const MainMenuWithTemplate: Story = { + render: (args) => ({ + props: { + ...args, + mainTableAction: true, + showMainDatatableActions: true + }, + template: insertContentToTemplate(` + + + + + + + `) + }) +}; + +export const StickyHeader: Story = { + render: (args) => ({ + props: { + ...args, + stickyHeader: true + }, + template: '
' + insertContentToTemplate(``) + '
' + }) +}; diff --git a/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts b/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts index 6ea942523d..20e92de0b7 100644 --- a/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts +++ b/lib/core/src/lib/datatable/components/mocks/datatable.mock.ts @@ -15,13 +15,14 @@ * limitations under the License. */ +import { PathInfo } from '../../../models/path.model'; import { DataColumn } from '../../data/data-column.model'; export const mockCarsData: any = [ { car_id: 1, car_name: 'Fiat 126p (Process)', - car_price: 599.0, + car_price: 599, fuel_consumption: 5.25789, is_available: 'false', production_start: '1972-04-23', @@ -131,3 +132,29 @@ export const mockCarsSchemaDefinition: DataColumn[] = [ draggable: true } ]; + +export const mockPathInfos: PathInfo[] = [ + { + elements: [ + { id: '1', name: 'User files', nodeType: 'folder' }, + { id: '2', name: 'Favorite', nodeType: 'folder' }, + { id: '3', name: 'Movies', nodeType: 'folder' } + ], + name: '/User files/Favorite/Movies' + }, + { + elements: [ + { id: '1', name: 'User files', nodeType: 'folder' }, + { id: '4', name: 'Photos', nodeType: 'folder' } + ], + name: '/User files/Photos' + }, + { + elements: [ + { id: '1', name: 'User files', nodeType: 'folder' }, + { id: '2', name: 'Favorite', nodeType: 'folder' }, + { id: '5', name: 'Series', nodeType: 'folder' } + ], + name: '/User files/Favorite/Series' + } +]; diff --git a/lib/core/src/lib/datatable/data-column/data-column.component.stories.ts b/lib/core/src/lib/datatable/data-column/data-column.component.stories.ts new file mode 100644 index 0000000000..ce35fe0b8e --- /dev/null +++ b/lib/core/src/lib/datatable/data-column/data-column.component.stories.ts @@ -0,0 +1,531 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { DataColumnComponent } from './data-column.component'; +import { DataTableComponent } from '../components/datatable/datatable.component'; +import { DataColumnListComponent, DateColumnHeaderComponent } from '../data-column'; +import * as mockData from '../../mock/data-column.mock'; +import { DataRow } from '../index'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +const meta: Meta = { + component: DataColumnComponent, + title: 'Core/Data Column/Data Column', + decorators: [ + moduleMetadata({ + imports: [DataColumnComponent, DataColumnListComponent, DateColumnHeaderComponent, DataTableComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + copyContent: { + description: 'Enables/disables a Clipboard directive to allow copying of cell contents.', + control: { type: 'boolean' }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + } + } + }, + cssClass: { + description: 'Additional CSS class to be applied to column (header and cells).', + control: { type: 'text' }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + } + } + }, + customData: { + description: 'You can specify any custom data which can be used by any specific feature', + control: { disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'any' + } + } + }, + draggable: { + description: 'Toggles drag and drop for header column.', + control: { type: 'boolean' }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'false' + } + } + }, + resizable: { + description: 'Toggles resize for column.', + control: { type: 'boolean' }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'true' + } + } + }, + editable: { + description: 'Toggles the editing support of the column data.', + control: { type: 'boolean', disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'false' + } + } + }, + focus: { + description: 'Enable or disable cell focus', + control: { disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'true' + } + } + }, + format: { + description: 'Used for location type. Setups root path for router navigation.', + control: { type: 'text', disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + } + } + }, + formatTooltip: { + description: 'Custom tooltip formatter function.', + control: { disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'Function' + } + } + }, + id: { + description: 'Column identifier.', + control: { disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + }, + defaultValue: { + summary: '' + } + } + }, + isHidden: { + description: 'Hides columns', + control: { type: 'boolean' }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'false' + } + } + }, + key: { + description: 'Data source key. Can be either a column/property key like title or a property path like `createdBy.name`.', + control: { type: 'text', disable: false }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + } + } + }, + sortable: { + description: 'Toggles ability to sort by this column, for example by clicking the column header.', + control: { type: 'boolean' }, + table: { + category: 'Component Inputs', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'true' + } + } + }, + sortingKey: { + description: 'When using server side sorting the column used by the api call where the sorting will be performed', + control: { disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + } + } + }, + srTitle: { + description: 'Title to be used for screen readers.', + control: { type: 'text' }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + }, + defaultValue: { + summary: '' + } + } + }, + title: { + description: + 'Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically.', + control: { type: 'text' }, + table: { + category: 'Component Inputs', + type: { + summary: 'string' + }, + defaultValue: { + summary: '' + } + } + }, + type: { + description: + 'Value type for the column. Possible settings are: `text`, `icon`, `image`, `date`, `fileSize`, `location`, `boolean`, `amount`, `number` and `json`.', + control: { type: 'select', disable: false }, + options: ['text', 'icon', 'image', 'date', 'fileSize', 'location', 'boolean', 'amount', 'number', 'json'], + table: { + category: 'Component Inputs', + type: { + summary: 'DataColumnType' + }, + defaultValue: { + summary: 'text' + } + } + }, + currencyConfig: { + description: `The currencyConfig input allows you to customize the formatting and display of currency values within the component.`, + control: { type: 'object', disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'CurrencyConfig' + }, + defaultValue: { + summary: `{ code: 'USD', display: 'symbol' }` + } + } + }, + decimalConfig: { + description: `The decimalConfig input allows you to customize the formatting and display of decimal values within the component.`, + control: { type: 'object', disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'DecimalConfig' + }, + defaultValue: { + summary: `{}` + } + } + }, + dateConfig: { + description: `The dateConfig input allows you to configure date formatting and localization for a component.`, + control: { type: 'object', disable: true }, + table: { + category: 'Component Inputs', + type: { + summary: 'DateConfig' + }, + defaultValue: { + summary: `{ format: 'medium', tooltipFormat: 'medium' }` + } + } + }, + rows: { + description: 'Provides rows for DataTable component', + control: { disable: false }, + table: { + category: 'Component data', + type: { + summary: 'array' + } + } + } + }, + args: { + copyContent: false, + cssClass: '', + customData: {}, + draggable: false, + editable: false, + focus: true, + format: '', + formatTooltip: null, + id: '', + isHidden: false, + key: '', + sortable: true, + sortingKey: '', + srTitle: '', + title: '', + type: 'text', + currencyConfig: { + code: 'USD', + display: 'symbol', + digitsInfo: undefined, + locale: undefined + }, + decimalConfig: { + digitsInfo: '2.4-5', + locale: undefined + }, + dateConfig: { + format: 'medium', + tooltipFormat: 'medium', + locale: undefined + } + } +}; + +export default meta; +type Story = StoryObj; + +const formatCustomTooltip = (row: DataRow): string => (row ? 'This is ' + row.getValue('firstname') : null); + +const render = (args: DataColumnComponent & { rows: DataRow[] }) => ({ + props: args, + template: ` + + + + + + + ` +}); + +// Text Column +export const TextColumn: Story = { + render: render, + args: { + rows: mockData.textColumnRows, + key: 'firstname', + type: 'text', + title: 'Text Column' + } +}; + +// Text Column With Custom Tooltip +export const TextColumnWithCustomTooltip: Story = { + render: render, + argTypes: { + formatTooltip: { control: { disable: false } } + }, + args: { + rows: mockData.textColumnRows, + key: 'firstname', + type: 'text', + title: 'Custom Tooltip Column', + formatTooltip: formatCustomTooltip + } +}; + +// Icon Column +export const IconColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.iconColumnRows, + key: 'icon', + type: 'icon', + title: 'Icon Column' + } +}; + +// Image Column +export const ImageColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.imageColumnRows, + key: 'image', + type: 'image', + title: 'Image Column' + } +}; + +// Date Column +export const DateColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } }, + dateConfig: { control: { disable: false } } + }, + args: { + rows: mockData.dateColumnRows, + key: 'createdOn', + type: 'date', + title: 'Date Column' + } +}; + +// Date Column Time Ago +export const DateColumnTimeAgo: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } }, + dateConfig: { control: { disable: false } } + }, + args: { + rows: mockData.dateColumnTimeAgoRows, + key: 'modifiedOn', + type: 'date', + title: 'Date Column Time Ago', + dateConfig: { format: 'timeAgo' } + } +}; + +// File Size Column +export const FileSizeColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.fileSizeColumnRows, + key: 'size', + type: 'fileSize', + title: 'File Size Column' + } +}; + +// Location Column +export const LocationColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } }, + format: { control: { disable: false } }, + sortable: { control: { disable: true } } + }, + args: { + rows: mockData.locationColumnRows, + format: '/files', + key: 'path', + type: 'location', + title: 'Location Column' + } +}; + +// Boolean Column +export const BooleanColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.booleanColumnRows, + key: 'bool', + type: 'boolean', + title: 'Boolean Column' + } +}; + +// Json Column +export const JsonColumn: Story = { + render: render, + argTypes: { + editable: { control: { disable: false } }, + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.jsonColumnRows, + key: 'rowInfo', + type: 'json', + title: 'JSON Column' + } +}; + +// Amount Column +export const AmountColumn: Story = { + render: render, + argTypes: { + copyContent: { control: { disable: true } }, + currencyConfig: { control: { disable: false } } + }, + args: { + rows: mockData.amountColumnRows, + key: 'price', + type: 'amount', + title: 'Amount Column' + } +}; + +// Number Column +export const NumberColumn: Story = { + render: render, + argTypes: { + decimalConfig: { control: { disable: false } }, + copyContent: { control: { disable: true } } + }, + args: { + rows: mockData.amountColumnRows, + key: 'price', + type: 'number', + title: 'Number Column' + } +}; diff --git a/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.component.ts b/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.component.ts new file mode 100644 index 0000000000..329b6d1cc5 --- /dev/null +++ b/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.component.ts @@ -0,0 +1,79 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, inject, OnInit, OnChanges, Input } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { EditJsonDialogComponent, EditJsonDialogSettings } from './edit-json.dialog'; +import { MatButtonModule } from '@angular/material/button'; + +@Component({ + selector: 'adf-edit-json-dialog-storybook', + template: ``, + imports: [MatButtonModule] +}) +export class EditJsonDialogStorybookComponent implements OnInit, OnChanges { + @Input() + title: string; + + @Input() + editable: boolean; + + @Input() + value: string; + + private _settings: EditJsonDialogSettings; + + set settings(newSettings: EditJsonDialogSettings) { + this._settings = { + title: newSettings.title, + editable: newSettings.editable, + value: JSON.stringify(newSettings.value, null, ' ') + }; + } + + private readonly dialog = inject(MatDialog); + + ngOnInit() { + this.assignSettings(); + } + + ngOnChanges() { + this.assignSettings(); + } + + openDialog() { + this.dialog + .open(EditJsonDialogComponent, { + data: this._settings, + minWidth: `50%` + }) + .afterClosed() + .subscribe((value: string) => { + if (value) { + this._settings.value = JSON.stringify(JSON.parse(value), null, ' '); + } + }); + } + + private assignSettings() { + this.settings = { + title: this.title, + editable: this.editable, + value: this.value + }; + } +} diff --git a/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.ts b/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.ts new file mode 100644 index 0000000000..0e23fff451 --- /dev/null +++ b/lib/core/src/lib/dialogs/edit-json/edit-json.dialog.stories.ts @@ -0,0 +1,100 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { EditJsonDialogStorybookComponent } from './edit-json.dialog.stories.component'; +import { MatButtonModule } from '@angular/material/button'; +import { EditJsonDialogComponent } from './edit-json.dialog'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +const jsonData = { + maxValue: 50, + minValue: 10, + values: [10, 15, 14, 27, 35, 23, 49, 38], + measurementId: 'm_10001', + researcherId: 's_10002' +}; + +const meta: Meta = { + component: EditJsonDialogStorybookComponent, + title: 'Core/Dialog/Edit JSON Dialog', + decorators: [ + moduleMetadata({ + imports: [EditJsonDialogComponent, MatButtonModule] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + value: { + description: 'Displayed text', + control: { + type: 'object' + }, + table: { + category: 'Provider settings', + type: { + summary: 'object' + } + } + }, + editable: { + description: 'Defines if component is editable', + control: { + type: 'boolean' + }, + table: { + category: 'Provider settings', + type: { + summary: 'boolean' + }, + defaultValue: { + summary: 'false' + } + } + }, + title: { + control: { + type: 'text' + }, + table: { + category: 'Provider settings', + type: { + summary: 'string' + }, + defaultValue: { + summary: 'JSON' + } + } + } + }, + args: { + value: jsonData as unknown as string, + editable: false, + title: 'JSON Dialog Title' + } +}; + +export default meta; +type Story = StoryObj; + +export const EditJSONDialog: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/core/src/lib/form/components/form-renderer.component.scss b/lib/core/src/lib/form/components/form-renderer.component.scss index 7d17eb91ae..e2e7fbad62 100644 --- a/lib/core/src/lib/form/components/form-renderer.component.scss +++ b/lib/core/src/lib/form/components/form-renderer.component.scss @@ -42,15 +42,15 @@ display: grid; &-column-view { - @include flex.layout-bp(lt-md) { - display: flow; - } - display: flex; margin-right: -1%; width: 100%; gap: 8px; + @include flex.layout-bp(lt-md) { + display: flow; + } + &-item { width: 100%; box-sizing: border-box; diff --git a/lib/core/src/lib/icon/icon.component.stories.ts b/lib/core/src/lib/icon/icon.component.stories.ts new file mode 100644 index 0000000000..f9c5d375b6 --- /dev/null +++ b/lib/core/src/lib/icon/icon.component.stories.ts @@ -0,0 +1,80 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular'; +import { IconComponent } from './icon.component'; +import { provideStoryCore } from '../stories/core-story.providers'; + +const meta: Meta = { + component: IconComponent, + title: 'Core/Icon/Icon', + decorators: [ + moduleMetadata({ + imports: [IconComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Provides a universal way of rendering registered and named icons.` + } + } + }, + argTypes: { + color: { + control: 'radio', + options: ['primary', 'accent', 'warn', undefined], + description: 'icon color', + defaultValue: undefined, + table: { + type: { summary: 'ThemePalette' }, + defaultValue: { summary: 'undefined' } + } + }, + value: { + description: 'icon name', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'settings' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultIcon: Story = { + render: (args) => ({ + props: args + }), + args: { + value: '' + } +}; + +export const CustomIcon: Story = { + render: (args) => ({ + props: args + }), + args: { + value: 'cloud_download' + } +}; diff --git a/lib/core/src/lib/identity-user-info/identity-user-info.component.stories.ts b/lib/core/src/lib/identity-user-info/identity-user-info.component.stories.ts new file mode 100644 index 0000000000..271b5bf0de --- /dev/null +++ b/lib/core/src/lib/identity-user-info/identity-user-info.component.stories.ts @@ -0,0 +1,124 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { IdentityUserInfoComponent } from './identity-user-info.component'; +import { provideStoryCore } from '../stories/core-story.providers'; + +const fakeIdentityUser = { + familyName: 'Identity', + givenName: 'John', + email: 'john.identity@gmail.com', + username: 'johnyIdentity99' +}; + +const meta: Meta = { + component: IdentityUserInfoComponent, + title: 'Core/Identity User Info/Identity User Info', + decorators: [ + moduleMetadata({ + imports: [IdentityUserInfoComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + isLoggedIn: { + description: 'Determines if user is logged in', + control: 'boolean', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + identityUser: { + description: 'Identity User Info', + control: 'object', + table: { + type: { summary: 'IdentityUserModel' } + } + }, + menuPositionX: { + description: 'Material Angular menu horizontal position in regard to User Info', + control: 'radio', + options: ['before', 'after'], + table: { + type: { summary: 'MenuPositionX' }, + defaultValue: { summary: 'after' } + } + }, + menuPositionY: { + description: 'Material Angular menu vertical position in regard to User Info', + control: 'radio', + options: ['above', 'below'], + table: { + type: { summary: 'MenuPositionY' }, + defaultValue: { summary: 'below' } + } + }, + showName: { + description: 'Determines if name should be shown next to user avatar', + control: 'boolean', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + namePosition: { + description: 'User name position in regard to avatar', + control: 'radio', + options: ['left', 'right'], + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'right' } + } + }, + bpmBackgroundImage: { + description: 'Menu background banner image for APS users', + control: { + disable: true + }, + table: { + type: { + summary: 'string' + }, + defaultValue: { + summary: './assets/images/bpm-background.png' + } + } + } + }, + args: { + identityUser: fakeIdentityUser, + isLoggedIn: true, + menuPositionX: 'after', + menuPositionY: 'below', + showName: true, + namePosition: 'right', + bpmBackgroundImage: './assets/images/bpm-background.png' + } +}; + +export default meta; +type Story = StoryObj; + +export const LoginWithSSO: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/core/src/lib/info-drawer/info-drawer.component.stories.ts b/lib/core/src/lib/info-drawer/info-drawer.component.stories.ts new file mode 100644 index 0000000000..891ac228f0 --- /dev/null +++ b/lib/core/src/lib/info-drawer/info-drawer.component.stories.ts @@ -0,0 +1,334 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { InfoDrawerComponent, InfoDrawerTabComponent } from './info-drawer.component'; +import { InfoDrawerButtonsDirective, InfoDrawerContentDirective, InfoDrawerTitleDirective } from './info-drawer-layout.component'; +import { mockTabText, mockCardText } from './mock/info-drawer.mock'; +import { provideStoryCore } from '../stories/core-story.providers'; +import { MatIconModule } from '@angular/material/icon'; + +type InfoDrawerStoryArgs = InfoDrawerComponent & { + showSecondTab?: boolean; + showThirdTab?: boolean; + label1?: string; + label2?: string; + label3?: string; + icon1?: string; + icon2?: string; + icon3?: string; + tab1Text?: string; + tab2Text?: string; + tab3Text?: string; + cardText?: string; +}; + +const meta: Meta = { + component: InfoDrawerComponent, + title: 'Core/Info Drawer/Info Drawer', + decorators: [ + moduleMetadata({ + imports: [ + InfoDrawerTabComponent, + InfoDrawerComponent, + InfoDrawerTitleDirective, + InfoDrawerButtonsDirective, + InfoDrawerContentDirective, + MatIconModule + ] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays a sidebar-style information panel in single layout or using tabs.` + } + } + }, + argTypes: { + selectedIndex: { + control: 'select', + options: [0, 1, 2], + defaultValue: 0, + description: 'The selected index tab (Tab Layout only)', + table: { + type: { summary: 'number' }, + defaultValue: { summary: '0' } + } + }, + title: { + control: 'text', + description: 'The title of the info drawer', + defaultValue: null, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'null' } + }, + if: { arg: 'showHeader', truthy: true } + }, + showHeader: { + control: 'boolean', + description: 'Visibility of the header', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showSecondTab: { + control: 'boolean', + description: 'Visibility of the second tab (Tab Layout only)', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showThirdTab: { + control: 'boolean', + description: 'Visibility of the third tab (Tab Layout only)', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + label1: { + control: 'text', + description: 'Label of the first tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Labels' + } + }, + label2: { + control: 'text', + description: 'Label of the second tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Labels' + }, + if: { arg: 'showSecondTab', truthy: true } + }, + label3: { + control: 'text', + description: 'Label of the third tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Labels' + }, + if: { arg: 'showThirdTab', truthy: true } + }, + icon1: { + control: 'text', + description: 'Icon of the first tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Icons' + } + }, + icon2: { + control: 'text', + description: 'Icon of the second tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Icons' + }, + if: { arg: 'showSecondTab', truthy: true } + }, + icon3: { + control: 'text', + description: 'Icon of the third tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Icons' + }, + if: { arg: 'showThirdTab', truthy: true } + }, + tab1Text: { + control: 'text', + description: 'Text content of the first tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Tab Content' + } + }, + tab2Text: { + control: 'text', + description: 'Text content of the second tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Tab Content' + }, + if: { arg: 'showSecondTab', truthy: true } + }, + tab3Text: { + control: 'text', + description: 'Text content of the third tab (Tab Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Tab Content' + }, + if: { arg: 'showThirdTab', truthy: true } + }, + cardText: { + control: 'text', + description: 'The content of the single card (Single Layout only)', + defaultValue: undefined, + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + currentTab: { + action: 'currentTab', + description: 'Emitted when the currently active tab changes', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + } + }, + args: { + selectedIndex: 0, + showHeader: true, + showSecondTab: true, + showThirdTab: true + } +}; + +export default meta; +type Story = StoryObj; + +export const TabLayoutWithTextLabels: Story = { + render: (args) => ({ + props: args, + template: ` +
+ clear +
+ + +
{{ tab1Text }}
+
+ + +
{{ tab2Text }}
+
+ + +
{{ tab3Text }}
+
+ +
` + }), + args: { + title: 'Activities', + label1: 'Activity', + label2: 'Details', + label3: 'More Info', + tab1Text: `This is a variant of the Info Drawer Layout component that displays information in tabs. ${mockTabText}`, + tab2Text: mockTabText, + tab3Text: mockTabText + }, + parameters: { + controls: { exclude: ['cardText'] } + } +}; + +export const TabLayoutWithIconLabels: Story = { + render: (args) => ({ + props: args, + template: ` +
+ clear +
+ + +
{{ tab1Text }}
+
+ + +
{{ tab2Text }}
+
+ + +
{{ tab3Text }}
+
+ +
` + }), + args: { + title: 'Activities', + icon1: 'people', + icon2: 'android', + icon3: 'comment', + tab1Text: `This is a variant of the Info Drawer Layout component that displays information in tabs. ${mockTabText}`, + tab2Text: mockTabText, + tab3Text: mockTabText + }, + parameters: { + controls: { exclude: ['cardText'] } + } +}; + +export const SingleLayout: Story = { + render: (args) => ({ + props: args, + template: ` +
File info
+ +
+ clear +
+ +
+ + {{ cardText }} + +
+
` + }), + args: { + title: 'Single Activities', + cardText: mockCardText, + showHeader: true, + showSecondTab: false, + showThirdTab: false + } +}; diff --git a/lib/core/src/lib/info-drawer/mock/info-drawer.mock.ts b/lib/core/src/lib/info-drawer/mock/info-drawer.mock.ts new file mode 100644 index 0000000000..bdbadc33c1 --- /dev/null +++ b/lib/core/src/lib/info-drawer/mock/info-drawer.mock.ts @@ -0,0 +1,34 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable @cspell/spellchecker */ + +export const mockTabText = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam urna odio, sagittis vel nulla vel, condimentum egestas dolor. +Interdum et malesuada fames ac ante ipsum primis in faucibus. Mauris eu hendrerit lectus. Aliquam et ex imperdiet, sodales tellus finibus, malesuada eros. +Vestibulum aliquet eros sed diam euismod tincidunt. +Pellentesque euismod, augue at blandit dapibus, ex nunc viverra nisl, non laoreet nibh odio in libero. +Quisque facilisis, dui luctus fringilla lacinia, dui enim accumsan diam, a vehicula mi nulla quis dolor. +Maecenas non neque sed nulla tincidunt vehicula.`; + +export const mockCardText = `Suspendisse euismod egestas nisi, non ullamcorper orci scelerisque id. Vestibulum mollis ex imperdiet nisl viverra egestas. +Nunc commodo, mi elementum auctor bibendum, neque tortor justo, eget gravida eros. +Vestibulum nec dui ac ipsum posuere ullamcorper. Nullam ultrices eget tellus ut gravida. Aliquam ullamcorper tellus ac dui vehicula venenatis. +Maecenas ante ipsum, vestibulum sit amet fringilla a, fringilla quis leo. +Sed nisl nisi, lacinia ac ullamcorper non, tincidunt at massa. Sed at metus fermentum augue eleifend porta. Sed nec dui ut quam facilisis cursus at et eros. +Nulla quis diam vitae odio faucibus faucibus ac ac erat. Sed vehicula est eu congue pretium. +Donec quis nisi ligula. Donec pellentesque nibh nec scelerisque placerat. Nulla facilisi. Sed egestas nisi at risus iaculis faucibus. Nulla facilisi. +Aliquam ac tincidunt justo, sit amet aliquet libero.`; diff --git a/lib/core/src/lib/language-menu/language-menu.component.stories.ts b/lib/core/src/lib/language-menu/language-menu.component.stories.ts new file mode 100644 index 0000000000..99ab4637e5 --- /dev/null +++ b/lib/core/src/lib/language-menu/language-menu.component.stories.ts @@ -0,0 +1,107 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, componentWrapperDecorator, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { LanguageMenuComponent } from './language-menu.component'; +import { LanguageService } from './service/language.service'; +import { LanguageServiceMock } from '../mock/language.service.mock'; +import { provideStoryCore } from '../stories/core-story.providers'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; + +const meta: Meta = { + component: LanguageMenuComponent, + title: 'Core/Language Menu/Language Menu', + decorators: [ + moduleMetadata({ + imports: [LanguageMenuComponent, MatMenuModule, MatButtonModule, MatIconModule], + providers: [{ provide: LanguageService, useClass: LanguageServiceMock }] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays all the languages that are present in "app.config.json" and the default (EN).` + } + } + }, + argTypes: { + changedLanguage: { + action: 'changedLanguage', + description: 'Emitted when the user clicks on one of the language buttons.', + table: { + category: 'Actions', + type: { summary: 'EventEmitter ' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const AsMainMenu: Story = { + render: (args) => ({ + props: args + }), + decorators: [ + componentWrapperDecorator( + (story) => ` + + + ${story} + + ` + ) + ] +}; + +export const AsNestedMenu: Story = { + render: (args) => ({ + props: args + }), + decorators: [ + componentWrapperDecorator( + (story) => ` + + + + + + ${story} + + ` + ) + ] +}; diff --git a/lib/core/src/lib/language-menu/language-picker.component.stories.ts b/lib/core/src/lib/language-menu/language-picker.component.stories.ts new file mode 100644 index 0000000000..1ce62dad9b --- /dev/null +++ b/lib/core/src/lib/language-menu/language-picker.component.stories.ts @@ -0,0 +1,76 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, componentWrapperDecorator, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { LanguagePickerComponent } from './language-picker.component'; +import { LanguageService } from './service/language.service'; +import { LanguageServiceMock } from '../mock/language.service.mock'; +import { provideStoryCore } from '../stories/core-story.providers'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; + +const meta: Meta = { + component: LanguagePickerComponent, + title: 'Core/Language Menu/Language Picker', + decorators: [ + moduleMetadata({ + imports: [LanguagePickerComponent, MatMenuModule, MatButtonModule, MatIconModule], + providers: [{ provide: LanguageService, useClass: LanguageServiceMock }] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + changedLanguage: { + action: 'changedLanguage', + description: 'Emitted when the user clicks on one of the language buttons.', + table: { + category: 'Actions', + type: { summary: 'EventEmitter ' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + render: (args) => ({ + props: args + }) +}; + +export const AsNestedMenu: Story = { + render: (args) => ({ + props: args + }), + decorators: [ + componentWrapperDecorator( + (story) => ` + + + ${story} + + ` + ) + ] +}; diff --git a/lib/core/src/lib/layout/components/header/header.component.stories.ts b/lib/core/src/lib/layout/components/header/header.component.stories.ts new file mode 100644 index 0000000000..9cc0c33b33 --- /dev/null +++ b/lib/core/src/lib/layout/components/header/header.component.stories.ts @@ -0,0 +1,142 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { HeaderLayoutComponent } from './header.component'; +import { provideStoryCore } from '../../../stories/core-story.providers'; + +const meta: Meta = { + component: HeaderLayoutComponent, + title: 'Core/Layout/Header', + decorators: [ + moduleMetadata({ + imports: [HeaderLayoutComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `This component displays a customizable header for Alfresco applications that can be reused. + Use the input properties to configure the left side (title, button) and the primary color of the header. + The right part of the header can contain other components which are transcluded in the header component.` + } + } + }, + argTypes: { + color: { + control: 'radio', + options: ['primary', 'accent', 'warn', '#42f57e', undefined], + description: `Background color for the header. + It can be any hex color code or one of the Material theme colors: 'primary', 'accent' or 'warn'`, + table: { + type: { summary: 'ThemePalette' }, + defaultValue: { summary: 'undefined' } + } + }, + expandedSidenav: { + control: 'boolean', + description: 'Toggles the expanded state of the component', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showSidenavToggle: { + control: 'boolean', + description: 'Toggles whether the sidenav button will be displayed in the header or not', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + logo: { + control: 'text', + description: 'Path to an image file for the application logo', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + title: { + control: 'text', + description: 'Title of the application', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + tooltip: { + control: 'text', + description: 'The tooltip text for the application logo', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + position: { + control: 'radio', + options: ['start', 'end'], + description: `The side of the page that the drawer is attached to (can be 'start' or 'end')`, + defaultValue: 'start', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'start' } + } + }, + redirectUrl: { + control: 'text', + description: 'The router link for the application logo, when clicked', + defaultValue: '/', + table: { + type: { summary: 'string | any[]' }, + defaultValue: { summary: '/' } + } + }, + clicked: { + action: 'clicked', + description: 'Emitted when the sidenav button is clicked', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + } + }, + args: { + expandedSidenav: true, + showSidenavToggle: true, + position: 'start', + redirectUrl: '/' + } +}; + +export default meta; +type Story = StoryObj; + +export const Header: Story = { + render: (args) => ({ + props: args + }), + args: { + title: 'Hello from Header!', + tooltip: 'Default Tooltip text' + } +}; diff --git a/lib/core/src/lib/layout/components/sidebar-action/sidebar-action.component.stories.ts b/lib/core/src/lib/layout/components/sidebar-action/sidebar-action.component.stories.ts new file mode 100644 index 0000000000..a9e014b368 --- /dev/null +++ b/lib/core/src/lib/layout/components/sidebar-action/sidebar-action.component.stories.ts @@ -0,0 +1,82 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { SidebarActionMenuComponent } from './sidebar-action-menu.component'; +import { provideStoryCore } from '../../../stories/core-story.providers'; + +const meta: Meta = { + component: SidebarActionMenuComponent, + title: 'Core/Layout/Sidebar Action Menu', + decorators: [ + moduleMetadata({ + imports: [SidebarActionMenuComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays a sidebar-action menu information panel.` + } + } + }, + argTypes: { + expanded: { + control: 'boolean', + description: 'Toggle the sidebar action menu on expand', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + title: { + control: 'text', + description: 'The title of the sidebar action', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + width: { + control: 'number', + description: 'Width in pixels for sidebar action menu options', + table: { + type: { summary: 'number' }, + defaultValue: { summary: '272' } + } + } + }, + args: { + expanded: true, + width: 272 + } +}; + +export default meta; +type Story = StoryObj; + +export const SidebarActionMenu: Story = { + render: (args) => ({ + props: args + }), + args: { + title: 'Hello from Sidebar Action Menu!' + } +}; diff --git a/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.scss b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.scss index fa4405181d..e7a7e12cec 100644 --- a/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.scss +++ b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.scss @@ -3,6 +3,10 @@ @use '../../../styles/mat-selectors' as ms; .adf-sidenav-layout { + @include mixins.flex-column; + + width: 100%; + &-full-space { display: flex; flex-direction: column; @@ -13,10 +17,6 @@ width: 100%; } - @include mixins.flex-column; - - width: 100%; - .adf-layout__content { flex: 1 1 auto; } diff --git a/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.stories.ts b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.stories.ts new file mode 100644 index 0000000000..ce3aad480f --- /dev/null +++ b/lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.stories.ts @@ -0,0 +1,243 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { SidenavLayoutComponent } from './sidenav-layout.component'; +import { MatListModule } from '@angular/material/list'; +import { MatIconModule } from '@angular/material/icon'; +import { provideStoryCore } from '../../../stories/core-story.providers'; + +type SidenavLayoutStoryArgs = SidenavLayoutComponent & { + title?: string; + color?: 'primary' | 'accent' | 'warn'; + clicked?: any; +}; + +const meta: Meta = { + component: SidenavLayoutComponent, + title: 'Core/Layout/Sidenav Layout', + decorators: [ + moduleMetadata({ + imports: [SidenavLayoutComponent, MatIconModule, MatListModule] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays the standard three-region ADF application layout.` + } + } + }, + argTypes: { + expandedSidenav: { + control: 'boolean', + description: 'Toggles the expand of navigation region', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' }, + category: 'Navigation' + } + }, + hideSidenav: { + control: 'boolean', + description: 'Toggles showing/hiding the navigation region', + defaultValue: false, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' }, + category: 'Navigation' + } + }, + position: { + control: 'radio', + options: ['start', 'end'], + description: `The side of the page that the drawer is attached to (can be 'start' or 'end')`, + defaultValue: 'start', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'start' }, + category: 'Navigation' + } + }, + sidenavMax: { + control: 'number', + description: 'Maximum size of the navigation region', + table: { + type: { summary: 'number' }, + defaultValue: { summary: 'undefined' }, + category: 'Navigation' + } + }, + sidenavMin: { + control: 'number', + description: 'Minimum size of the navigation region', + table: { + type: { summary: 'number' }, + defaultValue: { summary: 'undefined' }, + category: 'Navigation' + } + }, + stepOver: { + control: 'number', + description: 'Screen size at which display switches from small screen to large screen configuration', + table: { + type: { summary: 'number' }, + defaultValue: { summary: 'undefined' } + } + }, + title: { + control: 'text', + description: 'Title of the application', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' }, + category: 'Header' + } + }, + color: { + control: 'radio', + options: ['primary', 'accent', 'warn', undefined], + description: `Background color for the header. + It can be any hex color code or one of the Material theme colors: 'primary', 'accent' or 'warn'`, + table: { + type: { summary: 'ThemePalette' }, + defaultValue: { summary: 'undefined' }, + category: 'Header' + } + }, + clicked: { + action: 'expanded', + description: 'Emitted when the menu toggle and the collapsed/expanded state of the sideNav changes', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + } + }, + args: { + expandedSidenav: true, + hideSidenav: false, + position: 'start' + } +}; + +export default meta; +type Story = StoryObj; + +export const SidenavLayout: Story = { + render: (args) => ({ + props: args, + template: ` + +
+ + + + + + + + + + + home + Home + + + + device_hub + Content Processes + + + + folder_open + Files + + + + rowing + Quick Search + + + + cloud + Cloud + + + + settings + Settings + + + + exit_to_app + Logout + + + + + + + +
+ Thanks to transclusion you can put anything you want inside header, sidenav and this (content) sections. + ADF Layout Header component is located in header section. In navigation, there is + Angular Material Navigation list where items can contain routes to ADF components which then they will be rendered here, in content section. +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. +

+ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. + Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. + Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? + Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? + At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, + similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. + Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, + omnis voluptas assumenda est, omnis dolor repellendus. + Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. + Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. +
+
+
+
+
` + }), + args: { + sidenavMin: 85, + sidenavMax: 250, + stepOver: 600, + position: 'start', + title: 'Hello from Sidenav Layout!' + } +}; diff --git a/lib/core/src/lib/login/components/login/login.component.stories.ts b/lib/core/src/lib/login/components/login/login.component.stories.ts new file mode 100644 index 0000000000..324a196c29 --- /dev/null +++ b/lib/core/src/lib/login/components/login/login.component.stories.ts @@ -0,0 +1,183 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { LoginComponent } from './login.component'; +import { provideStoryCore } from '../../../stories/core-story.providers'; +import { NoopAuthModule } from '@alfresco/adf-core'; + +type LoginStoryArgs = LoginComponent & { + correct?: any; + corsError?: any; + csrfError?: any; + ecmAccessError?: any; +}; + +const meta: Meta = { + component: LoginComponent, + title: 'Core/Login/Login', + decorators: [ + moduleMetadata({ + imports: [LoginComponent, NoopAuthModule] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Authenticates to Alfresco Content Services and Alfresco Process Services.` + } + } + }, + argTypes: { + correct: { + name: 'To test correct functionality:', + description: 'Use `fake-username` and `fake-password`.', + table: { category: 'Storybook Info' } + }, + corsError: { + name: 'To test CORS error:', + description: 'Use `fake-username-CORS-error` and `fake-password`.', + table: { category: 'Storybook Info' } + }, + csrfError: { + name: 'To test CSRF error:', + description: 'Use `fake-username-CSRF-error` and `fake-password`.', + table: { category: 'Storybook Info' } + }, + ecmAccessError: { + name: 'To test ECM access error:', + description: 'Use `fake-username-ECM-access-error` and `fake-password`.', + table: { category: 'Storybook Info' } + }, + showRememberMe: { + control: 'boolean', + description: + 'Should the `Remember me` checkbox be shown? When selected, this option will remember the logged-in user after the browser is closed to avoid logging in repeatedly.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showLoginActions: { + control: 'boolean', + description: 'Should the extra actions (`Need Help`, `Register`, etc) be shown?', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + needHelpLink: { + control: 'text', + description: 'Sets the URL of the NEED HELP link in the footer.', + defaultValue: '/?path=/story/core-login-login--login', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '/?path=/story/core-login-login--login' } + } + }, + registerLink: { + control: 'text', + description: 'Sets the URL of the REGISTER link in the footer.', + defaultValue: '/?path=/story/core-login-login--login', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '/?path=/story/core-login-login--login' } + } + }, + logoImageUrl: { + control: 'text', + description: 'Path to a custom logo image.', + defaultValue: './assets/images/alfresco-logo.svg', + table: { + type: { summary: 'string' }, + defaultValue: { summary: './assets/images/alfresco-logo.svg' } + } + }, + backgroundImageUrl: { + control: 'text', + description: 'Path to a custom background image.', + defaultValue: './assets/images/background.svg', + table: { + type: { summary: 'string' }, + defaultValue: { summary: './assets/images/background.svg' } + } + }, + copyrightText: { + control: 'text', + description: 'The copyright text below the login box.', + defaultValue: '\u00A9 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '\u00A9 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.' } + } + }, + fieldsValidation: { + control: 'object', + description: 'Custom validation rules for the login form.', + table: { + type: { summary: 'any' }, + defaultValue: { summary: 'undefined' } + } + }, + successRoute: { + control: 'text', + description: 'Route to redirect to on successful login.', + defaultValue: '.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '.' } + } + }, + success: { + action: 'success', + description: 'Emitted when the login is successful.', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + }, + error: { + action: 'error', + description: 'Emitted when the login fails.', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + }, + executeSubmit: { + action: 'executeSubmit', + description: 'Emitted when the login form is submitted.', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const Login: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/core/src/lib/mock/data-column.mock.ts b/lib/core/src/lib/mock/data-column.mock.ts new file mode 100644 index 0000000000..d29b0f775c --- /dev/null +++ b/lib/core/src/lib/mock/data-column.mock.ts @@ -0,0 +1,63 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { mockPathInfos } from '../datatable/components/mocks/datatable.mock'; + +export const textColumnRows = [{ firstname: 'John' }, { firstname: 'Henry' }, { firstname: 'David' }, { firstname: 'Thomas' }]; + +export const dateColumnRows = [ + { createdOn: new Date(2016, 6, 1, 11, 8, 4) }, + { createdOn: new Date(2018, 4, 3, 12, 8, 4) }, + { createdOn: new Date(2021, 2, 3, 9, 8, 4) } +]; + +const aMinuteInMilliseconds = 60 * 1000; +const anHourInMilliseconds = 60 * aMinuteInMilliseconds; +const aDayInMilliseconds = 24 * anHourInMilliseconds; + +export const dateColumnTimeAgoRows = [ + { modifiedOn: new Date() }, + { modifiedOn: new Date(Date.now() - 44 * aMinuteInMilliseconds) }, + { modifiedOn: new Date(Date.now() - 45 * aMinuteInMilliseconds) }, + { modifiedOn: new Date(Date.now() - 23 * anHourInMilliseconds) }, + { modifiedOn: new Date(Date.now() - 7 * aDayInMilliseconds) }, + { modifiedOn: new Date(Date.now() - 8 * aDayInMilliseconds) } +]; + +export const locationColumnRows = [ + { + path: mockPathInfos[0] + }, + { + path: mockPathInfos[1] + }, + { + path: mockPathInfos[2] + } +]; + +export const booleanColumnRows = [{ bool: 'true' }, { bool: 'false' }, { bool: true }, { bool: false }]; + +export const iconColumnRows = [{ icon: 'alarm' }, { icon: 'folder_open' }, { icon: 'accessibility' }]; + +export const imageColumnRows = [{ image: 'material-icons://image' }, { image: 'material-icons://image' }, { image: 'material-icons://image' }]; + +export const fileSizeColumnRows = [{ size: 12313 }, { size: 23 }, { size: 42421412421 }]; + +export const amountColumnRows = [{ price: 1230 }, { price: 422.55 }, { price: 50000.7855332 }, { price: 0.123 }, { price: -2022.3321 }]; + +export const jsonColumnRows = [{ rowInfo: { id: 1, name: 'row1' } }, { rowInfo: { id: 2, name: 'row2' } }, { rowInfo: { id: 3, name: 'row3' } }]; diff --git a/lib/core/src/lib/mock/language.service.mock.ts b/lib/core/src/lib/mock/language.service.mock.ts new file mode 100644 index 0000000000..acf43eddd2 --- /dev/null +++ b/lib/core/src/lib/mock/language.service.mock.ts @@ -0,0 +1,54 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LanguageServiceInterface } from '../language-menu/service/language.service.interface'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; +import { LanguageItem } from '../common/services/language-item.interface'; + +@Injectable() +export class LanguageServiceMock implements LanguageServiceInterface { + private languages = new BehaviorSubject([ + { key: 'de', label: 'Deutsch' }, + { key: 'en', label: 'English' }, + { key: 'es', label: 'Español' }, + { key: 'fr', label: 'Français' }, + { key: 'it', label: 'Italiano' }, + { key: 'ja', label: '日本語' }, + { key: 'nb', label: 'Bokmål' }, + { key: 'nl', label: 'Nederlands' }, + { key: 'pt-BR', label: 'Português (Brasil)' }, + { key: 'ru', label: 'Русский' }, + { key: 'zh-CN', label: '中文简体' }, + { key: 'cs', label: 'Čeština' }, + { key: 'da', label: 'Dansk' }, + { key: 'fi', label: 'Suomi' }, + { key: 'pl', label: 'Polski' }, + { key: 'sv', label: 'Svenska' }, + { key: 'ar', label: 'العربية', direction: 'rtl' } + ]); + + languages$ = this.languages.asObservable(); + + changeLanguage(_language: LanguageItem): void {} + + setLanguages(items: LanguageItem[]): void { + if (items?.length > 0) { + this.languages.next(items); + } + } +} diff --git a/lib/core/src/lib/notifications/components/add-notification-component.mock.ts b/lib/core/src/lib/notifications/components/add-notification-component.mock.ts new file mode 100644 index 0000000000..fcf1981748 --- /dev/null +++ b/lib/core/src/lib/notifications/components/add-notification-component.mock.ts @@ -0,0 +1,36 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { NotificationService } from '../services/notification.service'; +import { MatButtonModule } from '@angular/material/button'; + +@Component({ + selector: 'adf-add-notification-storybook', + imports: [MatButtonModule], + template: ` ` +}) +export class AddNotificationStorybookComponent { + infoCounter: number = 1; + + constructor(private notificationService: NotificationService) {} + + showInfo() { + this.notificationService.showInfo(`Example notification ${this.infoCounter}`); + this.infoCounter++; + } +} diff --git a/lib/core/src/lib/notifications/components/notification-history.component.stories.ts b/lib/core/src/lib/notifications/components/notification-history.component.stories.ts new file mode 100644 index 0000000000..890851d468 --- /dev/null +++ b/lib/core/src/lib/notifications/components/notification-history.component.stories.ts @@ -0,0 +1,93 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { NotificationHistoryComponent } from './notification-history.component'; +import { AddNotificationStorybookComponent } from './add-notification-component.mock'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +const meta: Meta = { + component: NotificationHistoryComponent, + title: 'Core/Notification History/Notification History', + decorators: [ + moduleMetadata({ + imports: [NotificationHistoryComponent, AddNotificationStorybookComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Lists notifications received in the current session. The notifications disappear from the list after refresh.` + } + } + }, + argTypes: { + menuPositionX: { + control: 'inline-radio', + options: ['before', 'after'], + description: 'Custom choice for opening the menu at the bottom.', + table: { + type: { summary: 'MenuPositionX' }, + defaultValue: { summary: 'after' } + } + }, + menuPositionY: { + control: 'inline-radio', + options: ['below', 'above'], + description: 'Custom choice for opening the menu at the bottom.', + table: { + type: { summary: 'MenuPositionY' }, + defaultValue: { summary: 'below' } + } + }, + maxNotifications: { + control: 'number', + description: 'Maximum number of notifications to display. The rest will remain hidden until load more is clicked.', + table: { + type: { summary: 'number' }, + defaultValue: { summary: '5' } + } + } + }, + args: { + menuPositionX: 'after', + menuPositionY: 'below', + maxNotifications: 5 + } +}; + +export default meta; +type Story = StoryObj; + +export const NotificationHistory: Story = { + render: (args) => ({ + props: args, + template: ` +
+ + + + +
` + }) +}; diff --git a/lib/core/src/lib/pagination/pagination.component.stories.ts b/lib/core/src/lib/pagination/pagination.component.stories.ts new file mode 100644 index 0000000000..235e1cb3f1 --- /dev/null +++ b/lib/core/src/lib/pagination/pagination.component.stories.ts @@ -0,0 +1,99 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { PaginationComponent } from './pagination.component'; +import { provideStoryCore } from '../stories/core-story.providers'; + +const meta: Meta = { + component: PaginationComponent, + title: 'Core/Pagination/Pagination', + decorators: [ + moduleMetadata({ + imports: [PaginationComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + target: { + control: 'object', + description: 'Component that provides custom pagination support.', + table: { type: { summary: 'PaginatedComponent' } } + }, + supportedPageSizes: { + control: 'object', + description: 'An array of page sizes.', + table: { type: { summary: 'number[]' } } + }, + pagination: { + control: 'object', + description: 'Pagination object.', + table: { + type: { summary: 'PaginationModel' }, + defaultValue: { + summary: 'PaginationModel', + detail: + '{\n skipCount: 0 /* How many entities exist in the collection before those included in this list? */,' + + '\n maxItems: 25 /* The value of the maxItems parameter used to generate this list. The default value is 100. */,' + + '\n totalItems: 0 /* An integer describing the total number of entities in the collection. */,' + + '\n count: 0, /* The number of objects in the entries array. */' + + '\n hasMoreItems: false /* Are there more entities in the collection beyond those in this response? */\n}' + } + } + }, + change: { + action: 'change', + description: 'Emitted when pagination changes in any way.', + table: { category: 'Actions' } + }, + changePageNumber: { + action: 'changePageNumber', + description: 'Emitted when the page number changes.', + table: { category: 'Actions' } + }, + changePageSize: { + action: 'changePageSize', + description: 'Emitted when the page size changes.', + table: { category: 'Actions' } + }, + nextPage: { + action: 'nextPage', + description: 'Emitted when the next page is requested.', + table: { category: 'Actions' } + }, + prevPage: { + action: 'prevPage', + description: 'Emitted when the previous page is requested.', + table: { category: 'Actions' } + } + }, + args: { + supportedPageSizes: [5, 10, 15, 20], + pagination: { skipCount: 0, maxItems: 25, totalItems: 100, count: 100, hasMoreItems: false } + } +}; + +export default meta; +type Story = StoryObj; + +export const Pagination: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/core/src/lib/sorting-picker/sorting-picker.component.stories.ts b/lib/core/src/lib/sorting-picker/sorting-picker.component.stories.ts new file mode 100644 index 0000000000..75a932996c --- /dev/null +++ b/lib/core/src/lib/sorting-picker/sorting-picker.component.stories.ts @@ -0,0 +1,108 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { SortingPickerComponent } from './sorting-picker.component'; +import { provideStoryCore } from '../stories/core-story.providers'; + +const initialSortingTypes: Array<{ key: string; label: string }> = [ + { key: 'sortByFirstName', label: 'First Name' }, + { key: 'sortByLastName', label: 'Last Name' }, + { key: 'sortByBirthDate', label: 'Birth Date' } +]; + +const initialOptionKeys = [...initialSortingTypes.map((type) => type.key.toString())]; + +const meta: Meta = { + component: SortingPickerComponent, + title: 'Core/Sorting Picker/Sorting Picker', + decorators: [ + moduleMetadata({ + imports: [SortingPickerComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `The picker shows the user a menu of sorting options (which could be data columns to sort on alphabetical vs numerical search, etc) + and the choice of ascending vs descending sort order. + Note that picker only implements the menu, so you are responsible for implementing the sorting options yourself.` + } + } + }, + argTypes: { + selected: { + control: 'select', + options: initialOptionKeys, + description: 'Currently selected option key', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'undefined' } + } + }, + ascending: { + control: 'boolean', + description: 'Current sorting direction', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + options: { + description: 'Available sorting options', + table: { + type: { summary: 'Array<{key: string; label: string}>' }, + defaultValue: { summary: '[]' } + } + }, + valueChange: { + action: 'valueChange', + description: 'Raised each time sorting key gets changed', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + }, + sortingChange: { + action: 'sortingChange', + description: 'Raised each time direction gets changed', + table: { + type: { summary: 'EventEmitter ' }, + category: 'Actions' + } + } + }, + args: { + ascending: true, + options: [] + } +}; + +export default meta; +type Story = StoryObj; + +export const SortingPicker: Story = { + render: (args) => ({ + props: args + }), + args: { + options: initialSortingTypes + } +}; diff --git a/lib/core/src/lib/stories/core-story.providers.ts b/lib/core/src/lib/stories/core-story.providers.ts new file mode 100644 index 0000000000..f510432ce4 --- /dev/null +++ b/lib/core/src/lib/stories/core-story.providers.ts @@ -0,0 +1,49 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Provider, EnvironmentProviders, provideAppInitializer, inject } from '@angular/core'; +import { provideAnimations } from '@angular/platform-browser/animations'; +import { provideCoreAuthTesting } from '../testing/noop-auth.module'; +import { provideAppConfig } from '../app-config/provide-app-config'; +import { AppConfigService } from '../app-config/app-config.service'; +import { provideI18N } from '../translation'; +import { provideRouter, withHashLocation } from '@angular/router'; + +/** + * Provides the core providers for the storybook. + * + * @returns An array of providers for the core module. + */ +export function provideStoryCore(): (Provider | EnvironmentProviders)[] { + return [ + provideAppConfig(), + provideI18N({ + assets: [ + ['adf-core', 'assets/adf-core'], + ['adf-process-services', 'assets/adf-process-services'], + ['adf-process-services-cloud', 'assets/adf-process-services-cloud'] + ] + }), + provideAnimations(), + provideCoreAuthTesting(), + provideAppInitializer(() => { + const appConfig = inject(AppConfigService); + appConfig.config = { ...appConfig.config, locale: 'en' }; + }), + provideRouter([], withHashLocation()) + ]; +} diff --git a/lib/core/src/lib/stories/index.ts b/lib/core/src/lib/stories/index.ts new file mode 100644 index 0000000000..3e1793c56f --- /dev/null +++ b/lib/core/src/lib/stories/index.ts @@ -0,0 +1,18 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './core-story.providers'; diff --git a/lib/core/src/lib/styles/_flex.scss b/lib/core/src/lib/styles/_flex.scss index d82dff54f4..e8d83066f4 100644 --- a/lib/core/src/lib/styles/_flex.scss +++ b/lib/core/src/lib/styles/_flex.scss @@ -64,19 +64,16 @@ $overlapping-lt: ( @if map.has-key($breakpoints, $bp) { $min: map.get(map.get($breakpoints, $bp), begin); $max: map.get(map.get($breakpoints, $bp), end); - @media (min-width: $min) and (max-width: $max) { @content; } } @else if map.has-key($overlapping-gt, $bp) { $min: map.get($overlapping-gt, $bp); - @media (min-width: $min) { @content; } } @else if map.has-key($overlapping-lt, $bp) { $max: map.get($overlapping-lt, $bp); - @media (max-width: $max) { @content; } diff --git a/lib/core/src/lib/templates/empty-content/empty-content.component.stories.ts b/lib/core/src/lib/templates/empty-content/empty-content.component.stories.ts new file mode 100644 index 0000000000..43e9d3ceeb --- /dev/null +++ b/lib/core/src/lib/templates/empty-content/empty-content.component.stories.ts @@ -0,0 +1,104 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { EmptyContentComponent } from './empty-content.component'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +type EmptyContentStoryArgs = EmptyContentComponent & { + anyContentProjection?: boolean; +}; + +const meta: Meta = { + component: EmptyContentComponent, + title: 'Core/Template/Empty Content', + decorators: [ + moduleMetadata({ + imports: [EmptyContentComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Provides a generic "Empty Content" placeholder for components.` + } + } + }, + argTypes: { + icon: { + control: 'text', + description: 'Material Icon to use.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'cake' } + } + }, + title: { + control: 'text', + description: 'String or Resource Key for the title.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'title' } + } + }, + subtitle: { + control: 'text', + description: 'String or Resource Key for the subtitle.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'subtitle' } + } + }, + anyContentProjection: { + name: 'with any component / selector', + control: 'boolean', + description: 'Showcase content projection with any component / selector', + table: { + category: 'Content Projection', + type: { + summary: 'code', + detail: '
\n projected content\n
' + }, + defaultValue: { summary: 'false' } + } + } + }, + args: { + icon: 'cake', + title: 'title', + subtitle: 'subtitle', + anyContentProjection: false + } +}; + +export default meta; +type Story = StoryObj; + +export const EmptyContent: Story = { + render: (args: EmptyContentComponent & { anyContentProjection: boolean }) => ({ + props: args, + template: ` + +
+ projected content +
+
` + }) +}; diff --git a/lib/core/src/lib/templates/error-content/error-content.component.stories.ts b/lib/core/src/lib/templates/error-content/error-content.component.stories.ts new file mode 100644 index 0000000000..fb080a1078 --- /dev/null +++ b/lib/core/src/lib/templates/error-content/error-content.component.stories.ts @@ -0,0 +1,89 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { ErrorContentComponent } from './error-content.component'; +import { ActivatedRoute } from '@angular/router'; +import { of } from 'rxjs'; +import { provideStoryCore } from '../../stories/core-story.providers'; + +type ErrorContentStoryArgs = ErrorContentComponent & { + errorContentActions?: boolean; +}; + +const meta: Meta = { + component: ErrorContentComponent, + title: 'Core/Template/Error Content', + decorators: [ + moduleMetadata({ + imports: [ErrorContentComponent], + providers: [{ provide: ActivatedRoute, useValue: { params: of({}) } }] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + parameters: { + docs: { + description: { + component: `Displays information about a specific error.` + } + } + }, + argTypes: { + errorCode: { + control: 'text', + description: 'Error code associated with this error.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: 'UNKNOWN' } + } + }, + errorContentActions: { + name: 'with adf-error-content-actions selector', + control: 'boolean', + description: 'Showcase content projection with adf-error-content-actions selector', + table: { + category: 'Content Projection', + type: { + summary: 'code', + detail: '
\n \n
' + }, + defaultValue: { summary: 'false' } + } + } + }, + args: { + errorCode: 'UNKNOWN', + errorContentActions: false + } +}; + +export default meta; +type Story = StoryObj; + +export const ErrorContent: Story = { + render: (args: ErrorContentComponent & { errorContentActions: boolean }) => ({ + props: args, + template: ` + +
+ +
+
` + }) +}; diff --git a/lib/core/src/lib/toolbar/toolbar.component.stories.ts b/lib/core/src/lib/toolbar/toolbar.component.stories.ts new file mode 100644 index 0000000000..c7df9a1002 --- /dev/null +++ b/lib/core/src/lib/toolbar/toolbar.component.stories.ts @@ -0,0 +1,122 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { ToolbarComponent } from './toolbar.component'; +import { ToolbarDividerComponent } from './toolbar-divider.component'; +import { ToolbarTitleComponent } from './toolbar-title.component'; +import { provideStoryCore } from '../stories/core-story.providers'; + +type ToolbarStoryArgs = ToolbarComponent & { + toolbarTitle?: boolean; + toolbarDivider?: boolean; + anyContentProjection?: boolean; +}; + +const meta: Meta = { + component: ToolbarComponent, + title: 'Core/Toolbar/Toolbar', + decorators: [ + moduleMetadata({ + imports: [ToolbarComponent, ToolbarTitleComponent, ToolbarDividerComponent] + }), + applicationConfig({ + providers: [...provideStoryCore()] + }) + ], + argTypes: { + color: { + control: 'radio', + options: ['primary', 'accent', 'warn', undefined], + description: 'Toolbar color.', + table: { + type: { summary: 'ThemePalette' }, + defaultValue: { summary: 'undefined' } + } + }, + title: { + control: 'text', + description: 'Toolbar title.', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '' } + } + }, + toolbarTitle: { + name: 'with adf-toolbar-title component', + control: 'boolean', + description: 'Showcase content projection with adf-toolbar-title component', + table: { + category: 'Content Projection', + type: { + summary: 'code', + detail: 'Projected Title' + }, + defaultValue: { summary: 'false' } + } + }, + toolbarDivider: { + name: 'with adf-toolbar-divider component', + control: 'boolean', + description: 'Showcase content projection with adf-toolbar-divider component', + table: { + category: 'Content Projection', + type: { + summary: 'code', + detail: 'leftright' + }, + defaultValue: { summary: 'false' } + } + }, + anyContentProjection: { + name: 'with any component / selector', + control: 'boolean', + description: 'Showcase content projection with any component / selector', + table: { + category: 'Content Projection', + type: { + summary: 'code', + detail: 'projected content' + }, + defaultValue: { summary: 'false' } + } + } + }, + args: { + title: '', + toolbarTitle: false, + toolbarDivider: false, + anyContentProjection: false + } +}; + +export default meta; +type Story = StoryObj; + +export const Toolbar: Story = { + render: (args: ToolbarComponent & { anyContentProjection: boolean } & { toolbarDivider: boolean } & { toolbarTitle: boolean }) => ({ + props: args, + template: ` + + Projected Title + + projected content + + leftright + ` + }) +}; diff --git a/lib/core/src/public-api.ts b/lib/core/src/public-api.ts index c8dd1e4a3e..53936cd229 100644 --- a/lib/core/src/public-api.ts +++ b/lib/core/src/public-api.ts @@ -52,6 +52,7 @@ export * from './lib/models/index'; export * from './lib/events/index'; export * from './lib/mock/index'; export * from './lib/testing'; +export * from './lib/stories/index'; export * from './lib/auth'; export * from './lib/common'; diff --git a/lib/core/tsconfig.json b/lib/core/tsconfig.json index c311f0310d..a93df7905c 100644 --- a/lib/core/tsconfig.json +++ b/lib/core/tsconfig.json @@ -8,6 +8,9 @@ }, { "path": "./tsconfig.lib.prod.json" + }, + { + "path": "./.storybook/tsconfig.json" } ], "compilerOptions": { diff --git a/lib/core/tsconfig.lib.json b/lib/core/tsconfig.lib.json index 5235439297..fc8142f89d 100644 --- a/lib/core/tsconfig.lib.json +++ b/lib/core/tsconfig.lib.json @@ -17,6 +17,6 @@ "target": "ES2022", "useDefineForClassFields": false }, - "exclude": ["./test.ts", "**/*.spec.ts", "**/*.test.ts"], + "exclude": ["./test.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.stories.ts", "**/*.mock.ts"], "include": ["**/*.ts"] } diff --git a/lib/extensions/.eslintignore b/lib/extensions/.eslintignore index 4ebc8aea50..16523ff94f 100644 --- a/lib/extensions/.eslintignore +++ b/lib/extensions/.eslintignore @@ -1 +1,2 @@ +.storybook coverage diff --git a/lib/insights/.eslintignore b/lib/insights/.eslintignore index 4ebc8aea50..16523ff94f 100644 --- a/lib/insights/.eslintignore +++ b/lib/insights/.eslintignore @@ -1 +1,2 @@ +.storybook coverage diff --git a/lib/insights/tsconfig.lib.json b/lib/insights/tsconfig.lib.json index 56f880a88a..eea234db05 100644 --- a/lib/insights/tsconfig.lib.json +++ b/lib/insights/tsconfig.lib.json @@ -16,5 +16,6 @@ "target": "ES2022", "useDefineForClassFields": false }, + "exclude": ["./test.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.stories.ts"], "include": ["src/**/*.ts", "index.ts"] } diff --git a/lib/js-api/.eslintignore b/lib/js-api/.eslintignore index 7432c9a739..e5b1dd5fc0 100644 --- a/lib/js-api/.eslintignore +++ b/lib/js-api/.eslintignore @@ -1,2 +1,3 @@ +.storybook coverage docs diff --git a/lib/js-api/package.json b/lib/js-api/package.json index 2eaf73c2ba..77931831b6 100644 --- a/lib/js-api/package.json +++ b/lib/js-api/package.json @@ -20,6 +20,7 @@ "tslib": "^2.6.1" }, "typings": "./typings/index.d.ts", + "types": "./typings/index.d.ts", "module": "./esm5/index.js", "es2015": "./esm2015/index.js" } diff --git a/lib/process-services-cloud/.eslintignore b/lib/process-services-cloud/.eslintignore index 4ebc8aea50..16523ff94f 100644 --- a/lib/process-services-cloud/.eslintignore +++ b/lib/process-services-cloud/.eslintignore @@ -1 +1,2 @@ +.storybook coverage diff --git a/lib/process-services-cloud/.eslintrc.json b/lib/process-services-cloud/.eslintrc.json index 1547f99639..8959afd373 100644 --- a/lib/process-services-cloud/.eslintrc.json +++ b/lib/process-services-cloud/.eslintrc.json @@ -6,7 +6,7 @@ "files": ["*.ts"], "extends": ["plugin:@nx/angular"], "parserOptions": { - "project": ["lib/process-services-cloud/tsconfig.lib.json", "lib/process-services-cloud/tsconfig.spec.json"], + "project": ["lib/process-services-cloud/tsconfig.lib.json", "lib/process-services-cloud/tsconfig.spec.json", "lib/process-services-cloud/.storybook/tsconfig.json"], "createDefaultProgram": true }, "rules": { diff --git a/lib/process-services-cloud/.storybook/main.ts b/lib/process-services-cloud/.storybook/main.ts new file mode 100644 index 0000000000..a378293848 --- /dev/null +++ b/lib/process-services-cloud/.storybook/main.ts @@ -0,0 +1,24 @@ +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import type { StorybookConfig } from '@storybook/angular'; +import rootMain from '../../../.storybook/main'; + +const config: StorybookConfig = { + ...rootMain, + stories: ['../**/*.stories.@(js|jsx|ts|tsx)'], + staticDirs: [ + { from: '../../core/src/lib/i18n', to: 'assets/adf-core/i18n' }, + { from: '../../process-services/src/lib/i18n', to: 'assets/adf-process-services/i18n' }, + { from: '../src/lib/i18n', to: 'assets/adf-process-services-cloud/i18n' } + ], + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + } +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} diff --git a/lib/process-services-cloud/.storybook/preview.ts b/lib/process-services-cloud/.storybook/preview.ts new file mode 100644 index 0000000000..99f6869d95 --- /dev/null +++ b/lib/process-services-cloud/.storybook/preview.ts @@ -0,0 +1,11 @@ +import { type Preview } from '@storybook/angular'; + +const preview: Preview = { + parameters: { + docs: { inlineStories: true }, + controls: { expanded: true } + }, + tags: ['autodocs'] +}; + +export default preview; diff --git a/lib/process-services-cloud/.storybook/tsconfig.json b/lib/process-services-cloud/.storybook/tsconfig.json new file mode 100644 index 0000000000..57100f1b7e --- /dev/null +++ b/lib/process-services-cloud/.storybook/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "moduleResolution": "bundler" + }, + "exclude": ["../**/*.spec.ts", "../**/test.ts", "../**/*.module.ts" ], + "include": ["../src/**/*", "*.ts"] +} diff --git a/lib/process-services-cloud/README.md b/lib/process-services-cloud/README.md index d6312a9401..42e57d9cf7 100644 --- a/lib/process-services-cloud/README.md +++ b/lib/process-services-cloud/README.md @@ -9,6 +9,7 @@ Contains a variety of components, directives and services used throughout ADF - [Documentation](#documentation) - [Prerequisites](#prerequisites) - [Install](#install) +- [Storybook](#storybook) - [License](#license) @@ -33,6 +34,21 @@ necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng npm install @alfresco/adf-process-services-cloud ``` +## Storybook + +In case you would like to aggregate all the stories from process services cloud library use + +``` +nx run process-services-cloud:storybook +``` +And navigate to `http://localhost:4400/`. + +To create a Storybook process services cloud library build use + +``` +nx run process-services-cloud:build-storybook +``` + ## License [Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE) diff --git a/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.stories.ts b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.stories.ts new file mode 100644 index 0000000000..e0b091bbdf --- /dev/null +++ b/lib/process-services-cloud/src/lib/common/date-range-filter/date-range-filter.component.stories.ts @@ -0,0 +1,68 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { provideStoryProcessServicesCloud } from '../../stories/process-services-cloud-story.providers'; +import { mockFilterProperty } from '../mock/date-range-filter.mock'; +import { DateRangeFilterComponent } from './date-range-filter.component'; + +const meta: Meta = { + component: DateRangeFilterComponent, + title: 'Process Services Cloud/Process Common/Date Range Filter', + decorators: [ + moduleMetadata({ + imports: [DateRangeFilterComponent] + }), + applicationConfig({ + providers: [...provideStoryProcessServicesCloud()] + }) + ], + argTypes: { + processFilterProperty: { + control: 'object', + table: { + type: { summary: 'ApplicationInstanceModel' } + } + }, + options: { + control: 'object', + table: { + type: { summary: 'DateCloudFilterType[]' } + } + }, + dateChanged: { + action: 'dateChanged', + table: { category: 'Actions' } + }, + dateTypeChange: { + action: 'dateTypeChange', + table: { category: 'Actions' } + } + }, + args: { + processFilterProperty: mockFilterProperty + } +}; + +export default meta; +type Story = StoryObj; + +export const DateRangeFilter: Story = { + render: (args) => ({ + props: args + }) +}; diff --git a/lib/process-services-cloud/src/lib/flex.scss b/lib/process-services-cloud/src/lib/flex.scss index d82dff54f4..e8d83066f4 100644 --- a/lib/process-services-cloud/src/lib/flex.scss +++ b/lib/process-services-cloud/src/lib/flex.scss @@ -64,19 +64,16 @@ $overlapping-lt: ( @if map.has-key($breakpoints, $bp) { $min: map.get(map.get($breakpoints, $bp), begin); $max: map.get(map.get($breakpoints, $bp), end); - @media (min-width: $min) and (max-width: $max) { @content; } } @else if map.has-key($overlapping-gt, $bp) { $min: map.get($overlapping-gt, $bp); - @media (min-width: $min) { @content; } } @else if map.has-key($overlapping-lt, $bp) { $max: map.get($overlapping-lt, $bp); - @media (max-width: $max) { @content; } diff --git a/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts b/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts index a11c5f8046..2f3a27612e 100644 --- a/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts +++ b/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts @@ -60,7 +60,7 @@ export const cloudFormMock = { id: 'text2', name: 'Text2', type: 'text', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -147,6 +147,7 @@ export const cloudFormMock = { overrideId: false, name: 'Number1', type: 'integer', + value: null, colspan: 1, placeholder: null, readOnly: true, @@ -240,7 +241,7 @@ export const cloudFormMock = { id: 'dropdown1', name: 'Dropdown1', type: 'dropdown', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -267,7 +268,7 @@ export const cloudFormMock = { id: 'dropdown2', name: 'Dropdown2', type: 'dropdown', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -304,7 +305,7 @@ export const cloudFormMock = { id: 'amount1', name: 'Amount1', type: 'amount', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -327,7 +328,7 @@ export const cloudFormMock = { id: 'amount2', name: 'Amount2', type: 'amount', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -412,7 +413,7 @@ export const cloudFormMock = { id: 'radiobuttons1', name: 'Radio buttons1', type: 'radio-buttons', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -448,7 +449,7 @@ export const cloudFormMock = { id: 'radiobuttons2', name: 'Radio buttons2', type: 'radio-buttons', - value: null, + value: '', required: false, readOnly: true, overrideId: false, @@ -494,7 +495,7 @@ export const cloudFormMock = { id: 'attachfile1', name: 'Attach file1', type: 'upload', - value: null, + value: [], required: false, readOnly: true, overrideId: false, @@ -519,7 +520,7 @@ export const cloudFormMock = { id: 'attachfile2', name: 'Attach file2', type: 'upload', - value: null, + value: [], required: false, readOnly: true, overrideId: false, @@ -704,7 +705,7 @@ export const fakeCloudForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -723,7 +724,7 @@ export const fakeCloudForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -1076,7 +1077,7 @@ export const fakeMetadataForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -1095,7 +1096,7 @@ export const fakeMetadataForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -1263,7 +1264,7 @@ export const fakeMetadataForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -1282,7 +1283,7 @@ export const fakeMetadataForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, @@ -1301,7 +1302,7 @@ export const fakeMetadataForm = { }, visibilityCondition: null, placeholder: null, - value: null, + value: '', required: false, minLength: 0, maxLength: 0, diff --git a/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts b/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts new file mode 100644 index 0000000000..d85861f67b --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/mocks/form-cloud.service.mock.ts @@ -0,0 +1,105 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FormFieldOption, FormModel, FormValues } from '@alfresco/adf-core'; +import { UploadApi } from '@alfresco/js-api'; +import { Observable, of, throwError } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; +import { FormContent } from '../../services/form-fields.interfaces'; +import { TaskDetailsCloudModel } from '../../task/public-api'; +import { taskDetailsContainer } from '../../task/task-header/mocks/task-details-cloud.mock'; +import { fakeCloudForm } from '../mocks/cloud-form.mock'; +import { TaskVariableCloud } from '../models/task-variable-cloud.model'; +import { FormCloudServiceInterface } from '../services/form-cloud.service.interface'; + +export class FormCloudServiceMock implements FormCloudServiceInterface { + uploadApi: UploadApi; + + getTaskForm(appName: string, taskId: string, version?: number): Observable { + if (appName === 'invalid-app') { + return throwError(() => new Error('App Name not configured')); + } + return this.getTask(appName, taskId).pipe( + switchMap((task) => + this.getForm(appName, task.formKey, version).pipe( + map((form: FormContent) => { + const flattenForm = { + ...form.formRepresentation, + ...form.formRepresentation.formDefinition, + taskId: task.id, + taskName: task.name, + processDefinitionId: task.processDefinitionId, + processInstanceId: task.processInstanceId + }; + delete flattenForm.formDefinition; + return flattenForm; + }) + ) + ) + ); + } + + getTask(_appName: string, taskId: string): Observable { + return of(taskDetailsContainer[taskId]); + } + + getForm(_appName: string, _formKey: string, _version?: number): Observable { + return of(fakeCloudForm); + } + + getTaskVariables(_appName: string, _taskId: string): Observable { + return of([new TaskVariableCloud({ name: 'name1', value: 5, type: 'text', id: '52' })]); + } + + saveTaskForm( + _appName: string, + taskId: string, + _processInstanceId: string, + _formId: string, + _values: FormValues + ): Observable { + return of(taskDetailsContainer[taskId]); + } + + completeTaskForm( + _appName: string, + taskId: string, + _processInstanceId: string, + _formId: string, + _formValues: FormValues, + _outcome: string, + _version: number + ): Observable { + return of(taskDetailsContainer[taskId]); + } + + createTemporaryRawRelatedContent(_file: any, _nodeId: string, _contentHost: string): Observable { + throw new Error('Method not implemented.'); + } + + getDropDownJsonData(_url: string): Observable { + throw new Error('Method not implemented.'); + } + + parseForm(_json: any, _data?: TaskVariableCloud[], _readOnly: boolean = false): FormModel { + throw new Error('Method not implemented.'); + } + + getRestWidgetData(_formName: string, _widgetId: string, _body: Map): Observable { + throw new Error('Method not implemented.'); + } +} diff --git a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.stories.ts new file mode 100644 index 0000000000..3ed2fb5c45 --- /dev/null +++ b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.stories.ts @@ -0,0 +1,194 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { GroupCloudComponent } from './group-cloud.component'; +import { provideStoryProcessServicesCloud } from '../../stories/process-services-cloud-story.providers'; +import { IdentityGroupService } from '../services/identity-group.service'; +import { IdentityGroupServiceMock, mockFoodGroups, mockMeatChicken, mockVegetableAubergine } from '../mock/group-cloud.mock'; + +const meta: Meta = { + component: GroupCloudComponent, + title: 'Process Services Cloud/Group Cloud/Group Cloud', + decorators: [ + moduleMetadata({ + imports: [GroupCloudComponent] + }), + applicationConfig({ + providers: [{ provide: IdentityGroupService, useClass: IdentityGroupServiceMock }, ...provideStoryProcessServicesCloud()] + }) + ], + argTypes: { + appName: { + control: 'text', + description: 'Name of the application. If specified this shows the groups who have access to the app.', + table: { + type: { summary: 'string' } + } + }, + title: { + control: 'text', + description: 'Title of the field.', + table: { + type: { summary: 'string' } + } + }, + mode: { + control: 'radio', + options: ['single', 'multiple'], + description: 'Group selection mode.', + table: { + type: { summary: 'ComponentSelectionMode' }, + defaultValue: { summary: 'single' } + } + }, + preSelectGroups: { + control: 'object', + description: + 'Array of groups to be pre-selected. This pre-selects all groups in multi selection mode and only the first group of the array in single selection mode.', + table: { + type: { summary: 'IdentityGroupModel[]' }, + defaultValue: { summary: '[]' } + } + }, + validate: { + control: 'boolean', + description: + 'This flag enables the validation on the preSelectGroups passed as input.\n\n' + + 'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n' + + 'Otherwise, no check will be done.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + readOnly: { + control: 'boolean', + description: 'Show the info in readonly mode.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + required: { + control: 'boolean', + description: 'Mark this field as required.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + groupChipsCtrl: { + control: 'object', + description: 'FormControl to list of group.', + table: { + type: { summary: 'FormControl' }, + defaultValue: { summary: "new FormControl({ value: '', disabled: false })" }, + category: 'Form Controls' + } + }, + searchGroupsControl: { + control: 'object', + description: 'FormControl to search the group.', + table: { + type: { summary: 'FormControl' }, + defaultValue: { summary: "new FormControl({ value: '', disabled: false })" }, + category: 'Form Controls' + } + }, + roles: { + control: 'object', + description: 'Role names of the groups to be listed.', + table: { + type: { summary: 'string[]' }, + defaultValue: { summary: '[]' } + } + }, + selectGroup: { + action: 'selectGroup', + description: 'Emitted when a group is selected.', + table: { category: 'Actions' } + }, + removeGroup: { + action: 'removeGroup', + description: 'Emitted when a group is removed.', + table: { category: 'Actions' } + }, + changedGroups: { + action: 'changedGroups', + description: 'Emitted when a group selection changes.', + table: { category: 'Actions' } + }, + warning: { + action: 'warning', + description: 'Emitted when an warning occurs.', + table: { category: 'Actions' } + } + }, + args: { + appName: 'app', + title: 'Groups', + mode: 'single', + preSelectGroups: [], + validate: false, + readOnly: false, + required: false, + roles: [] + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultGroupCloud: Story = { + render: (args) => ({ + props: args + }) +}; + +export const ValidPreselectedGroups: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectGroups: mockFoodGroups + } +}; + +export const MandatoryPreselectedGroups: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectGroups: [mockVegetableAubergine, { ...mockMeatChicken, readonly: true }] + } +}; + +export const InvalidPreselectedGroups: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectGroups: [{ id: 'invalid-group', name: 'Invalid Group' }] + } +}; diff --git a/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts b/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts index 4bb86ed895..cfc2cec541 100644 --- a/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/group/mock/group-cloud.mock.ts @@ -15,9 +15,23 @@ * limitations under the License. */ +import { Injectable } from '@angular/core'; +import { Observable, EMPTY, of } from 'rxjs'; import { IdentityGroupModel } from '../models/identity-group.model'; +import { IdentityGroupService } from '@alfresco/adf-process-services-cloud'; export const mockVegetableAubergine: IdentityGroupModel = { id: 'aubergine', name: 'Vegetable Aubergine' }; export const mockMeatChicken: IdentityGroupModel = { id: 'chicken', name: 'Meat Chicken' }; export const mockFoodGroups = [mockVegetableAubergine, mockMeatChicken]; + +@Injectable() +export class IdentityGroupServiceMock extends IdentityGroupService { + search(name: string): Observable { + if (name.trim() === '') { + return EMPTY; + } + + return of(mockFoodGroups.filter((group) => group.name.toUpperCase().includes(name.toUpperCase()))); + } +} diff --git a/lib/process-services-cloud/src/lib/people/components/people-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/people/components/people-cloud.component.stories.ts new file mode 100644 index 0000000000..7cb1e171bc --- /dev/null +++ b/lib/process-services-cloud/src/lib/people/components/people-cloud.component.stories.ts @@ -0,0 +1,238 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { PeopleCloudComponent } from './people-cloud.component'; +import { provideStoryProcessServicesCloud } from '../../stories/process-services-cloud-story.providers'; +import { IdentityUserService } from '../services/identity-user.service'; +import { IdentityUserServiceMock, mockFoodUsers, mockKielbasaSausage, mockShepherdsPie, mockYorkshirePudding } from '../mock/people-cloud.mock'; + +const meta: Meta = { + component: PeopleCloudComponent, + title: 'Process Services Cloud/People Cloud/People Cloud', + decorators: [ + moduleMetadata({ + imports: [PeopleCloudComponent] + }), + applicationConfig({ + providers: [{ provide: IdentityUserService, useClass: IdentityUserServiceMock }, ...provideStoryProcessServicesCloud()] + }) + ], + argTypes: { + appName: { + control: 'text', + description: 'Name of the application. If specified, this shows the users who have access to the app.', + table: { + type: { summary: 'string' } + } + }, + mode: { + control: 'radio', + options: ['single', 'multiple'], + description: 'User selection mode.', + table: { + type: { summary: 'ComponentSelectionMode' }, + defaultValue: { summary: 'single' } + } + }, + roles: { + control: 'object', + description: 'Role names of the users to be listed.', + table: { + type: { summary: 'string[]' }, + defaultValue: { summary: '[]' } + } + }, + validate: { + control: 'boolean', + description: + 'This flag enables the validation on the preSelectUsers passed as input.\n\n' + + 'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n' + + 'Otherwise, no check will be done.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + readOnly: { + control: 'boolean', + description: 'Show the info in readonly mode.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + required: { + control: 'boolean', + description: 'Mark this field as required.', + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + preSelectUsers: { + control: 'object', + description: + 'Array of users to be pre-selected. All users in the array are pre-selected in multi selection mode, but only the first user is pre-selected in single selection mode. Mandatory properties are: id, email, username', + table: { + type: { summary: 'IdentityUserModel[]' }, + defaultValue: { summary: '[]' } + } + }, + excludedUsers: { + control: 'object', + description: 'Array of users to be excluded. Mandatory properties are: id, email, username', + table: { + type: { summary: 'IdentityUserModel[]' }, + defaultValue: { summary: '[]' } + } + }, + groupsRestriction: { + control: 'object', + description: 'Array of groups to restrict user searches. Mandatory property is group name', + table: { + type: { summary: 'string[]' }, + defaultValue: { summary: '[]' } + } + }, + userChipsCtrl: { + control: 'object', + description: 'FormControl to list of users.', + table: { + type: { summary: 'FormControl' }, + defaultValue: { summary: "new FormControl({ value: '', disabled: false })" }, + category: 'Form Controls' + } + }, + searchUserCtrl: { + control: 'object', + description: 'FormControl to search the user.', + table: { + type: { summary: 'FormControl' }, + defaultValue: { summary: "new FormControl({ value: '', disabled: false })" }, + category: 'Form Controls' + } + }, + title: { + control: 'text', + description: 'Title of the field.', + table: { + type: { summary: 'string' } + } + }, + selectUser: { + action: 'selectUser', + description: 'Emitted when a user is selected.', + table: { category: 'Actions' } + }, + removeUser: { + action: 'removeUser', + description: 'Emitted when a selected user is removed in multi selection mode.', + table: { category: 'Actions' } + }, + changedUsers: { + action: 'changedUsers', + description: 'Emitted when a user selection changes.', + table: { category: 'Actions' } + }, + warning: { + action: 'warning', + description: 'Emitted when an warning occurs.', + table: { category: 'Actions' } + } + }, + args: { + appName: 'app', + mode: 'single', + roles: [], + validate: false, + readOnly: false, + required: false, + preSelectUsers: [], + excludedUsers: [], + groupsRestriction: [] + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultPeopleCloud: Story = { + render: (args) => ({ + props: args + }) +}; + +export const ValidPreselectedUsers: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectUsers: mockFoodUsers + } +}; + +export const MandatoryPreselectedUsers: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectUsers: [{ ...mockKielbasaSausage, readonly: true }, mockShepherdsPie] + } +}; + +export const InvalidPreselectedUsers: Story = { + render: (args) => ({ + props: args + }), + args: { + validate: true, + mode: 'multiple', + preSelectUsers: [{ id: 'invalid-user', username: 'Invalid User', firstName: 'Invalid', lastName: 'User', email: 'invalid@xyz.com' }] + } +}; + +export const ExcludedUsers: Story = { + render: (args) => ({ + props: args + }), + args: { + excludedUsers: [mockKielbasaSausage, mockYorkshirePudding] + } +}; + +export const NoUsers: Story = { + render: (args) => ({ + props: args + }), + args: { + excludedUsers: mockFoodUsers + } +}; + +export const InvalidOrEmptyAppName: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: null + } +}; diff --git a/lib/process-services-cloud/src/lib/process/mock/process-cloud.service.mock.ts b/lib/process-services-cloud/src/lib/process/mock/process-cloud.service.mock.ts new file mode 100644 index 0000000000..a9e63c1868 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/mock/process-cloud.service.mock.ts @@ -0,0 +1,67 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Observable, of, Subject, throwError } from 'rxjs'; +import { ProcessInstanceCloud } from '../start-process/models/process-instance-cloud.model'; +import { ProcessDefinitionCloud } from '../../models/process-definition-cloud.model'; +import { ApplicationVersionModel } from '../../models/application-version.model'; +import { processInstancePlaceholdersCloudMock, processInstanceDetailsCloudMock } from './process-instance-details-cloud.mock'; +import { fakeProcessDefinitions } from '../start-process/mock/start-process.component.mock'; +import { mockAppVersions } from '../process-filters/mock/process-filters-cloud.mock'; +import { ProcessCloudService } from '../services/process-cloud.service'; + +@Injectable() +export class ProcessCloudServiceMock extends ProcessCloudService { + dataChangesDetected = new Subject(); + + getProcessInstanceById(appName: string, processInstanceId: string): Observable { + if (appName === 'app-placeholders' && processInstanceId) { + return of(processInstancePlaceholdersCloudMock); + } + + if (appName && processInstanceId) { + return of(processInstanceDetailsCloudMock); + } else { + return throwError(() => 'AppName/ProcessInstanceId not configured'); + } + } + + getProcessDefinitions(appName: string): Observable { + if (appName || appName === '') { + return of(fakeProcessDefinitions); + } else { + return throwError(() => 'AppName not configured'); + } + } + + getApplicationVersions(appName: string): Observable { + if (appName) { + return of(mockAppVersions); + } else { + return throwError(() => 'AppName not configured'); + } + } + + cancelProcess(appName: string, processInstanceId: string): Observable { + if (appName && processInstanceId) { + return of(); + } else { + return throwError(() => 'App name and process id not configured'); + } + } +} diff --git a/lib/process-services-cloud/src/lib/process/mock/process-instance-details-cloud.mock.ts b/lib/process-services-cloud/src/lib/process/mock/process-instance-details-cloud.mock.ts index 6882451342..74364aad17 100644 --- a/lib/process-services-cloud/src/lib/process/mock/process-instance-details-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/process/mock/process-instance-details-cloud.mock.ts @@ -28,3 +28,15 @@ export const processInstanceDetailsCloudMock: ProcessInstanceCloud = { startDate: new Date(1552152187080), status: 'RUNNING' }; + +export const processInstancePlaceholdersCloudMock: ProcessInstanceCloud = { + appName: 'app-placeholders', + businessKey: '', + id: '00fcc4ab-4290-11e9-b133-0a586460016a', + initiator: 'devopsuser', + lastModified: new Date(2022, 1, 1, 1, 30, 40), + name: '', + parentId: '', + startDate: new Date(1552152187080), + status: 'RUNNING' +}; diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.stories.ts new file mode 100644 index 0000000000..80c5b032c5 --- /dev/null +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.stories.ts @@ -0,0 +1,96 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { provideStoryProcessServicesCloud } from '../../../stories/process-services-cloud-story.providers'; +import { ProcessHeaderCloudComponent } from './process-header-cloud.component'; +import { ProcessCloudServiceMock } from '../../mock/process-cloud.service.mock'; +import { ProcessCloudService } from '../../services/process-cloud.service'; + +const meta: Meta = { + component: ProcessHeaderCloudComponent, + title: 'Process Services Cloud/Process Cloud/Process Header Cloud/Process Header Cloud', + decorators: [ + moduleMetadata({ + imports: [ProcessHeaderCloudComponent] + }), + applicationConfig({ + providers: [{ provide: ProcessCloudService, useClass: ProcessCloudServiceMock }, ...provideStoryProcessServicesCloud()] + }) + ], + argTypes: { + appName: { + control: 'text', + description: '(Required) The name of the application.', + defaultValue: '', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '' } + } + }, + processInstanceId: { + control: 'text', + description: '(Required) The id of the process instance.', + table: { + type: { summary: 'string' } + } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultProcessHeaderCloud: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: 'app', + processInstanceId: 'mock-process-id' + } +}; + +export const NoParentAndBusinessAndName: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: 'app-placeholders', + processInstanceId: 'mock-process-id' + } +}; + +export const InvalidOrMissingAppName: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: undefined, + processInstanceId: 'mock-process-id' + } +}; + +export const InvalidOrMissingProcessInstanceID: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: 'app', + processInstanceId: undefined + } +}; diff --git a/lib/process-services-cloud/src/lib/stories/process-services-cloud-story.providers.ts b/lib/process-services-cloud/src/lib/stories/process-services-cloud-story.providers.ts new file mode 100644 index 0000000000..43cf0c4591 --- /dev/null +++ b/lib/process-services-cloud/src/lib/stories/process-services-cloud-story.providers.ts @@ -0,0 +1,48 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Provider, EnvironmentProviders } from '@angular/core'; +import { provideCoreAuth, provideAppConfig, provideI18N } from '@alfresco/adf-core'; +import { provideCloudFormRenderer, provideCloudPreferences } from '../providers'; +import { TASK_LIST_CLOUD_TOKEN } from '../services/cloud-token.service'; +import { TaskListCloudService } from '../task/task-list/services/task-list-cloud.service'; +import { provideAnimations } from '@angular/platform-browser/animations'; +import { provideRouter, withHashLocation } from '@angular/router'; + +/** + * Provides the providers for the process services cloud story. + * + * @returns An array of providers for the process services cloud story. + */ +export function provideStoryProcessServicesCloud(): (Provider | EnvironmentProviders)[] { + return [ + provideI18N({ + assets: [ + ['adf-core', 'assets/adf-core'], + ['adf-process-services', 'assets/adf-process-services'], + ['adf-process-services-cloud', 'assets/adf-process-services-cloud'] + ] + }), + provideAppConfig(), + provideCoreAuth(), + provideCloudPreferences(), + provideCloudFormRenderer(), + provideAnimations(), + { provide: TASK_LIST_CLOUD_TOKEN, useClass: TaskListCloudService }, + provideRouter([], withHashLocation()) + ]; +} diff --git a/lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts b/lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts new file mode 100644 index 0000000000..029b1d73c5 --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/mock/task-cloud.service.mock.ts @@ -0,0 +1,70 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Observable, of, Subject } from 'rxjs'; +import { TaskDetailsCloudModel, TASK_ASSIGNED_STATE, TASK_CREATED_STATE } from '../models/task-details-cloud.model'; +import { taskDetailsContainer } from '../task-header/mocks/task-details-cloud.mock'; +import { TaskCloudService } from '../services/task-cloud.service'; +import { AdfHttpClient } from '@alfresco/adf-core/api'; + +@Injectable() +export class TaskCloudServiceMock extends TaskCloudService { + currentUserMock = 'AssignedTaskUser'; + dataChangesDetected$ = new Subject(); + + constructor(adfHttpClient: AdfHttpClient) { + super(adfHttpClient); + } + + getTaskById(_appName: string, taskId: string): Observable { + return of(taskDetailsContainer[taskId]); + } + + getCandidateUsers(_appName: string, taskId: string): Observable { + if (taskId === 'mock-no-candidate-users') { + return of([]); + } + + return of(['user1', 'user2']); + } + + getCandidateGroups(_appName: string, taskId: string): Observable { + if (taskId === 'mock-no-candidate-groups') { + return of([]); + } + + return of(['group1', 'group2']); + } + + updateTask(_appName: string, taskId: string): Observable { + return of(taskDetailsContainer[taskId]); + } + + canClaimTask(taskDetails: TaskDetailsCloudModel): boolean { + return taskDetails?.status === TASK_CREATED_STATE; + } + + protected isAssignedToMe(assignee: string): boolean { + return assignee === this.currentUserMock; + } + + canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean { + const currentUser = this.currentUserMock; + return taskDetails?.status === TASK_ASSIGNED_STATE && taskDetails.assignee === currentUser; + } +} diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud/task-form-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud/task-form-cloud.component.stories.ts new file mode 100644 index 0000000000..9e42d0fa0f --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud/task-form-cloud.component.stories.ts @@ -0,0 +1,220 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { applicationConfig, Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { FormCloudService } from '../../../../form/public-api'; +import { TaskCloudService } from '../../../services/task-cloud.service'; +import { TaskFormCloudComponent } from './task-form-cloud.component'; +import { TaskCloudServiceMock } from '../../../mock/task-cloud.service.mock'; +import { FormCloudServiceMock } from '../../../../form/mocks/form-cloud.service.mock'; +import { provideStoryProcessServicesCloud } from '../../../../stories/process-services-cloud-story.providers'; +import { taskWithFormDetailsMock } from '../../../task-header/mocks/task-details-cloud.mock'; + +const meta: Meta = { + component: TaskFormCloudComponent, + title: 'Process Services Cloud/Task Cloud/Task Form/Task Form Cloud', + decorators: [ + moduleMetadata({ + imports: [TaskFormCloudComponent], + providers: [ + { provide: TaskCloudService, useClass: TaskCloudServiceMock }, + { provide: FormCloudService, useClass: FormCloudServiceMock } + ] + }), + applicationConfig({ + providers: [...provideStoryProcessServicesCloud()] + }) + ], + argTypes: { + appName: { + control: 'text', + description: 'App id to fetch corresponding form and values.', + defaultValue: '', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '' } + } + }, + taskId: { + control: 'text', + description: 'Task id to fetch corresponding form and values.', + table: { + type: { summary: 'string' } + } + }, + showTitle: { + control: 'boolean', + description: 'Toggle rendering of the form title.', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showRefreshButton: { + control: 'boolean', + description: 'Toggle rendering of the `Refresh` button.', + defaultValue: false, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + showValidationIcon: { + control: 'boolean', + description: 'Toggle rendering of the `Validation` icon.', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showCancelButton: { + control: 'boolean', + description: 'Toggle rendering of the `Cancel` button.', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + showCompleteButton: { + control: 'boolean', + description: 'Toggle rendering of the `Complete` button.', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + readOnly: { + control: 'boolean', + description: 'Toggle readonly state of the task.', + defaultValue: false, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'false' } + } + }, + taskDetails: { + control: 'object', + description: 'Task details.', + table: { + type: { summary: 'TaskDetailsCloudModel' } + } + }, + displayModeConfigurations: { + control: 'object', + description: 'The available display configurations for the form.', + table: { + type: { summary: 'FormCloudDisplayModeConfiguration[]' } + } + }, + formSaved: { + action: 'formSaved', + description: 'Emitted when the form is saved.', + table: { category: 'Actions' } + }, + formCompleted: { + action: 'formCompleted', + description: 'Emitted when the form is submitted with the `Complete` outcome.', + table: { category: 'Actions' } + }, + taskCompleted: { + action: 'taskCompleted', + description: 'Emitted when the task is completed.', + table: { category: 'Actions' } + }, + taskClaimed: { + action: 'taskClaimed', + description: 'Emitted when the task is claimed.', + table: { category: 'Actions' } + }, + taskUnclaimed: { + action: 'taskUnclaimed', + description: 'Emitted when the task is unclaimed.', + table: { category: 'Actions' } + }, + candidateUsers: { + control: 'object', + description: 'Candidate users.', + table: { + type: { summary: 'string[]' }, + defaultValue: { summary: '[]' } + } + }, + candidateGroups: { + control: 'object', + description: 'Candidate groups.', + table: { + type: { summary: 'string[]' }, + defaultValue: { summary: '[]' } + } + }, + cancelClick: { + action: 'cancelClick', + description: 'Emitted when the cancel button is clicked.', + table: { category: 'Actions' } + }, + formContentClicked: { + action: 'formContentClicked', + description: 'Emitted when form content is clicked.', + table: { category: 'Actions' } + }, + error: { + action: 'error', + description: 'Emitted when any error occurs.', + table: { category: 'Actions' } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const DefaultTaskFormCloud: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: 'app', + taskId: 'mock-task-with-form', + taskDetails: { ...taskWithFormDetailsMock } + } +}; + +export const InvalidOrMissingApp: Story = { + render: (args) => ({ + props: args + }), + args: { + ...DefaultTaskFormCloud.args, + appName: undefined, + taskDetails: { ...taskWithFormDetailsMock } + } +}; + +export const InvalidOrMissingTaskId: Story = { + render: (args) => ({ + props: args + }), + args: { + ...DefaultTaskFormCloud.args, + taskId: undefined, + taskDetails: { ...taskWithFormDetailsMock } + } +}; diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts new file mode 100644 index 0000000000..861c0365da --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.stories.ts @@ -0,0 +1,170 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Meta, StoryObj, applicationConfig, moduleMetadata } from '@storybook/angular'; +import { TaskHeaderCloudComponent } from './task-header-cloud.component'; +import { TaskCloudService } from '../../services/task-cloud.service'; +import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock'; +import { provideStoryProcessServicesCloud } from '../../../stories/process-services-cloud-story.providers'; + +const meta: Meta = { + component: TaskHeaderCloudComponent, + title: 'Process Services Cloud/Task Cloud/Task Header Cloud/Task Header Cloud', + decorators: [ + applicationConfig({ + providers: [...provideStoryProcessServicesCloud(), { provide: TaskCloudService, useClass: TaskCloudServiceMock }] + }), + moduleMetadata({ + imports: [TaskHeaderCloudComponent] + }) + ], + argTypes: { + appName: { + control: 'text', + description: '(Required) The name of the application.', + defaultValue: '', + table: { + type: { summary: 'string' }, + defaultValue: { summary: '' } + } + }, + taskId: { + control: 'text', + description: '(Required) The id of the task.', + table: { + type: { summary: 'string' } + } + }, + showTitle: { + control: 'boolean', + description: 'Show/Hide the task title.', + defaultValue: true, + table: { + type: { summary: 'boolean' }, + defaultValue: { summary: 'true' } + } + }, + claim: { + action: 'claim', + description: 'Emitted when the task is claimed.', + table: { category: 'Actions' } + }, + unclaim: { + action: 'unclaim', + description: 'Emitted when the task is unclaimed (ie, requeued).', + table: { category: 'Actions' } + }, + error: { + action: 'error', + description: 'Emitted when the given task has errors.', + table: { category: 'Actions' } + } + } +}; + +export default meta; +type Story = StoryObj; + +export const AssignedAndEditable: Story = { + render: (args) => ({ + props: args + }), + args: { + appName: 'app', + taskId: 'mock-assigned-task' + } +}; + +export const CompletedAndReadonly: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-completed-task' + } +}; + +export const Suspended: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-suspended-task' + } +}; + +export const WithParentId: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-parent-task-id' + } +}; + +export const WithoutAssignee: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-created-task' + } +}; + +export const NotClaimableByUser: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-no-candidate-users' + } +}; + +export const TaskNotClaimableByGroupUser: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: 'mock-no-candidate-groups' + } +}; + +export const InvalidForMissingApp: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + appName: undefined + } +}; + +export const InvalidForMissingTaskId: Story = { + render: (args) => ({ + props: args + }), + args: { + ...AssignedAndEditable.args, + taskId: undefined + } +}; diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index fdad7490f1..46e9c6c55b 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -130,8 +130,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnChanges { .subscribe( ([taskDetails, candidateUsers, candidateGroups]) => { this.taskDetails = taskDetails; - this.candidateGroups = candidateGroups.map((user) => ({ icon: 'group', value: user } as CardViewArrayItem)); - this.candidateUsers = candidateUsers.map((group) => ({ icon: 'person', value: group } as CardViewArrayItem)); + this.candidateGroups = candidateGroups.map((user) => ({ icon: 'group', value: user }) as CardViewArrayItem); + this.candidateUsers = candidateUsers.map((group) => ({ icon: 'person', value: group }) as CardViewArrayItem); this.processInstanceId = taskDetails.processInstanceId; if (this.taskDetails.parentTaskId) { this.loadParentName(`${this.taskDetails.parentTaskId}`); diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts index 0f780b271f..6e5f73724d 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts @@ -180,3 +180,80 @@ export const suspendedTaskDetailsCloudMock: TaskDetailsCloudModel = { lastModifiedTo: null, lastModifiedFrom: null }; + +export const noCandidateUsersTaskDetailsCloudMock: TaskDetailsCloudModel = { + appName: 'mock-app-name', + appVersion: 1, + id: 'mock-task-id', + assignee: '', + name: 'This is a new task', + description: 'This is the description ', + createdDate: new Date(1545048055900), + dueDate: new Date(1545091200000), + claimedDate: null, + priority: 5, + category: null, + processDefinitionId: null, + processInstanceId: null, + status: 'CREATED', + owner: 'ownerUser', + candidateUsers: null, + parentTaskId: null, + formKey: null, + lastModified: new Date(1545048055900), + lastModifiedTo: null, + lastModifiedFrom: null, + standalone: false +}; + +export const noCandidateGroupsTaskDetailsCloudMock: TaskDetailsCloudModel = { + appName: 'mock-app-name', + appVersion: 1, + id: 'mock-task-id', + assignee: '', + name: 'This is a new task', + description: 'This is the description ', + createdDate: new Date(1545048055900), + dueDate: new Date(1545091200000), + claimedDate: null, + priority: 5, + category: null, + processDefinitionId: null, + processInstanceId: null, + status: 'CREATED', + owner: 'ownerUser', + candidateGroups: null, + parentTaskId: null, + formKey: null, + lastModified: new Date(1545048055900), + lastModifiedTo: null, + lastModifiedFrom: null, + standalone: false +}; + +export const taskWithFormDetailsMock: TaskDetailsCloudModel = { + appName: 'mock-app-name', + assignee: 'AssignedTaskUser', + completedDate: null, + createdDate: new Date(1555419255340), + dueDate: new Date(1558419255340), + description: null, + formKey: '4', + priority: 1, + parentTaskId: 'bd6b1741-6046-11e9-80f0-0a586460040d', + id: 'bd6b1741-6046-11e9-80f0-0a586460040d', + name: 'Task1', + owner: 'fakeAdmin', + status: 'ASSIGNED' +}; + +export const taskDetailsContainer = { + 'mock-assigned-task': assignedTaskDetailsCloudMock, + 'mock-completed-task': completedTaskDetailsCloudMock, + 'mock-created-task': createdStateTaskDetailsCloudMock, + 'mock-parent-task-id': taskDetailsWithParentTaskIdMock, + 'mock-suspended-task': suspendedTaskDetailsCloudMock, + 'mock-no-candidate-users': noCandidateUsersTaskDetailsCloudMock, + 'mock-no-candidate-groups': noCandidateGroupsTaskDetailsCloudMock, + 'mock-task-with-form': taskWithFormDetailsMock +}; diff --git a/lib/process-services-cloud/tsconfig.json b/lib/process-services-cloud/tsconfig.json index 204cc68ba2..93cbd20d23 100644 --- a/lib/process-services-cloud/tsconfig.json +++ b/lib/process-services-cloud/tsconfig.json @@ -11,6 +11,9 @@ }, { "path": "./tsconfig.spec.json" + }, + { + "path": "./.storybook/tsconfig.json" } ], "compilerOptions": { diff --git a/lib/process-services-cloud/tsconfig.lib.json b/lib/process-services-cloud/tsconfig.lib.json index a9878d0d29..b3eca6df41 100644 --- a/lib/process-services-cloud/tsconfig.lib.json +++ b/lib/process-services-cloud/tsconfig.lib.json @@ -18,5 +18,6 @@ "target": "ES2022", "useDefineForClassFields": false }, + "exclude": ["./test.ts", "**/*.spec.ts", "**/*.test.ts", "**/*.stories.ts", "**/*.mock.ts"], "include": ["src/**/*.ts", "index.ts"] } diff --git a/lib/stories/.storybook/main.ts b/lib/stories/.storybook/main.ts new file mode 100644 index 0000000000..1962bc6d5d --- /dev/null +++ b/lib/stories/.storybook/main.ts @@ -0,0 +1,36 @@ +import type { StorybookConfig } from '@storybook/angular'; +import rootMain from '../../../.storybook/main'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const config: StorybookConfig = { + ...rootMain, + framework: { + name: getAbsolutePath('@storybook/angular'), + options: {} + }, + stories: ['../../core/**/*.stories.ts', '../../content-services/**/*.stories.ts', '../../process-services-cloud/**/*.stories.ts'], + staticDirs: [ + { from: '../../core/src/lib/i18n', to: 'assets/adf-core/i18n' }, + { from: '../../core/src/lib/assets/images', to: 'assets/images' }, + { from: '../../content-services/src/lib/i18n', to: 'assets/adf-content-services/i18n' }, + { from: '../../process-services/src/lib/i18n', to: 'assets/adf-process-services/i18n' }, + { from: '../../process-services-cloud/src/lib/i18n', to: 'assets/adf-process-services-cloud/i18n' }, + { from: '../../config/app.config.json', to: 'app.config.json' } + ], + addons: ['@storybook/addon-themes'], + webpackFinal: async (config) => { + if (config.performance) { + config.performance.hints = false; + } else { + config.performance = { hints: false }; + } + return config; + } +}; + +export default config; + +function getAbsolutePath(value: string): any { + return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`))); +} diff --git a/lib/stories/.storybook/preview.ts b/lib/stories/.storybook/preview.ts new file mode 100644 index 0000000000..84757659b3 --- /dev/null +++ b/lib/stories/.storybook/preview.ts @@ -0,0 +1,34 @@ +import { type Preview, type AngularRenderer, moduleMetadata } from '@storybook/angular'; +import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; +import { withThemeByClassName } from '@storybook/addon-themes'; + +const preview: Preview = { + parameters: { + docs: { inlineStories: true }, + controls: { expanded: true }, + layout: 'centered' + }, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, + useValue: { + appearance: 'outline' + } + } + ] + }), + withThemeByClassName({ + themes: { + light: 'adf-storybook-light-theme', + dark: 'adf-storybook-dark-theme' + }, + defaultTheme: 'light', + parentSelector: 'html' + }) + ], + tags: ['autodocs'] +}; + +export default preview; diff --git a/lib/stories/.storybook/tsconfig.json b/lib/stories/.storybook/tsconfig.json new file mode 100644 index 0000000000..c927466932 --- /dev/null +++ b/lib/stories/.storybook/tsconfig.json @@ -0,0 +1,41 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "moduleResolution": "bundler" + }, + + "exclude": [ + "../**/*.spec.ts", + "../../core/**/*.spec.ts", + "../../core/**/mocks/**/*.ts", + "../../core/**/mock/**/*", + "../../core/feature-flags/**/*.ts", + "../../core/breadcrumbs/public-api.ts", + "../../core/breadcrumbs/src/index.ts", + "../../core/index.ts", + "../../core/schematics/**/*", + "../../core/shell/**/*", + "../../core/test.ts", + "../../core/src/lib/testing/**/*", + "../../core/src/lib/models/basic-auth.ts", + "../../core/src/lib/models/oauth2.ts", + "../../core/src/lib/services/startup-service-factory.ts", + "../../core/src/lib/card-view/directives/card-view-property-validator.spec.directive.ts", + "../../content-services/**/*.spec.ts", + "../../content-services/**/mock/**/*", + "../../content-services/**/mocks/**/*", + "../../content-services/src/lib/testing/**/*", + "../../content-services/src/lib/content-type/public-api.ts", + "../../content-services/src/lib/folder-directive/folder-edit.directive.ts", + "../../content-services/src/lib/content-metadata/components/content-metadata/mock-data.ts", + "../../content-services/src/test.ts", + "../../process-services-cloud/**/*.spec.ts", + "../../process-services-cloud/**/mocks/**/*", + "../../process-services-cloud/**/mock/**/*", + "../../process-services-cloud/src/lib/testing/**/*", + "../../process-services-cloud/src/test.ts", + "../../../.storybook/main.ts" + ], + "include": ["../src/**/*", "preview.ts", "../../core/**/*", "../../content-services/**/*", "../../process-services-cloud/**/*"] +} diff --git a/lib/stories/README.md b/lib/stories/README.md new file mode 100644 index 0000000000..aae0ee31f6 --- /dev/null +++ b/lib/stories/README.md @@ -0,0 +1,32 @@ +# Alfresco Stories Library + +Contains Storybook stories from **Core**, **Content Services** and **Process Services cloud** libraries to gather them in one place. + + + + + +- [Storybook](#storybook) +- [License](#license) + + + + + +## Storybook + +In case you would like to aggregate all the stories across libraries use +```bash +npm run storybook +``` +And navigate to `http://localhost:4400/`. + +To create a Storybook stories library build use + +```bash +npm run build-storybook +``` + +## License + +[Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE) diff --git a/lib/stories/project.json b/lib/stories/project.json new file mode 100644 index 0000000000..eb2e4d4a50 --- /dev/null +++ b/lib/stories/project.json @@ -0,0 +1,45 @@ +{ + "name": "stories", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "lib/stories", + "projectType": "library", + "targets": { + "storybook": { + "executor": "@storybook/angular:start-storybook", + "options": { + "port": 4400, + "browserTarget": "stories:storybook", + "configDir": "lib/stories/.storybook", + "compodoc": false, + "stylePreprocessorOptions": { + "includePaths": ["lib", "lib/core/src/lib"] + }, + "styles": ["node_modules/cropperjs/dist/cropper.min.css", "node_modules/pdfjs-dist/web/pdf_viewer.css", "lib/stories/src/styles.scss"], + "sourceMap": true + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@storybook/angular:build-storybook", + "options": { + "browserTarget": "stories:build-storybook", + "configDir": "lib/stories/.storybook", + "outputDir": "dist/storybook/stories", + "compodoc": false, + "styles": ["node_modules/cropperjs/dist/cropper.min.css", "node_modules/pdfjs-dist/web/pdf_viewer.css", "lib/stories/src/styles.scss"], + "stylePreprocessorOptions": { + "includePaths": ["lib", "lib/core/src/lib"] + } + }, + "configurations": { + "ci": { + "quiet": true + } + } + } + } +} diff --git a/lib/stories/src/styles.scss b/lib/stories/src/styles.scss new file mode 100644 index 0000000000..e7f388cd0e --- /dev/null +++ b/lib/stories/src/styles.scss @@ -0,0 +1,30 @@ +@use '@angular/material' as mat; +@use 'material-icons/iconfont/material-icons.css' as *; + +html { + color-scheme: light dark; + $font-family: 'Nunito Sans', sans-serif; + + font-family: $font-family; + + @include mat.theme( + ( + color: mat.$yellow-palette, + typography: $font-family, + density: 0 + ) + ); + + &.adf-storybook-light-theme { + color-scheme: light; + } + + &.adf-storybook-dark-theme { + color-scheme: dark; + } + + body { + background: var(--mat-sys-surface); + color: var(--mat-sys-on-surface); + } +} diff --git a/lib/stories/tsconfig.json b/lib/stories/tsconfig.json new file mode 100644 index 0000000000..f14da61cdf --- /dev/null +++ b/lib/stories/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/lib/stories/tsconfig.lib.json b/lib/stories/tsconfig.lib.json new file mode 100644 index 0000000000..98c92af56e --- /dev/null +++ b/lib/stories/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2022", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2022"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": [], + "include": ["**/*.ts"] +} diff --git a/nx.json b/nx.json index 0304728812..54b012420c 100644 --- a/nx.json +++ b/nx.json @@ -25,8 +25,20 @@ }, "namedInputs": { "default": ["{projectRoot}/**/*", "sharedGlobals"], - "sharedGlobals": ["{workspaceRoot}/angular.json", "{workspaceRoot}/e2e/protractor.excludes.json", "{workspaceRoot}/e2e/protractor.conf.js"], - "production": ["default", "!{projectRoot}/**/*.spec.[jt]s", "!{projectRoot}/tsconfig.spec.json", "!{projectRoot}/karma.conf.js"] + "sharedGlobals": [ + "{workspaceRoot}/angular.json", + "{workspaceRoot}/e2e/protractor.excludes.json", + "{workspaceRoot}/e2e/protractor.conf.js" + ], + "production": [ + "default", + "!{projectRoot}/.storybook/**/*", + "!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)", + "!{projectRoot}/**/*.spec.[jt]s", + "!{projectRoot}/tsconfig.spec.json", + "!{projectRoot}/karma.conf.js", + "!{projectRoot}/tsconfig.storybook.json" + ] }, "cacheDirectory": "nxcache", "defaultBase": "develop" diff --git a/package-lock.json b/package-lock.json index cc5d0c13ff..72685ad88e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,12 +56,16 @@ "@angular-eslint/eslint-plugin-template": "19.3.0", "@angular-eslint/template-parser": "19.3.0", "@angular/compiler-cli": "19.2.17", + "@chromatic-com/storybook": "4.1.3", "@nx/angular": "22.1.3", "@nx/eslint-plugin": "22.1.3", "@nx/js": "22.1.3", "@nx/node": "22.1.3", + "@nx/storybook": "20.8.0", "@nx/workspace": "22.1.3", "@schematics/angular": "19.2.7", + "@storybook/addon-themes": "^10.1.11", + "@storybook/angular": "10.1.11", "@types/ejs": "^3.1.5", "@types/jasmine": "4.0.3", "@types/jasminewd2": "~2.0.2", @@ -87,6 +91,7 @@ "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-rxjs": "^5.0.3", + "eslint-plugin-storybook": "10.1.11", "eslint-plugin-unicorn": "^49.0.0", "graphql": "^16.9.0", "husky": "^9.1.7", @@ -116,6 +121,7 @@ "rimraf": "^6.1.2", "sass-loader": "16.0.5", "spdx-license-list": "^6.9.0", + "storybook": "10.1.11", "stylelint": "16.20.0", "stylelint-config-standard-scss": "^13.1.0", "ts-node": "^10.9.2", @@ -132,6 +138,13 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true, + "license": "MIT" + }, "node_modules/@alfresco/eslint-plugin-eslint-angular": { "resolved": "lib/eslint-angular", "link": true @@ -181,6 +194,7 @@ "integrity": "sha512-uIxi6Vzss6+ycljVhkyPUPWa20w8qxJL9lEn0h6+sX/fhM8Djt0FHIuTQjoX58EoMaQ/1jrXaRaGimkbaFcG9A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.1902.19", @@ -301,30 +315,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -335,53 +325,6 @@ "tslib": "^2.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.98.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", - "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1902.19", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1902.19.tgz", @@ -418,6 +361,7 @@ "integrity": "sha512-JbLL+4IMLMBgjLZlnPG4lYDfz4zGrJ/s6Aoon321NJKuw1Kb1k5KpFu9dUY0BqLIe8xPQ2UJBpI+xXdK5MXMHQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", @@ -574,6 +518,7 @@ "integrity": "sha512-SFzQ1bRkNFiOVu+aaz+9INmts7tDUrsHLEr9HmARXr9qk5UmR8prlw39p2u+Bvi6/lCiJ18TZMQQl9mGyr63lg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "2.3.0", "@angular-devkit/architect": "0.1902.19", @@ -654,6 +599,290 @@ } } }, + "node_modules/@angular/build/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", + "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-android-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", + "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", + "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", + "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", + "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", + "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", + "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", + "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", + "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", + "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", + "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", + "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", + "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", + "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", + "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", + "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", + "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular/build/node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular/build/node_modules/rollup": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", + "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.8", + "@rollup/rollup-android-arm64": "4.34.8", + "@rollup/rollup-darwin-arm64": "4.34.8", + "@rollup/rollup-darwin-x64": "4.34.8", + "@rollup/rollup-freebsd-arm64": "4.34.8", + "@rollup/rollup-freebsd-x64": "4.34.8", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", + "@rollup/rollup-linux-arm-musleabihf": "4.34.8", + "@rollup/rollup-linux-arm64-gnu": "4.34.8", + "@rollup/rollup-linux-arm64-musl": "4.34.8", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", + "@rollup/rollup-linux-riscv64-gnu": "4.34.8", + "@rollup/rollup-linux-s390x-gnu": "4.34.8", + "@rollup/rollup-linux-x64-gnu": "4.34.8", + "@rollup/rollup-linux-x64-musl": "4.34.8", + "@rollup/rollup-win32-arm64-msvc": "4.34.8", + "@rollup/rollup-win32-ia32-msvc": "4.34.8", + "@rollup/rollup-win32-x64-msvc": "4.34.8", + "fsevents": "~2.3.2" + } + }, "node_modules/@angular/cdk": { "version": "19.2.19", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.2.19.tgz", @@ -692,6 +921,7 @@ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.17.tgz", "integrity": "sha512-qo8psYASAlDiQ8fAL8i/E2JfWH2nPTpZDKKZxSWvgBVA8o+zUEjYAJu6/k6btnu+4Qcb425T0rmM/zao6EU9Aw==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -2958,6 +3188,56 @@ "@keyv/serialize": "^1.1.1" } }, + "node_modules/@chromatic-com/storybook": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-4.1.3.tgz", + "integrity": "sha512-hc0HO9GAV9pxqDE6fTVOV5KeLpTiCfV8Jrpk5ogKLiIgeq2C+NPjpt74YnrZTjiK8E19fYcMP+2WY9ZtX7zHmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@neoconfetti/react": "^1.0.0", + "chromatic": "^13.3.3", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20.0.0", + "yarn": ">=1.22.18" + }, + "peerDependencies": { + "storybook": "^0.0.0-0 || ^9.0.0 || ^9.1.0-0 || ^9.2.0-0 || ^10.0.0-0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -4187,9 +4467,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -4440,7 +4720,7 @@ "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" + "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" @@ -6746,9 +7026,6 @@ }, "react": { "optional": true - }, - "react-dom": { - "optional": true } } }, @@ -7497,6 +7774,13 @@ "@tybys/wasm-util": "^0.10.1" } }, + "node_modules/@neoconfetti/react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@neoconfetti/react/-/react-1.0.0.tgz", + "integrity": "sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==", + "dev": true, + "license": "MIT" + }, "node_modules/@ngtools/webpack": { "version": "19.2.19", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.2.19.tgz", @@ -7858,6 +8142,664 @@ "node": ">=10.0.0" } }, + "node_modules/@nx/cypress": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-20.8.0.tgz", + "integrity": "sha512-tiS9R3X//9ZVeNU9d5uV5voDmrp0Sh+B25EuZoeFtah7RNgQcnNXqc488dmCYhCK5Tl58K44eDNyyXvIwOlyCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.8.0", + "@nx/eslint": "20.8.0", + "@nx/js": "20.8.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "detect-port": "^1.5.1", + "semver": "^7.6.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "cypress": ">= 3 < 15" + }, + "peerDependenciesMeta": { + "cypress": { + "optional": true + } + } + }, + "node_modules/@nx/cypress/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/devkit": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.8.0.tgz", + "integrity": "sha512-0616zW0Krwb5frNZ7C0HUItonCDiAHY9UYSTyJm6hnal0Xc6XkJuEAFNjbx2sEOopO85CEAMNeYEHkRyWsSxCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 19 <= 21" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/eslint": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.8.0.tgz", + "integrity": "sha512-FPpw/RHgg08gkhntf/d7xh8GtNKOjTzLrwh7/YUO5UTi26lCjglM0nsFJJEQS988STElgjBEeDh78wcMuXeQ7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.8.0", + "@nx/js": "20.8.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.7.2" + }, + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } + } + }, + "node_modules/@nx/cypress/node_modules/@nx/js": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.8.0.tgz", + "integrity": "sha512-JqQ94l0njkoCCIeqRzFsajMoSV5WodfGGG3giipBe9+cmqsMCZJxh7DiSTGCZ2vnUo3zoX8hodumlk8r+HtMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nx/devkit": "20.8.0", + "@nx/workspace": "20.8.0", + "@zkochan/js-yaml": "0.0.7", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "picocolors": "^1.1.0", + "picomatch": "4.0.2", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "tinyglobby": "^0.2.12", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^6.0.5" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-darwin-arm64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.8.0.tgz", + "integrity": "sha512-A6Te2KlINtcOo/depXJzPyjbk9E0cmgbom/sm/49XdQ8G94aDfyIIY1RIdwmDCK5NVd74KFG3JIByTk5+VnAhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-darwin-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.8.0.tgz", + "integrity": "sha512-UpqayUjgalArXaDvOoshqSelTrEp42cGDsZGy0sqpxwBpm3oPQ8wE1d7oBAmRo208rAxOuFP0LZRFUqRrwGvLA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-freebsd-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.8.0.tgz", + "integrity": "sha512-dUR2fsLyKZYMHByvjy2zvmdMbsdXAiP+6uTlIAuu8eHMZ2FPQCAtt7lPYLwOFUxUXChbek2AJ+uCI0gRAgK/eg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.8.0.tgz", + "integrity": "sha512-GuZ7t0SzSX5ksLYva7koKZovQ5h/Kr1pFbOsQcBf3VLREBqFPSz6t7CVYpsIsMhiu/I3EKq6FZI3wDOJbee5uw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.8.0.tgz", + "integrity": "sha512-CiI955Q+XZmBBZ7cQqQg0MhGEFwZIgSpJnjPfWBt3iOYP8aE6nZpNOkmD7O8XcN/nEwwyeCOF8euXqEStwsk8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-linux-arm64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.8.0.tgz", + "integrity": "sha512-Iy9DpvVisxsfNh4gOinmMQ4cLWdBlgvt1wmry1UwvcXg479p1oJQ1Kp1wksUZoWYqrAG8VPZUmkE0f7gjyHTGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-linux-x64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.8.0.tgz", + "integrity": "sha512-kZrrXXzVSbqwmdTmQ9xL4Jhi0/FSLrePSxYCL9oOM3Rsj0lmo/aC9kz4NBv1ZzuqT7fumpBOnhqiL1QyhOWOeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-linux-x64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.8.0.tgz", + "integrity": "sha512-0l9jEMN8NhULKYCFiDF7QVpMMNG40duya+OF8dH0OzFj52N0zTsvsgLY72TIhslCB/cC74oAzsmWEIiFslscnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.8.0.tgz", + "integrity": "sha512-5miZJmRSwx1jybBsiB3NGocXL9TxGdT2D+dOqR2fsLklpGz0ItEWm8+i8lhDjgOdAr2nFcuQUfQMY57f9FOHrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/nx-win32-x64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.8.0.tgz", + "integrity": "sha512-0P5r+bDuSNvoWys+6C1/KqGpYlqwSHpigCcyRzR62iZpT3OooZv+nWO06RlURkxMR8LNvYXTSSLvoLkjxqM8uQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/cypress/node_modules/@nx/workspace": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.8.0.tgz", + "integrity": "sha512-FdaHA5ISHSN+RyHswAAx+2A9HC77kWeFgeucdX2NSBs2QK2Lzg2Et639RzR1sYk2gYTP6tOkQXHHGKcg3jmiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.8.0", + "@zkochan/js-yaml": "0.0.7", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "20.8.0", + "picomatch": "4.0.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/cypress/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@nx/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@nx/cypress/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nx/cypress/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/cypress/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/cypress/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/cypress/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/cypress/node_modules/nx": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.8.0.tgz", + "integrity": "sha512-+BN5B5DFBB5WswD8flDDTnr4/bf1VTySXOv60aUAllHqR+KS6deT0p70TTMZF4/A2n/L2UCWDaDro37MGaYozA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.2", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.8.3", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "resolve.exports": "2.0.3", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yaml": "^2.6.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "20.8.0", + "@nx/nx-darwin-x64": "20.8.0", + "@nx/nx-freebsd-x64": "20.8.0", + "@nx/nx-linux-arm-gnueabihf": "20.8.0", + "@nx/nx-linux-arm64-gnu": "20.8.0", + "@nx/nx-linux-arm64-musl": "20.8.0", + "@nx/nx-linux-x64-gnu": "20.8.0", + "@nx/nx-linux-x64-musl": "20.8.0", + "@nx/nx-win32-arm64-msvc": "20.8.0", + "@nx/nx-win32-x64-msvc": "20.8.0" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/cypress/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/cypress/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/cypress/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@nx/cypress/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@nx/cypress/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@nx/cypress/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/cypress/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@nx/cypress/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nx/cypress/node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@nx/devkit": { "version": "22.1.3", "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.1.3.tgz", @@ -8382,6 +9324,656 @@ "dev": true, "license": "MIT" }, + "node_modules/@nx/storybook": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/storybook/-/storybook-20.8.0.tgz", + "integrity": "sha512-czGPlYdukeR4ThhwuUSWQI889aVJrW/bxhAY7BInBJGK56UFnBt1Galnw2um2TzQErN21eS2pRELwyyFeP6/OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/cypress": "20.8.0", + "@nx/devkit": "20.8.0", + "@nx/eslint": "20.8.0", + "@nx/js": "20.8.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "semver": "^7.5.3", + "tslib": "^2.3.0" + } + }, + "node_modules/@nx/storybook/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/devkit": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.8.0.tgz", + "integrity": "sha512-0616zW0Krwb5frNZ7C0HUItonCDiAHY9UYSTyJm6hnal0Xc6XkJuEAFNjbx2sEOopO85CEAMNeYEHkRyWsSxCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 19 <= 21" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/eslint": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.8.0.tgz", + "integrity": "sha512-FPpw/RHgg08gkhntf/d7xh8GtNKOjTzLrwh7/YUO5UTi26lCjglM0nsFJJEQS988STElgjBEeDh78wcMuXeQ7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.8.0", + "@nx/js": "20.8.0", + "semver": "^7.5.3", + "tslib": "^2.3.0", + "typescript": "~5.7.2" + }, + "peerDependencies": { + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } + } + }, + "node_modules/@nx/storybook/node_modules/@nx/js": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.8.0.tgz", + "integrity": "sha512-JqQ94l0njkoCCIeqRzFsajMoSV5WodfGGG3giipBe9+cmqsMCZJxh7DiSTGCZ2vnUo3zoX8hodumlk8r+HtMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nx/devkit": "20.8.0", + "@nx/workspace": "20.8.0", + "@zkochan/js-yaml": "0.0.7", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "picocolors": "^1.1.0", + "picomatch": "4.0.2", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "tinyglobby": "^0.2.12", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^6.0.5" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-darwin-arm64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.8.0.tgz", + "integrity": "sha512-A6Te2KlINtcOo/depXJzPyjbk9E0cmgbom/sm/49XdQ8G94aDfyIIY1RIdwmDCK5NVd74KFG3JIByTk5+VnAhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-darwin-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.8.0.tgz", + "integrity": "sha512-UpqayUjgalArXaDvOoshqSelTrEp42cGDsZGy0sqpxwBpm3oPQ8wE1d7oBAmRo208rAxOuFP0LZRFUqRrwGvLA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-freebsd-x64": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.8.0.tgz", + "integrity": "sha512-dUR2fsLyKZYMHByvjy2zvmdMbsdXAiP+6uTlIAuu8eHMZ2FPQCAtt7lPYLwOFUxUXChbek2AJ+uCI0gRAgK/eg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.8.0.tgz", + "integrity": "sha512-GuZ7t0SzSX5ksLYva7koKZovQ5h/Kr1pFbOsQcBf3VLREBqFPSz6t7CVYpsIsMhiu/I3EKq6FZI3wDOJbee5uw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.8.0.tgz", + "integrity": "sha512-CiI955Q+XZmBBZ7cQqQg0MhGEFwZIgSpJnjPfWBt3iOYP8aE6nZpNOkmD7O8XcN/nEwwyeCOF8euXqEStwsk8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.8.0.tgz", + "integrity": "sha512-Iy9DpvVisxsfNh4gOinmMQ4cLWdBlgvt1wmry1UwvcXg479p1oJQ1Kp1wksUZoWYqrAG8VPZUmkE0f7gjyHTGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-x64-gnu": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.8.0.tgz", + "integrity": "sha512-kZrrXXzVSbqwmdTmQ9xL4Jhi0/FSLrePSxYCL9oOM3Rsj0lmo/aC9kz4NBv1ZzuqT7fumpBOnhqiL1QyhOWOeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-x64-musl": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.8.0.tgz", + "integrity": "sha512-0l9jEMN8NhULKYCFiDF7QVpMMNG40duya+OF8dH0OzFj52N0zTsvsgLY72TIhslCB/cC74oAzsmWEIiFslscnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.8.0.tgz", + "integrity": "sha512-5miZJmRSwx1jybBsiB3NGocXL9TxGdT2D+dOqR2fsLklpGz0ItEWm8+i8lhDjgOdAr2nFcuQUfQMY57f9FOHrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-win32-x64-msvc": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.8.0.tgz", + "integrity": "sha512-0P5r+bDuSNvoWys+6C1/KqGpYlqwSHpigCcyRzR62iZpT3OooZv+nWO06RlURkxMR8LNvYXTSSLvoLkjxqM8uQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/workspace": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.8.0.tgz", + "integrity": "sha512-FdaHA5ISHSN+RyHswAAx+2A9HC77kWeFgeucdX2NSBs2QK2Lzg2Et639RzR1sYk2gYTP6tOkQXHHGKcg3jmiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.8.0", + "@zkochan/js-yaml": "0.0.7", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "20.8.0", + "picomatch": "4.0.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/storybook/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@nx/storybook/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@nx/storybook/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@nx/storybook/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/storybook/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/storybook/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/storybook/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/storybook/node_modules/nx": { + "version": "20.8.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.8.0.tgz", + "integrity": "sha512-+BN5B5DFBB5WswD8flDDTnr4/bf1VTySXOv60aUAllHqR+KS6deT0p70TTMZF4/A2n/L2UCWDaDro37MGaYozA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.2", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.8.3", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "resolve.exports": "2.0.3", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yaml": "^2.6.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "20.8.0", + "@nx/nx-darwin-x64": "20.8.0", + "@nx/nx-freebsd-x64": "20.8.0", + "@nx/nx-linux-arm-gnueabihf": "20.8.0", + "@nx/nx-linux-arm64-gnu": "20.8.0", + "@nx/nx-linux-arm64-musl": "20.8.0", + "@nx/nx-linux-x64-gnu": "20.8.0", + "@nx/nx-linux-x64-musl": "20.8.0", + "@nx/nx-win32-arm64-msvc": "20.8.0", + "@nx/nx-win32-x64-msvc": "20.8.0" + }, + "peerDependencies": { + "@swc-node/register": "^1.8.0", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/storybook/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/storybook/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nx/storybook/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@nx/storybook/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@nx/storybook/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@nx/storybook/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@nx/storybook/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nx/storybook/node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@nx/web": { "version": "22.1.3", "resolved": "https://registry.npmjs.org/@nx/web/-/web-22.1.3.tgz", @@ -9637,9 +11229,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", - "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "cpu": [ "arm" ], @@ -9651,9 +11243,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", - "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "cpu": [ "arm64" ], @@ -9665,9 +11257,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", - "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "cpu": [ "arm64" ], @@ -9679,9 +11271,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", - "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "cpu": [ "x64" ], @@ -9693,9 +11285,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", - "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "cpu": [ "arm64" ], @@ -9707,9 +11299,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", - "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "cpu": [ "x64" ], @@ -9721,9 +11313,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", - "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "cpu": [ "arm" ], @@ -9735,9 +11327,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", - "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "cpu": [ "arm" ], @@ -9749,9 +11341,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", - "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "cpu": [ "arm64" ], @@ -9763,9 +11355,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", - "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "cpu": [ "arm64" ], @@ -9777,9 +11369,23 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "cpu": [ "loong64" ], @@ -9819,9 +11425,23 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", "cpu": [ "ppc64" ], @@ -9833,9 +11453,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", - "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "cpu": [ "riscv64" ], @@ -9847,9 +11467,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "cpu": [ "riscv64" ], @@ -9861,9 +11481,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", - "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "cpu": [ "s390x" ], @@ -9875,9 +11495,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", - "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "cpu": [ "x64" ], @@ -9889,9 +11509,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", - "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "cpu": [ "x64" ], @@ -9902,10 +11522,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "cpu": [ "arm64" ], @@ -9917,9 +11551,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", - "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "cpu": [ "arm64" ], @@ -9931,9 +11565,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", - "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "cpu": [ "ia32" ], @@ -9945,9 +11579,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "cpu": [ "x64" ], @@ -9959,9 +11593,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", - "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "cpu": [ "x64" ], @@ -10397,9 +12031,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "version": "0.34.47", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.47.tgz", + "integrity": "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==", "license": "MIT" }, "node_modules/@sindresorhus/merge-streams": { @@ -10442,6 +12076,492 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/addon-themes": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-10.1.11.tgz", + "integrity": "sha512-tUX5C1ms+W4GFK8UBWd3Fq4irkLc3h092BqW90tZghcoOmGY/sfKR+PlcLhoaTs/kkHQSSHPrz8HSFR1AXVbHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.1.11" + } + }, + "node_modules/@storybook/angular": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-10.1.11.tgz", + "integrity": "sha512-iwmzxMB9t70RdC0Yb9BYVCIwsb7IQ1qkoMnDgKz8/cFl76H92OqoTWbXrrl8lR5vbeyGt1qmvhrMF30Sr5Y3Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/builder-webpack5": "10.1.11", + "@storybook/global": "^5.0.0", + "telejson": "8.0.0", + "ts-dedent": "^2.0.0", + "tsconfig-paths-webpack-plugin": "^4.0.1", + "webpack": "5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@angular-devkit/architect": ">=0.1800.0 < 0.2200.0", + "@angular-devkit/build-angular": ">=18.0.0 < 22.0.0", + "@angular-devkit/core": ">=18.0.0 < 22.0.0", + "@angular/animations": ">=18.0.0 < 22.0.0", + "@angular/cli": ">=18.0.0 < 22.0.0", + "@angular/common": ">=18.0.0 < 22.0.0", + "@angular/compiler": ">=18.0.0 < 22.0.0", + "@angular/compiler-cli": ">=18.0.0 < 22.0.0", + "@angular/core": ">=18.0.0 < 22.0.0", + "@angular/platform-browser": ">=18.0.0 < 22.0.0", + "@angular/platform-browser-dynamic": ">=18.0.0 < 22.0.0", + "rxjs": "^6.5.3 || ^7.4.0", + "storybook": "^10.1.11", + "typescript": "^4.9.0 || ^5.0.0", + "zone.js": ">=0.14.0" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + }, + "@angular/cli": { + "optional": true + }, + "zone.js": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-10.1.11.tgz", + "integrity": "sha512-NGG27B2tVVmaB7DwFDOuvTLHMb/tsvWkm6yVEjYYMyleThQdOMUxptKxwBvyDOR1gTvv3Z7SBjU6SJUA8Rdh1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/core-webpack": "10.1.11", + "@vitest/mocker": "3.2.4", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "css-loader": "^7.1.2", + "es-module-lexer": "^1.5.0", + "fork-ts-checker-webpack-plugin": "^9.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "style-loader": "^4.0.0", + "terser-webpack-plugin": "^5.3.14", + "ts-dedent": "^2.0.0", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.1.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", + "integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^4.0.1", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/core-webpack": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-10.1.11.tgz", + "integrity": "sha512-AAqITgkch3HgBvYySWKGxp3xRuPJyGzgEpiUkUjj54hARHD1S9XKdN7ZJx10OsDJM6lSdrMHJ2VKBfTYUpLn/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.1.11" + } + }, + "node_modules/@storybook/core/node_modules/@storybook/theming": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.14.tgz", + "integrity": "sha512-r4y+LsiB37V5hzpQo+BM10PaCsp7YlZ0YcZzQP1OCkPlYXmUAFy2VvDKaFRpD8IeNPKug2u4iFm/laDEbs03dg==", + "extraneous": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -10499,6 +12619,13 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -10563,6 +12690,17 @@ "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -10599,6 +12737,13 @@ "@types/node": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ejs": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", @@ -10668,6 +12813,13 @@ "@types/node": "*" } }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/http-errors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", @@ -10842,11 +12994,12 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "license": "MIT", "dependencies": { + "@types/mime": "^1", "@types/node": "*" } }, @@ -10870,16 +13023,6 @@ "@types/send": "<1" } }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, "node_modules/@types/sockjs": { "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", @@ -11458,17 +13601,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", - "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", + "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/utils": "8.48.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11483,15 +13626,15 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/project-service": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", - "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.48.1", - "@typescript-eslint/types": "^8.48.1", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11504,28 +13647,10 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", - "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", - "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", "dev": true, "license": "MIT", "engines": { @@ -11540,21 +13665,21 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", - "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.48.1", - "@typescript-eslint/tsconfig-utils": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11567,38 +13692,14 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", - "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", - "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -11638,10 +13739,23 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/type-utils/node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -11652,9 +13766,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", - "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", "dev": true, "license": "MIT", "peer": true, @@ -11757,9 +13871,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -11770,17 +13884,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", - "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11795,15 +13909,15 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/project-service": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", - "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.51.0", - "@typescript-eslint/types": "^8.51.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11817,14 +13931,14 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", - "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0" + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11835,9 +13949,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", - "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", "dev": true, "license": "MIT", "engines": { @@ -11851,36 +13965,22 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", - "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", - "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.51.0", - "@typescript-eslint/tsconfig-utils": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.2.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11894,13 +13994,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", - "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -11940,6 +14040,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils/node_modules/ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", @@ -12286,6 +14399,101 @@ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" } }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -13046,6 +15254,29 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "license": "MIT" }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -13842,6 +16073,17 @@ "node": ">=6" } }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -13884,6 +16126,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -13891,6 +16143,23 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -13928,6 +16197,16 @@ "pnpm": ">=8" } }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -13944,6 +16223,30 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chromatic": { + "version": "13.3.4", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-13.3.4.tgz", + "integrity": "sha512-TR5rvyH0ESXobBB3bV8jc87AEAFQC7/n+Eb4XWhJz6hW3YNxIQPVjcbgLv+a4oKHEl1dUBueWSoIQsOVGTd+RQ==", + "dev": true, + "license": "MIT", + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -13975,6 +16278,29 @@ "dev": true, "license": "MIT" }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/clean-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", @@ -15812,6 +18138,13 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -16135,6 +18468,16 @@ } } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -16280,6 +18623,16 @@ "node": ">=4" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -16407,6 +18760,23 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, "node_modules/dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -16489,6 +18859,17 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -17468,6 +19849,20 @@ "typescript": ">=4.0.0" } }, + "node_modules/eslint-plugin-storybook": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-10.1.11.tgz", + "integrity": "sha512-mbq2r2kK5+AcLl0XDJ3to91JOgzCbHOqj+J3n+FRw6drk+M1boRqMShSoMMm0HdzXPLmlr7iur+qJ5ZuhH6ayQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.8.1" + }, + "peerDependencies": { + "eslint": ">=8", + "storybook": "^10.1.11" + } + }, "node_modules/eslint-plugin-unicorn": { "version": "49.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-49.0.0.tgz", @@ -18275,6 +20670,16 @@ "node": ">=10" } }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 10.4.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -19485,7 +21890,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "he": "bin/he" @@ -19566,15 +21971,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -19612,6 +22008,38 @@ "dev": true, "license": "MIT" }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -19625,6 +22053,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-webpack-plugin": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.5.tgz", + "integrity": "sha512-4xynFbKNNk+WlzXeQQ+6YYsH2g7mpfPszQZUi3ovKlj+pDmngQ7vRXjrrmGROabmKwyQkcgcX5hqfOwHbFmK5g==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, "node_modules/htmlparser2": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", @@ -21234,9 +23696,9 @@ } }, "node_modules/jest-circus/node_modules/cjs-module-lexer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.1.tgz", - "integrity": "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "dev": true, "license": "MIT" }, @@ -22315,9 +24777,9 @@ } }, "node_modules/jest-config/node_modules/cjs-module-lexer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.1.tgz", - "integrity": "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "dev": true, "license": "MIT" }, @@ -25347,7 +27809,6 @@ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -27009,7 +29470,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/lodash-es": { @@ -27337,6 +29798,23 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -27356,6 +29834,16 @@ "node": ">=12" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -28331,6 +30819,17 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/nock": { "version": "13.5.5", "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.5.tgz", @@ -28423,6 +30922,122 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "extraneous": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "extraneous": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "extraneous": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "extraneous": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "extraneous": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "extraneous": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "extraneous": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "extraneous": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -28519,6 +31134,42 @@ "dev": true, "license": "ISC" }, + "node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -29376,6 +32027,17 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/parent-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", @@ -29506,6 +32168,17 @@ "node": ">= 0.8" } }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -29578,6 +32251,16 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/pdfjs-dist": { "version": "5.1.91", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.1.91.tgz", @@ -30537,6 +33220,17 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -30592,6 +33286,16 @@ "dev": true, "license": "MIT" }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -31067,6 +33771,47 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", @@ -31234,6 +33979,123 @@ } } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "devOptional": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "devOptional": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -31513,13 +34375,13 @@ } }, "node_modules/rollup": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", - "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -31529,35 +34391,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.8", - "@rollup/rollup-android-arm64": "4.34.8", - "@rollup/rollup-darwin-arm64": "4.34.8", - "@rollup/rollup-darwin-x64": "4.34.8", - "@rollup/rollup-freebsd-arm64": "4.34.8", - "@rollup/rollup-freebsd-x64": "4.34.8", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", - "@rollup/rollup-linux-arm-musleabihf": "4.34.8", - "@rollup/rollup-linux-arm64-gnu": "4.34.8", - "@rollup/rollup-linux-arm64-musl": "4.34.8", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", - "@rollup/rollup-linux-riscv64-gnu": "4.34.8", - "@rollup/rollup-linux-s390x-gnu": "4.34.8", - "@rollup/rollup-linux-x64-gnu": "4.34.8", - "@rollup/rollup-linux-x64-musl": "4.34.8", - "@rollup/rollup-win32-arm64-msvc": "4.34.8", - "@rollup/rollup-win32-ia32-msvc": "4.34.8", - "@rollup/rollup-win32-x64-msvc": "4.34.8", + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -32322,15 +35183,15 @@ } }, "node_modules/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~2.0.0", + "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", @@ -32360,6 +35221,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -32487,79 +35357,6 @@ "node": ">= 0.8.0" } }, - "node_modules/serve-static/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-static/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/serve-static/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -33226,6 +36023,73 @@ "node": ">= 0.4" } }, + "node_modules/storybook": { + "version": "10.1.11", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.1.11.tgz", + "integrity": "sha512-pKP5jXJYM4OjvNklGuHKO53wOCAwfx79KvZyOWHoi9zXUH5WVMFUe/ZfWyxXG/GTcj0maRgHGUjq/0I43r0dDQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/icons": "^2.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/user-event": "^14.6.1", + "@vitest/expect": "3.2.4", + "@vitest/spy": "3.2.4", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", + "open": "^10.2.0", + "recast": "^0.23.5", + "semver": "^7.6.2", + "use-sync-external-store": "^1.5.0", + "ws": "^8.18.0" + }, + "bin": { + "storybook": "dist/bin/dispatcher.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/storybook/node_modules/@storybook/icons": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-2.0.1.tgz", + "integrity": "sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/storybook/node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/streamroller": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", @@ -33277,14 +36141,20 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -34358,6 +37228,13 @@ "dev": true, "license": "MIT" }, + "node_modules/telejson": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-8.0.0.tgz", + "integrity": "sha512-8mCI1dHX80nchOkIEgvyWlGLgeh/SxO7JZPOud0DxvfFdI6MgwxRL8ff7rVdj6436uHhpWaxLQjU74Jb2I0u9g==", + "dev": true, + "license": "MIT" + }, "node_modules/terser": { "version": "5.39.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", @@ -34534,6 +37411,13 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "license": "MIT" }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -34562,6 +37446,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", @@ -34827,6 +37731,16 @@ "node": ">=8.10.0" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-invariant": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", @@ -35565,6 +38479,16 @@ "requires-port": "^1.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -35578,6 +38502,13 @@ "dev": true, "license": "MIT" }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -35647,6 +38578,16 @@ "spdx-license-ids": "^3.0.0" } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", @@ -35738,244 +38679,6 @@ } } }, - "node_modules/vite/node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/vite/node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -36005,48 +38708,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/vite/node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -36409,6 +39070,19 @@ "node": ">=8.10.0" } }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", @@ -36463,6 +39137,13 @@ } } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -36819,6 +39500,22 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xdg-basedir": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", diff --git a/package.json b/package.json index 65d480cc32..65760ade3e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "publish": "nx run-many -t npm-publish", "clean": "rimraf dist node_modules dist/libs", "nx:run-target": "nx run", - "nx:run-many": "nx run-many" + "nx:run-many": "nx run-many", + "storybook": "nx run stories:storybook", + "build-storybook": "nx run stories:build-storybook" }, "repository": { "type": "git", @@ -83,12 +85,16 @@ "@angular-eslint/eslint-plugin-template": "19.3.0", "@angular-eslint/template-parser": "19.3.0", "@angular/compiler-cli": "19.2.17", + "@chromatic-com/storybook": "4.1.3", "@nx/angular": "22.1.3", "@nx/eslint-plugin": "22.1.3", "@nx/js": "22.1.3", "@nx/node": "22.1.3", + "@nx/storybook": "20.8.0", "@nx/workspace": "22.1.3", "@schematics/angular": "19.2.7", + "@storybook/addon-themes": "^10.1.11", + "@storybook/angular": "10.1.11", "@types/ejs": "^3.1.5", "@types/jasmine": "4.0.3", "@types/jasminewd2": "~2.0.2", @@ -114,6 +120,7 @@ "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-rxjs": "^5.0.3", + "eslint-plugin-storybook": "10.1.11", "eslint-plugin-unicorn": "^49.0.0", "graphql": "^16.9.0", "husky": "^9.1.7", @@ -143,12 +150,18 @@ "rimraf": "^6.1.2", "sass-loader": "16.0.5", "spdx-license-list": "^6.9.0", + "storybook": "10.1.11", "stylelint": "16.20.0", "stylelint-config-standard-scss": "^13.1.0", "ts-node": "^10.9.2", "typescript": "5.8.3", "webpack": "5.101.3" }, + "overrides": { + "@storybook/angular": { + "webpack": "5.101.3" + } + }, "license": "Apache-2.0", "engines": { "node": ">=18.0.0"