diff --git a/.github/workflows/build-app-crm.yml b/.github/workflows/build-app-crm.yml index 2bfd89874a..77062edcad 100644 --- a/.github/workflows/build-app-crm.yml +++ b/.github/workflows/build-app-crm.yml @@ -46,4 +46,8 @@ jobs: - name: 'Generate live editing and build samples' run: npm run build:app-crm env: + # esbuild is a Go binary: Node heap flags do not limit it, GOMEMLIMIT/GOGC do. + # Without this the app build OOM-kills the runner ("The operation was canceled"). + GOMEMLIMIT: '6GiB' + GOGC: '50' NODE_OPTIONS: "--max_old_space_size=4096" diff --git a/.github/workflows/build-app-lob.yml b/.github/workflows/build-app-lob.yml index 699c333d3b..47fe1767ac 100644 --- a/.github/workflows/build-app-lob.yml +++ b/.github/workflows/build-app-lob.yml @@ -48,4 +48,8 @@ jobs: - name: 'Generate live editing and build samples' run: npm run build:app-lob env: + # esbuild is a Go binary: Node heap flags do not limit it, GOMEMLIMIT/GOGC do. + # Without this the app build OOM-kills the runner ("The operation was canceled"). + GOMEMLIMIT: '6GiB' + GOGC: '50' NODE_OPTIONS: "--max_old_space_size=4096" diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 3c19b5984f..ae90b48623 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -46,4 +46,8 @@ jobs: - name: 'Generate live editing and build samples' run: npm run build env: + # esbuild is a Go binary: Node heap flags do not limit it, GOMEMLIMIT/GOGC do. + # Without this the app build OOM-kills the runner ("The operation was canceled"). + GOMEMLIMIT: '6GiB' + GOGC: '50' NODE_OPTIONS: "--max_old_space_size=4096" diff --git a/angular.json b/angular.json index 1509ba457b..9fc62240d3 100644 --- a/angular.json +++ b/angular.json @@ -19,7 +19,12 @@ "tsConfig": "src/tsconfig.app.json", "assets": [ "src/assets", - "src/favicon.ico" + "src/favicon.ico", + { + "glob": "igniteui-{angular,angular-dark,fluent-light,fluent-dark,bootstrap-light,bootstrap-dark,indigo-light,indigo-dark}.css", + "input": "node_modules/igniteui-angular/styles", + "output": "assets/themes" + } ], "styles": [ "src/styles.scss" @@ -155,7 +160,6 @@ "node_modules" ] }, - "preserveSymlinks": true, "browser": "projects/app-lob/src/main.ts", "server": "projects/app-lob/src/main.server.ts", "outputMode": "static", diff --git a/live-editing/configs/AccordionConfigGenerator.ts b/live-editing/configs/AccordionConfigGenerator.ts index 58d7c2bca3..d35dece3ed 100644 --- a/live-editing/configs/AccordionConfigGenerator.ts +++ b/live-editing/configs/AccordionConfigGenerator.ts @@ -31,6 +31,12 @@ export class AccordionConfigGenerator implements IConfigGenerator { shortenComponentPathBy: '/layouts/accordion/' })); + configs.push(new Config({ + component: 'AccordionProgrammaticExpansionComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: '/layouts/accordion/' + })); + configs.push(new Config({ component: 'AccordionStyleComponent', additionalFiles: ["/src/app/layouts/accordion/accordion-style/layout.scss"], diff --git a/live-editing/configs/BreadcrumbsConfigGenerator.ts b/live-editing/configs/BreadcrumbsConfigGenerator.ts new file mode 100644 index 0000000000..4b42140780 --- /dev/null +++ b/live-editing/configs/BreadcrumbsConfigGenerator.ts @@ -0,0 +1,60 @@ +import { Config, IConfigGenerator } from 'igniteui-live-editing' +import { BaseAppConfig } from './BaseConfig'; +export class BreadcrumbsConfigGenerator implements IConfigGenerator { + + public generateConfigs(): Config[] { + const configs = new Array(); + + configs.push(new Config({ + component: 'BreadcrumbsOverviewComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsSizesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsStatesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsPrefixSuffixComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsCustomSeparatorComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsWrappingComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsStylingComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + configs.push(new Config({ + component: 'BreadcrumbsTailwindStylingComponent', + additionalDependencies: ["tailwindcss", "@tailwindcss/postcss"], + additionalFiles: [".postcssrc.json"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/layouts/breadcrumbs/" + })); + + return configs; + } +} diff --git a/live-editing/configs/ButtonConfigGenerator.ts b/live-editing/configs/ButtonConfigGenerator.ts index 5dc013ef22..fbdecc8022 100644 --- a/live-editing/configs/ButtonConfigGenerator.ts +++ b/live-editing/configs/ButtonConfigGenerator.ts @@ -1,48 +1,95 @@ -import { IgxButtonGroupModule } from 'igniteui-angular/button-group'; -import { IgxButtonModule, IgxRippleModule } from 'igniteui-angular/directives'; -import { IgxIconModule } from 'igniteui-angular/icon'; -import { AppModuleConfig, Config, IConfigGenerator } from 'igniteui-live-editing' +import { Config, IConfigGenerator } from 'igniteui-live-editing' import { BaseAppConfig } from './BaseConfig'; -import { ButtonsRoundnessComponent } from '../../src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample'; export class ButtonConfigGenerator implements IConfigGenerator { public generateConfigs(): Config[] { const configs = new Array(); - // buttons sample 1 + // button overview configs.push(new Config({ - component: 'ButtonsSample1Component', + component: 'ButtonOverviewComponent', appConfig: BaseAppConfig, - shortenComponentPathBy: "/data-entries/buttons/" + shortenComponentPathBy: "/data-entries/button/" })); - // buttons roundness + // flat button configs.push(new Config({ - component: 'ButtonsDisabledComponent', + component: 'ButtonFlatComponent', appConfig: BaseAppConfig, - shortenComponentPathBy: "/data-entries/buttons/" + shortenComponentPathBy: "/data-entries/button/" })); - // buttons display density + // button interaction states configs.push(new Config({ - component: 'ButtonsDisplayDensityComponent', + component: 'ButtonInteractionStatesComponent', appConfig: BaseAppConfig, - shortenComponentPathBy: "/data-entries/buttons/" + shortenComponentPathBy: "/data-entries/button/" })); + // button layout configs.push(new Config({ - component: 'ButtonsRoundnessComponent', + component: 'ButtonLayoutComponent', appConfig: BaseAppConfig, - shortenComponentPathBy: "/data-entries/buttons/" + shortenComponentPathBy: "/data-entries/button/" })); - // button style + // contained button configs.push(new Config({ - component: 'ButtonsStyleComponent', - additionalFiles: ["/src/app/data-entries/buttons/buttons-style/layout.scss"], + component: 'ButtonContainedComponent', appConfig: BaseAppConfig, - shortenComponentPathBy: "/data-entries/buttons/" + shortenComponentPathBy: "/data-entries/button/" + })); + + // floating action button + configs.push(new Config({ + component: 'ButtonFabComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // outlined button + configs.push(new Config({ + component: 'ButtonOutlinedComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // button states + configs.push(new Config({ + component: 'ButtonStatesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // button size + configs.push(new Config({ + component: 'ButtonSizeComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // download button + configs.push(new Config({ + component: 'ButtonDownloadComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // button styling + configs.push(new Config({ + component: 'ButtonStylingComponent', + additionalFiles: ["/src/app/data-entries/button/button-styling/layout.scss"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" + })); + + // button tailwind styling + configs.push(new Config({ + component: 'ButtonTailwindStylingComponent', + additionalFiles: ["/src/app/data-entries/button/button-tailwind-styling/layout.scss"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/button/" })); return configs; diff --git a/live-editing/configs/ButtonGroupConfigGenerator.ts b/live-editing/configs/ButtonGroupConfigGenerator.ts index 9db78ec06d..64aeafcbc4 100644 --- a/live-editing/configs/ButtonGroupConfigGenerator.ts +++ b/live-editing/configs/ButtonGroupConfigGenerator.ts @@ -69,7 +69,6 @@ export class ButtonGroupConfigGenerator implements IConfigGenerator { // button group styling configs.push(new Config({ component: 'ButtonGroupStylingComponent', - additionalFiles: ["/src/app/data-entries/buttonGroup/button-group-styling/layout.scss"], appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/buttonGroup/" })); diff --git a/live-editing/configs/CheckboxConfigGenerator.ts b/live-editing/configs/CheckboxConfigGenerator.ts index 1e1722c264..54a9935632 100644 --- a/live-editing/configs/CheckboxConfigGenerator.ts +++ b/live-editing/configs/CheckboxConfigGenerator.ts @@ -7,29 +7,30 @@ export class CheckboxConfigGenerator implements IConfigGenerator { public generateConfigs(): Config[] { const configs = new Array(); - // checkbox sample 2 + // checkbox overview configs.push(new Config({ - component: 'CheckboxSample1Component', + component: 'CheckboxOverviewComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/checkbox/" })); - // checkbox sample 2 + // checkbox states configs.push(new Config({ - component: 'CheckboxSample2Component', + component: 'CheckboxStatesComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/checkbox/" })); + // checkbox styling configs.push(new Config({ - component: 'CheckboxSample3Component', + component: 'CheckboxStylingComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/checkbox/" })); - // checkbox styling + // checkbox tailwind styling configs.push(new Config({ - component: 'CheckboxStylingComponent', + component: 'CheckboxTailwindStylingComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/checkbox/" })); diff --git a/live-editing/configs/ColorPickerConfigGenerator.ts b/live-editing/configs/ColorPickerConfigGenerator.ts new file mode 100644 index 0000000000..7647634eee --- /dev/null +++ b/live-editing/configs/ColorPickerConfigGenerator.ts @@ -0,0 +1,85 @@ +import { Config, IConfigGenerator } from 'igniteui-live-editing' +import { BaseAppConfig } from './BaseConfig'; +export class ColorPickerConfigGenerator implements IConfigGenerator { + + public generateConfigs(): Config[] { + const configs = new Array(); + + configs.push(new Config({ + component: 'ColorPickerOverviewComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerValueComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerFormatComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerAlphaComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerSwatchesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerInputComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerSizesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerInputSizesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerStatesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerReactiveFormComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerStylingComponent', + additionalFiles: ["src/app/data-entries/color-picker/styling/layout.scss"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + configs.push(new Config({ + component: 'ColorPickerTailwindStylingComponent', + additionalDependencies: ["tailwindcss", "@tailwindcss/postcss"], + additionalFiles: [".postcssrc.json"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/color-picker/" + })); + + return configs; + } +} diff --git a/live-editing/configs/GridConfigGenerator.ts b/live-editing/configs/GridConfigGenerator.ts index 0675968292..472080951b 100644 --- a/live-editing/configs/GridConfigGenerator.ts +++ b/live-editing/configs/GridConfigGenerator.ts @@ -574,6 +574,11 @@ export class GridConfigGenerator implements IConfigGenerator { additionalFiles: ['/src/app/directives/prevent-scroll.directive.ts', '/src/app/data/customers.ts', '/src/app/grid/grid-sample-pinning-styling/layout.scss'], appConfig: BaseAppConfig })); + configs.push(new Config({ + component: 'GridThemingComponent', + additionalFiles: ['/src/app/directives/prevent-scroll.directive.ts', '/src/app/data/invoiceData.ts'], + appConfig: BaseAppConfig + })); configs.push(new Config({ component: 'GridGroupByStylingComponent', additionalFiles: ['/src/app/directives/prevent-scroll.directive.ts', '/src/app/data/invoiceData.ts', '/src/app/grid/grid-groupby-styling/layout.scss'], diff --git a/live-editing/configs/PivotGridConfigGenerator.ts b/live-editing/configs/PivotGridConfigGenerator.ts index 7f7fb25e2e..c7c720c47b 100644 --- a/live-editing/configs/PivotGridConfigGenerator.ts +++ b/live-editing/configs/PivotGridConfigGenerator.ts @@ -83,7 +83,7 @@ export class PivotGridConfigGenerator implements IConfigGenerator { })); configs.push(new Config({ - additionalFiles: ['/src/app/directives/prevent-scroll.directive.ts', '/src/app/data/dataToAnalyze.ts'], + additionalFiles: ['/src/app/data/pivot-data.ts', '/src/app/pivot-grid/pivot-styling/layout.scss'], appConfig: BaseAppConfig, component: 'PivotStylingComponent' })); diff --git a/live-editing/configs/QrCodeConfigGenerator.ts b/live-editing/configs/QrCodeConfigGenerator.ts new file mode 100644 index 0000000000..c8b13e05ed --- /dev/null +++ b/live-editing/configs/QrCodeConfigGenerator.ts @@ -0,0 +1,60 @@ +import { Config, IConfigGenerator } from 'igniteui-live-editing' +import { BaseAppConfig } from './BaseConfig'; +export class QrCodeConfigGenerator implements IConfigGenerator { + + public generateConfigs(): Config[] { + const configs = new Array(); + + configs.push(new Config({ + component: 'QrCodeOverviewComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeSizeComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeErrorCorrectionComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeDotShapesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeCornerShapesComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeLogoComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeStylingComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + configs.push(new Config({ + component: 'QrCodeTailwindStylingComponent', + additionalDependencies: ["tailwindcss", "@tailwindcss/postcss"], + additionalFiles: [".postcssrc.json"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/qr-code/" + })); + + return configs; + } +} diff --git a/live-editing/configs/SwitchConfigGenerator.ts b/live-editing/configs/SwitchConfigGenerator.ts index 3e92e34182..6000f24dbe 100644 --- a/live-editing/configs/SwitchConfigGenerator.ts +++ b/live-editing/configs/SwitchConfigGenerator.ts @@ -7,16 +7,37 @@ export class SwitchConfigGenerator implements IConfigGenerator { public generateConfigs(): Config[] { const configs = new Array(); - // switch sample 1 + // switch overview configs.push(new Config({ - component: 'SwitchSample1Component', + component: 'SwitchOverviewComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/switch/" })); - // switch sample 2 + // switch enabled configs.push(new Config({ - component: 'SwitchSample2Component', + component: 'SwitchEnabledComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/switch/" + })); + + // switch disabled + configs.push(new Config({ + component: 'SwitchDisabledComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/switch/" + })); + + // switch selected + configs.push(new Config({ + component: 'SwitchSelectedComponent', + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-entries/switch/" + })); + + // switch layout + configs.push(new Config({ + component: 'SwitchLayoutComponent', appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/switch/" })); @@ -24,7 +45,6 @@ export class SwitchConfigGenerator implements IConfigGenerator { // switch styling configs.push(new Config({ component: 'SwitchStylingComponent', - additionalFiles: ["/src/app/data-entries/switch/switch-styling/layout.scss"], appConfig: BaseAppConfig, shortenComponentPathBy: "/data-entries/switch/" })); diff --git a/live-editing/configs/ThemingConfigGenerator.ts b/live-editing/configs/ThemingConfigGenerator.ts index 3c0a10d09e..9e99a6b441 100644 --- a/live-editing/configs/ThemingConfigGenerator.ts +++ b/live-editing/configs/ThemingConfigGenerator.ts @@ -72,6 +72,19 @@ export class ThemingConfigGenerator implements IConfigGenerator { shortenComponentPathBy: '/theming/angular/' })); + configs.push(new Config({ + component: 'GridThemePlaygroundComponent', + additionalDependencies: ['igniteui-webcomponents'], + additionalFiles: [ + '/src/app/data/invoiceData.ts', + '/src/app/data/pivot-data.ts', + '/src/app/data/singersData.ts', + '/src/app/tree-grid/data/employees-flat-avatars.ts' + ], + appConfig: BaseAppConfig, + shortenComponentPathBy: '/theming/grid-theme-playground/' + })); + configs.push(new Config({ component: 'TailwindSampleComponent', appConfig: BaseAppConfig, diff --git a/live-editing/configs/VirtualScrollConfigGenerator.ts b/live-editing/configs/VirtualScrollConfigGenerator.ts new file mode 100644 index 0000000000..2066fdebe7 --- /dev/null +++ b/live-editing/configs/VirtualScrollConfigGenerator.ts @@ -0,0 +1,59 @@ +import {Config, IConfigGenerator} from 'igniteui-live-editing' +import { BaseAppConfig } from './BaseConfig'; +export class VirtualScrollConfigGenerator implements IConfigGenerator { + + + public generateConfigs(): Config[] { + const configs = new Array(); + + // virtual scroll overview + configs.push(new Config({ + component: 'VirtualScrollOverviewComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + // virtual scroll variable item size + configs.push(new Config({ + component: 'VirtualScrollVariableSizeComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + // virtual scroll horizontal + configs.push(new Config({ + component: 'VirtualScrollHorizontalComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + // virtual scroll scroll to index + configs.push(new Config({ + component: 'VirtualScrollScrollToIndexComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + // virtual scroll infinite scroll + configs.push(new Config({ + component: 'VirtualScrollInfiniteScrollComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + // virtual scroll paged data + configs.push(new Config({ + component: 'VirtualScrollPagedDataComponent', + additionalFiles: ["/src/app/data-display/virtual-scroll/employees.ts"], + appConfig: BaseAppConfig, + shortenComponentPathBy: "/data-display/" + })); + + return configs; + } +} diff --git a/live-editing/generators/ConfigGenerators.ts b/live-editing/generators/ConfigGenerators.ts index 25c0c09525..858d004a34 100644 --- a/live-editing/generators/ConfigGenerators.ts +++ b/live-editing/generators/ConfigGenerators.ts @@ -3,6 +3,7 @@ import { AutocompleteConfigGenerator } from '../configs/AutocompleteConfigGenera import { AvatarConfigGenerator } from '../configs/AvatarConfigGenerator'; import { BadgeConfigGenerator } from '../configs/BadgeConfigGenerator'; import { BannerConfigGenerator } from '../configs/BannerConfigGenerator'; +import { BreadcrumbsConfigGenerator } from '../configs/BreadcrumbsConfigGenerator'; import { ButtonConfigGenerator } from '../configs/ButtonConfigGenerator'; import { ButtonGroupConfigGenerator } from '../configs/ButtonGroupConfigGenerator'; import { CalendarConfigGenerator } from '../configs/CalendarConfigGenerator'; @@ -12,6 +13,7 @@ import { ChatConfigGenerator } from '../configs/ChatConfigGenerator'; import { CheckboxConfigGenerator } from '../configs/CheckboxConfigGenerator'; import { ChipConfigGenerator } from '../configs/ChipConfigGenerator'; import { CircularProgressbarConfigGenerator } from '../configs/CircularProgressbarConfigGenerator'; +import { ColorPickerConfigGenerator } from '../configs/ColorPickerConfigGenerator'; import { ComboConfigGenerator } from '../configs/ComboConfigGenerator'; import { DatePickerConfigGenerator } from '../configs/DatePickerConfigGenerator'; import { DateRangePickerConfigGenerator } from '../configs/DateRangePickerConfigGenerator'; @@ -26,6 +28,7 @@ import { ExportCsvConfigGenerator } from '../configs/ExportCsvConfigGenerator'; import { ExportExcelConfigGenerator } from '../configs/ExportExcelConfigGenerator'; import { ExportPdfConfigGenerator } from '../configs/ExportPdfConfigGenerator'; import { ForConfigGenerator } from '../configs/ForConfigGenerator'; +import { VirtualScrollConfigGenerator } from '../configs/VirtualScrollConfigGenerator'; import { GridConfigGenerator } from '../configs/GridConfigGenerator'; import { HierarchicalGridConfigGenerator } from '../configs/HierarchicalGridConfigGenerator'; import { IconConfigGenerator } from '../configs/IconConfigGenerator'; @@ -63,6 +66,7 @@ import { StepperConfigGenerator } from '../configs/StepperConfigGenerator'; import { PaginationConfigGenerator } from '../configs/PaginationConfigGenerator'; import { PivotGridConfigGenerator } from '../configs/PivotGridConfigGenerator'; import { QueryBuilderConfigGenerator } from '../configs/QueryBuilderConfigGenerator'; +import { QrCodeConfigGenerator } from '../configs/QrCodeConfigGenerator'; import { TileManagerConfigGenerator } from '../configs/TileManagerConfigGenerator'; import { GridLiteConfigGenerator } from '../configs/GridLiteConfigGenerator'; @@ -79,6 +83,7 @@ export const CONFIG_GENERATORS = AvatarConfigGenerator, BadgeConfigGenerator, BannerConfigGenerator, + BreadcrumbsConfigGenerator, CardConfigGenerator, CarouselConfigGenerator, ChipConfigGenerator, @@ -99,6 +104,7 @@ export const CONFIG_GENERATORS = ButtonGroupConfigGenerator, CalendarConfigGenerator, CheckboxConfigGenerator, + ColorPickerConfigGenerator, ComboConfigGenerator, DatePickerConfigGenerator, DateRangePickerConfigGenerator, @@ -128,6 +134,7 @@ export const CONFIG_GENERATORS = CircularProgressbarConfigGenerator, DividerConfigGenerator, ForConfigGenerator, + VirtualScrollConfigGenerator, IconConfigGenerator, OverlayConfigGenerator, LinearProgressbarConfigGenerator, @@ -143,5 +150,6 @@ export const CONFIG_GENERATORS = DockManagerConfigGenerator, TileManagerConfigGenerator, PaginationConfigGenerator, - QueryBuilderConfigGenerator + QueryBuilderConfigGenerator, + QrCodeConfigGenerator ]; diff --git a/package-lock.json b/package-lock.json index f1400169da..153b01495f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,22 +9,22 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@angular/animations": "^22.0.1", + "@angular/animations": "^22.2.0", "@angular/cdk": "^22.0.1", - "@angular/common": "^22.0.1", - "@angular/compiler": "^22.0.1", - "@angular/core": "^22.0.1", - "@angular/forms": "^22.0.1", - "@angular/localize": "^22.0.1", + "@angular/common": "^22.2.0", + "@angular/compiler": "^22.2.0", + "@angular/core": "^22.2.0", + "@angular/forms": "^22.2.0", + "@angular/localize": "^22.2.0", "@angular/material": "^22.0.1", - "@angular/platform-browser": "^22.0.1", - "@angular/platform-browser-dynamic": "^22.0.1", - "@angular/platform-server": "^22.0.1", - "@angular/router": "^22.0.1", - "@angular/ssr": "^22.0.1", + "@angular/platform-browser": "^22.2.0", + "@angular/platform-browser-dynamic": "^22.2.0", + "@angular/platform-server": "^22.2.0", + "@angular/router": "^22.2.0", + "@angular/ssr": "^22.2.0", "@igniteui/material-icons-extended": "^3.1.0", "@microsoft/signalr": "^8.0.7", - "@ng-bootstrap/ng-bootstrap": "^20.0.0", + "@ng-bootstrap/ng-bootstrap": "^21.0.0", "@popperjs/core": "2.11.8", "@tailwindcss/postcss": "^4.1.10", "@types/file-saver": "^2.0.2", @@ -34,16 +34,16 @@ "express": "^4.18.2", "file-saver": "^2.0.2", "fuse.js": "^7.1.0", - "igniteui-angular": "22.1.0", + "igniteui-angular": "22.2.0", "igniteui-angular-charts": "^22.0.0", "igniteui-angular-core": "^22.0.0", - "igniteui-angular-extras": "22.1.0", - "igniteui-angular-i18n": "22.1.0", + "igniteui-angular-extras": "22.2.0", + "igniteui-angular-i18n": "22.2.0", "igniteui-dockmanager": "^1.17.0", - "igniteui-grid-lite": "0.10.0", + "igniteui-grid-lite": "0.11.0", "igniteui-i18n-resources": "^1.0.4", "igniteui-live-editing": "^3.5.2", - "igniteui-webcomponents": "^7.3.0", + "igniteui-webcomponents": "^7.4.1", "marked": "^18.0.11", "marked-shiki": "^1.2.1", "minireset.css": "0.0.6", @@ -55,15 +55,15 @@ "tslib": "^2.6.1" }, "devDependencies": { - "@angular-eslint/builder": "^22.0.0", - "@angular-eslint/eslint-plugin": "^22.0.0", - "@angular-eslint/eslint-plugin-template": "^22.0.0", - "@angular-eslint/schematics": "^22.0.0", - "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "^22.0.0", - "@angular/cli": "^22.0.1", - "@angular/compiler-cli": "^22.0.1", - "@angular/language-service": "^22.0.1", + "@angular-eslint/builder": "^22.5.0", + "@angular-eslint/eslint-plugin": "^22.5.0", + "@angular-eslint/eslint-plugin-template": "^22.5.0", + "@angular-eslint/schematics": "^22.5.0", + "@angular-eslint/template-parser": "^22.5.0", + "@angular/build": "^22.2.0", + "@angular/cli": "^22.2.0", + "@angular/compiler-cli": "^22.2.0", + "@angular/language-service": "^22.2.0", "@igniteui/angular-schematics": "^22.0.0", "@juggle/resize-observer": "^3.3.1", "@types/express": "^4.17.17", @@ -72,7 +72,7 @@ "@types/node": "^25.9.3", "@typescript-eslint/eslint-plugin": "^8.61.0", "@typescript-eslint/parser": "^8.61.0", - "angular-eslint": "^22.0.0", + "angular-eslint": "^22.5.0", "eslint": "^9.8.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^63.0.2", @@ -121,13 +121,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2201.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2201.6.tgz", - "integrity": "sha512-oGQEdof2/1bZk58PN9dvpGi8pvtbgE5vkP1xRtCqN8dSVxwre1l0pKynOj/Uge1KxjCvs4c1QrQu0vsAnY0vpg==", + "version": "0.2202.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2202.0.tgz", + "integrity": "sha512-HxY8JxLd3WxFj45BtDUHZ9I6hO4KebTz32UQ4ZkPh0EMK/TZdspbSgwd2lo1jE6a90knRAQkAsnBTKwWvGSm3A==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.1.6", + "@angular-devkit/core": "22.2.0", "rxjs": "7.8.2" }, "bin": { @@ -140,18 +140,18 @@ } }, "node_modules/@angular-devkit/core": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.1.6.tgz", - "integrity": "sha512-KLBsZoc2RhOy0xSdeYcLoSOqV/fBP3feBmhY9o12ry2IuyW/17sCmWr6XbIfTIYQN6M98Y1ewmwVNFsvV5b0gA==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-22.2.0.tgz", + "integrity": "sha512-dELBwXtJWUxFALdEVvdk8qK+XBa17EH5H9NZm+041/esjNi6SaZMusqBgr2PZKq7hD+O2jSCEHbey/hwkz2Awg==", "dev": true, "license": "MIT", "dependencies": { "ajv": "8.20.0", "ajv-formats": "3.0.1", "jsonc-parser": "3.3.1", - "picomatch": "4.0.5", + "picomatch": "4.0.7", "rxjs": "7.8.2", - "source-map": "0.7.6" + "source-map": "0.8.0" }, "engines": { "node": "^22.22.3 || ^24.15.0 || >=26.0.0", @@ -168,15 +168,15 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.1.6.tgz", - "integrity": "sha512-IbDO9KbQyQm20uinsfT8d9ZtQw41/WVutI/65mAw39WZfN8Ky+MOgOUJCGLiSccMprvZ9YdodBTnN9bLH149Ag==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-22.2.0.tgz", + "integrity": "sha512-yhp/LRzKHJOzo2gFm9+H5DKnsT9adi+ItO2pW0pW2B455sqZYE8RJaSku+TSlv+PvWSmbtFsPXNgSRLA6pSk8Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.1.6", + "@angular-devkit/core": "22.2.0", "jsonc-parser": "3.3.1", - "magic-string": "1.0.0", + "magic-string": "1.4.1", "ora": "9.4.1", "rxjs": "7.8.2" }, @@ -187,9 +187,9 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-22.1.0.tgz", - "integrity": "sha512-gmdk06PK0whNJlapIQjRnhud2/n+oIIDBIoLUHWFFxhHRs+ZstVc6+81gf+sYDOm1Ehmb0V3nZAg3YpT1Mk0Eg==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-22.5.0.tgz", + "integrity": "sha512-bChGIHOApVk3eXaAfCOxxb54tToIttSzADEUpuBN6cs7Jp7OO96lNpMktv9IPvxfyVrhbriocwNy33jhpRSt0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -197,27 +197,26 @@ "@angular-devkit/core": ">= 22.0.0 < 23.0.0" }, "peerDependencies": { - "@angular/cli": ">= 22.0.0 < 23.0.0", "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.1.0.tgz", - "integrity": "sha512-iOtOQ2jtrtko1rIQo6i+g3ezxGL0lyYv80j4GccFTK1JGh4K+AqYkmaBvfUfNtqoE/7VcKsOoyxaFt6iIpKhaQ==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.5.0.tgz", + "integrity": "sha512-AdvtopHjjenM02LqsgqQbpTWTbE2DqFS4ZJT8YxEIzUKUdLNwkGUgZn9WpKHBHGBvaiA3hj2BLWRCJs/vJmV3g==", "dev": true, "license": "MIT" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-22.1.0.tgz", - "integrity": "sha512-nRwdbUiW7vF0gbwtxw2hRGPZYZCNWOTLZKw4HM+I37o5YFIA0CFLtbyRKgZWs6JZCIqzTYSwCyKNsW41Qw0FwQ==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-22.5.0.tgz", + "integrity": "sha512-3MooyC+F156Aa0XmNLwNMeQFVmSPhJYqPdX8FditvzSYuo5qANZTSbBABMU8XepvmxXcpPmEsj5sQUpbTdRl9Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.1.0", - "@angular-eslint/utils": "22.1.0", + "@angular-eslint/bundled-angular-compiler": "22.5.0", + "@angular-eslint/utils": "22.5.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { @@ -227,19 +226,19 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.1.0.tgz", - "integrity": "sha512-GK/Mwhwvj+MX6DefD29/IfuYjcai5CsCbYJ6Qb9P6IAzZaQqw+EN+CiXxIwzMnzm2edLcJzAsX8iBk4X7sVi2Q==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.5.0.tgz", + "integrity": "sha512-qHi292XBe5TIFpPjEKY+NtiFGEZLrYzD8GPVzBuIruaKQz1Y//eqPp3Ve/MYYBbwdj0gD8rPZRjDIXAcsRUMVg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.1.0", - "@angular-eslint/utils": "22.1.0", + "@angular-eslint/bundled-angular-compiler": "22.5.0", + "@angular-eslint/utils": "22.5.0", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, "peerDependencies": { - "@angular-eslint/template-parser": "22.1.0", + "@angular-eslint/template-parser": "22.5.0", "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", "eslint": "^9.0.0 || ^10.0.0", @@ -247,32 +246,29 @@ } }, "node_modules/@angular-eslint/schematics": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-22.1.0.tgz", - "integrity": "sha512-/Z7MEO9ys9P5w5itM2mpNW4R/QNAVxtDdcU5LVFulSx/lo7zCDx1rZ/tLDuzbN5k5RGQy5ZkdRIs0MoscsGXQQ==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-22.5.0.tgz", + "integrity": "sha512-4B7Bpph/H6vNI0Wfi3p4w4AKw6VJrTG9IGNbSx6NKbPzcwBSaFSuJUpIUxiuzlsaFy6csbRWU2E3UPyXjEfFew==", "dev": true, "license": "MIT", "dependencies": { "@angular-devkit/core": ">= 22.0.0 < 23.0.0", "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", - "@angular-eslint/eslint-plugin": "22.1.0", - "@angular-eslint/eslint-plugin-template": "22.1.0", - "ignore": "7.0.5", + "@angular-eslint/eslint-plugin": "22.5.0", + "@angular-eslint/eslint-plugin-template": "22.5.0", + "ignore": "7.0.8", "semver": "7.8.5", "strip-json-comments": "3.1.1" - }, - "peerDependencies": { - "@angular/cli": ">= 22.0.0 < 23.0.0" } }, "node_modules/@angular-eslint/template-parser": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.1.0.tgz", - "integrity": "sha512-gcufZLI/Rl2fOWtBk2MgMRkH1t+OrbJGxIsfT0w3pVjKm0zwi7njM/dtPbVjCHzsGhx7szQMvY0i0UwTBVYkSw==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.5.0.tgz", + "integrity": "sha512-p0C48htmzd1/Qum3TIQz3FZMWivbkm7x8z3Q6GY3CzNOIzVRKQU2MwZtpocXPkctJGjYnC5wJ58d8Ow4E5LVbA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.1.0", + "@angular-eslint/bundled-angular-compiler": "22.5.0", "eslint-scope": "9.1.2" }, "peerDependencies": { @@ -281,13 +277,13 @@ } }, "node_modules/@angular-eslint/utils": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.1.0.tgz", - "integrity": "sha512-zDPJqgOxlkG20UJWsVDSvnEtC2MfIP0+yKMaQUBL+2nrEknV/fVLrz7ApnerWiDrGTcAms5si49KV10MarMpRA==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.5.0.tgz", + "integrity": "sha512-i106BkmVnXM3ub5nsaXmAZNk1bnajzVOwrGrEVt9U0mX22zcVlunLMWC49z2dqGjl91Ppw0Xr5ed+QrKWm9Ldg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.1.0" + "@angular-eslint/bundled-angular-compiler": "22.5.0" }, "peerDependencies": { "@typescript-eslint/utils": "^8.0.0", @@ -296,10 +292,9 @@ } }, "node_modules/@angular/animations": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-22.1.3.tgz", - "integrity": "sha512-EgL1BrPcn3yaRamr/R9NlYlV6hZzzKRGxVp/cnfkYzzWKG4Wcno7lkGEo6eA2Vry66AJuXUu4M1BMyhHJ96zzg==", - "deprecated": "@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-22.2.0.tgz", + "integrity": "sha512-JfBaStn07PC4kIw7vHPlKgyjzIM+d3ZgoxjHuTbLMa6lW1IXmUqgJVNSzgI3TUWmYUBtereMjOnZ2PVuIA+L4g==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -308,42 +303,43 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/core": "22.1.3" + "@angular/core": "22.2.0" } }, "node_modules/@angular/build": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-22.1.6.tgz", - "integrity": "sha512-J7JBd3hDAV4dlGNMavDC0KjtvbDd4KOddaom1inwkq92tYnD1ljmhDDigAsUBnRvQhJ82cvagD8zi0s9Ki4rTQ==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-22.2.0.tgz", + "integrity": "sha512-9ABYN9zp4DqDfZxiqyIMEB5iec6xIuVys+BfVjOFkwd3tCnOK+DnRtU8OmI7R8BxUZwLzbPqFffZzvCVVfHP7Q==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2201.6", - "@babel/core": "8.0.1", - "@babel/helper-annotate-as-pure": "8.0.0", - "@babel/helper-split-export-declaration": "7.24.7", - "@inquirer/confirm": "6.1.1", + "@angular-devkit/architect": "0.2202.0", + "@babel/core": "8.0.5", + "@inquirer/confirm": "6.3.2", + "@parcel/watcher": "2.6.0", "@vitejs/plugin-basic-ssl": "2.3.0", - "beasties": "0.4.3", + "beasties": "0.5.4", "browserslist": "^4.26.0", + "chokidar": "5.0.0", "esbuild": "0.28.2", "https-proxy-agent": "9.1.0", "jsonc-parser": "3.3.1", - "listr2": "11.0.0", - "magic-string": "1.0.0", + "listr2": "11.1.0", + "magic-string": "1.4.1", "mrmime": "2.0.1", - "oxc-parser": "0.142.0", + "oxc-parser": "0.150.0", "parse5-html-rewriting-stream": "8.0.1", - "picomatch": "4.0.5", - "piscina": "5.2.0", - "rolldown": "1.2.0", - "sass": "1.101.0", + "picomatch": "4.0.7", + "piscina": "5.3.2", + "rolldown": "1.2.8", + "sass": "1.104.1", + "sass-embedded": "1.104.1", "semver": "7.8.5", "source-map-support": "0.5.21", "tinyglobby": "0.2.17", - "vite": "8.1.5", - "watchpack": "2.5.2" + "vite": "8.3.0", + "xxhash-wasm": "1.1.0" }, "engines": { "node": "^22.22.3 || ^24.15.0 || >=26.0.0", @@ -361,7 +357,7 @@ "@angular/platform-browser": "^22.0.0", "@angular/platform-server": "^22.0.0", "@angular/service-worker": "^22.0.0", - "@angular/ssr": "^22.1.6", + "@angular/ssr": "^22.2.0", "istanbul-lib-instrument": "^6.0.0", "karma": "^6.4.0", "less": "^4.2.0", @@ -371,7 +367,7 @@ "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", "typescript": ">=6.0 <6.1", - "vitest": "^4.0.8" + "vitest": "^4.0.8 || ^5.0.0" }, "peerDependenciesMeta": { "@angular/core": { @@ -418,6 +414,438 @@ } } }, + "node_modules/@angular/build/node_modules/@babel/core": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-8.0.5.tgz", + "integrity": "sha512-2/oWkgTbBYoqioCWAE4XJobOrzwxTDa5/XjDP3tJ1BhDr/owcd9qnXBp4xc3/2G5X4bvXM04nrxbRJxFcXAxFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^8.0.0", + "@babel/generator": "^8.0.5", + "@babel/helper-compilation-targets": "^8.0.5", + "@babel/helpers": "^8.0.5", + "@babel/parser": "^8.0.5", + "@babel/template": "^8.0.0", + "@babel/traverse": "^8.0.5", + "@babel/types": "^8.0.5", + "@types/gensync": "^1.0.5", + "convert-source-map": "^2.0.0", + "empathic": "^2.0.1", + "gensync": "^1.0.0-beta.2", + "import-meta-resolve": "^4.2.0", + "json5": "^2.2.3", + "obug": "^2.1.1", + "verkit": "^0.3.2" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/build/node_modules/colorjs.io": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.7.1.tgz", + "integrity": "sha512-LY7OHnJZxHwT5UlzNa9bbhHHDbzB6yE5+3MIPwJEQKRvSCt/T4G7epsj+9j2BExUIIfXFIJGsIXUKdfrK9Q5tA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/color" + } + }, + "node_modules/@angular/build/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular/build/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.104.1.tgz", + "integrity": "sha512-7LxbtPJ1MWKVbhzOnGx1sHTkHTcHVJ9hbgVsU29p/8gY1VeXt19fcJFr5xsx2f6zfrrR3FeOcYMt0uYDLAxpgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "colorjs.io": "^0.7.0", + "immutable": "^5.1.5", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.104.1", + "sass-embedded-android-arm": "1.104.1", + "sass-embedded-android-arm64": "1.104.1", + "sass-embedded-android-riscv64": "1.104.1", + "sass-embedded-android-x64": "1.104.1", + "sass-embedded-darwin-arm64": "1.104.1", + "sass-embedded-darwin-x64": "1.104.1", + "sass-embedded-linux-arm": "1.104.1", + "sass-embedded-linux-arm64": "1.104.1", + "sass-embedded-linux-musl-arm": "1.104.1", + "sass-embedded-linux-musl-arm64": "1.104.1", + "sass-embedded-linux-musl-riscv64": "1.104.1", + "sass-embedded-linux-musl-x64": "1.104.1", + "sass-embedded-linux-riscv64": "1.104.1", + "sass-embedded-linux-x64": "1.104.1", + "sass-embedded-unknown-all": "1.104.1", + "sass-embedded-win32-arm64": "1.104.1", + "sass-embedded-win32-x64": "1.104.1" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-all-unknown": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.104.1.tgz", + "integrity": "sha512-toyMCyUKkT6DsYlHuKZGjd8T6WltaW4TGX07F7HnF4tNJM5m/8VaVsd74zrq3QSPqGE9JjxIDK4NrNc/QY9pkA==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "sass": "1.104.1" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-android-arm": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.104.1.tgz", + "integrity": "sha512-g/XPAJYAzSSQZFP4xCdGD0HLKB4mf24cJ/+5Nls8rMool3jNkBv9+AFO4EV0b+RxN8rLcEsMccH1CR64yIFYcQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-android-arm64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.104.1.tgz", + "integrity": "sha512-yW3BVW4YFpN2vu2cVQ+Pz5JrRTvoIz36aCdo+J/Mo1A9gEN8eVPV/AL7aeZ803YdKgIitd3qw3pY4wpmT6TXNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-android-riscv64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.104.1.tgz", + "integrity": "sha512-ZYY8oMKQS7Q/6FBoC8w3T16O3MucDe3xv8iKym41Nht5uvLCGGpm4fC4OF5nlv7wQkJv8oactYddGG3Wd0Rqkg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-android-x64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.104.1.tgz", + "integrity": "sha512-5WZKC4lSfjMIjzZdQUlYQUAV+UiatBhD8w28U7cYLLj4/dMgEPOBd4g3VMv0BwpgH2JOaycMS42dXq29W2bcDg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-darwin-arm64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.104.1.tgz", + "integrity": "sha512-oatuHzn0NsEg0d9Dcze6CuWUPvuETtMxRK4cv0eRAg7p6R0vHnv5GZRyWG6gEy3nc/ha/L+GtTasWVU82f4jrQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-darwin-x64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.104.1.tgz", + "integrity": "sha512-gql/5sHGzUTVwuHfM3QLCDeb6NYwen+LLj22gz81C2NKHF/4nUtDyh4N+fURWdT7J0/EhtMOd0+FLML3sGNP7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-arm": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.104.1.tgz", + "integrity": "sha512-WfmshPJOp9vUKxgp8wZ2ncaKBbyrlW9J51M2aUQHWECjMNxTULnGOHWSmD7FViXv4zwn1Co5FIFQUipW7RCxtA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": "glibc", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-arm64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.104.1.tgz", + "integrity": "sha512-sVWUKXNTu8sP3X95Df0xo/t49Ce5IseTIMqXHxhFBKVmx7gf7kBWNLK0wH5ym+4khc+B5nNJPgq4IxpelG8tMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": "glibc", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-musl-arm": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.104.1.tgz", + "integrity": "sha512-k0cQ/CxBzFVYiQEObg6CpF6CUglkdEhi/DZgZXQbwC27kbGGY+fatmIs/cFPJL2z1ulACwoAr86RQUFzYvw5eg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": "musl", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.104.1.tgz", + "integrity": "sha512-H7b+LzZ/w8pwNExInM8HDHraqvxCMdUc5ZRGU/aSJJhZ9HjeRKBjF3GxaisVHnx7o18j1l4VQ5cLBL9tTmNzZw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": "musl", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.104.1.tgz", + "integrity": "sha512-9DYdn4wfrkidjxJVtEd2iCx8HKdZe+uF82GDmrYEZhgu4NjVE6a4fQyW7OLwzn3erZMHKBaObBOH1d37DnXI1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": "musl", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-musl-x64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.104.1.tgz", + "integrity": "sha512-5xz+nAr01b6yaRdrGVgE7lNvm1lGFjwNdUvnz+teidvHCbD5oTcbhrRVrnDoLHHvq5n3Jve9TzWaaHhezaEfHA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": "musl", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-riscv64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.104.1.tgz", + "integrity": "sha512-oWryPJWTXK5adtlz/FD7wd2kS4I0CEgp6mWLUVb4oMFURMLz9bA9fO87D7lc4SV++lds7T51PU1kykCbOvNHMg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": "glibc", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-linux-x64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.104.1.tgz", + "integrity": "sha512-j/sX/yKTx/wJKepC5/ISlR6kPeSuHKThf76D2za5i2VnbHg0MN19jQq3WMorowR3kRghqt6azs3awogG+e7IRA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": "glibc", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-unknown-all": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.104.1.tgz", + "integrity": "sha512-RaMsYZB5mRioL4qhoI7T5mmNb2OunakbPTJW2cuu3MeIULnGoxo7Wd5QKFxeQvF7sSQL57RuaQ+q9pH+/pQ9Fg==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], + "dependencies": { + "sass": "1.104.1" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-win32-arm64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.104.1.tgz", + "integrity": "sha512-fS6DL7lcnTPclqGLF4xRt8egZlFY9cU23d57ufbWqaUbCFu9JTu0+8qB4jMxfx1la6byi3GoSTfbnNOLfWv8sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/sass-embedded-win32-x64": { + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.104.1.tgz", + "integrity": "sha512-/c4N2A93Ckms6DuRFVftKYISuI1tyC8gmlVJ8WaWFzgCBN/Swq2rARJIBUNeuxlmxjmYXfd3+2f/u887K63wbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@angular/build/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/@angular/cdk": { "version": "22.1.4", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-22.1.4.tgz", @@ -435,26 +863,26 @@ } }, "node_modules/@angular/cli": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.1.6.tgz", - "integrity": "sha512-HT3OzYkSpCyXMTgD5G1tsS7vkrY8cYJ/JgSjRjrpwOAooSMtKF1hv7BgBcn79sKg4eaiPLrDpQLXP93vHxgSFg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.2.0.tgz", + "integrity": "sha512-FW4RCNXaPpbBcS4w6fetTO6eRT0xySYGSdQ2DGREU30G1TBnpJdJ6TAvs8mTBPXNfFMQTyioR2ie7UkJljLJKg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2201.6", - "@angular-devkit/core": "22.1.6", - "@angular-devkit/schematics": "22.1.6", - "@inquirer/prompts": "8.5.2", - "@listr2/prompt-adapter-inquirer": "4.2.5", - "@modelcontextprotocol/sdk": "1.30.0", - "@schematics/angular": "22.1.6", + "@angular-devkit/architect": "0.2202.0", + "@angular-devkit/core": "22.2.0", + "@angular-devkit/schematics": "22.2.0", + "@inquirer/prompts": "8.7.2", + "@listr2/prompt-adapter-inquirer": "4.2.7", + "@modelcontextprotocol/server": "2.0.0", + "@schematics/angular": "22.2.0", "jsonc-parser": "3.3.1", - "listr2": "11.0.0", + "listr2": "11.1.0", "npm-package-arg": "14.0.0", "parse5-html-rewriting-stream": "8.0.1", "semver": "7.8.5", "yargs": "18.1.0", - "zod": "4.4.3" + "zod": "4.6.5" }, "bin": { "ng": "bin/ng.js" @@ -466,9 +894,9 @@ } }, "node_modules/@angular/common": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-22.1.3.tgz", - "integrity": "sha512-QtMkjhiRd0EnmKR50bw3WbCWYTi6CmA72nnSz1BLQPpaLSi2goloCrPPniHz8fP+w2ESrmmlOWxs1Da3COgnQg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-22.2.0.tgz", + "integrity": "sha512-BUKkncKwnaEcF/qatBOpzSIx2NthFZLYlTcE7iHwwsw+XQrwB9hU8Ca/l5HqaTJiMg0D8MjI/SWHnD4LFtNN+w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -477,14 +905,14 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/core": "22.1.3", + "@angular/core": "22.2.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-22.1.3.tgz", - "integrity": "sha512-L8Mw2r7bGG/obqgQC+RU3mdFJ3NtLgO5gWhEC1ylcHpLCMPIAXYsMKJIL8dnS78S1wXo/omXwmJ4FiIlCwWahg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-22.2.0.tgz", + "integrity": "sha512-bnqql/HfhnhDXoS7isNaXJAsbKYszcH+nFVWA6YhiAVZhqo3f+XoQb30qeqNtEOKuuC7SZfaAJ3jBkAvyC5CKg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -494,9 +922,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-22.1.3.tgz", - "integrity": "sha512-37lLaDp0RHWZ/lmJqCmIEr0HOM2D5ulHy61gqTBm7KRj3Y6ZaxR8B/JqZmeIpPzKFILVsga+NQ4A8apBUkmezw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-22.2.0.tgz", + "integrity": "sha512-xDOvPlNv+RT7sE01wjuGFRMc5SDxWs3RZpGfO5NoI3a0jxM87UW49HmmgwQ6PaU0fya9mttNkHufhfOAbh0ZKQ==", "license": "MIT", "dependencies": { "@babel/core": "8.0.1", @@ -516,7 +944,7 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "22.1.3", + "@angular/compiler": "22.2.0", "typescript": ">=6.0 <6.1" }, "peerDependenciesMeta": { @@ -526,9 +954,9 @@ } }, "node_modules/@angular/core": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-22.1.3.tgz", - "integrity": "sha512-313+Xkf970AmStJE0E/zNJW/9xvDExQG+6TNltBBl+KJsW0q5dffK2w2PQfV4mtTquBqYoeHSRsms4WgjBKL8g==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-22.2.0.tgz", + "integrity": "sha512-VhAgJ4GCdGgAy9+zADpSyEM9gt4pKg6+cqNeK3RBNeF3M3B8y7AWfD/nYRdM3Xzi152Pu+ipgFFNHpupCLTsvQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -537,7 +965,7 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "22.1.3", + "@angular/compiler": "22.2.0", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0 || ~0.16.0" }, @@ -551,9 +979,9 @@ } }, "node_modules/@angular/forms": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-22.1.3.tgz", - "integrity": "sha512-b4ual9pgfNqcnEHord50w960DDFIytG3Qb3bu2aCgzmagvRlg9wrtwQNqY+oqY2FVq7c9McNUN7MZRcWl9HNdQ==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-22.2.0.tgz", + "integrity": "sha512-Nm8o1uBk31EuQGzsK5EunNBVFzTN9MuTYLSrmg1SCPTcava4qK3AzSpl1+Put+cZTTnGtEBIy45AFaxHR2oryg==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -564,16 +992,16 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "22.1.3", - "@angular/core": "22.1.3", - "@angular/platform-browser": "22.1.3", + "@angular/common": "22.2.0", + "@angular/core": "22.2.0", + "@angular/platform-browser": "22.2.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-22.1.3.tgz", - "integrity": "sha512-Nc5cHyuYTTH9uENTSmJFiqR85xPGFkpOwxN6Ms2qlqz767FyOXna0iqw2DprNRB1+xG/WtP4RbCI6ofyXHbM0w==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-22.2.0.tgz", + "integrity": "sha512-J1uqzKP2/u5hWp8ShskUyuwp8J9EjbNnAjvmp4Klor9hwtlQ48e4wW8+Wd7ugrxbjDQ57dwHlOoeXuQLRCjonQ==", "dev": true, "license": "MIT", "engines": { @@ -581,9 +1009,9 @@ } }, "node_modules/@angular/localize": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-22.1.3.tgz", - "integrity": "sha512-/u0nCz2AY+RXB4HUdw3Y7C/ZiierPPmUuWR/nDPCylHwllVdMKpi6PPtKvfzgM5ZvaISzDghTVykOVjU7obMhg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-22.2.0.tgz", + "integrity": "sha512-RfaF5tAKWyQwGzu0P5bJUavB8QWrWdM/xU5gDXydIFopBk4WERaMYh5E5fGm39h09dod2vmFH3JND1Ht0Vgy6w==", "license": "MIT", "dependencies": { "@babel/core": "8.0.1", @@ -599,8 +1027,8 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/compiler": "22.1.3", - "@angular/compiler-cli": "22.1.3" + "@angular/compiler": "22.2.0", + "@angular/compiler-cli": "22.2.0" } }, "node_modules/@angular/material": { @@ -621,9 +1049,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-22.1.3.tgz", - "integrity": "sha512-A8McE6AclwZa2ese4jMfZZu+qZfBFQ4Hl6CaMpzJ1C6Vv6+sXkLu9pouTosJEsUE+etVdepDsqau90lhzgw3Eg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-22.2.0.tgz", + "integrity": "sha512-XMUOyn8WARk9NdFGO3uRgdC3hPrp+2xsSYNeSkaEZ4jI3Pc23f22e4GI8Vayl/UOmShHVn/i+NWfTWh3SEbbSw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -632,9 +1060,9 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/animations": "22.1.3", - "@angular/common": "22.1.3", - "@angular/core": "22.1.3" + "@angular/animations": "22.2.0", + "@angular/common": "22.2.0", + "@angular/core": "22.2.0" }, "peerDependenciesMeta": { "@angular/animations": { @@ -643,10 +1071,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-22.1.3.tgz", - "integrity": "sha512-dXI8U7C4QZOvWIA2VWPFjGQjJ6ceHlYRkShdvaluKmml6CxxPPvirjwQGj+G/syfAaArSzLijK4hM9xDuMo41w==", - "deprecated": "@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-22.2.0.tgz", + "integrity": "sha512-KG/m6Jz3tKAeXWFYFgEISiEsWSBQusemI+/uafmq2GYiI4cZneCeW35v7mHujgFzVH8jzyJwPyPQtpnKDdGg6g==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -655,16 +1082,16 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "22.1.3", - "@angular/compiler": "22.1.3", - "@angular/core": "22.1.3", - "@angular/platform-browser": "22.1.3" + "@angular/common": "22.2.0", + "@angular/compiler": "22.2.0", + "@angular/core": "22.2.0", + "@angular/platform-browser": "22.2.0" } }, "node_modules/@angular/platform-server": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-22.1.3.tgz", - "integrity": "sha512-tzbMQSwHx2oIIjWQAgRunNNz3FW+AMYiUwVtdkKBXvPSp2d/ry+/6XO6fZ0BIi3ejhwtfIJL3GlOtmPMCHTkyw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-22.2.0.tgz", + "integrity": "sha512-Ppb0Zqr0lLubAW2UvjsNYDuoh+WX8ZeKdrmEMa8qhpVIxD1UL6CAQnKSlQQabWfuCQOphzBi7u7QeotGsTajKQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0", @@ -674,17 +1101,17 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "22.1.3", - "@angular/compiler": "22.1.3", - "@angular/core": "22.1.3", - "@angular/platform-browser": "22.1.3", + "@angular/common": "22.2.0", + "@angular/compiler": "22.2.0", + "@angular/core": "22.2.0", + "@angular/platform-browser": "22.2.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/router": { - "version": "22.1.3", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-22.1.3.tgz", - "integrity": "sha512-23owvZKCpdL7Yh3EzBj4OLf3x0z+jT9b57Qk96wdwI8Lsyf9L78/RJPYCutJ5r+zq3pFM/BHVKyd+2hkfH7N6Q==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-22.2.0.tgz", + "integrity": "sha512-+pxHMwWWKg+ejS1vKa+tS91CDusCIK1MOSy6fVLc89McMOY/C8tsLrh1uJaMjklejsz+3XUhJgrLOvl3ISNz6w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -693,18 +1120,19 @@ "node": "^22.22.3 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "@angular/common": "22.1.3", - "@angular/core": "22.1.3", - "@angular/platform-browser": "22.1.3", + "@angular/common": "22.2.0", + "@angular/core": "22.2.0", + "@angular/platform-browser": "22.2.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/ssr": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-22.1.6.tgz", - "integrity": "sha512-MvSaCg2Kren50Ei8o98bDG4555aNAQdeP+PfamOyUPWx3LBdoW5LEhnOq7yxWDcuzyXIs/k0DjQnbojPH/75Uw==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-22.2.0.tgz", + "integrity": "sha512-5BMf7oS+KQh7KvOAGqEwQ0zkPUvFT4DwHNsAlOSdjQhJ9Xfq+m5VxclePSek4Y4ykmcIjyI60tgF1yHd36c7ow==", "license": "MIT", "dependencies": { + "beasties": "0.5.4", "tslib": "^2.3.0" }, "peerDependencies": { @@ -720,12 +1148,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-8.0.0.tgz", - "integrity": "sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-8.0.6.tgz", + "integrity": "sha512-uMHhvmDmwFiLuiozaoRYTZHqMFuu3fem/X9JY78lohAuLoh8LSGGC8JqUzo2cVuBsBxkjMZNk56CE7ock8Xxkw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^8.0.0", + "@babel/helper-validator-identifier": "^8.0.6", "js-tokens": "^10.0.0" }, "engines": { @@ -733,9 +1161,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-8.0.0.tgz", - "integrity": "sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-8.0.5.tgz", + "integrity": "sha512-YLsYoQMvL8l8WrGpN3Zj7O1wK5LEBN+cQtux7BcuHyxIXve724XG+zuJ1n3U1cUweRtTzQOA4IHbuQw3N34SZw==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" @@ -779,15 +1207,15 @@ "license": "MIT" }, "node_modules/@babel/generator": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0.tgz", - "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^8.0.0", - "@babel/types": "^8.0.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.6.tgz", + "integrity": "sha512-/pcanjdRsonCexCuxgGD8fKnBLLzk2i9uM4kmcmGyyev2R5YDs+rafMYZ89RvaGY1mW8T7C5au0TyYaEeHBGng==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^8.0.6", + "@babel/types": "^8.0.6", + "@jridgewell/gen-mapping": "0.4.0-beta.0", + "@jridgewell/trace-mapping": "^0.3.31", "@types/jsesc": "^2.5.0", "jsesc": "^3.0.2" }, @@ -795,39 +1223,36 @@ "node": "^22.18.0 || >=24.11.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-8.0.0.tgz", - "integrity": "sha512-NSpMkMsvvZqzThJ0p1B02cbtA2ObEyfBvq950bmNkyxsxvcxwhvvCB036rKhlEnuBBo30bOrk13u3FzlKSoRrw==", - "dev": true, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.4.0-beta.0.tgz", + "integrity": "sha512-JdGNkbE4GlNPYQhM0L95fBQr7ctLZJ276QXQLTad4t1oSdnnCI3fDq9DW3BqYAWv8Wc3+HS+4Gsii1oPMCfz1w==", "license": "MIT", "dependencies": { - "@babel/types": "^8.0.0" - }, - "engines": { - "node": "^22.18.0 || >=24.11.0" + "@jridgewell/sourcemap-codec": "^1.6.0-beta.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-8.0.0.tgz", - "integrity": "sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-8.0.6.tgz", + "integrity": "sha512-HTrtZ4+iA0+kzdbCgvdSk1U4pEl3BvpGnlUbualCGNbrVhhQvhgBzurTUmqpWyvyHbWYWaIfdx2mOlL9LJjsew==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^8.0.0", + "@babel/compat-data": "^8.0.5", "@babel/helper-validator-option": "^8.0.0", "browserslist": "^4.24.0", - "lru-cache": "^11.0.0", - "semver": "^7.7.3" + "flru": "1.0.2", + "verkit": "^0.3.2" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helper-globals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-8.0.0.tgz", - "integrity": "sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-8.0.6.tgz", + "integrity": "sha512-OdnA/N52LhzFpeUuVz5YGuSWjc7TPHiFmVYZbPlSgExocO2GwbxVpSni9MVs5wwW+wZ4kPuwBEBN9pIPDYz1mA==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" @@ -980,66 +1405,19 @@ "dev": true, "license": "MIT" }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", - "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz", - "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.6.tgz", + "integrity": "sha512-+6HYEBnsDRZHJtUTAEfMQd0zMDqdFHS7C+5vAsEZqBUr3vEMWOWlHJ0Jz1gS8jJIlCvLsuA6ivmeoqzH936YcA==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz", - "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.6.tgz", + "integrity": "sha512-HYx0YmuchRxRSpnjvcNffnPS8DCauKNmnumIuHG3jnQAVewRA7kfJGwF13ayEpSZs7s4R/oBH4eppuXcAQd5JQ==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" @@ -1055,25 +1433,25 @@ } }, "node_modules/@babel/helpers": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-8.0.0.tgz", - "integrity": "sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-8.0.5.tgz", + "integrity": "sha512-fQtPOXjYOYv85PIdwotp2TJGVYOycX0PQq+l844fFAxOULtBy8BVF35GyeueX0r4KvDthqPH5xAI1clQPk/2uA==", "license": "MIT", "dependencies": { "@babel/template": "^8.0.0", - "@babel/types": "^8.0.0" + "@babel/types": "^8.0.5" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/parser": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz", - "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.6.tgz", + "integrity": "sha512-LpGDIYJAzc3Y3PT9x+FxBrGYu2PlWxLmyN7SwPTzaX0LSwEmFJBsRnPBqmaXF2r1v+Zhz6lNiEJ+7yKtM5+Ugg==", "license": "MIT", "dependencies": { - "@babel/types": "^8.0.4" + "@babel/types": "^8.0.6" }, "bin": { "parser": "bin/babel-parser.js" @@ -1106,17 +1484,17 @@ } }, "node_modules/@babel/traverse": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.4.tgz", - "integrity": "sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.6.tgz", + "integrity": "sha512-ilYV+qLStGzSKLipJlETdvdtpK3rAuwfCmCoGKv15MU4EoeIuLkespSNoNLFGOPSciEHx9TLWtN5mv0fz5w5mQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^8.0.0", - "@babel/generator": "^8.0.0", - "@babel/helper-globals": "^8.0.0", - "@babel/parser": "^8.0.4", + "@babel/code-frame": "^8.0.6", + "@babel/generator": "^8.0.6", + "@babel/helper-globals": "^8.0.6", + "@babel/parser": "^8.0.6", "@babel/template": "^8.0.0", - "@babel/types": "^8.0.4", + "@babel/types": "^8.0.6", "obug": "^2.1.1" }, "engines": { @@ -1124,13 +1502,13 @@ } }, "node_modules/@babel/types": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz", - "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.6.tgz", + "integrity": "sha512-c+xgSWboV2pdwXP67BUWDVRHi2BO5Q3KwxyFVs7taVTY+fsK47/L51ZXQoV9rozHJDNHvJ4v4WEsI/IlxV2l2A==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^8.0.0", - "@babel/helper-validator-identifier": "^8.0.4" + "@babel/helper-string-parser": "^8.0.6", + "@babel/helper-validator-identifier": "^8.0.6" }, "engines": { "node": "^22.18.0 || >=24.11.0" @@ -1738,9 +2116,9 @@ "license": "MIT" }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -1836,9 +2214,9 @@ "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -2574,9 +2952,9 @@ "license": "MIT" }, "node_modules/@inquirer/ansi": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.7.tgz", - "integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.8.tgz", + "integrity": "sha512-WpQM+Ti6Z40EFwwt+uL2p4UabT+W179zHp6HhLVOzfbwnVn05IPO/eXIZXGNqcT1jbQ15SujNLzQ39k4QPPxBQ==", "dev": true, "license": "MIT", "engines": { @@ -2584,43 +2962,16 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.2.tgz", - "integrity": "sha512-Y5/bAScMy5Y+9isCx0SKbyJebMCaXXX5em0kxkj115eZNscgV9srOHrgyfS0e5xAVymIfOh9piYBKDILktsMMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^12.0.0", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/checkbox/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.5.tgz", + "integrity": "sha512-bRt8J8m+Fot9CXv+zNQGXUq2ET0MggR1fPz7v6edN6MFYmsbfGnMmkmWZJEegMKqrAC8ej/o1sqisHZXZJMAfQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2635,14 +2986,14 @@ } }, "node_modules/@inquirer/confirm": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.1.1.tgz", - "integrity": "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.3.2.tgz", + "integrity": "sha512-Xvr/0HggjddPtGppuqVmxhTw+Hr8PvsZ/k0HmOEaAqQEt80OITNkFWnsdNmyT0/eM4Ab+iJLx2R8rctlEyfSVg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2657,15 +3008,15 @@ } }, "node_modules/@inquirer/core": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz", - "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==", + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.3.tgz", + "integrity": "sha512-wsSy0sznmXwkty+2PzZwx00Cazc/E0r0B7mAzdGROz2Ct+DFZXaK7WDjGZvgjRldxH5ZhFVfF2lgkYrqgOw2KA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.7", - "@inquirer/type": "^4.0.7", + "@inquirer/ansi": "^2.0.8", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1", "cli-width": "^4.1.0", "fast-wrap-ansi": "^0.2.0", "mute-stream": "^3.0.0", @@ -2684,221 +3035,15 @@ } }, "node_modules/@inquirer/editor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.3.0.tgz", - "integrity": "sha512-nnsP/IdJ8s83q7ZuObmgn12QM+uLCkab9E0Oordojbn62WUg1c+v9Ou/F/057pgh0ppX0W+Hj5bO/Dp5hsxQtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/external-editor": "^3.0.4", - "@inquirer/type": "^4.0.7" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.2.tgz", - "integrity": "sha512-OWIH1IyyWqEKIyqC9Xy+Bnga7NkGMovFdo4atYZMUOTRqf6rO2WCv9E/1MyzvOErDBCxs+9UFliRUDc50xs/jw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/type": "^4.0.7" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.4.tgz", - "integrity": "sha512-tZbbaK2ovq6vlrRBNQvjrypmrED/p5x2ncIHQ79cD55tei3dD96v5glMMA+6tiq7K104i/25DVYKWVPJuV6ptA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.2" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.8.tgz", - "integrity": "sha512-tApbon79GM9ry56ja/Ud3SY2CL4TQsao9fIwDQbgTeNY55025GdMzQ2+UdegV/lx51VNGUB59M0v0nMpybYY4Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - } - }, - "node_modules/@inquirer/input": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.3.tgz", - "integrity": "sha512-F/BZHtyEzP+HO+IGVd4AjBRgvX/ywm42bx8S0+dENk2YclzE9tJ3X/15THwtT6ehApmKvdYDMsVTuyyDod0gOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/type": "^4.0.7" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/input/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.2.0.tgz", - "integrity": "sha512-ew+fSDijsQ/WhD4TV3XLb+if400cDuzTzHfGR8sTNBXkK9CYDWoGE8fhaO8GbT312pNv1AJEOsDxy/z/HVettA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/type": "^4.0.7" - }, - "engines": { - "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.3.3.tgz", + "integrity": "sha512-YsKkS2q63IiLtaDK/9nqzdComN97SDQrmKiyNggN+ceP4ty+Z6VwyTz3FpjeUWeW1Efss2xHFKCC9sx7hnrsxg==", "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "dependencies": { + "@inquirer/core": "^12.0.3", + "@inquirer/external-editor": "^3.0.5", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2912,16 +3057,15 @@ } } }, - "node_modules/@inquirer/password": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.1.2.tgz", - "integrity": "sha512-nSdufycW8xynEVssFkNQEYIzTySilog0UlfOVRwh3pXzPSk4frXUT2jZWjHnKae6RU9PaoF9wfy1pGwewQuqGw==", + "node_modules/@inquirer/expand": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.5.tgz", + "integrity": "sha512-uHuXLmXW+TtIfT/9vSBotypAkqn1n34Ul+CLGPos/xANyO4Ff5xZzkYhbKR4NEcfVK4a9mHQOpwVZzluSHFRGw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^12.0.0", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2935,20 +3079,15 @@ } } }, - "node_modules/@inquirer/password/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "node_modules/@inquirer/external-editor": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.5.tgz", + "integrity": "sha512-f3QQJRIX5ZEneBHNUIuPjmbdzHnmRFJA8r2dkcb8q+OM5Uv5KtnuAttQumnrjcBVBM3mcTX1CkmtAkU58VRZxg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2962,23 +3101,25 @@ } } }, - "node_modules/@inquirer/prompts": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.5.2.tgz", - "integrity": "sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==", + "node_modules/@inquirer/figures": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.9.tgz", + "integrity": "sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" + } + }, + "node_modules/@inquirer/input": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.6.tgz", + "integrity": "sha512-HtcJhB2QFVXbLuJ5S3syhNbTUVxYvwqV4VRBDkQceBloC9bmTViUoRFP5PbSaDZb3HzfPmpuU/gG4ybVBz4FHA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^5.2.1", - "@inquirer/confirm": "^6.1.1", - "@inquirer/editor": "^5.2.2", - "@inquirer/expand": "^5.1.1", - "@inquirer/input": "^5.1.2", - "@inquirer/number": "^4.1.1", - "@inquirer/password": "^5.1.1", - "@inquirer/rawlist": "^5.3.1", - "@inquirer/search": "^4.2.1", - "@inquirer/select": "^5.2.1" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -2992,15 +3133,15 @@ } } }, - "node_modules/@inquirer/rawlist": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.2.tgz", - "integrity": "sha512-oPSKrYK1X1bMkjXDzIKHUkJp195LFSfgbnVtXnjSKGFjrCbS6I+wyvfAZTwKE9BSt3HwWgfD7JfsXALBgCogzQ==", + "node_modules/@inquirer/number": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.2.3.tgz", + "integrity": "sha512-6Yuwh1NGSbu1Lo4N1EWjXs1jKRntLg/ZCwhmeorEHde90v1XxAozdbd4Iu30eOQLW+6h1hp2O9ujNfLSbTPJnA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3014,20 +3155,16 @@ } } }, - "node_modules/@inquirer/rawlist/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "node_modules/@inquirer/password": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.2.2.tgz", + "integrity": "sha512-W9zYdyzogK+6110mqwaSJWCBu2yA5Q/OfnGSjjZB1bNpHlmUozXxTl0+QOZBNeVd6Qo81/qT75gW05gLAtITxw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3041,16 +3178,23 @@ } } }, - "node_modules/@inquirer/search": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.3.0.tgz", - "integrity": "sha512-HFxXE5w727ctSUcAwrDquftJGjMgu36OeV5SHEXMlr2j/ahzmRX9xSEeVolV8tzYnTf45cg6vGkdMMRdm3RPhQ==", + "node_modules/@inquirer/prompts": { + "version": "8.7.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.7.2.tgz", + "integrity": "sha512-QoRB4wFIjgH5iOhSjoIKMkTvSHDuV+O3OITlIqAYO0oK5x364GJILXiMBvlPiE+klg7Xx9tq5XVqQHcGUDYYPA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^12.0.0", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7" + "@inquirer/checkbox": "^5.2.5", + "@inquirer/confirm": "^6.3.2", + "@inquirer/editor": "^5.3.3", + "@inquirer/expand": "^5.1.5", + "@inquirer/input": "^5.1.6", + "@inquirer/number": "^4.2.3", + "@inquirer/password": "^5.2.2", + "@inquirer/rawlist": "^5.3.5", + "@inquirer/search": "^4.3.3", + "@inquirer/select": "^5.2.5" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3064,20 +3208,15 @@ } } }, - "node_modules/@inquirer/search/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "node_modules/@inquirer/rawlist": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.5.tgz", + "integrity": "sha512-1oHky1ONfCOwNrnkQGDE1oaSij/3fI6HFMSf2H/WsGO2lEyDX9My82iggITSy9ddSZ8yk8j9v41OI0fVoSIoaA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3091,17 +3230,16 @@ } } }, - "node_modules/@inquirer/select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.2.tgz", - "integrity": "sha512-RkI8dRHWt+bh04oLixvF1kFzKC7e5rqJoHKkzcqSHATebBXFC6GmrT8ddbVkgSzLV0HnHs2cPFuBINr8otij8Q==", + "node_modules/@inquirer/search": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.3.3.tgz", + "integrity": "sha512-fyuIU1Nbpvwlikjg3gXwJFDI11+EFjqQ7P+iByfmivIKQ1vmaykNrD/vy5unHuUqUpsOsnvJ25//tPF7E/RBRA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^12.0.0", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3115,20 +3253,17 @@ } } }, - "node_modules/@inquirer/select/node_modules/@inquirer/core": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.0.tgz", - "integrity": "sha512-+nnvFEXIB08CZNVXpvW3B+zHW96QXvGUjNKJ8NJIPqAZi5Kd4WhYt2S3C234ReepG1qw2HOlEUbjYVHBowXObA==", + "node_modules/@inquirer/select": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.5.tgz", + "integrity": "sha512-9kc15hr8r/kI+3DO/xLog5nOzTz1jqsHXa6JBFzmQKhkoJ8Slda1I1L/uD8ZSZ9tF1yp79wwXe7mclvX1rqR2Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.8", - "@inquirer/type": "^4.0.7", - "cli-width": "^4.1.0", - "fast-wrap-ansi": "^0.2.0", - "mute-stream": "^3.0.0", - "signal-exit": "^4.1.0" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -3143,9 +3278,9 @@ } }, "node_modules/@inquirer/type": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.7.tgz", - "integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.1.1.tgz", + "integrity": "sha512-yJoHYrMnxIsJZCY+0Vb66Dy3he3kL3e2wOBKhoSwWWAzZAY82emlxwgprCtp6yRixvNRNq9ztfRWQYPNr3Go7A==", "dev": true, "license": "MIT", "engines": { @@ -3210,9 +3345,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -3233,9 +3368,9 @@ "license": "Apache-2.0" }, "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-4.2.5.tgz", - "integrity": "sha512-pYGy9dTdTwXdasPgyohkr0HoQ4FrkAzFnsUZl/gcnadDArbpZ8e+fgr+F9WBdNEl2y00mb9bCM4WgmoBkZJ27A==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-4.2.7.tgz", + "integrity": "sha512-k180vxSv2KqmnDxoato6pCqEJsov4U5C0EVmldZkAdNeVBxY48A/LM6TCNPGIzDK/iZSfsZP0Mw+gbWc5hXLyA==", "dev": true, "license": "MIT", "dependencies": { @@ -3246,7 +3381,7 @@ }, "peerDependencies": { "@inquirer/prompts": ">= 3 < 9", - "listr2": "11.0.0" + "listr2": "11.1.0" } }, "node_modules/@lit-labs/ssr-dom-shim": { @@ -3255,16 +3390,6 @@ "integrity": "sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==", "license": "BSD-3-Clause" }, - "node_modules/@lit-labs/virtualizer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@lit-labs/virtualizer/-/virtualizer-2.1.1.tgz", - "integrity": "sha512-JWxMwnlouLdwpw8spLTuax53WMnSP3xt0dCyxAS7GJr5Otda9MGgR/ghAdfwhSY75TmjbE1T2TqChwoGCw3ggw==", - "license": "BSD-3-Clause", - "dependencies": { - "lit": "^3.2.0", - "tslib": "^2.0.3" - } - }, "node_modules/@lit/context": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.6.tgz", @@ -3394,6 +3519,19 @@ "ws": "^7.5.10" } }, + "node_modules/@modelcontextprotocol/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/core/-/core-2.0.0.tgz", + "integrity": "sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "zod": "^4.2.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", @@ -3746,6 +3884,20 @@ "url": "https://opencollective.com/express" } }, + "node_modules/@modelcontextprotocol/server": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/server/-/server-2.0.0.tgz", + "integrity": "sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/core": "2.0.0", + "zod": "^4.2.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", @@ -4196,26 +4348,26 @@ } }, "node_modules/@ng-bootstrap/ng-bootstrap": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-20.0.0.tgz", - "integrity": "sha512-Jt+GUQ0PdM8VsOUUVr7vTQXhwcGwe2DCe1mmfS21vz9pLSOtGRz41ohZKc1egUevj5Rxm2sHVq5Sve68/nTMfA==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-21.0.0.tgz", + "integrity": "sha512-H7lGYGQGERoX5PeU1nf99U8tvPBJwQod6G99NoaJYwhBtKDoA/W0auUJqcbPMOGnO3gHtjtnOCji49tRbUIbPw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^21.0.0", - "@angular/core": "^21.0.0", - "@angular/forms": "^21.0.0", - "@angular/localize": "^21.0.0", + "@angular/common": "^22.0.0", + "@angular/core": "^22.0.0", + "@angular/forms": "^22.0.0", + "@angular/localize": "^22.0.0", "@popperjs/core": "^2.11.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@oxc-parser/binding-android-arm-eabi": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.142.0.tgz", - "integrity": "sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.150.0.tgz", + "integrity": "sha512-oQef2Zu4Prz1KLKznz3HqZzU9uVoA5PMoDZuuLmqms7hKmKSAPzlaMnLllJq3t+rgKmfJJ2siPrpZfFrW06btw==", "cpu": [ "arm" ], @@ -4230,9 +4382,9 @@ } }, "node_modules/@oxc-parser/binding-android-arm64": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.142.0.tgz", - "integrity": "sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.150.0.tgz", + "integrity": "sha512-B6ofpoFiAUwIZ0MJ2IgHPvZK8FAtL4qzSZRwOkAKIfxEobE1mQC8nDdiFZj7pUaJiVUVCsfkMsBJKedzO8rZvA==", "cpu": [ "arm64" ], @@ -4247,9 +4399,9 @@ } }, "node_modules/@oxc-parser/binding-darwin-arm64": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.142.0.tgz", - "integrity": "sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.150.0.tgz", + "integrity": "sha512-J+9IHKzx/bSz1JetOfD4zKXSK9sOm4/a7+0qomJODcTL6JsRXGeV/ZdkAPSIDydfFmWzYCraMlQEosSZEyBYkQ==", "cpu": [ "arm64" ], @@ -4264,9 +4416,9 @@ } }, "node_modules/@oxc-parser/binding-darwin-x64": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.142.0.tgz", - "integrity": "sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.150.0.tgz", + "integrity": "sha512-v6IPfcAcSYrBWXV5Tce1DmxDMXLhEYpIIWiRFPJopgCVscZdLaV4MRQOUxvL3usQlw+yrwYOjBFB9IwBx+jUiQ==", "cpu": [ "x64" ], @@ -4281,9 +4433,9 @@ } }, "node_modules/@oxc-parser/binding-freebsd-x64": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.142.0.tgz", - "integrity": "sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.150.0.tgz", + "integrity": "sha512-AoR/4jD02HET0KO0yNT4nbTE+XJUxiO9jB1X/ycEjUE3WrIJ3IjV/Vf+gskhWLcqqeXfvNnkDtBR7epllAm88A==", "cpu": [ "x64" ], @@ -4298,9 +4450,9 @@ } }, "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.142.0.tgz", - "integrity": "sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.150.0.tgz", + "integrity": "sha512-A/hycCFjLUrCmLoL5O/vBp40ohlaXO1Ta3v5hqYZxicYFs129wZmgZJggcW4mYGYbZebQLhup+N8JjeQl8qwyw==", "cpu": [ "arm" ], @@ -4315,9 +4467,9 @@ } }, "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.142.0.tgz", - "integrity": "sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.150.0.tgz", + "integrity": "sha512-pbqahg1Pkz7J4RKmXm30s/iQu99hv64ayXCu8P4p75HcEH5azOdR4eGqiB6lFGkFR3mMpzaYsSKLkS8oJbjmeQ==", "cpu": [ "arm" ], @@ -4332,9 +4484,9 @@ } }, "node_modules/@oxc-parser/binding-linux-arm64-gnu": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.142.0.tgz", - "integrity": "sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.150.0.tgz", + "integrity": "sha512-HV11aRbBQGwqv8bEo+K/6qr88uB4fEe1mhXncMhlVCrj+WpBSraxrUzHaPVmeQRU6x6x8v/3DuCbbo93rpp+fw==", "cpu": [ "arm64" ], @@ -4352,9 +4504,9 @@ } }, "node_modules/@oxc-parser/binding-linux-arm64-musl": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.142.0.tgz", - "integrity": "sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.150.0.tgz", + "integrity": "sha512-k6pVkJqALwtEuP4zukVhGRhdIy4+ofChUIUUsAHHyqDZlNsknmel3JjbggrJiWGaes6h/dIcWmEXsKW4SmK9oQ==", "cpu": [ "arm64" ], @@ -4372,9 +4524,9 @@ } }, "node_modules/@oxc-parser/binding-linux-ppc64-gnu": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.142.0.tgz", - "integrity": "sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.150.0.tgz", + "integrity": "sha512-tEFg39mw/rHO5n8GK2DR4ZMFfsPQZtnQIPbsIpjoQRomJc/2tRfsCSmCT6gNit+NZGoeJG5aH9ATDH5bf0WnoQ==", "cpu": [ "ppc64" ], @@ -4392,9 +4544,9 @@ } }, "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.142.0.tgz", - "integrity": "sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.150.0.tgz", + "integrity": "sha512-0JO7IFkoek6HqV589Menx3hJySNXi6quRhO4tq2P7kpEHKEXoDATnoPVUpn5B7gDH2KLkdo751N0uIrGJFCTCw==", "cpu": [ "riscv64" ], @@ -4412,9 +4564,9 @@ } }, "node_modules/@oxc-parser/binding-linux-riscv64-musl": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.142.0.tgz", - "integrity": "sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.150.0.tgz", + "integrity": "sha512-7XPzREnyAS5wHU9aB+49Uaqgoo1gVCklHc3DRlc3fJy2tXD/eAJFN1QFz/crj+Ulup5P1+axNREF+/RGaB/IRA==", "cpu": [ "riscv64" ], @@ -4432,9 +4584,9 @@ } }, "node_modules/@oxc-parser/binding-linux-s390x-gnu": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.142.0.tgz", - "integrity": "sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.150.0.tgz", + "integrity": "sha512-7n7ZxcbRWDFaTdyj8M8p0O9OfzoMKm8O6syBAIgcSutbOALq0Bb9G52Me+XH0anMLZV+NgXc726gqgG2q39vcQ==", "cpu": [ "s390x" ], @@ -4452,9 +4604,9 @@ } }, "node_modules/@oxc-parser/binding-linux-x64-gnu": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.142.0.tgz", - "integrity": "sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.150.0.tgz", + "integrity": "sha512-Vx0GSA9ZCRTUiczoEQnIIyXkMvtEY8uc6IiwLQtMe5ci2sXPqjrry0Ek5fsPP1k2kCzkML3ow9UOOEgnEDi7Bw==", "cpu": [ "x64" ], @@ -4472,9 +4624,9 @@ } }, "node_modules/@oxc-parser/binding-linux-x64-musl": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.142.0.tgz", - "integrity": "sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.150.0.tgz", + "integrity": "sha512-ii4/9m3viDLssMnfXU7/Pni/3nYplApuGayceX4qsVGaqqQJCx3tHIH9M/HWIeSty5i8LjS21zPYT6lVIkwLxw==", "cpu": [ "x64" ], @@ -4492,9 +4644,9 @@ } }, "node_modules/@oxc-parser/binding-openharmony-arm64": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.142.0.tgz", - "integrity": "sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.150.0.tgz", + "integrity": "sha512-ZtoxX5rez36ZWkwtiEhjkCPnlTPoQ2I7lIL0IYZ1yjxMYohbvoOjBmUIZzrf9W/HouONq0omIfTeCWEY+R380w==", "cpu": [ "arm64" ], @@ -4508,29 +4660,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@oxc-parser/binding-wasm32-wasi": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.142.0.tgz", - "integrity": "sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.2", - "@emnapi/runtime": "1.11.2", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@oxc-parser/binding-win32-arm64-msvc": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.142.0.tgz", - "integrity": "sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.150.0.tgz", + "integrity": "sha512-VqeRb5JX/bKYBrff7TUDvJyKY0914UzuCkuXIGxJS4FUmvMNfqkCbc7Sq90iMz9DlmAtlggwaBYQ9eg3h3ltiw==", "cpu": [ "arm64" ], @@ -4545,9 +4678,9 @@ } }, "node_modules/@oxc-parser/binding-win32-ia32-msvc": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.142.0.tgz", - "integrity": "sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.150.0.tgz", + "integrity": "sha512-EPqJfeZ4Pgg2BJSsCV8GozxV0FDltRzpVtGVa1r2noJu1iu+opOw3gtBWXwIo9odCT/MdFfyHxdy0/CRqs3OqA==", "cpu": [ "ia32" ], @@ -4562,9 +4695,9 @@ } }, "node_modules/@oxc-parser/binding-win32-x64-msvc": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.142.0.tgz", - "integrity": "sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.150.0.tgz", + "integrity": "sha512-n5YMzbqwPQqozbkrexi0lNZrUz5cnPHalYpFWe6Dau7AmKIWNo+y24IwzDuZEQtEdUHuKhXmMMih/MPjOI+CMw==", "cpu": [ "x64" ], @@ -4579,22 +4712,22 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz", - "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.150.0.tgz", + "integrity": "sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw==", "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@parcel/watcher": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==", + "devOptional": true, "hasInstallScript": true, "license": "MIT", - "optional": true, "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", @@ -4885,8 +5018,8 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/@polka/url": { "version": "1.0.0-next.29", @@ -4905,10 +5038,27 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.0.tgz", - "integrity": "sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", "cpu": [ "arm64" ], @@ -4923,9 +5073,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.0.tgz", - "integrity": "sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", "cpu": [ "arm64" ], @@ -4940,9 +5090,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.0.tgz", - "integrity": "sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", "cpu": [ "x64" ], @@ -4957,9 +5107,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.0.tgz", - "integrity": "sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", "cpu": [ "x64" ], @@ -4974,9 +5124,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.0.tgz", - "integrity": "sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", "cpu": [ "arm" ], @@ -4991,9 +5141,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.0.tgz", - "integrity": "sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", "cpu": [ "arm64" ], @@ -5011,9 +5161,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.0.tgz", - "integrity": "sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", "cpu": [ "arm64" ], @@ -5031,9 +5181,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.0.tgz", - "integrity": "sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", "cpu": [ "ppc64" ], @@ -5051,9 +5201,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.0.tgz", - "integrity": "sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", "cpu": [ "s390x" ], @@ -5071,9 +5221,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.0.tgz", - "integrity": "sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", "cpu": [ "x64" ], @@ -5091,9 +5241,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.0.tgz", - "integrity": "sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", "cpu": [ "x64" ], @@ -5111,9 +5261,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.0.tgz", - "integrity": "sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", "cpu": [ "arm64" ], @@ -5127,29 +5277,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.0.tgz", - "integrity": "sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.2", - "@emnapi/runtime": "1.11.2", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.0.tgz", - "integrity": "sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", "cpu": [ "arm64" ], @@ -5164,9 +5295,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.0.tgz", - "integrity": "sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", "cpu": [ "x64" ], @@ -5195,15 +5326,16 @@ "license": "MIT" }, "node_modules/@schematics/angular": { - "version": "22.1.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-22.1.6.tgz", - "integrity": "sha512-RiD4OZJ4yuaM1aXb3pt1gjDSWwkP0jrgiCuoaBls1eabcrDmlsNuQv0ekxbcGgCRPdSJvmHRZIHHmFPzei8w3Q==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-22.2.0.tgz", + "integrity": "sha512-IOD+T+S5LyVVuLAtLq/5k+WxnT9UpJecyDPvIT+AWug+mZJkd+HKVVHryenNJBaW29tIxNfoDuVFPEsZ4UKcNw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "22.1.6", - "@angular-devkit/schematics": "22.1.6", + "@angular-devkit/core": "22.2.0", + "@angular-devkit/schematics": "22.2.0", "jsonc-parser": "3.3.1", + "oxc-parser": "0.150.0", "typescript": "6.0.3" }, "engines": { @@ -6254,24 +6386,23 @@ } }, "node_modules/angular-eslint": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-22.1.0.tgz", - "integrity": "sha512-LU5a6MOSeQTETnc4xaHi10p9S1cstNczr93sChi3rx8IzgH4+risIsjjQHVLSnQDrSGH2O8jAGCaChker7f7TQ==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-22.5.0.tgz", + "integrity": "sha512-qDJVh/YLYiZ7k2qZCBGsmfO+qSiHcdyQp1UFdm3eHHc3YRNlW/Xvj1wp1oDKxuHSE//aqmbVFHlkcqdwJyymdg==", "dev": true, "license": "MIT", "dependencies": { "@angular-devkit/core": ">= 22.0.0 < 23.0.0", "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", - "@angular-eslint/builder": "22.1.0", - "@angular-eslint/eslint-plugin": "22.1.0", - "@angular-eslint/eslint-plugin-template": "22.1.0", - "@angular-eslint/schematics": "22.1.0", - "@angular-eslint/template-parser": "22.1.0", + "@angular-eslint/builder": "22.5.0", + "@angular-eslint/eslint-plugin": "22.5.0", + "@angular-eslint/eslint-plugin-template": "22.5.0", + "@angular-eslint/schematics": "22.5.0", + "@angular-eslint/template-parser": "22.5.0", "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { - "@angular/cli": ">= 22.0.0 < 23.0.0", "eslint": "^9.0.0 || ^10.0.0", "typescript": "*", "typescript-eslint": "^8.0.0" @@ -6713,24 +6844,23 @@ } }, "node_modules/beasties": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.4.3.tgz", - "integrity": "sha512-fIIeLOcbAB/K1kb1HBVJoiq1alHL4RCYBSo5e7HzrNkkgMggXR1Vqt/Z9JWnkfe/qdCo66Ux3QRwZioAIBdWRA==", - "dev": true, + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.5.4.tgz", + "integrity": "sha512-8/lOOjT+PElYCnaUbmhgd3Uad5R1VTQ4Wg0k4rK8bX04m5WEqHNmnlLy3Q/lJ7dk25XA+72gayzc/skTfKKpcA==", "license": "Apache-2.0", "dependencies": { - "css-select": "^6.0.0", - "css-what": "^7.0.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "htmlparser2": "^10.0.0", + "css-select": "^7.0.0", + "css-what": "^8.0.0", + "dom-serializer": "^3.0.0", + "domhandler": "^6.0.0", + "htmlparser2": "^12.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.49", "postcss-media-query-parser": "^0.2.3", "postcss-safe-parser": "^7.0.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.19.0" } }, "node_modules/binary-extensions": { @@ -6774,9 +6904,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", - "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "version": "1.20.8", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.8.tgz", + "integrity": "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -6787,7 +6917,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.15.1", + "qs": "~6.16.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -6824,6 +6954,22 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/body-parser/node_modules/raw-body": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", @@ -6840,11 +6986,17 @@ } }, "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-2.0.0.tgz", + "integrity": "sha512-DkVaaQHymRhpYEYo9x1oo7Q7B0Y6KJUsjm3c9eTyFDby4MHLBTwZ6ZDWBel5zrYxj1WsZgC5oLpiz+93MluXeA==", + "license": "ISC", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } }, "node_modules/bootstrap": { "version": "5.3.3", @@ -6866,9 +7018,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7183,9 +7335,9 @@ } }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", - "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7553,32 +7705,35 @@ } }, "node_modules/css-select": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz", - "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==", - "dev": true, + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-7.0.0.tgz", + "integrity": "sha512-snmjEVXy+1LnwXdxhYvTMj1d9tOh4HxkA1YmoayVBeeyR2C14Pum7fcxJIm4SswYspVy866eYNwlH6xC3/VH5g==", "license": "BSD-2-Clause", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^7.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "nth-check": "^2.1.1" + "boolbase": "^2.0.0", + "css-what": "^8.0.0", + "domhandler": "^6.0.1", + "domutils": "^4.0.2", + "nth-check": "^3.0.1" + }, + "engines": { + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/sponsors/fb55" } }, "node_modules/css-what": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", - "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==", - "dev": true, + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-8.0.0.tgz", + "integrity": "sha512-DH0Bqq3DNp5tdOReuNyAA+Ev4Y2GS5FMbZpeTLP6C4CDi0h5nL0BmUPChXw3o/qbHLDWHl49sbNqQVY7bMSDdw==", "license": "BSD-2-Clause", "engines": { - "node": ">= 6" + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/sponsors/fb55" } }, @@ -7830,46 +7985,51 @@ } }, "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz", + "integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==", "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "entities": "^8.0.0" + }, + "engines": { + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz", + "integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } ], - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + } }, "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz", + "integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==", "license": "BSD-2-Clause", "dependencies": { - "domelementtype": "^2.3.0" + "domelementtype": "^3.0.0" }, "engines": { - "node": ">= 4" + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/fb55/domhandler?sponsor=1" } }, @@ -7883,17 +8043,20 @@ } }, "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz", + "integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==", "license": "BSD-2-Clause", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "dom-serializer": "^3.0.0", + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0" + }, + "engines": { + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/fb55/domutils?sponsor=1" } }, @@ -7980,9 +8143,9 @@ } }, "node_modules/engine.io": { - "version": "6.6.9", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.9.tgz", - "integrity": "sha512-clKkw4C7nJ22mGgoVcCg6V/W/TxdNyIOTr89k2ONZu81qqkddPFDF0LXcbAwhzPD8DjkiRCjzuiO6Y+fkpD4vg==", + "version": "6.6.11", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.11.tgz", + "integrity": "sha512-z34mGpLoY/82ZbkX1LqGMIaf3wjVMPL6gVC681QDqnmzJ26synI8qAE32P+a7UazmpJZ8UGrFIeAavgRfXzYrg==", "dev": true, "license": "MIT", "dependencies": { @@ -7990,7 +8153,6 @@ "@types/node": ">=10.0.0", "@types/ws": "^8.5.12", "accepts": "~1.3.4", - "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.4.1", @@ -8063,13 +8225,12 @@ } }, "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -8476,9 +8637,9 @@ "license": "MIT" }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -8675,9 +8836,9 @@ "license": "MIT" }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -9120,9 +9281,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.6.tgz", - "integrity": "sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", "funding": [ { "type": "github", @@ -9344,6 +9505,15 @@ "dev": true, "license": "ISC" }, + "node_modules/flru": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flru/-/flru-1.0.2.tgz", + "integrity": "sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -10335,10 +10505,9 @@ } }, "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", - "dev": true, + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-12.0.0.tgz", + "integrity": "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -10348,23 +10517,13 @@ ], "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "domutils": "^4.0.2", + "entities": "^8.0.0" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": ">=20.19.0" } }, "node_modules/http-errors": { @@ -10455,15 +10614,15 @@ "license": "BSD-3-Clause" }, "node_modules/igniteui-angular": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/igniteui-angular/-/igniteui-angular-22.1.0.tgz", - "integrity": "sha512-05Wdj9RvkIVm6wYyZFNdqi0oS/P9IKhrUAnwVzQ8nW8i5NHA13Fn+a6ZY3q/SKXyBc5C2Sb5ZyBL2DwK1Bbxrg==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/igniteui-angular/-/igniteui-angular-22.2.0.tgz", + "integrity": "sha512-512fLFm2dPW6LwZyIZMUG2Hf9Bq4Ld/m9qBXgqAXnxrAXNLQd/TJpnW1trAfOVjQZtCxGxDVGPiLY/GgyRTw3w==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@igniteui/material-icons-extended": "^3.1.0", "fflate": "^0.8.2", "igniteui-i18n-core": "^1.0.5", - "igniteui-theming": "^28.1.1", + "igniteui-theming": "^29.0.0", "igniteui-trial-watermark": "^3.1.0", "jspdf": "^4.2.1", "lodash-es": "^4.17.21", @@ -10474,8 +10633,8 @@ "@angular/common": "22", "@angular/core": "22", "@angular/forms": "22", - "igniteui-grid-lite": "~0.10.0", - "igniteui-webcomponents": "~7.3.0" + "igniteui-grid-lite": "~0.11.0", + "igniteui-webcomponents": "~7.4.0" }, "peerDependenciesMeta": { "igniteui-grid-lite": { @@ -10516,9 +10675,9 @@ } }, "node_modules/igniteui-angular-extras": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/igniteui-angular-extras/-/igniteui-angular-extras-22.1.0.tgz", - "integrity": "sha512-6uGpfV6hbH/FPegXBAdiCtiwp8Qq0/mqcBUw5S2kFkUyQoaIaESvgtzCE0swi153NpHPA36OhWGKq5jbw0vsqQ==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/igniteui-angular-extras/-/igniteui-angular-extras-22.2.0.tgz", + "integrity": "sha512-NvH4aLsMLxjkfMPs1jvKx7n9e0rehDVVTWAWiioaEZUpea3GzRbwDLTN44ntpEWtbdVykvumHlpUAQvturJy6A==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "igniteui-trial-watermark": "^3.1.0", @@ -10533,9 +10692,9 @@ } }, "node_modules/igniteui-angular-i18n": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/igniteui-angular-i18n/-/igniteui-angular-i18n-22.1.0.tgz", - "integrity": "sha512-rwGcf7ZUNp7mLU2K5FhsGEWX/8v6EZYitlDLlbLYZL/O2oFZISBfJRvzqi3GLJhEINJTE4Q8h8FNrjhz0tj8RQ==", + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/igniteui-angular-i18n/-/igniteui-angular-i18n-22.2.0.tgz", + "integrity": "sha512-iEg/PxMpPM6UoC86oWx9J/9cWg3j4UbD+jgjYtN+zrGaRkP0RnW7E5E6pipfefkNdwbRuSUzdeDP7m93Xcjr2w==", "license": "MIT", "dependencies": { "igniteui-i18n-core": "^1.0.2", @@ -10558,14 +10717,13 @@ "license": "Apache-2.0" }, "node_modules/igniteui-grid-lite": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.10.0.tgz", - "integrity": "sha512-frMjK3jIdsu76SoKjxKw7U9aFbFAoqWapCelL4CXf75MF80UyQR+g22iMkUR1Nu2/PsQkmJP1hmC4R/4+PmtDA==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.11.0.tgz", + "integrity": "sha512-vFPWIMihTZ+qbSKRjTMeGRgmnnziNhY5zjs8VdyipojmdkuoHrYW2VFBFHCg0Ci1bWfeBQpLrGOF0mmn57CVHA==", "license": "MIT", "dependencies": { - "@lit-labs/virtualizer": "~2.1.0", "@lit/context": "~1.1.5", - "igniteui-webcomponents": "~7.3.0", + "igniteui-webcomponents": "~7.4.1", "lit": "^3.3.0" }, "engines": { @@ -10602,9 +10760,9 @@ "license": "MIT" }, "node_modules/igniteui-theming": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-28.1.1.tgz", - "integrity": "sha512-ioNSE9t36nqNfItashgM6oZxfgiLPjzeJ4X2g++3kU9oU0kklkz1Ax9F0FmGiwyIC2atWELkb76LsyT+0ZSTSQ==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-29.0.0.tgz", + "integrity": "sha512-WpOJs6xX+VKG7uO2Dvkb1EmmXVDj+vnUCnlwmr6XCflgKv3baJLDDb3b/APWMLjPggDFxysrpgqAr6QHuI55Bw==", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.28.0", @@ -10635,9 +10793,9 @@ } }, "node_modules/igniteui-webcomponents": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.3.0.tgz", - "integrity": "sha512-/99QNPMnupVDGeuuDVa2XGewusFTvvXvu8+vFOVuXBGMtxZluMzAuC7U6BLDcArcxpkEqEL4LEPpob5ULur0Dw==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.4.1.tgz", + "integrity": "sha512-4VxbkDO4QpEmhy7ga609RRDpnuX1N4SU7CveavzXQ/xVYdxZb7olcPcqRlcKvKn9abAYR9wsDIhB0MUT7AwUow==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.8.0", @@ -10674,9 +10832,9 @@ } }, "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz", + "integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==", "dev": true, "license": "MIT", "engines": { @@ -10783,9 +10941,9 @@ "license": "MIT" }, "node_modules/ip-address": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", - "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz", + "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==", "license": "MIT", "engines": { "node": ">= 12" @@ -11730,9 +11888,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", - "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, "funding": [ { @@ -11977,9 +12135,9 @@ "license": "MIT" }, "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -12535,15 +12693,15 @@ } }, "node_modules/listr2": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-11.0.0.tgz", - "integrity": "sha512-8K88S0aSrcSXdJfiZtEy5BQMnR+TyjrCGLcgAvQs6ta0NEnIm0RJ72/Pv67Jvg07cfBhDbuN74V81lSSVYEFEw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-11.1.0.tgz", + "integrity": "sha512-xsuczF6mWkEo/E80QHaEokQzKmTy7m80KcLRnkUt9wrcePres2w7dbQi5zOsWtDUg8Dac4gPFyu4EJ/IvKwTOg==", "dev": true, "license": "MIT", "dependencies": { "cli-truncate": "^6.1.1", "log-update": "^8.0.0", - "wrap-ansi": "^10.0.0" + "wrap-ansi": "^10.0.1" }, "engines": { "node": ">=22.13.0" @@ -12684,9 +12842,9 @@ } }, "node_modules/log-update/node_modules/string-width": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", - "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12721,19 +12879,20 @@ "version": "11.5.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } }, "node_modules/magic-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.0.0.tgz", - "integrity": "sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.1.tgz", + "integrity": "sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.6.0" } }, "node_modules/make-error": { @@ -13311,15 +13470,18 @@ } }, "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-3.0.1.tgz", + "integrity": "sha512-GX0gsdbGVCgnRgbeGaubfjpBXyYRWOOCVeYh08bSQvDZqxz5ndXs1OTfAt/h36G1xvI94YIspsI0sVFqAV9+RQ==", "license": "BSD-2-Clause", "dependencies": { - "boolbase": "^1.0.0" + "boolbase": "^2.0.0" + }, + "engines": { + "node": ">=20.19.0" }, "funding": { + "type": "github", "url": "https://github.com/fb55/nth-check?sponsor=1" } }, @@ -13656,41 +13818,40 @@ } }, "node_modules/oxc-parser": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.142.0.tgz", - "integrity": "sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw==", + "version": "0.150.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.150.0.tgz", + "integrity": "sha512-zwajKw1GUa57IOdafIS7/yOObGF2NihwIfZfs5yJTRprMSkiwhWOc/k+n8bwnUPbHr2/XsjfBO8KyTPaW3VpWg==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "^0.142.0" + "@oxc-project/types": "^0.150.0" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" }, "optionalDependencies": { - "@oxc-parser/binding-android-arm-eabi": "0.142.0", - "@oxc-parser/binding-android-arm64": "0.142.0", - "@oxc-parser/binding-darwin-arm64": "0.142.0", - "@oxc-parser/binding-darwin-x64": "0.142.0", - "@oxc-parser/binding-freebsd-x64": "0.142.0", - "@oxc-parser/binding-linux-arm-gnueabihf": "0.142.0", - "@oxc-parser/binding-linux-arm-musleabihf": "0.142.0", - "@oxc-parser/binding-linux-arm64-gnu": "0.142.0", - "@oxc-parser/binding-linux-arm64-musl": "0.142.0", - "@oxc-parser/binding-linux-ppc64-gnu": "0.142.0", - "@oxc-parser/binding-linux-riscv64-gnu": "0.142.0", - "@oxc-parser/binding-linux-riscv64-musl": "0.142.0", - "@oxc-parser/binding-linux-s390x-gnu": "0.142.0", - "@oxc-parser/binding-linux-x64-gnu": "0.142.0", - "@oxc-parser/binding-linux-x64-musl": "0.142.0", - "@oxc-parser/binding-openharmony-arm64": "0.142.0", - "@oxc-parser/binding-wasm32-wasi": "0.142.0", - "@oxc-parser/binding-win32-arm64-msvc": "0.142.0", - "@oxc-parser/binding-win32-ia32-msvc": "0.142.0", - "@oxc-parser/binding-win32-x64-msvc": "0.142.0" + "@oxc-parser/binding-android-arm-eabi": "0.150.0", + "@oxc-parser/binding-android-arm64": "0.150.0", + "@oxc-parser/binding-darwin-arm64": "0.150.0", + "@oxc-parser/binding-darwin-x64": "0.150.0", + "@oxc-parser/binding-freebsd-x64": "0.150.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.150.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.150.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.150.0", + "@oxc-parser/binding-linux-arm64-musl": "0.150.0", + "@oxc-parser/binding-linux-ppc64-gnu": "0.150.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.150.0", + "@oxc-parser/binding-linux-riscv64-musl": "0.150.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.150.0", + "@oxc-parser/binding-linux-x64-gnu": "0.150.0", + "@oxc-parser/binding-linux-x64-musl": "0.150.0", + "@oxc-parser/binding-openharmony-arm64": "0.150.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.150.0", + "@oxc-parser/binding-win32-ia32-msvc": "0.150.0", + "@oxc-parser/binding-win32-x64-msvc": "0.150.0" } }, "node_modules/p-limit": { @@ -13830,19 +13991,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", - "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parse5-sax-parser": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", @@ -13856,18 +14004,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5/node_modules/entities": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", - "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -13986,9 +14122,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -13998,9 +14134,9 @@ } }, "node_modules/piscina": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.2.0.tgz", - "integrity": "sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.3.2.tgz", + "integrity": "sha512-vv7l/mM7B9WgrhDaudIqv1x6v4LOBRYYmpWGdWushhpbCmVHp11sUB2v4hj1CAeTGXVxuZFz6xOU1RalAiPKfQ==", "dev": true, "license": "MIT", "engines": { @@ -14030,9 +14166,9 @@ } }, "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -14049,7 +14185,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.17", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -14061,14 +14197,12 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true, "license": "MIT" }, "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", - "dev": true, + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.1.0.tgz", + "integrity": "sha512-1WzZxRLaAFwEh6Do+zyGpjWV3nGJNxxhuh7Ubu/q1ICImMgZJnLwhoaEpRbG4pJppp2Y1ncL9ffA2f+LhrefQg==", "funding": [ { "type": "opencollective", @@ -14636,9 +14770,9 @@ "license": "MIT" }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -14682,13 +14816,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.0.tgz", - "integrity": "sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.140.0", + "@oxc-project/types": "=0.149.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -14698,31 +14832,31 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.2.0", - "@rolldown/binding-darwin-arm64": "1.2.0", - "@rolldown/binding-darwin-x64": "1.2.0", - "@rolldown/binding-freebsd-x64": "1.2.0", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.0", - "@rolldown/binding-linux-arm64-gnu": "1.2.0", - "@rolldown/binding-linux-arm64-musl": "1.2.0", - "@rolldown/binding-linux-ppc64-gnu": "1.2.0", - "@rolldown/binding-linux-s390x-gnu": "1.2.0", - "@rolldown/binding-linux-x64-gnu": "1.2.0", - "@rolldown/binding-linux-x64-musl": "1.2.0", - "@rolldown/binding-openharmony-arm64": "1.2.0", - "@rolldown/binding-wasm32-wasi": "1.2.0", - "@rolldown/binding-win32-arm64-msvc": "1.2.0", - "@rolldown/binding-win32-x64-msvc": "1.2.0" + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" } }, "node_modules/rolldown/node_modules/@oxc-project/types": { - "version": "0.140.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.140.0.tgz", - "integrity": "sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==", + "version": "0.149.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/router": { @@ -14842,9 +14976,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.101.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz", - "integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==", + "version": "1.104.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.104.1.tgz", + "integrity": "sha512-yDA+1aIG3EHgN4V/BvuhCvu61FF6hEd4e+9DxikUm9U0CAGuvdIZ/UYy7qbOxjhbbWQraoyLlMuzdRGOSV5Bmw==", "dev": true, "license": "MIT", "dependencies": { @@ -15629,9 +15763,9 @@ } }, "node_modules/slice-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-9.0.0.tgz", - "integrity": "sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-9.0.1.tgz", + "integrity": "sha512-aBY19bn/XA+hKOKX0qL7Z0UfdBsbQvc9hn993U8ALUjzxCvDcuZqLoRXjGJrUARWAlwMnsRVD9sw2AFNOYvalA==", "dev": true, "license": "MIT", "dependencies": { @@ -15725,9 +15859,9 @@ } }, "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0.tgz", + "integrity": "sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -16950,6 +17084,18 @@ "node": ">= 0.8" } }, + "node_modules/verkit": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.3.2.tgz", + "integrity": "sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==", + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -17073,16 +17219,16 @@ "license": "MIT" }, "node_modules/vite": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", - "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz", + "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.17", - "rolldown": "~1.1.5", + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.6", "tinyglobby": "^0.2.17" }, "bin": { @@ -17099,7 +17245,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", + "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -17150,128 +17296,145 @@ } } }, - "node_modules/vite/node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/vite/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "node_modules/vite/node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, - "license": "MIT", - "optional": true, + "license": "MPL-2.0", "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/vite/node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", - "dev": true, - "license": "MIT", + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/vite/node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/vite/node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "android" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "node_modules/vite/node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "node_modules/vite/node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "node_modules/vite/node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "freebsd" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], @@ -17279,19 +17442,23 @@ "libc": [ "glibc" ], - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], @@ -17299,59 +17466,23 @@ "libc": [ "musl" ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/vite/node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/vite/node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], @@ -17359,19 +17490,23 @@ "libc": [ "glibc" ], - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], @@ -17379,117 +17514,59 @@ "libc": [ "musl" ], - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/vite/node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/vite/node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" + "node": ">= 12.0.0" }, - "engines": { - "node": "^20.19.0 || >=22.12.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/vite/node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/vite/node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.139.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">= 12.0.0" }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/void-elements": { @@ -17502,19 +17579,6 @@ "node": ">=0.10.0" } }, - "node_modules/watchpack": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", - "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/weak-lru-cache": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", @@ -17704,9 +17768,9 @@ } }, "node_modules/wrap-ansi": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.1.tgz", - "integrity": "sha512-M0N4xzyzosiIok3svYlEo1sdLZts/8FPgYH/GPC3wvlmPoRvnoManGMrE54waYj3tISA8w6lsdesfVv67qSr8Q==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.2.tgz", + "integrity": "sha512-6OLRNZqRntVGBm26ghZ5eZhCuWWyOkRCSn8XsOIuq5stpCE/tjLbdozd93naILZig0lmD8ANfRwnhn0DLeXGlg==", "dev": true, "license": "MIT", "dependencies": { @@ -17734,9 +17798,9 @@ } }, "node_modules/wrap-ansi/node_modules/string-width": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", - "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.3.0.tgz", + "integrity": "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17796,6 +17860,13 @@ "node": ">=0.4" } }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "dev": true, + "license": "MIT" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -17904,9 +17975,9 @@ } }, "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", + "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 2ca6bbe650..85f4481294 100644 --- a/package.json +++ b/package.json @@ -46,22 +46,22 @@ "url": "git://github.com/IgniteUI/igniteui-angular-samples/repository.git" }, "dependencies": { - "@angular/animations": "^22.0.1", + "@angular/animations": "^22.2.0", "@angular/cdk": "^22.0.1", - "@angular/common": "^22.0.1", - "@angular/compiler": "^22.0.1", - "@angular/core": "^22.0.1", - "@angular/forms": "^22.0.1", - "@angular/localize": "^22.0.1", + "@angular/common": "^22.2.0", + "@angular/compiler": "^22.2.0", + "@angular/core": "^22.2.0", + "@angular/forms": "^22.2.0", + "@angular/localize": "^22.2.0", "@angular/material": "^22.0.1", - "@angular/platform-browser": "^22.0.1", - "@angular/platform-browser-dynamic": "^22.0.1", - "@angular/platform-server": "^22.0.1", - "@angular/router": "^22.0.1", - "@angular/ssr": "^22.0.1", + "@angular/platform-browser": "^22.2.0", + "@angular/platform-browser-dynamic": "^22.2.0", + "@angular/platform-server": "^22.2.0", + "@angular/router": "^22.2.0", + "@angular/ssr": "^22.2.0", "@igniteui/material-icons-extended": "^3.1.0", "@microsoft/signalr": "^8.0.7", - "@ng-bootstrap/ng-bootstrap": "^20.0.0", + "@ng-bootstrap/ng-bootstrap": "^21.0.0", "@popperjs/core": "2.11.8", "@tailwindcss/postcss": "^4.1.10", "@types/file-saver": "^2.0.2", @@ -71,16 +71,16 @@ "express": "^4.18.2", "file-saver": "^2.0.2", "fuse.js": "^7.1.0", - "igniteui-angular": "22.1.0", + "igniteui-angular": "22.2.0", "igniteui-angular-charts": "^22.0.0", "igniteui-angular-core": "^22.0.0", - "igniteui-angular-extras": "22.1.0", - "igniteui-angular-i18n": "22.1.0", + "igniteui-angular-extras": "22.2.0", + "igniteui-angular-i18n": "22.2.0", "igniteui-dockmanager": "^1.17.0", - "igniteui-grid-lite": "0.10.0", + "igniteui-grid-lite": "0.11.0", "igniteui-i18n-resources": "^1.0.4", "igniteui-live-editing": "^3.5.2", - "igniteui-webcomponents": "^7.3.0", + "igniteui-webcomponents": "^7.4.1", "marked": "^18.0.11", "marked-shiki": "^1.2.1", "minireset.css": "0.0.6", @@ -92,13 +92,6 @@ "tslib": "^2.6.1" }, "overrides": { - "@ng-bootstrap/ng-bootstrap": { - "@angular/common": "^22.0.0", - "@angular/core": "^22.0.0", - "@angular/forms": "^22.0.0", - "@angular/localize": "^22.0.0", - "@angular/compiler": "^22.0.0" - }, "igniteui-angular-core": { "@angular/core": "^22.0.0", "@angular/common": "^22.0.0", @@ -110,8 +103,8 @@ "@angular/compiler": "^22.0.0" }, "igniteui-angular-extras": { - "igniteui-angular": "22.1.0", - "@infragistics/igniteui-angular": "^22.0.0", + "igniteui-angular": "22.2.0", + "@infragistics/igniteui-angular": "22.2.0", "igniteui-angular-core": "^22.0.0", "igniteui-angular-charts": "^22.0.0", "@angular/core": "^22.0.0", @@ -120,15 +113,15 @@ } }, "devDependencies": { - "@angular-eslint/builder": "^22.0.0", - "@angular-eslint/eslint-plugin": "^22.0.0", - "@angular-eslint/eslint-plugin-template": "^22.0.0", - "@angular-eslint/schematics": "^22.0.0", - "@angular-eslint/template-parser": "^22.0.0", - "@angular/build": "^22.0.0", - "@angular/cli": "^22.0.1", - "@angular/compiler-cli": "^22.0.1", - "@angular/language-service": "^22.0.1", + "@angular-eslint/builder": "^22.5.0", + "@angular-eslint/eslint-plugin": "^22.5.0", + "@angular-eslint/eslint-plugin-template": "^22.5.0", + "@angular-eslint/schematics": "^22.5.0", + "@angular-eslint/template-parser": "^22.5.0", + "@angular/build": "^22.2.0", + "@angular/cli": "^22.2.0", + "@angular/compiler-cli": "^22.2.0", + "@angular/language-service": "^22.2.0", "@igniteui/angular-schematics": "^22.0.0", "@juggle/resize-observer": "^3.3.1", "@types/express": "^4.17.17", @@ -137,7 +130,7 @@ "@types/node": "^25.9.3", "@typescript-eslint/eslint-plugin": "^8.61.0", "@typescript-eslint/parser": "^8.61.0", - "angular-eslint": "^22.0.0", + "angular-eslint": "^22.5.0", "eslint": "^9.8.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^63.0.2", diff --git a/projects/app-lob/src/app/grid-dynamic-chart-data/data-analysis-dock-manager/data-analysis-dock-manager.component.scss b/projects/app-lob/src/app/grid-dynamic-chart-data/data-analysis-dock-manager/data-analysis-dock-manager.component.scss index 8e1de676e3..6c7b3ef9a2 100644 --- a/projects/app-lob/src/app/grid-dynamic-chart-data/data-analysis-dock-manager/data-analysis-dock-manager.component.scss +++ b/projects/app-lob/src/app/grid-dynamic-chart-data/data-analysis-dock-manager/data-analysis-dock-manager.component.scss @@ -19,6 +19,15 @@ --igc-pane-content-background: #{contrast-color($color: 'gray', $variant: 900)}; igx-grid { + // The host carries `light-theme` for the dock manager's own theme (igc.themes.css), + // but styles.scss also emits every Ignite UI component theme under that same class, + // so the host keeps the last one's short aliases - the tooltip's dark, translucent + // background and foreground. The grid's derived-themes layer reads those aliases + // before its own tokens, which tints its scrollbars. Drop them so the grid falls + // back to --ig-grid-background / --ig-grid-foreground. + --background: initial; + --foreground: initial; + --ig-size: var(--ig-size-small); } } @@ -31,8 +40,6 @@ } .selection-area { - - @include scrollbar(scrollbar-theme($sb-size: 6px)); width: 100%; height: 90%; display: inline-flex; @@ -89,12 +96,6 @@ $custom-badge-theme: badge-theme( } } - .grid-chart-contextmenu-wrapper { - igx-grid { - @include scrollbar(scrollbar-theme($sb-size: 16px)); - } - } - .analytics-btn { @include tokens( contained-button-theme( @@ -123,10 +124,6 @@ $custom-badge-theme: badge-theme( height: auto; } - igx-tab-content { - @include scrollbar(scrollbar-theme($sb-size: 10px)); - } - } .selected, .disabled { @@ -146,8 +143,6 @@ $custom-badge-theme: badge-theme( $font-family: 'Titillium Web', 'Roboto', 'Helvetica Neue', sans-serif; .tab-options-wrapper { - @include scrollbar(scrollbar-theme($sb-size: 6px)); - display: flex; flex-flow: column; max-height: rem(110px); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1046547447..10970e42e6 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,7 @@ import { Component, HostListener, OnInit, DOCUMENT, inject } from '@angular/core'; import { RouterOutlet } from '@angular/router'; +import { ThemeService } from './services/theme.service'; @Component({ selector: 'app-root', @@ -10,50 +11,22 @@ import { RouterOutlet } from '@angular/router'; }) export class AppComponent implements OnInit { private document = inject(DOCUMENT); + private themeService = inject(ThemeService); public title = 'Samples'; - private theme = 'default-theme'; - private styleElem: HTMLStyleElement; - private typefacesLoaded = ['Titillium Web', 'Roboto']; - private typefaceUrl = 'https://fonts.googleapis.com/css?family='; public ngOnInit() { - this.createThemeStyle(); + this.document.body.classList.add('custom-body'); + this.themeService.init(); } - // eslint-disable-next-line @typescript-eslint/member-ordering + /** + * Samples are embedded in the documentation as iframes and the theming + * widget shown next to each of them posts the visitor's theme selection + * down into the sample. Anything that is not such a message is left alone. + */ @HostListener('window:message', ['$event']) protected onMessage(e: MessageEvent) { - if (e.origin === e.data.origin && typeof e.data.themeStyle === 'string') { - this.styleElem.textContent = e.data.themeStyle; - const typeface = window.getComputedStyle(this.document.body).fontFamily.replace(/[\'\"]/g, ''); - if (!(typeface.match(/,/g) || []).length && - !this.typefacesLoaded.includes(typeface)) { - this.typefacesLoaded.push(typeface); - this.createTypefaceLink(typeface); - } - } else if (e.origin === e.data.origin && typeof e.data.theme === 'string') { - this.document.body.classList.remove(this.theme); - this.document.body.classList.add(e.data.theme); - this.theme = e.data.theme; - } - } - - private createTypefaceLink(typeface: string) { - let typefaceElem = this.document.getElementById('igniteui-theme-typeface') as HTMLLinkElement; - if (!typefaceElem) { - typefaceElem = this.document.createElement('link'); - typefaceElem.rel = 'stylesheet'; - typefaceElem.id = 'igniteui-theme-typeface'; - this.document.head.appendChild(typefaceElem); - } - typefaceElem.href = this.typefaceUrl + typeface.split(' ').join('+'); - } - - private createThemeStyle() { - this.styleElem = this.document.createElement('style'); - this.styleElem.id = 'igniteui-theme'; - this.document.head.appendChild(this.styleElem); - this.document.body.classList.add('custom-body'); + this.themeService.handleMessage(e); } } diff --git a/src/app/app.routes.server.ts b/src/app/app.routes.server.ts index 85274dd7e2..2960e62832 100644 --- a/src/app/app.routes.server.ts +++ b/src/app/app.routes.server.ts @@ -49,6 +49,16 @@ export const serverRoutes: ServerRoute[] = [ path: 'samples/lists/**', renderMode: RenderMode.Client // TODO: Fails with Prerender }, + { + // Hosts grid previews, and grids fail under Prerender like every other + // grid route below. Must precede the theming/** globs. + path: 'theming/grid-theme-playground', + renderMode: RenderMode.Client + }, + { + path: 'samples/theming/grid-theme-playground', + renderMode: RenderMode.Client + }, { path: 'theming/**', renderMode: RenderMode.Prerender diff --git a/src/app/data-display/badge/badge-dot/badge-dot.component.scss b/src/app/data-display/badge/badge-dot/badge-dot.component.scss index db1defa585..ffb0282478 100644 --- a/src/app/data-display/badge/badge-dot/badge-dot.component.scss +++ b/src/app/data-display/badge/badge-dot/badge-dot.component.scss @@ -2,7 +2,7 @@ @use "igniteui-theming/sass/typography" as *; :host { - --sample-accent: #0057a9; + --sample-accent: var(--ig-primary-800); display: grid; grid-auto-flow: column; @@ -21,6 +21,10 @@ igx-badge { translate: -50% -50%; } +igx-avatar.icon-anchor { + --ig-avatar-background: var(--ig-gray-300); +} + $anchors: icon, avatar; @each $anchor in $anchors { @@ -70,7 +74,7 @@ $anchors: icon, avatar; } .unread { - color: var(--sample-accent); + color: var(--ig-gray-900); font-weight: 600; } diff --git a/src/app/data-display/badge/badge-icon/badge-icon.component.scss b/src/app/data-display/badge/badge-icon/badge-icon.component.scss index 5dccea83e4..5f295bcc03 100644 --- a/src/app/data-display/badge/badge-icon/badge-icon.component.scss +++ b/src/app/data-display/badge/badge-icon/badge-icon.component.scss @@ -30,7 +30,12 @@ span { grid-row: 2; text-align: center; - color: var(--ig-gray-700); + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); } igx-badge:last-of-type { diff --git a/src/app/data-display/badge/badge-outlined/badge-outlined.component.scss b/src/app/data-display/badge/badge-outlined/badge-outlined.component.scss index 7f7ef73214..4dd987fdd4 100644 --- a/src/app/data-display/badge/badge-outlined/badge-outlined.component.scss +++ b/src/app/data-display/badge/badge-outlined/badge-outlined.component.scss @@ -7,7 +7,7 @@ place-content: center; place-items: center; column-gap: rem(60px); - min-height: 7rem; + min-height: 100vh; padding-inline: rem(16px); ::ng-deep { @@ -55,7 +55,7 @@ igx-stepper { --ig-stepper-step-separator-style: dashed; --ig-stepper-step-separator-color: var(--ig-gray-400); - max-width: rem(316px); + inline-size: rem(320px); } span[igxStepIndicator] { diff --git a/src/app/data-display/badge/badge-shape/badge-shape.component.scss b/src/app/data-display/badge/badge-shape/badge-shape.component.scss index 8e7dfd50b4..5d38bab74a 100644 --- a/src/app/data-display/badge/badge-shape/badge-shape.component.scss +++ b/src/app/data-display/badge/badge-shape/badge-shape.component.scss @@ -13,7 +13,12 @@ span { justify-self: end; - color: var(--ig-gray-700); + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-2") { margin: 0; diff --git a/src/app/data-display/badge/badge-size/badge-size.component.scss b/src/app/data-display/badge/badge-size/badge-size.component.scss index bdedf7a51b..7f2108c1b2 100644 --- a/src/app/data-display/badge/badge-size/badge-size.component.scss +++ b/src/app/data-display/badge/badge-size/badge-size.component.scss @@ -13,7 +13,12 @@ span { justify-self: end; - color: var(--ig-gray-700); + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-2") { margin: 0; diff --git a/src/app/data-display/badge/badge-type/badge-type.component.scss b/src/app/data-display/badge/badge-type/badge-type.component.scss index 9b22c01142..ae272a6dc2 100644 --- a/src/app/data-display/badge/badge-type/badge-type.component.scss +++ b/src/app/data-display/badge/badge-type/badge-type.component.scss @@ -24,7 +24,12 @@ igx-avatar { span { grid-row: 2; text-align: center; - color: var(--ig-gray-700); + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("caption") { margin: 0; diff --git a/src/app/data-display/badge/badge-variants/badge-variants.component.scss b/src/app/data-display/badge/badge-variants/badge-variants.component.scss index 7cbd9ac603..8f88e19dac 100644 --- a/src/app/data-display/badge/badge-variants/badge-variants.component.scss +++ b/src/app/data-display/badge/badge-variants/badge-variants.component.scss @@ -22,7 +22,12 @@ igx-avatar { span { grid-row: 2; text-align: center; - color: var(--ig-gray-700); + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-2") { margin: 0; diff --git a/src/app/data-display/data-display-routes-data.ts b/src/app/data-display/data-display-routes-data.ts index 39ceef1ea1..9d197973fd 100644 --- a/src/app/data-display/data-display-routes-data.ts +++ b/src/app/data-display/data-display-routes-data.ts @@ -31,6 +31,12 @@ export const dataDisplayRoutesData = { "material-icons-extended": { displayName: "Material Icons Extended", parentName: "Icon" }, "igx-for-sample-1": { displayName: "List with igxFor directive", parentName: "For" }, "igx-for-sample-2": { displayName: "IgxFor Horizontal virtualization", parentName: "For" }, + "virtual-scroll-overview": { displayName: "Virtual Scroll Overview", parentName: "Virtual Scroll" }, + "virtual-scroll-variable-size": { displayName: "Virtual Scroll Variable Item Size", parentName: "Virtual Scroll" }, + "virtual-scroll-horizontal": { displayName: "Virtual Scroll Horizontal", parentName: "Virtual Scroll" }, + "virtual-scroll-scroll-to-index": { displayName: "Virtual Scroll Scroll to Index", parentName: "Virtual Scroll" }, + "virtual-scroll-infinite-scroll": { displayName: "Virtual Scroll Infinite Scroll", parentName: "Virtual Scroll" }, + "virtual-scroll-paged-data": { displayName: "Virtual Scroll Paged Data", parentName: "Virtual Scroll" }, "linear-dynamic-sample": { displayName: "Dynamic Linear Progressbar", parentName: "Linear Progressbar" }, "linear-progressbar": { displayName: "Simple Linear Progressbar", parentName: "Linear Progressbar" }, "linear-progressbar-sample-1": { displayName: "Linear Progressbar Types", parentName: "Linear Progressbar" }, @@ -43,5 +49,13 @@ export const dataDisplayRoutesData = { "mask-sample-5": { displayName: "Placeholder", parentName: "Mask" }, "text-highlight-1": { displayName: "Search within a single container", parentName: "Text Highlight" }, "text-highlight-2": { displayName: "Search within multiple containers", parentName: "Text Highlight" }, - "text-highlight-style": { displayName: "Text Highlight Style", parentName: "Text Highlight" } + "text-highlight-style": { displayName: "Text Highlight Style", parentName: "Text Highlight" }, + "qr-code-overview": { displayName: "Overview", parentName: "QR Code" }, + "qr-code-error-correction": { displayName: "QR Code Error Correction", parentName: "QR Code" }, + "qr-code-size": { displayName: "QR Code Size", parentName: "QR Code" }, + "qr-code-dot-shapes": { displayName: "QR Code Dot Shapes", parentName: "QR Code" }, + "qr-code-corner-shapes": { displayName: "QR Code Corner Shapes", parentName: "QR Code" }, + "qr-code-logo": { displayName: "QR Code Logo", parentName: "QR Code" }, + "qr-code-styling": { displayName: "QR Code Styling", parentName: "QR Code" }, + "qr-code-tailwind-styling": { displayName: "QR Code Tailwind Styling", parentName: "QR Code" } }; diff --git a/src/app/data-display/data-display.routes.ts b/src/app/data-display/data-display.routes.ts index de1538d481..0c0584b651 100644 --- a/src/app/data-display/data-display.routes.ts +++ b/src/app/data-display/data-display.routes.ts @@ -30,6 +30,12 @@ import { IconServiceSampleComponent } from './icon/icon-service-sample/icon-serv import { SvgIconSampleComponent } from './icon/svg-icon-sample/svg-icon-sample.component'; import { IgxForComponent } from './igxFor/igxFor.component'; import { IgxForHorizontalComponent } from './igxFor/igxFor-horizontal-sample/igxFor-horizontal.component'; +import { VirtualScrollOverviewComponent } from './virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component'; +import { VirtualScrollVariableSizeComponent } from './virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component'; +import { VirtualScrollHorizontalComponent } from './virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component'; +import { VirtualScrollScrollToIndexComponent } from './virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component'; +import { VirtualScrollInfiniteScrollComponent } from './virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component'; +import { VirtualScrollPagedDataComponent } from './virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component'; import { LinearDynamicSampleComponent } from './linear-progressbar/linear-dynamic-sample/linear-dynamic-sample.component'; import { LinearProgressbarSample1Component } from './linear-progressbar/linear-progressbar-sample-1/linear-progressbar-sample-1.component'; import { LinearProgressbarSample2Component } from './linear-progressbar/linear-progressbar-sample-2/linear-progressbar-sample-2.component'; @@ -49,8 +55,16 @@ import { TextHighlightStyleComponent } from './text-highlight/text-highlight-sty import { MaterialIconsExtendedComponent} from './icon/material-icons-extended/material-icons-extended.component'; import { MaterialSymbolsComponent } from './icon/material-symbols/material-symbols.component'; +import { QrCodeOverviewComponent } from './qr-code/qr-code-overview/qr-code-overview.component'; +import { QrCodeStylingComponent } from './qr-code/qr-code-styling/qr-code-styling.component'; +import { QrCodeTailwindStylingComponent } from './qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component'; import { dataDisplayRoutesData } from './data-display-routes-data'; import { Routes } from '@angular/router'; +import { QrCodeErrorCorrectionComponent } from './qr-code/qr-code-error-correction/qr-code-error-correction.component'; +import { QrCodeSizeComponent } from './qr-code/qr-code-size/qr-code-size.component'; +import { QrCodeDotShapesComponent } from './qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component'; +import { QrCodeCornerShapesComponent } from './qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component'; +import { QrCodeLogoComponent } from './qr-code/qr-code-logo/qr-code-logo.component'; export const DataDisplayRoutes: Routes = [ { @@ -183,6 +197,36 @@ export const DataDisplayRoutes: Routes = [ data: dataDisplayRoutesData['igx-for-sample-2'], path: 'igx-for-sample-2' }, + { + component: VirtualScrollOverviewComponent, + data: dataDisplayRoutesData['virtual-scroll-overview'], + path: 'virtual-scroll-overview' + }, + { + component: VirtualScrollVariableSizeComponent, + data: dataDisplayRoutesData['virtual-scroll-variable-size'], + path: 'virtual-scroll-variable-size' + }, + { + component: VirtualScrollHorizontalComponent, + data: dataDisplayRoutesData['virtual-scroll-horizontal'], + path: 'virtual-scroll-horizontal' + }, + { + component: VirtualScrollScrollToIndexComponent, + data: dataDisplayRoutesData['virtual-scroll-scroll-to-index'], + path: 'virtual-scroll-scroll-to-index' + }, + { + component: VirtualScrollInfiniteScrollComponent, + data: dataDisplayRoutesData['virtual-scroll-infinite-scroll'], + path: 'virtual-scroll-infinite-scroll' + }, + { + component: VirtualScrollPagedDataComponent, + data: dataDisplayRoutesData['virtual-scroll-paged-data'], + path: 'virtual-scroll-paged-data' + }, { component: LinearDynamicSampleComponent, data: dataDisplayRoutesData['linear-dynamic-sample'], @@ -282,5 +326,46 @@ export const DataDisplayRoutes: Routes = [ component: MaterialIconsExtendedComponent, data: dataDisplayRoutesData['material-icons-extended'], path: 'material-icons-extended' + }, + { + component: QrCodeOverviewComponent, + data: dataDisplayRoutesData['qr-code-overview'], + path: 'qr-code-overview' + }, + { + component: QrCodeErrorCorrectionComponent, + data: dataDisplayRoutesData['qr-code-error-correction'], + path: 'qr-code-error-correction' + }, + { + component: QrCodeSizeComponent, + data: dataDisplayRoutesData['qr-code-size'], + path: 'qr-code-size' + }, + { + component: QrCodeStylingComponent, + data: dataDisplayRoutesData['qr-code-styling'], + path: 'qr-code-styling' + }, + { + component: QrCodeDotShapesComponent, + data: dataDisplayRoutesData['qr-code-dot-shapes'], + path: 'qr-code-dot-shapes' + }, + { + component: QrCodeCornerShapesComponent, + data: dataDisplayRoutesData['qr-code-corner-shapes'], + path: 'qr-code-corner-shapes' + }, + { + component: QrCodeLogoComponent, + data: dataDisplayRoutesData['qr-code-logo'], + path: 'qr-code-logo' + }, + + { + component: QrCodeTailwindStylingComponent, + data: dataDisplayRoutesData['qr-code-tailwind-styling'], + path: 'qr-code-tailwind-styling' } ]; diff --git a/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.html b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.html new file mode 100644 index 0000000000..9d4298ed79 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.html @@ -0,0 +1,12 @@ +
+ + Square style: square +
+
+ + Square style: circle +
+
+ + Square style: rounded +
diff --git a/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.scss b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.scss new file mode 100644 index 0000000000..62ea1b7fe9 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.scss @@ -0,0 +1,30 @@ +:host { + display: flex; + align-items: flex-start; + gap: 3.75rem; + justify-content: center; + flex-direction: row; + overflow-y: auto; + height: 100%; + font-family: "Aktiv Grotesk", sans-serif; +} + +div { + display: flex; + flex-direction: column; + align-items: center; +} + +span { + margin-block-start: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +@media (width < 850px) { + :host { + flex-direction: column; + align-items: center; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.ts b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.ts new file mode 100644 index 0000000000..882bfce599 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-corner-shapes/qr-code-corner-shapes.component.ts @@ -0,0 +1,13 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-corner-shapes', + templateUrl: './qr-code-corner-shapes.component.html', + styleUrls: ['./qr-code-corner-shapes.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeCornerShapesComponent { +} diff --git a/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.html b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.html new file mode 100644 index 0000000000..af3cf80ce3 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.html @@ -0,0 +1,12 @@ +
+ + Dot style: square +
+
+ + Dot style: circle +
+
+ + Dot style: rounded +
diff --git a/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.scss b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.scss new file mode 100644 index 0000000000..62ea1b7fe9 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.scss @@ -0,0 +1,30 @@ +:host { + display: flex; + align-items: flex-start; + gap: 3.75rem; + justify-content: center; + flex-direction: row; + overflow-y: auto; + height: 100%; + font-family: "Aktiv Grotesk", sans-serif; +} + +div { + display: flex; + flex-direction: column; + align-items: center; +} + +span { + margin-block-start: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +@media (width < 850px) { + :host { + flex-direction: column; + align-items: center; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.ts b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.ts new file mode 100644 index 0000000000..8ad0cc61e0 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-dot-shapes/qr-code-dot-shapes.component.ts @@ -0,0 +1,13 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-dot-shapes', + templateUrl: './qr-code-dot-shapes.component.html', + styleUrls: ['./qr-code-dot-shapes.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeDotShapesComponent { +} diff --git a/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.html b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.html new file mode 100644 index 0000000000..be9ca34e2e --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.html @@ -0,0 +1,12 @@ +
+ > + Error level: L +
+
+ > + Error level: M +
+
+ > + Error level: Q +
diff --git a/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.scss b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.scss new file mode 100644 index 0000000000..62ea1b7fe9 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.scss @@ -0,0 +1,30 @@ +:host { + display: flex; + align-items: flex-start; + gap: 3.75rem; + justify-content: center; + flex-direction: row; + overflow-y: auto; + height: 100%; + font-family: "Aktiv Grotesk", sans-serif; +} + +div { + display: flex; + flex-direction: column; + align-items: center; +} + +span { + margin-block-start: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +@media (width < 850px) { + :host { + flex-direction: column; + align-items: center; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.ts b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.ts new file mode 100644 index 0000000000..3790218fca --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-error-correction/qr-code-error-correction.component.ts @@ -0,0 +1,13 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-error-correction', + templateUrl: './qr-code-error-correction.component.html', + styleUrls: ['./qr-code-error-correction.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeErrorCorrectionComponent { +} diff --git a/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.html b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.html new file mode 100644 index 0000000000..69175e4213 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.html @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.scss b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.scss similarity index 50% rename from src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.scss rename to src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.scss index 3de9aa4997..f21bc9f9bb 100644 --- a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.scss +++ b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.scss @@ -1,4 +1,4 @@ :host { display: flex; - padding: 16px; + justify-content: center; } diff --git a/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.ts b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.ts new file mode 100644 index 0000000000..03601dda0a --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-logo/qr-code-logo.component.ts @@ -0,0 +1,14 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-logo', + templateUrl: './qr-code-logo.component.html', + styleUrls: ['./qr-code-logo.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeLogoComponent { + public readonly logoSrc = 'https://static.infragistics.com/marketing/Website/products/ignite-ui/shared/ignite-ui-logo-light-background-horizontal.svg'; +} diff --git a/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.html b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.html new file mode 100644 index 0000000000..412f22793e --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.html @@ -0,0 +1,27 @@ +
+ + Square + Circle + Rounded + + + + Small + Medium + Large + Extra large + + + Logo +
+ + diff --git a/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.scss b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.scss new file mode 100644 index 0000000000..7e602e0753 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.scss @@ -0,0 +1,24 @@ +:host { + display: flex; + flex-direction: column; + align-items: center; + gap: 2.5rem; + overflow-y: auto; + height: 100%; +} + +.qr-controls { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 2.5rem; +} + +igx-radio-group { + display: flex; + align-items: center; + flex-wrap: wrap; + width: fit-content; + gap: 0.25rem; +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.ts b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.ts new file mode 100644 index 0000000000..ba69eaa348 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-overview/qr-code-overview.component.ts @@ -0,0 +1,23 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; +import { IgxRadioGroupDirective, IgxRadioComponent } from 'igniteui-angular/radio'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-overview', + templateUrl: './qr-code-overview.component.html', + styleUrls: ['./qr-code-overview.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [FormsModule, IgxRadioGroupDirective, IgxRadioComponent, IgxSwitchComponent] +}) +export class QrCodeOverviewComponent { + public shape: 'square' | 'circle' | 'rounded' = 'square'; + public size = 300; + public showLogo = true; + + public readonly value = 'https://www.infragistics.com/products/ignite-ui-web-components'; + public readonly logoSrc = 'https://static.infragistics.com/marketing/Website/products/ignite-ui/shared/ignite-ui-logo-light-background-horizontal.svg'; +} diff --git a/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.html b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.html new file mode 100644 index 0000000000..dc437fda32 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.html @@ -0,0 +1,12 @@ +
+ > + Size: 128px +
+
+ > + Size: 192px +
+
+ > + Size: 256px +
\ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.scss b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.scss new file mode 100644 index 0000000000..deb4beee82 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.scss @@ -0,0 +1,30 @@ +:host { + display: flex; + align-items: baseline; + gap: 3.75rem; + justify-content: center; + flex-direction: row; + overflow-y: auto; + height: 100%; + font-family: "Aktiv Grotesk", sans-serif; +} + +div { + display: flex; + flex-direction: column; + align-items: center; +} + +span { + margin-block-start: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +@media (width < 850px) { + :host { + flex-direction: column; + align-items: center; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.ts b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.ts new file mode 100644 index 0000000000..173efa4b85 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-size/qr-code-size.component.ts @@ -0,0 +1,14 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-size', + templateUrl: './qr-code-size.component.html', + styleUrls: ['./qr-code-size.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeSizeComponent { + public readonly value = 'https://www.infragistics.com/products/ignite-ui-web-components'; +} diff --git a/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.html b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.html new file mode 100644 index 0000000000..6b00fc2b65 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.html @@ -0,0 +1,8 @@ + + + + diff --git a/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.scss b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.scss new file mode 100644 index 0000000000..b748a92836 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.scss @@ -0,0 +1,37 @@ +:host { + display: flex; + align-items: flex-start; + gap: 3.75rem; + justify-content: center; + flex-direction: row; + overflow-y: auto; + height: 100%; +} + +.qr-blue { + --ig-qr-code-background: #e3edfb; + --ig-qr-code-dark-color: #1361e0; +} + +.qr-orange { + --ig-qr-code-background: #fbe6e1; + --ig-qr-code-dark-color: #f0562b; +} + +.qr-green { + --ig-qr-code-background: #e5f7e6; + --ig-qr-code-dark-color: #3fa845; +} + +.qr-dark { + --ig-qr-code-background: #0b1b3a; + --ig-qr-code-dark-color: #ffffff; +} + +@media (width < 850px) { + :host { + flex-direction: column; + align-items: center; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.ts b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.ts new file mode 100644 index 0000000000..7fa8456031 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-styling/qr-code-styling.component.ts @@ -0,0 +1,14 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-styling', + templateUrl: './qr-code-styling.component.html', + styleUrls: ['./qr-code-styling.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeStylingComponent { + public readonly value = 'https://www.infragistics.com/products/ignite-ui-web-components'; +} diff --git a/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.html b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.html new file mode 100644 index 0000000000..22a1bb3e2d --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.html @@ -0,0 +1,19 @@ +
+ + + + +
\ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.scss b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.scss new file mode 100644 index 0000000000..53ba8128ab --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.scss @@ -0,0 +1,22 @@ +:host { + display: block; + height: 100%; + overflow-y: auto; +} + +.container { + display: flex; + gap: 1.5rem; + padding: 1rem; + background: #111; + width: fit-content; + flex-direction: row; + flex-wrap: wrap; + margin-inline: auto; +} + +@media (width < 800px) { + .container { + flex-direction: column; + } +} \ No newline at end of file diff --git a/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.ts b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.ts new file mode 100644 index 0000000000..16a0739ba4 --- /dev/null +++ b/src/app/data-display/qr-code/qr-code-tailwind-styling/qr-code-tailwind-styling.component.ts @@ -0,0 +1,12 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcQrCodeComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcQrCodeComponent); + +@Component({ + selector: 'app-qr-code-tailwind-styling', + templateUrl: './qr-code-tailwind-styling.component.html', + styleUrls: ['./qr-code-tailwind-styling.component.scss'], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class QrCodeTailwindStylingComponent { } diff --git a/src/app/data-display/virtual-scroll/employees.ts b/src/app/data-display/virtual-scroll/employees.ts new file mode 100644 index 0000000000..99d94b972f --- /dev/null +++ b/src/app/data-display/virtual-scroll/employees.ts @@ -0,0 +1,52 @@ +export type DepartmentVariant = 'primary' | 'info' | 'success' | 'warning' | 'danger'; + +export interface Employee { + id: number; + name: string; + initials: string; + email: string; + department: string; + variant: DepartmentVariant; + bio: string | null; +} + +const DEPARTMENTS = ['Engineering', 'Design', 'Marketing', 'Sales', 'HR', 'Finance', 'Legal', 'Operations']; +const VARIANTS: DepartmentVariant[] = ['primary', 'info', 'success', 'warning', 'danger']; + +const FIRST_NAMES = [ + 'Alice', 'Bob', 'Carol', 'David', 'Eve', 'Frank', 'Grace', 'Henry', + 'Iris', 'Jack', 'Karen', 'Leo', 'Mia', 'Noah', 'Olivia', 'Paul' +]; + +const LAST_NAMES = [ + 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', + 'Davis', 'Wilson', 'Moore', 'Taylor', 'Anderson', 'Thomas', 'Jackson' +]; + +const BIOS = [ + 'Leads a cross-functional team across three time zones and owns the quarterly delivery plan.', + 'Specializes in scalable service architecture.', + 'Passionate about accessible, pixel-perfect user interfaces and design systems that scale across products.', + 'Drives product strategy and stakeholder alignment.', + 'Champions data-driven decision making, runs the weekly metrics review and mentors new analysts.' +]; + +export function createEmployee(index: number): Employee { + const first = FIRST_NAMES[index % FIRST_NAMES.length]; + const last = LAST_NAMES[Math.floor(index / FIRST_NAMES.length) % LAST_NAMES.length]; + const departmentIndex = index % DEPARTMENTS.length; + + return { + id: index + 1, + name: `${first} ${last}`, + initials: `${first[0]}${last[0]}`, + email: `${first.toLowerCase()}.${last.toLowerCase()}${index + 1}@example.com`, + department: DEPARTMENTS[departmentIndex], + variant: VARIANTS[departmentIndex % VARIANTS.length], + bio: index % 3 === 0 ? BIOS[index % BIOS.length] : null + }; +} + +export function generateEmployees(count: number, startIndex = 0): Employee[] { + return Array.from({ length: count }, (_, i) => createEmployee(startIndex + i)); +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.html new file mode 100644 index 0000000000..35519873f7 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.html @@ -0,0 +1,21 @@ + + +
+ + + +

{{ employee.name }}

+
{{ employee.bio ? employee.email : '#' + employee.id }}
+
+ + {{ employee.department }} + +
+
+
+
diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.scss new file mode 100644 index 0000000000..e2df6834ef --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.scss @@ -0,0 +1,25 @@ +:host { + display: block; + padding: 16px; +} + +.cards { + block-size: 200px; +} + +// Items are measured by their border box, so the spacing between cards is +// padding on the item wrapper rather than a margin. +.cards__item { + box-sizing: border-box; + inline-size: 220px; + block-size: 100%; + padding: 8px; + + igx-card { + block-size: 100%; + } +} + +.cards__item--wide { + inline-size: 320px; +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.ts new file mode 100644 index 0000000000..62d3bc5101 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-horizontal/virtual-scroll-horizontal.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxCardComponent, IgxCardContentDirective, IgxCardHeaderComponent, IgxCardHeaderSubtitleDirective, IgxCardHeaderTitleDirective, IgxCardThumbnailDirective } from 'igniteui-angular/card'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +@Component({ + selector: 'app-virtual-scroll-horizontal', + styleUrls: ['./virtual-scroll-horizontal.component.scss'], + templateUrl: './virtual-scroll-horizontal.component.html', + imports: [ + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxCardComponent, + IgxCardHeaderComponent, + IgxCardThumbnailDirective, + IgxCardHeaderTitleDirective, + IgxCardHeaderSubtitleDirective, + IgxCardContentDirective, + IgxAvatarComponent, + IgxChipComponent + ] +}) +export class VirtualScrollHorizontalComponent { + public readonly employees: Employee[] = generateEmployees(10_000); +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.html new file mode 100644 index 0000000000..cae74ff601 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.html @@ -0,0 +1,22 @@ + + Loaded {{ employees().length }} of {{ totalCount }} employees + + + + + #{{ employee.id }} {{ employee.name }} + {{ employee.email }} + {{ employee.department }} + + + +
+ @if (loading()) { + + } +
+
diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.scss new file mode 100644 index 0000000000..85cd472c6e --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.scss @@ -0,0 +1,12 @@ +:host { + display: block; + padding: 16px; +} + +.employees__viewport { + block-size: 440px; +} + +.employees__status { + block-size: 4px; +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.ts new file mode 100644 index 0000000000..056dd1ef17 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-infinite-scroll/virtual-scroll-infinite-scroll.component.ts @@ -0,0 +1,62 @@ +import { Component, signal } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { + IgxListActionDirective, + IgxListComponent, + IgxListItemComponent, + IgxListLineSubTitleDirective, + IgxListLineTitleDirective, + IgxListThumbnailDirective +} from 'igniteui-angular/list'; +import { IgxLinearProgressBarComponent } from 'igniteui-angular/progressbar'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent, VirtualScrollDataRequest } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +/** The size of the whole remote collection. */ +const TOTAL_COUNT = 1_000; +const PAGE_SIZE = 50; + +@Component({ + selector: 'app-virtual-scroll-infinite-scroll', + styleUrls: ['./virtual-scroll-infinite-scroll.component.scss'], + templateUrl: './virtual-scroll-infinite-scroll.component.html', + imports: [ + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListActionDirective, + IgxAvatarComponent, + IgxChipComponent, + IgxLinearProgressBarComponent + ] +}) +export class VirtualScrollInfiniteScrollComponent { + public readonly totalCount = TOTAL_COUNT; + public readonly employees = signal(generateEmployees(PAGE_SIZE)); + public readonly loading = signal(false); + + /** + * `dataRequest` is emitted when the rendered window nears the end of `data`. + * Only one request is emitted at a time: the next one follows the next `data` change. + */ + public loadMore(request: VirtualScrollDataRequest): void { + if (this.loading() || request.startIndex >= TOTAL_COUNT) { + return; + } + + this.loading.set(true); + const count = Math.min(Math.max(request.count, PAGE_SIZE), TOTAL_COUNT - request.startIndex); + + // Simulates a request to a remote service. + setTimeout(() => { + // Assign a new array: `data` is compared by reference. + this.employees.update(current => [...current, ...generateEmployees(count, request.startIndex)]); + this.loading.set(false); + }, 800); + } +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.html new file mode 100644 index 0000000000..c7968217bc --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.html @@ -0,0 +1,13 @@ + + Employees ({{ employees.length }}) + + + + + {{ employee.name }} + {{ employee.email }} + {{ employee.department }} + + + + diff --git a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.scss similarity index 50% rename from src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.scss rename to src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.scss index 5bc4862429..93ada4e191 100644 --- a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.scss +++ b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.scss @@ -2,3 +2,7 @@ display: block; padding: 16px; } + +.employees__viewport { + block-size: 480px; +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.ts new file mode 100644 index 0000000000..7d3d04cbac --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-overview/virtual-scroll-overview.component.ts @@ -0,0 +1,34 @@ +import { Component } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { + IgxListActionDirective, + IgxListComponent, + IgxListItemComponent, + IgxListLineSubTitleDirective, + IgxListLineTitleDirective, + IgxListThumbnailDirective +} from 'igniteui-angular/list'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +@Component({ + selector: 'app-virtual-scroll-overview', + styleUrls: ['./virtual-scroll-overview.component.scss'], + templateUrl: './virtual-scroll-overview.component.html', + imports: [ + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListActionDirective, + IgxAvatarComponent, + IgxChipComponent + ] +}) +export class VirtualScrollOverviewComponent { + public readonly employees: Employee[] = generateEmployees(100_000); +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.html new file mode 100644 index 0000000000..27b8534f49 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.html @@ -0,0 +1,24 @@ + + + Records {{ page().startIndex + 1 }}–{{ page().startIndex + page().items.length }} of {{ page().totalCount }} in memory + + + + + + #{{ employee.id }} {{ employee.name }} + {{ employee.email }} + {{ employee.department }} + + + +
+ @if (loading()) { + + } +
+
diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.scss new file mode 100644 index 0000000000..85cd472c6e --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.scss @@ -0,0 +1,12 @@ +:host { + display: block; + padding: 16px; +} + +.employees__viewport { + block-size: 440px; +} + +.employees__status { + block-size: 4px; +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.ts new file mode 100644 index 0000000000..cf4e7f1d47 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-paged-data/virtual-scroll-paged-data.component.ts @@ -0,0 +1,86 @@ +import { Component, signal } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { + IgxListActionDirective, + IgxListComponent, + IgxListItemComponent, + IgxListLineSubTitleDirective, + IgxListLineTitleDirective, + IgxListThumbnailDirective +} from 'igniteui-angular/list'; +import { IgxLinearProgressBarComponent } from 'igniteui-angular/progressbar'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent, VirtualDataWindow, VirtualScrollState } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +/** The size of the whole remote collection. */ +const TOTAL_COUNT = 100_000; +/** Extra records requested on each side of the range the viewport wants. */ +const BUFFER = 30; + +@Component({ + selector: 'app-virtual-scroll-paged-data', + styleUrls: ['./virtual-scroll-paged-data.component.scss'], + templateUrl: './virtual-scroll-paged-data.component.html', + imports: [ + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListActionDirective, + IgxAvatarComponent, + IgxChipComponent, + IgxLinearProgressBarComponent + ] +}) +export class VirtualScrollPagedDataComponent { + /** Only this page is in memory, while the scrollbar spans `totalCount` records. */ + public readonly page = signal>({ + items: generateEmployees(2 * BUFFER), + startIndex: 0, + totalCount: TOTAL_COUNT + }); + public readonly loading = signal(false); + + private wantedRange: VirtualScrollState | null = null; + + /** `stateChange` reports the range the viewport wants, which the next page is loaded from. */ + public onStateChange(state: VirtualScrollState): void { + this.wantedRange = state; + this.loadPageIfNeeded(); + } + + private loadPageIfNeeded(): void { + const wanted = this.wantedRange; + if (!wanted || wanted.endIndex < wanted.startIndex || this.loading()) { + return; + } + + const page = this.page(); + const pageEnd = page.startIndex + page.items.length - 1; + if (wanted.startIndex >= page.startIndex && wanted.endIndex <= pageEnd) { + return; + } + + const startIndex = Math.max(0, wanted.startIndex - BUFFER); + const endIndex = Math.min(TOTAL_COUNT - 1, wanted.endIndex + BUFFER); + + this.loading.set(true); + this.fetchPage(startIndex, endIndex - startIndex + 1).then(({ items, totalCount }) => { + this.page.set({ items, startIndex, totalCount }); + this.loading.set(false); + // The user may have scrolled further while the request was in flight. + this.loadPageIfNeeded(); + }); + } + + /** Simulates a request to a remote service that supports skip/take paging. */ + private fetchPage(skip: number, take: number): Promise<{ items: Employee[]; totalCount: number }> { + return new Promise(resolve => { + setTimeout(() => resolve({ items: generateEmployees(take, skip), totalCount: TOTAL_COUNT }), 300); + }); + } +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.html new file mode 100644 index 0000000000..4469bcaace --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.html @@ -0,0 +1,45 @@ +
+ + + + + + + @for (value of alignments; track value) { + {{ value }} + } + + +
+ + + + + +
+
+ + + Employees ({{ employees.length }}) + + + + + #{{ index }} {{ employee.name }} + {{ employee.email }} + {{ employee.department }} + + + + diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.scss new file mode 100644 index 0000000000..efa47683dd --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.scss @@ -0,0 +1,40 @@ +:host { + display: block; + padding: 16px; +} + +.toolbar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 16px; + margin-block-end: 16px; +} + +.toolbar__index { + inline-size: 140px; +} + +.toolbar__actions { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.employees__viewport { + block-size: 400px; +} + +.employees__item--highlighted { + animation: highlight 1.5s ease-out; +} + +@keyframes highlight { + from { + box-shadow: inset 0 0 0 3px var(--ig-warn-500); + } + + to { + box-shadow: inset 0 0 0 3px transparent; + } +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.ts new file mode 100644 index 0000000000..c5440eda05 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-scroll-to-index/virtual-scroll-scroll-to-index.component.ts @@ -0,0 +1,68 @@ +import { Component, signal, viewChild } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective } from 'igniteui-angular/input-group'; +import { + IgxListActionDirective, + IgxListComponent, + IgxListItemComponent, + IgxListLineSubTitleDirective, + IgxListLineTitleDirective, + IgxListThumbnailDirective +} from 'igniteui-angular/list'; +import { IgxRadioComponent, IgxRadioGroupDirective } from 'igniteui-angular/radio'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +@Component({ + selector: 'app-virtual-scroll-scroll-to-index', + styleUrls: ['./virtual-scroll-scroll-to-index.component.scss'], + templateUrl: './virtual-scroll-scroll-to-index.component.html', + imports: [ + FormsModule, + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxInputGroupComponent, + IgxInputDirective, + IgxLabelDirective, + IgxRadioGroupDirective, + IgxRadioComponent, + IgxButtonDirective, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListActionDirective, + IgxAvatarComponent, + IgxChipComponent + ] +}) +export class VirtualScrollScrollToIndexComponent { + public readonly employees: Employee[] = generateEmployees(100_000); + public readonly alignments: ScrollLogicalPosition[] = ['start', 'center', 'end', 'nearest']; + + public readonly targetIndex = signal(50_000); + public readonly alignment = signal('start'); + public readonly highlightedIndex = signal(null); + + private readonly virtualScroll = viewChild.required>('virtualScroll'); + + public async goTo(index: number): Promise { + const target = Math.min(Math.max(Math.trunc(index) || 0, 0), this.employees.length - 1); + this.targetIndex.set(target); + this.highlightedIndex.set(null); + + // Items that have not been rendered only have an estimated size, so the + // first jump lands near the target. The promise resolves once the + // component has measured the landing area and corrected the offset. + await this.virtualScroll().scrollToIndex(target, { block: this.alignment() }); + this.highlightedIndex.set(target); + } + + public goToRandom(): void { + this.goTo(Math.floor(Math.random() * this.employees.length)); + } +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.html b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.html new file mode 100644 index 0000000000..051234423d --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.html @@ -0,0 +1,16 @@ + + Team directory ({{ employees.length }}) + + + + + {{ employee.name }} + {{ employee.email }} + @if (employee.bio) { + {{ employee.bio }} + } + {{ employee.department }} + + + + diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.scss b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.scss new file mode 100644 index 0000000000..33088f9700 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.scss @@ -0,0 +1,14 @@ +:host { + display: block; + padding: 16px; +} + +.employees__viewport { + block-size: 480px; +} + +.employees__bio { + padding-block-start: 4px; + white-space: normal; + color: var(--ig-gray-700); +} diff --git a/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.ts b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.ts new file mode 100644 index 0000000000..ce3366e283 --- /dev/null +++ b/src/app/data-display/virtual-scroll/virtual-scroll-variable-size/virtual-scroll-variable-size.component.ts @@ -0,0 +1,36 @@ +import { Component } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxChipComponent } from 'igniteui-angular/chips'; +import { + IgxListActionDirective, + IgxListComponent, + IgxListItemComponent, + IgxListLineDirective, + IgxListLineSubTitleDirective, + IgxListLineTitleDirective, + IgxListThumbnailDirective +} from 'igniteui-angular/list'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent } from 'igniteui-angular/virtual-scroll'; +import { Employee, generateEmployees } from '../employees'; + +@Component({ + selector: 'app-virtual-scroll-variable-size', + styleUrls: ['./virtual-scroll-variable-size.component.scss'], + templateUrl: './virtual-scroll-variable-size.component.html', + imports: [ + IgxVirtualScrollComponent, + IgxVirtualItemDirective, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListLineDirective, + IgxListActionDirective, + IgxAvatarComponent, + IgxChipComponent + ] +}) +export class VirtualScrollVariableSizeComponent { + public readonly employees: Employee[] = generateEmployees(10_000); +} diff --git a/src/app/data-entries/button/button-contained/button-contained.component.html b/src/app/data-entries/button/button-contained/button-contained.component.html new file mode 100644 index 0000000000..48a7b7ad3d --- /dev/null +++ b/src/app/data-entries/button/button-contained/button-contained.component.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/src/app/data-entries/button/button-contained/button-contained.component.scss b/src/app/data-entries/button/button-contained/button-contained.component.scss new file mode 100644 index 0000000000..c98e6acd18 --- /dev/null +++ b/src/app/data-entries/button/button-contained/button-contained.component.scss @@ -0,0 +1,9 @@ +.button-sample { + display: flex; + padding: 2.5rem; +} + +.button-sample button { + width: 46%; + margin: auto; +} diff --git a/src/app/data-entries/button/button-contained/button-contained.component.ts b/src/app/data-entries/button/button-contained/button-contained.component.ts new file mode 100644 index 0000000000..7caea5fad4 --- /dev/null +++ b/src/app/data-entries/button/button-contained/button-contained.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-contained', + styleUrls: ['./button-contained.component.scss'], + templateUrl: './button-contained.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonContainedComponent { } diff --git a/src/app/data-entries/button/button-download/button-download.component.html b/src/app/data-entries/button/button-download/button-download.component.html new file mode 100644 index 0000000000..165292aa2e --- /dev/null +++ b/src/app/data-entries/button/button-download/button-download.component.html @@ -0,0 +1,3 @@ + diff --git a/src/app/data-entries/button/button-download/button-download.component.scss b/src/app/data-entries/button/button-download/button-download.component.scss new file mode 100644 index 0000000000..0809677340 --- /dev/null +++ b/src/app/data-entries/button/button-download/button-download.component.scss @@ -0,0 +1,9 @@ +.button-sample { + display: flex; + padding: 2.5rem; +} + +.button-sample a { + width: 46%; + margin: auto; +} diff --git a/src/app/data-entries/button/button-download/button-download.component.ts b/src/app/data-entries/button/button-download/button-download.component.ts new file mode 100644 index 0000000000..f382891209 --- /dev/null +++ b/src/app/data-entries/button/button-download/button-download.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; + +@Component({ + selector: 'app-button-download', + styleUrls: ['./button-download.component.scss'], + templateUrl: './button-download.component.html', + imports: [IgxButtonDirective] +}) +export class ButtonDownloadComponent { } diff --git a/src/app/data-entries/button/button-fab/button-fab.component.html b/src/app/data-entries/button/button-fab/button-fab.component.html new file mode 100644 index 0000000000..8eaaad311b --- /dev/null +++ b/src/app/data-entries/button/button-fab/button-fab.component.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/src/app/data-entries/button/button-fab/button-fab.component.scss b/src/app/data-entries/button/button-fab/button-fab.component.scss new file mode 100644 index 0000000000..d41b93c4b1 --- /dev/null +++ b/src/app/data-entries/button/button-fab/button-fab.component.scss @@ -0,0 +1,9 @@ +.button-sample { + display: flex; + padding: 2rem; +} + +.button-sample button { + width: 45%; + margin: auto; +} diff --git a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.ts b/src/app/data-entries/button/button-fab/button-fab.component.ts similarity index 55% rename from src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.ts rename to src/app/data-entries/button/button-fab/button-fab.component.ts index 6d07452311..d611bb25ea 100644 --- a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.ts +++ b/src/app/data-entries/button/button-fab/button-fab.component.ts @@ -3,9 +3,9 @@ import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; @Component({ - selector: 'app-buttons-sample-6', - styleUrls: ['./buttons-sample-6.component.scss'], - templateUrl: './buttons-sample-6.component.html', + selector: 'app-button-fab', + styleUrls: ['./button-fab.component.scss'], + templateUrl: './button-fab.component.html', imports: [IgxButtonDirective, IgxIconComponent] }) -export class ButtonsSample6Component { } +export class ButtonFabComponent { } diff --git a/src/app/data-entries/button/button-flat/button-flat.component.html b/src/app/data-entries/button/button-flat/button-flat.component.html new file mode 100644 index 0000000000..c5c68089a8 --- /dev/null +++ b/src/app/data-entries/button/button-flat/button-flat.component.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/src/app/data-entries/button/button-flat/button-flat.component.scss b/src/app/data-entries/button/button-flat/button-flat.component.scss new file mode 100644 index 0000000000..c98e6acd18 --- /dev/null +++ b/src/app/data-entries/button/button-flat/button-flat.component.scss @@ -0,0 +1,9 @@ +.button-sample { + display: flex; + padding: 2.5rem; +} + +.button-sample button { + width: 46%; + margin: auto; +} diff --git a/src/app/data-entries/button/button-flat/button-flat.component.ts b/src/app/data-entries/button/button-flat/button-flat.component.ts new file mode 100644 index 0000000000..ab6dcb1229 --- /dev/null +++ b/src/app/data-entries/button/button-flat/button-flat.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-flat', + styleUrls: ['./button-flat.component.scss'], + templateUrl: './button-flat.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonFlatComponent { } diff --git a/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.html b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.html new file mode 100644 index 0000000000..fca47f84e6 --- /dev/null +++ b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.html @@ -0,0 +1,12 @@ +
+ @for (state of states; track state.value) { +
+ {{ state.label }} + +
+ } +
diff --git a/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.scss b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.scss new file mode 100644 index 0000000000..02a12c7905 --- /dev/null +++ b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.scss @@ -0,0 +1,47 @@ +@use "igniteui-angular/theming" as *; + +.button-container { + display: flex; + justify-content: center; + align-items: center; + gap: 2rem; + padding: 1rem; +} + +.button-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; + --hover-background: var(--ig-contained-button-hover-background); + --hover-foreground: var(--ig-contained-button-hover-foreground); + --focus-background: var(--ig-contained-button-focus-background); + --focus-foreground: var(--ig-contained-button-focus-foreground); + --focus-hover-background: var(--ig-contained-button-focus-hover-background); + --focus-hover-foreground: var(--ig-contained-button-focus-hover-foreground); +} + +.button-label { + color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: 13px; + font-weight: 400; + font-style: normal; + line-height: 20px; + letter-spacing: 0.3px; +} + +.button-item button.state-hover { + background: var(--hover-background); + color: var(--hover-foreground); +} + +.button-item button.state-focused { + background: var(--focus-background); + color: var(--focus-foreground); +} + +.button-item button.state-focused-hover { + background: var(--focus-hover-background); + color: var(--focus-hover-foreground); +} diff --git a/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.ts b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.ts new file mode 100644 index 0000000000..0e2ddee7da --- /dev/null +++ b/src/app/data-entries/button/button-interaction-states/button-interaction-states.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-interaction-states', + styleUrls: ['./button-interaction-states.component.scss'], + templateUrl: './button-interaction-states.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonInteractionStatesComponent { + public states = [ + { label: 'Idle', value: 'idle' }, + { label: 'Hover', value: 'state-hover' }, + { label: 'Focused', value: 'state-focused' }, + { label: 'Focused & Hover', value: 'state-focused-hover' } + ]; +} diff --git a/src/app/data-entries/button/button-layout/button-layout.component.html b/src/app/data-entries/button/button-layout/button-layout.component.html new file mode 100644 index 0000000000..ac8ca6e9f2 --- /dev/null +++ b/src/app/data-entries/button/button-layout/button-layout.component.html @@ -0,0 +1,8 @@ +
+
+
+
+
+
+
+
diff --git a/src/app/data-entries/button/button-layout/button-layout.component.scss b/src/app/data-entries/button/button-layout/button-layout.component.scss new file mode 100644 index 0000000000..7b8cb2563f --- /dev/null +++ b/src/app/data-entries/button/button-layout/button-layout.component.scss @@ -0,0 +1,24 @@ +.button-container { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + width: 100%; + box-sizing: border-box; + padding: 2.5rem; +} + +.button-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; +} + +.button-container button { + --ig-font-family: 'Titillium Web', sans-serif; + --ig-button-text-transform: uppercase; + + font-size: 0.85rem; + letter-spacing: 1px; +} diff --git a/src/app/data-entries/button/button-layout/button-layout.component.ts b/src/app/data-entries/button/button-layout/button-layout.component.ts new file mode 100644 index 0000000000..f7c82fea63 --- /dev/null +++ b/src/app/data-entries/button/button-layout/button-layout.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-layout', + styleUrls: ['./button-layout.component.scss'], + templateUrl: './button-layout.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonLayoutComponent { +} diff --git a/src/app/data-entries/button/button-outlined/button-outlined.component.html b/src/app/data-entries/button/button-outlined/button-outlined.component.html new file mode 100644 index 0000000000..b5f35da49f --- /dev/null +++ b/src/app/data-entries/button/button-outlined/button-outlined.component.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/src/app/data-entries/button/button-outlined/button-outlined.component.scss b/src/app/data-entries/button/button-outlined/button-outlined.component.scss new file mode 100644 index 0000000000..c98e6acd18 --- /dev/null +++ b/src/app/data-entries/button/button-outlined/button-outlined.component.scss @@ -0,0 +1,9 @@ +.button-sample { + display: flex; + padding: 2.5rem; +} + +.button-sample button { + width: 46%; + margin: auto; +} diff --git a/src/app/data-entries/button/button-outlined/button-outlined.component.ts b/src/app/data-entries/button/button-outlined/button-outlined.component.ts new file mode 100644 index 0000000000..41cff29372 --- /dev/null +++ b/src/app/data-entries/button/button-outlined/button-outlined.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-outlined', + styleUrls: ['./button-outlined.component.scss'], + templateUrl: './button-outlined.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonOutlinedComponent { } diff --git a/src/app/data-entries/button/button-overview/button-overview.component.html b/src/app/data-entries/button/button-overview/button-overview.component.html new file mode 100644 index 0000000000..b4963b3145 --- /dev/null +++ b/src/app/data-entries/button/button-overview/button-overview.component.html @@ -0,0 +1,15 @@ +
+ +
+ + + + + + +
+ + +
+
+
diff --git a/src/app/data-entries/button/button-overview/button-overview.component.scss b/src/app/data-entries/button/button-overview/button-overview.component.scss new file mode 100644 index 0000000000..6c2b3ea3ca --- /dev/null +++ b/src/app/data-entries/button/button-overview/button-overview.component.scss @@ -0,0 +1,37 @@ +.form { + display: flex; + justify-content: center; + gap: 1.25rem; + padding: 2.5rem; +} + +.form igx-avatar { + --ig-size: var(--ig-size-large); +} + +.fields { + display: flex; + flex-direction: column; + gap: 1rem; + max-width: 260px; + width: 100%; +} + +:host ::ng-deep .fields .igx-input-group__bundle { + background-color: var(--ig-gray-50); +} + +:host ::ng-deep .fields igx-input-group, +:host ::ng-deep .fields igx-input-group .igx-input-group__input { + --ig-size: var(--ig-size-medium); +} + +:host ::ng-deep .fields .igx-input-group__input { + margin: 0; +} +.actions { + display: flex; + justify-content: flex-end; + gap: 1rem; + margin-top: 0.5rem; +} diff --git a/src/app/data-entries/button/button-overview/button-overview.component.ts b/src/app/data-entries/button/button-overview/button-overview.component.ts new file mode 100644 index 0000000000..48c8c8b098 --- /dev/null +++ b/src/app/data-entries/button/button-overview/button-overview.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxInputDirective, IgxInputGroupComponent } from 'igniteui-angular/input-group'; + +@Component({ + selector: 'app-button-overview', + styleUrls: ['./button-overview.component.scss'], + templateUrl: './button-overview.component.html', + imports: [IgxAvatarComponent, IgxButtonDirective, IgxInputGroupComponent, IgxInputDirective] +}) +export class ButtonOverviewComponent { } diff --git a/src/app/data-entries/button/button-size/button-size.component.html b/src/app/data-entries/button/button-size/button-size.component.html new file mode 100644 index 0000000000..9f0156c2ed --- /dev/null +++ b/src/app/data-entries/button/button-size/button-size.component.html @@ -0,0 +1,20 @@ +
+
ContainedOutlinedFlatFab
+ @for (size of sizes; track size) { +
+ {{ size | titlecase }} + @for (variant of variants; track variant) { + + } + +
+ } +
diff --git a/src/app/data-entries/button/button-size/button-size.component.scss b/src/app/data-entries/button/button-size/button-size.component.scss new file mode 100644 index 0000000000..58d897c929 --- /dev/null +++ b/src/app/data-entries/button/button-size/button-size.component.scss @@ -0,0 +1,61 @@ +:host { + display: flex; + justify-content: center; + align-items: center; +} + +.size-grid { + display: flex; + flex-direction: column; + gap: 1.25rem; + padding: 1rem; + width: 100%; + box-sizing: border-box; + overflow: hidden; +} + +.size-row { + display: grid; + grid-template-columns: 70px repeat(4, minmax(0, 1fr)); + align-items: center; + justify-items: center; + column-gap: 1rem; + row-gap: 0.5rem; + width: 100%; +} + +.size-header { + display: grid; + grid-template-columns: 70px repeat(4, minmax(0, 1fr)); + align-items: center; + justify-items: center; + column-gap: 1rem; + width: 100%; + color: var(--ig-gray-600); + font: 13px/20px "Aktiv Grotesk", sans-serif; + letter-spacing: .3px; +} + +.size-label { + justify-self: start; + color: var(--ig-gray-600); + font: 400 13px/20px "Aktiv Grotesk", sans-serif; + letter-spacing: .3px; +} + +.size-row button { + width: auto; + transform: scale(.9); +} + +.size-small { + --ig-size: var(--ig-size-small) !important; +} + +.size-medium { + --ig-size: var(--ig-size-medium) !important; +} + +.size-large { + --ig-size: var(--ig-size-large) !important; +} diff --git a/src/app/data-entries/button/button-size/button-size.component.ts b/src/app/data-entries/button/button-size/button-size.component.ts new file mode 100644 index 0000000000..016ad98c77 --- /dev/null +++ b/src/app/data-entries/button/button-size/button-size.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { TitleCasePipe } from '@angular/common'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-size', + styleUrls: ['./button-size.component.scss'], + templateUrl: './button-size.component.html', + imports: [IgxButtonDirective, IgxIconComponent, TitleCasePipe] +}) +export class ButtonSizeComponent { + public sizes = ['large', 'medium', 'small']; + public variants = ['contained', 'outlined', 'flat'] as const; +} diff --git a/src/app/data-entries/button/button-states/button-states.component.html b/src/app/data-entries/button/button-states/button-states.component.html new file mode 100644 index 0000000000..cd4424548e --- /dev/null +++ b/src/app/data-entries/button/button-states/button-states.component.html @@ -0,0 +1,30 @@ +
+
+ +
+
+ +
+
+ +
+
+ +
+
diff --git a/src/app/data-entries/button/button-states/button-states.component.scss b/src/app/data-entries/button/button-states/button-states.component.scss new file mode 100644 index 0000000000..3b224d1409 --- /dev/null +++ b/src/app/data-entries/button/button-states/button-states.component.scss @@ -0,0 +1,14 @@ +.button-container { + display: flex; + justify-content: center; + align-items: center; + gap: 2rem; + padding: 2rem; +} + +.button-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; +} diff --git a/src/app/data-entries/button/button-states/button-states.component.ts b/src/app/data-entries/button/button-states/button-states.component.ts new file mode 100644 index 0000000000..398a2c54d5 --- /dev/null +++ b/src/app/data-entries/button/button-states/button-states.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-states', + styleUrls: ['./button-states.component.scss'], + templateUrl: './button-states.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonStatesComponent { } diff --git a/src/app/data-entries/button/button-styling/button-styling.component.html b/src/app/data-entries/button/button-styling/button-styling.component.html new file mode 100644 index 0000000000..6954e7df30 --- /dev/null +++ b/src/app/data-entries/button/button-styling/button-styling.component.html @@ -0,0 +1,14 @@ +
+
+ + + + +
+
diff --git a/src/app/data-entries/button/button-styling/button-styling.component.scss b/src/app/data-entries/button/button-styling/button-styling.component.scss new file mode 100644 index 0000000000..4637a2ccee --- /dev/null +++ b/src/app/data-entries/button/button-styling/button-styling.component.scss @@ -0,0 +1,39 @@ +@use "layout.scss"; + +// CSS variables approach + +.confirm-button { + --background: #1275c4; + --foreground: #fff; + --hover-background: #1275c4; + --hover-foreground: #fff; + &:hover { --hover-background: #0b4f8a; } +} + +.send-button { + --background: transparent; + --border-color: #8a2be2; + --foreground: #8a2be2; + --hover-border-color: #8a2be2; + --hover-foreground: #8a2be2; + --icon-color: #8a2be2; + --icon-color-hover: #8a2be2; + &:hover { --hover-background: #8a2be2; --hover-border-color: #6a1bb1; --hover-foreground: #fff; --icon-color-hover: #fff; } +} + +.cancel-button { + --foreground: #1275c4; + --hover-foreground: #1275c4; + &:hover { --hover-background: #dbeeff; --hover-foreground: #063b68; } +} + +.add-button { + --background: #4caf50; + --foreground: #000; + --hover-background: #4caf50; + --hover-foreground: #000; + --icon-color: #000; + --icon-color-hover: #000; + --border-radius: 999px; + &:hover { --hover-background: #257a2b; --hover-foreground: #fff; --icon-color-hover: #fff; } +} diff --git a/src/app/data-entries/button/button-styling/button-styling.component.ts b/src/app/data-entries/button/button-styling/button-styling.component.ts new file mode 100644 index 0000000000..eb66365452 --- /dev/null +++ b/src/app/data-entries/button/button-styling/button-styling.component.ts @@ -0,0 +1,12 @@ +import { Component, ViewEncapsulation } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-styling', + encapsulation: ViewEncapsulation.None, + styleUrls: ['./button-styling.component.scss'], + templateUrl: './button-styling.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonStylingComponent { } diff --git a/src/app/data-entries/button/button-styling/layout.scss b/src/app/data-entries/button/button-styling/layout.scss new file mode 100644 index 0000000000..a77566283c --- /dev/null +++ b/src/app/data-entries/button/button-styling/layout.scss @@ -0,0 +1,41 @@ +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/button/button-component" as button; +@use "igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"; + +.bootstrap-theme { + ::ng-deep { + @include button( + $flat: flat-button-theme($schema: $light-bootstrap-schema), + $contained: contained-button-theme($schema: $light-bootstrap-schema), + $outlined: outlined-button-theme($schema: $light-bootstrap-schema), + $fab: fab-button-theme($schema: $light-bootstrap-schema) + ); + @include button.component(); + } +} + +.button-row button.confirm-button, +.button-row button.send-button, +.button-row button.cancel-button { + height: 40px; + min-height: 40px; + width: 90%; +} + +.button-grid { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + gap: 1.5rem; + padding: 1rem; +} + +.button-row { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + align-items: center; + justify-items: center; + gap: 3rem; +} diff --git a/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.html b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.html new file mode 100644 index 0000000000..0a6427ed84 --- /dev/null +++ b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.html @@ -0,0 +1,14 @@ +
+
+ + + + +
+
diff --git a/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.scss b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.scss new file mode 100644 index 0000000000..f0ca253bc3 --- /dev/null +++ b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.scss @@ -0,0 +1,6 @@ +@use "layout.scss"; + +.confirm-button { --hover-background: #3730a3; --hover-foreground: #fff; } +.send-button { --hover-background: #db2777; --hover-border-color: #be185d; --hover-foreground: #fff; --icon-color-hover: #fff; } +.cancel-button { --hover-background: #fef3c7; --hover-foreground: #78350f; } +.add-button { --hover-background: #0f766e; --hover-foreground: #fff; --icon-color-hover: #fff; } diff --git a/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.ts b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.ts new file mode 100644 index 0000000000..70ea8e811c --- /dev/null +++ b/src/app/data-entries/button/button-tailwind-styling/button-tailwind-styling.component.ts @@ -0,0 +1,12 @@ +import { Component, ViewEncapsulation } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-button-tailwind-styling', + encapsulation: ViewEncapsulation.None, + styleUrls: ['./button-tailwind-styling.component.scss'], + templateUrl: './button-tailwind-styling.component.html', + imports: [IgxButtonDirective, IgxIconComponent] +}) +export class ButtonTailwindStylingComponent { } diff --git a/src/app/data-entries/button/button-tailwind-styling/layout.scss b/src/app/data-entries/button/button-tailwind-styling/layout.scss new file mode 100644 index 0000000000..df3c97ac6d --- /dev/null +++ b/src/app/data-entries/button/button-tailwind-styling/layout.scss @@ -0,0 +1,56 @@ +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/button/button-component" as button; +@use "igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"; + +:host { + ::ng-deep { + @include button( + $flat: flat-button-theme($schema: $light-bootstrap-schema), + $contained: contained-button-theme($schema: $light-bootstrap-schema), + $outlined: outlined-button-theme($schema: $light-bootstrap-schema), + $fab: fab-button-theme($schema: $light-bootstrap-schema) + ); + @include button.component(); + } +} + +.button-row button.confirm-button, +.button-row button.send-button, +.button-row button.cancel-button { + height: 40px; + min-height: 40px; + width: 90%; +} + +.confirm-button { + --background: #4338ca; + --foreground: #fff; + --hover-background: #4338ca; + --hover-foreground: #fff; +} + +.send-button { + --background: transparent; + --border-color: #db2777; + --foreground: #db2777; + --hover-border-color: #db2777; + --hover-foreground: #db2777; + --icon-color: #db2777; + --icon-color-hover: #db2777; +} + +.cancel-button { + --foreground: #b45309; + --hover-foreground: #b45309; +} + +.add-button { + --background: #14b8a6; + --foreground: #000; + --hover-background: #14b8a6; + --hover-foreground: #000; + --icon-color: #fff; + --icon-color-hover: #fff; + --border-radius: 9999px; + background-color: #14b8a6; +} diff --git a/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.html b/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.html index 4bf378781a..e4d6a8727e 100644 --- a/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.html +++ b/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.html @@ -1,6 +1,6 @@ -
+
@for (alignment of alignments; track alignment.value) { -
+
{{ alignment.label }} @for (city of cities; track city) { @@ -9,4 +9,4 @@
} -
+ diff --git a/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.scss b/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.scss index d8f1c12333..a91d9b616d 100644 --- a/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-alignment/button-group-alignment.component.scss @@ -1,35 +1,36 @@ -.button-group-alignment { - display: flex; - align-items: flex-start; - justify-content: center; - gap: 60px; - padding: 24px; +@use 'igniteui-theming' as *; + +:host { + display: grid; + place-items: center; + height: 100vh; } -.button-group-alignment-item { +.sample-layout { display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - gap: 16px; + gap: rem(32px); + align-items: start; + justify-content: center; + flex-wrap: wrap; } -.button-group-alignment-item igx-buttongroup { - width: 240px; +.sample-inner-layout { + display: grid; + gap: rem(8px); + align-items: start; } -.button-group-alignment-item:first-child igx-buttongroup { - width: 320px; +igx-buttongroup { + min-width: rem(280px); } -.button-group-alignment-item span { - width: 100%; - text-align: center; - color: #556c86; +span { + color: var(--ig-gray-600); font-family: "Aktiv Grotesk", sans-serif; - font-size: 13px; + font-size: rem(13px); font-weight: 400; - font-style: normal; - line-height: 20px; - letter-spacing: 0.3px; + line-height: rem(20px); + letter-spacing: rem(0.3px); + margin: rem(8px); + text-align: center; } diff --git a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.html b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.html index 6c27c58e2a..03fc4ff1ff 100644 --- a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.html +++ b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.html @@ -1,3 +1 @@ -
- -
+ diff --git a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.scss b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.scss index 157e28c3ca..134b02ca04 100644 --- a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.scss @@ -1,11 +1,11 @@ -.button-group-custom-toggle { - display: flex; - justify-content: center; - align-items: center; - min-height: 7rem; +@use 'igniteui-theming' as *; + +:host { + display: grid; + place-items: center; + height: 100vh; } igx-buttongroup { - display: inline-block; - width: 300px; + inline-size: rem(180px); } diff --git a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.ts b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.ts index d6038eab52..4c6fe4a227 100644 --- a/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.ts +++ b/src/app/data-entries/buttonGroup/button-group-custom-toggle/button-group-custom-toggle.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxButtonGroupComponent, IButtonGroupButton } from 'igniteui-angular/button-group'; interface IButton { ripple?: string; @@ -11,14 +11,14 @@ interface IButton { icon?: string; } -class CustomToggle { - private ripple: string; - private label: string; - private disabled: boolean; - private togglable: boolean; - private selected: boolean; - private color: string; - private icon: string; +class CustomToggle implements IButtonGroupButton { + label: string; + icon?: string; + ripple?: string; + selected?: boolean; + disabled?: boolean; + togglable?: boolean; + color?: string; constructor(obj?: IButton) { this.ripple = obj.ripple || 'gray'; diff --git a/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.html b/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.html index 49b20d26bf..21bcea7b66 100644 --- a/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.html +++ b/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.html @@ -1,28 +1,31 @@ -
-
+
+
@for (state of states; track state) { {{ getLabel(state) }} } -
+ @for (row of rows; track row.label) { -
+
{{ row.label }} @for (state of states; track state) { - - - +
+ {{ getLabel(state) }} + + + +
} -
+ }
diff --git a/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.scss b/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.scss index c78233443a..3619484b4a 100644 --- a/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-interaction-states/button-group-interaction-states.component.scss @@ -1,73 +1,119 @@ -.button-group-interaction-states { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - gap: 20px; - padding: 20px; +@use "igniteui-theming/sass/typography" as *; + +:host { + container-type: inline-size; + display: grid; + grid-template-columns: minmax(0, 1fr); + align-content: center; + height: 100vh; +} + +.states-matrix { + display: grid; + grid-template-columns: auto repeat(3, minmax(rem(124px), 1fr)); + gap: rem(16px); + inline-size: 100%; + max-inline-size: rem(680px); + margin-inline: auto; } -.button-group-interaction-states-row { +.states-row { display: grid; - grid-template-columns: 120px 164px 164px 164px; + grid-column: 1 / -1; + grid-template-columns: subgrid; align-items: center; - gap: 16px; } -.button-group-interaction-states .row-label, -.button-group-interaction-states .column-label { - color: #556c86; +.row-label, +.column-label, +.cell-label { + color: var(--ig-gray-600); font-family: "Aktiv Grotesk", sans-serif; - font-size: 13px; + font-size: rem(13px); font-weight: 400; - font-style: normal; - line-height: 20px; - letter-spacing: 0.3px; + line-height: rem(20px); + letter-spacing: rem(0.3px); } -.button-group-interaction-states .column-label { +.column-label, +.cell-label { text-align: center; } -.button-group-interaction-states igx-buttongroup { - width: 164px; +.cell-label { + display: none; +} + +.state-cell { + display: grid; + gap: rem(4px); +} + +igx-icon { + --ig-icon-size: #{rem(16px)}; } -.button-group-interaction-states button { - width: 100%; - gap: 4px; +@container (width < 34rem) { + .states-matrix { + grid-template-columns: minmax(0, 1fr); + } + + .states-row { + grid-template-columns: repeat(auto-fit, minmax(rem(150px), 1fr)); + } + + header.states-row { + display: none; + } + + .row-label { + grid-column: 1 / -1; + } + + .cell-label { + display: block; + text-align: start; + margin-block-start: rem(16px); + } + + .state-cell { + margin-inline-end: rem(8px); + } } -.button-group-interaction-states igx-icon { - --ig-icon-size: 16px; +// WARNING START: Demo overrides only. Do not copy to production. +// Forced state classes are used here solely to present all component states visually. +igx-buttongroup{ + pointer-events: none; } -.button-group-interaction-states button.state-hover:not(.state-selected) { +.igx-button-group__item.state-hover:not(.state-selected) { background: var(--item-hover-background); border-color: var(--item-hover-border-color); color: var(--item-hover-text-color); } -.button-group-interaction-states button.state-idle.state-selected { - background: var(--item-active-background); - border-color: var(--item-active-border-color); - color: var(--item-active-text-color); +.igx-button-group__item.state-idle.state-selected { + background: var(--item-selected-background); + border-color: var(--item-selected-border-color); + color: var(--item-selected-text-color); } -.button-group-interaction-states button.state-focused:not(.state-selected) { - background: var(--item-focused-hover-background); - border-color: var(--item-focused-hover-border-color); - color: var(--item-focused-hover-text-color); +.igx-button-group__item.state-focused:not(.state-selected) { + background: var(--item-focused-background); + border-color: var(--item-focused-border-color); + color: var(--item-focused-text-color); } -.button-group-interaction-states button.state-hover.state-selected { - background: var(--item-selected-active-background); - border-color: var(--item-selected-active-border-color); +.igx-button-group__item.state-hover.state-selected { + background: var(--item-selected-hover-background); + border-color: var(--item-selected-hover-border-color); color: var(--item-selected-hover-text-color); } -.button-group-interaction-states button.state-focused.state-selected { - background: var(--item-selected-active-background); - border-color: var(--item-selected-active-border-color); - color: var(--item-focused-hover-text-color); +.igx-button-group__item.state-focused.state-selected { + background: var(--item-selected-focus-background); + border-color: var(--item-selected-hover-border-color); + color: var(--item-selected-text-color); } +// WARNING END diff --git a/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.html b/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.html index f2cee52a01..bc87b51456 100644 --- a/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.html +++ b/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.html @@ -1,10 +1,9 @@ -
+
@for (layout of layouts; track layout.value) { } - @for (layout of layouts; track layout.value) { } -
+ diff --git a/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.scss b/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.scss index fc95cf4014..9b0b34eb79 100644 --- a/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-layout/button-group-layout.component.scss @@ -1,21 +1,20 @@ -.button-group-layout { +@use 'igniteui-theming' as *; + +:host { + display: grid; + place-items: center; + height: 100vh; +} + +.sample-layout { display: flex; - flex-direction: row; align-items: center; justify-content: center; - gap: 80px; - min-height: 5.5rem; + flex-wrap: wrap; + gap: rem(60px); } igx-buttongroup { - display: inline-block; max-width: 400px; -} - -.button-group-layout button { - min-width: 100px; -} - -.button-group-layout igx-icon { - --ig-icon-size: 20px; + min-width: 280px; } diff --git a/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.html b/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.html index e6f995b8d8..ee2f12c634 100644 --- a/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.html +++ b/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.html @@ -1,4 +1,4 @@ -
+
+ diff --git a/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.scss b/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.scss index 128e5f6f92..37cdf83608 100644 --- a/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-overview/button-group-overview.component.scss @@ -1,31 +1,32 @@ -.button-group-overview { - display: flex; - flex-direction: column; - align-items: center; +@use 'igniteui-theming' as *; + +:host { + display: grid; + place-items: center; + height: 100vh; } -igx-buttongroup { - display: block; - width: 280px; - max-width: 100%; +.sample-layout { + display: grid; + width: rem(280px); + gap: rem(8px); } -.album { - margin-top: 8px; - width: 280px; - max-width: 100%; +igx-buttongroup { + max-width: rem(280px); } .album-title { - display: inline-block; - margin-bottom: 8px; - color: #1f89d4; + @include type-style('body-2'); + + margin-block: 0 rem(8px); + color: var(--ig-primary-500); } .album-photos { display: grid; grid-template-columns: repeat(2, 1fr); - gap: 4px; + gap: rem(4px); } .album-photos img { diff --git a/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.html b/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.html index 65ff4542c1..c904dd7fc7 100644 --- a/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.html +++ b/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.html @@ -1,18 +1,16 @@
@for (mode of selectionModes; track mode.value) { -
- {{ mode.label }} - - - - - -
+ {{ mode.label }} + + + + + }
diff --git a/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.scss b/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.scss index 7e52239fa8..5bf42ecfb0 100644 --- a/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-selection/button-group-selection.component.scss @@ -1,30 +1,48 @@ -.selection-samples { - display: flex; - justify-content: center; - flex-direction: column; - align-items: flex-start; - gap: 35px; - padding-left: 48px; +@use 'igniteui-theming' as *; + +:host { + container-type: inline-size; + display: grid; + grid-template-columns: minmax(0, 1fr); + align-content: center; + height: 100vh; } -.selection-sample { - display: flex; +.selection-samples { + display: grid; + grid-template-columns: auto minmax(rem(180px), 1fr); align-items: center; - gap: 30px; + gap: rem(24px) rem(32px); + inline-size: 100%; + max-inline-size: rem(380px); + margin-inline: auto; } -.selection-sample > span { - width: 120px; - text-align: right; - color: #556c86; +.sample-label { + color: var(--ig-gray-600); font-family: "Aktiv Grotesk", sans-serif; - font-size: 13px; + font-size: rem(13px); font-weight: 400; - font-style: normal; - line-height: 20px; - letter-spacing: 0.3px; + line-height: rem(20px); + letter-spacing: rem(0.3px); + text-align: end; } -.selection-sample igx-buttongroup { - width: 200px; +igx-buttongroup { + inline-size: 100%; +} + +@container (width < 22rem) { + .selection-samples { + grid-template-columns: minmax(0, 1fr); + gap: rem(4px); + } + + .sample-label { + text-align: start; + + &:not(:first-of-type) { + margin-block-start: rem(16px); + } + } } diff --git a/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.html b/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.html index 57418c0d59..bfc42db3f3 100644 --- a/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.html +++ b/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.html @@ -1,16 +1,10 @@
@for (size of sizes; track size) { -
- {{ getLabel(size) }} - - @for (city of cities; track city) { - - } - -
+ {{ getLabel(size) }} + + @for (city of cities; track city) { + + } + }
diff --git a/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.scss b/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.scss index 7d9127e015..d1e5c076b0 100644 --- a/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-size/button-group-size.component.scss @@ -1,41 +1,70 @@ -.button-group-size { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: center; - gap: 32px; - padding: 13px; - padding-left: 3rem; +@use 'igniteui-theming' as *; + +:host { + container-type: inline-size; + display: grid; + grid-template-columns: minmax(0, 1fr); + place-items: center; + height: 100vh; } -.button-group-size-item { - display: flex; - flex-direction: row; +.button-group-size { + display: grid; + grid-template-columns: auto minmax(rem(240px), 1fr); align-items: center; - justify-content: flex-start; - gap: 32px; + gap: rem(24px) rem(32px); + inline-size: 100%; + max-inline-size: rem(480px); + margin-inline: auto; } -.button-group-size-item span { - width: 52px; - text-align: right; - color: #556c86; +.sample-label { + color: var(--ig-gray-600); font-family: "Aktiv Grotesk", sans-serif; - font-size: 13px; + font-size: rem(13px); font-weight: 400; - font-style: normal; - line-height: 20px; - letter-spacing: 0.3px; + line-height: rem(20px); + letter-spacing: rem(0.3px); + text-align: end; } -.button-group-small button { - min-width: 90px; -} +igx-buttongroup { + &:nth-of-type(1n) { + --ig-size: var(--ig-size-small); + + ::ng-deep button.igx-button-group__item { + min-height: rem(32px); + } + } -.button-group-medium button { - min-width: 100px; + &:nth-of-type(2n) { + --ig-size: var(--ig-size-medium); + + ::ng-deep button.igx-button-group__item { + min-height: rem(40px); + } + } + + &:nth-of-type(3n) { + --ig-size: var(--ig-size-large); + + ::ng-deep button.igx-button-group__item { + min-height: rem(48px); + } + } } -.button-group-large button { - min-width: 110px; +@container (width < 22rem) { + .button-group-size { + grid-template-columns: minmax(0, 1fr); + gap: rem(4px); + } + + .sample-label { + text-align: start; + + &:not(:first-of-type) { + margin-block-start: rem(16px); + } + } } diff --git a/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.html b/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.html index 81234c33df..de47bb98db 100644 --- a/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.html +++ b/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.html @@ -1,26 +1,30 @@ -
-
+
+
Enabled Disabled -
+ @for (row of rows; track row.label) { -
+
{{ row.label }} - - - +
+ Enabled + + + +
- - - -
+
+ Disabled + + + +
+ }
diff --git a/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.scss b/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.scss index c823cd9347..813e4e4902 100644 --- a/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-states/button-group-states.component.scss @@ -1,41 +1,86 @@ -.button-group-states { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - gap: 20px; - padding: 20px; +@use 'igniteui-theming' as *; + +:host { + container-type: inline-size; + display: grid; + grid-template-columns: minmax(0, 1fr); + align-content: center; + height: 100vh; +} + +.states-matrix { + --state-columns: 2; + + display: grid; + grid-template-columns: auto repeat(var(--state-columns), minmax(rem(120px), 1fr)); + gap: rem(16px); + inline-size: 100%; + max-inline-size: rem(520px); + margin-inline: auto; } -.button-group-states-row { +.states-row { display: grid; - grid-template-columns: 120px 160px 160px; + grid-column: 1 / -1; + grid-template-columns: subgrid; align-items: center; - gap: 16px; } -.button-group-states .row-label, -.button-group-states .column-label { - color: #556c86; +.row-label, +.column-label, +.cell-label { + color: var(--ig-gray-600); font-family: "Aktiv Grotesk", sans-serif; - font-size: 13px; + font-size: rem(13px); font-weight: 400; - font-style: normal; - line-height: 20px; - letter-spacing: 0.3px; + line-height: rem(20px); + letter-spacing: rem(0.3px); +} + +.column-label, +.cell-label { text-align: center; } -.button-group-states igx-buttongroup { - width: 160px; +.cell-label { + display: none; +} + +.state-cell { + display: grid; + gap: rem(4px); } -.button-group-states button { - width: 100%; +// Too narrow for the matrix: drop the header, let the cells wrap, and move +// each column label into the cell it describes. +@container (width < 24rem) { + .states-matrix { + grid-template-columns: minmax(0, 1fr); + } + + .states-row { + grid-template-columns: repeat(auto-fit, minmax(rem(140px), 1fr)); + column-gap: rem(8px); + } + + header.states-row { + display: none; + } + + .row-label { + grid-column: 1 / -1; + } + + .cell-label { + display: block; + text-align: start; + margin-block-start: rem(16px); + } } -.button-group-states button.state-idle.state-selected { - background: var(--item-active-background); - border-color: var(--item-active-border-color); - color: var(--item-active-text-color); +// WARNING START: Demo overrides only. Do not copy to production. +// Interaction is disabled so the matrix stays a static picture of each state. +igx-buttongroup { + pointer-events: none; } +// WARNING END diff --git a/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.html b/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.html index c59162f0a1..1a47dc7e80 100644 --- a/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.html +++ b/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.html @@ -1,7 +1,5 @@ -
- - @for (layout of layouts; track layout) { - - } - -
+ + @for (layout of layouts; track layout) { + + } + diff --git a/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.scss b/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.scss index 4475acc9d9..34bed7af82 100644 --- a/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-styling/button-group-styling.component.scss @@ -1,7 +1,19 @@ -@use "layout.scss" as *; @use "igniteui-angular/theming" as *; +:host { + display: grid; + place-items: center; + height: 100vh; +} + +igx-buttongroup { + display: inline-block; + width: 100%; + max-width: rem(400px); +} + $custom-button-group: button-group-theme( + $border-radius: 4px, $item-text-color: #4a5a66, $item-background: #cfe8fb, $item-border-color: #4da3e8, diff --git a/src/app/data-entries/buttonGroup/button-group-styling/layout.scss b/src/app/data-entries/buttonGroup/button-group-styling/layout.scss deleted file mode 100644 index 544499adef..0000000000 --- a/src/app/data-entries/buttonGroup/button-group-styling/layout.scss +++ /dev/null @@ -1,13 +0,0 @@ -.button-group-styling { - display: flex; - align-items: center; - justify-content: center; - min-height: 7rem; -} - -igx-buttongroup { - width: 420px; - border: 2px solid #4da3e8; - border-radius: 4px; - overflow: hidden; -} diff --git a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.html b/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.html index 8a1bc14d88..4ea6203b54 100644 --- a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.html +++ b/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.html @@ -1,7 +1,6 @@ -
- - @for (view of views; track view) { - - } - -
+ + @for (view of views; track view) { + + } + diff --git a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.scss b/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.scss index 2c28a26070..f83f399b97 100644 --- a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.scss +++ b/src/app/data-entries/buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component.scss @@ -1,15 +1,13 @@ -@use "layout.scss"; +@use 'igniteui-theming' as *; -.button-group-style { - --item-text-color: #6d28d9; - --item-background: #ffffff; - --item-border-color: #c4b5fd; - --item-hover-text-color: #6d28d9; - --item-hover-background: #fae8ff; - --item-hover-border-color: #c4b5fd; - --item-selected-text-color: #ffffff; - --item-selected-background: #7c3aed; - --item-selected-border-color: #c4b5fd; - --item-selected-hover-text-color: #ffffff; - --item-selected-hover-background: #7c3aed; +:host { + display: grid; + place-items: center; + height: 100vh; +} + +igx-buttongroup { + display: inline-block; + width: 100%; + max-width: rem(400px); } diff --git a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/layout.scss b/src/app/data-entries/buttonGroup/button-group-tailwind-styling/layout.scss deleted file mode 100644 index 4b18df3f16..0000000000 --- a/src/app/data-entries/buttonGroup/button-group-tailwind-styling/layout.scss +++ /dev/null @@ -1,16 +0,0 @@ -.button-group-tailwind-styling { - display: flex; - align-items: center; - justify-content: center; - min-height: 7rem; - width: 100%; - padding: 1.5rem; - box-sizing: border-box; - background: #f5f3ff; -} - -.button-group-tailwind-styling igx-buttongroup { - width: 420px; - max-width: 100%; - overflow: hidden; -} diff --git a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.html b/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.html deleted file mode 100644 index 34d38c8158..0000000000 --- a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.scss b/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.ts b/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.ts deleted file mode 100644 index c3542a0796..0000000000 --- a/src/app/data-entries/buttons/buttons-disabled-sample/buttons-disabled-sample.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-disabled-sample', - styleUrls: ['./buttons-disabled-sample.scss'], - templateUrl: './buttons-disabled-sample.html', - imports: [IgxButtonDirective] -}) -export class ButtonsDisabledComponent { } diff --git a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.html b/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.html deleted file mode 100644 index 853533d488..0000000000 --- a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.html +++ /dev/null @@ -1,27 +0,0 @@ -
-
- -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
diff --git a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.scss b/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.scss deleted file mode 100644 index 38b1bb22b2..0000000000 --- a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.scss +++ /dev/null @@ -1,15 +0,0 @@ -.buttons-sample { - display: flex; - flex-flow: row wrap; -} - -.button-sample { - display: flex; - flex: 1 0 20%; - align-items: center; - justify-content: space-evenly; -} - -.density-chooser { - margin-bottom: 24px; -} diff --git a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.ts b/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.ts deleted file mode 100644 index 841a908270..0000000000 --- a/src/app/data-entries/buttons/buttons-display-density/buttons-display-density.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Component, HostBinding, OnInit } from '@angular/core'; -import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; -import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; -import { IgxIconComponent } from 'igniteui-angular/icon'; - -@Component({ - selector: 'app-buttons-display-density', - styleUrls: ['./buttons-display-density.component.scss'], - templateUrl: './buttons-display-density.component.html', - imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxRippleDirective, IgxIconComponent] -}) -export class ButtonsDisplayDensityComponent implements OnInit { - public size = 'large'; - public sizes; - - public ngOnInit(): void { - this.sizes = [ - { label: 'large', selected: this.size === 'large', togglable: true }, - { label: 'medium', selected: this.size === 'medium', togglable: true }, - { label: 'small', selected: this.size === 'small', togglable: true } - ]; - } - - @HostBinding('style.--ig-size') - protected get sizeStyle() { - return `var(--ig-size-${this.size})`; - } - - public selectSize(event) { - this.size = this.sizes[event.index].label; - } -} diff --git a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.html b/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.html deleted file mode 100644 index 0c93305128..0000000000 --- a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.html +++ /dev/null @@ -1,22 +0,0 @@ -
-
-
-
- -
-
- -
-
- -
-
- -
-
-
-
diff --git a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.scss b/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.scss deleted file mode 100644 index 81efc9eb5e..0000000000 --- a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.scss +++ /dev/null @@ -1,44 +0,0 @@ -@use '../../../../variables' as *; - -$flatBtn: flat-button-theme( - $border-radius: .5 -); - -$containedBtn: contained-button-theme( - $border-radius: 30px -); - -$fabBtn: fab-button-theme( - $border-radius: 10% -); - -$iconBtn: flat-icon-button-theme( - $border-radius: 12px -); - -.flat { - @include tokens($flatBtn); -} - -.contained { - @include tokens($containedBtn); -} - -.fab { - @include tokens($fabBtn); -} - -.icon { - @include tokens($iconBtn); -} - -.buttons-sample { - display: flex; -} - -.buttons-sample_item { - display: flex; - align-items: center; - justify-content: center; - flex: 1; -} diff --git a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.ts b/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.ts deleted file mode 100644 index c791699b35..0000000000 --- a/src/app/data-entries/buttons/buttons-roundness-sample/buttons-roundness-sample.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective, IgxIconButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; -import { IgxIconComponent } from 'igniteui-angular/icon'; - -@Component({ - selector: 'app-buttons-roundness-sample', - styleUrls: ['./buttons-roundness-sample.scss'], - templateUrl: './buttons-roundness-sample.html', - imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent, IgxIconButtonDirective] -}) -export class ButtonsRoundnessComponent {} diff --git a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.html b/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.html deleted file mode 100644 index 2a08fc960d..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.html +++ /dev/null @@ -1,11 +0,0 @@ -
-
- -
-
- -
-
- -
-
diff --git a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.scss b/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.scss deleted file mode 100644 index 9d1157d397..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -.wrapper { - display: flex; - flex-flow: row wrap; -} - -.button-sample { - display: flex; - flex-flow: row wrap; - justify-content: center; - align-items: center; - flex: 1 0 30%; - margin: 16px 0; -} diff --git a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.ts b/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.ts deleted file mode 100644 index 6e81376588..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-1/buttons-sample-1.component.ts +++ /dev/null @@ -1,11 +0,0 @@ - -import { Component, OnInit } from '@angular/core'; -import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-1', - styleUrls: ['./buttons-sample-1.component.scss'], - templateUrl: './buttons-sample-1.component.html', - imports: [IgxButtonDirective, IgxRippleDirective] -}) -export class ButtonsSample1Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.html b/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.html deleted file mode 100644 index a0a5a22826..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.scss b/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.ts b/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.ts deleted file mode 100644 index 048e47f634..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-2/buttons-sample-2.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-2', - styleUrls: ['./buttons-sample-2.component.scss'], - templateUrl: './buttons-sample-2.component.html', - imports: [IgxButtonDirective] -}) -export class ButtonsSample2Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.html b/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.html deleted file mode 100644 index dbd51e8aa4..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.scss b/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.ts b/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.ts deleted file mode 100644 index 95c52d74d6..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-3/buttons-sample-3.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-3', - styleUrls: ['./buttons-sample-3.component.scss'], - templateUrl: './buttons-sample-3.component.html', - imports: [IgxButtonDirective, IgxRippleDirective] -}) -export class ButtonsSample3Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.html b/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.html deleted file mode 100644 index ea82ea38fe..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.html +++ /dev/null @@ -1 +0,0 @@ -Span diff --git a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.scss b/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.ts b/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.ts deleted file mode 100644 index e0aa368980..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-4/buttons-sample-4.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-4', - styleUrls: ['./buttons-sample-4.component.scss'], - templateUrl: './buttons-sample-4.component.html', - imports: [IgxButtonDirective, IgxRippleDirective] -}) -export class ButtonsSample4Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.html b/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.html deleted file mode 100644 index a05ed23958..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.scss b/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.ts b/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.ts deleted file mode 100644 index ea471e6e36..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-5/buttons-sample-5.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-5', - styleUrls: ['./buttons-sample-5.component.scss'], - templateUrl: './buttons-sample-5.component.html', - imports: [IgxButtonDirective] -}) -export class ButtonsSample5Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.html b/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.html deleted file mode 100644 index 8c8f119053..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.html +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.scss b/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.scss deleted file mode 100644 index 03448c1a67..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-6/buttons-sample-6.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 1rem; -} diff --git a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.html b/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.html deleted file mode 100644 index 39863f9e05..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.scss b/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.ts b/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.ts deleted file mode 100644 index 532edeff95..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-7/buttons-sample-7.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxIconButtonDirective } from 'igniteui-angular/directives'; -import { IgxIconComponent } from 'igniteui-angular/icon'; - -@Component({ - selector: 'app-buttons-sample-7', - styleUrls: ['./buttons-sample-7.component.scss'], - templateUrl: './buttons-sample-7.component.html', - imports: [IgxIconButtonDirective, IgxIconComponent] -}) -export class ButtonsSample7Component { } diff --git a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.html b/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.html deleted file mode 100644 index ec9a161264..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.scss b/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.scss deleted file mode 100644 index 932b31c68c..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.btn { - margin: 8px; -} diff --git a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.ts b/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.ts deleted file mode 100644 index 77b080c3a4..0000000000 --- a/src/app/data-entries/buttons/buttons-sample-8/buttons-sample-8.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-sample-8', - styleUrls: ['./buttons-sample-8.component.scss'], - templateUrl: './buttons-sample-8.component.html', - imports: [IgxButtonDirective] -}) -export class ButtonsSample8Component { } diff --git a/src/app/data-entries/buttons/buttons-style/buttons-style.component.html b/src/app/data-entries/buttons/buttons-style/buttons-style.component.html deleted file mode 100644 index 8eee79e1d3..0000000000 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.html +++ /dev/null @@ -1,22 +0,0 @@ -@for (item of range; let i = $index; track i) { -
-
- -
-
- -
-
- -
-
- -
-
- -
- -
-} \ No newline at end of file diff --git a/src/app/data-entries/buttons/buttons-style/buttons-style.component.scss b/src/app/data-entries/buttons/buttons-style/buttons-style.component.scss deleted file mode 100644 index 67df53853d..0000000000 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.scss +++ /dev/null @@ -1,241 +0,0 @@ -@use "layout.scss"; -@use "igniteui-angular/theming" as *; -@use "sass:map"; - -// CSS variables approach - -$list: ( - "sample-1": ( - "primary": #000, - "secondary": rgba(0, 0, 0, 0.75), - "active": rgba(0, 0, 0, 0.95), - "focus": #fff, - "hover": #4096ff, - "foreground": rgba(0, 0, 0, 0.88), - "border": #d9d9d9, - "active-foreground": #0958d9, - "flat-foreground": #69b1ff, - "flat-background": rgba(0, 0, 0, 0.04), - "flat-active": rgba(0, 0, 0, 0.15), - "flat-hover": rgba(0, 0, 0, 0.06), - ), - "sample-2": ( - "primary": #1677ff, - "secondary": #4096ff, - "active": #0958d9, - "focus": #fff, - "flat-background": #e6f4ff, - "flat-hover": #bae0ff, - "flat-active": #91caff, - ), - "sample-3": ( - "primary": #ff4d4f, - "secondary": #ff7875, - "active": #d9363e, - "focus": #fff, - "flat-background": #fff2f0, - "flat-hover": #ffdfdc, - "flat-active": #ffccc7, - ), - "sample-4": ( - "primary": #eb2f96, - "secondary": #f759ab, - "active": #c41d7f, - "focus": #fff, - "flat-background": #fff0f6, - "flat-hover": #ffd6e7, - "flat-active": #ffadd2, - ), - "sample-5": ( - "primary": #722ed1, - "secondary": #9254de, - "active": #531dab, - "focus": #fff, - "flat-background": #f9f0ff, - "flat-hover": #efdbff, - "flat-active": #d3adf7, - ), - "sample-6": ( - "primary": #13c2c2, - "secondary": #36cfc9, - "active": #08979c, - "focus": #fff, - "flat-background": #e6fffb, - "flat-hover": #b5f5ec, - "flat-active": #b5f5ec, - ), -); - -@each $variant, $style in $list { - .buttons-#{$variant} [igxbutton="contained"] { - --background: #{map-get($style, "primary")}; - --hover-background: #{map-get($style, "secondary")}; - --active-background: #{map-get($style, "active")}; - --focus-visible-background: #{map-get($style, "primary")}; - --focus-visible-foreground: #{map-get($style, "focus")}; - --focus-hover-background: #{map-get($style, "secondary")}; - --focus-hover-foreground: #{map-get($style, "focus")}; - --focus-background: #{map-get($style, "active")}; - } - - @if $variant == "sample-1" { - .buttons-#{$variant} [igxbutton="outlined"] { - --foreground: #{map-get($style, "foreground")}; - --border-color: #{map-get($style, "border")}; - --hover-foreground: #{map-get($style, "hover")}; - --hover-border-color: #{map-get($style, "hover")}; - --active-foreground: #{map-get($style, "active-foreground")}; - --active-border-color: #{map-get($style, "active-foreground")}; - --focus-hover-background: #{map-get($style, "focus")}; - --focus-hover-foreground: #{map-get($style, "hover")}; - --focus-background: #{map-get($style, "focus")}; - --focus-foreground: #{map-get($style, "active-foreground")}; - --focus-visible-border-color: #{map-get($style, "border")}; - } - - .buttons-#{$variant} [igxbutton="flat"] { - --foreground: #{map-get($style, "foreground")}; - --active-foreground: #{map-get($style, "foreground")}; - } - - .buttons-#{$variant} .filled [igxbutton="flat"] { - --background: #{map-get($style, "flat-background")}; - --hover-background: #{map-get($style, "flat-hover")}; - --focus-visible-background: #{map-get($style, "flat-background")}; - } - - .buttons-#{$variant} .filled [igxbutton="flat"], - .buttons-#{$variant} .text [igxbutton="flat"] { - --hover-foreground: #{map-get($style, "foreground")}; - --focus-hover-background: #{map-get($style, "flat-hover")}; - --focus-background: #{map-get($style, "flat-active")}; - --focus-foreground: #{map-get($style, "foreground")}; - --focus-hover-foreground: #{map-get($style, "foreground")}; - --active-background: #{map-get($style, "flat-active")}; - } - - .buttons-#{$variant} .text [igxbutton="flat"] { - --hover-background: #{map-get($style, "flat-background")}; - } - - .buttons-#{$variant} .link [igxbutton="flat"] { - --hover-foreground: #{map-get($style, "flat-foreground")}; - --active-foreground: #{map-get($style, "active-foreground")}; - } - } - - @else { - .buttons-#{$variant} [igxbutton="outlined"] { - --foreground: #{map-get($style, "primary")}; - --border-color: #{map-get($style, "primary")}; - --hover-foreground: #{map-get($style, "secondary")}; - --hover-border-color: #{map-get($style, "secondary")}; - --active-foreground: #{map-get($style, "active")}; - --active-border-color: #{map-get($style, "active")}; - --focus-hover-background: #{map-get($style, "focus")}; - --focus-hover-foreground: #{map-get($style, "secondary")}; - --focus-background: #{map-get($style, "focus")}; - --focus-foreground: #{map-get($style, "active")}; - --focus-visible-border-color: #{map-get($style, "primary")}; - } - - .buttons-#{$variant} .filled [igxbutton="flat"] { - --background: #{map-get($style, "flat-background")}; - --hover-background: #{map-get($style, "flat-hover")}; - --hover-foreground: #{map-get($style, "primary")}; - --active-foreground: #{map-get($style, "primary")}; - --focus-visible-background: #{map-get($style, "flat-background")}; - --focus-hover-foreground: #{map-get($style, "primary")}; - --focus-foreground: #{map-get($style, "primary")}; - } - - .buttons-#{$variant} .filled [igxbutton="flat"], - .buttons-#{$variant} .text [igxbutton="flat"] { - --active-background: #{map-get($style, "flat-active")}; - } - - .buttons-#{$variant} .text [igxbutton="flat"], - .buttons-#{$variant} .link [igxbutton="flat"] { - --hover-foreground: #{map-get($style, "secondary")}; - --active-foreground: #{map-get($style, "active")}; - --focus-hover-foreground: #{map-get($style, "secondary")}; - --focus-foreground: #{map-get($style, "active")}; - } - - .buttons-#{$variant} [igxbutton="flat"] { - --foreground: #{map-get($style, "primary")}; - --focus-hover-background: #{map-get($style, "flat-hover")}; - --focus-background: #{map-get($style, "flat-active")}; - } - - .buttons-#{$variant} .text [igxbutton="flat"] { - --hover-background: #{map-get($style, "flat-background")}; - } - } - - .buttons-#{$variant} [igxbutton="flat"], - .buttons-#{$variant} [igxbutton="outlined"] { - --focus-visible-foreground: #{map-get($style, "primary")}; - } - - .buttons-#{$variant} [igxbutton="outlined"], - .buttons-#{$variant} .text [igxbutton="flat"], - .buttons-#{$variant} .link [igxbutton="flat"] { - --focus-visible-background: transparent; - } -} - -.button-sample [igxbutton="contained"] { - --foreground: #fff; - --hover-foreground: #fff; - --active-foreground: #fff; -} - -.button-sample [igxbutton="outlined"] { - --background: transparent; - --hover-background: transparent; - --active-background: transparent; -} - -// Sass theme approach - -// $custom-contained-theme: contained-button-theme( -// $background: #f9f0ff, -// $foreground: #722ed1, -// $hover-background: #efdbff, -// $hover-foreground: #9254de, -// $active-foreground: #531dab, -// $active-background: #dfc2fa, -// $focus-visible-background: #d3adf7 -// ); - -// $custom-outlined-theme: outlined-button-theme( -// $background: #fff2f0, -// $foreground: #ff4d4f, -// $border-color: #ff4d4f, -// $hover-background: #ffdfdc, -// $hover-foreground: #ff7875, -// $hover-border-color: #ff7875, -// $focus-visible-background: #ffccc7, -// $focus-visible-foreground: #d9363e, -// $focus-border-color: #d9363e -// ); - -// $custom-flat-theme: flat-button-theme( -// $background: #e6fffb, -// $foreground: #13c2c2, -// $hover-background: #b5f5ec, -// $hover-foreground: #36cfc9, -// $active-foreground: #08979c, -// $focus-visible-background: #b5f5ec, -// $focus-visible-foreground: #08979c -// ); - -// .button-sample { -// @include tokens($custom-contained-theme); -// @include tokens($custom-outlined-theme); -// } - -// .button-sample.filled { -// @include tokens($custom-flat-theme); -// } diff --git a/src/app/data-entries/buttons/buttons-style/buttons-style.component.ts b/src/app/data-entries/buttons/buttons-style/buttons-style.component.ts deleted file mode 100644 index ce5d497395..0000000000 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; -import { THEME_TOKEN, ThemeToken } from 'igniteui-angular/core'; - -@Component({ - selector: 'app-buttons-style', - styleUrls: ['./buttons-style.component.scss'], - templateUrl: './buttons-style.component.html', - imports: [IgxButtonDirective], - providers: [{provide: THEME_TOKEN, useFactory: () => new ThemeToken('bootstrap')}] -}) -export class ButtonsStyleComponent { - range = Array(6); -} diff --git a/src/app/data-entries/buttons/buttons-style/layout.scss b/src/app/data-entries/buttons/buttons-style/layout.scss deleted file mode 100644 index 43cf337fa2..0000000000 --- a/src/app/data-entries/buttons/buttons-style/layout.scss +++ /dev/null @@ -1,47 +0,0 @@ -@use "igniteui-angular/theming" as *; -@use "igniteui-angular/lib/core/styles/components/button/button-component" as button; -@use 'sass:map'; - -:host { - ::ng-deep { - @include button($flat: flat-button-theme($schema: $light-bootstrap-schema), - $contained: contained-button-theme($schema: $light-bootstrap-schema), - $outlined: outlined-button-theme($schema: $light-bootstrap-schema), - $fab: fab-button-theme($schema: $light-bootstrap-schema)); - @include button.component(); - } -} - -[class^=buttons-sample] { - display: flex; - margin: 1rem rem(8px) rem(8px) 1rem; -} - -.button-sample { - margin-right: 1rem; -} - -.dashed button{ - border-style: dashed; -} - -[class^="buttons-sample"]:hover .link button { - background: none; -} - -[igxbutton] { - --ig-button-font-weight: 400; - --ig-button-text-transform: capitalize; - min-height: rem(24px); - outline: rem(1px) solid #fff; -} - -.button-sample button { - --ig-size: var(--ig-size-medium); - padding: 0px rem(7px); - min-width: unset; -} - -.button-sample .igx-button { - --ig-font-family: 'alibaba-sans', sans-serif; -} \ No newline at end of file diff --git a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.html b/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.html deleted file mode 100644 index 51cc42daa2..0000000000 --- a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
- -
-
- -
-
- -
-
- -
-
diff --git a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.scss b/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.scss deleted file mode 100644 index a60d456faa..0000000000 --- a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.scss +++ /dev/null @@ -1 +0,0 @@ -@use "layout.scss"; diff --git a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.ts b/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.ts deleted file mode 100644 index 2bbd669b48..0000000000 --- a/src/app/data-entries/buttons/buttons-tailwind-style/buttons-tailwind-style.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxButtonDirective } from 'igniteui-angular/directives'; - -@Component({ - selector: 'app-buttons-tailwind-style', - styleUrls: ['./buttons-tailwind-style.component.scss'], - templateUrl: './buttons-tailwind-style.component.html', - imports: [IgxButtonDirective] -}) -export class ButtonsTailwindStyleComponent {} diff --git a/src/app/data-entries/buttons/buttons-tailwind-style/layout.scss b/src/app/data-entries/buttons/buttons-tailwind-style/layout.scss deleted file mode 100644 index 36396d2d00..0000000000 --- a/src/app/data-entries/buttons/buttons-tailwind-style/layout.scss +++ /dev/null @@ -1,9 +0,0 @@ -.buttons-sample { - display: flex; - margin: 8px; -} - -.button-sample { - display: flex; - margin-right: 16px; -} \ No newline at end of file diff --git a/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.html b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.html new file mode 100644 index 0000000000..0cbca8c1c2 --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.html @@ -0,0 +1,23 @@ +
+ + @for (group of groups; track group.title) { + + {{ group.title }} + + @for (item of group.items; track item.label) { + + + {{ item.label }} + + + + } + } + + + +
diff --git a/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.scss b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.scss new file mode 100644 index 0000000000..08d2d6a02c --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.scss @@ -0,0 +1,116 @@ +:host { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.shopping-list { + position: relative; + display: flex; + flex-direction: column; + box-sizing: border-box; + gap: 1rem; + width: 22.5rem; + height: 24.3125rem; + padding: 1rem 0; + overflow: hidden; + border-radius: 0.25rem; + background: var(--ig-surface-100); + box-shadow: 0 0.0625rem 0.25rem rgb(0 0 0 / 16%); +} + +/* Bootstrap draws its controls a size bigger than the other themes do, and at + the large size styles.scss asks the page for, the rows stop fitting the + card. Only Bootstrap steps down. */ +@container style(--ig-theme: bootstrap) { + .shopping-list { + --ig-size: var(--ig-size-medium); + } +} + +.list { + background: transparent; + border: none; + gap: 0.25rem; + overflow: hidden; +} + +/* The header keeps the theme's own overline typography; only the inset that + lines it up with the rows below is the design's. */ +.group-header { + padding: 0 1rem; + background: transparent; +} + +.shopping-item + .group-header { + margin-top: 0.75rem; +} + +.group-title { + color: var(--ig-secondary-500); +} + +.shopping-item { + background: transparent; + border-bottom: none; + --border-color: transparent; + --border-width: 0; +} + +/* The row's own padding and gap sit on the item's content wrapper. */ +.shopping-item ::ng-deep .igx-list-item__content { + padding: 0 1rem; + gap: 0.5rem; + background: transparent; +} + +.shopping-item:hover, +.shopping-item:focus-within { + background: transparent; + box-shadow: none; +} + +.shopping-item:hover ::ng-deep .igx-list-item__content, +.shopping-item:focus-within ::ng-deep .igx-list-item__content { + background: transparent; + box-shadow: none; +} + +.shopping-item ::ng-deep .igx-list-item__thumbnail { + margin-inline-start: 0.125rem; +} + +.shopping-item igx-checkbox { + --label-margin: 1.125rem; +} + +.shopping-item-checked, +.shopping-item-checked:hover, +.shopping-item-checked:focus-within { + background: var(--ig-gray-100); + box-shadow: none; +} + +.shopping-item-checked ::ng-deep .igx-list-item__content, +.shopping-item-checked:hover ::ng-deep .igx-list-item__content, +.shopping-item-checked:focus-within ::ng-deep .igx-list-item__content { + background: var(--ig-gray-100); +} + +.item-menu { + color: var(--ig-gray-700); +} + +.item-menu igx-icon { + font-size: 1.5rem; +} + +.add-item { + --ig-size: var(--ig-size-large); + --ig-fab-button-border-radius: 50%; + position: absolute; + inset-inline-end: 1rem; + inset-block-end: 1rem; +} diff --git a/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.ts b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.ts new file mode 100644 index 0000000000..75287da672 --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-overview/checkbox-overview.component.ts @@ -0,0 +1,53 @@ +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { IgxButtonDirective, IgxIconButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxListActionDirective, IgxListComponent, IgxListItemComponent, IgxListThumbnailDirective } from 'igniteui-angular/list'; + +interface ShoppingItem { + label: string; + checked: boolean; +} + +interface ShoppingGroup { + title: string; + items: ShoppingItem[]; +} + +@Component({ + selector: 'app-checkbox-overview', + styleUrls: ['./checkbox-overview.component.scss'], + templateUrl: './checkbox-overview.component.html', + imports: [ + FormsModule, + IgxCheckboxComponent, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListActionDirective, + IgxIconButtonDirective, + IgxButtonDirective, + IgxIconComponent + ] +}) +export class CheckboxOverviewComponent { + public groups: ShoppingGroup[] = [ + { + title: 'Grocery store', + items: [ + { label: 'Bread', checked: false }, + { label: 'Milk 4l', checked: false }, + { label: 'Eggs 1 pack', checked: true } + ] + }, + { + title: 'Fruit and vegetable shop', + items: [ + { label: 'Strawberries', checked: false }, + { label: 'Lemons', checked: false }, + { label: 'Single Line Item', checked: true } + ] + } + ]; +} diff --git a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.html b/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.html deleted file mode 100644 index 37ea059ef6..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - Simple checkbox - diff --git a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.ts b/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.ts deleted file mode 100644 index 57bc770cbe..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-1/checkbox-sample-1.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; - -@Component({ - selector: 'app-checkbox-sample-1', - styleUrls: ['./checkbox-sample-1.component.scss'], - templateUrl: './checkbox-sample-1.component.html', - imports: [IgxCheckboxComponent] -}) -export class CheckboxSample1Component { } diff --git a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.html b/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.html deleted file mode 100644 index c0a2fbe075..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.html +++ /dev/null @@ -1,6 +0,0 @@ -@for (task of tasks; track task) { - - {{ task.description }} - -} - diff --git a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.scss b/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.scss deleted file mode 100644 index 01aef9d947..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.scss +++ /dev/null @@ -1,9 +0,0 @@ -:host { - display: flex; - flex-flow: column nowrap; - padding: 16px; -} - -igx-checkbox { - margin-top: 16px; -} diff --git a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.ts b/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.ts deleted file mode 100644 index 780fbd7013..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-2/checkbox-sample-2.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component } from '@angular/core'; - -import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; - -@Component({ - selector: 'app-checkbox-sample-2', - styleUrls: ['./checkbox-sample-2.component.scss'], - templateUrl: './checkbox-sample-2.component.html', - imports: [IgxCheckboxComponent] -}) -export class CheckboxSample2Component { - public tasks = [ - { done: true, description: 'Research' }, - { done: true, description: 'Implement' }, - { done: false, description: 'Test' } - ]; -} diff --git a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.html b/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.html deleted file mode 100644 index e9bc179833..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.html +++ /dev/null @@ -1,13 +0,0 @@ - - All done - -@for (task of tasks; track task) { - - {{ task.description }} - -} diff --git a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.scss b/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.scss deleted file mode 100644 index 16c5cb6b06..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -:host { - display: flex; - flex-flow: column nowrap; - padding: 16px; -} - -igx-checkbox { - margin-top: 16px; -} - -igx-checkbox.tasks { - padding-left: 10px; -} diff --git a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.ts b/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.ts deleted file mode 100644 index 0ebf0cb53e..0000000000 --- a/src/app/data-entries/checkbox/checkbox-sample-3/checkbox-sample-3.component.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; -import { FormsModule } from '@angular/forms'; - - -@Component({ - selector: 'app-checkbox-sample-3', - styleUrls: ['./checkbox-sample-3.component.scss'], - templateUrl: './checkbox-sample-3.component.html', - imports: [IgxCheckboxComponent, FormsModule] -}) -export class CheckboxSample3Component { - public tasks = [ - { done: true, description: 'Research' }, - { done: true, description: 'Implement' }, - { done: false, description: 'Test' } - ]; - - public get masterCheckbox() { - return this.tasks.reduce( - (acc, curr, idx, arr) => { - acc.checked = acc.checked && curr.done; - acc.done = curr.done ? acc.done + 1 : acc.done; - acc.indeterminate = acc.done === arr.length ? false : !!acc.done; - - return acc; - }, - { - checked: true, - done: 0, - indeterminate: false - } - ); - } - - public toggleAll() { - if (this.masterCheckbox.checked) { - for (const task of this.tasks) { - task.done = false; - } - } else { - for (const task of this.tasks) { - task.done = true; - } - } - } -} diff --git a/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.html b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.html new file mode 100644 index 0000000000..ae3890ced0 --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.html @@ -0,0 +1,27 @@ + +
+
+ Indeterminate + +
+
+ On + +
+
+ Off + +
+
+ Disabled + +
+
+ Invalid + +
+
+ Required + +
+
diff --git a/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.scss b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.scss new file mode 100644 index 0000000000..e1368ef8d6 --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.scss @@ -0,0 +1,43 @@ +:host { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.states { + display: flex; + align-items: flex-end; + gap: 4.5rem; +} + +.state { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; +} + +/* the checkboxes are display-only, so they don't offer a pointer */ +.state igx-checkbox { + display: block; + width: 1rem; + height: 1rem; + cursor: default; +} + +.state igx-checkbox ::ng-deep .igx-checkbox__composite-wrapper { + width: 1rem; + height: 1rem; + padding: 0; +} + +.state-label { + font-family: "Aktiv Grotesk", sans-serif; + font-size: 14px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-600); +} diff --git a/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.ts b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.ts new file mode 100644 index 0000000000..6f99af6476 --- /dev/null +++ b/src/app/data-entries/checkbox/checkbox-states/checkbox-states.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; + +@Component({ + selector: 'app-checkbox-states', + styleUrls: ['./checkbox-states.component.scss'], + templateUrl: './checkbox-states.component.html', + imports: [IgxCheckboxComponent] +}) +export class CheckboxStatesComponent { } diff --git a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.html b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.html index 67b225595e..b749729fb4 100644 --- a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.html +++ b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.html @@ -1,3 +1,29 @@ - - Styled checkbox - +
+

Team members

+ + + Select all + + + + @for (member of members; track member.email) { + + + {{ member.name }} + {{ member.email }} + + + } + + + +
diff --git a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.scss b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.scss index 656193ef8d..e5ec9c7744 100644 --- a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.scss +++ b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.scss @@ -1,39 +1,167 @@ -@use "sass:map"; -@use "igniteui-angular/theming" as *; +@use "sass:meta"; +@import url("https://use.typekit.net/bng2zgw.css"); +@include meta.load-css("igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"); -:host { - --ig-font-family: Arial, Helvetica, sans-serif; - --ig-subtitle-1-font-size: #{rem(14px)}; +app-checkbox-styling { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.team-card { + /* The design's own palette and typeface. They are set here instead of + coming from the theme, so the sample keeps its custom look in every theme. */ + --team-surface: #fff; + --team-primary: #0176ff; + --team-gray-100: #f3f6fa; + --team-gray-200: #e5ebf3; + --team-gray-400: #a9b8cc; + --team-gray-500: #7d91ab; + --team-gray-600: #556c86; + --team-gray-700: #344b65; + --team-gray-900: #00142b; + /* aktiv-grotesk is the kit's family name. */ + --ig-font-family: aktiv-grotesk, sans-serif; + + --ig-checkbox-empty-color: var(--team-gray-400); + --ig-checkbox-empty-color-hover: var(--team-gray-400); + --ig-checkbox-fill-color: var(--team-primary); + --ig-checkbox-fill-color-hover: var(--team-primary); + --ig-checkbox-tick-color: #fff; + --ig-checkbox-tick-color-hover: #fff; + + display: flex; + flex-direction: column; + box-sizing: border-box; + width: 26.3125rem; + padding: 0.5rem 0; + border: 1px solid var(--team-gray-200); + border-radius: 0.75rem; + background: var(--team-surface); + font-family: var(--ig-font-family); +} + +.team-title { + display: flex; + align-items: center; + height: 2rem; + margin: 0; + padding: 0 1rem; + color: var(--team-gray-500); + font-family: var(--ig-body-1-font-family, var(--ig-font-family)); + font-size: var(--ig-body-1-font-size); + font-weight: var(--ig-body-1-font-weight); + line-height: var(--ig-body-1-line-height); + letter-spacing: var(--ig-body-1-letter-spacing); + text-transform: var(--ig-body-1-text-transform); +} + +.select-all { + --ig-checkbox-empty-color: var(--team-gray-500); + --ig-checkbox-empty-color-hover: var(--team-gray-500); + --ig-checkbox-label-color: var(--team-gray-600); + --ig-checkbox-label-color-hover: var(--team-gray-600); + + box-sizing: border-box; + width: 100%; + justify-content: space-between; + padding: 0.5rem 1rem; +} + +.select-all .igx-checkbox__label--before { + margin-inline-start: 0; + font-size: 1rem; + font-weight: 600; + line-height: 1.5rem; + letter-spacing: 0.15px; +} + +/* A 24px slot around the 20px box, as in the design. */ +.select-all .igx-checkbox__composite-wrapper, +.member-check .igx-checkbox__composite-wrapper { + margin: 0.125rem; +} + +.members { + background: transparent; + border: none; + overflow: hidden; +} + +.member { + background: transparent; + border-bottom: none; + --border-color: transparent; + --border-width: 0; +} +/* The row's own padding and gap sit on the item's content wrapper. */ +.member .igx-list-item__content { + gap: 1rem; + padding: 0.5rem 1rem; + background: transparent; +} + +.member:hover, +.member:focus-within { + background: transparent; + box-shadow: none; +} + +.member:hover .igx-list-item__content, +.member:focus-within .igx-list-item__content { + background: transparent; + box-shadow: none; +} + +.member-selected, +.member-selected:hover, +.member-selected:focus-within { + background: var(--team-gray-100); +} + +.member-selected .igx-list-item__content, +.member-selected:hover .igx-list-item__content, +.member-selected:focus-within .igx-list-item__content { + background: var(--team-gray-100); +} + +.member igx-avatar { + --ig-size: var(--ig-size-small); +} + +.member .member-name { display: block; - padding: rem(18px) 0 0 rem(18px); -} - -// CSS variables approach -.igx-checkbox { - --tick-color: black; - --tick-color-hover: black; - --tick-width: 4; - --fill-color: orange; - --fill-color-hover: oklch(from var(--fill-color) calc(l * 0.9) c h); - --label-color: black; - --empty-color: orange; - --border-width: #{rem(3px)}; - --border-radius: #{rem(3px)}; -} - -// Sass theme approach -// $custom-checkbox-theme: checkbox-theme( -// $tick-color: black, -// $tick-color-hover: black, -// $tick-width: 4, -// $fill-color: orange, -// $fill-color-hover: oklch(from var(--fill-color) calc(l * 0.9) c h), -// $label-color: black, -// $empty-color: orange, -// $border-radius: rem(3px), -// ); -// -// :host ::ng-deep { -// @include tokens($custom-checkbox-theme); -// } + color: var(--team-gray-900); + font-size: 0.875rem; + font-weight: 600; + line-height: 1.125rem; +} + +.member .member-email { + display: block; + color: var(--team-gray-700); + font-size: 0.75rem; + line-height: 1rem; + letter-spacing: 0.4px; +} + +.continue-button { + align-self: flex-end; + margin: 1rem 1rem 0; + min-width: auto; + width: 5.25rem; + min-height: 1.875rem; + height: 1.875rem; + padding: 0 0.75rem; + border-color: var(--team-primary); + background: var(--team-primary); + color: #fff; + font-size: 0.875rem; + font-weight: 500; + line-height: 1.375rem; + letter-spacing: 0.1px; + text-transform: none; +} diff --git a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.ts b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.ts index 34adc68489..ffb600e5be 100644 --- a/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.ts +++ b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.ts @@ -1,13 +1,52 @@ -import { Component } from '@angular/core'; +import { Component, ViewEncapsulation } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; -import { THEME_TOKEN, ThemeToken } from 'igniteui-angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxListActionDirective, IgxListComponent, IgxListItemComponent, IgxListLineSubTitleDirective, IgxListLineTitleDirective, IgxListThumbnailDirective } from 'igniteui-angular/list'; + +interface TeamMember { + name: string; + email: string; + avatar: string; + selected: boolean; +} @Component({ - selector: 'app-checkbox-styling', - styleUrls: ['./checkbox-styling.component.scss'], - templateUrl: './checkbox-styling.component.html', - providers: [{ provide: THEME_TOKEN, useFactory: () => new ThemeToken('fluent') }], - imports: [IgxCheckboxComponent] + selector: 'app-checkbox-styling', + encapsulation: ViewEncapsulation.None, + styleUrls: ['./checkbox-styling.component.scss'], + templateUrl: './checkbox-styling.component.html', + imports: [ + FormsModule, + IgxCheckboxComponent, + IgxAvatarComponent, + IgxListComponent, + IgxListItemComponent, + IgxListThumbnailDirective, + IgxListLineTitleDirective, + IgxListLineSubTitleDirective, + IgxListActionDirective, + IgxButtonDirective + ] }) export class CheckboxStylingComponent { + public members: TeamMember[] = [ + { name: 'Emily Potter', email: 'emily@team.com', avatar: 'https://dl.infragistics.com/x/img/avatars/avatar-profile-06.png', selected: false }, + { name: 'Alex Lima', email: 'alex@team.com', avatar: 'https://dl.infragistics.com/x/img/avatars/avatar-profile-05.png', selected: true }, + { name: 'Mateo García', email: 'mateo@team.com', avatar: 'https://dl.infragistics.com/x/img/avatars/avatar-profile-07.png', selected: false }, + { name: 'Kate Roberts', email: 'kate@team.com', avatar: 'https://dl.infragistics.com/x/img/avatars/avatar-profile-08.png', selected: false } + ]; + + public get allSelected(): boolean { + return this.members.every((member) => member.selected); + } + + public get someSelected(): boolean { + return this.members.some((member) => member.selected); + } + + public toggleAll(checked: boolean): void { + this.members.forEach((member) => member.selected = checked); + } } diff --git a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.html b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.html index d427737911..9d0f5b3fad 100644 --- a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.html +++ b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.html @@ -1,3 +1,26 @@ - - Styled checkbox - +
+ + @for (section of sections; track section.title) { + + + + {{ section.title }} + + + +
+ @for (option of section.options; track option.label) { + + {{ option.label }} + + } +
+
+
+ } +
+
diff --git a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.scss b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.scss index e69de29bb2..ce444be31c 100644 --- a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.scss +++ b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.scss @@ -0,0 +1,31 @@ +@use "sass:meta"; +@import url("https://use.typekit.net/bng2zgw.css"); +@include meta.load-css("igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"); + +app-checkbox-tailwind-styling { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +/* The design's 44px header: an 8px inset around the title's 28px box. */ +igx-expansion-panel-header .igx-expansion-panel__header-inner { + padding: 0.5rem 1rem; +} + +/* The body's own inset is the theme's, so it is set here instead: 6px, which + the option's 10px of padding completes into the header's 16px. */ +igx-expansion-panel-body { + padding: 0 0.375rem 0.5rem; +} + +/* A 40px row in every theme. The padding sits on the checkbox itself rather + than on the box, so the padding a theme adds around the box for its ripple + can no longer stretch the row. */ +.filter-option { + --label-margin: 0.75rem; + + padding: 0.5rem 0.625rem; +} diff --git a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.ts b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.ts index e492210351..1540c59e11 100644 --- a/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.ts +++ b/src/app/data-entries/checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component.ts @@ -1,10 +1,64 @@ -import { Component } from '@angular/core'; +import { Component, ViewEncapsulation } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; + +interface FilterOption { + label: string; + checked: boolean; +} + +interface FilterSection { + title: string; + collapsed: boolean; + options: FilterOption[]; +} @Component({ selector: 'app-checkbox-tailwind-styling', + encapsulation: ViewEncapsulation.None, styleUrls: ['./checkbox-tailwind-styling.component.scss'], templateUrl: './checkbox-tailwind-styling.component.html', - imports: [IgxCheckboxComponent] + imports: [ + FormsModule, + IgxCheckboxComponent, + IgxAccordionComponent, + IgxExpansionPanelComponent, + IgxExpansionPanelHeaderComponent, + IgxExpansionPanelTitleDirective, + IgxExpansionPanelBodyComponent + ] }) -export class CheckboxTailwindStylingComponent { } +export class CheckboxTailwindStylingComponent { + public sections: FilterSection[] = [ + { + title: 'Brand', + collapsed: false, + options: [ + { label: 'Nike', checked: true }, + { label: 'Roxy', checked: false }, + { label: 'Guess', checked: false } + ] + }, + { + title: 'Color', + collapsed: false, + options: [ + { label: 'Black', checked: false }, + { label: 'White', checked: true }, + { label: 'Gray', checked: false } + ] + }, + { + title: 'Size', + collapsed: false, + options: [ + { label: 'Small', checked: false }, + { label: 'Medium', checked: true }, + { label: 'Large', checked: false }, + { label: 'Extra large', checked: false } + ] + } + ]; +} diff --git a/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.html b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.html new file mode 100644 index 0000000000..ebd41ed541 --- /dev/null +++ b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.scss b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.scss new file mode 100644 index 0000000000..f4cefbb18b --- /dev/null +++ b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.scss @@ -0,0 +1,13 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + padding-block-start: 0.5rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} diff --git a/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.ts b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.ts new file mode 100644 index 0000000000..b9c1958d69 --- /dev/null +++ b/src/app/data-entries/color-picker/alpha/color-picker-alpha.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-alpha', + styleUrls: ['./color-picker-alpha.component.scss'], + templateUrl: './color-picker-alpha.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerAlphaComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/format/color-picker-format.component.html b/src/app/data-entries/color-picker/format/color-picker-format.component.html new file mode 100644 index 0000000000..e0e0fbdc83 --- /dev/null +++ b/src/app/data-entries/color-picker/format/color-picker-format.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/data-entries/color-picker/format/color-picker-format.component.scss b/src/app/data-entries/color-picker/format/color-picker-format.component.scss new file mode 100644 index 0000000000..f4cefbb18b --- /dev/null +++ b/src/app/data-entries/color-picker/format/color-picker-format.component.scss @@ -0,0 +1,13 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + padding-block-start: 0.5rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} diff --git a/src/app/data-entries/color-picker/format/color-picker-format.component.ts b/src/app/data-entries/color-picker/format/color-picker-format.component.ts new file mode 100644 index 0000000000..a867942a14 --- /dev/null +++ b/src/app/data-entries/color-picker/format/color-picker-format.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-format', + styleUrls: ['./color-picker-format.component.scss'], + templateUrl: './color-picker-format.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerFormatComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.html b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.html new file mode 100644 index 0000000000..cc4d57f304 --- /dev/null +++ b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.html @@ -0,0 +1,14 @@ +
+
+ Small + +
+
+ Medium + +
+
+ Large + +
+
diff --git a/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.scss b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.scss new file mode 100644 index 0000000000..b7324cc0e8 --- /dev/null +++ b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.scss @@ -0,0 +1,41 @@ +.small-picker { + --ig-size: var(--ig-size-small); +} + +.medium-picker { + --ig-size: var(--ig-size-medium); +} + +.large-picker { + --ig-size: var(--ig-size-large); +} + +.sample-container { + display: flex; + flex-direction: row; + justify-content: center; + gap: 2rem; + padding-block-start: 0.5rem; + font-family: "Aktiv Grotesk", sans-serif; +} + +span { + display: block; + text-align: center; + margin-block-end: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} + +@media (width < 450px) { + .sample-container { + flex-direction: column; + align-items: center; + } +} diff --git a/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.ts b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.ts new file mode 100644 index 0000000000..04443afb1a --- /dev/null +++ b/src/app/data-entries/color-picker/input-sizes/color-picker-input-sizes.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-input-sizes', + styleUrls: ['./color-picker-input-sizes.component.scss'], + templateUrl: './color-picker-input-sizes.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerInputSizesComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/input/color-picker-input.component.html b/src/app/data-entries/color-picker/input/color-picker-input.component.html new file mode 100644 index 0000000000..67554f034e --- /dev/null +++ b/src/app/data-entries/color-picker/input/color-picker-input.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/data-entries/color-picker/input/color-picker-input.component.scss b/src/app/data-entries/color-picker/input/color-picker-input.component.scss new file mode 100644 index 0000000000..f4cefbb18b --- /dev/null +++ b/src/app/data-entries/color-picker/input/color-picker-input.component.scss @@ -0,0 +1,13 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + padding-block-start: 0.5rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} diff --git a/src/app/data-entries/color-picker/input/color-picker-input.component.ts b/src/app/data-entries/color-picker/input/color-picker-input.component.ts new file mode 100644 index 0000000000..161e442ffe --- /dev/null +++ b/src/app/data-entries/color-picker/input/color-picker-input.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-input', + styleUrls: ['./color-picker-input.component.scss'], + templateUrl: './color-picker-input.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerInputComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/overview/color-picker-overview.component.html b/src/app/data-entries/color-picker/overview/color-picker-overview.component.html new file mode 100644 index 0000000000..befe6c3b9d --- /dev/null +++ b/src/app/data-entries/color-picker/overview/color-picker-overview.component.html @@ -0,0 +1,34 @@ +
+ + +

Choose your interior color

+ + + @for (item of paintTypes; track item) { + {{ item }} + } + + + + @for (item of paintQuantities; track item) { + {{ item }} + } + +
+ + +
+
+ + +
+ + + +
+ +
+
+
diff --git a/src/app/data-entries/color-picker/overview/color-picker-overview.component.scss b/src/app/data-entries/color-picker/overview/color-picker-overview.component.scss new file mode 100644 index 0000000000..9de9d4db02 --- /dev/null +++ b/src/app/data-entries/color-picker/overview/color-picker-overview.component.scss @@ -0,0 +1,80 @@ +.sample-container { + display: flex; + justify-content: center; + align-items: center; + padding-block-start: 0.5rem; +} + +igx-card { + --ig-size: 2; + + width: 22rem; +} + +h2 { + margin: 0 0 1rem; + font-size: 1.25rem; + color: var(--ig-gray-900); +} + +igx-card-content { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +igx-select { + width: 100%; +} + +.color-row { + position: relative; +} + +igc-color-picker { + width: 100%; +} + +igc-color-picker::part(color-picker) { + width: 100%; + grid-template-columns: auto; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-12); +} + +.igx-icon-button { + position: absolute; + right: 0.5rem; + align-self: center; + z-index: 1; +} + +igx-card-actions { + display: flex; + align-items: center; + justify-content: space-between; +} + +.stepper { + display: flex; + gap: 0.375rem; +} + +.stepper .dot { + width: 0.375rem; + height: 0.375rem; + border-radius: 50%; + background: var(--ig-gray-300); +} + +.stepper .dot.active { + background: var(--ig-secondary-500); +} + +::ng-deep { + .igx-card-actions__end { + margin-inline-start: unset; + } +} diff --git a/src/app/data-entries/color-picker/overview/color-picker-overview.component.ts b/src/app/data-entries/color-picker/overview/color-picker-overview.component.ts new file mode 100644 index 0000000000..10d22cf962 --- /dev/null +++ b/src/app/data-entries/color-picker/overview/color-picker-overview.component.ts @@ -0,0 +1,41 @@ +import { Component, ElementRef, ViewChild, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; +import { IgxCardComponent, IgxCardContentDirective, IgxCardActionsComponent } from 'igniteui-angular/card'; +import { IgxButtonDirective, IgxIconButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxSelectComponent, IgxSelectItemComponent } from 'igniteui-angular/select'; +import { IgxLabelDirective } from 'igniteui-angular/input-group'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-overview', + styleUrls: ['./color-picker-overview.component.scss'], + templateUrl: './color-picker-overview.component.html', + imports: [ + FormsModule, + IgxCardComponent, + IgxCardContentDirective, + IgxCardActionsComponent, + IgxButtonDirective, + IgxIconButtonDirective, + IgxIconComponent, + IgxSelectComponent, + IgxSelectItemComponent, + IgxLabelDirective + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerOverviewComponent { + @ViewChild('picker', { static: true }) + public picker!: ElementRef; + + public paintTypes = ['Matte', 'Satin', 'Eggshell', 'Gloss']; + public paintQuantities = ['1 litre', '3 litres', '5 litres', '10 litres']; + + public resetColor(): void { + this.picker.nativeElement.value = ''; + } +} diff --git a/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.html b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.html new file mode 100644 index 0000000000..97f917eef7 --- /dev/null +++ b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.html @@ -0,0 +1,45 @@ +
+ + +
+

Create a label

+ + + + @if (name.touched && name.invalid) { + A label name is required. + } + + + Pick a swatch or select any color value. + A label color is required. + + + +
+ Preview + + {{ labelForm.value.name || 'Label' }} + +
+
+ + +
+
+
+
+
diff --git a/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.scss b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.scss new file mode 100644 index 0000000000..c5b1f896f1 --- /dev/null +++ b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.scss @@ -0,0 +1,62 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + padding-block-start: 0.5rem; +} + +igx-card { + width: 24rem; +} + +form { + display: flex; + flex-direction: column; + gap: 1.25rem; +} + +h2 { + margin: 0; + font-size: 1.25rem; + color: var(--ig-gray-900); +} + +igc-color-picker[mode="input"] { + width: 100%; +} + +igc-color-picker[mode="input"]::part(color-picker) { + width: 100%; + grid-template-columns: auto; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} + +.preview { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.preview-caption { + font-size: 0.875rem; + color: var(--ig-gray-600); +} + +.preview-label { + padding: 0.25rem 0.75rem; + border-radius: 1rem; + font-size: 0.875rem; + font-weight: 600; +} + +.actions { + display: flex; + justify-content: flex-end; + gap: 0.5rem; +} diff --git a/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.ts b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.ts new file mode 100644 index 0000000000..a0a7fea1a1 --- /dev/null +++ b/src/app/data-entries/color-picker/reactive-form/color-picker-reactive-form.component.ts @@ -0,0 +1,57 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; +import { IgcFormControlDirective, IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxCardComponent, IgxCardContentDirective } from 'igniteui-angular/card'; +import { IgxHintDirective, IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective } from 'igniteui-angular/input-group'; + +defineComponents(IgcColorPickerComponent); + +interface LabelForm { + name: FormControl; + color: FormControl; + textColor: FormControl; +} + +const initialValue = { name: '', color: '', textColor: '#000000' }; + +@Component({ + selector: 'app-color-picker-reactive-form', + styleUrls: ['./color-picker-reactive-form.component.scss'], + templateUrl: './color-picker-reactive-form.component.html', + imports: [ + ReactiveFormsModule, + IgcFormControlDirective, + IgxButtonDirective, + IgxCardComponent, + IgxCardContentDirective, + IgxInputGroupComponent, + IgxInputDirective, + IgxLabelDirective, + IgxHintDirective + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerReactiveFormComponent { + public swatches = ['#d32f2f', '#f57c00', '#fbc02d', '#388e3c', '#1976d2', '#7b1fa2', '#455a64']; + + public labelForm = new FormGroup({ + name: new FormControl(initialValue.name, Validators.required), + color: new FormControl(initialValue.color, Validators.required), + textColor: new FormControl(initialValue.textColor) + }); + + public get name() { + return this.labelForm.controls.name; + } + + public get color() { + return this.labelForm.controls.color; + } + + public onReset(form: HTMLFormElement): void { + form.reset(); + this.labelForm.reset(initialValue); + } +} diff --git a/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.html b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.html new file mode 100644 index 0000000000..11a68b6c13 --- /dev/null +++ b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.html @@ -0,0 +1,14 @@ +
+
+ Small + +
+
+ Medium + +
+
+ Large + +
+
diff --git a/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.scss b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.scss new file mode 100644 index 0000000000..b7324cc0e8 --- /dev/null +++ b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.scss @@ -0,0 +1,41 @@ +.small-picker { + --ig-size: var(--ig-size-small); +} + +.medium-picker { + --ig-size: var(--ig-size-medium); +} + +.large-picker { + --ig-size: var(--ig-size-large); +} + +.sample-container { + display: flex; + flex-direction: row; + justify-content: center; + gap: 2rem; + padding-block-start: 0.5rem; + font-family: "Aktiv Grotesk", sans-serif; +} + +span { + display: block; + text-align: center; + margin-block-end: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} + +@media (width < 450px) { + .sample-container { + flex-direction: column; + align-items: center; + } +} diff --git a/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.ts b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.ts new file mode 100644 index 0000000000..9d0a203e94 --- /dev/null +++ b/src/app/data-entries/color-picker/sizes/color-picker-sizes.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-sizes', + styleUrls: ['./color-picker-sizes.component.scss'], + templateUrl: './color-picker-sizes.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerSizesComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/states/color-picker-states.component.html b/src/app/data-entries/color-picker/states/color-picker-states.component.html new file mode 100644 index 0000000000..5ac47a4df9 --- /dev/null +++ b/src/app/data-entries/color-picker/states/color-picker-states.component.html @@ -0,0 +1,14 @@ +
+
+ Default state + +
+
+ Invalid state + +
+
+ Disabled state + +
+
diff --git a/src/app/data-entries/color-picker/states/color-picker-states.component.scss b/src/app/data-entries/color-picker/states/color-picker-states.component.scss new file mode 100644 index 0000000000..a3da2c25bd --- /dev/null +++ b/src/app/data-entries/color-picker/states/color-picker-states.component.scss @@ -0,0 +1,31 @@ +.sample-container { + --ig-size: 2; + + display: flex; + flex-direction: row; + justify-content: center; + gap: 2rem; + padding-block-start: 0.5rem; + font-family: "Aktiv Grotesk", sans-serif; +} + +span { + display: block; + text-align: center; + margin-block-end: 1rem; + color: var(--ig-gray-600); + font-size: 0.875rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} + +@media (width < 450px) { + .sample-container { + flex-direction: column; + align-items: center; + } +} diff --git a/src/app/data-entries/color-picker/states/color-picker-states.component.ts b/src/app/data-entries/color-picker/states/color-picker-states.component.ts new file mode 100644 index 0000000000..1578339f88 --- /dev/null +++ b/src/app/data-entries/color-picker/states/color-picker-states.component.ts @@ -0,0 +1,27 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-states', + styleUrls: ['./color-picker-states.component.scss'], + templateUrl: './color-picker-states.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerStatesComponent implements AfterViewInit { + public invalid = true; + + public onInput(): void { + this.invalid = false; + } + + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/styling/color-picker-styling.component.html b/src/app/data-entries/color-picker/styling/color-picker-styling.component.html new file mode 100644 index 0000000000..29b527c55f --- /dev/null +++ b/src/app/data-entries/color-picker/styling/color-picker-styling.component.html @@ -0,0 +1,57 @@ +
+
+
+ Text +
+ +
+
+
+ Alignment +
+ + + + +
+
+
+ Content +
+ + + +
+
+
+ Charts +
+ +
+
+
+ Colors +
+ +
+
+
+
diff --git a/src/app/data-entries/color-picker/styling/color-picker-styling.component.scss b/src/app/data-entries/color-picker/styling/color-picker-styling.component.scss new file mode 100644 index 0000000000..055ca3c761 --- /dev/null +++ b/src/app/data-entries/color-picker/styling/color-picker-styling.component.scss @@ -0,0 +1,16 @@ +@use "layout.scss"; + +igc-color-picker { + --ig-color-picker-picker-background: #e6f2ff; + --ig-color-picker-picker-border-color: #a9b8cc; + --ig-color-picker-picker-border-radius: 1rem; + --ig-color-picker-picker-elevation: none; +} + +igc-color-picker::part(anchor) { + border: 0.125rem solid #a9b8cc; +} + +igc-color-picker::part(picker-canvas) { + border-radius: 0.25rem; +} diff --git a/src/app/data-entries/color-picker/styling/color-picker-styling.component.ts b/src/app/data-entries/color-picker/styling/color-picker-styling.component.ts new file mode 100644 index 0000000000..43903a85f0 --- /dev/null +++ b/src/app/data-entries/color-picker/styling/color-picker-styling.component.ts @@ -0,0 +1,16 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; +import { IgxIconButtonDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-styling', + styleUrls: ['./color-picker-styling.component.scss'], + templateUrl: './color-picker-styling.component.html', + imports: [IgxIconButtonDirective, IgxIconComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerStylingComponent {} diff --git a/src/app/data-entries/color-picker/styling/layout.scss b/src/app/data-entries/color-picker/styling/layout.scss new file mode 100644 index 0000000000..6a8181ff03 --- /dev/null +++ b/src/app/data-entries/color-picker/styling/layout.scss @@ -0,0 +1,99 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + align-items: center; + padding-block-start: 0.5rem; +} + +.editor-toolbar { + display: flex; + align-items: stretch; + gap: 0.5rem; + padding: 1rem; + border-radius: 1rem; + background: #00142b; + font-family: "Aktiv Grotesk", sans-serif; +} + +.toolbar-group { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; +} + +.toolbar-group-label { + font-size: 0.75rem; + font-weight: 600; + line-height: 1rem; + letter-spacing: 0.009375rem; + color: #d2dbe8; +} + +.toolbar-actions { + border-radius: 0.5rem; + background: #556c86; +} + +[igxIconButton] { + width: fit-content; + height: fit-content; + padding: 0.5rem; + --foreground: #fcfcfc; + --hover-foreground: #fff; +} + +[igxIconButton] igx-icon { + --size: 0.875rem; + width: 1.6em; + height: 1.6em; + align-items: center; + justify-content: center; +} + +.toolbar-group:nth-child(2) { + [igxIconButton]:nth-of-type(2) { + padding-inline: unset; + } + + [igxIconButton]:nth-of-type(3) { + padding-inline-end: unset; + } +} + +.toolbar-group:nth-child(3) [igxIconButton]:nth-of-type(2) { + padding-inline: unset; +} + +igc-color-picker { + --ig-size: var(--ig-size-small); + --ig-input-group-border-color: transparent; + --ig-input-group-hover-border-color: rgb(255 255 255 / 15%); + --ig-input-group-focused-border-color: transparent; + --ig-input-group-border-border-radius: 0.5rem; + --ig-input-group-filled-text-color: #fff; + --ig-input-group-filled-text-hover-color: #fff; + --ig-input-group-focused-text-color: #fff; + --ig-input-group-placeholder-color: #fff; + --ig-input-group-hover-placeholder-color: #fff; + --ig-input-group-focus-placeholder-color: #fff; + + width: 8.75rem; +} + +igc-color-picker::part(picker) { + --ig-input-group-filled-text-color: var(--ig-gray-900); + --ig-input-group-filled-text-hover-color: var(--ig-gray-900); + --ig-input-group-focused-text-color: var(--ig-gray-900); + --ig-input-group-placeholder-color: var(--ig-gray-900); + --ig-input-group-hover-placeholder-color: var(--ig-gray-900); + --ig-input-group-focus-placeholder-color: var(--ig-gray-900); + --ig-input-group-border-color: var(--ig-gray-500); + --ig-input-group-hover-border-color: var(--ig-gray-500); + --ig-input-group-focused-border-color: var(--ig-gray-500); + --ig-input-group-border-border-radius: 0.25rem; + + margin-top: 1.25rem; +} \ No newline at end of file diff --git a/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.html b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.html new file mode 100644 index 0000000000..8408e1d465 --- /dev/null +++ b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.html @@ -0,0 +1,4 @@ +
+ + +
diff --git a/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.scss b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.scss new file mode 100644 index 0000000000..b4ca3f0bb6 --- /dev/null +++ b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.scss @@ -0,0 +1,14 @@ +.sample-container { + --ig-size: 2; + + display: flex; + flex-direction: row; + justify-content: space-between; + padding-block-start: 0.5rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} \ No newline at end of file diff --git a/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.ts b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.ts new file mode 100644 index 0000000000..e2d803fc53 --- /dev/null +++ b/src/app/data-entries/color-picker/swatches/color-picker-swatches.component.ts @@ -0,0 +1,31 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-swatches', + styleUrls: ['./color-picker-swatches.component.scss'], + templateUrl: './color-picker-swatches.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerSwatchesComponent implements AfterViewInit { + public oneLineSwatches = ['#f44336', '#e91e63', '#9c27b0', '#3f51b5', '#2196f3', '#4caf50']; + + public multiLineSwatches = [ + '#f44336', '#e91e63', '#9c27b0', '#3f51b5', '#2196f3', '#4caf50', '#ffeb3b', '#ff9800', '#795548', '#607d8b', '#ffffff', '#000000', '#0000ff', '#00ff00', '#ff00ff', '#00ffff', '#ff0000', '#ffff00', '#ff00ff', '#00ffff', '#c0c0c0', '#808080', '#800000', '#808000' + ]; + + @ViewChild('colorPicker1', { static: true }) + colorPicker1!: ElementRef; + + @ViewChild('colorPicker2', { static: true }) + colorPicker2!: ElementRef; + + ngAfterViewInit() { + this.colorPicker1.nativeElement.toggle(); + this.colorPicker2.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.html b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.html new file mode 100644 index 0000000000..85e1cf2920 --- /dev/null +++ b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.html @@ -0,0 +1,62 @@ +
+
+
+
+

Theme Editor

+

Use the pickers to style the card.

+
+ +
+
+
+ + Card surface color + +
+
+ + Body & heading color + +
+
+ + Button & tag color + +
+
+ + Card edge color + +
+
+ + Upgrade to unlock + +
+
+ + + Design +

Color Picker in Practice

+

Pick colors above to see them applied live across every element of this card.

+
+ + +
+
+
+
+
diff --git a/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.scss b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.scss new file mode 100644 index 0000000000..b76c19079b --- /dev/null +++ b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.scss @@ -0,0 +1,176 @@ +igc-color-picker::part(copy), +igc-color-picker::part(eye-dropper) { + --foreground: #c6451b; +} + +igc-color-picker::part(picker) { + --ig-input-group-border-color: #f95924; + --ig-input-group-hover-border-color: #f95924; + --ig-input-group-focused-border-color: #f95924; + + margin-top: 1.25rem; +} + +igc-color-picker::part(buttons) { + gap: 0rem; +} + +igc-color-picker { + --ig-color-picker-picker-elevation: none; +} + +.sample-container { + --ig-size: 2; + + display: flex; + height: fit-content; + max-width: 55rem; + margin-inline: auto; + padding-block-start: 0.5rem; +} + +.theme-editor { + --ig-font-family: "Aktiv Grotesk", sans-serif; + + width: 100%; + border-radius: 0.75rem; + border: 0.063rem solid; + padding: 1.5rem; + border-color: var(--ig-gray-200); + background: var(--ig-surface-500); +} + +.theme-editor-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 1rem; + border-bottom: 0.063rem solid; + border-color: var(--ig-gray-200); +} + +.theme-editor-header h2 { + font-size: 1rem; + line-height: 1.5rem; + font-weight: 600; + margin: 0; + color: var(--ig-gray-900); + letter-spacing: 0.009rem; +} + +.theme-editor-header p { + font-size: 0.875rem; + line-height: 1.25rem; + margin: 0.125rem 0 0; + color: var(--ig-gray-600); +} + +.theme-editor-header igx-icon { + --size: 1.5rem; +} + +.swatches { + display: flex; + flex-wrap: wrap; + gap: 1.5rem; + padding: 1.5rem 1rem 1rem; +} + +.swatch-item { + display: flex; + align-items: center; + gap: 0.5rem; + max-width: 8.5rem; + width: 100%; +} + +.swatch-item igc-color-picker { + --ig-color-picker-anchor-border-radius: 0.375rem; + --ig-color-picker-label-color: var(--ig-gray-900); +} + +.swatch-item igc-color-picker::part(label) { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +igc-color-picker::part(anchor) { + --anchor-border-radius: 0.25rem; + --anchor-border-color: var(--ig-gray-600); + --swatch-preview-border-color: var(--ig-gray-300); +} + +.swatch-item.disabled igc-color-picker { + --ig-color-picker-label-color-disabled: var(--ig-gray-400); +} + +.swatch-item.disabled .swatch-hint { + color: var(--ig-gray-400); +} + +.swatch-hint { + font-size: 0.75rem; + line-height: 1rem; + color: var(--ig-gray-600); +} + +igx-card { + margin-block-start: 1rem; + border-radius: 0.5rem; + background: var(--preview-bg); + border: 0.063rem solid var(--preview-border); + box-shadow: var(--ig-elevation-4); +} + +.preview-chip { + --ig-size: var(--ig-size-large); + --ig-chip-background: color-mix(in srgb, var(--preview-accent) 25%, transparent); + --ig-chip-hover-background: color-mix(in srgb, var(--preview-accent) 75%, transparent); + --ig-chip-text-color: var(--preview-accent); +} + +.preview-primary, +.preview-secondary { + --ig-size: var(--ig-size-medium); + text-transform: capitalize; +} + +.preview-primary { + --background: var(--preview-accent); + --foreground: var(--preview-bg); + --hover-background: hsl(from var(--preview-accent) h s 40%); +} + +.preview-secondary { + --foreground: var(--preview-accent); + --hover-foreground: hsl(from var(--preview-accent) h s 40%); + --border-color: var(--preview-accent); + --hover-border-color: hsl(from var(--preview-accent) h s 40%); + min-width: unset; +} + +.preview-title, +.preview-text { + color: var(--preview-text); +} + +.preview-title { + font-size: 1rem; + line-height: 1.5rem; + font-weight: 600; + margin: 1rem 0 0.25rem; + letter-spacing: 0.009rem; +} + +.preview-text { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 500; +} + +.preview-actions { + display: flex; + gap: 0.75rem; + margin-top: 1.25rem; +} diff --git a/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.ts b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.ts new file mode 100644 index 0000000000..5223f3be76 --- /dev/null +++ b/src/app/data-entries/color-picker/tailwind-styling/color-picker-tailwind-styling.component.ts @@ -0,0 +1,60 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; +import { IgxCardComponent, IgxCardContentDirective } from 'igniteui-angular/card'; +import { IgxButtonDirective, IgxIconButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxChipComponent } from 'igniteui-angular/chips'; + +defineComponents(IgcColorPickerComponent); + +const defaults = { + background: '#1a314a', + text: '#e5ebf3', + accent: '#f9592a', + border: '#00142b' +}; + +@Component({ + selector: 'app-color-picker-tailwind-styling', + styleUrls: ['./color-picker-tailwind-styling.component.scss'], + templateUrl: './color-picker-tailwind-styling.component.html', + imports: [ + IgxCardComponent, + IgxCardContentDirective, + IgxButtonDirective, + IgxIconButtonDirective, + IgxRippleDirective, + IgxIconComponent, + IgxChipComponent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class ColorPickerTailwindStylingComponent { + public background = defaults.background; + public text = defaults.text; + public accent = defaults.accent; + public border = defaults.border; + + public onBackgroundInput(event: Event): void { + this.background = (event as CustomEvent).detail; + } + + public onTextInput(event: Event): void { + this.text = (event as CustomEvent).detail; + } + + public onAccentInput(event: Event): void { + this.accent = (event as CustomEvent).detail; + } + + public onBorderInput(event: Event): void { + this.border = (event as CustomEvent).detail; + } + + public reset(): void { + this.background = defaults.background; + this.text = defaults.text; + this.accent = defaults.accent; + this.border = defaults.border; + } +} diff --git a/src/app/data-entries/color-picker/value/color-picker-value.component.html b/src/app/data-entries/color-picker/value/color-picker-value.component.html new file mode 100644 index 0000000000..6c4d826eda --- /dev/null +++ b/src/app/data-entries/color-picker/value/color-picker-value.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/app/data-entries/color-picker/value/color-picker-value.component.scss b/src/app/data-entries/color-picker/value/color-picker-value.component.scss new file mode 100644 index 0000000000..3b5129b704 --- /dev/null +++ b/src/app/data-entries/color-picker/value/color-picker-value.component.scss @@ -0,0 +1,17 @@ +.sample-container { + --ig-size: 2; + + display: flex; + justify-content: center; + padding-block-start: 0.5rem; +} + +igc-color-picker::part(picker) { + --picker-elevation: var(--ig-elevation-4); + + margin-top: 0.5rem; +} + +:root { + overflow: auto; +} diff --git a/src/app/data-entries/color-picker/value/color-picker-value.component.ts b/src/app/data-entries/color-picker/value/color-picker-value.component.ts new file mode 100644 index 0000000000..310a701495 --- /dev/null +++ b/src/app/data-entries/color-picker/value/color-picker-value.component.ts @@ -0,0 +1,21 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcColorPickerComponent); + +@Component({ + selector: 'app-color-picker-value', + styleUrls: ['./color-picker-value.component.scss'], + templateUrl: './color-picker-value.component.html', + imports: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class ColorPickerValueComponent implements AfterViewInit { + @ViewChild('colorPicker', { static: true }) + colorPicker!: ElementRef; + + ngAfterViewInit() { + this.colorPicker.nativeElement.toggle(); + } +} diff --git a/src/app/data-entries/data-entries-routes-data.ts b/src/app/data-entries/data-entries-routes-data.ts index 5e710a28e7..c60900ec61 100644 --- a/src/app/data-entries/data-entries-routes-data.ts +++ b/src/app/data-entries/data-entries-routes-data.ts @@ -13,24 +13,33 @@ export const dataEntriesRoutesData = { "button-group-size": { displayName: "Button Group Size", parentName: "Button Group" }, "button-group-styling": { displayName: "Button Group Styling", parentName: "Button Group" }, "button-group-tailwind-styling": { displayName: "Button Group Tailwind Styling", parentName: "Button Group" }, - "buttons-sample-1": { displayName: "Overview", parentName: "Buttons" }, - "buttons-sample-2": { displayName: "Flat Button", parentName: "Buttons" }, - "buttons-sample-3": { displayName: "Button Ripple", parentName: "Buttons" }, - "buttons-sample-4": { displayName: "Span Button", parentName: "Buttons" }, - "buttons-sample-5": { displayName: "Contained Button", parentName: "Buttons" }, - "buttons-sample-6": { displayName: "Floating Action Button", parentName: "Buttons" }, - "buttons-sample-7": { displayName: "Icon Button", parentName: "Buttons" }, - "buttons-sample-8": { displayName: "Outlined Button", parentName: "Buttons" }, - "buttons-disabled-sample": { displayName: "Disabled Button", parentName: "Buttons" }, - "buttons-display-density": { displayName: "Display Density", parentName: "Buttons" }, - "buttons-roundness-sample": { displayName: "Components Roundness", parentName: "Buttons" }, - "buttons-style": { displayName: "Button Style", parentName: "Buttons" }, - "buttons-tailwind-style": { displayName: "Button Tailwind Style", parentName: "Buttons" }, - "checkbox-sample-1": { displayName: "Simple Checkbox", parentName: "Checkbox" }, - "checkbox-sample-2": { displayName: "Multiple Checkboxes", parentName: "Checkbox" }, - "checkbox-sample-3": { displayName: "Indeterminate Checkbox", parentName: "Checkbox" }, + "button-overview": { displayName: "Overview", parentName: "Button" }, + "button-flat": { displayName: "Flat Button", parentName: "Button" }, + "button-interaction-states": { displayName: "Button Interaction States", parentName: "Button" }, + "button-layout": { displayName: "Button Layout", parentName: "Button" }, + "button-contained": { displayName: "Contained Button", parentName: "Button" }, + "button-fab": { displayName: "Floating Action Button", parentName: "Button" }, + "button-states": { displayName: "Button States", parentName: "Button" }, + "button-size": { displayName: "Button Size", parentName: "Button" }, + "button-download": { displayName: "Download Button", parentName: "Button" }, + "button-styling": { displayName: "Button Style", parentName: "Button" }, + "button-tailwind-styling": { displayName: "Button Tailwind Style", parentName: "Button" }, + "checkbox-overview": { displayName: "Checkbox Overview", parentName: "Checkbox" }, + "checkbox-states": { displayName: "Checkbox States", parentName: "Checkbox" }, "checkbox-styling": { displayName: "Checkbox Styling", parentName: "Checkbox" }, "checkbox-tailwind-styling": { displayName: "Checkbox Tailwind Styling", parentName: "Checkbox" }, + "color-picker-overview": { displayName: "Overview", parentName: "Color Picker" }, + "color-picker-value": { displayName: "Value", parentName: "Color Picker" }, + "color-picker-input": { displayName: "Input Mode", parentName: "Color Picker" }, + "color-picker-format": { displayName: "Format", parentName: "Color Picker" }, + "color-picker-alpha": { displayName: "Alpha", parentName: "Color Picker" }, + "color-picker-swatches": { displayName: "Swatches", parentName: "Color Picker" }, + "color-picker-states": { displayName: "States", parentName: "Color Picker" }, + "color-picker-sizes": { displayName: "Sizes", parentName: "Color Picker" }, + "color-picker-input-sizes": { displayName: "Input Sizes", parentName: "Color Picker" }, + "color-picker-styling": { displayName: "Color Picker Styling", parentName: "Color Picker" }, + "color-picker-tailwind-styling": { displayName: "Color Picker Tailwind Styling", parentName: "Color Picker" }, + "color-picker-reactive-form": { displayName: "Color Picker in Reactive Form", parentName: "Color Picker" }, "dropdown-remote": { displayName: "Virtual Dropdown - Remote Data", parentName: "Dropdown" }, "dropdown-virtual": { displayName: "Virtual Dropdown", parentName: "Dropdown" }, "dropdown-menu": { displayName: "Dropdown as Menu", parentName: "Dropdown" }, @@ -69,8 +78,11 @@ export const dataEntriesRoutesData = { "radio-styling-sample": { displayName: "Styling Radio Buttons", parentName: "Radio" }, "radio-tailwind-styling-sample": { displayName: "Tailwind Styling Radio Buttons", parentName: "Radio" }, "rating-form": { displayName: "Rating in Form", parentName: "Rating" }, - "switch-sample-1": { displayName: "Switch Overview", parentName: "Switch" }, - "switch-sample-2": { displayName: "Multiple Switches", parentName: "Switch" }, + "switch-overview": { displayName: "Switch Overview", parentName: "Switch" }, + "switch-enabled": { displayName: "Enabled Switches", parentName: "Switch" }, + "switch-disabled": { displayName: "Disabled Switches", parentName: "Switch" }, + "switch-selected": { displayName: "Selected Switches", parentName: "Switch" }, + "switch-layout": { displayName: "Switch Label Position", parentName: "Switch" }, "switch-styling": { displayName: "Styled Switches", parentName: "Switch" }, "switch-tailwind-styling": { displayName: "Tailwind Styled Switches", parentName: "Switch" }, "select-sample-1": { displayName: "Simple Select", parentName: "Select" }, diff --git a/src/app/data-entries/data-entries.routes.ts b/src/app/data-entries/data-entries.routes.ts index 8bc329cfcc..1219ec653a 100644 --- a/src/app/data-entries/data-entries.routes.ts +++ b/src/app/data-entries/data-entries.routes.ts @@ -11,24 +11,34 @@ import { ButtonGroupSelectionComponent } from './buttonGroup/button-group-select import { ButtonGroupSizeComponent } from './buttonGroup/button-group-size/button-group-size.component'; import { ButtonGroupStylingComponent } from './buttonGroup/button-group-styling/button-group-styling.component'; import { ButtonGroupTailwindStylingComponent } from './buttonGroup/button-group-tailwind-styling/button-group-tailwind-styling.component'; -import { ButtonsDisabledComponent } from './buttons/buttons-disabled-sample/buttons-disabled-sample'; -import { ButtonsDisplayDensityComponent } from './buttons/buttons-display-density/buttons-display-density.component'; -import { ButtonsRoundnessComponent } from './buttons/buttons-roundness-sample/buttons-roundness-sample'; -import { ButtonsSample1Component } from './buttons/buttons-sample-1/buttons-sample-1.component'; -import { ButtonsSample2Component } from './buttons/buttons-sample-2/buttons-sample-2.component'; -import { ButtonsSample3Component } from './buttons/buttons-sample-3/buttons-sample-3.component'; -import { ButtonsSample4Component } from './buttons/buttons-sample-4/buttons-sample-4.component'; -import { ButtonsSample5Component } from './buttons/buttons-sample-5/buttons-sample-5.component'; -import { ButtonsSample6Component } from './buttons/buttons-sample-6/buttons-sample-6.component'; -import { ButtonsSample7Component } from './buttons/buttons-sample-7/buttons-sample-7.component'; -import { ButtonsSample8Component } from './buttons/buttons-sample-8/buttons-sample-8.component'; -import { ButtonsStyleComponent } from './buttons/buttons-style/buttons-style.component'; -import { ButtonsTailwindStyleComponent } from './buttons/buttons-tailwind-style/buttons-tailwind-style.component'; -import { CheckboxSample1Component } from './checkbox/checkbox-sample-1/checkbox-sample-1.component'; -import { CheckboxSample2Component } from './checkbox/checkbox-sample-2/checkbox-sample-2.component'; -import { CheckboxSample3Component } from './checkbox/checkbox-sample-3/checkbox-sample-3.component'; +import { ButtonStatesComponent } from './button/button-states/button-states.component'; +import { ButtonSizeComponent } from './button/button-size/button-size.component'; +import { ButtonDownloadComponent } from './button/button-download/button-download.component'; +import { ButtonOverviewComponent } from './button/button-overview/button-overview.component'; +import { ButtonFlatComponent } from './button/button-flat/button-flat.component'; +import { ButtonInteractionStatesComponent } from './button/button-interaction-states/button-interaction-states.component'; +import { ButtonLayoutComponent } from './button/button-layout/button-layout.component'; +import { ButtonContainedComponent } from './button/button-contained/button-contained.component'; +import { ButtonFabComponent } from './button/button-fab/button-fab.component'; +import { ButtonOutlinedComponent } from './button/button-outlined/button-outlined.component'; +import { ButtonStylingComponent } from './button/button-styling/button-styling.component'; +import { ButtonTailwindStylingComponent } from './button/button-tailwind-styling/button-tailwind-styling.component'; +import { CheckboxOverviewComponent } from './checkbox/checkbox-overview/checkbox-overview.component'; +import { CheckboxStatesComponent } from './checkbox/checkbox-states/checkbox-states.component'; import { CheckboxStylingComponent } from './checkbox/checkbox-styling/checkbox-styling.component'; import { CheckboxTailwindStylingComponent } from './checkbox/checkbox-tailwind-styling/checkbox-tailwind-styling.component'; +import { ColorPickerOverviewComponent } from './color-picker/overview/color-picker-overview.component'; +import { ColorPickerValueComponent } from './color-picker/value/color-picker-value.component'; +import { ColorPickerInputComponent } from './color-picker/input/color-picker-input.component'; +import { ColorPickerFormatComponent } from './color-picker/format/color-picker-format.component'; +import { ColorPickerAlphaComponent } from './color-picker/alpha/color-picker-alpha.component'; +import { ColorPickerSwatchesComponent } from './color-picker/swatches/color-picker-swatches.component'; +import { ColorPickerStatesComponent } from './color-picker/states/color-picker-states.component'; +import { ColorPickerSizesComponent } from './color-picker/sizes/color-picker-sizes.component'; +import { ColorPickerInputSizesComponent } from './color-picker/input-sizes/color-picker-input-sizes.component'; +import { ColorPickerStylingComponent } from './color-picker/styling/color-picker-styling.component'; +import { ColorPickerTailwindStylingComponent } from './color-picker/tailwind-styling/color-picker-tailwind-styling.component'; +import { ColorPickerReactiveFormComponent } from './color-picker/reactive-form/color-picker-reactive-form.component'; import { dataEntriesRoutesData } from './data-entries-routes-data'; import { DropDownRemoteComponent } from './dropdown/drop-down-remote-virtual/drop-down-remote.component'; import { DropDownVirtualComponent } from './dropdown/drop-down-virtual/drop-down-virtual.component'; @@ -67,8 +77,11 @@ import { SelectSample2Component } from './select/select-sample-2/select-sample-2 import { SelectSample4Component } from './select/select-sample-4/select-sample-4.component'; import { SelectStylingComponent } from './select/select-styling/select-styling.component'; import { SelectTailwindStylingComponent } from './select/select-tailwind-styling/select-tailwind-styling.component'; -import { SwitchSample1Component } from './switch/switch-sample-1/switch-sample-1.component'; -import { SwitchSample2Component } from './switch/switch-sample-2/switch-sample-2.component'; +import { SwitchOverviewComponent } from './switch/switch-overview/switch-overview.component'; +import { SwitchEnabledComponent } from './switch/switch-enabled/switch-enabled.component'; +import { SwitchDisabledComponent } from './switch/switch-disabled/switch-disabled.component'; +import { SwitchSelectedComponent } from './switch/switch-selected/switch-selected.component'; +import { SwitchLayoutComponent } from './switch/switch-layout/switch-layout.component'; import { SwitchStylingComponent } from './switch/switch-styling/switch-styling.component'; import { SwitchTailwindStylingComponent } from './switch/switch-tailwind-styling/switch-tailwind-styling.component'; import { RatingInFormComponent } from './rating/rating-form/rating-form.component'; @@ -97,9 +110,9 @@ export const DataEntriesRoutes: Routes = [ path: 'movie' }, { - component: ButtonsDisplayDensityComponent, - data: dataEntriesRoutesData['buttons-display-density'], - path: 'buttons-display-density' + component: ButtonSizeComponent, + data: dataEntriesRoutesData['button-size'], + path: 'button-size' }, { component: ButtonGroupOverviewComponent, @@ -152,79 +165,69 @@ export const DataEntriesRoutes: Routes = [ path: 'button-group-tailwind-styling' }, { - component: ButtonsRoundnessComponent, - data: dataEntriesRoutesData['buttons-roundness-sample'], - path: 'buttons-roundness-sample' + component: ButtonOverviewComponent, + data: dataEntriesRoutesData['button-overview'], + path: 'button-overview' }, { - component: ButtonsSample1Component, - data: dataEntriesRoutesData['buttons-sample-1'], - path: 'buttons-sample-1' + component: ButtonFlatComponent, + data: dataEntriesRoutesData['button-flat'], + path: 'button-flat' }, { - component: ButtonsSample2Component, - data: dataEntriesRoutesData['buttons-sample-2'], - path: 'buttons-sample-2' + component: ButtonInteractionStatesComponent, + data: dataEntriesRoutesData['button-interaction-states'], + path: 'button-interaction-states' }, { - component: ButtonsSample3Component, - data: dataEntriesRoutesData['buttons-sample-3'], - path: 'buttons-sample-3' + component: ButtonLayoutComponent, + data: dataEntriesRoutesData['button-layout'], + path: 'button-layout' }, { - component: ButtonsSample4Component, - data: dataEntriesRoutesData['buttons-sample-4'], - path: 'buttons-sample-4' + component: ButtonContainedComponent, + data: dataEntriesRoutesData['button-contained'], + path: 'button-contained' }, { - component: ButtonsSample5Component, - data: dataEntriesRoutesData['buttons-sample-5'], - path: 'buttons-sample-5' + component: ButtonFabComponent, + data: dataEntriesRoutesData['button-fab'], + path: 'button-fab' }, { - component: ButtonsSample6Component, - data: dataEntriesRoutesData['buttons-sample-6'], - path: 'buttons-sample-6' + component: ButtonOutlinedComponent, + data: dataEntriesRoutesData['button-outlined'], + path: 'button-outlined' }, { - component: ButtonsSample7Component, - data: dataEntriesRoutesData['buttons-sample-7'], - path: 'buttons-sample-7' + component: ButtonStatesComponent, + data: dataEntriesRoutesData['button-states'], + path: 'button-states' }, { - component: ButtonsSample8Component, - data: dataEntriesRoutesData['buttons-sample-8'], - path: 'buttons-sample-8' + component: ButtonDownloadComponent, + data: dataEntriesRoutesData['button-download'], + path: 'button-download' }, { - component: ButtonsDisabledComponent, - data: dataEntriesRoutesData['buttons-disabled-sample'], - path: 'buttons-disabled-sample' + component: ButtonStylingComponent, + data: dataEntriesRoutesData['button-styling'], + path: 'button-styling' }, { - component: ButtonsStyleComponent, - data: dataEntriesRoutesData['buttons-style'], - path: 'buttons-style' + component: ButtonTailwindStylingComponent, + data: dataEntriesRoutesData['button-tailwind-styling'], + path: 'button-tailwind-styling' }, { - component: ButtonsTailwindStyleComponent, - data: dataEntriesRoutesData['buttons-tailwind-style'], - path: 'buttons-tailwind-style' + component: CheckboxOverviewComponent, + data: dataEntriesRoutesData['checkbox-overview'], + path: 'checkbox-overview' }, { - component: CheckboxSample1Component, - data: dataEntriesRoutesData['checkbox-sample-1'], - path: 'checkbox-sample-1' - }, - { - component: CheckboxSample2Component, - data: dataEntriesRoutesData['checkbox-sample-2'], - path: 'checkbox-sample-2' - }, - { - component: CheckboxSample3Component, - data: dataEntriesRoutesData['checkbox-sample-3'], - path: 'checkbox-sample-3' + component: CheckboxStatesComponent, + data: dataEntriesRoutesData['checkbox-states'], + path: 'checkbox-states' }, { component: CheckboxStylingComponent, @@ -236,6 +239,66 @@ export const DataEntriesRoutes: Routes = [ data: dataEntriesRoutesData['checkbox-tailwind-styling'], path: 'checkbox-tailwind-styling' }, + { + component: ColorPickerOverviewComponent, + data: dataEntriesRoutesData['color-picker-overview'], + path: 'color-picker-overview' + }, + { + component: ColorPickerValueComponent, + data: dataEntriesRoutesData['color-picker-value'], + path: 'color-picker-value' + }, + { + component: ColorPickerInputComponent, + data: dataEntriesRoutesData['color-picker-input'], + path: 'color-picker-input' + }, + { + component: ColorPickerFormatComponent, + data: dataEntriesRoutesData['color-picker-format'], + path: 'color-picker-format' + }, + { + component: ColorPickerAlphaComponent, + data: dataEntriesRoutesData['color-picker-alpha'], + path: 'color-picker-alpha' + }, + { + component: ColorPickerSwatchesComponent, + data: dataEntriesRoutesData['color-picker-swatches'], + path: 'color-picker-swatches' + }, + { + component: ColorPickerStatesComponent, + data: dataEntriesRoutesData['color-picker-states'], + path: 'color-picker-states' + }, + { + component: ColorPickerSizesComponent, + data: dataEntriesRoutesData['color-picker-sizes'], + path: 'color-picker-sizes' + }, + { + component: ColorPickerInputSizesComponent, + data: dataEntriesRoutesData['color-picker-input-sizes'], + path: 'color-picker-input-sizes' + }, + { + component: ColorPickerStylingComponent, + data: dataEntriesRoutesData['color-picker-styling'], + path: 'color-picker-styling' + }, + { + component: ColorPickerTailwindStylingComponent, + data: dataEntriesRoutesData['color-picker-tailwind-styling'], + path: 'color-picker-tailwind-styling' + }, + { + component: ColorPickerReactiveFormComponent, + data: dataEntriesRoutesData['color-picker-reactive-form'], + path: 'color-picker-reactive-form' + }, { component: DropdownMenuComponent, data: dataEntriesRoutesData['dropdown-menu'], @@ -427,14 +490,29 @@ export const DataEntriesRoutes: Routes = [ path: 'rating-form' }, { - component: SwitchSample1Component, - data: dataEntriesRoutesData['switch-sample-1'], - path: 'switch-sample-1' + component: SwitchOverviewComponent, + data: dataEntriesRoutesData['switch-overview'], + path: 'switch-overview' + }, + { + component: SwitchEnabledComponent, + data: dataEntriesRoutesData['switch-enabled'], + path: 'switch-enabled' + }, + { + component: SwitchDisabledComponent, + data: dataEntriesRoutesData['switch-disabled'], + path: 'switch-disabled' + }, + { + component: SwitchSelectedComponent, + data: dataEntriesRoutesData['switch-selected'], + path: 'switch-selected' }, { - component: SwitchSample2Component, - data: dataEntriesRoutesData['switch-sample-2'], - path: 'switch-sample-2' + component: SwitchLayoutComponent, + data: dataEntriesRoutesData['switch-layout'], + path: 'switch-layout' }, { component: SwitchStylingComponent, diff --git a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.html b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.html index 326ce80547..a51fc5cce1 100644 --- a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.html +++ b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.html @@ -1,13 +1,16 @@ - + + + + {{ item.ProductName }} + + +
Selected Product: {{ remoteDropDown.selectedItem?.value }} diff --git a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.scss b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.scss index 7e4e00cd9b..7a96deeff0 100644 --- a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.scss +++ b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.scss @@ -1,5 +1,5 @@ +// The virtual scroll host is the scroll container, so it needs a fixed height. .drop-down-virtual-wrapper { - overflow-y: hidden; width: 260px; height: 320px; } diff --git a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.ts b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.ts index 9a2941bfec..8077fe682d 100644 --- a/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.ts +++ b/src/app/data-entries/dropdown/drop-down-remote-virtual/drop-down-remote.component.ts @@ -1,74 +1,65 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, AfterViewInit, inject } from '@angular/core'; -// tslint:disable-next-line:max-line-length -import { IForOfState, IgxButtonDirective, IgxForOfDirective, IgxToggleActionDirective } from 'igniteui-angular/directives'; +import { Component, OnDestroy, OnInit, ViewChild, inject, signal } from '@angular/core'; +import { IgxButtonDirective, IgxToggleActionDirective } from 'igniteui-angular/directives'; import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective } from 'igniteui-angular/drop-down'; import { IgxToastComponent } from 'igniteui-angular/toast'; import { VerticalAlignment } from 'igniteui-angular/core'; -import { Subject, Subscription } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent, VirtualDataWindow, VirtualScrollState } from 'igniteui-angular/virtual-scroll'; +import { Subscription } from 'rxjs'; import { RemoteNWindService } from '../../../services/remoteNwind.service'; -import { AsyncPipe } from '@angular/common'; -// tslint:disable:object-literal-sort-keys +/** Extra records requested on each side of the range the viewport wants. */ +const BUFFER = 10; + @Component({ providers: [RemoteNWindService], selector: 'app-drop-down-remote', templateUrl: './drop-down-remote.component.html', styleUrls: ['./drop-down-remote.component.scss'], - imports: [IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxForOfDirective, IgxDropDownItemComponent, IgxToastComponent, AsyncPipe] + imports: [IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxVirtualScrollComponent, IgxVirtualItemDirective, IgxDropDownItemComponent, IgxToastComponent] }) -export class DropDownRemoteComponent implements OnInit, OnDestroy, AfterViewInit { +export class DropDownRemoteComponent implements OnInit, OnDestroy { private remoteService = inject(RemoteNWindService); - cdr = inject(ChangeDetectorRef); @ViewChild('loadingToast', { read: IgxToastComponent, static: true }) public loadingToast: IgxToastComponent; - @ViewChild(IgxForOfDirective, { read: IgxForOfDirective, static: true }) - public remoteForDir: IgxForOfDirective; @ViewChild('remoteDropDown', { read: IgxDropDownComponent, static: true }) public remoteDropDown: IgxDropDownComponent; - public itemHeight = 48; - public itemsMaxHeight = 320; - public prevRequest: Subscription; - public rData: any; - private destroy$ = new Subject(); + public itemHeight = 40; - public ngAfterViewInit() { - const initialState: IForOfState = { - startIndex: 0, chunkSize: Math.floor(this.itemsMaxHeight / this.itemHeight) + 1 - }; - this.remoteService.getData(initialState, null, (data) => { - this.remoteForDir.totalItemCount = data['@odata.count']; - }); - this.remoteForDir.chunkPreload.pipe(takeUntil(this.destroy$)).subscribe((data) => { - this.dataLoading(data); - }); + /** The loaded page; the list is as long as `totalCount`, so the scrollbar spans every product. */ + public readonly page = signal>({ items: [], startIndex: 0, totalCount: 0 }); + + private pending: Subscription; + + public ngOnInit() { + this.loadPage(0, 2 * BUFFER); } - public dataLoading(evt) { - if (this.prevRequest) { - this.prevRequest.unsubscribe(); + /** `stateChange` reports the range the viewport wants; load a page when the loaded one does not cover it. */ + public onStateChange(state: VirtualScrollState) { + const page = this.page(); + if (state.startIndex >= page.startIndex && state.endIndex < page.startIndex + page.items.length) { + return; } - this.loadingToast.positionSettings.verticalDirection = VerticalAlignment.Middle; - this.loadingToast.autoHide = false; - this.loadingToast.open('Loading Remote Data...'); - this.cdr.detectChanges(); - this.prevRequest = this.remoteService.getData( - evt, - null, - (data) => { - this.remoteForDir.totalItemCount = data['@odata.count']; - this.loadingToast.close(); - this.cdr.detectChanges(); - }); - } - public ngOnInit() { - this.rData = this.remoteService.remoteData; + const startIndex = Math.max(0, state.startIndex - BUFFER); + this.loadPage(startIndex, state.endIndex - startIndex + 1 + BUFFER); } public ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); + this.pending?.unsubscribe(); + } + + private loadPage(startIndex: number, count: number) { + // Cancel the previous request, so a slow response cannot replace a newer page. + this.pending?.unsubscribe(); + this.loadingToast.positionSettings.verticalDirection = VerticalAlignment.Middle; + this.loadingToast.autoHide = false; + this.loadingToast.open('Loading Remote Data...'); + + this.pending = this.remoteService.getData({ startIndex, chunkSize: count }, null, (data) => { + this.page.set({ items: data.value, startIndex, totalCount: data['@odata.count'] }); + this.loadingToast.close(); + }); } } diff --git a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.html b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.html index b1d9861c2b..67ffd36299 100644 --- a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.html +++ b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.html @@ -1,12 +1,11 @@ - + + + + {{ item.name }} + + +
Selected Model: {{ dropdown.selectedItem?.value.name }}
diff --git a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.scss b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.scss index 888c5ba127..bb5418c335 100644 --- a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.scss +++ b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.scss @@ -1,6 +1,6 @@ +// The virtual scroll host is the scroll container, so it needs a fixed height. .drop-down-virtual-wrapper { - overflow: hidden; - max-height: 240px; + height: 240px; width: 180px; } diff --git a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.ts b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.ts index f7efad5d6f..4904b88554 100644 --- a/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.ts +++ b/src/app/data-entries/dropdown/drop-down-virtual/drop-down-virtual.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; -import { IgxButtonDirective, IgxForOfDirective, IgxToggleActionDirective } from 'igniteui-angular/directives'; +import { IgxButtonDirective, IgxToggleActionDirective } from 'igniteui-angular/directives'; import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective } from 'igniteui-angular/drop-down'; +import { IgxVirtualItemDirective, IgxVirtualScrollComponent } from 'igniteui-angular/virtual-scroll'; // tslint:disable:object-literal-sort-keys // tslint:disable-next-line:interface-name @@ -15,12 +16,11 @@ interface DataItem { selector: 'app-drop-down-virtual', templateUrl: './drop-down-virtual.component.html', styleUrls: ['./drop-down-virtual.component.scss'], - imports: [IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxForOfDirective, IgxDropDownItemComponent] + imports: [IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxVirtualScrollComponent, IgxVirtualItemDirective, IgxDropDownItemComponent] }) export class DropDownVirtualComponent { public items: DataItem[]; - public itemHeight = 48; - public itemsMaxHeight = 240; + public itemHeight = 40; constructor() { const itemsCollection: DataItem[] = []; diff --git a/src/app/data-entries/switch/switch-disabled/switch-disabled.component.html b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.html new file mode 100644 index 0000000000..280874ac2c --- /dev/null +++ b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.html @@ -0,0 +1,14 @@ +
+
+ Disabled Checked + + Power + +
+
+ Disabled Unchecked + + Power + +
+
diff --git a/src/app/data-entries/switch/switch-disabled/switch-disabled.component.scss b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.scss new file mode 100644 index 0000000000..28c0265f91 --- /dev/null +++ b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.scss @@ -0,0 +1,30 @@ +:host { + display: flex; + min-block-size: 100%; + box-sizing: border-box; + place-content: center; + place-items: center; + padding: 16px; +} + +.states { + --variant-gap: 60px; + --label-gap: 30px; + + display: flex; + align-items: center; + justify-content: center; + gap: var(--variant-gap); + + .states__variant { + display: flex; + align-items: center; + gap: var(--label-gap); + } + + .states__label { + font: 500 14px / 24px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.1px; + color: var(--ig-gray-600); + } +} diff --git a/src/app/data-entries/switch/switch-disabled/switch-disabled.component.ts b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.ts new file mode 100644 index 0000000000..0dba8b971d --- /dev/null +++ b/src/app/data-entries/switch/switch-disabled/switch-disabled.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-switch-disabled', + styleUrls: ['./switch-disabled.component.scss'], + templateUrl: './switch-disabled.component.html', + imports: [IgxSwitchComponent] +}) +export class SwitchDisabledComponent { } diff --git a/src/app/data-entries/switch/switch-enabled/switch-enabled.component.html b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.html new file mode 100644 index 0000000000..4ca5c510c4 --- /dev/null +++ b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.html @@ -0,0 +1,28 @@ +
+ + Hover + Focused + Focused & Hover + + Enabled / On + + Power + + + Power + + + Power + + + Enabled / Off + + Power + + + Power + + + Power + +
diff --git a/src/app/data-entries/switch/switch-enabled/switch-enabled.component.scss b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.scss new file mode 100644 index 0000000000..d36f357ba4 --- /dev/null +++ b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.scss @@ -0,0 +1,32 @@ +:host { + display: flex; + place-content: center; + place-items: center; + padding: 16px; +} + +.states { + display: grid; + grid-template-columns: repeat(4, auto); + align-items: center; + gap: 32px 24px; + + .states__column, + .states__row { + font: 500 14px / 24px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.1px; + color: var(--ig-gray-600); + } + + .states__column { + text-align: center; + } + + .states__row { + text-align: end; + } + + igx-switch { + justify-self: center; + } +} diff --git a/src/app/data-entries/switch/switch-enabled/switch-enabled.component.ts b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.ts new file mode 100644 index 0000000000..8eaf65933b --- /dev/null +++ b/src/app/data-entries/switch/switch-enabled/switch-enabled.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-switch-enabled', + styleUrls: ['./switch-enabled.component.scss'], + templateUrl: './switch-enabled.component.html', + imports: [IgxSwitchComponent] +}) +export class SwitchEnabledComponent { } diff --git a/src/app/data-entries/switch/switch-layout/switch-layout.component.html b/src/app/data-entries/switch/switch-layout/switch-layout.component.html new file mode 100644 index 0000000000..0458faa19e --- /dev/null +++ b/src/app/data-entries/switch/switch-layout/switch-layout.component.html @@ -0,0 +1,14 @@ +
+
+ Label Before + + Power + +
+
+ Label After + + Power + +
+
diff --git a/src/app/data-entries/switch/switch-layout/switch-layout.component.scss b/src/app/data-entries/switch/switch-layout/switch-layout.component.scss new file mode 100644 index 0000000000..9cb1380aaa --- /dev/null +++ b/src/app/data-entries/switch/switch-layout/switch-layout.component.scss @@ -0,0 +1,31 @@ +:host { + display: flex; + min-block-size: 100%; + box-sizing: border-box; + place-content: center; + place-items: center; + padding: 16px; +} + +.variants { + --variant-gap: 60px; + --label-gap: 30px; + + display: flex; + inline-size: 100%; + align-items: center; + justify-content: center; + gap: var(--variant-gap); + + .variants__item { + display: flex; + align-items: center; + gap: var(--label-gap); + } + + .variants__label { + font: 500 14px / 24px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.1px; + color: var(--ig-gray-600); + } +} diff --git a/src/app/data-entries/switch/switch-layout/switch-layout.component.ts b/src/app/data-entries/switch/switch-layout/switch-layout.component.ts new file mode 100644 index 0000000000..d9bef05a86 --- /dev/null +++ b/src/app/data-entries/switch/switch-layout/switch-layout.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-switch-layout', + styleUrls: ['./switch-layout.component.scss'], + templateUrl: './switch-layout.component.html', + imports: [IgxSwitchComponent] +}) +export class SwitchLayoutComponent { } diff --git a/src/app/data-entries/switch/switch-overview/switch-overview.component.html b/src/app/data-entries/switch/switch-overview/switch-overview.component.html new file mode 100644 index 0000000000..2d0fe64c1b --- /dev/null +++ b/src/app/data-entries/switch/switch-overview/switch-overview.component.html @@ -0,0 +1,27 @@ +
+
Notifications
+
+ + + Push notifications + Deliver alerts to this device + + +
+
+ + + Weekly digest + Summary email every Monday + + +
+
+ + + SMS alerts + Unavailable on your plan + + +
+
diff --git a/src/app/data-entries/switch/switch-overview/switch-overview.component.scss b/src/app/data-entries/switch/switch-overview/switch-overview.component.scss new file mode 100644 index 0000000000..4eb2dd76b2 --- /dev/null +++ b/src/app/data-entries/switch/switch-overview/switch-overview.component.scss @@ -0,0 +1,57 @@ +:host { + display: flex; + place-content: center; + place-items: center; + padding: 16px; +} + +.notifications { + inline-size: 100%; + max-inline-size: 384px; + background: var(--ig-surface-500); + border-radius: 4px; + overflow: hidden; + + .notifications__title { + margin: 0; + padding: 16px; + font: 400 10px / 16px "Titillium Web", sans-serif; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--ig-secondary-500); + } + + .notifications__row { + padding-block: 12px; + padding-inline: 16px; + + igx-switch { + inline-size: 100%; + justify-content: space-between; + gap: 16px; + transform: translateX(-10px); + + ::ng-deep .igx-switch__composite { + transform: translateX(8px); + } + } + } +} + +.option { + display: flex; + flex-direction: column; + gap: 2px; + text-align: start; + white-space: normal; + + .option__label { + font-size: 16px; + color: var(--ig-gray-900); + } + + .option__hint { + font-size: 13px; + color: var(--ig-gray-700); + } +} diff --git a/src/app/data-entries/switch/switch-overview/switch-overview.component.ts b/src/app/data-entries/switch/switch-overview/switch-overview.component.ts new file mode 100644 index 0000000000..88946f53fe --- /dev/null +++ b/src/app/data-entries/switch/switch-overview/switch-overview.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-switch-overview', + styleUrls: ['./switch-overview.component.scss'], + templateUrl: './switch-overview.component.html', + imports: [IgxSwitchComponent] +}) +export class SwitchOverviewComponent { } diff --git a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.html b/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.html deleted file mode 100644 index f6c2ce336f..0000000000 --- a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.html +++ /dev/null @@ -1,3 +0,0 @@ - - Simple switch - diff --git a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.ts b/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.ts deleted file mode 100644 index 906229df20..0000000000 --- a/src/app/data-entries/switch/switch-sample-1/switch-sample-1.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { IgxSwitchComponent } from 'igniteui-angular/switch'; - -@Component({ - selector: 'app-switch-sample-1', - styleUrls: ['./switch-sample-1.component.scss'], - templateUrl: './switch-sample-1.component.html', - imports: [IgxSwitchComponent] -}) -export class SwitchSample1Component { } diff --git a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.html b/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.html deleted file mode 100644 index 82bb5ae9f7..0000000000 --- a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.html +++ /dev/null @@ -1,6 +0,0 @@ -@for (setting of settings; track setting) { - - {{ setting.name }} - -} - diff --git a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.scss b/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.scss deleted file mode 100644 index 7ccd0c810c..0000000000 --- a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.scss +++ /dev/null @@ -1,9 +0,0 @@ -:host { - display: flex; - flex-flow: column nowrap; - padding: 16px; -} - -igx-switch { - margin-top: 24px; -} diff --git a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.ts b/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.ts deleted file mode 100644 index 54c4e0d49a..0000000000 --- a/src/app/data-entries/switch/switch-sample-2/switch-sample-2.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component } from '@angular/core'; - -import { IgxSwitchComponent } from 'igniteui-angular/switch'; - -@Component({ - selector: 'app-switch-sample-2', - styleUrls: ['./switch-sample-2.component.scss'], - templateUrl: './switch-sample-2.component.html', - imports: [IgxSwitchComponent] -}) -export class SwitchSample2Component { - public settings = [ - { name: 'WiFi', state: false}, - { name: 'Bluetooth', state: true}, - { name: 'Device visibility', state: false} - ]; -} diff --git a/src/app/data-entries/switch/switch-selected/switch-selected.component.html b/src/app/data-entries/switch/switch-selected/switch-selected.component.html new file mode 100644 index 0000000000..223f269045 --- /dev/null +++ b/src/app/data-entries/switch/switch-selected/switch-selected.component.html @@ -0,0 +1,17 @@ +
+ On + + Power + + + Power + + + Off + + Power + + + Power + +
diff --git a/src/app/data-entries/switch/switch-selected/switch-selected.component.scss b/src/app/data-entries/switch/switch-selected/switch-selected.component.scss new file mode 100644 index 0000000000..3b46e34548 --- /dev/null +++ b/src/app/data-entries/switch/switch-selected/switch-selected.component.scss @@ -0,0 +1,25 @@ +:host { + display: flex; + place-content: center; + place-items: center; + padding: 16px; +} + +.states { + display: grid; + grid-template-columns: repeat(3, auto); + align-items: center; + gap: 32px; + transform: translateY(16px); + + .states__row { + text-align: end; + font: 500 14px / 24px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.1px; + color: var(--ig-gray-600); + } + + .states__disabled { + margin-inline-start: 16px; + } +} diff --git a/src/app/data-entries/switch/switch-selected/switch-selected.component.ts b/src/app/data-entries/switch/switch-selected/switch-selected.component.ts new file mode 100644 index 0000000000..706b5c9295 --- /dev/null +++ b/src/app/data-entries/switch/switch-selected/switch-selected.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-switch-selected', + styleUrls: ['./switch-selected.component.scss'], + templateUrl: './switch-selected.component.html', + imports: [IgxSwitchComponent] +}) +export class SwitchSelectedComponent { } diff --git a/src/app/data-entries/switch/switch-styling/layout.scss b/src/app/data-entries/switch/switch-styling/layout.scss deleted file mode 100644 index 6e92f5d995..0000000000 --- a/src/app/data-entries/switch/switch-styling/layout.scss +++ /dev/null @@ -1,59 +0,0 @@ -@use "igniteui-angular/theming" as *; -@use 'sass:map'; - -:host { - ::ng-deep { - $_switch-schema: map.get($light-fluent-schema, switch); - @include tokens(switch-theme($schema: $_switch-schema)); - - // Note: This is not the standard approach for styling the component. - // We're using it here solely to mirror the UI5 sample. - - igx-switch:hover .igx-switch__thumb { - --border-hover-color: #fff; - } - - .igx-switch__composite { - width: rem(44px); - height: rem(20px); - padding-left: rem(2px); - } - - .igx-switch__composite-thumb { - width: rem(25px); - height: 1rem; - min-width: rem(25px); - transform: translateX(-0.5px); - } - - .igx-switch__thumb { - width: rem(25px); - height: 1rem; - min-width: rem(25px); - } - - .igx-switch--checked .igx-switch__composite .igx-switch__composite-thumb { - transform: translateX(0.85rem); - } - - .igx-switch--focused .igx-switch__composite::after { - border-radius: 1rem; - box-shadow: 0 0 0 rem(2px) var(--focus-outline-color); - } - } -} - -igx-switch { - margin-top: rem(24px); - width: max-content; -} - -igx-switch:hover { - --track-off-color: #637d97; -} - -.switch-wrapper { - display: flex; - flex-flow: column nowrap; - padding: 2rem; -} \ No newline at end of file diff --git a/src/app/data-entries/switch/switch-styling/switch-styling.component.html b/src/app/data-entries/switch/switch-styling/switch-styling.component.html index db4efd584c..9904fecca5 100644 --- a/src/app/data-entries/switch/switch-styling/switch-styling.component.html +++ b/src/app/data-entries/switch/switch-styling/switch-styling.component.html @@ -1,8 +1,22 @@ -
- @for (setting of settings; track setting) { - - {{ setting.name }} - - } -
+ + + + + Two-factor authentication + Extra sign-in verification + + + + + + + + + + Authenticator app + Security key + Backup codes + + + diff --git a/src/app/data-entries/switch/switch-styling/switch-styling.component.scss b/src/app/data-entries/switch/switch-styling/switch-styling.component.scss index 656327aab1..1bcc8dcda4 100644 --- a/src/app/data-entries/switch/switch-styling/switch-styling.component.scss +++ b/src/app/data-entries/switch/switch-styling/switch-styling.component.scss @@ -1,40 +1,130 @@ -@use "layout.scss"; @use "igniteui-angular/theming" as *; -// CSS variables approach - -igx-switch { - --thumb-on-color: #e3f0ff; - --thumb-off-color: #fff; - --thumb-off-hover-color: #ededed; - --track-on-color: #0064d9; - --track-off-color: #788fa6; - --track-on-hover-color: #0058bf; - --border-radius-track: 1rem; - --focus-outline-color: #0032a5; - --border-on-color: transparent; - --border-color: transparent; - --border-on-hover-color: transparent; - --border-hover-color: transparent; -} - -// Sass theme approach - -// $custom-switch-theme: switch-theme( -// $thumb-on-color: #e3f0ff, -// $track-on-color: #0064d9, -// $track-on-hover-color: #0058bf, -// $thumb-off-color: #fff, -// $thumb-off-hover-color: #ededed, -// $track-off-color: #788fa6, -// $border-radius-track: 1rem, -// $focus-outline-color: #0032a5, -// $border-on-color: transparent, -// $border-on-hover-color: transparent, -// $border-color: transparent, -// $border-hover-color: transparent, -// ); - -// :host { -// @include tokens($custom-switch-theme); -// } +:host ::ng-deep igx-switch .igx-switch__thumb { + min-width: 10px; + transform: translateY(-1px); +} + +:host ::ng-deep igx-switch .igx-switch__ripple { + display: none; +} + +:host { + display: flex; + place-content: center; + place-items: center; + min-block-size: 100%; + padding: 1rem; +} + +.security { + display: block; + inline-size: 100%; + max-inline-size: 348px; + background: var(--ig-surface-500); + border: rem(1px) solid var(--ig-gray-300); + border-radius: rem(16px); + box-shadow: 0 rem(1px) rem(3px) rgb(0 0 0 / 12%); + overflow: hidden; + + igx-expansion-panel-header { + display: block !important; + } + + ::ng-deep igx-expansion-panel-header > div { + padding: rem(12px) rem(16px) !important; + gap: rem(16px) !important; + } + + igx-expansion-panel-title { + flex: 1 1 auto; + min-inline-size: 0; + } + + igx-expansion-panel-icon { + flex: 0 0 auto; + transform: none; + margin-inline-start: 0; + } + + igx-expansion-panel-body { + display: block; + padding-inline-start: rem(5px); + border-block-start: rem(1px) solid var(--ig-gray-300); + } + + igx-switch { + inline-size: rem(43px); + block-size: rem(24px); + transform: translateX(rem(2px)); + } + + igx-radio-group { + display: flex; + flex-direction: column; + gap: rem(8px); + margin-inline-start: rem(10px); + } +} + +.option { + display: flex; + flex-direction: column; + gap: rem(2px); + text-align: start; + white-space: normal; + min-inline-size: 0; + + .option__label { + font: 600 #{rem(16px)} / #{rem(24px)} "Aktiv Grotesk", sans-serif; + letter-spacing: #{rem(0.15px)}; + color: var(--ig-gray-700); + } + + .option__hint { + font: 500 #{rem(14px)} / #{rem(24px)} "Aktiv Grotesk", sans-serif; + letter-spacing: #{rem(0.1px)}; + color: var(--ig-gray-600); + } +} + +igx-radio { + font: 600 #{rem(12px)} / #{rem(16px)} "Aktiv Grotesk", sans-serif; + letter-spacing: #{rem(0.15px)}; + color: var(--ig-primary-900); + + --fill-color: var(--ig-primary-500); + --fill-color-hover: var(--ig-primary-500); + --fill-hover-border-color: var(--ig-primary-500); +} + +:host ::ng-deep igx-radio.igx-radio--checked .igx-radio__composite::after { + background: transparent; + border-color: transparent; +} + +:host ::ng-deep igx-radio.igx-radio--checked .igx-radio__composite::before { + transform: none !important; +} + +:host ::ng-deep igx-radio .igx-radio__composite::before, +:host ::ng-deep igx-radio .igx-radio__composite::after { + width: 16px; + height: 16px; +} + +:host ::ng-deep igx-radio .igx-radio__label { + transform: translateY(-2px); +} + +:host ::ng-deep igx-radio .igx-radio__composite, +:host ::ng-deep igx-radio .igx-radio__composite::before, +:host ::ng-deep igx-radio .igx-radio__composite::after { + animation: none !important; + transition: none !important; +} + +:host ::ng-deep igx-radio .igx-radio__ripple { + opacity: 0; + pointer-events: none; +} diff --git a/src/app/data-entries/switch/switch-styling/switch-styling.component.ts b/src/app/data-entries/switch/switch-styling/switch-styling.component.ts index 31793317e2..a2ddb55ffb 100644 --- a/src/app/data-entries/switch/switch-styling/switch-styling.component.ts +++ b/src/app/data-entries/switch/switch-styling/switch-styling.component.ts @@ -1,16 +1,32 @@ import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { IgxSwitchComponent } from 'igniteui-angular/switch'; +import { IgxRadioComponent, IgxRadioGroupDirective, RadioGroupAlignment } from 'igniteui-angular/radio'; +import { + IgxExpansionPanelBodyComponent, + IgxExpansionPanelComponent, + IgxExpansionPanelHeaderComponent, + IgxExpansionPanelIconDirective, + IgxExpansionPanelTitleDirective +} from 'igniteui-angular/expansion-panel'; @Component({ selector: 'app-switch-styling', styleUrls: ['./switch-styling.component.scss'], templateUrl: './switch-styling.component.html', - imports: [IgxSwitchComponent] + imports: [ + IgxSwitchComponent, + IgxRadioComponent, + IgxRadioGroupDirective, + IgxExpansionPanelComponent, + IgxExpansionPanelHeaderComponent, + IgxExpansionPanelTitleDirective, + IgxExpansionPanelIconDirective, + IgxExpansionPanelBodyComponent, + FormsModule + ] }) export class SwitchStylingComponent { - public settings = [ - { name: 'WiFi', state: false }, - { name: 'Bluetooth', state: true }, - { name: 'Device visibility', state: false } - ]; + public alignment = RadioGroupAlignment.vertical; + public method = 'app'; } diff --git a/src/app/data-entries/switch/switch-tailwind-styling/layout.scss b/src/app/data-entries/switch/switch-tailwind-styling/layout.scss deleted file mode 100644 index 0988ab89bd..0000000000 --- a/src/app/data-entries/switch/switch-tailwind-styling/layout.scss +++ /dev/null @@ -1,9 +0,0 @@ -igx-switch { - margin-bottom: 24px; -} - -.switch-wrapper { - display: flex; - flex-flow: column nowrap; - padding: 16px; -} diff --git a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.html b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.html index 1a54d792c9..955b3e531b 100644 --- a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.html +++ b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.html @@ -1,7 +1,19 @@ -
- @for (setting of settings; track setting) { - - {{ setting.name }} - - } +
+
+ Dashboard + + + + Dark mode + + +
+
+
Revenue overview
+

+ $84,290 this month, up 12% from July.
+ Your top-performing channel is Direct, driving 41% of total revenue. +

+
diff --git a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.scss b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.scss index a60d456faa..20b66dbc13 100644 --- a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.scss +++ b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.scss @@ -1 +1,14 @@ -@use "layout.scss"; +:host ::ng-deep igx-switch .igx-switch__thumb { + min-width: 10px; +} + +:host ::ng-deep igx-switch .igx-switch__ripple { + display: none; +} + +:host { + display: flex; + place-content: center; + place-items: center; + padding: 40px; +} diff --git a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.ts b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.ts index e49904ee31..f758af0066 100644 --- a/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.ts +++ b/src/app/data-entries/switch/switch-tailwind-styling/switch-tailwind-styling.component.ts @@ -1,17 +1,20 @@ -import { Component } from '@angular/core'; - +import { Component, inject } from '@angular/core'; import { IgxSwitchComponent } from 'igniteui-angular/switch'; +import { IgxIconComponent, IgxIconService } from 'igniteui-angular/icon'; + +const darkModeIcon = + ''; @Component({ selector: 'app-switch-tailwind-styling', styleUrls: ['./switch-tailwind-styling.component.scss'], templateUrl: './switch-tailwind-styling.component.html', - imports: [IgxSwitchComponent] + imports: [IgxSwitchComponent, IgxIconComponent] }) export class SwitchTailwindStylingComponent { - public settings = [ - { name: 'WiFi', state: false}, - { name: 'Bluetooth', state: true}, - { name: 'Device visibility', state: false} - ]; + public isDarkMode = true; + + constructor() { + inject(IgxIconService).addSvgIconFromText('dark_mode', darkModeIcon, 'material'); + } } diff --git a/src/app/grid/grid-groupby-summary-styling-sample/grid-groupby-summary-styling-sample.component.scss b/src/app/grid/grid-groupby-summary-styling-sample/grid-groupby-summary-styling-sample.component.scss index 0ade0da842..e886abfc87 100644 --- a/src/app/grid/grid-groupby-summary-styling-sample/grid-groupby-summary-styling-sample.component.scss +++ b/src/app/grid/grid-groupby-summary-styling-sample/grid-groupby-summary-styling-sample.component.scss @@ -7,7 +7,6 @@ $custom-theme: grid-summary-theme( $background-color: $summaries-background, $label-color: #e41c77, $result-color: black, - $pinned-border-width: 2px, $pinned-border-style: dotted, $pinned-border-color: #e41c77, ); diff --git a/src/app/grid/grid-routes-data.ts b/src/app/grid/grid-routes-data.ts index 57923487fe..10860e02df 100644 --- a/src/app/grid/grid-routes-data.ts +++ b/src/app/grid/grid-routes-data.ts @@ -4,6 +4,7 @@ export const gridsRoutesData = { 'grid-groupby': { displayName: 'Grid GroupBy', parentName: 'Grid' }, 'grid-cellMerge': { displayName: 'Grid Cell Merge', parentName: 'Grid' }, 'grid-cellMerge-custom': { displayName: 'Grid Cell Merge Custom', parentName: 'Grid' }, + 'grid-theming': { displayName: 'Grid Theming', parentName: 'Grid' }, 'grid-groupby-custom': {displayName: 'Grid GroupBy Custom', parentName: 'Grid'}, 'grid-groupby-paging': { displayName: 'Grid GroupBy Paging', parentName: 'Grid' }, 'grid-groupby-styling': { displayName: 'Grid GroupBy Styling', parentName: 'Grid' }, diff --git a/src/app/grid/grid-theming/grid-theming.component.html b/src/app/grid/grid-theming/grid-theming.component.html new file mode 100644 index 0000000000..6a044abecf --- /dev/null +++ b/src/app/grid/grid-theming/grid-theming.component.html @@ -0,0 +1,64 @@ +
+
+ Pick a theme + + + @for (theme of themes; track theme.class) { + + } + + +

+ Custom themes, not built-in: each is a grid-theme() with its + own background and accent. +

+
+ + + + + Invoices + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/app/grid/grid-theming/grid-theming.component.scss b/src/app/grid/grid-theming/grid-theming.component.scss new file mode 100644 index 0000000000..29578f9aa5 --- /dev/null +++ b/src/app/grid/grid-theming/grid-theming.component.scss @@ -0,0 +1,145 @@ +@use "igniteui-angular/theming" as *; + +$studio-bg: #faf4ed; +$studio-accent: #907aa9; +$ledger-bg: #eceff4; +$ledger-accent: #5e81ac; +$editorial-bg: #333c43; +$editorial-accent: #a7c080; +$midnight-bg: #282a36; +$midnight-accent: #bd93f9; + +:host { + display: block; + padding: 16px; +} + +.theme-studio { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0.6; + + @include tokens(grid-theme( + $background: $studio-bg, + $foreground: #575279, + $accent-color: $studio-accent, + $header-background: #fffaf3, + $header-border-color: #dfdad9, + $row-border-color: #f2e9e1, + $grid-border-color: #dfdad9, + $grid-shadow: (0 1px 3px rgba(87, 82, 121, 0.10), 0 1px 2px rgba(87, 82, 121, 0.06)) + )); +} + +.theme-ledger { + --ig-size: var(--ig-size-small); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $background: $ledger-bg, + $foreground: #2e3440, + $accent-color: $ledger-accent, + $header-background: #d8dee9, + $row-odd-background: #eceff4, + $row-even-background: #e5e9f0, + $body-column-border-color-odd: #d8dee9, + $body-column-border-color-even: #d8dee9, + $row-border-color: #d8dee9, + $grid-border-color: #c8d0dc + )); +} + +.theme-editorial { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $editorial-bg, + $foreground: #d3c6aa, + $accent-color: $editorial-accent, + $header-background: #3a464c, + $row-border-color: #333c43, + $grid-border-color: #333c43 + )); +} + +.theme-midnight { + --ig-size: var(--ig-size-medium); + --ig-radius-factor: 0.25; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $midnight-bg, + $foreground: #f8f8f2, + $accent-color: $midnight-accent, + $header-background: #21222c, + $body-column-border-color-odd: #44475a, + $body-column-border-color-even: #44475a, + $row-border-color: #44475a, + $grid-border-color: #44475a + )); +} + +.grid-theming-sample { + display: flex; + flex-direction: column; + gap: 16px; +} + +.theme-picker { + --ig-button-group-elevation: 0; + + display: flex; + flex-direction: column; + gap: 6px; + align-self: flex-start; +} + +.theme-picker__label { + font-size: 12px; + font-weight: 500; + letter-spacing: 0.04em; + color: var(--ig-gray-700); +} + +.theme-picker__hint { + margin: 0; + font-size: 12px; + line-height: 1.45; + color: var(--ig-gray-600); + + code { + font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace; + font-size: 11px; + } +} + +.theme-swatch { + display: inline-block; + min-width: 14px; + aspect-ratio: 1; + border-radius: 50%; + border: 1px solid var(--ig-gray-300); + vertical-align: -2px; + background: linear-gradient(135deg, var(--swatch-bg) 0 50%, var(--swatch-accent) 50% 100%); +} + +.theme-swatch--studio { + --swatch-bg: #{$studio-bg}; + --swatch-accent: #{$studio-accent}; +} + +.theme-swatch--ledger { + --swatch-bg: #{$ledger-bg}; + --swatch-accent: #{$ledger-accent}; +} + +.theme-swatch--editorial { + --swatch-bg: #{$editorial-bg}; + --swatch-accent: #{$editorial-accent}; +} + +.theme-swatch--midnight { + --swatch-bg: #{$midnight-bg}; + --swatch-accent: #{$midnight-accent}; +} diff --git a/src/app/grid/grid-theming/grid-theming.component.ts b/src/app/grid/grid-theming/grid-theming.component.ts new file mode 100644 index 0000000000..97fe513f41 --- /dev/null +++ b/src/app/grid/grid-theming/grid-theming.component.ts @@ -0,0 +1,53 @@ +import { Component, signal } from '@angular/core'; +import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxNumberSummaryOperand, IgxSummaryResult } from 'igniteui-angular/core'; +import { IgxColumnComponent, IgxGridToolbarActionsComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxGridToolbarTitleComponent } from 'igniteui-angular/grids/core'; +import { IgxGridComponent } from 'igniteui-angular/grids/grid'; +import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +import { INVOICE_DATA } from '../../data/invoiceData'; +import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive'; +class CompactSummary extends IgxNumberSummaryOperand { + public override operate(data?: any[]): IgxSummaryResult[] { + return super.operate(data).filter(r => r.key === 'count' || r.key === 'sum'); + } +} + +@Component({ + selector: 'app-grid-theming', + styleUrls: ['./grid-theming.component.scss'], + templateUrl: './grid-theming.component.html', + imports: [ + IgxButtonDirective, + IgxButtonGroupComponent, + IgxColumnComponent, + IgxGridComponent, + IgxGridToolbarActionsComponent, + IgxGridToolbarComponent, + IgxGridToolbarHidingComponent, + IgxGridToolbarPinningComponent, + IgxGridToolbarTitleComponent, + IgxPaginatorComponent, + IgxPreventDocumentScrollDirective + ] +}) +export class GridThemingComponent { + public data = INVOICE_DATA; + public compactSummary = CompactSummary; + public themes = [ + { label: 'Studio', class: 'theme-studio', swatch: 'theme-swatch--studio' }, + { label: 'Ledger', class: 'theme-ledger', swatch: 'theme-swatch--ledger' }, + { label: 'Editorial', class: 'theme-editorial', swatch: 'theme-swatch--editorial' }, + { label: 'Midnight', class: 'theme-midnight', swatch: 'theme-swatch--midnight' } + ]; + + public activeTheme = signal(this.themes[0].class); + + public selectTheme(args: { index: number }) { + this.activeTheme.set(this.themes[args.index].class); + } + + public formatCurrency(value: number) { + return '$' + value.toFixed(2); + } +} diff --git a/src/app/grid/grid-validation-style/grid-validation-style.component.ts b/src/app/grid/grid-validation-style/grid-validation-style.component.ts index 89c22dfaed..ccf4d404d8 100644 --- a/src/app/grid/grid-validation-style/grid-validation-style.component.ts +++ b/src/app/grid/grid-validation-style/grid-validation-style.component.ts @@ -14,7 +14,7 @@ import { NgTemplateOutlet } from '@angular/common'; export class GridValidationStyleComponent { @ViewChild('grid', { read: IgxGridComponent, static: true }) public grid: IgxGridComponent; public data: any[]; - public rowStyles = { + public rowStyles: any = { background: (row: RowType) => row.validation.status === 'INVALID' ? '#FF000033' : '#00000000' }; public cellStyles = { diff --git a/src/app/grid/grids.routes.ts b/src/app/grid/grids.routes.ts index be9950dbc9..c5ded8e028 100644 --- a/src/app/grid/grids.routes.ts +++ b/src/app/grid/grids.routes.ts @@ -31,6 +31,7 @@ import { GridGroupByCustomSampleComponent } from './grid-groupby-custom-sample/g import { GridGroupByPagingSampleComponent } from './grid-group-by-paging-sample/grid-group-by-paging-sample.component'; import { GridGroupBySampleComponent } from './grid-groupby-sample/grid-groupby-sample.component'; import { GridGroupByStylingComponent } from './grid-groupby-styling/grid-groupby-styling.component'; +import { GridThemingComponent } from './grid-theming/grid-theming.component'; import { GridGroupBySummarySampleComponent } from './grid-groupby-summary-sample/grid-groupby-summary-sample.component'; import { GridGroupBySummaryStylingSampleComponent } from './grid-groupby-summary-styling-sample/grid-groupby-summary-styling-sample.component'; import { GridMovingSampleComponent } from './grid-moving-sample/grid-moving-sample.component'; @@ -168,6 +169,11 @@ export const GridsRoutes: Routes = [ data: gridsRoutesData['grid-cellMerge-custom'], path: 'grid-cellMerge-custom' }, + { + component: GridThemingComponent, + data: gridsRoutesData['grid-theming'], + path: 'grid-theming' + }, { component: GridGroupByStylingComponent, data: gridsRoutesData['grid-groupby-styling'], diff --git a/src/app/hierarchical-grid/hgrid-rowStyle-sample/hgrid-rowStyles.component.ts b/src/app/hierarchical-grid/hgrid-rowStyle-sample/hgrid-rowStyles.component.ts index ae92b4259b..cb950623cf 100644 --- a/src/app/hierarchical-grid/hgrid-rowStyle-sample/hgrid-rowStyles.component.ts +++ b/src/app/hierarchical-grid/hgrid-rowStyle-sample/hgrid-rowStyles.component.ts @@ -18,12 +18,12 @@ export class HGridRowStylesSampleComponent implements OnInit { private hierarchicalGrid: IgxHierarchicalGridComponent; public localdata; - public rowStyles = { + public rowStyles: any = { background:(row: RowType) => row.data['HasGrammyAward'] ? '#eeddd3' : '#f0efeb', 'border-left': (row: RowType) => row.data['HasGrammyAward'] ? '2px solid #dda15e' : null }; - public childRowStyles = { + public childRowStyles: any = { 'border-left': (row: RowType) => row.data['BillboardReview'] > 70 ? '3.5px solid #dda15e' : null }; constructor() { } diff --git a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.html b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.html index 7028f9adae..8f27753f0c 100644 --- a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.html +++ b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.html @@ -1,36 +1,67 @@
- - - - -
- -
-
-
- - - +
+ Pick a theme - - - - - - - - - - - - + + @for (theme of themes; track theme.class) { + + } + - - - - - - - +

+ Custom themes, not built-in: each is a grid-theme() with its + own background and accent. +

+
+ + + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.scss b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.scss index 2c0d35a3be..9a14ff29e1 100644 --- a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.scss +++ b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.scss @@ -1,16 +1,141 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$background: #292826; -$foreground: #eeece1; -$accent: #ffcd0f; - -$custom-grid: grid-theme( - $background: $background, - $foreground: $foreground, - $accent-color: $accent, -); - -:host { - @include tokens($custom-grid); +$studio-bg: #faf4ed; +$studio-accent: #907aa9; +$ledger-bg: #eceff4; +$ledger-accent: #5e81ac; +$editorial-bg: #333c43; +$editorial-accent: #a7c080; +$midnight-bg: #282a36; +$midnight-accent: #bd93f9; + +.theme-studio { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0.6; + + @include tokens(grid-theme( + $background: $studio-bg, + $foreground: #575279, + $accent-color: $studio-accent, + $header-background: #fffaf3, + $header-border-color: #dfdad9, + $row-border-color: #f2e9e1, + $grid-border-color: #dfdad9, + $grid-shadow: (0 1px 3px rgba(87, 82, 121, 0.10), 0 1px 2px rgba(87, 82, 121, 0.06)) + )); +} + +.theme-ledger { + --ig-size: var(--ig-size-small); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $background: $ledger-bg, + $foreground: #2e3440, + $accent-color: $ledger-accent, + $header-background: #d8dee9, + $row-odd-background: #eceff4, + $row-even-background: #e5e9f0, + $body-column-border-color-odd: #d8dee9, + $body-column-border-color-even: #d8dee9, + $row-border-color: #d8dee9, + $grid-border-color: #c8d0dc + )); +} + +.theme-editorial { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $editorial-bg, + $foreground: #d3c6aa, + $accent-color: $editorial-accent, + $header-background: #3a464c, + $row-border-color: #333c43, + $grid-border-color: #333c43 + )); +} + +.theme-midnight { + --ig-size: var(--ig-size-medium); + --ig-radius-factor: 0.25; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $midnight-bg, + $foreground: #f8f8f2, + $accent-color: $midnight-accent, + $header-background: #21222c, + $body-column-border-color-odd: #44475a, + $body-column-border-color-even: #44475a, + $row-border-color: #44475a, + $grid-border-color: #44475a + )); +} + +.grid__wrapper { + display: flex; + flex-direction: column; + gap: 16px; +} + +.theme-picker { + --ig-button-group-elevation: 0; + + display: flex; + flex-direction: column; + gap: 6px; + align-self: flex-start; +} + +.theme-picker__label { + font-size: 12px; + font-weight: 500; + letter-spacing: 0.04em; + color: var(--ig-gray-700); +} + +.theme-picker__hint { + margin: 0; + font-size: 12px; + line-height: 1.45; + color: var(--ig-gray-600); + + code { + font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace; + font-size: 11px; + } +} + +.theme-swatch { + display: inline-block; + min-width: 14px; + aspect-ratio: 1; + border-radius: 50%; + border: 1px solid var(--ig-gray-300); + vertical-align: -2px; + background: linear-gradient(135deg, var(--swatch-bg) 0 50%, var(--swatch-accent) 50% 100%); +} + +.theme-swatch--studio { + --swatch-bg: #{$studio-bg}; + --swatch-accent: #{$studio-accent}; +} + +.theme-swatch--ledger { + --swatch-bg: #{$ledger-bg}; + --swatch-accent: #{$ledger-accent}; +} + +.theme-swatch--editorial { + --swatch-bg: #{$editorial-bg}; + --swatch-accent: #{$editorial-accent}; +} + +.theme-swatch--midnight { + --swatch-bg: #{$midnight-bg}; + --swatch-accent: #{$midnight-accent}; } diff --git a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.ts b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.ts index fcc915ddfc..91bd07fa4c 100644 --- a/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.ts +++ b/src/app/hierarchical-grid/hierarchical-grid-styling/hierarchical-grid-styling.component.ts @@ -1,4 +1,6 @@ -import { Component } from '@angular/core'; +import { Component, signal } from '@angular/core'; +import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IgxCellTemplateDirective, IgxColumnComponent } from 'igniteui-angular/grids/core'; import { IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular/grids/hierarchical-grid'; import { SINGERS } from '../../data/singersData'; @@ -8,7 +10,7 @@ import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scro selector: 'app-hierarchical-grid-styling', styleUrls: ['./hierarchical-grid-styling.component.scss'], templateUrl: 'hierarchical-grid-styling.component.html', - imports: [IgxHierarchicalGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxRowIslandComponent] + imports: [IgxHierarchicalGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxRowIslandComponent, IgxButtonGroupComponent, IgxButtonDirective] }) export class HGridStylingComponent { @@ -16,11 +18,23 @@ export class HGridStylingComponent { public col: IgxColumnComponent; public pWidth: string; public nWidth: string; + public themes = [ + { label: 'Studio', class: 'theme-studio', swatch: 'theme-swatch--studio' }, + { label: 'Ledger', class: 'theme-ledger', swatch: 'theme-swatch--ledger' }, + { label: 'Editorial', class: 'theme-editorial', swatch: 'theme-swatch--editorial' }, + { label: 'Midnight', class: 'theme-midnight', swatch: 'theme-swatch--midnight' } + ]; + + public activeTheme = signal(this.themes[0].class); constructor() { this.localdata = SINGERS; } + public selectTheme(args: { index: number }) { + this.activeTheme.set(this.themes[args.index].class); + } + public onResize(event) { this.col = event.column; this.pWidth = event.prevWidth; diff --git a/src/app/hierarchical-grid/hierarchical-grid-styling/layout.scss b/src/app/hierarchical-grid/hierarchical-grid-styling/layout.scss index b620c7ade6..e2bcf0bd0e 100644 --- a/src/app/hierarchical-grid/hierarchical-grid-styling/layout.scss +++ b/src/app/hierarchical-grid/hierarchical-grid-styling/layout.scss @@ -1,12 +1,18 @@ +// Fits the smallest row density. .photo { vertical-align: middle; - max-height: 62px; + max-block-size: 24px; + border-radius: 50%; } .cell__inner_2 { margin: 1px } +:host { + display: block; +} + .grid__wrapper{ padding: 10px; } diff --git a/src/app/hierarchical-grid/hierarchical-grid-validation-style/hierarchical-grid-validation-style.component.ts b/src/app/hierarchical-grid/hierarchical-grid-validation-style/hierarchical-grid-validation-style.component.ts index 49871eb70b..ffc614547d 100644 --- a/src/app/hierarchical-grid/hierarchical-grid-validation-style/hierarchical-grid-validation-style.component.ts +++ b/src/app/hierarchical-grid/hierarchical-grid-validation-style/hierarchical-grid-validation-style.component.ts @@ -17,7 +17,7 @@ export class HGridValidationStyleComponent { @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hierarchicalGrid: IgxHierarchicalGridComponent; @ViewChild('childGrid', { static: true }) private childGrid: IgxRowIslandComponent; public localData: Singer[]; - public rowStyles = { + public rowStyles: any = { background: (row: RowType) => row.validation.status === 'INVALID' ? '#FF000033' : '#00000000' }; public cellStyles = { diff --git a/src/app/index/index.component.scss b/src/app/index/index.component.scss index f6cb2bd6a5..5b2502768b 100644 --- a/src/app/index/index.component.scss +++ b/src/app/index/index.component.scss @@ -3,19 +3,21 @@ } .main { + display: flex; + flex-direction: column; width: calc(100% - 300px); + height: 100%; } -.content { - width: 100%; - // height: calc(100% - 56px); - height: 100%; +.content { + width: 100%; + flex: 1 1 auto; max-height: 1000px; min-width: 300px; min-height: 300px; justify-content: center; align-items: stretch; - overflow: auto; + overflow: auto; } .navdrawer-ellipsis { diff --git a/src/app/layouts/accordion/accordion-customization/accordion-customization.component.html b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.html new file mode 100644 index 0000000000..f3d9ddfe51 --- /dev/null +++ b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.html @@ -0,0 +1,70 @@ +
+
+ + + + Transportation@if (selectedCategories) {: {{ selectedCategories }}} + Choose how you want to travel + + +

Select one or more transportation options for your trip.

+
+ @for (category of categories; track category.type) { + {{ category.type }} + } +
+
+
+ + + + Budget: ${{ slider.lowerValue }} - ${{ slider.upperValue }} + Set the price range + + +

Adjust the minimum and maximum cost for available options.

+
+ ${{ slider.lowerValue }} + ${{ slider.upperValue }} +
+ +
+
+ + + + Minimum Rating@if (rating) {: {{ rating }}} + Filter by review score + + +

Choose the lowest rating you want to include in the results.

+
+ @for (ratingOption of ratingOptions; track ratingOption) { + + {{ ratingOption }} stars or more + + @for (star of [].constructor(ratingOption); track $index) { + star + } + + + } +
+
+
+ + + + Arrival Time{{ time }} + Set the latest arrival time + + +

Pick the latest acceptable arrival time for your trip.

+ + + +
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-customization/accordion-customization.component.scss b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.scss new file mode 100644 index 0000000000..f2b6961adc --- /dev/null +++ b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.scss @@ -0,0 +1,66 @@ +.accordion-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +.accordion-content { + width: min(760px, 100%); + margin: 0 auto; + padding: 24px; + box-sizing: border-box; +} + +igx-accordion { + display: block; + border: 1px solid var(--ig-gray-300); + border-radius: 4px; +} + +.panel-description { + margin: 0 0 16px; + color: var(--ig-gray-700); +} + +.categories-container { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px 24px; + max-width: 520px; +} + +.category-option, +.rating-option { + margin: 4px 0; +} + +.range-summary { + display: flex; + justify-content: space-between; + max-width: 560px; + margin-bottom: 4px; + font-weight: 600; +} + +.cost-slider { + max-width: 560px; + margin: 8px 0 0; +} + +.rating-options { + display: grid; + gap: 8px; + max-width: 360px; +} + +.rating-control { + flex-direction: row; +} + +.time-input { + max-width: 260px; +} + +.size-small { + --ig-size: var(--ig-size-small); +} diff --git a/src/app/layouts/accordion/accordion-customization/accordion-customization.component.ts b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.ts new file mode 100644 index 0000000000..82311cc43c --- /dev/null +++ b/src/app/layouts/accordion/accordion-customization/accordion-customization.component.ts @@ -0,0 +1,52 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxRadioComponent } from 'igniteui-angular/radio'; +import { IgxSliderComponent, IgxSliderType } from 'igniteui-angular/slider'; +import { IgxLabelDirective } from 'igniteui-angular/input-group'; +import { IgxTimePickerComponent } from 'igniteui-angular/time-picker'; + +@Component({ + selector: 'app-accordion-customization', + styleUrls: ['./accordion-customization.component.scss'], + templateUrl: './accordion-customization.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [FormsModule, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent, IgxCheckboxComponent, IgxSliderComponent, IgxRadioComponent, IgxIconComponent, IgxTimePickerComponent, IgxLabelDirective] +}) +export class AccordionCustomizationComponent { + public readonly ratingOptions = [2, 3, 4, 5]; + public readonly sliderType = IgxSliderType; + public priceRange = new PriceRange(200, 800); + public rating = ''; + public arriveTime: Date | null = null; + + public categories = [ + { checked: false, type: 'Bike' }, + { checked: false, type: 'Motorcycle' }, + { checked: false, type: 'Car' }, + { checked: false, type: 'Taxi' }, + { checked: false, type: 'Public Transport' } + ]; + + public get selectedCategories(): string { + return this.categories + .filter(item => item.checked) + .map(item => item.type) + .join(', '); + } + + public get time(): string { + return this.arriveTime ? `: ${this.arriveTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}` : ''; + } +} + +class PriceRange { + constructor( + public lower: number, + public upper: number + ) { + } +} diff --git a/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.html b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.html new file mode 100644 index 0000000000..7b66ad84dd --- /dev/null +++ b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.html @@ -0,0 +1,69 @@ +
+
+
+ Single Expand +
+ + + + + Workspace Settings + Nested account, access, and billing options + + + + + + Profile + Name, photo, and contact details + + +

Update the public information shown to other workspace members.

+
+
+ + + + Security + Password and sign-in preferences + + +

Review active sessions, change your password, and configure sign-in requirements.

+
+
+ + + + Notifications + Email and product updates + + +

Choose the messages you receive for comments, assignments, and releases.

+
+
+
+
+
+ + + + Team Access + Members, roles, and permissions + + +

Invite teammates, assign roles, and review workspace permissions.

+
+
+ + + + Billing + Plan, invoices, and payment method + + +

Manage subscription details, billing contacts, and invoice delivery.

+
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.scss b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.scss new file mode 100644 index 0000000000..7f946ce906 --- /dev/null +++ b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.scss @@ -0,0 +1,24 @@ +.accordion-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +.accordion-content { + width: min(760px, 100%); + margin: 0 auto; + padding: 24px; + box-sizing: border-box; +} + +.accordion-toolbar { + display: flex; + justify-content: flex-end; + margin-bottom: 12px; +} + +igx-accordion { + display: block; + border: 1px solid var(--ig-gray-300); + border-radius: 4px; +} diff --git a/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.ts b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.ts new file mode 100644 index 0000000000..38cd02d135 --- /dev/null +++ b/src/app/layouts/accordion/accordion-nested-scenario/accordion-nested-scenario.component.ts @@ -0,0 +1,16 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-accordion-nested-scenario', + styleUrls: ['./accordion-nested-scenario.component.scss'], + templateUrl: './accordion-nested-scenario.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [FormsModule, IgxSwitchComponent, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent] +}) +export class AccordionNestedScenarioComponent { + public singleBranchExpand = false; +} diff --git a/src/app/layouts/accordion/accordion-overview/accordion-overview.component.html b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.html new file mode 100644 index 0000000000..953f53c2f4 --- /dev/null +++ b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.html @@ -0,0 +1,37 @@ +
+
+
+ Single Expand +
+ + + + + Account + Profile and security settings + + +

Update your profile details, password, and sign-in preferences.

+
+
+ + + Notifications + Email and product updates + + +

Choose which notifications you receive and how often they are delivered.

+
+
+ + + Billing + Payment and invoice settings + + +

Manage payment methods, billing contacts, and invoice delivery options.

+
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-overview/accordion-overview.component.scss b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.scss new file mode 100644 index 0000000000..868bd0c158 --- /dev/null +++ b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.scss @@ -0,0 +1,24 @@ +.accordion-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +.accordion-content { + width: min(720px, 100%); + margin: 0 auto; + padding: 24px; + box-sizing: border-box; +} + +.accordion-toolbar { + display: flex; + justify-content: flex-end; + margin-bottom: 12px; +} + +igx-accordion { + display: block; + border: 1px solid var(--ig-gray-300); + border-radius: 4px; +} diff --git a/src/app/layouts/accordion/accordion-overview/accordion-overview.component.ts b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.ts new file mode 100644 index 0000000000..440f9fd557 --- /dev/null +++ b/src/app/layouts/accordion/accordion-overview/accordion-overview.component.ts @@ -0,0 +1,16 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; +import { FormsModule } from '@angular/forms'; + +@Component({ + selector: 'app-accordion-overview', + styleUrls: ['./accordion-overview.component.scss'], + templateUrl: './accordion-overview.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [IgxSwitchComponent, FormsModule, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent] +}) +export class AccordionOverviewComponent { + public singleBranchExpand = false; +} diff --git a/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.html b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.html new file mode 100644 index 0000000000..3e16857cc5 --- /dev/null +++ b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.html @@ -0,0 +1,40 @@ +
+
+
+ + +
+ + + + + Billing + Invoices and payment settings + + +

Review invoices, update payment methods, and manage billing contacts.

+
+
+ + + + Security + Password and access controls + + +

Configure password rules, multi-factor authentication, and recovery options.

+
+
+ + + + Notifications + Product updates and account alerts + + +

Choose which product updates and account alerts are sent to your team.

+
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.scss b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.scss new file mode 100644 index 0000000000..11f32c5cb5 --- /dev/null +++ b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.scss @@ -0,0 +1,29 @@ +.accordion-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +.accordion-content { + width: min(720px, 100%); + margin: 0 auto; + padding: 24px; + box-sizing: border-box; +} + +.accordion-toolbar { + display: flex; + justify-content: flex-end; + gap: 8px; + margin-bottom: 12px; +} + +.action-button { + min-width: 96px; +} + +igx-accordion { + display: block; + border: 1px solid var(--ig-gray-300); + border-radius: 4px; +} diff --git a/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.ts b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.ts new file mode 100644 index 0000000000..2c3ea01263 --- /dev/null +++ b/src/app/layouts/accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; + +@Component({ + selector: 'app-accordion-programmatic-expansion', + styleUrls: ['./accordion-programmatic-expansion.component.scss'], + templateUrl: './accordion-programmatic-expansion.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [IgxButtonDirective, IgxRippleDirective, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent] +}) +export class AccordionProgrammaticExpansionComponent { +} diff --git a/src/app/layouts/accordion/accordion-styling/accordion-styling.component.html b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.html new file mode 100644 index 0000000000..62a0a50618 --- /dev/null +++ b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.html @@ -0,0 +1,35 @@ +
+
+ + + + Getting Started + Setup and onboarding + + +

Find installation steps, project setup guidance, and resources for building your first application.

+
+
+ + + + Billing + Invoices and payment methods + + +

Review invoices, update payment methods, and manage billing contacts for your account.

+
+
+ + + + Security + Access and authentication + + +

Configure password rules, multi-factor authentication, and recovery options for your team.

+
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-styling/accordion-styling.component.scss b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.scss new file mode 100644 index 0000000000..205bf6afb1 --- /dev/null +++ b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.scss @@ -0,0 +1,50 @@ +@use "igniteui-angular/theming" as *; + +.accordion-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +.accordion-content { + width: min(720px, 100%); + margin: 0 auto; + padding: 24px; + box-sizing: border-box; +} + +igx-accordion { + display: block; + border: 1px solid var(--ig-gray-300); + border-radius: 4px; +} + +$custom-panel-theme: expansion-panel-theme( + $header-background: var(--ig-gray-100), + $header-focus-background: var(--ig-primary-50), + $body-background: var(--ig-gray-50), + $body-color: var(--ig-gray-700), + $header-title-color: var(--ig-gray-900), + $header-description-color: var(--ig-gray-900), + $header-icon-color: var(--ig-primary-500), + $border-radius: 4px +); + +:host { + @include tokens($custom-panel-theme); +} + +::ng-deep { + .igx-expansion-panel--expanded .igx-expansion-panel__header-inner { + background-color: var(--ig-primary-50); + } + + .igx-expansion-panel--expanded .igx-expansion-panel__header-title, + .igx-expansion-panel--expanded .igx-expansion-panel__header-description { + color: var(--ig-primary-700); + } + + .igx-expansion-panel__header-title { + font-weight: 600; + } +} diff --git a/src/app/layouts/accordion/accordion-styling/accordion-styling.component.ts b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.ts new file mode 100644 index 0000000000..e5958cb697 --- /dev/null +++ b/src/app/layouts/accordion/accordion-styling/accordion-styling.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; + +@Component({ + selector: 'app-accordion-styling', + styleUrls: ['./accordion-styling.component.scss'], + templateUrl: './accordion-styling.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent] +}) +export class AccordionStylingComponent {} diff --git a/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.html b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.html new file mode 100644 index 0000000000..655e1358eb --- /dev/null +++ b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.html @@ -0,0 +1,35 @@ +
+
+ + + + Getting Started + Setup and onboarding + + +

Find installation steps, project setup guidance, and resources for building your first application.

+
+
+ + + + Billing + Invoices and payment methods + + +

Review invoices, update payment methods, and manage billing contacts for your account.

+
+
+ + + + Security + Access and authentication + + +

Configure password rules, multi-factor authentication, and recovery options for your team.

+
+
+
+
+
diff --git a/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.scss b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.scss new file mode 100644 index 0000000000..70523e2fd8 --- /dev/null +++ b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.scss @@ -0,0 +1,20 @@ +.accordion-tailwind-sample { + width: 100%; + height: 100%; + overflow-y: auto; +} + +::ng-deep { + .igx-expansion-panel--expanded .igx-expansion-panel__header-inner { + background-color: var(--ig-primary-50); + } + + .igx-expansion-panel--expanded .igx-expansion-panel__header-title, + .igx-expansion-panel--expanded .igx-expansion-panel__header-description { + color: var(--ig-primary-700); + } + + .igx-expansion-panel__header-title { + font-weight: 600; + } +} diff --git a/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.ts b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.ts new file mode 100644 index 0000000000..0275ca542c --- /dev/null +++ b/src/app/layouts/accordion/accordion-tailwind-styling/accordion-tailwind-styling.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective } from 'igniteui-angular/expansion-panel'; + +@Component({ + selector: 'app-accordion-tailwind-styling', + styleUrls: ['./accordion-tailwind-styling.component.scss'], + templateUrl: './accordion-tailwind-styling.component.html', + changeDetection: ChangeDetectionStrategy.Eager, + imports: [IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelBodyComponent] +}) +export class AccordionTailwindStylingComponent {} diff --git a/src/app/layouts/avatar/avatar-overview/avatar-overview.component.scss b/src/app/layouts/avatar/avatar-overview/avatar-overview.component.scss index 6ee88140a1..66ce9fc688 100644 --- a/src/app/layouts/avatar/avatar-overview/avatar-overview.component.scss +++ b/src/app/layouts/avatar/avatar-overview/avatar-overview.component.scss @@ -26,10 +26,13 @@ display: flex; igx-avatar { - box-shadow: 0 0 0 rem(6px) var(--ig-surface-500); + box-shadow: 0 0 0 calc(var(--size) * 0.07) var(--ig-surface-500); + igx-avatar { - margin-inline-start: rem(-24px); + // Proportional to the avatar's own rendered size (--size, set by + // the theme) rather than a fixed length, since themes disagree + // widely on how big a "large" avatar actually is. + margin-inline-start: calc(var(--size) * -0.27); } &:last-child { diff --git a/src/app/layouts/avatar/avatar-shape/avatar-shape.component.scss b/src/app/layouts/avatar/avatar-shape/avatar-shape.component.scss index a6a47666fd..cbaac2cdce 100644 --- a/src/app/layouts/avatar/avatar-shape/avatar-shape.component.scss +++ b/src/app/layouts/avatar/avatar-shape/avatar-shape.component.scss @@ -23,6 +23,11 @@ span { grid-row: 2; text-align: center; color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-1") { margin: 0; diff --git a/src/app/layouts/avatar/avatar-size/avatar-size.component.scss b/src/app/layouts/avatar/avatar-size/avatar-size.component.scss index 79f4204bbe..119e5278c7 100644 --- a/src/app/layouts/avatar/avatar-size/avatar-size.component.scss +++ b/src/app/layouts/avatar/avatar-size/avatar-size.component.scss @@ -21,6 +21,11 @@ span { grid-row: 2; text-align: center; color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-1") { margin: 0; diff --git a/src/app/layouts/avatar/avatar-variants/avatar-variants.component.scss b/src/app/layouts/avatar/avatar-variants/avatar-variants.component.scss index a4c56b17fc..25fc17d779 100644 --- a/src/app/layouts/avatar/avatar-variants/avatar-variants.component.scss +++ b/src/app/layouts/avatar/avatar-variants/avatar-variants.component.scss @@ -24,6 +24,11 @@ $avatars: circle, square, rounded; grid-row: 2; text-align: center; color: var(--ig-gray-600); + font-family: "Aktiv Grotesk", sans-serif; + font-size: rem(13px); + font-weight: 400; + line-height: rem(20px); + letter-spacing: rem(0.3px); @include type-style("body-1") { margin: 0; diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.html new file mode 100644 index 0000000000..c669651643 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.html @@ -0,0 +1,8 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.scss new file mode 100644 index 0000000000..8d48436a15 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.scss @@ -0,0 +1,17 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + align-items: center; + overflow: auto; +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); +} + +@layer base { + a { + color: revert-layer; + } +} \ No newline at end of file diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.ts new file mode 100644 index 0000000000..4b324dcd1d --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component.ts @@ -0,0 +1,20 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent); + +const slashIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('slash', slashIcon); +} + +@Component({ + selector: 'app-breadcrumbs-custom-separator', + styleUrls: ['./breadcrumbs-custom-separator.component.scss'], + templateUrl: './breadcrumbs-custom-separator.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class BreadcrumbsCustomSeparatorComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.html new file mode 100644 index 0000000000..0a16048f7b --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.html @@ -0,0 +1,24 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.scss new file mode 100644 index 0000000000..54a214167f --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.scss @@ -0,0 +1,18 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + align-items: center; + overflow: auto; + font-family: var(--ig-font-family); +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); +} + +@layer base { + a { + color: revert-layer; + } +} \ No newline at end of file diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.ts new file mode 100644 index 0000000000..096b998ac5 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component.ts @@ -0,0 +1,23 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, IgcIconComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent, IgcIconComponent); + +const homeIcon = + ''; +const notificationsIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('home', homeIcon); + registerIconFromText('notifications', notificationsIcon); +} + +@Component({ + selector: 'app-breadcrumbs-overview', + styleUrls: ['./breadcrumbs-overview.component.scss'], + templateUrl: './breadcrumbs-overview.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class BreadcrumbsOverviewComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.html new file mode 100644 index 0000000000..1809c86dec --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.html @@ -0,0 +1,18 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.scss new file mode 100644 index 0000000000..0d132379d2 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.scss @@ -0,0 +1,21 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + align-items: center; + overflow: auto; +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); +} + +@layer base { + a { + color: revert-layer; + } + + * { + padding: revert-layer; + } +} \ No newline at end of file diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.ts new file mode 100644 index 0000000000..6307c497e1 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component.ts @@ -0,0 +1,20 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, IgcIconComponent, IgcBadgeComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent, IgcIconComponent, IgcBadgeComponent); + +const homeIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('home', homeIcon); +} + +@Component({ + selector: 'app-breadcrumbs-prefix-suffix', + styleUrls: ['./breadcrumbs-prefix-suffix.component.scss'], + templateUrl: './breadcrumbs-prefix-suffix.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class BreadcrumbsPrefixSuffixComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.html new file mode 100644 index 0000000000..cf3f50ed2a --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.html @@ -0,0 +1,35 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.scss new file mode 100644 index 0000000000..a3d90d08d9 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.scss @@ -0,0 +1,48 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + align-items: center; + overflow: auto; +} + +.small { + --ig-size: var(--ig-size-small); +} + +.medium { + --ig-size: var(--ig-size-medium); +} + +.large { + --ig-size: var(--ig-size-large); + + margin-block-start: -0.25rem; +} + +span { + color: #7d8a96; + width: 3.75rem; + margin-inline-end: 2rem; + font-size: 0.875rem; + font-family: "Aktiv Grotesk", sans-serif; +} + +nav { + display: flex; + flex-direction: column; + gap: 1rem; +} + +@layer base { + a { + color: revert-layer; + } +} + +@media (width < 290px) { + span { + width: auto; + margin-inline-end: 1rem; + } +} diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.ts new file mode 100644 index 0000000000..e86c6a568c --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component.ts @@ -0,0 +1,23 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, IgcIconComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent, IgcIconComponent); + +const homeIcon = + ''; +const notificationsIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('home', homeIcon); + registerIconFromText('notifications', notificationsIcon); +} + +@Component({ + selector: 'app-breadcrumbs-sizes', + styleUrls: ['./breadcrumbs-sizes.component.scss'], + templateUrl: './breadcrumbs-sizes.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) + +export class BreadcrumbsSizesComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.html new file mode 100644 index 0000000000..c8b47f221a --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.html @@ -0,0 +1,58 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.scss new file mode 100644 index 0000000000..ad8b1b3ed2 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.scss @@ -0,0 +1,116 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + max-height: 15rem; + padding-block-start: 1rem; + overflow: auto; +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); +} + +.state-hover { + igc-icon { + color: var(--hover-icon-color); + } + + a { + color: var(--hover-text-color); + } +} + +.state-focused { + igc-icon { + color: var(--focus-icon-color); + } + + a { + color: var(--focus-text-color); + text-decoration: underline var(--focus-underline-color); + } +} + +.state-pressed { + igc-icon { + color: var(--pressed-icon-color); + } + + a { + color: var(--pressed-text-color); + } +} + +.state-focused-hover { + igc-icon { + color: var(--focus-hover-icon-color); + } + + a { + color: var(--focus-hover-text-color); + text-decoration: underline var(--focus-hover-underline-color); + } +} + +.state-focused-pressed { + igc-icon { + color: var(--focus-pressed-icon-color); + } + + a { + color: var(--focus-pressed-text-color); + text-decoration: underline var(--focus-pressed-underline-color); + } +} + +.state-disabled { + igc-icon { + color: var(--disabled-icon-color); + } + + a { + color: var(--disabled-text-color); + } +} + +span { + color: #7d8a96; + font-size: 0.875rem; + margin-block-end: 1rem; + font-family: "Aktiv Grotesk", sans-serif; +} + +nav { + display: grid; + column-gap: 3rem; + row-gap: 1rem; +} + +igc-breadcrumbs { + flex-direction: column; + height: fit-content; +} + +igc-breadcrumbs:nth-of-type(-n+3) { + grid-row: 1; +} + +igc-breadcrumbs:nth-of-type(n+4) { + grid-row: 2; +} + +@media (width < 510px) { + :host { + max-height: unset; + } + + igc-breadcrumbs:nth-of-type(-n+3), + igc-breadcrumbs:nth-of-type(n+4) { + grid-row: unset; + } + + nav { + row-gap: 3rem; + } +} diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.ts new file mode 100644 index 0000000000..c44fa99701 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-states/breadcrumbs-states.component.ts @@ -0,0 +1,19 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, IgcIconComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent, IgcIconComponent); + +const homeIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('home', homeIcon); +} + +@Component({ + selector: 'app-breadcrumbs-states', + styleUrls: ['./breadcrumbs-states.component.scss'], + templateUrl: './breadcrumbs-states.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BreadcrumbsStatesComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.html new file mode 100644 index 0000000000..7d308f0df8 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.html @@ -0,0 +1,12 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.scss new file mode 100644 index 0000000000..af00e1bad9 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.scss @@ -0,0 +1,27 @@ +igc-breadcrumbs { + --ig-breadcrumb-text-color: var(--ig-gray-900); + --ig-breadcrumb-icon-color: #8b5bb1; + --ig-breadcrumb-hover-text-color: var(--ig-gray-900); + --ig-breadcrumb-hover-icon-color: #8b5bb1; + --ig-breadcrumb-focus-text-color: var(--ig-gray-900); + --ig-breadcrumb-focus-icon-color: #8b5bb1; + --ig-breadcrumb-current-text-color: #8b5bb1; + --ig-breadcrumb-separator-color: #8b5bb1; + --ig-breadcrumb-focus-pressed-text-color: var(--ig-gray-900); + --ig-breadcrumb-focus-pressed-icon-color: #8b5bb1; + --ig-size: var(--ig-size-medium); +} + +:host { + display: flex; + justify-content: center; + height: 100%; + overflow: auto; + align-items: center; +} + +@layer base { + a { + color: revert-layer; + } +} \ No newline at end of file diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.ts new file mode 100644 index 0000000000..63f37484b1 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component.ts @@ -0,0 +1,22 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, IgcIconComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent, IgcIconComponent); + +const musicNoteIcon = + ''; +const homeIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('music_note', musicNoteIcon); + registerIconFromText('home', homeIcon); +} + +@Component({ + selector: 'app-breadcrumbs-styling', + styleUrls: ['./breadcrumbs-styling.component.scss'], + templateUrl: './breadcrumbs-styling.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BreadcrumbsStylingComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.html new file mode 100644 index 0000000000..3c36b5168a --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.html @@ -0,0 +1,10 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.scss new file mode 100644 index 0000000000..6831fe4713 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.scss @@ -0,0 +1,17 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + align-items: center; + overflow: auto; +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); +} + +@layer base { + a { + color: revert-layer; + } +} diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.ts new file mode 100644 index 0000000000..e4ddb5bb03 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component.ts @@ -0,0 +1,19 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent, registerIconFromText } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent); + +const slashIcon = + ''; + +if (typeof window !== 'undefined') { + registerIconFromText('slash', slashIcon); +} + +@Component({ + selector: 'app-breadcrumbs-tailwind-styling', + styleUrls: ['./breadcrumbs-tailwind-styling.component.scss'], + templateUrl: './breadcrumbs-tailwind-styling.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BreadcrumbsTailwindStylingComponent { } diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.html b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.html new file mode 100644 index 0000000000..1d7e826f1e --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.html @@ -0,0 +1,16 @@ + diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.scss b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.scss new file mode 100644 index 0000000000..a588c8709d --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.scss @@ -0,0 +1,19 @@ +:host { + display: flex; + justify-content: center; + height: 100%; + overflow: auto; + align-items: center; +} + +igc-breadcrumbs { + --ig-size: var(--ig-size-medium); + + max-width: 16rem; +} + +@layer base { + a { + color: revert-layer; + } +} \ No newline at end of file diff --git a/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.ts b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.ts new file mode 100644 index 0000000000..5093c8e4b7 --- /dev/null +++ b/src/app/layouts/breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component.ts @@ -0,0 +1,12 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { defineComponents, IgcBreadcrumbComponent, IgcBreadcrumbsComponent } from 'igniteui-webcomponents'; + +defineComponents(IgcBreadcrumbsComponent, IgcBreadcrumbComponent); + +@Component({ + selector: 'app-breadcrumbs-wrapping', + styleUrls: ['./breadcrumbs-wrapping.component.scss'], + templateUrl: './breadcrumbs-wrapping.component.html', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BreadcrumbsWrappingComponent { } diff --git a/src/app/layouts/carousel/carousel-animations-sample/carousel-animations-sample.component.ts b/src/app/layouts/carousel/carousel-animations-sample/carousel-animations-sample.component.ts index a2cb7bf53a..d72d86cea0 100644 --- a/src/app/layouts/carousel/carousel-animations-sample/carousel-animations-sample.component.ts +++ b/src/app/layouts/carousel/carousel-animations-sample/carousel-animations-sample.component.ts @@ -10,6 +10,7 @@ import { TitleCasePipe } from '@angular/common'; @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel-animations-sample.component.scss'], templateUrl: './carousel-animations-sample.component.html', imports: [IgxSelectComponent, IgxSwitchComponent, FormsModule, IgxSelectItemComponent, IgxCarouselComponent, IgxSlideComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxCardMediaDirective, IgxCardActionsComponent, IgxButtonDirective, IgxPrefixDirective, TitleCasePipe] diff --git a/src/app/layouts/carousel/carousel-animations/carousel-animations.component.html b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.html new file mode 100644 index 0000000000..d5b66b7f15 --- /dev/null +++ b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.html @@ -0,0 +1,31 @@ + diff --git a/src/app/layouts/carousel/carousel-animations/carousel-animations.component.scss b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.scss new file mode 100644 index 0000000000..ae1d7379c7 --- /dev/null +++ b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.scss @@ -0,0 +1,123 @@ +.carousel-wrapper { + display: flex; + width: min(860px, calc(100% - 32px)); + flex-direction: column; + gap: 16px; + margin: 16px auto 0; +} + +.action-wrapper { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 24px; +} + +.action { display: flex; align-items: center; gap: 8px; } +.action-label { color: var(--ig-gray-700); } + +igx-select { + width: 150px; + --ig-size: 1; +} + +:host ::ng-deep igx-select igx-input-group { --size: 2rem; } + +igx-switch { --ig-size: var(--ig-size-small); } + +igx-carousel { + height: 360px; + overflow: hidden; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: var(--ig-surface-500); +} + +:host ::ng-deep igx-carousel .igx-carousel__arrow--prev, +:host ::ng-deep igx-carousel .igx-carousel__arrow--next { + transition: opacity 120ms ease-in-out; +} + +:host ::ng-deep igx-carousel.is-orientation-changing .igx-carousel__arrow--prev, +:host ::ng-deep igx-carousel.is-orientation-changing .igx-carousel__arrow--next { + opacity: 0; + pointer-events: none; +} + +:host ::ng-deep .igx-slide { + height: 100%; +} + +.slide-wrapper { + position: relative; + display: grid; + box-sizing: border-box; + width: 100%; + height: 100%; + margin: 0; + padding: 56px 84px; + overflow: hidden; + place-items: center; + background: + linear-gradient(135deg, color-mix(in srgb, var(--ig-primary-500) 8%, transparent), transparent 46%), + linear-gradient(315deg, color-mix(in srgb, var(--ig-secondary-500) 10%, transparent), transparent 42%), + var(--ig-gray-100); +} + +.slide-content { width: min(460px, calc(100% - 128px)); max-width: 460px; color: var(--ig-gray-900); } + +.slide-label { + display: block; + margin-bottom: 12px; + color: var(--ig-primary-500); + font-size: 12px; + font-weight: 700; +} + +.slide-content h3 { margin: 0; font-size: 32px; line-height: 1.15; } +.slide-content p { margin: 12px 0 0; color: var(--ig-gray-700); font-size: 18px; line-height: 1.45; } + +.slide-details { + display: inline-flex; + align-items: center; + gap: 16px; + margin-top: 28px; + padding: 10px 14px; + border: 1px solid var(--ig-gray-300); + border-radius: 999px; + background: color-mix(in srgb, var(--ig-surface-500) 72%, transparent); +} + +.slide-details span { color: var(--ig-gray-700); } +.slide-details strong { color: var(--ig-gray-900); } + +.slide-preview { + position: absolute; + top: 50%; + right: 84px; + display: grid; + width: 120px; + height: 220px; + grid-template-columns: repeat(3, 1fr); + align-items: center; + gap: 14px; + transform: translateY(-50%); +} + +.slide-preview span { + display: block; + border-radius: 8px; + background: color-mix(in srgb, var(--ig-primary-500) 20%, transparent); + box-shadow: 0 10px 24px rgb(0 0 0 / 0.12); +} + +.slide-preview span:nth-child(1) { height: 120px; opacity: 0.55; } +.slide-preview span:nth-child(2) { height: 180px; background: var(--ig-primary-300); } +.slide-preview span:nth-child(3) { height: 92px; opacity: 0.75; } + +@media (max-width: 640px) { + .action-wrapper { align-items: flex-start; flex-direction: column; gap: 12px; } + .slide-wrapper { grid-template-columns: 1fr; gap: 28px; padding: 32px 64px; } + .slide-preview { position: static; width: 100%; height: 120px; transform: none; } + .slide-content h3 { font-size: 28px; } +} diff --git a/src/app/layouts/carousel/carousel-animations/carousel-animations.component.ts b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.ts new file mode 100644 index 0000000000..58cc861215 --- /dev/null +++ b/src/app/layouts/carousel/carousel-animations/carousel-animations.component.ts @@ -0,0 +1,73 @@ +import { ChangeDetectorRef, Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { CarouselAnimationType, IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carousel'; +import { IgxSelectComponent, IgxSelectItemComponent } from 'igniteui-angular/select'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-carousel-animations', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-animations.component.scss'], + templateUrl: './carousel-animations.component.html', + imports: [ + FormsModule, + IgxCarouselComponent, + IgxSelectComponent, + IgxSelectItemComponent, + IgxSlideComponent, + IgxSwitchComponent + ] +}) +export class CarouselAnimationsComponent { + public animationType: CarouselAnimationType = CarouselAnimationType.slide; + public isCarouselVertical = false; + public isOrientationChanging = false; + private orientationTimer?: ReturnType; + public readonly animationTypes = [ + { label: 'Slide', value: CarouselAnimationType.slide }, + { label: 'Fade', value: CarouselAnimationType.fade }, + { label: 'None', value: CarouselAnimationType.none } + ]; + public readonly slides = [ + { + detail: 'Best for sequential browsing', + label: '01', + metric: '320ms', + subtitle: 'Moves content horizontally or vertically to preserve directional context.', + title: 'Slide transition' + }, + { + detail: 'Best for featured content', + label: '02', + metric: '240ms', + subtitle: 'Cross-fades between slides when the relationship between items is looser.', + title: 'Fade transition' + }, + { + detail: 'Best for direct state changes', + label: '03', + metric: '0ms', + subtitle: 'Updates the active slide immediately for reduced motion or dense workflows.', + title: 'No transition' + } + ]; + + constructor(private cdr: ChangeDetectorRef) {} + + public changeOrientation(isVertical: boolean): void { + if (this.orientationTimer !== undefined) { + clearTimeout(this.orientationTimer); + } + + this.isOrientationChanging = true; + this.cdr.detectChanges(); + this.orientationTimer = setTimeout(() => { + this.isCarouselVertical = isVertical; + this.cdr.detectChanges(); + this.orientationTimer = setTimeout(() => { + this.isOrientationChanging = false; + this.cdr.detectChanges(); + }, 16); + }, 120); + } +} diff --git a/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.html b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.html new file mode 100644 index 0000000000..3c039fdf9e --- /dev/null +++ b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.html @@ -0,0 +1,73 @@ + diff --git a/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.scss b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.scss new file mode 100644 index 0000000000..e433a4f155 --- /dev/null +++ b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.scss @@ -0,0 +1,220 @@ +.carousel-container { + width: min(760px, 100%); + margin: 16px auto 0; +} + +igx-carousel { + height: 440px; + overflow: hidden; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: var(--ig-surface-500); +} + +:host ::ng-deep { + .igx-carousel__nav-button { + width: 40px; + height: 40px; + } + + .igx-slide { + display: grid; + box-sizing: border-box; + height: 100%; + padding-bottom: 48px; + place-items: center; + } + + .igx-slide.slide-frame { + background: var(--ig-gray-100); + } + + .igx-slide.slide-coast { + background: + linear-gradient(135deg, color-mix(in srgb, var(--ig-primary-500) 12%, transparent), transparent 45%), + var(--ig-gray-100); + } + + .igx-slide.slide-city { + background: + linear-gradient(135deg, color-mix(in srgb, var(--ig-secondary-500) 12%, transparent), transparent 45%), + var(--ig-gray-100); + } + + .igx-slide.slide-resort { + padding-bottom: 76px; + background: + linear-gradient(135deg, color-mix(in srgb, var(--ig-success-500) 12%, transparent), transparent 45%), + var(--ig-gray-100); + } +} + +.slide-shell { + display: grid; + width: fit-content; + height: auto; + grid-template-columns: minmax(0, 390px) 120px; + align-items: center; + justify-content: center; + gap: 28px; + margin: 0 auto; + padding: 24px 0; +} + +.feature-card { + display: grid; + gap: 14px; + padding: 22px 24px; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: color-mix(in srgb, var(--ig-surface-500) 86%, transparent); + box-shadow: 0 14px 34px rgb(0 0 0 / 0.14); +} + +.slide-label { + color: var(--ig-primary-500); + font-size: 12px; + font-weight: 700; +} + +.feature-copy { + display: grid; + gap: 8px; +} + +.feature-copy h3 { + margin: 0; + color: var(--ig-gray-900); + font-size: 24px; + line-height: 1.2; +} + +.feature-copy p { + margin: 0 0 8px; + color: var(--ig-gray-700); + line-height: 1.45; +} + +.feature-card button { + justify-self: start; +} + +.chip-row { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.chip-row span { + padding: 6px 10px; + border: 1px solid var(--ig-gray-300); + border-radius: 999px; + color: var(--ig-gray-700); + background: var(--ig-surface-500); + font-size: 14px; +} + +.route-visual { + display: grid; + width: 120px; + height: 180px; + grid-template-columns: repeat(3, 1fr); + align-items: end; + gap: 8px; +} + +.route-visual span, +.ticket, +.amenity-visual span { + display: block; + border-radius: 8px; + background: color-mix(in srgb, var(--ig-surface-500) 72%, transparent); + box-shadow: 0 10px 24px rgb(0 0 0 / 0.12); +} + +.route-visual span:nth-child(1) { height: 46%; opacity: 0.75; } +.route-visual span:nth-child(2) { height: 82%; } +.route-visual span:nth-child(3) { height: 62%; opacity: 0.9; } + +.event-card { gap: 10px; padding: 18px 22px; } + +.event-summary { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: var(--ig-surface-500); +} + +.event-date { + display: grid; + width: 46px; + padding: 4px 0; + place-items: center; + border-radius: 6px; + color: var(--ig-primary-500); + background: color-mix(in srgb, var(--ig-primary-500) 16%, transparent); + font-size: 10px; + font-weight: 700; + line-height: 1.1; +} + +.event-date strong { color: var(--ig-gray-900); font-size: 22px; } + +.event-details { display: grid; gap: 3px; color: var(--ig-gray-700); font-size: 14px; } +.event-details strong { color: var(--ig-gray-900); font-size: 15px; } + +.event-visual { position: relative; width: 120px; height: 180px; } + +.ticket-stack { + position: absolute; + top: 10px; + left: 20px; + width: 96px; + height: 144px; +} + +.ticket { position: absolute; display: grid; width: 96px; height: 144px; border-radius: 10px; box-sizing: content-box; } +.ticket--back { top: 12px; left: -20px; opacity: 0.56; transform: rotate(-8deg); } + +.ticket--front { + inset: 0; + grid-template-rows: 1fr auto 1fr; + padding: 18px; + transform: rotate(5deg); +} + +.ticket--front span { display: block; height: 8px; border-radius: 999px; background: var(--ig-primary-300); } +.ticket--front span:nth-child(2) { width: 72%; background: var(--ig-primary-500); } +.ticket--front span:nth-child(3) { align-self: end; width: 54%; background: var(--ig-gray-300); } + +.offer-summary { display: grid; gap: 4px; color: var(--ig-gray-700); font-size: 14px; } +.offer-card { gap: 8px; padding: 16px 22px; } +.offer-summary > div { display: flex; align-items: baseline; justify-content: space-between; } +.offer-summary strong { color: var(--ig-gray-900); font-size: 24px; } + +.addon-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 9px 12px; + border-radius: 8px; + color: var(--ig-gray-700); + background: var(--ig-gray-100); + font-size: 14px; +} + +.addon-row strong { color: var(--ig-gray-900); } + +.amenity-visual { display: grid; width: 120px; height: 180px; align-content: center; gap: 12px; } +.amenity-visual span { height: 44px; border-radius: 12px; } +.amenity-visual span:nth-child(1) { width: 78%; } +.amenity-visual span:nth-child(2) { width: 100%; background: color-mix(in srgb, var(--ig-surface-500) 90%, transparent); } +.amenity-visual span:nth-child(3) { width: 62%; justify-self: end; } + +@media (max-width: 720px) { + .slide-shell { grid-template-columns: 1fr; padding: 32px 64px; } + .feature-visual, .event-visual, .amenity-visual { display: none; } +} diff --git a/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.ts b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.ts new file mode 100644 index 0000000000..2d3b7087df --- /dev/null +++ b/src/app/layouts/carousel/carousel-components-sample/carousel-components-sample.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carousel'; +import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxInputDirective, IgxInputGroupComponent, IgxPrefixDirective } from 'igniteui-angular/input-group'; + +@Component({ + selector: 'app-carousel-components-sample', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-components-sample.component.scss'], + templateUrl: './carousel-components-sample.component.html', + imports: [ + IgxButtonDirective, + IgxCarouselComponent, + IgxCheckboxComponent, + IgxIconComponent, + IgxInputDirective, + IgxInputGroupComponent, + IgxPrefixDirective, + IgxSlideComponent + ] +}) +export class CarouselComponentsSampleComponent { } diff --git a/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.html b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.html new file mode 100644 index 0000000000..d756d02d6c --- /dev/null +++ b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.html @@ -0,0 +1,19 @@ +
+
+ Hide navigation + Hide indicators + Disable loop +
+ + + +
01

Coastal route

A compact visual slide for checking navigation and indicators.

+
+ +
02

City guide

A second slide makes loop behavior easy to verify.

+
+ +
03

Resort access

Use the controls to compare the Carousel configuration states.

+
+
+
diff --git a/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.scss b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.scss new file mode 100644 index 0000000000..efa53232c0 --- /dev/null +++ b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.scss @@ -0,0 +1,60 @@ +.configuration-sample { + display: grid; + width: min(860px, calc(100% - 32px)); + gap: 16px; + margin: 16px auto 0; +} + +.configuration-controls { + display: grid; + grid-template-columns: repeat(3, max-content); + align-items: center; + justify-content: end; + gap: 16px; +} + +igx-switch { --ig-size: var(--ig-size-small); } + +igx-carousel { + height: 340px; + overflow: hidden; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: var(--ig-surface-500); +} + +:host ::ng-deep { + .igx-carousel__arrow { width: 40px; height: 40px; } + .igx-carousel__arrow--prev { left: 16px; } + .igx-carousel__arrow--next { right: 16px; } + .igx-slide { + display: grid; + height: 100%; + place-items: center; + background: + linear-gradient(135deg, color-mix(in srgb, var(--ig-primary-500) 12%, transparent), transparent 42%), + linear-gradient(315deg, color-mix(in srgb, var(--ig-secondary-500) 12%, transparent), transparent 42%), + var(--ig-gray-100); + } +} + +.slide-card { + display: grid; + width: min(420px, 100%); + gap: 10px; + margin: 0; + padding: 28px; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + color: var(--ig-gray-900); + background: color-mix(in srgb, var(--ig-surface-500) 88%, transparent); + box-shadow: 0 14px 34px rgb(0 0 0 / 0.14); +} + +.slide-card span { color: var(--ig-primary-500); font-size: 12px; font-weight: 700; } +.slide-card h3 { margin: 0; font-size: 28px; line-height: 1.2; } +.slide-card p { margin: 0; color: var(--ig-gray-700); line-height: 1.45; } + +@media (max-width: 760px) { + .configuration-controls { grid-template-columns: repeat(2, minmax(0, 1fr)); justify-content: stretch; } +} diff --git a/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.ts b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.ts new file mode 100644 index 0000000000..8efa83ff30 --- /dev/null +++ b/src/app/layouts/carousel/carousel-configuration-sample/carousel-configuration-sample.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carousel'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; + +@Component({ + selector: 'app-carousel-configuration-sample', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-configuration-sample.component.scss'], + templateUrl: './carousel-configuration-sample.component.html', + imports: [FormsModule, IgxCarouselComponent, IgxSlideComponent, IgxSwitchComponent] +}) +export class CarouselConfigurationSampleComponent { + public hideNavigation = false; + public hideIndicators = false; + public disableLoop = false; +} diff --git a/src/app/layouts/carousel/carousel-no-navigation-sample/carousel-no-navigation-sample.component.ts b/src/app/layouts/carousel/carousel-no-navigation-sample/carousel-no-navigation-sample.component.ts index e848ec5553..2c668d09ab 100644 --- a/src/app/layouts/carousel/carousel-no-navigation-sample/carousel-no-navigation-sample.component.ts +++ b/src/app/layouts/carousel/carousel-no-navigation-sample/carousel-no-navigation-sample.component.ts @@ -5,6 +5,7 @@ import { NgStyle, NgClass, CurrencyPipe } from '@angular/common'; @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel-no-navigation-sample.component.scss'], templateUrl: './carousel-no-navigation-sample.component.html', imports: [IgxCarouselComponent, IgxSlideComponent, NgStyle, NgClass, IgxListComponent, IgxListItemComponent, IgxListThumbnailDirective, CurrencyPipe] diff --git a/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.html b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.html new file mode 100644 index 0000000000..64d7356dbe --- /dev/null +++ b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.html @@ -0,0 +1,11 @@ + diff --git a/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.scss b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.scss new file mode 100644 index 0000000000..27bc6d9e87 --- /dev/null +++ b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.scss @@ -0,0 +1,30 @@ +.carousel-container { + padding: 16px; +} + +.image-container { + display: flex; + height: 100%; + align-items: center; + justify-content: center; +} + +igx-carousel { + height: 450px; + margin-inline: auto; + max-width: 75%; +} + +img { + max-height: 90%; + max-width: 90%; + object-fit: contain; +} + +:host ::ng-deep .igx-slide { + display: flex; + justify-content: center; + align-items: center; + max-width: 75%; + margin-inline: auto; +} diff --git a/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.ts b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.ts new file mode 100644 index 0000000000..14edb3d44e --- /dev/null +++ b/src/app/layouts/carousel/carousel-overview-sample/carousel-overview-sample.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carousel'; + +@Component({ + selector: 'app-carousel-overview-sample', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-overview-sample.component.scss'], + templateUrl: './carousel-overview-sample.component.html', + imports: [IgxCarouselComponent, IgxSlideComponent] +}) +export class CarouselOverviewSampleComponent { + public readonly slides = [ + { + alt: 'Ignite UI Angular Indigo Design', + src: 'https://dl.infragistics.com/x/img/carousel/ignite-ui-angular-indigo-design.png' + }, + { + alt: 'Chart preview', + src: 'https://dl.infragistics.com/x/img/carousel/slider-image-chart.png' + }, + { + alt: 'Ignite UI Angular Charts', + src: 'https://dl.infragistics.com/x/img/carousel/ignite-ui-angular-charts.png' + } + ]; +} diff --git a/src/app/layouts/carousel/carousel-styling-sample/carousel-styling-sample.component.ts b/src/app/layouts/carousel/carousel-styling-sample/carousel-styling-sample.component.ts index b8c53cf230..e6de4c43a3 100644 --- a/src/app/layouts/carousel/carousel-styling-sample/carousel-styling-sample.component.ts +++ b/src/app/layouts/carousel/carousel-styling-sample/carousel-styling-sample.component.ts @@ -3,6 +3,7 @@ import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carous @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel-styling-sample.component.scss'], templateUrl: './carousel-styling-sample.component.html', imports: [IgxCarouselComponent, IgxSlideComponent] diff --git a/src/app/layouts/carousel/carousel-styling/carousel-styling.component.html b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.html new file mode 100644 index 0000000000..f09b81c5d5 --- /dev/null +++ b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.html @@ -0,0 +1,26 @@ +
+ + + chevron_left + + + chevron_right + + + + + + @for (slide of slides; track slide.image) { + +
+ +
+ {{ slide.label }} +

{{ slide.title }}

+

{{ slide.subtitle }}

+
+
+
+ } +
+
diff --git a/src/app/layouts/carousel/carousel-styling/carousel-styling.component.scss b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.scss new file mode 100644 index 0000000000..af21c4ba17 --- /dev/null +++ b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.scss @@ -0,0 +1,111 @@ +:host { + display: block; + width: 100%; +} + +.container { + width: min(860px, calc(100% - 32px)); + margin: 16px auto 0; +} + +.styled-carousel { + width: 100%; + height: 430px; + margin: 0; + overflow: hidden; + border: 1px solid var(--ig-gray-300); + border-radius: 8px; + background: var(--ig-surface-500); +} + +:host ::ng-deep { + .styled-carousel .igx-carousel-indicators { + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.82); + box-shadow: 0 6px 16px rgba(11, 31, 53, 0.16); + } + + .styled-carousel .igx-carousel__arrow { + display: grid; + width: 40px; + height: 40px; + place-items: center; + border: 0; + border-radius: 50%; + color: var(--ig-gray-800); + background: rgba(255, 255, 255, 0.88); + box-shadow: 0 6px 16px rgba(11, 31, 53, 0.22); + } + + .styled-carousel .igx-slide { + height: 100%; + } +} + +.carousel-navigation-button { + display: inline-grid; + width: 20px; + height: 20px; + place-items: center; + line-height: 1; +} + +.carousel-navigation-button igx-icon { + width: 20px; + height: 20px; + color: inherit; +} + +.carousel-indicator { + display: block; + width: 9px; + height: 9px; + border: 2px solid var(--ig-gray-600); + border-radius: 50%; + background: transparent; +} + +.carousel-indicator-active { + border-color: var(--ig-primary-500); + background: var(--ig-primary-500); +} + +.slide-card { + position: relative; + display: grid; + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; +} + +.slide-image { + width: 100%; + height: 100%; + object-fit: cover; +} + +.slide-content { + position: absolute; + inset: auto 56px 44px 56px; + max-width: 380px; + padding: 20px 24px; + border-radius: 8px; + color: var(--ig-gray-900); + background: rgba(255, 255, 255, 0.88); + box-shadow: 0 14px 34px rgba(11, 31, 53, 0.18); +} + +.slide-label { + display: block; + margin-bottom: 8px; + color: var(--ig-primary-600); + font-size: 12px; + font-weight: 700; + letter-spacing: 0; +} + +.slide-content h3 { margin: 0; font-size: 24px; line-height: 1.2; } +.slide-content p { margin: 8px 0 0; color: var(--ig-gray-700); line-height: 1.45; } diff --git a/src/app/layouts/carousel/carousel-styling/carousel-styling.component.ts b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.ts new file mode 100644 index 0000000000..9aa540ec58 --- /dev/null +++ b/src/app/layouts/carousel/carousel-styling/carousel-styling.component.ts @@ -0,0 +1,49 @@ +import { Component } from '@angular/core'; +import { + IgxCarouselComponent, + IgxCarouselIndicatorDirective, + IgxCarouselNextButtonDirective, + IgxCarouselPrevButtonDirective, + IgxSlideComponent +} from 'igniteui-angular/carousel'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-carousel-styling', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-styling.component.scss'], + templateUrl: './carousel-styling.component.html', + imports: [ + IgxCarouselComponent, + IgxCarouselIndicatorDirective, + IgxCarouselNextButtonDirective, + IgxCarouselPrevButtonDirective, + IgxIconComponent, + IgxSlideComponent + ] +}) +export class CarouselStylingComponent { + public readonly slides = [ + { + alt: 'Wonderful coast', + image: 'https://dl.infragistics.com/x/img/carousel/WonderfulCoast.png', + label: '01', + subtitle: 'A quiet route along cliffs, beach towns, and open water.', + title: 'Coastal retreat' + }, + { + alt: 'Cultural district', + image: 'https://dl.infragistics.com/x/img/carousel/CulturalDip.png', + label: '02', + subtitle: 'Museums, galleries, and historic streets in one walkable plan.', + title: 'Cultural district' + }, + { + alt: 'Golden beaches', + image: 'https://dl.infragistics.com/x/img/carousel/GoldenBeaches.png', + label: '03', + subtitle: 'A sunny itinerary built around swimming, dining, and sunsets.', + title: 'Golden beaches' + } + ]; +} diff --git a/src/app/layouts/carousel/carousel-tailwind-sample/carousel-tailwind-sample.component.ts b/src/app/layouts/carousel/carousel-tailwind-sample/carousel-tailwind-sample.component.ts index 58903f63e3..0ecc12ef85 100644 --- a/src/app/layouts/carousel/carousel-tailwind-sample/carousel-tailwind-sample.component.ts +++ b/src/app/layouts/carousel/carousel-tailwind-sample/carousel-tailwind-sample.component.ts @@ -3,6 +3,7 @@ import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carous @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel-tailwind-sample.component.scss'], templateUrl: './carousel-tailwind-sample.component.html', imports: [IgxCarouselComponent, IgxSlideComponent] diff --git a/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.html b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.html new file mode 100644 index 0000000000..2de32eeb75 --- /dev/null +++ b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.html @@ -0,0 +1,39 @@ +
+ + + chevron_left + + + chevron_right + + + + + + @for (slide of slides; track slide.image) { + +
+ +
+
+ {{ slide.label }} / ITINERARY +

{{ slide.title }}

+

{{ slide.subtitle }}

+
+
+ @for (detail of slide.details; track detail) { + {{ detail }} + } +
+
+ @for (tag of slide.tags; track tag) { + {{ tag }} + } +
+ +
+
+
+ } +
+
diff --git a/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.scss b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.scss new file mode 100644 index 0000000000..d6f1d8e69a --- /dev/null +++ b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.scss @@ -0,0 +1,60 @@ +:host { + display: block; + width: 100%; +} + +.container { + width: min(960px, calc(100% - 32px)); + margin: 16px auto 0; +} + +.styled-carousel { + width: 100%; + height: 430px; + margin: 0; +} +:host ::ng-deep { + .styled-carousel .igx-carousel-indicators { + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.82); + box-shadow: 0 6px 16px rgba(11, 31, 53, 0.16); + } + + .styled-carousel .igx-carousel__arrow { + display: grid; + width: 40px; + height: 40px; + place-items: center; + border: 0; + border-radius: 50%; + color: var(--ig-gray-800); + background: rgba(255, 255, 255, 0.88); + box-shadow: 0 6px 16px rgba(11, 31, 53, 0.22); + } + + .styled-carousel .igx-slide { + height: 100%; + } +} + +.carousel-navigation-button igx-icon { + width: 20px; + height: 20px; + color: inherit; +} + +.carousel-indicator { + display: block; + width: 9px; + height: 9px; + border: 2px solid var(--ig-gray-600); + border-radius: 50%; + background: transparent; +} + +.carousel-indicator-active { + border-color: var(--ig-primary-500); + background: var(--ig-primary-500); +} diff --git a/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.ts b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.ts new file mode 100644 index 0000000000..c6bba6c3b6 --- /dev/null +++ b/src/app/layouts/carousel/carousel-tailwind-styling/carousel-tailwind-styling.component.ts @@ -0,0 +1,57 @@ +import { Component } from '@angular/core'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { + IgxCarouselComponent, + IgxCarouselIndicatorDirective, + IgxCarouselNextButtonDirective, + IgxCarouselPrevButtonDirective, + IgxSlideComponent +} from 'igniteui-angular/carousel'; +import { IgxIconComponent } from 'igniteui-angular/icon'; + +@Component({ + selector: 'app-carousel-tailwind-styling', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-tailwind-styling.component.scss'], + templateUrl: './carousel-tailwind-styling.component.html', + imports: [ + IgxButtonDirective, + IgxCarouselComponent, + IgxCarouselIndicatorDirective, + IgxCarouselNextButtonDirective, + IgxCarouselPrevButtonDirective, + IgxIconComponent, + IgxSlideComponent + ] +}) +export class CarouselTailwindStylingComponent { + public readonly slides = [ + { + alt: 'Scenic travel destination', + details: ['3 days', '8 stops', 'Flexible dates'], + image: 'https://dl.infragistics.com/x/img/carousel/AdobeStock_1937350575-s.png', + label: '01', + subtitle: 'A flexible travel plan built around memorable views and time to explore.', + tags: ['Scenic route', 'Flexible pace'], + title: 'Scenic getaway' + }, + { + alt: 'Mountain trail ride', + details: ['1 day', '12 km', 'Advanced'], + image: 'https://dl.infragistics.com/x/img/carousel/AdobeStock_215535179-s.png', + label: '02', + subtitle: 'A high-energy route through rugged terrain, with technical descents and open trail views.', + tags: ['Mountain bike', 'Trail ride'], + title: 'Mountain trail ride' + }, + { + alt: 'Weekend escape', + details: ['Weekend', '5 highlights', 'Year round'], + image: 'https://dl.infragistics.com/x/img/carousel/AdobeStock_637533323-s.png', + label: '03', + subtitle: 'A short break with unhurried moments, fresh perspectives, and room to recharge.', + tags: ['Unwind', 'Go at your pace'], + title: 'Weekend escape' + } + ]; +} diff --git a/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.html b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.html new file mode 100644 index 0000000000..dcec596a97 --- /dev/null +++ b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.html @@ -0,0 +1,18 @@ + diff --git a/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.scss b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.scss new file mode 100644 index 0000000000..6847d4f554 --- /dev/null +++ b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.scss @@ -0,0 +1,26 @@ +.carousel-container { + margin: 16px auto 0; +} + +igx-carousel { + height: 420px; + margin-inline: auto; + max-width: 75%; +} + +:host ::ng-deep { + .igx-carousel-indicators { + border-radius: 2px; + } + + .slide-image { + width: 100%; + height: 100%; + object-fit: cover; + } +} + +.blurred { + filter: blur(2px); + opacity: 0.5; +} diff --git a/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.ts b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.ts new file mode 100644 index 0000000000..d3e1316f2e --- /dev/null +++ b/src/app/layouts/carousel/carousel-thumbnail/carousel-thumbnail.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { IgxCarouselComponent, IgxCarouselIndicatorDirective, IgxSlideComponent } from 'igniteui-angular/carousel'; + +@Component({ + selector: 'app-carousel-thumbnail', + host: { class: 'ig-typography' }, + styleUrls: ['./carousel-thumbnail.component.scss'], + templateUrl: './carousel-thumbnail.component.html', + imports: [IgxCarouselComponent, IgxCarouselIndicatorDirective, IgxSlideComponent] +}) +export class CarouselThumbnailComponent { + public readonly slides = [ + { alt: 'Wonderful coast', image: 'assets/images/carousel/WonderfulCoast.png', thumbnail: 'assets/images/carousel/WonderfulCoastThumb.png' }, + { alt: 'Cultural district', image: 'assets/images/carousel/CulturalDip.png', thumbnail: 'assets/images/carousel/CulturalDipThumb.png' }, + { alt: 'Golden beaches', image: 'assets/images/carousel/GoldenBeaches.png', thumbnail: 'assets/images/carousel/GoldenBeachesThumb.png' }, + { alt: 'Island of history', image: 'assets/images/carousel/IslandOfHistory.png', thumbnail: 'assets/images/carousel/IslandOfHistoryThumb.png' }, + { alt: 'Amazing bridge', image: 'assets/images/carousel/AmazingBridge.png', thumbnail: 'assets/images/carousel/AmazingBridgeThumb.png' } + ]; +} diff --git a/src/app/layouts/carousel/carousel-with-components-sample/carousel-with-components-sample.component.ts b/src/app/layouts/carousel/carousel-with-components-sample/carousel-with-components-sample.component.ts index 02c4a0a0a3..536b39deeb 100644 --- a/src/app/layouts/carousel/carousel-with-components-sample/carousel-with-components-sample.component.ts +++ b/src/app/layouts/carousel/carousel-with-components-sample/carousel-with-components-sample.component.ts @@ -7,6 +7,7 @@ import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel-with-components-sample.component.scss'], templateUrl: './carousel-with-components-sample.component.html', imports: [IgxCarouselComponent, IgxSlideComponent, FormsModule, IgxInputGroupComponent, IgxPrefixDirective, IgxIconComponent, IgxLabelDirective, IgxInputDirective, IgxButtonDirective] diff --git a/src/app/layouts/carousel/carousel.component.ts b/src/app/layouts/carousel/carousel.component.ts index 083bbe7709..deda7fa1b6 100644 --- a/src/app/layouts/carousel/carousel.component.ts +++ b/src/app/layouts/carousel/carousel.component.ts @@ -4,6 +4,7 @@ import { IgxCarouselComponent, IgxSlideComponent } from 'igniteui-angular/carous @Component({ selector: 'app-carousel', + host: { class: 'ig-typography' }, styleUrls: ['./carousel.component.scss'], templateUrl: './carousel.component.html', imports: [IgxCarouselComponent, IgxSlideComponent] diff --git a/src/app/layouts/layouts-routes-data.ts b/src/app/layouts/layouts-routes-data.ts index 8890bf4c99..cb49866c68 100644 --- a/src/app/layouts/layouts-routes-data.ts +++ b/src/app/layouts/layouts-routes-data.ts @@ -1,9 +1,15 @@ /* eslint-disable quote-props */ export const layoutsRoutesData = { + 'accordion-customization': { displayName: 'Accordion Customization', parentName: 'Accordion' }, + 'accordion-nested-scenario': { displayName: 'Accordion Nested Scenario', parentName: 'Accordion' }, + 'accordion-overview': { displayName: 'Accordion Overview', parentName: 'Accordion' }, + 'accordion-styling': { displayName: 'Accordion Styling', parentName: 'Accordion' }, + 'accordion-tailwind-styling': { displayName: 'Accordion Tailwind Styling', parentName: 'Accordion' }, 'accordion-sample-1': { displayName: 'Accordion 1', parentName: 'Accordion' }, 'accordion-sample-2': { displayName: 'Accordion 2', parentName: 'Accordion' }, 'accordion-sample-3': { displayName: 'Accordion 3', parentName: 'Accordion' }, + 'accordion-programmatic-expansion': { displayName: 'Accordion Programmatic Expansion', parentName: 'Accordion' }, 'accordion-style': { displayName: 'Accordion Styling', parentName: 'Accordion' }, 'avatar-overview': { displayName: 'Avatar Overview', parentName: 'Avatar' }, 'avatar-variants': { displayName: 'Avatar Variants', parentName: 'Avatar' }, @@ -11,7 +17,22 @@ export const layoutsRoutesData = { 'avatar-size': { displayName: 'Avatar Size', parentName: 'Avatar' }, 'avatar-styling': { displayName: 'Styling avatars', parentName: 'Avatar' }, 'avatar-tailwind-styling': { displayName: 'Styling Avatar with Tailwind', parentName: 'Avatar' }, + 'breadcrumbs-overview': { displayName: 'Breadcrumbs Overview', parentName: 'Breadcrumbs' }, + 'breadcrumbs-custom-separator': { displayName: 'Breadcrumbs Custom Separator', parentName: 'Breadcrumbs' }, + 'breadcrumbs-prefix-suffix': { displayName: 'Breadcrumbs Prefix and Suffix', parentName: 'Breadcrumbs' }, + 'breadcrumbs-styling': { displayName: 'Breadcrumbs Styling', parentName: 'Breadcrumbs' }, + 'breadcrumbs-tailwind-styling': { displayName: 'Breadcrumbs Tailwind Styling', parentName: 'Breadcrumbs' }, + 'breadcrumbs-wrapping': { displayName: 'Breadcrumbs Wrapping', parentName: 'Breadcrumbs' }, + 'breadcrumbs-sizes': { displayName: 'Breadcrumbs Sizes', parentName: 'Breadcrumbs' }, + 'breadcrumbs-states': { displayName: 'Breadcrumbs States', parentName: 'Breadcrumbs' }, 'carousel': { displayName: 'Carousel Base', parentName: 'Carousel' }, + 'carousel-overview-sample': { displayName: 'Carousel Overview', parentName: 'Carousel' }, + 'carousel-configuration-sample': { displayName: 'Carousel Configuration', parentName: 'Carousel' }, + 'carousel-components-sample': { displayName: 'Carousel Components', parentName: 'Carousel' }, + 'carousel-animations': { displayName: 'Carousel Animations', parentName: 'Carousel' }, + 'carousel-thumbnail': { displayName: 'Carousel Thumbnail Indicators', parentName: 'Carousel' }, + 'carousel-styling': { displayName: 'Carousel Styling', parentName: 'Carousel' }, + 'carousel-tailwind-styling': { displayName: 'Carousel Tailwind Styling', parentName: 'Carousel' }, 'carousel-no-navigation-sample': { displayName: 'Carousel No Navigation', parentName: 'Carousel' }, 'carousel-animations-sample': { displayName: 'Carousel Animations', parentName: 'Carousel' }, 'carousel-with-components-sample': { displayName: 'Carousel With Other Components', parentName: 'Carousel' }, diff --git a/src/app/layouts/layouts.routes.ts b/src/app/layouts/layouts.routes.ts index 7385391ce8..ff1087244c 100644 --- a/src/app/layouts/layouts.routes.ts +++ b/src/app/layouts/layouts.routes.ts @@ -6,6 +6,14 @@ import { AvatarShapeComponent } from './avatar/avatar-shape/avatar-shape.compone import { AvatarSizeComponent } from './avatar/avatar-size/avatar-size.component'; import { AvatarStylingSampleComponent } from './avatar/avatar-styling/avatar-styling.component'; import { AvatarTailwindStylingSampleComponent } from './avatar/avatar-tailwind-styling/avatar-tailwind-styling.component'; +import { BreadcrumbsOverviewComponent } from './breadcrumbs/breadcrumbs-overview/breadcrumbs-overview.component'; +import { BreadcrumbsCustomSeparatorComponent } from './breadcrumbs/breadcrumbs-custom-separator/breadcrumbs-custom-separator.component'; +import { BreadcrumbsPrefixSuffixComponent } from './breadcrumbs/breadcrumbs-prefix-suffix/breadcrumbs-prefix-suffix.component'; +import { BreadcrumbsStylingComponent } from './breadcrumbs/breadcrumbs-styling/breadcrumbs-styling.component'; +import { BreadcrumbsTailwindStylingComponent } from './breadcrumbs/breadcrumbs-tailwind-styling/breadcrumbs-tailwind-styling.component'; +import { BreadcrumbsWrappingComponent } from './breadcrumbs/breadcrumbs-wrapping/breadcrumbs-wrapping.component'; +import { BreadcrumbsSizesComponent } from './breadcrumbs/breadcrumbs-sizes/breadcrumbs-sizes.component'; +import { BreadcrumbsStatesComponent } from './breadcrumbs/breadcrumbs-states/breadcrumbs-states.component'; import { CardSample1Component } from './card/card-sample-1/card-sample-1.component'; import { CardSample2Component } from './card/card-sample-2/card-sample-2.component'; import { CardSample3Component } from './card/card-sample-3/card-sample-3.component'; @@ -28,6 +36,27 @@ import { import { CarouselStylingSampleComponent } from './carousel/carousel-styling-sample/carousel-styling-sample.component'; +import { + CarouselOverviewSampleComponent +} from './carousel/carousel-overview-sample/carousel-overview-sample.component'; +import { + CarouselConfigurationSampleComponent +} from './carousel/carousel-configuration-sample/carousel-configuration-sample.component'; +import { + CarouselComponentsSampleComponent +} from './carousel/carousel-components-sample/carousel-components-sample.component'; +import { + CarouselAnimationsComponent +} from './carousel/carousel-animations/carousel-animations.component'; +import { + CarouselThumbnailComponent +} from './carousel/carousel-thumbnail/carousel-thumbnail.component'; +import { + CarouselStylingComponent +} from './carousel/carousel-styling/carousel-styling.component'; +import { + CarouselTailwindStylingComponent +} from './carousel/carousel-tailwind-styling/carousel-tailwind-styling.component'; import { CarouselComponent } from './carousel/carousel.component'; import { DividerDashedComponent } from './divider/dashed/divider-dashed.component'; import { DividerDefaultComponent } from './divider/default/divider-default.component'; @@ -77,8 +106,14 @@ import { View1Component } from './tabs/views/view1/view1.component'; import { View2Component } from './tabs/views/view2/view2.component'; import { View3Component } from './tabs/views/view3/view3.component'; import { AccordionSample1Component } from './accordion/accordion-sample-1/accordion-sample-1.component'; +import { AccordionCustomizationComponent } from './accordion/accordion-customization/accordion-customization.component'; +import { AccordionNestedScenarioComponent } from './accordion/accordion-nested-scenario/accordion-nested-scenario.component'; +import { AccordionOverviewComponent } from './accordion/accordion-overview/accordion-overview.component'; +import { AccordionStylingComponent } from './accordion/accordion-styling/accordion-styling.component'; +import { AccordionTailwindStylingComponent } from './accordion/accordion-tailwind-styling/accordion-tailwind-styling.component'; import { AccordionSample2Component } from './accordion/accordion-sample-2/accordion-sample-2.component'; import { AccordionSample3Component } from './accordion/accordion-sample-3/accordion-sample-3.component'; +import { AccordionProgrammaticExpansionComponent } from './accordion/accordion-programmatic-expansion/accordion-programmatic-expansion.component'; import { AccordionStyleComponent } from './accordion/accordion-style/accordion-style.component'; import {StepperLabelPositionAndOrientationSampleComponent } from './stepper/stepper-label-position-and-orientation-sample/stepper-label-position-and-orientation-sample.component'; @@ -91,6 +126,31 @@ import { StepperSampleReactiveFormsComponent } from './stepper/stepper-sample-re import { TileManagerComponent } from './tile-manager/tile-manager-sample/tile-manager.component'; export const LayoutsRoutes: Routes = [ + { + component: AccordionOverviewComponent, + data: layoutsRoutesData['accordion-overview'], + path: 'accordion-overview' + }, + { + component: AccordionCustomizationComponent, + data: layoutsRoutesData['accordion-customization'], + path: 'accordion-customization' + }, + { + component: AccordionNestedScenarioComponent, + data: layoutsRoutesData['accordion-nested-scenario'], + path: 'accordion-nested-scenario' + }, + { + component: AccordionStylingComponent, + data: layoutsRoutesData['accordion-styling'], + path: 'accordion-styling' + }, + { + component: AccordionTailwindStylingComponent, + data: layoutsRoutesData['accordion-tailwind-styling'], + path: 'accordion-tailwind-styling' + }, { component: AccordionSample1Component, data: layoutsRoutesData['accordion-sample-1'], @@ -106,6 +166,11 @@ export const LayoutsRoutes: Routes = [ data: layoutsRoutesData['accordion-sample-3'], path: 'accordion-sample-3' }, + { + component: AccordionProgrammaticExpansionComponent, + data: layoutsRoutesData['accordion-programmatic-expansion'], + path: 'accordion-programmatic-expansion' + }, { component: AccordionStyleComponent, data: layoutsRoutesData['accordion-style'], @@ -141,6 +206,46 @@ export const LayoutsRoutes: Routes = [ data: layoutsRoutesData['avatar-tailwind-styling'], path: 'avatar-tailwind-styling' }, + { + component: BreadcrumbsOverviewComponent, + data: layoutsRoutesData['breadcrumbs-overview'], + path: 'breadcrumbs-overview' + }, + { + component: BreadcrumbsCustomSeparatorComponent, + data: layoutsRoutesData['breadcrumbs-custom-separator'], + path: 'breadcrumbs-custom-separator' + }, + { + component: BreadcrumbsPrefixSuffixComponent, + data: layoutsRoutesData['breadcrumbs-prefix-suffix'], + path: 'breadcrumbs-prefix-suffix' + }, + { + component: BreadcrumbsStylingComponent, + data: layoutsRoutesData['breadcrumbs-styling'], + path: 'breadcrumbs-styling' + }, + { + component: BreadcrumbsTailwindStylingComponent, + data: layoutsRoutesData['breadcrumbs-tailwind-styling'], + path: 'breadcrumbs-tailwind-styling' + }, + { + component: BreadcrumbsWrappingComponent, + data: layoutsRoutesData['breadcrumbs-wrapping'], + path: 'breadcrumbs-wrapping' + }, + { + component: BreadcrumbsSizesComponent, + data: layoutsRoutesData['breadcrumbs-sizes'], + path: 'breadcrumbs-sizes' + }, + { + component: BreadcrumbsStatesComponent, + data: layoutsRoutesData['breadcrumbs-states'], + path: 'breadcrumbs-states' + }, { component: CarouselNoNavigationSampleComponent, data: layoutsRoutesData['carousel-no-navigation-sample'], @@ -166,6 +271,41 @@ export const LayoutsRoutes: Routes = [ data: layoutsRoutesData['carousel-styling-sample'], path: 'carousel-styling-sample' }, + { + component: CarouselOverviewSampleComponent, + data: layoutsRoutesData['carousel-overview-sample'], + path: 'carousel-overview-sample' + }, + { + component: CarouselConfigurationSampleComponent, + data: layoutsRoutesData['carousel-configuration-sample'], + path: 'carousel-configuration-sample' + }, + { + component: CarouselComponentsSampleComponent, + data: layoutsRoutesData['carousel-components-sample'], + path: 'carousel-components-sample' + }, + { + component: CarouselAnimationsComponent, + data: layoutsRoutesData['carousel-animations'], + path: 'carousel-animations' + }, + { + component: CarouselThumbnailComponent, + data: layoutsRoutesData['carousel-thumbnail'], + path: 'carousel-thumbnail' + }, + { + component: CarouselStylingComponent, + data: layoutsRoutesData['carousel-styling'], + path: 'carousel-styling' + }, + { + component: CarouselTailwindStylingComponent, + data: layoutsRoutesData['carousel-tailwind-styling'], + path: 'carousel-tailwind-styling' + }, { component: CarouselComponent, data: layoutsRoutesData['carousel'], diff --git a/src/app/lists/combo/combo-remote/combo-remote.component.ts b/src/app/lists/combo/combo-remote/combo-remote.component.ts index 994071a9af..febc5e093a 100644 --- a/src/app/lists/combo/combo-remote/combo-remote.component.ts +++ b/src/app/lists/combo/combo-remote/combo-remote.component.ts @@ -83,8 +83,9 @@ export class ComboRemoteComponent implements OnInit, AfterViewInit { } public onOpened() { - const scroll: number = this.remoteCombo.virtualScrollContainer.getScrollForIndex(this.itemID - 1); - this.remoteCombo.virtualScrollContainer.scrollPosition = scroll + this.additionalScroll; + // additionalScroll is one row, set when the selection is the last item. Landing a + // row further down puts that item at the bottom of the viewport. + void this.remoteCombo.virtualScrollContainer.scrollToIndex(this.itemID - 1 + (this.additionalScroll ? 1 : 0), { block: 'start' }); this.cdr.detectChanges(); } diff --git a/src/app/lists/combo/simple-combo-remote/simple-combo-remote.component.ts b/src/app/lists/combo/simple-combo-remote/simple-combo-remote.component.ts index 1a7caaad9c..6d1ebc7cff 100644 --- a/src/app/lists/combo/simple-combo-remote/simple-combo-remote.component.ts +++ b/src/app/lists/combo/simple-combo-remote/simple-combo-remote.component.ts @@ -70,8 +70,9 @@ export class SimpleComboRemoteComponent implements OnInit, AfterViewInit { } public onOpened() { - const scroll: number = this.remoteSimpleCombo.virtualScrollContainer.getScrollForIndex(this.itemID - 1); - this.remoteSimpleCombo.virtualScrollContainer.scrollPosition = scroll + this.additionalScroll; + // additionalScroll is one row, set when the selection is the last item. Landing a + // row further down puts that item at the bottom of the viewport. + void this.remoteSimpleCombo.virtualScrollContainer.scrollToIndex(this.itemID - 1 + (this.additionalScroll ? 1 : 0), { block: 'start' }); this.cdr.detectChanges(); } diff --git a/src/app/pivot-grid/pivot-styling/pivot-styling.component.html b/src/app/pivot-grid/pivot-styling/pivot-styling.component.html index 08df70c02f..f94ecf55aa 100644 --- a/src/app/pivot-grid/pivot-styling/pivot-styling.component.html +++ b/src/app/pivot-grid/pivot-styling/pivot-styling.component.html @@ -1,2 +1,32 @@ - - \ No newline at end of file +
+
+ Pick a theme + + + @for (theme of themes; track theme.class) { + + } + + +

+ Custom themes, not built-in: each is a grid-theme() with its + own background and accent. +

+
+ + + +
diff --git a/src/app/pivot-grid/pivot-styling/pivot-styling.component.scss b/src/app/pivot-grid/pivot-styling/pivot-styling.component.scss index 238acf9733..d703a350ad 100644 --- a/src/app/pivot-grid/pivot-styling/pivot-styling.component.scss +++ b/src/app/pivot-grid/pivot-styling/pivot-styling.component.scss @@ -1,16 +1,141 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$background: #292826; -$foreground: #eeece1; -$accent: #ffcd0f; - -$custom-grid: grid-theme( - $background: $background, - $foreground: $foreground, - $accent-color: $accent, -); - -igx-pivot-grid { - @include tokens($custom-grid); +$studio-bg: #faf4ed; +$studio-accent: #907aa9; +$ledger-bg: #eceff4; +$ledger-accent: #5e81ac; +$editorial-bg: #333c43; +$editorial-accent: #a7c080; +$midnight-bg: #282a36; +$midnight-accent: #bd93f9; + +.theme-studio { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0.6; + + @include tokens(grid-theme( + $background: $studio-bg, + $foreground: #575279, + $accent-color: $studio-accent, + $header-background: #fffaf3, + $header-border-color: #dfdad9, + $row-border-color: #f2e9e1, + $grid-border-color: #dfdad9, + $grid-shadow: (0 1px 3px rgba(87, 82, 121, 0.10), 0 1px 2px rgba(87, 82, 121, 0.06)) + )); +} + +.theme-ledger { + --ig-size: var(--ig-size-small); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $background: $ledger-bg, + $foreground: #2e3440, + $accent-color: $ledger-accent, + $header-background: #d8dee9, + $row-odd-background: #eceff4, + $row-even-background: #e5e9f0, + $body-column-border-color-odd: #d8dee9, + $body-column-border-color-even: #d8dee9, + $row-border-color: #d8dee9, + $grid-border-color: #c8d0dc + )); +} + +.theme-editorial { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $editorial-bg, + $foreground: #d3c6aa, + $accent-color: $editorial-accent, + $header-background: #3a464c, + $row-border-color: #333c43, + $grid-border-color: #333c43 + )); +} + +.theme-midnight { + --ig-size: var(--ig-size-medium); + --ig-radius-factor: 0.25; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $midnight-bg, + $foreground: #f8f8f2, + $accent-color: $midnight-accent, + $header-background: #21222c, + $body-column-border-color-odd: #44475a, + $body-column-border-color-even: #44475a, + $row-border-color: #44475a, + $grid-border-color: #44475a + )); +} + +.pivot-theming-sample { + display: flex; + flex-direction: column; + gap: 16px; +} + +.theme-picker { + --ig-button-group-elevation: 0; + + display: flex; + flex-direction: column; + gap: 6px; + align-self: flex-start; +} + +.theme-picker__label { + font-size: 12px; + font-weight: 500; + letter-spacing: 0.04em; + color: var(--ig-gray-700); +} + +.theme-picker__hint { + margin: 0; + font-size: 12px; + line-height: 1.45; + color: var(--ig-gray-600); + + code { + font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace; + font-size: 11px; + } +} + +.theme-swatch { + display: inline-block; + min-width: 14px; + aspect-ratio: 1; + border-radius: 50%; + border: 1px solid var(--ig-gray-300); + vertical-align: -2px; + background: linear-gradient(135deg, var(--swatch-bg) 0 50%, var(--swatch-accent) 50% 100%); +} + +.theme-swatch--studio { + --swatch-bg: #{$studio-bg}; + --swatch-accent: #{$studio-accent}; +} + +.theme-swatch--ledger { + --swatch-bg: #{$ledger-bg}; + --swatch-accent: #{$ledger-accent}; +} + +.theme-swatch--editorial { + --swatch-bg: #{$editorial-bg}; + --swatch-accent: #{$editorial-accent}; +} + +.theme-swatch--midnight { + --swatch-bg: #{$midnight-bg}; + --swatch-accent: #{$midnight-accent}; } diff --git a/src/app/pivot-grid/pivot-styling/pivot-styling.component.ts b/src/app/pivot-grid/pivot-styling/pivot-styling.component.ts index b85a70c4fe..039ae0185f 100644 --- a/src/app/pivot-grid/pivot-styling/pivot-styling.component.ts +++ b/src/app/pivot-grid/pivot-styling/pivot-styling.component.ts @@ -1,6 +1,8 @@ -import { Component, ChangeDetectionStrategy } from "@angular/core"; +import { Component, ChangeDetectionStrategy, signal } from "@angular/core"; import { DATA } from '../../data/pivot-data'; +import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; import { IPivotConfiguration, IgxPivotNumericAggregate } from 'igniteui-angular/grids/core'; import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid'; @@ -9,24 +11,38 @@ import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid'; styleUrls: ['./pivot-styling.component.scss'], templateUrl: './pivot-styling.component.html', changeDetection: ChangeDetectionStrategy.Eager, - imports: [IgxPivotGridComponent] + imports: [IgxPivotGridComponent, IgxButtonGroupComponent, IgxButtonDirective] }) export class PivotStylingComponent { public data = DATA; + public themes = [ + { label: 'Studio', class: 'theme-studio', swatch: 'theme-swatch--studio' }, + { label: 'Ledger', class: 'theme-ledger', swatch: 'theme-swatch--ledger' }, + { label: 'Editorial', class: 'theme-editorial', swatch: 'theme-swatch--editorial' }, + { label: 'Midnight', class: 'theme-midnight', swatch: 'theme-swatch--midnight' } + ]; + + public activeTheme = signal(this.themes[0].class); + public pivotConfigHierarchy: IPivotConfiguration = { columns: [ { memberName: 'Product', memberFunction: (data) => data.Product.Name, enabled: true - } + } ], rows: [ { - memberName: 'Seller', - memberFunction: (data) => data.Seller.Name, - enabled: true + memberName: 'City', + memberFunction: (data) => data.Seller.City, + enabled: true, + childLevel: { + memberName: 'Seller', + memberFunction: (data) => data.Seller.Name, + enabled: true + } } ], values: [ @@ -42,4 +58,8 @@ export class PivotStylingComponent { ], filters: null }; + + public selectTheme(args: { index: number }) { + this.activeTheme.set(this.themes[args.index].class); + } } diff --git a/src/app/services/theme.service.spec.ts b/src/app/services/theme.service.spec.ts new file mode 100644 index 0000000000..b38886632a --- /dev/null +++ b/src/app/services/theme.service.spec.ts @@ -0,0 +1,67 @@ +import { DOCUMENT, PLATFORM_ID, signal } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { THEME_TOKEN, type IgxTheme } from 'igniteui-angular/core'; +import { THEME_MESSAGE, ThemeService } from './theme.service'; + +describe('ThemeService theme validation', () => { + let service: ThemeService; + let document: Document; + + beforeEach(() => { + document = window.document.implementation.createHTMLDocument(); + TestBed.configureTestingModule({ + providers: [ + { provide: DOCUMENT, useValue: document }, + { provide: PLATFORM_ID, useValue: 'browser' }, + { provide: THEME_TOKEN, useValue: signal('material') } + ] + }); + service = TestBed.inject(ThemeService); + service.init(); + }); + + for (const theme of ['toString', 'constructor', '__proto__', 'hasOwnProperty']) { + it(`rejects inherited theme key ${theme}`, () => { + const link = document.getElementById('igniteui-theme'); + const href = link.getAttribute('href'); + + expect(service.handleMessage(new MessageEvent('message', { + data: { type: THEME_MESSAGE, theme } + }))).toBeFalse(); + expect(service.theme()).toBe('material'); + expect(link.getAttribute('href')).toBe(href); + + expect(service.set(theme, 'dark')).toBeTrue(); + expect(service.theme()).toBe('material'); + expect(service.mode()).toBe('dark'); + expect(link.getAttribute('href')).toBe('assets/themes/igniteui-angular-dark.css'); + }); + } + + for (const [theme, stylesheet] of [ + ['material', 'igniteui-angular.css'], + ['fluent', 'igniteui-fluent-light.css'], + ['bootstrap', 'igniteui-bootstrap-light.css'], + ['indigo', 'igniteui-indigo-light.css'] + ] as const) { + it(`accepts supported theme ${theme}`, () => { + expect(service.handleMessage(new MessageEvent('message', { + data: { type: THEME_MESSAGE, theme } + }))).toBeTrue(); + expect(service.theme()).toBe(theme); + expect(document.getElementById('igniteui-theme').getAttribute('href')) + .toBe(`assets/themes/${stylesheet}`); + }); + } + + it('reflects the color mode as the root color-scheme', () => { + const root = document.documentElement; + expect(root.style.colorScheme).toBe('light'); + + expect(service.set('bootstrap', 'dark')).toBeTrue(); + expect(root.style.colorScheme).toBe('dark'); + + expect(service.set('bootstrap', 'light')).toBeTrue(); + expect(root.style.colorScheme).toBe('light'); + }); +}); diff --git a/src/app/services/theme.service.ts b/src/app/services/theme.service.ts new file mode 100644 index 0000000000..03f2ef9c81 --- /dev/null +++ b/src/app/services/theme.service.ts @@ -0,0 +1,235 @@ +import { isPlatformBrowser } from '@angular/common'; +import { DOCUMENT, Injectable, PLATFORM_ID, inject, signal } from '@angular/core'; +import { THEME_TOKEN, type IgxTheme } from 'igniteui-angular/core'; + +/** + * Message type posted by the documentation site's theming widget into the + * sample iframe. See `ThemeService.handleMessage`. + */ +export const THEME_MESSAGE = 'igd-sample-theme'; + +/** Color modes the theming widget can request. */ +export type ThemeMode = 'light' | 'dark' | 'system'; + +/** `system` resolved against the OS preference. */ +export type ColorScheme = 'light' | 'dark'; + +/** + * Prebuilt Ignite UI stylesheets, one per theme/scheme pair. They are copied + * out of `igniteui-angular/styles` into `assets/themes` at build time - see the + * `assets` section of angular.json. + */ +const THEME_STYLESHEETS: Record> = { + material: { light: 'igniteui-angular.css', dark: 'igniteui-angular-dark.css' }, + fluent: { light: 'igniteui-fluent-light.css', dark: 'igniteui-fluent-dark.css' }, + bootstrap: { light: 'igniteui-bootstrap-light.css', dark: 'igniteui-bootstrap-dark.css' }, + indigo: { light: 'igniteui-indigo-light.css', dark: 'igniteui-indigo-dark.css' } +}; + +const THEMES_PATH = 'assets/themes/'; + +/** Id of the `` in index.html that carries the active theme. */ +const THEME_LINK_ID = 'igniteui-theme'; + +const TYPEFACE_URL = 'https://fonts.googleapis.com/css?family='; +const TYPEFACE_WEIGHTS = ':300,400,600,700'; + +/** + * Font families that never need to be fetched: generic CSS keywords and the + * system fonts the Bootstrap theme is built on. + */ +const LOCAL_FAMILIES = new Set([ + 'sans-serif', 'serif', 'monospace', 'cursive', 'fantasy', + 'system-ui', 'ui-sans-serif', 'ui-serif', 'ui-monospace', + 'segoe ui', 'helvetica', 'helvetica neue', 'arial', 'roboto' +]); + +const isTheme = (value: unknown): value is IgxTheme => + typeof value === 'string' && Object.hasOwn(THEME_STYLESHEETS, value); + +const isMode = (value: unknown): value is ThemeMode => + value === 'light' || value === 'dark' || value === 'system'; + +/** + * Swaps the Ignite UI theme of the samples application at runtime. + * + * Samples are embedded in the documentation as iframes and the site's theming + * widget posts the visitor's selection into them, so the whole application has + * to be able to move between the Material, Fluent, Bootstrap and Indigo themes + * (each in a light and a dark variant) without reloading. That is done by + * pointing a single `` at one of the prebuilt stylesheets instead of + * compiling a single theme into `styles.scss`. + */ +@Injectable({ providedIn: 'root' }) +export class ThemeService { + private document = inject(DOCUMENT); + private themeToken = inject(THEME_TOKEN); + private isBrowser = isPlatformBrowser(inject(PLATFORM_ID)); + + /** The selected theme. */ + public readonly theme = signal('material'); + + /** The selected color mode, `system` included. */ + public readonly mode = signal('light'); + + /** The color mode actually in effect, with `system` already resolved. */ + public readonly colorScheme = signal('light'); + + private prefersDark: MediaQueryList; + private typefaces = new Set(); + + /** + * Applies the initial theme and starts following the OS color preference. + * Safe to call more than once. + */ + public init(): void { + if (this.isBrowser && !this.prefersDark) { + this.prefersDark = this.document.defaultView?.matchMedia('(prefers-color-scheme: dark)'); + // Only relevant while the widget is on `system`; `apply` ignores it otherwise. + this.prefersDark?.addEventListener('change', () => this.apply()); + } + + this.apply(); + } + + /** + * Handles a `message` event coming from the documentation site. + * + * The widget posts `{ type: 'igd-sample-theme', theme, themeName, mode }` + * once when the iframe loads and again on every change. The message is + * trusted for its shape rather than for its origin - the documentation is + * served from a number of hosts, and the only thing acted upon is a choice + * between the four known themes and the three known modes. + * + * @returns whether the message was recognized and applied. + */ + public handleMessage(event: MessageEvent): boolean { + const data = event.data; + + if (!data || (data.type !== THEME_MESSAGE && data.event !== THEME_MESSAGE)) { + return false; + } + + return this.set(data.theme ?? data.themeName, data.mode); + } + + /** + * Switches to `theme` / `mode`. Unknown or missing values leave the + * corresponding part of the selection untouched. + * + * @returns whether anything was recognized. + */ + public set(theme?: unknown, mode?: unknown): boolean { + let known = false; + + if (isTheme(theme)) { + this.theme.set(theme); + known = true; + } + + if (isMode(mode)) { + this.mode.set(mode); + known = true; + } + + if (known) { + this.apply(); + } + + return known; + } + + private apply(): void { + if (!this.isBrowser) { + return; + } + + const theme = this.theme(); + const scheme = this.resolveScheme(); + this.colorScheme.set(scheme); + + // Exposed for samples that need to react to the selection. Deliberately + // not used to paint a page background: the documentation's Sample + // component owns the surface behind the iframe. + const root = this.document.documentElement; + root.dataset.igTheme = theme; + root.dataset.igMode = scheme; + // The Sample component gives its iframe the same color-scheme. When the + // two differ, the browser paints an opaque default canvas behind the + // page instead of leaving it transparent for that surface to show through. + root.style.colorScheme = scheme; + + const href = THEMES_PATH + THEME_STYLESHEETS[theme][scheme]; + const link = this.themeLink(); + + if (!link.getAttribute('href')?.endsWith(href)) { + link.addEventListener('load', () => this.loadTypeface(), { once: true }); + link.href = href; + } + + // Components such as igx-input-group render differently per theme and + // take the theme from this token rather than from the stylesheet. + this.themeToken.set(theme); + } + + private resolveScheme(): ColorScheme { + const mode = this.mode(); + + if (mode !== 'system') { + return mode; + } + + return this.prefersDark?.matches ? 'dark' : 'light'; + } + + private themeLink(): HTMLLinkElement { + let link = this.document.getElementById(THEME_LINK_ID) as HTMLLinkElement; + + if (!link) { + link = this.document.createElement('link'); + link.id = THEME_LINK_ID; + link.rel = 'stylesheet'; + // Ahead of everything else in the head, so that the application's + // own styles keep overriding the theme as they do in index.html. + this.document.head.insertBefore(link, this.document.head.firstChild); + } + + return link; + } + + /** + * Each theme comes with its own typeface. Once a theme stylesheet is in + * place, take the first family off `--ig-font-family` and pick it up from + * Google Fonts unless it is one the browser already has. + */ + private loadTypeface(): void { + const view = this.document.defaultView; + + if (!view) { + return; + } + + const family = view.getComputedStyle(this.document.body) + .getPropertyValue('--ig-font-family') + .split(',')[0] + .trim() + .replace(/['"]/g, ''); + + if (!family || family.startsWith('-') || LOCAL_FAMILIES.has(family.toLowerCase())) { + return; + } + + if (this.typefaces.has(family)) { + return; + } + + this.typefaces.add(family); + + // A link per family, so that switching back to an earlier theme does + // not have to fetch its typeface again. + const link = this.document.createElement('link'); + link.rel = 'stylesheet'; + link.href = TYPEFACE_URL + family.split(' ').join('+') + TYPEFACE_WEIGHTS; + this.document.head.appendChild(link); + } +} diff --git a/src/app/theming/grid-theme-playground/grid-theme-playground.component.html b/src/app/theming/grid-theme-playground/grid-theme-playground.component.html new file mode 100644 index 0000000000..303a30a094 --- /dev/null +++ b/src/app/theming/grid-theme-playground/grid-theme-playground.component.html @@ -0,0 +1,243 @@ +
+ +
+
+ + @switch (preview()) { + @case ('grid') { + + + + + + + + + } + @case ('tree') { + @defer (on immediate) { + + + +
+ + {{ cell.value }} +
+
+
+ + + +
+ } @placeholder { +
Loading preview…
+ } + } + @case ('hierarchical') { + @defer (on immediate) { + + + + + + + + + + + + } @placeholder { +
Loading preview…
+ } + } + @case ('pivot') { + @defer (on immediate) { + + + } @placeholder { +
Loading preview…
+ } + } + } +
+
+
+ + + +
Theme code
+
+ +
+ + + + SCSS + + + +
+
+
+ + + + CSS variables + + + +
+
+
+
+
+ +
+ +
+
diff --git a/src/app/theming/grid-theme-playground/grid-theme-playground.component.scss b/src/app/theming/grid-theme-playground/grid-theme-playground.component.scss new file mode 100644 index 0000000000..f382346c6f --- /dev/null +++ b/src/app/theming/grid-theme-playground/grid-theme-playground.component.scss @@ -0,0 +1,190 @@ +@use "igniteui-angular/theming" as *; + +:host { + display: block; + block-size: 100%; +} + +.playground { + display: flex; + align-items: stretch; + gap: 20px; + padding: 16px; + box-sizing: border-box; + block-size: 100%; + min-block-size: 520px; + overflow: hidden; +} + +.playground__stage { + @include tokens(grid-theme( + $background: #08002e, + $accent-color: #ff7d52 + )); +} + +.playground__rail { + --ig-size: var(--ig-size-medium); + --ig-button-group-elevation: 0; + + flex: 0 0 280px; + display: flex; + flex-direction: column; + gap: 12px; + min-block-size: 0; + overflow-y: auto; + padding-inline-end: 4px; + + igx-expansion-panel-title { + font-size: 13px; + font-weight: 600; + letter-spacing: 0.04em; + color: var(--ig-gray-700); + } +} + +.playground__hint { + margin: 0 0 10px; + font-size: 12px; + line-height: 1.45; + color: var(--ig-gray-600); +} + +.playground__fields { + display: flex; + flex-direction: column; + gap: 14px; +} + +.playground__color-control { + anchor-scope: --grid-color-input; + + igc-color-picker { + anchor-name: --grid-color-input; + inline-size: 100%; + } + + button { + position: absolute; + position-anchor: --grid-color-input; + inset-inline-end: calc(anchor(self-end) + 0.5rem); + align-self: anchor-center; + z-index: 1; + } +} + +.playground__control { + display: flex; + flex-direction: column; + gap: 6px; +} + +.playground__label { + font-size: 12px; + color: var(--ig-gray-700); +} + +.playground__actions { + position: sticky; + inset-block-end: 0; + z-index: 1; + display: flex; + gap: 8px; + padding-block: 8px; + background: var(--ig-surface-500); + border-block-start: 1px solid var(--ig-gray-200); + + button { + flex: 1; + } +} + +.playground__dialog-title { + font-size: 16px; + font-weight: 600; +} + +.playground__dialog-body { + --ig-size: var(--ig-size-medium); + --ig-icon-size: 18px; + --ig-h5-font-size: 14px; + --ig-h5-font-weight: 600; + --ig-expansion-panel-border-radius: 4px; + --ig-expansion-panel-header-background: var(--ig-gray-100); + + inline-size: min(680px, 80vw); + + ::ng-deep .igx-expansion-panel__body { + padding: 0; + } +} + +.playground__copy { + margin-inline-start: auto; +} + +.playground__export { + border: 1px solid var(--ig-gray-300); + border-radius: 6px; + overflow: hidden; +} + +.playground__code { + ::ng-deep pre.shiki { + margin: 0; + padding: 10px 12px; + font-size: 13px; + line-height: 1.5; + font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace; + max-block-size: 55vh; + overflow: auto; + overscroll-behavior: contain; + } +} + +.playground__loading { + display: grid; + place-items: center; + block-size: 100%; + color: var(--ig-gray-600); + font-size: 13px; +} + +.playground__preview { + flex: 1 1 auto; + min-inline-size: 0; + min-block-size: 0; + display: flex; + flex-direction: column; + gap: 12px; +} + +.playground__stage { + flex: 1 1 auto; + min-block-size: 0; + overflow: hidden; +} + +.playground__cell { + display: flex; + align-items: center; + gap: 8px; + height: 100%; +} + +@media (max-width: 860px) { + .playground { + flex-direction: column; + block-size: auto; + overflow: visible; + } + + .playground__rail { + flex: 0 0 auto; + overflow: visible; + } + + .playground__stage { + min-block-size: 460px; + } +} diff --git a/src/app/theming/grid-theme-playground/grid-theme-playground.component.ts b/src/app/theming/grid-theme-playground/grid-theme-playground.component.ts new file mode 100644 index 0000000000..80af219aab --- /dev/null +++ b/src/app/theming/grid-theme-playground/grid-theme-playground.component.ts @@ -0,0 +1,329 @@ +import { isPlatformBrowser } from '@angular/common'; +import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, PLATFORM_ID, afterNextRender, computed, inject, signal, viewChild } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { IgxAccordionComponent } from 'igniteui-angular/accordion'; +import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxNumberSummaryOperand, IgxSummaryResult } from 'igniteui-angular/core'; +import { IgxIconComponent } from 'igniteui-angular/icon'; +import { IgxDialogActionsDirective, IgxDialogComponent, IgxDialogTitleDirective } from 'igniteui-angular/dialog'; +import { IgxButtonDirective, IgxIconButtonDirective } from 'igniteui-angular/directives'; +import { IGX_EXPANSION_PANEL_DIRECTIVES } from 'igniteui-angular/expansion-panel'; +import { IgxCellTemplateDirective, IgxColumnComponent, IPivotConfiguration, IgxPivotNumericAggregate } from 'igniteui-angular/grids/core'; +import { IgxGridComponent } from 'igniteui-angular/grids/grid'; +import { IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular/grids/hierarchical-grid'; +import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid'; +import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; +import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +import { IgxSwitchComponent } from 'igniteui-angular/switch'; +import { defineComponents, IgcColorPickerComponent } from 'igniteui-webcomponents'; +import { INVOICE_DATA } from '../../data/invoiceData'; +import { DATA as PIVOT_DATA } from '../../data/pivot-data'; +import { SINGERS } from '../../data/singersData'; +import { EMPLOYEE_FLAT_AVATARS_DATA } from '../../tree-grid/data/employees-flat-avatars'; + +type TokenKey = 'background' | 'accentColor' | 'foreground' | 'headerBackground' | 'headerForeground'; + +interface TokenDescriptor { + key: TokenKey; + cssVar: string; + scss: string; + label: string; +} +class CompactSummary extends IgxNumberSummaryOperand { + public override operate(data?: any[]): IgxSummaryResult[] { + return super.operate(data).filter(r => r.key === 'count' || r.key === 'sum'); + } +} +const PRIMARY_TOKENS: TokenDescriptor[] = [ + { key: 'background', cssVar: '--ig-grid-background', scss: '$background', label: 'Background' }, + { key: 'accentColor', cssVar: '--ig-grid-accent-color', scss: '$accent-color', label: 'Accent' }, + { key: 'foreground', cssVar: '--ig-grid-foreground', scss: '$foreground', label: 'Foreground' } +]; +const HEADER_TOKENS: TokenDescriptor[] = [ + { key: 'headerBackground', cssVar: '--ig-grid-header-background', scss: '$header-background', label: 'Header background' }, + { key: 'headerForeground', cssVar: '--ig-grid-header-text-color', scss: '$header-text-color', label: 'Header foreground' } +]; + +const ALL_TOKENS = [...PRIMARY_TOKENS, ...HEADER_TOKENS]; + +const EMPTY_COLORS: Record = { + background: '', accentColor: '', foreground: '', headerBackground: '', headerForeground: '' +}; +/** What Sass emits for header text once $header-background is declared. */ +const HEADER_TEXT_ON_HEADER = 'hsla(from color(from var(--ig-grid-header-background) var(--y-contrast)) h 0 l/1)'; +const DIVIDER = 'hsl(from color-mix(in srgb, var(--ig-grid-foreground) 16%, var(--ig-grid-background)) h s l/0.38)'; +const ZEBRA = 'color-mix(in srgb, var(--ig-grid-foreground) 4%, var(--ig-grid-background))'; +const NO_DIVIDER = 'var(--ig-grid-background)'; + +@Component({ + selector: 'app-grid-theme-playground', + styleUrls: ['./grid-theme-playground.component.scss'], + templateUrl: './grid-theme-playground.component.html', + imports: [ + IgxAccordionComponent, IGX_EXPANSION_PANEL_DIRECTIVES, IgxAvatarComponent, IgxButtonDirective, + IgxButtonGroupComponent, IgxCellTemplateDirective, IgxColumnComponent, + IgxDialogActionsDirective, IgxDialogComponent, IgxDialogTitleDirective, IgxGridComponent, + IgxHierarchicalGridComponent, IgxIconButtonDirective, IgxIconComponent, IgxPaginatorComponent, IgxPivotGridComponent, IgxRowIslandComponent, + IgxSwitchComponent, IgxTreeGridComponent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridThemePlaygroundComponent { + protected readonly primaryTokens = PRIMARY_TOKENS; + protected readonly headerTokens = HEADER_TOKENS; + protected readonly compactSummary = CompactSummary; + + private initialColors: Record = { ...EMPTY_COLORS }; + protected readonly colors = signal>({ ...EMPTY_COLORS }); + protected readonly size = signal<'small' | 'medium' | 'large'>('medium'); + protected readonly radiusFactor = signal(0.4); + protected readonly horizontalDividers = signal(true); + protected readonly verticalDividers = signal(false); + protected readonly zebra = signal(false); + protected readonly preview = signal<'grid' | 'tree' | 'hierarchical' | 'pivot'>('grid'); + + protected readonly copied = signal<'scss' | 'css' | null>(null); + + protected readonly sizes = [ + { label: 'Small', selected: false }, + { label: 'Medium', selected: true }, + { label: 'Large', selected: false } + ]; + protected readonly roundnessOptions = [ + { label: 'Square', selected: false }, + { label: 'Soft', selected: true }, + { label: 'Round', selected: false } + ]; + protected readonly previews = [ + { label: 'Flat', selected: true }, + { label: 'Tree', selected: false }, + { label: 'Hierarchical', selected: false }, + { label: 'Pivot', selected: false } + ]; + + public readonly data = INVOICE_DATA; + public readonly treeData = EMPLOYEE_FLAT_AVATARS_DATA(); + public readonly hierarchicalData = SINGERS; + public readonly pivotData = PIVOT_DATA; + + public pivotConfig: IPivotConfiguration = { + columns: [{ memberName: 'Product', memberFunction: (data) => data.Product.Name, enabled: true }], + rows: [{ + memberName: 'City', + memberFunction: (data) => data.Seller.City, + enabled: true, + childLevel: { memberName: 'Seller', memberFunction: (data) => data.Seller.Name, enabled: true } + }], + values: [{ + member: 'NumberOfUnits', + aggregate: { aggregator: IgxPivotNumericAggregate.sum, key: 'sum', label: 'Sum' }, + enabled: true + }], + filters: null + }; + + private readonly sanitizer = inject(DomSanitizer); + + protected readonly scssHtml = signal(null); + protected readonly cssHtml = signal(null); + + private highlighter: { codeToHtml: (code: string, opts: { lang: string; theme: string }) => string } | null = null; + + private readonly stage = viewChild.required>('stage'); + /** The compiled theme, read from the stylesheet: the CSS export needs every + * token, not just the roots, to work in an app with no grid-theme(). */ + private readonly themeTokens = signal<[string, string][]>([]); + + constructor() { + if (isPlatformBrowser(inject(PLATFORM_ID))) { + defineComponents(IgcColorPickerComponent); + } + afterNextRender(() => { + this.seedFromStylesheet(); + this.readCompiledTheme(); + }); + } + protected readonly previewStyle = computed>(() => { + const style: Record = {}; + const colors = this.colors(); + + for (const token of ALL_TOKENS) { + if (colors[token.key]) { + style[token.cssVar] = colors[token.key]; + } + } + if (colors.headerBackground && !colors.headerForeground) { + style['--ig-grid-header-text-color'] = HEADER_TEXT_ON_HEADER; + } + + style['--ig-size'] = `var(--ig-size-${this.size()})`; + style['--ig-radius-factor'] = `${this.radiusFactor()}`; + style['--ig-grid-row-border-color'] = this.horizontalDividers() ? DIVIDER : NO_DIVIDER; + + const columnRule = this.verticalDividers() ? DIVIDER : NO_DIVIDER; + style['--ig-grid-body-column-border-color-odd'] = columnRule; + style['--ig-grid-body-column-border-color-even'] = columnRule; + + if (this.zebra()) { + style['--ig-grid-row-even-background'] = ZEBRA; + } + + return style; + }); + protected readonly exportScss = computed(() => { + const colors = this.colors(); + const themeLines = ALL_TOKENS + .filter(token => colors[token.key]) + .map(token => ` ${token.scss}: ${colors[token.key]},`); + + if (!this.horizontalDividers()) { + themeLines.push(` $row-border-color: ${NO_DIVIDER},`); + } + if (this.verticalDividers()) { + themeLines.push(` $body-column-border-color-odd: ${DIVIDER},`); + themeLines.push(` $body-column-border-color-even: ${DIVIDER},`); + } + if (this.zebra()) { + themeLines.push(` $row-even-background: ${ZEBRA},`); + } + + const varLines = [ + ` --ig-size: var(--ig-size-${this.size()});`, + ` --ig-radius-factor: ${this.radiusFactor()};` + ]; + + if (!themeLines.length) { + return `.my-grid {\n${varLines.join('\n')}\n}`; + } + + return `.my-grid {\n${varLines.join('\n')}\n\n @include tokens(grid-theme(\n${themeLines.join('\n')}\n ));\n}`; + }); + + protected readonly exportCss = computed(() => { + const overrides = this.previewStyle(); + const base = this.themeTokens(); + + if (!base.length) { + const lines = Object.entries(overrides).map(([name, value]) => ` ${name}: ${value};`); + return `/* Overrides only -- requires a grid-theme() base to derive from. */\n.my-grid {\n${lines.join('\n')}\n}`; + } + + const emitted = new Set(); + const lines = base.map(([name, value]) => { + emitted.add(name); + return ` ${name}: ${overrides[name] ?? value};`; + }); + const extras = Object.entries(overrides) + .filter(([name]) => !emitted.has(name)) + .map(([name, value]) => ` ${name}: ${value};`); + + return `.my-grid {\n${[...extras, ...lines].join('\n')}\n}`; + }); + + protected onColorChange(key: TokenKey, event: Event): void { + // Ignore input events bubbling from the picker's internal text fields; + // only the picker itself emits validated color values. + if (event.composedPath()[0] === event.currentTarget) { + this.setColor(key, (event as CustomEvent).detail); + } + } + + protected setColor(key: TokenKey, value: string): void { + this.colors.update(current => ({ ...current, [key]: value })); + } + + protected reset(): void { + this.colors.set({ ...this.initialColors }); + this.size.set('medium'); + this.radiusFactor.set(0.4); + this.horizontalDividers.set(true); + this.verticalDividers.set(false); + this.zebra.set(false); + } + + protected async showCode(dialog: IgxDialogComponent): Promise { + if (!this.highlighter) { + const [core, engine, scss, css, theme] = await Promise.all([ + import('shiki/core'), + import('shiki/engine/javascript'), + import('shiki/langs/scss.mjs'), + import('shiki/langs/css.mjs'), + import('shiki/themes/dark-plus.mjs') + ]); + + this.highlighter = await core.createHighlighterCore({ + themes: [theme.default], + langs: [scss.default, css.default], + engine: engine.createJavaScriptRegexEngine() + }); + } + + const render = (code: string | null, lang: string) => code + ? this.sanitizer.bypassSecurityTrustHtml(this.highlighter.codeToHtml(code, { lang, theme: 'dark-plus' })) + : null; + + this.scssHtml.set(render(this.exportScss(), 'scss')); + this.cssHtml.set(render(this.exportCss(), 'css')); + dialog.open(); + } + + protected copy(code: string | null, format: 'scss' | 'css'): void { + if (!code) return; + navigator.clipboard.writeText(code).then(() => { + this.copied.set(format); + setTimeout(() => this.copied.set(null), 2000); + }); + } + + protected onSize(args: { index: number }): void { + this.size.set((['small', 'medium', 'large'] as const)[args.index]); + } + + protected onRoundness(args: { index: number }): void { + this.radiusFactor.set([0, 0.4, 1][args.index]); + } + + protected onPreview(args: { index: number }): void { + this.preview.set((['grid', 'tree', 'hierarchical', 'pivot'] as const)[args.index]); + } + private readCompiledTheme(): void { + const tokens: [string, string][] = []; + + for (const sheet of Array.from(document.styleSheets)) { + let rules: CSSRuleList; + + try { + rules = sheet.cssRules; + } catch { + continue; // cross-origin sheet, not ours + } + + for (const rule of Array.from(rules)) { + if (!(rule instanceof CSSStyleRule) || !rule.selectorText.includes('playground__stage')) { + continue; + } + + for (let i = 0; i < rule.style.length; i++) { + const name = rule.style.item(i); + if (name.startsWith('--ig-')) { + tokens.push([name, rule.style.getPropertyValue(name).trim()]); + } + } + } + } + + this.themeTokens.set(tokens); + } + + private seedFromStylesheet(): void { + const styles = getComputedStyle(this.stage().nativeElement); + + this.initialColors = { + ...EMPTY_COLORS, + background: styles.getPropertyValue('--ig-grid-background').trim(), + accentColor: styles.getPropertyValue('--ig-grid-accent-color').trim() + }; + this.colors.set({ ...this.initialColors }); + } +} diff --git a/src/app/theming/theming-routes-data.ts b/src/app/theming/theming-routes-data.ts index a3a73cff12..91182ac677 100644 --- a/src/app/theming/theming-routes-data.ts +++ b/src/app/theming/theming-routes-data.ts @@ -12,5 +12,6 @@ export const themingRoutesData = { 'roundness': { displayName: 'Roundness', parentName: 'Themes' }, 'angular-sample': { displayName: 'Angular Material Theming', parentName: 'Themes' }, 'bootstrap-sample': { displayName: 'Bootstrap Theming', parentName: 'Themes' }, - 'card-sample-shadow': { displayName: 'card-sample-shadow', parentName: 'Shadows' } + 'card-sample-shadow': { displayName: 'card-sample-shadow', parentName: 'Shadows' }, + 'grid-theme-playground': { displayName: 'Grid Theme Playground', parentName: 'Themes' } }; diff --git a/src/app/theming/theming.routes.ts b/src/app/theming/theming.routes.ts index 2a0cd5e31b..b1e0d0aac8 100644 --- a/src/app/theming/theming.routes.ts +++ b/src/app/theming/theming.routes.ts @@ -4,6 +4,7 @@ import { AnimationsSample2Component } from './animations/animations-sample-2/ani import { AngularMaterialComponent } from './angular/angular-sample.component'; import { BootstrapComponent } from './bootstrap/bootstrap-sample.component'; import { DefaultThemeSampleComponent } from './default-theme-sample/default-theme-sample.component'; +import { GridThemePlaygroundComponent } from './grid-theme-playground/grid-theme-playground.component'; import { DisplayDensityComponent } from './display-density/display-density.component'; import { RoundnessComponent } from './roundness/roundness-sample.component'; import { CardSampleShadowComponent} from './shadows/card-sample-shadow/card-sample-shadow'; @@ -68,5 +69,10 @@ export const ThemingRoutes: Routes = [ component: TailwindSampleComponent, data: themingRoutesData['tailwind-sample'], path: 'tailwind-sample' + }, + { + component: GridThemePlaygroundComponent, + data: themingRoutesData['grid-theme-playground'], + path: 'grid-theme-playground' } ]; diff --git a/src/app/tree-grid/tree-grid-rowStyles-sample/tree-grid-rowStyle.component.ts b/src/app/tree-grid/tree-grid-rowStyles-sample/tree-grid-rowStyle.component.ts index b18c2bcc1a..324867face 100644 --- a/src/app/tree-grid/tree-grid-rowStyles-sample/tree-grid-rowStyle.component.ts +++ b/src/app/tree-grid/tree-grid-rowStyles-sample/tree-grid-rowStyle.component.ts @@ -25,7 +25,7 @@ export class TreeGridRowStylesComponent implements OnInit { row.data['Title'].includes('Senior') ? '#f8f9fa' : null; // eslint-disable-next-line @typescript-eslint/member-ordering - public rowStyles = { + public rowStyles: any = { background: this.background, 'border-left': (row: RowType) => row.data['Title'] === 'CEO' || row.data['Title'].includes('President') ? '2px solid' : null, diff --git a/src/app/tree-grid/tree-grid-style/layout.scss b/src/app/tree-grid/tree-grid-style/layout.scss index 0fda2fbb55..5c88726269 100644 --- a/src/app/tree-grid/tree-grid-style/layout.scss +++ b/src/app/tree-grid/tree-grid-style/layout.scss @@ -1,5 +1,9 @@ +:host { + display: block; +} + .grid__wrapper { - margin: 10px; + padding: 10px; } .cell__inner { diff --git a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.html b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.html index 9eeff6a075..751efd7181 100644 --- a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.html +++ b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.html @@ -1,6 +1,38 @@
- - +
+ Pick a theme + + + @for (theme of themes; track theme.class) { + + } + + +

+ Custom themes, not built-in: each is a grid-theme() with its + own background and accent. +

+
+ + +
@@ -8,8 +40,8 @@
- - - + + +
diff --git a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.scss b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.scss index 2c0d35a3be..9a14ff29e1 100644 --- a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.scss +++ b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.scss @@ -1,16 +1,141 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$background: #292826; -$foreground: #eeece1; -$accent: #ffcd0f; - -$custom-grid: grid-theme( - $background: $background, - $foreground: $foreground, - $accent-color: $accent, -); - -:host { - @include tokens($custom-grid); +$studio-bg: #faf4ed; +$studio-accent: #907aa9; +$ledger-bg: #eceff4; +$ledger-accent: #5e81ac; +$editorial-bg: #333c43; +$editorial-accent: #a7c080; +$midnight-bg: #282a36; +$midnight-accent: #bd93f9; + +.theme-studio { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0.6; + + @include tokens(grid-theme( + $background: $studio-bg, + $foreground: #575279, + $accent-color: $studio-accent, + $header-background: #fffaf3, + $header-border-color: #dfdad9, + $row-border-color: #f2e9e1, + $grid-border-color: #dfdad9, + $grid-shadow: (0 1px 3px rgba(87, 82, 121, 0.10), 0 1px 2px rgba(87, 82, 121, 0.06)) + )); +} + +.theme-ledger { + --ig-size: var(--ig-size-small); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $background: $ledger-bg, + $foreground: #2e3440, + $accent-color: $ledger-accent, + $header-background: #d8dee9, + $row-odd-background: #eceff4, + $row-even-background: #e5e9f0, + $body-column-border-color-odd: #d8dee9, + $body-column-border-color-even: #d8dee9, + $row-border-color: #d8dee9, + $grid-border-color: #c8d0dc + )); +} + +.theme-editorial { + --ig-size: var(--ig-size-large); + --ig-radius-factor: 0; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $editorial-bg, + $foreground: #d3c6aa, + $accent-color: $editorial-accent, + $header-background: #3a464c, + $row-border-color: #333c43, + $grid-border-color: #333c43 + )); +} + +.theme-midnight { + --ig-size: var(--ig-size-medium); + --ig-radius-factor: 0.25; + + @include tokens(grid-theme( + $schema: $dark-material-schema, + $background: $midnight-bg, + $foreground: #f8f8f2, + $accent-color: $midnight-accent, + $header-background: #21222c, + $body-column-border-color-odd: #44475a, + $body-column-border-color-even: #44475a, + $row-border-color: #44475a, + $grid-border-color: #44475a + )); +} + +.grid__wrapper { + display: flex; + flex-direction: column; + gap: 16px; +} + +.theme-picker { + --ig-button-group-elevation: 0; + + display: flex; + flex-direction: column; + gap: 6px; + align-self: flex-start; +} + +.theme-picker__label { + font-size: 12px; + font-weight: 500; + letter-spacing: 0.04em; + color: var(--ig-gray-700); +} + +.theme-picker__hint { + margin: 0; + font-size: 12px; + line-height: 1.45; + color: var(--ig-gray-600); + + code { + font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace; + font-size: 11px; + } +} + +.theme-swatch { + display: inline-block; + min-width: 14px; + aspect-ratio: 1; + border-radius: 50%; + border: 1px solid var(--ig-gray-300); + vertical-align: -2px; + background: linear-gradient(135deg, var(--swatch-bg) 0 50%, var(--swatch-accent) 50% 100%); +} + +.theme-swatch--studio { + --swatch-bg: #{$studio-bg}; + --swatch-accent: #{$studio-accent}; +} + +.theme-swatch--ledger { + --swatch-bg: #{$ledger-bg}; + --swatch-accent: #{$ledger-accent}; +} + +.theme-swatch--editorial { + --swatch-bg: #{$editorial-bg}; + --swatch-accent: #{$editorial-accent}; +} + +.theme-swatch--midnight { + --swatch-bg: #{$midnight-bg}; + --swatch-accent: #{$midnight-accent}; } diff --git a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.ts b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.ts index 653f39c22b..f2a2472061 100644 --- a/src/app/tree-grid/tree-grid-style/tree-grid-style.component.ts +++ b/src/app/tree-grid/tree-grid-style/tree-grid-style.component.ts @@ -1,21 +1,35 @@ -import { Component, OnInit } from '@angular/core'; -import { EMPLOYEE_FLAT_AVATARS_DATA } from '../data/employees-flat-avatars'; -import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; -import { IgxCellTemplateDirective, IgxColumnComponent } from 'igniteui-angular/grids/core'; +import { Component, OnInit, signal } from '@angular/core'; import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { IgxButtonGroupComponent } from 'igniteui-angular/button-group'; +import { IgxButtonDirective } from 'igniteui-angular/directives'; +import { IgxCellTemplateDirective, IgxColumnComponent } from 'igniteui-angular/grids/core'; +import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; +import { EMPLOYEE_FLAT_AVATARS_DATA } from '../data/employees-flat-avatars'; import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive'; @Component({ selector: 'app-tree-grid-style', styleUrls: ['./tree-grid-style.component.scss'], templateUrl: './tree-grid-style.component.html', - imports: [IgxTreeGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxAvatarComponent] + imports: [IgxTreeGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxAvatarComponent, IgxButtonGroupComponent, IgxButtonDirective] }) export class TreeGridStyleComponent implements OnInit { public data: any[]; + public themes = [ + { label: 'Studio', class: 'theme-studio', swatch: 'theme-swatch--studio' }, + { label: 'Ledger', class: 'theme-ledger', swatch: 'theme-swatch--ledger' }, + { label: 'Editorial', class: 'theme-editorial', swatch: 'theme-swatch--editorial' }, + { label: 'Midnight', class: 'theme-midnight', swatch: 'theme-swatch--midnight' } + ]; + + public activeTheme = signal(this.themes[0].class); public ngOnInit() { this.data = EMPLOYEE_FLAT_AVATARS_DATA(); } + + public selectTheme(args: { index: number }) { + this.activeTheme.set(this.themes[args.index].class); + } } diff --git a/src/app/tree-grid/tree-grid-summary-styling/tree-grid-summary-styling.component.scss b/src/app/tree-grid/tree-grid-summary-styling/tree-grid-summary-styling.component.scss index 07c3707c3a..6013b5f3df 100644 --- a/src/app/tree-grid/tree-grid-summary-styling/tree-grid-summary-styling.component.scss +++ b/src/app/tree-grid/tree-grid-summary-styling/tree-grid-summary-styling.component.scss @@ -7,7 +7,6 @@ $custom-theme: grid-summary-theme( $background-color: $summaries-background, $label-color: #486821, $result-color: #172505, - $pinned-border-width: 2px, $pinned-border-style: dotted, $pinned-border-color: #172505, ); diff --git a/src/app/tree-grid/tree-grid-validation-style/tree-grid-validation-style.component.ts b/src/app/tree-grid/tree-grid-validation-style/tree-grid-validation-style.component.ts index dad7ada413..b6d515bcd4 100644 --- a/src/app/tree-grid/tree-grid-validation-style/tree-grid-validation-style.component.ts +++ b/src/app/tree-grid/tree-grid-validation-style/tree-grid-validation-style.component.ts @@ -17,7 +17,7 @@ export class TreeGridValidationStyleComponent implements OnInit { public data: IEmployee[]; public columns: any[]; public selectionMode = 'multiple'; - public rowStyles = { + public rowStyles: any = { background: (row: RowType) => row.cells.find(c => c.validation.errors !== null && c.validation.errors !== undefined) ? '#FF000033' : '#00000000' }; public cellStyles = { diff --git a/src/index.html b/src/index.html index 9920eced30..edf598d753 100644 --- a/src/index.html +++ b/src/index.html @@ -3,6 +3,10 @@ + + Angular Demos @@ -12,6 +16,14 @@ + + + + + diff --git a/src/server.ts b/src/server.ts index 72bf56bec2..3af8c6cd81 100644 --- a/src/server.ts +++ b/src/server.ts @@ -46,7 +46,13 @@ app.use('/**', (req, res, next) => { .then((response) => response ? writeResponseToNodeResponse(response, res) : next() ) - .catch(next); + .catch((error: unknown) => { + if (error instanceof Error && error.name === 'AbortError') { + return; + } + + next(error); + }); }); /** diff --git a/src/styles.scss b/src/styles.scss index 8c144ff6dd..03a2dd70b9 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -5,6 +5,14 @@ @use 'app-layout'; @import "tailwindcss"; +// The Ignite UI theme itself is deliberately NOT compiled into this file. Every +// sample is embedded in the documentation next to a theming widget that can +// switch it between the Material, Fluent, Bootstrap and Indigo themes in light +// or dark, so the theme is loaded as a swappable stylesheet instead - see the +// `igniteui-theme` link in index.html, the `assets/themes` entry in angular.json +// and `src/app/services/theme.service.ts`. A theme compiled in here would sit +// later in the cascade and win over the one the visitor picked. + // Specifies large size for all components to match the previous defaults // This may not be needed for your project. Please consult https://www.infragistics.com/products/ignite-ui-angular/angular/components/general/update-guide for more details. :root { @@ -19,6 +27,13 @@ body { margin: 0; } +// Nothing here paints a page background per color mode on purpose. The sample +// is embedded in an iframe and the documentation's Sample component draws the +// surface behind it from the same mode the theming widget posts down here, so +// the iframe is left transparent for it to show through. `ThemeService` still +// reflects `data-ig-theme` / `data-ig-mode` onto the root element for samples +// that need to react to the selection themselves. + body.custom-body:has( app-badge-overview, app-badge-styling, @@ -34,16 +49,8 @@ body.custom-body:has( background: transparent; } -@include core(); -@include typography(); -@include theme( - $palette: $palette, - $schema: $schema -); - -:root { - @include palette($palette); -} +// `core()`, `typography()`, `theme()` and the root palette all ship inside the +// prebuilt stylesheets loaded through the `igniteui-theme` link (see above). .light-theme { @include light-theme($palette);