diff --git a/.github/workflows/deploy-trigger.yml b/.github/workflows/deploy-trigger.yml index 1efbc9a3d8..329a838a36 100644 --- a/.github/workflows/deploy-trigger.yml +++ b/.github/workflows/deploy-trigger.yml @@ -85,4 +85,4 @@ jobs: unit: false, integration: true } - }); \ No newline at end of file + }); diff --git a/live-editing/Routes.ts b/live-editing/Routes.ts index 8b37443186..969036b830 100644 --- a/live-editing/Routes.ts +++ b/live-editing/Routes.ts @@ -9,6 +9,7 @@ import * as TreeGridDvRoutingModule from '../projects/app-lob/src/app/tree-grid/ import * as DataDisplayRouting from '../src/app/data-display/data-display.routes'; import * as DataEntriesRouting from '../src/app/data-entries/data-entries.routes'; import * as GridRouting from '../src/app/grid/grids.routes'; +import * as GridLiteRouting from '../src/app/grid-lite/grid-lite.routes'; import * as PivotGridRouting from '../src/app/pivot-grid/pivot-grids.routes'; import * as HierarchicalGridRouting from '../src/app/hierarchical-grid/hierarchical-grid.routes'; import * as InteractionsRouting from '../src/app/interactions/interactions.routes'; @@ -68,6 +69,10 @@ export const MODULE_ROUTES = [ path: 'grid', routes: GridRouting.GridsRoutes }, + { + path: 'grid-lite', + routes: GridLiteRouting.GridLiteRoutes + }, { path: 'pivot-grid', routes: PivotGridRouting.PivotGridsRoutes diff --git a/live-editing/configs/GridLiteConfigGenerator.ts b/live-editing/configs/GridLiteConfigGenerator.ts new file mode 100644 index 0000000000..fa50c8afdf --- /dev/null +++ b/live-editing/configs/GridLiteConfigGenerator.ts @@ -0,0 +1,140 @@ +import { Config, IConfigGenerator } from 'igniteui-live-editing' +import { BaseAppConfig } from './BaseConfig'; + +export class GridLiteConfigGenerator implements IConfigGenerator { + public additionalImports = { + //GridLiteDataService: '../../src/app/grid-lite/grid-lite-data.service.ts' + }; + + public generateConfigs(): Config[] { + const configs = new Array(); + + configs.push(new Config({ + component: 'GridLiteOverviewComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteColumnConfigSimpleComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteColumnConfigDynamicComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteColumnConfigHeadersComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteDataBindingDynamicComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteFilteringSimpleComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteFilteringEventsComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteFilteringPipelineComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteSortingSimpleComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteSortingEventsComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteSortingGridConfigComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteSortingPipelineComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteStylingCustomComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + configs.push(new Config({ + component: 'GridLiteStylingThemesComponent', + additionalDependencies: ['igniteui-grid-lite'], + additionalFiles: [ + '/src/app/grid-lite/grid-lite-data.service.ts' + ], + appConfig: BaseAppConfig + })); + + return configs; + }; +} \ No newline at end of file diff --git a/live-editing/generators/ConfigGenerators.ts b/live-editing/generators/ConfigGenerators.ts index f3e2cac078..737037792f 100644 --- a/live-editing/generators/ConfigGenerators.ts +++ b/live-editing/generators/ConfigGenerators.ts @@ -1,5 +1,3 @@ -import { Config, IConfigGenerator } from 'igniteui-live-editing' -import { BaseAppConfig } from './BaseConfig';; import { ActionStripConfigGenerator } from '../configs/ActionStripConfigGenerator'; import { AutocompleteConfigGenerator } from '../configs/AutocompleteConfigGenerator'; import { AvatarConfigGenerator } from '../configs/AvatarConfigGenerator'; @@ -64,6 +62,7 @@ import { PaginationConfigGenerator } from '../configs/PaginationConfigGenerator' import { PivotGridConfigGenerator } from '../configs/PivotGridConfigGenerator'; import { QueryBuilderConfigGenerator } from '../configs/QueryBuilderConfigGenerator'; import { TileManagerConfigGenerator } from '../configs/TileManagerConfigGenerator'; +import { GridLiteConfigGenerator } from '../configs/GridLiteConfigGenerator'; export const CONFIG_GENERATORS = [ @@ -118,6 +117,7 @@ export const CONFIG_GENERATORS = HierarchicalGridConfigGenerator, TreeGridConfigGenerator, PivotGridConfigGenerator, + GridLiteConfigGenerator, // other: ActionStripConfigGenerator, diff --git a/package-lock.json b/package-lock.json index 72aad866bb..fae45a8147 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,12 +35,13 @@ "express": "^4.18.2", "file-saver": "^2.0.2", "hammerjs": "^2.0.8", - "igniteui-angular": "^20.1.4", + "igniteui-angular": "^20.1.6", "igniteui-angular-charts": "^20.1.0", "igniteui-angular-core": "^20.1.0", "igniteui-angular-extras": "^20.0.2", "igniteui-angular-i18n": "^20.1.4", "igniteui-dockmanager": "^1.17.0", + "igniteui-grid-lite": "1.0.0-alpha.9", "igniteui-live-editing": "^3.2.0", "igniteui-webcomponents": "^6.2.0", "minireset.css": "0.0.6", @@ -12561,14 +12562,14 @@ "license": "BSD-3-Clause" }, "node_modules/igniteui-angular": { - "version": "20.1.4", - "resolved": "https://registry.npmjs.org/igniteui-angular/-/igniteui-angular-20.1.4.tgz", - "integrity": "sha512-IhHfhDtcjpATs2ap97BelZDhl04lWCzsfngTplWsSvNfvodCGEeVqKlrFv7R++0TP9cv+vWsbb3S6Mp1imyGDQ==", + "version": "20.1.6", + "resolved": "https://registry.npmjs.org/igniteui-angular/-/igniteui-angular-20.1.6.tgz", + "integrity": "sha512-8JiuQTKFWEhBe8x8MfU7IVpr0uW3uxB4XCgsB9tQUicJvsPOrdIUmu9b36G96FhUoKimIumpjY5K6o9d1cVpOA==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@igniteui/material-icons-extended": "^3.1.0", "fflate": "^0.8.1", - "igniteui-theming": "^21.0.2", + "igniteui-theming": "^22.0.0", "igniteui-trial-watermark": "^3.1.0", "lodash-es": "^4.17.21", "tslib": "^2.3.0" @@ -12636,9 +12637,9 @@ } }, "node_modules/igniteui-angular-i18n": { - "version": "20.1.4", - "resolved": "https://registry.npmjs.org/igniteui-angular-i18n/-/igniteui-angular-i18n-20.1.4.tgz", - "integrity": "sha512-pwJTCMv+DiuibVD2dhi9upoab8scBC/EZFQwNG54fu8ZtHXYOXNr5Ge2gpqSir283Q5nehti//okhkVDZ63eZw==", + "version": "20.1.6", + "resolved": "https://registry.npmjs.org/igniteui-angular-i18n/-/igniteui-angular-i18n-20.1.6.tgz", + "integrity": "sha512-1TQk/g54ohVbw+iyLZMnnl5C5FcDIZzL0V5SLTt+sH5H89J+1FWPkSLkc/n5rIqbOMJopW9QakdjlUFgBwJLEA==", "license": "MIT" }, "node_modules/igniteui-dockmanager": { @@ -12656,6 +12657,36 @@ "integrity": "sha512-q6thtu+7R6MOB+i9GorFPCcWeOImW43BzCAtKnDAYWwaoueb8Lg1EhBkIhAyfEIH+yZ/9c5lnZdU61/GRPoP+g==", "license": "Apache-2.0" }, + "node_modules/igniteui-grid-lite": { + "version": "1.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-1.0.0-alpha.9.tgz", + "integrity": "sha512-LxyUDHf/lTTbAAupup8HovSKsy1qgTUp4btrWVRQDFq2HI2s75UroplNGSX1yLfy3VCMEf8xY0sciM2tyFgzQQ==", + "license": "MIT", + "dependencies": { + "@lit-labs/virtualizer": "~2.1.0", + "@lit/context": "~1.1.5", + "igniteui-webcomponents": "~6.1.0", + "lit": "^3.3.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/igniteui-grid-lite/node_modules/igniteui-webcomponents": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-6.1.2.tgz", + "integrity": "sha512-q3a3Q28xzRwDBmfDprY0PsN9cs5xgqOJigXWWmbWAfcMgPg5dIrPyMDV6Aj6GD7u1RgPeoZmTP/pz9gTWNhHJA==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@floating-ui/dom": "^1.7.0", + "@lit-labs/virtualizer": "^2.1.0", + "@lit/context": "^1.1.0", + "lit": "^3.3.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/igniteui-live-editing": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/igniteui-live-editing/-/igniteui-live-editing-3.2.0.tgz", @@ -12663,9 +12694,9 @@ "license": "MIT" }, "node_modules/igniteui-theming": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-21.0.2.tgz", - "integrity": "sha512-RXs8b3PThVlS1FhLeUT9TlLMcPoNAiwJm/L+jHU7jrwsgZU7gGjipjEbQQRe97AURyTxgXKiC4M8CAuUilWQ2A==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-22.1.0.tgz", + "integrity": "sha512-Fi3QaVXTX6sLfEAXEQn96yfw3xWpHCIibOl8joWXH6H3GWjAgupF6WHBSewOPeS9z9Ei5Lh/MfmktW8jaqwiaQ==", "license": "MIT" }, "node_modules/igniteui-trial-watermark": { diff --git a/package.json b/package.json index f11155a678..0eaaefde2d 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,8 @@ "express": "^4.18.2", "file-saver": "^2.0.2", "hammerjs": "^2.0.8", - "igniteui-angular": "^20.1.4", + "igniteui-grid-lite": "1.0.0-alpha.9", + "igniteui-angular": "^20.1.6", "igniteui-angular-charts": "^20.1.0", "igniteui-angular-core": "^20.1.0", "igniteui-angular-extras": "^20.0.2", diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index d83b139643..e89bdcf71d 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -57,6 +57,10 @@ export const SamplesRoutes: Routes = [ loadChildren: () => import('./grid/grids.routes').then(m => m.GridsRoutes), path: 'grid' }, + { + loadChildren: () => import('./grid-lite/grid-lite.routes').then(m => m.GridLiteRoutes), + path: 'grid-lite' + }, { loadChildren: () => import('./pivot-grid/pivot-grids.routes').then(m => m.PivotGridsRoutes), path: 'pivot-grid' diff --git a/src/app/data-display/chip/chip-styling/chip-styling.component.html b/src/app/data-display/chip/chip-styling/chip-styling.component.html index 7f46d62b8d..7d388ed335 100644 --- a/src/app/data-display/chip/chip-styling/chip-styling.component.html +++ b/src/app/data-display/chip/chip-styling/chip-styling.component.html @@ -1,23 +1,8 @@ - + @for (chip of chipList; track chip) { - - {{chip.icon}} + + {{chip.text}} } - - - check_circle - - - - delete - diff --git a/src/app/data-display/chip/chip-styling/chip-styling.component.scss b/src/app/data-display/chip/chip-styling/chip-styling.component.scss index 02eda91f02..d6f8c34742 100644 --- a/src/app/data-display/chip/chip-styling/chip-styling.component.scss +++ b/src/app/data-display/chip/chip-styling/chip-styling.component.scss @@ -1,11 +1,48 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$custom-theme: chip-theme( - $background: #57a5cd, - $selected-background: #ecaa53, - $remove-icon-color: #d81414, - $border-radius: 5px, -); - -@include css-vars($custom-theme); +// CSS variables approach + +igx-chip { + --text-color: #fff; + --hover-text-color: #fff; + --focus-text-color: #fff; + --border-radius: #{rem(5px)}; +} + +.xcom { + --background: #000; + --hover-background: #000; + --focus-background: #323232; +} + +.youtube { + --background: #cd201f; + --hover-background: #cd201f; + --focus-background: #9f1717; +} + +.facebook { + --background: #3b5999; + --hover-background: #3b5999; + --focus-background: #2c4378; +} + +.linkedin { + --background: #55acee; + --hover-background: #55acee; + --focus-background: #4682af; +} + +// Sass theme approach + +// $custom-chip-theme: chip-theme( +// $background: #cd201f, +// $text-color: #fff, +// $hover-background: #cd201f, +// $focus-background: #9f1717, +// $border-radius: rem(5px) +// ); + +// @include css-vars($custom-chip-theme) + \ No newline at end of file diff --git a/src/app/data-display/chip/chip-styling/chip-styling.component.ts b/src/app/data-display/chip/chip-styling/chip-styling.component.ts index a50d6de308..20fbb999c6 100644 --- a/src/app/data-display/chip/chip-styling/chip-styling.component.ts +++ b/src/app/data-display/chip/chip-styling/chip-styling.component.ts @@ -1,52 +1,51 @@ -import { ChangeDetectorRef, Component, inject } from '@angular/core'; -import { IBaseChipEventArgs, IChipsAreaReorderEventArgs, IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective } from 'igniteui-angular'; - +import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core'; +import { facebook, linkedin } from '@igniteui/material-icons-extended'; +import { + IgxChipsAreaComponent, + IgxChipComponent, + IgxIconComponent, + IgxPrefixDirective, + IgxIconService +} from 'igniteui-angular'; +import { NgClass } from '@angular/common'; @Component({ - selector: 'app-chip', - styleUrls: ['./chip-styling.component.scss'], - templateUrl: './chip-styling.component.html', - imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective] + selector: 'app-chip', + styleUrls: ['./chip-styling.component.scss'], + templateUrl: './chip-styling.component.html', + imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective, NgClass] }) -export class ChipStylingSampleComponent { - changeDetectionRef = inject(ChangeDetectorRef); - - public chipList = [ - { - text: 'Country', - id: '1', - icon: 'place' - }, - { - text: 'City', - id: '2', - icon: 'location_city' - }, - { - text: 'Town', - id: '3', - icon: 'store' - }, - { - text: 'First Name', - id: '4', - icon: 'person_pin' - } - ]; - - - public chipRemoved(event: IBaseChipEventArgs) { - this.chipList = this.chipList.filter((item) => item.id !== event.owner.id); - this.changeDetectionRef.detectChanges(); - } +export class ChipStylingSampleComponent implements OnInit { + changeDetectionRef = inject(ChangeDetectorRef); + private iconService = inject(IgxIconService) + public ngOnInit() { + this.iconService.addSvgIconFromText('x', ''); + this.iconService.addSvgIconFromText('youtube', ' '); + this.iconService.addSvgIconFromText(facebook.name, facebook.value); + this.iconService.addSvgIconFromText(linkedin.name, linkedin.value); + } - public chipsOrderChanged(event: IChipsAreaReorderEventArgs) { - const newChipList = []; - for (const chip of event.chipsArray) { - const chipItem = this.chipList.filter((item) => item.id === chip.id)[0]; - newChipList.push(chipItem); - } - this.chipList = newChipList; + public chipList = [ + { + text: 'X.com', + class: 'xcom', + icon: 'x' + }, + { + text: 'Youtube', + class: 'youtube', + icon: 'youtube' + }, + { + text: 'Facebook', + class: 'facebook', + icon: 'facebook' + }, + { + text: 'LinkedIn', + class: 'linkedin', + icon: 'linkedin' } + ]; } diff --git a/src/app/data-display/chip/chip-styling/layout.scss b/src/app/data-display/chip/chip-styling/layout.scss index 619dc177ee..f80fd2f1c4 100644 --- a/src/app/data-display/chip/chip-styling/layout.scss +++ b/src/app/data-display/chip/chip-styling/layout.scss @@ -1,4 +1,23 @@ +@use "igniteui-angular/theming" as *; + +:host { + ::ng-deep { + .igx-chip__item { + height: rem(20px); + font-size: rem(12px); + } + } +} + igx-chip { - margin-right: 5px; - margin-top: 20px; + margin-right: rem(8px); + margin-top: rem(20px); +} + +igx-chips-area { + margin-left: rem(20px); +} + +igx-icon { + --size: #{rem(12px)}; } \ No newline at end of file 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 index 349481f203..8eee79e1d3 100644 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.html +++ b/src/app/data-entries/buttons/buttons-style/buttons-style.component.html @@ -1,17 +1,22 @@ -
-
- +@for (item of range; let i = $index; track i) { +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
-
- -
-
- -
-
- -
-
- -
-
\ No newline at end of file +} \ 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 index c0b38ce1e9..bd11ce2997 100644 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.scss +++ b/src/app/data-entries/buttons/buttons-style/buttons-style.component.scss @@ -1,25 +1,216 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; +@use "sass:map"; -$custom-contained-theme: contained-button-theme( - $background: #348ae0 -); +// CSS variables approach -$custom-flat-theme: flat-button-theme( - $foreground: var(--ig-error-800) +$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, + ), ); -$custom-outlined-theme: outlined-button-theme( - $foreground: var(--ig-success-500) -); +@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")}; + } -$custom-fab-theme: fab-button-theme( - $background: #ffc506 -); + @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-button-theme: button-theme( +// $background: #f9f0ff, +// $foreground: #722ed1, +// $border-color: #722ed1, +// $hover-background: #efdbff, +// $hover-foreground: #9254de, +// $hover-border-color: #9254de, +// $active-border-color: #531dab, +// $active-foreground: #531dab, +// $focus-visible-background: #f9f0ff, +// ); -.button-sample { - @include css-vars($custom-contained-theme); - @include css-vars($custom-flat-theme); - @include css-vars($custom-outlined-theme); - @include css-vars($custom-fab-theme); -}; \ No newline at end of file +// .button-sample { +// @include css-vars($custom-button-theme) +// } \ No newline at end of file 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 index a0380ea08c..657abb2a96 100644 --- a/src/app/data-entries/buttons/buttons-style/buttons-style.component.ts +++ b/src/app/data-entries/buttons/buttons-style/buttons-style.component.ts @@ -1,10 +1,13 @@ import { Component } from '@angular/core'; -import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular'; +import { IgxButtonDirective, THEME_TOKEN, ThemeToken } from 'igniteui-angular'; @Component({ selector: 'app-buttons-style', styleUrls: ['./buttons-style.component.scss'], templateUrl: './buttons-style.component.html', - imports: [IgxButtonDirective, IgxRippleDirective] + imports: [IgxButtonDirective], + providers: [{provide: THEME_TOKEN, useFactory: () => new ThemeToken('bootstrap')}] }) -export class ButtonsStyleComponent { } +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 index 36396d2d00..43cf337fa2 100644 --- a/src/app/data-entries/buttons/buttons-style/layout.scss +++ b/src/app/data-entries/buttons/buttons-style/layout.scss @@ -1,9 +1,47 @@ -.buttons-sample { - display: flex; - margin: 8px; +@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 { - display: flex; - margin-right: 16px; + 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/checkbox/checkbox-styling/checkbox-styling.component.html b/src/app/data-entries/checkbox/checkbox-styling/checkbox-styling.component.html index 1e959d579a..5d1a2f56c9 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,3 @@ - - Styled checkbox - + + Styled checkbox + \ No newline at end of file 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 c5b8a77146..9c88a08ec9 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,10 +1,36 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$custom-checkbox-theme: checkbox-theme( - $empty-color: #ecaa53, - $fill-color: #ecaa53, - $border-radius: 5px -); +// CSS variables approach -@include css-vars($custom-checkbox-theme); +igx-checkbox { + --tick-color: #0064d9; + --tick-color-hover: #e3f0ff; + --tick-width: 2; + --fill-color: transparent; + --fill-color-hover: #e3f0ff; + --label-color: #131e29; + --focus-outline-color: #0032a5; + --border-radius: #{rem(4px)}; +} + +igx-checkbox:hover { + --empty-fill-color: #e3f0ff; +} + +// Sass theme approach + +// $custom-checkbox-theme: checkbox-theme( +// $tick-color: #0064d9, +// $tick-width: 2, +// $tick-color-hover: #e3f0ff, +// $fill-color: transparent, +// $fill-color-hover: #e3f0ff, +// $label-color: #131e29, +// $focus-outline-color: #0032a5, +// $empty-color: #131e29, +// $border-radius: rem(4px), +// ); +// +// @include css-vars($custom-checkbox-theme); +// 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 3bd791043a..3f45dcb2b8 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,10 +1,12 @@ import { Component } from '@angular/core'; -import { IgxCheckboxComponent } from 'igniteui-angular'; +import { IgxCheckboxComponent, THEME_TOKEN, ThemeToken } from 'igniteui-angular'; @Component({ - selector: 'app-checkbox-styling', - styleUrls: ['./checkbox-styling.component.scss'], - templateUrl: './checkbox-styling.component.html', - imports: [IgxCheckboxComponent] + selector: 'app-checkbox-styling', + styleUrls: ['./checkbox-styling.component.scss'], + templateUrl: './checkbox-styling.component.html', + providers: [{ provide: THEME_TOKEN, useFactory: () => new ThemeToken('fluent') }], + imports: [IgxCheckboxComponent] }) -export class CheckboxStylingComponent { } +export class CheckboxStylingComponent { +} diff --git a/src/app/data-entries/checkbox/checkbox-styling/layout.scss b/src/app/data-entries/checkbox/checkbox-styling/layout.scss index 7f3591cc5a..b3d179bdc1 100644 --- a/src/app/data-entries/checkbox/checkbox-styling/layout.scss +++ b/src/app/data-entries/checkbox/checkbox-styling/layout.scss @@ -1,4 +1,45 @@ +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/checkbox/checkbox-component" as checkbox; +@use "sass:map"; + +:host { + ::ng-deep { + $_checkbox-schema: map.get($light-fluent-schema, checkbox); + @include checkbox(checkbox-theme($schema: $_checkbox-schema)); + @include checkbox.component(); + + // Note: This is not the standard approach for styling the component. + // We're using it here solely to mirror the UI5 sample. + + .igx-checkbox--checked .igx-checkbox__composite-wrapper .igx-checkbox__composite { + border-color: var(--empty-color); + } + + .igx-checkbox__composite { + min-width: rem(18px); + height: rem(18px); + } + + .igx-checkbox--checked:hover .igx-checkbox__composite-wrapper .igx-checkbox__composite { + border-color: var(--empty-color); + } + + .igx-checkbox__label { + margin-inline-start: auto; + } + } +} + igx-checkbox { + --ig-font-family: Arial, Helvetica, sans-serif; + --ig-subtitle-1-font-size: #{rem(14px)}; + display: flex; - padding: 16px; -} \ No newline at end of file + margin: rem(18px) 0 0 rem(18px); +} + +#checkbox-1.igx-checkbox--focused:after { + inset: rem(7px) rem(-6px) rem(7px) rem(6px); + border-radius: rem(8px); + box-shadow: 0 0 0 rem(2px) var(--focus-outline-color); +} diff --git a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.html b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.html index 85d8543382..d9fdfb886f 100644 --- a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.html +++ b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.html @@ -1,21 +1,7 @@
- - +359 - - - - phone - - Ex.: +359 888 123 456 + + + + Helper text - - - +359 - - - - phone - - Ex.: +359 888 123 456 - -
+ \ No newline at end of file diff --git a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.scss b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.scss index cf5356ec80..39ee2fd71d 100644 --- a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.scss +++ b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.scss @@ -1,19 +1,35 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -.sample-column { - gap: 1rem; +// CSS variables approach + +igx-input-group { + --border-color: #0f62fe; + --size: #{rem(40px)}; + --idle-bottom-line-color: #8d8d8d; + --hover-bottom-line-color: #8d8d8d; + --hover-placeholder-color: var(--ig-gray-600); + --idle-secondary-color: var(--ig-gray-600); + --focused-secondary-color: var(--ig-gray-700); + --focused-bottom-line-color: #8d8d8d; + --box-background-hover: var(--ig-gray-100); + --helper-text-color: var(--ig-gray-600); } -$custom-input-group: input-group-theme( - $border-color: #57a5cd, - $filled-text-color: #288a54, - $focused-text-color: #174f30, - $idle-text-color: #288a54, - $idle-bottom-line-color: #288a54, - $hover-bottom-line-color: #288a54, - $focused-secondary-color: #174f30, - $box-background: #57a5cd -); +// Sass theme approach + +// $custom-input-group: input-group-theme( +// $border-color: #0f62fe, +// $idle-bottom-line-color: #8d8d8d, +// $hover-bottom-line-color: #8d8d8d, +// $hover-placeholder-color: var(--ig-gray-600), +// $idle-secondary-color: var(--ig-gray-600), +// $focused-secondary-color: var(--ig-gray-700), +// $size: rem(40px), +// $box-border-radius: 0, +// $box-background-hover: var(--ig-gray-100), +// $placeholder-color: var(--ig-gray-600), +// $helper-text-color: var(--ig-gray-600) +// ); -@include css-vars($custom-input-group); +// @include css-vars($custom-input-group); \ No newline at end of file diff --git a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.ts b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.ts index e0d175f820..e98bc90dd6 100644 --- a/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.ts +++ b/src/app/data-entries/input-group/input-group-styling/input-group-styling.component.ts @@ -1,10 +1,11 @@ import { Component } from '@angular/core'; -import { IgxInputGroupComponent, IgxPrefixDirective, IgxLabelDirective, IgxInputDirective, IgxSuffixDirective, IgxIconComponent, IgxHintDirective } from 'igniteui-angular'; +import { IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective, IgxHintDirective, THEME_TOKEN, ThemeToken } from 'igniteui-angular'; @Component({ selector: 'app-input-group-style', templateUrl: 'input-group-styling.component.html', styleUrls: ['input-group-styling.component.scss'], - imports: [IgxInputGroupComponent, IgxPrefixDirective, IgxLabelDirective, IgxInputDirective, IgxSuffixDirective, IgxIconComponent, IgxHintDirective] + imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective, IgxHintDirective], + providers: [{provide: THEME_TOKEN, useFactory: () => new ThemeToken('indigo')}] }) export class InputGroupStyleComponent { } diff --git a/src/app/data-entries/input-group/input-group-styling/layout.scss b/src/app/data-entries/input-group/input-group-styling/layout.scss index fc4259acbb..74026e1dc1 100644 --- a/src/app/data-entries/input-group/input-group-styling/layout.scss +++ b/src/app/data-entries/input-group/input-group-styling/layout.scss @@ -1,3 +1,53 @@ -.sample-column { - max-width: 550px; +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/input/input-group-component" as input; +@use "sass:map"; + +:host { + ::ng-deep { + $_input-schema: map.get($light-indigo-schema, input-group); + @include input-group(input-group-theme($schema: $_input-schema)); + @include input.component(); + + // Note: This is not the standard approach for styling the component. + // We're using it here solely to mirror the Carbon sample. + + .igx-input-group__bundle { + background: var(--box-background-hover); + + [igxinput].igx-input-group__input { + letter-spacing: rem(0.16px); + padding-block: 0; + padding-inline: rem(12px); + font-size: rem(14px); + } + + input::placeholder { + font-size: rem(14px); + font-style: normal; + opacity: 0.7; + font-weight: 300; + font-family: "IBM Plex Sans", sans-serif; + } + } + + .igx-input-group--focused .igx-input-group__bundle::after { + border-block-end: 0; + inset: 0; + pointer-events: none; + box-shadow: inset 0 0 0 rem(2px) var(--border-color); + } + + .igx-input-group__label, igx-hint { + font-weight: 300; + } + } +} + +igx-input-group { + --ig-font-family: "IBM Plex Sans", sans-serif; } + +.sample-column { + max-width: rem(300px); + margin-top: rem(24px); +} \ No newline at end of file diff --git a/src/app/data-entries/radio/radio-styling-sample/layout.scss b/src/app/data-entries/radio/radio-styling-sample/layout.scss index a275b1e4e2..3c6fc3501a 100644 --- a/src/app/data-entries/radio/radio-styling-sample/layout.scss +++ b/src/app/data-entries/radio/radio-styling-sample/layout.scss @@ -1,9 +1,54 @@ +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/radio/radio-component" as radio; +@use "sass:map"; + +:host { + ::ng-deep{ + $_radio-schema: map.get($light-fluent-schema, radio); + @include radio(radio-theme($schema: $_radio-schema)); + @include radio.component(); + + // Note: This is not the standard approach for styling the component. + // We're using it here solely to mirror the UI5 sample. + + .igx-radio--checked .igx-radio__composite::after { + --fill-color: #556b81; + } + + .igx-radio__composite::after, + .igx-radio__composite::before, + .igx-radio__composite { + width: rem(18px); + height: rem(18px); + } + + .igx-radio__composite { + min-width: rem(18px); + } + + .igx-radio__ripple { + display: none; + } + } +} + igx-radio + igx-radio { - margin-top: 16px; + margin-top: 1rem; +} + +igx-radio { + --ig-subtitle-1-font-size: #{rem(14px)}; + --ig-font-family: Arial,Helvetica,sans-serif; } .radio-wrapper { - display: flex; - flex-flow: column nowrap; - padding: 16px; + display: flex; + flex-flow: column nowrap; + padding: 1rem; +} + +.igx-radio--focused::after { + inset: rem(1px) rem(-4px) rem(1px) rem(-2px); + border-radius: rem(8px); + box-shadow: 0 0 0 rem(2px) var(--focus-outline-color); } \ No newline at end of file diff --git a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.html b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.html index be0ba57fc4..3ad4431519 100644 --- a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.html +++ b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.html @@ -3,5 +3,5 @@ London Sofia Tokyo - Singapore -
+ Singapore + \ No newline at end of file diff --git a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.scss b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.scss index c2c3383809..93e3f63db7 100644 --- a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.scss +++ b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.scss @@ -1,9 +1,30 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$custom-radio-theme: radio-theme( - $empty-color: #345779, - $fill-color: #2dabe8, -); +// CSS variables approach -@include css-vars($custom-radio-theme); +igx-radio { + --empty-color: #556b81; + --label-color: #131e29; + --fill-color: #0064d9; + --focus-outline-color: #0032a5; +} + +igx-radio:hover { + --empty-fill-color: #e3f0ff; + --empty-color: #0064d9; + --hover-color: transparent; +} + +// Sass theme approach + +// $custom-radio-theme: radio-theme( +// $empty-color: #556b81, +// $label-color: #131e29, +// $fill-color: #0064d9, +// $focus-outline-color: #0032a5, +// $fill-color-hover: #0064d9, +// $hover-color: transparent +// ); + +// @include css-vars($custom-radio-theme); diff --git a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.ts b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.ts index 9881fad3fb..8972a6018b 100644 --- a/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.ts +++ b/src/app/data-entries/radio/radio-styling-sample/radio-styling-sample.component.ts @@ -3,11 +3,11 @@ import { IgxRadioComponent } from 'igniteui-angular'; import { FormsModule } from '@angular/forms'; @Component({ - selector: 'app-radio-sample-1', - styleUrls: ['./radio-styling-sample.component.scss'], - templateUrl: './radio-styling-sample.component.html', - imports: [IgxRadioComponent, FormsModule] + selector: 'app-radio-sample-1', + styleUrls: ['./radio-styling-sample.component.scss'], + templateUrl: './radio-styling-sample.component.html', + imports: [IgxRadioComponent, FormsModule] }) export class RadioStylingSampleComponent { - public selected: string; + public selected: string; } diff --git a/src/app/data-entries/switch/switch-styling/layout.scss b/src/app/data-entries/switch/switch-styling/layout.scss index dfc9dd1daf..b248011ce1 100644 --- a/src/app/data-entries/switch/switch-styling/layout.scss +++ b/src/app/data-entries/switch/switch-styling/layout.scss @@ -1,9 +1,61 @@ +@use "igniteui-angular/theming" as *; +@use "igniteui-angular/lib/core/styles/components/switch/switch-component" as switch; +@use 'sass:map'; + +:host { + ::ng-deep { + $_switch-schema: map.get($light-fluent-schema, switch); + @include switch(switch-theme($schema: $_switch-schema)); + @include switch.component(); + + // 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: 24px; + margin-top: rem(24px); + width: max-content; +} + +igx-switch:hover { + --track-off-color: #637d97; } .switch-wrapper { - display: flex; - flex-flow: column nowrap; - padding: 16px; + 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.scss b/src/app/data-entries/switch/switch-styling/switch-styling.component.scss index e85a3e4c51..f016f72976 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,9 +1,38 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$custom-switch-theme: switch-theme( - $thumb-off-color: #7cadd5, - $thumb-on-color: #ecaa53, -); +// CSS variables approach -@include css-vars($custom-switch-theme); +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, +// ); + +// @include css-vars($custom-switch-theme) 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 b6d5f3dece..16d3ee69a2 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,17 +1,16 @@ import { Component } from '@angular/core'; - import { IgxSwitchComponent } from 'igniteui-angular'; @Component({ - selector: 'app-switch-styling', - styleUrls: ['./switch-styling.component.scss'], - templateUrl: './switch-styling.component.html', - imports: [IgxSwitchComponent] + selector: 'app-switch-styling', + styleUrls: ['./switch-styling.component.scss'], + templateUrl: './switch-styling.component.html', + imports: [IgxSwitchComponent] }) export class SwitchStylingComponent { public settings = [ - { name: 'WiFi', state: false}, - { name: 'Bluetooth', state: true}, - { name: 'Device visibility', state: false} + { name: 'WiFi', state: false }, + { name: 'Bluetooth', state: true }, + { name: 'Device visibility', state: false } ]; } diff --git a/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.html b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.html new file mode 100644 index 0000000000..43bfef6008 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.html @@ -0,0 +1,17 @@ +
+
+ Column properties + + Value formatters: + +
+ + + +
diff --git a/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.scss b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.scss new file mode 100644 index 0000000000..e5cc3df9ac --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.scss @@ -0,0 +1,21 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: calc(100% - 50px); +} + +.panel { + margin: 1rem 0; + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + align-items: center; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.ts b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.ts new file mode 100644 index 0000000000..fe2717ecac --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component.ts @@ -0,0 +1,111 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, ViewChild, ElementRef, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcButtonComponent, IgcCheckboxComponent, IgcDropdownComponent, IgcSwitchComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcCheckboxComponent, IgcDropdownComponent, IgcSwitchComponent, IgcButtonComponent); + +@Component({ + selector: 'app-grid-lite-column-config-dynamic', + templateUrl: './grid-lite-column-config-dynamic.component.html', + styleUrls: ['./grid-lite-column-config-dynamic.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteColumnConfigDynamicComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + @ViewChild('gridLite', { static: false }) gridLite!: ElementRef; + + public data: ProductInfo[] = []; + public columns: any[] = []; + public hasFormatters = true; + + private formatter = new Intl.NumberFormat('en-EN', { + style: 'currency', + currency: 'EUR' + }); + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + + this.columns = [ + { + key: 'id', + hidden: true, + headerText: 'ID', + width: '15rem' + }, + { + key: 'name', + headerText: 'Product Name', + width: '15rem' + }, + { + key: 'price', + headerText: 'Price', + type: 'number', + width: '15rem', + cellTemplate: (params: any) => { + const span = document.createElement('span'); + span.textContent = this.formatter.format(params.value); + return span; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Units sold', + width: '15rem' + }, + { + key: 'total', + headerText: 'Total sold', + width: '15rem', + cellTemplate: (params: any) => { + const span = document.createElement('span'); + span.textContent = this.formatter.format(params.value); + return span; + } + }, + { + key: 'rating', + type: 'number', + headerText: 'Customer rating', + width: '15rem', + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + } + ]; + } + + updateColumnProperty(key: string, prop: string, value: any) { + const grid = this.gridLite?.nativeElement as any; + if (grid && grid.updateColumns) { + grid.updateColumns({ key, [prop]: value }); + } + } + + toggleFormatters(enabled: boolean) { + this.hasFormatters = enabled; + const grid = this.gridLite?.nativeElement as any; + if (grid && grid.updateColumns) { + const updates = ['price', 'total'].map(key => ({ + key, + cellTemplate: enabled ? (params: any) => { + const span = document.createElement('span'); + span.textContent = this.formatter.format(params.value); + return span; + } : undefined + })); + grid.updateColumns(updates); + } + } +} diff --git a/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.html b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.html new file mode 100644 index 0000000000..9b6326efb4 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.html @@ -0,0 +1,6 @@ +
+ + +
diff --git a/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.scss b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.scss new file mode 100644 index 0000000000..0c5a800394 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.scss @@ -0,0 +1,13 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.ts b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.ts new file mode 100644 index 0000000000..cefaadf5ef --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-headers/grid-lite-column-config-headers.component.ts @@ -0,0 +1,60 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent); + +@Component({ + selector: 'app-grid-lite-column-config-headers', + templateUrl: './grid-lite-column-config-headers.component.html', + styleUrls: ['./grid-lite-column-config-headers.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteColumnConfigHeadersComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + + this.columns = [ + { + key: 'name', + headerText: 'Product Name' + }, + { + key: 'price', + headerText: 'Price (€)', + type: 'number' + }, + { + key: 'sold', + type: 'number', + headerText: 'Units Sold' + }, + { + key: 'total', + headerText: 'Total Revenue', + type: 'number' + }, + { + key: 'rating', + type: 'number', + headerText: 'Customer Rating ⭐', + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + } + ]; + } +} diff --git a/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.html b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.html new file mode 100644 index 0000000000..9b6326efb4 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.html @@ -0,0 +1,6 @@ +
+ + +
diff --git a/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.scss b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.scss new file mode 100644 index 0000000000..0c5a800394 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.scss @@ -0,0 +1,13 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.ts b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.ts new file mode 100644 index 0000000000..86cc1c7ad7 --- /dev/null +++ b/src/app/grid-lite/grid-lite-column-config-simple/grid-lite-column-config-simple.component.ts @@ -0,0 +1,74 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent); + +@Component({ + selector: 'app-grid-lite-column-config-simple', + templateUrl: './grid-lite-column-config-simple.component.html', + styleUrls: ['./grid-lite-column-config-simple.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteColumnConfigSimpleComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + + private formatter = new Intl.NumberFormat('en-EN', { + style: 'currency', + currency: 'EUR' + }); + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + + this.columns = [ + { + key: 'name', + headerText: 'Product Name' + }, + { + key: 'price', + headerText: 'Price', + type: 'number', + cellTemplate: (params: any) => { + const span = document.createElement('span'); + span.textContent = this.formatter.format(params.value); + return span; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Units sold' + }, + { + key: 'total', + headerText: 'Total sold', + cellTemplate: (params: any) => { + const span = document.createElement('span'); + span.textContent = this.formatter.format(params.value); + return span; + } + }, + { + key: 'rating', + type: 'number', + headerText: 'Customer rating', + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + } + ]; + } +} diff --git a/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.html b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.html new file mode 100644 index 0000000000..52f0b2fd65 --- /dev/null +++ b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.html @@ -0,0 +1,8 @@ +
+ Switch data + + +
diff --git a/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.scss b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.scss new file mode 100644 index 0000000000..7eb01b5bc7 --- /dev/null +++ b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.scss @@ -0,0 +1,14 @@ +:host { + contain: content; + --ig-size: 1; +} + +.grid-lite-wrapper { + width: 100%; + height: calc(100% - 50px); +} + +igc-grid-lite { + margin-top: 1rem; + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.ts b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.ts new file mode 100644 index 0000000000..5f2c4d1ce5 --- /dev/null +++ b/src/app/grid-lite/grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component.ts @@ -0,0 +1,44 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, ViewChild, ElementRef, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcButtonComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo, UserSimple } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcButtonComponent); + +@Component({ + selector: 'app-grid-lite-data-binding-dynamic', + templateUrl: './grid-lite-data-binding-dynamic.component.html', + styleUrls: ['./grid-lite-data-binding-dynamic.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteDataBindingDynamicComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + @ViewChild('gridLite', { static: false }) gridLite!: ElementRef; + + public data: (ProductInfo | UserSimple)[] = []; + public dataType: 'products' | 'users' = 'products'; + public autoGenerate = true; + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + } + + switchData() { + this.dataType = this.dataType === 'products' ? 'users' : 'products'; + const grid = this.gridLite?.nativeElement as any; + + if (grid) { + grid.columns = []; + if (this.dataType === 'products') { + this.data = this.dataService.generateProducts(50); + } else { + this.data = this.dataService.generateSimpleUsers(50); + } + grid.data = this.data; + } + } +} diff --git a/src/app/grid-lite/grid-lite-data.service.ts b/src/app/grid-lite/grid-lite-data.service.ts new file mode 100644 index 0000000000..7a75559fdc --- /dev/null +++ b/src/app/grid-lite/grid-lite-data.service.ts @@ -0,0 +1,129 @@ +import { Injectable } from '@angular/core'; + +export type UserSimple = { + id: string; + username: string; + email: string; + subscribed: boolean; +}; + +export type ProductInfo = { + id: string; + name: string; + price: number; + sold: number; + rating: number; + total: number; +}; + +export type User = { + id: string; + firstName: string; + lastName: string; + age: number; + email: string; + avatar: string; + active: boolean; + priority: 'Low' | 'Standard' | 'High'; + satisfaction: number; + registeredAt: Date; +}; + +@Injectable({ + providedIn: 'root' +}) +export class GridLiteDataService { + private counter = 0; + + private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry', + 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel']; + private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', + 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris']; + private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption', + 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment']; + private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High']; + + private randomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + private randomFloat(min: number, max: number, precision = 2): number { + // Get a random float in [0,1) using crypto.getRandomValues + const array = new Uint32Array(1); + window.crypto.getRandomValues(array); + // Divide by 2^32 to get a float in [0,1) + const random01 = array[0] / 2 ** 32; + return parseFloat((random01 * (max - min) + min).toFixed(precision)); + } + + private randomElement(array: T[]): T { + return array[this.randomInt(0, array.length - 1)]; + } + + private randomBoolean(): boolean { + const array = new Uint8Array(1); + window.crypto.getRandomValues(array); + return (array[0] & 1) === 0; + } + + private generateId(): string { + return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`; + } + + createProductInfo(): ProductInfo { + const price = this.randomFloat(50, 500, 2); + const sold = this.randomInt(10, 100); + const total = parseFloat((price * sold).toFixed(2)); + + return { + price, + sold, + total, + id: this.generateId(), + name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`, + rating: this.randomFloat(0, 5, 1) + }; + } + + createUserSimple(): UserSimple { + const firstName = this.randomElement(this.firstNames); + const lastName = this.randomElement(this.lastNames); + return { + id: this.generateId(), + username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`, + email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`, + subscribed: this.randomBoolean() + }; + } + + createUser(): User { + const firstName = this.randomElement(this.firstNames); + const lastName = this.randomElement(this.lastNames); + const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`; + + return { + id: this.generateId(), + firstName, + lastName, + age: this.randomInt(18, 90), + email, + avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`, + active: this.randomBoolean(), + priority: this.randomElement(this.priorities), + satisfaction: this.randomInt(0, 5), + registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000)) + }; + } + + generateUsers(count: number): User[] { + return Array.from({ length: count }, () => this.createUser()); + } + + generateProducts(count: number): ProductInfo[] { + return Array.from({ length: count }, () => this.createProductInfo()); + } + + generateSimpleUsers(count: number): UserSimple[] { + return Array.from({ length: count }, () => this.createUserSimple()); + } +} diff --git a/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.html b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.html new file mode 100644 index 0000000000..e6cdea1be9 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.html @@ -0,0 +1,13 @@ +
+ + +
+ @for (entry of log; track entry) { +

{{ entry }}

+ } +
+
diff --git a/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.scss b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.scss new file mode 100644 index 0000000000..5855b949cb --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.scss @@ -0,0 +1,23 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} + +.log { + margin-top: 0.5rem; + border: 1px solid #ccc; + padding: 1rem; + min-height: 1rem; + font-size: 0.75rem; + max-height: 5rem; + overflow-y: auto; +} diff --git a/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.ts b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.ts new file mode 100644 index 0000000000..811ab58186 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-events/grid-lite-filtering-events.component.ts @@ -0,0 +1,83 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcCheckboxComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, User } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcCheckboxComponent); + +@Component({ + selector: 'app-grid-lite-filtering-events', + templateUrl: './grid-lite-filtering-events.component.html', + styleUrls: ['./grid-lite-filtering-events.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteFilteringEventsComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: User[] = []; + public columns: any[] = []; + public log: string[] = []; + + ngOnInit() { + this.data = this.dataService.generateUsers(50); + + this.columns = [ + { + key: 'firstName', + headerText: 'First name', + filter: true + }, + { + key: 'lastName', + headerText: 'Last name', + filter: true + }, + { + key: 'age', + headerText: 'Age', + filter: true, + type: 'number' + }, + { + key: 'active', + headerText: 'Active', + type: 'boolean', + filter: true, + cellTemplate: (params: any) => { + const checkbox = document.createElement('igc-checkbox'); + if (params.value) { + checkbox.setAttribute('checked', ''); + } + return checkbox; + } + } + ]; + } + + private get timeStamp(): string { + return `[${new Date().toLocaleTimeString()}]`; + } + + private updateLog(message: string) { + if (this.log.length > 10) { + this.log.shift(); + } + this.log = [...this.log, message]; + } + + handleFiltering(event: any) { + const { expressions, type } = event.detail; + this.updateLog( + `${this.timeStamp} :: Event 'filtering' :: Filter operation of type '${type}' for column '${expressions[0].key}'` + ); + } + + handleFiltered(event: any) { + this.updateLog( + `${this.timeStamp} :: Event 'filtered' for column '${event.detail.key}'` + ); + } +} diff --git a/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.html b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.html new file mode 100644 index 0000000000..650a29cac9 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.html @@ -0,0 +1,17 @@ +
+
+
Generated request
+

{{ queryString }}

+
+
+ + + + +
+
diff --git a/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.scss b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.scss new file mode 100644 index 0000000000..fa74b8eebe --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.scss @@ -0,0 +1,42 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +.grid-section { + position: relative; +} + +igc-circular-progress { + visibility: hidden; + --diameter: 4rem; + background-color: rgba(255, 255, 255, 0.5); + position: absolute; + z-index: 2; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.in-operation { + visibility: visible; + pointer-events: all; + user-select: contain; +} + +p { + border: 1px solid #ccc; + padding: 1rem; + min-height: 1rem; + font-size: 0.75rem; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.ts b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.ts new file mode 100644 index 0000000000..16dc1ebdc5 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component.ts @@ -0,0 +1,103 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcCheckboxComponent, IgcCircularProgressComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, User } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcCheckboxComponent, IgcCircularProgressComponent); + +@Component({ + selector: 'app-grid-lite-filtering-pipeline', + templateUrl: './grid-lite-filtering-pipeline.component.html', + styleUrls: ['./grid-lite-filtering-pipeline.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteFilteringPipelineComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: User[] = []; + public columns: any[] = []; + public dataPipelineConfiguration: any; + public inOperation = false; + public queryString = ''; + + ngOnInit() { + this.data = this.dataService.generateUsers(50); + + this.columns = [ + { + key: 'firstName', + headerText: 'First name', + filter: true + }, + { + key: 'lastName', + headerText: 'Last name', + filter: true + }, + { + key: 'age', + headerText: 'Age', + filter: true, + type: 'number' + }, + { + key: 'active', + headerText: 'Active', + type: 'boolean', + filter: true, + cellTemplate: (params: any) => { + const checkbox = document.createElement('igc-checkbox'); + if (params.value) { + checkbox.setAttribute('checked', ''); + } + return checkbox; + } + } + ]; + + this.dataPipelineConfiguration = { + filter: async ({ data, grid }: any) => { + this.inOperation = true; + this.buildUri(grid.filterExpressions); + await new Promise(resolve => setTimeout(resolve, 250)); + this.inOperation = false; + return data; + } + }; + } + + private buildUri(state: any[]) { + const grouped = this.groupBy(state, 'key'); + const out: string[] = []; + + for (const [key, exprs] of Object.entries(grouped)) { + out.push(`${key}(${this.mapExpressions(exprs as any[])})`); + } + + this.queryString = `GET: /data?filter=${out.join('&')}`; + } + + private groupBy(arr: T[], key: keyof T): Record { + const out: Record = {}; + for (const each of arr) { + const slot = each[key] as string; + if (!out[slot]) { + out[slot] = []; + } + out[slot].push(each); + } + return out; + } + + private mapExpressions(arr: any[]): string { + return arr.map(({ searchTerm, criteria, condition }, idx) => { + const c = condition; + return idx < 1 + ? `${c.name}("${searchTerm}")` + : `${criteria?.toUpperCase()} ${c.name}("${searchTerm}")`; + }).join(' '); + } +} diff --git a/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.html b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.html new file mode 100644 index 0000000000..9b6326efb4 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.html @@ -0,0 +1,6 @@ +
+ + +
diff --git a/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.scss b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.scss new file mode 100644 index 0000000000..0c5a800394 --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.scss @@ -0,0 +1,13 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.ts b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.ts new file mode 100644 index 0000000000..8c6e2360ed --- /dev/null +++ b/src/app/grid-lite/grid-lite-filtering-simple/grid-lite-filtering-simple.component.ts @@ -0,0 +1,58 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcCheckboxComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, User } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcCheckboxComponent); + +@Component({ + selector: 'app-grid-lite-filtering-simple', + templateUrl: './grid-lite-filtering-simple.component.html', + styleUrls: ['./grid-lite-filtering-simple.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteFilteringSimpleComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: User[] = []; + public columns: any[] = []; + + ngOnInit() { + this.data = this.dataService.generateUsers(50); + + this.columns = [ + { + key: 'firstName', + headerText: 'First name', + filter: true + }, + { + key: 'lastName', + headerText: 'Last name', + filter: true + }, + { + key: 'age', + headerText: 'Age', + filter: true, + type: 'number' + }, + { + key: 'active', + headerText: 'Active', + type: 'boolean', + filter: true, + cellTemplate: (params: any) => { + const checkbox = document.createElement('igc-checkbox'); + if (params.value) { + checkbox.setAttribute('checked', ''); + } + return checkbox; + } + } + ]; + } +} diff --git a/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.html b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.html new file mode 100644 index 0000000000..9b6326efb4 --- /dev/null +++ b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.html @@ -0,0 +1,6 @@ +
+ + +
diff --git a/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.scss b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.scss new file mode 100644 index 0000000000..89bcc80892 --- /dev/null +++ b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.scss @@ -0,0 +1,14 @@ +:host { + contain: strict; + min-height: 400px; + --ig-size: 1; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 75vh; +} diff --git a/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.ts b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.ts new file mode 100644 index 0000000000..feb1899068 --- /dev/null +++ b/src/app/grid-lite/grid-lite-overview/grid-lite-overview.component.ts @@ -0,0 +1,130 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + defineComponents, + IgcRatingComponent, + IgcCheckboxComponent, + IgcSelectComponent, + IgcAvatarComponent +} from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, User } from '../grid-lite-data.service'; + +IgcGridLite.register(); + +defineComponents( + IgcAvatarComponent, + IgcRatingComponent, + IgcCheckboxComponent, + IgcSelectComponent +); + +@Component({ + selector: 'app-grid-lite-overview', + templateUrl: './grid-lite-overview.component.html', + styleUrls: ['./grid-lite-overview.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteOverviewComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: User[] = []; + public columns: any[] = []; + private choices = ['Low', 'Standard', 'High']; + + ngOnInit() { + this.data = this.dataService.generateUsers(1000); + + this.columns = [ + { + key: 'avatar', + headerText: 'Avatar', + cellTemplate: (params: any) => { + const cell = document.createElement('igc-avatar'); + cell.setAttribute('shape', 'circle'); + cell.setAttribute('alt', 'User avatar'); + cell.setAttribute('src', params.value); + return cell; + } + }, + { + key: 'firstName', + headerText: 'First name', + sort: true, + filter: true, + resizable: true + }, + { + key: 'lastName', + headerText: 'Last name', + sort: true, + filter: true, + resizable: true + }, + { + key: 'email', + headerText: 'Email Address' + }, + { + key: 'priority', + headerText: 'Priority', + width: '12rem', + sort: { + comparer: (a: string, b: string) => this.choices.indexOf(a) - this.choices.indexOf(b), + caseSensitive: true + }, + cellTemplate: (params: any) => { + const select = document.createElement('igc-select'); + select.setAttribute('outlined', ''); + select.setAttribute('flip', ''); + select.setAttribute('value', params.value); + + this.choices.forEach(choice => { + const item = document.createElement('igc-select-item'); + item.setAttribute('value', choice); + item.textContent = choice; + select.appendChild(item); + }); + + return select; + } + }, + { + key: 'satisfaction', + headerText: 'Satisfaction rating', + type: 'number', + sort: true, + filter: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('value', params.value.toString()); + return rating; + } + }, + { + key: 'registeredAt', + headerText: 'Registered @', + sort: true, + cellTemplate: (params: any) => { + const span = document.createElement('span'); + span.textContent = params.value.toLocaleString(); + return span; + } + }, + { + key: 'active', + type: 'boolean', + headerText: 'Active', + cellTemplate: (params: any) => { + const checkbox = document.createElement('igc-checkbox'); + if (params.value) { + checkbox.setAttribute('checked', ''); + } + return checkbox; + } + } + ]; + } +} diff --git a/src/app/grid-lite/grid-lite-routes-data.ts b/src/app/grid-lite/grid-lite-routes-data.ts new file mode 100644 index 0000000000..b354dd66ba --- /dev/null +++ b/src/app/grid-lite/grid-lite-routes-data.ts @@ -0,0 +1,18 @@ +// tslint:disable:object-literal-sort-keys + +export const gridLiteRoutesData = { + 'overview': { displayName: 'Grid Lite Overview', parentName: 'Grid Lite' }, + 'column-config-simple': { displayName: 'Column Configuration - Simple', parentName: 'Grid Lite' }, + 'column-config-dynamic': { displayName: 'Column Configuration - Dynamic', parentName: 'Grid Lite' }, + 'column-config-headers': { displayName: 'Column Configuration - Headers', parentName: 'Grid Lite' }, + 'data-binding-dynamic': { displayName: 'Data Binding - Dynamic', parentName: 'Grid Lite' }, + 'filtering-simple': { displayName: 'Filtering - Simple', parentName: 'Grid Lite' }, + 'filtering-events': { displayName: 'Filtering - Events', parentName: 'Grid Lite' }, + 'filtering-pipeline': { displayName: 'Filtering - Pipeline', parentName: 'Grid Lite' }, + 'sorting-simple': { displayName: 'Sorting - Simple', parentName: 'Grid Lite' }, + 'sorting-events': { displayName: 'Sorting - Events', parentName: 'Grid Lite' }, + 'sorting-grid-config': { displayName: 'Sorting - Grid Configuration', parentName: 'Grid Lite' }, + 'sorting-pipeline': { displayName: 'Sorting - Pipeline', parentName: 'Grid Lite' }, + 'styling-custom': { displayName: 'Styling - Custom', parentName: 'Grid Lite' }, + 'styling-themes': { displayName: 'Styling - Themes', parentName: 'Grid Lite' } +}; diff --git a/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.html b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.html new file mode 100644 index 0000000000..5370c694cb --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.html @@ -0,0 +1,13 @@ +
+ + +
+ @for (entry of log; track entry) { +

{{ entry }}

+ } +
+
diff --git a/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.scss b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.scss new file mode 100644 index 0000000000..5855b949cb --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.scss @@ -0,0 +1,23 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} + +.log { + margin-top: 0.5rem; + border: 1px solid #ccc; + padding: 1rem; + min-height: 1rem; + font-size: 0.75rem; + max-height: 5rem; + overflow-y: auto; +} diff --git a/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.ts b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.ts new file mode 100644 index 0000000000..a41750c929 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-events/grid-lite-sorting-events.component.ts @@ -0,0 +1,100 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent); + +@Component({ + selector: 'app-grid-lite-sorting-events', + templateUrl: './grid-lite-sorting-events.component.html', + styleUrls: ['./grid-lite-sorting-events.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteSortingEventsComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + public log: string[] = []; + + ngOnInit() { + this.data = this.dataService.generateProducts(100); + + this.columns = [ + { + key: 'name', + headerText: 'Name', + sort: true + }, + { + key: 'price', + type: 'number', + headerText: 'Price', + sort: true + }, + { + key: 'rating', + type: 'number', + headerText: 'Rating', + sort: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Sold', + sort: true + }, + { + key: 'total', + type: 'number', + headerText: 'Total', + sort: true + } + ]; + } + + private get timeStamp(): string { + return `[${new Date().toLocaleTimeString()}]`; + } + + private updateLog(message: string) { + if (this.log.length > 10) { + this.log.shift(); + } + this.log = [...this.log, message]; + } + + handleSorting(event: any) { + const { detail, type } = event; + const allowedColumns = ['price', 'total', 'sold']; + + if (!allowedColumns.includes(detail.key)) { + event.preventDefault(); + this.updateLog( + `${this.timeStamp} :: Event '${type}' :: Sort operation was prevented for column '${detail.key}'` + ); + } else { + this.updateLog( + `${this.timeStamp} :: Event '${type}' :: Column '${detail.key}' is being sorted with expression: ${JSON.stringify(detail)}` + ); + } + } + + handleSorted(event: any) { + const { detail, type } = event; + this.updateLog( + `${this.timeStamp} :: Event '${type}' :: Column '${detail.key}' was sorted with expression: ${JSON.stringify(detail)}` + ); + } +} diff --git a/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.html b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.html new file mode 100644 index 0000000000..9b53145234 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.html @@ -0,0 +1,20 @@ +
+
+ + Enable multi-sort + + + Enable tri-state sorting + +
+ + + +
diff --git a/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.scss b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.scss new file mode 100644 index 0000000000..185062455d --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.scss @@ -0,0 +1,17 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +.config-panel { + margin: 1rem 0; +} + +igc-grid-lite { + height: 510px; +} diff --git a/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.ts b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.ts new file mode 100644 index 0000000000..eeeddaf909 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component.ts @@ -0,0 +1,73 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent, IgcSwitchComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent, IgcSwitchComponent); + +@Component({ + selector: 'app-grid-lite-sorting-grid-config', + templateUrl: './grid-lite-sorting-grid-config.component.html', + styleUrls: ['./grid-lite-sorting-grid-config.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteSortingGridConfigComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + public sortConfiguration: any = { + multiple: true, + triState: true + }; + + ngOnInit() { + this.data = this.dataService.generateProducts(100); + + this.columns = [ + { + key: 'name', + headerText: 'Name', + sort: true + }, + { + key: 'price', + type: 'number', + headerText: 'Price', + sort: true + }, + { + key: 'rating', + type: 'number', + headerText: 'Rating', + sort: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Sold', + sort: true + }, + { + key: 'total', + type: 'number', + headerText: 'Total', + sort: true + } + ]; + } + + updateConfig(prop: string, value: boolean) { + this.sortConfiguration = { ...this.sortConfiguration, [prop]: value }; + } +} diff --git a/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.html b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.html new file mode 100644 index 0000000000..650a29cac9 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.html @@ -0,0 +1,17 @@ +
+
+
Generated request
+

{{ queryString }}

+
+
+ + + + +
+
diff --git a/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.scss b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.scss new file mode 100644 index 0000000000..fa74b8eebe --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.scss @@ -0,0 +1,42 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +.grid-section { + position: relative; +} + +igc-circular-progress { + visibility: hidden; + --diameter: 4rem; + background-color: rgba(255, 255, 255, 0.5); + position: absolute; + z-index: 2; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.in-operation { + visibility: visible; + pointer-events: all; + user-select: contain; +} + +p { + border: 1px solid #ccc; + padding: 1rem; + min-height: 1rem; + font-size: 0.75rem; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.ts b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.ts new file mode 100644 index 0000000000..abaeb8c570 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component.ts @@ -0,0 +1,95 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, ViewChild, ElementRef, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent, IgcCircularProgressComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent, IgcCircularProgressComponent); + +@Component({ + selector: 'app-grid-lite-sorting-pipeline', + templateUrl: './grid-lite-sorting-pipeline.component.html', + styleUrls: ['./grid-lite-sorting-pipeline.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteSortingPipelineComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + public dataPipelineConfiguration: any; + public inOperation = false; + public queryString = ''; + + ngOnInit() { + this.data = this.dataService.generateProducts(100); + + this.columns = [ + { + key: 'name', + headerText: 'Name', + sort: true + }, + { + key: 'price', + type: 'number', + headerText: 'Price', + sort: true + }, + { + key: 'rating', + type: 'number', + headerText: 'Rating', + sort: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Sold', + sort: true + }, + { + key: 'total', + type: 'number', + headerText: 'Total', + sort: true + } + ]; + + this.dataPipelineConfiguration = { + sort: async ({ data, grid }: any) => { + this.inOperation = true; + this.queryString = grid.sortExpressions.length + ? this.buildUri(grid.sortExpressions) + : ''; + await new Promise(resolve => setTimeout(resolve, 250)); + this.inOperation = false; + return data; + } + }; + } + + private buildUri(state: any[]): string { + const uri: string[] = []; + for (const expr of state) { + if (expr.direction === 'none') { + continue; + } + uri.push( + expr.direction === 'ascending' + ? `asc(${expr.key})` + : `desc(${expr.key})` + ); + } + return `GET: /data?sort_by=${uri.join(',')}`; + } +} diff --git a/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.html b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.html new file mode 100644 index 0000000000..9b6326efb4 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.html @@ -0,0 +1,6 @@ +
+ + +
diff --git a/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.scss b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.scss new file mode 100644 index 0000000000..0c5a800394 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.scss @@ -0,0 +1,13 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +igc-grid-lite { + min-height: 65vh; +} diff --git a/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.ts b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.ts new file mode 100644 index 0000000000..d3256cb048 --- /dev/null +++ b/src/app/grid-lite/grid-lite-sorting-simple/grid-lite-sorting-simple.component.ts @@ -0,0 +1,67 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent); + +@Component({ + selector: 'app-grid-lite-sorting-simple', + templateUrl: './grid-lite-sorting-simple.component.html', + styleUrls: ['./grid-lite-sorting-simple.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteSortingSimpleComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + + ngOnInit() { + this.data = this.dataService.generateProducts(100); + + this.columns = [ + { + key: 'name', + headerText: 'Name', + sort: { + comparer: (a: string, b: string) => a.length - b.length + } + }, + { + key: 'price', + type: 'number', + headerText: 'Price', + sort: true + }, + { + key: 'rating', + type: 'number', + headerText: 'Rating', + sort: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('step', '0.01'); + rating.setAttribute('value', params.value.toString()); + return rating; + } + }, + { + key: 'sold', + type: 'number', + headerText: 'Sold', + sort: true + }, + { + key: 'total', + type: 'number', + headerText: 'Total', + sort: true + } + ]; + } +} diff --git a/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.html b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.html new file mode 100644 index 0000000000..f1befbff90 --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.html @@ -0,0 +1,17 @@ +
+
+ + Switch to {{ theme === 'dark' ? 'light' : 'dark' }} theme + +
+ + + +
diff --git a/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.scss b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.scss new file mode 100644 index 0000000000..60fe9043c3 --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.scss @@ -0,0 +1,47 @@ +@use "igniteui-angular/theming" as *; + +:host { + --ig-size: 2; + + contain: content; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +.theme-switcher { + margin-bottom: 2rem; +} + +igc-grid-lite { + min-height: rem(400px); +} + +$my-light-palette: palette( + $primary: #c1292e, + $secondary: #f1d302, + $surface: #fdfffc, + $gray: #235789, +); + +$my_dark_palette: palette( + $primary: #ddd020, + $secondary: #d5896f, + $surface: #031d44, + $gray: #04395e, +); + +.custom-light { + @include palette($my_light_palette); + @include typography('"Roboto", sans-serif', $bootstrap-type-scale); +} + +.custom-dark { + @include palette($my_dark_palette); + @include typography( + '"Merriweather Sans", sans-serif', + $bootstrap-type-scale + ); +} diff --git a/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.ts b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.ts new file mode 100644 index 0000000000..8c1449c392 --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-custom/grid-lite-styling-custom.component.ts @@ -0,0 +1,69 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject, ViewEncapsulation } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcSwitchComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcSwitchComponent); + +@Component({ + selector: 'app-grid-lite-styling-custom', + templateUrl: './grid-lite-styling-custom.component.html', + styleUrls: ['./grid-lite-styling-custom.component.scss'], + encapsulation: ViewEncapsulation.None, + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteStylingCustomComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + public theme: 'dark' | 'light' = 'dark'; + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + + this.columns = [ + { + key: 'name', + headerText: 'Product', + filter: true, + sort: true + }, + { + key: 'price', + headerText: 'Price', + type: 'number', + filter: true, + sort: true + }, + { + key: 'sold', + type: 'number', + headerText: 'Sold', + filter: true, + sort: true + }, + { + key: 'total', + headerText: 'Total', + type: 'number', + filter: true, + sort: true + }, + { + key: 'rating', + type: 'number', + headerText: 'Rating', + filter: true, + sort: true + } + ]; + } + + switchTheme() { + this.theme = this.theme === 'dark' ? 'light' : 'dark'; + } +} diff --git a/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.html b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.html new file mode 100644 index 0000000000..c19f47b31a --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.html @@ -0,0 +1,19 @@ +
+
+ + @for (theme of themes; track theme) { + {{ theme }} + } + +
+ + + +
diff --git a/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.scss b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.scss new file mode 100644 index 0000000000..3167c8b26c --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.scss @@ -0,0 +1,19 @@ +:host { + contain: content; + --ig-size: 2; +} + +.grid-lite-wrapper { + width: 100%; + height: 100%; +} + +.theme-selector { + display: flex; + margin-bottom: 2rem; + gap: 2rem; +} + +igc-grid-lite { + min-height: 400px; +} diff --git a/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.ts b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.ts new file mode 100644 index 0000000000..095ef4abd8 --- /dev/null +++ b/src/app/grid-lite/grid-lite-styling-themes/grid-lite-styling-themes.component.ts @@ -0,0 +1,84 @@ +import { Component, CUSTOM_ELEMENTS_SCHEMA, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { defineComponents, IgcRatingComponent, IgcSelectComponent, IgcSelectItemComponent } from 'igniteui-webcomponents'; +import { IgcGridLite } from 'igniteui-grid-lite'; +import { GridLiteDataService, ProductInfo } from '../grid-lite-data.service'; + +IgcGridLite.register(); +defineComponents(IgcRatingComponent, IgcSelectComponent, IgcSelectItemComponent); + +@Component({ + selector: 'app-grid-lite-styling-themes', + templateUrl: './grid-lite-styling-themes.component.html', + styleUrls: ['./grid-lite-styling-themes.component.scss'], + imports: [CommonModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class GridLiteStylingThemesComponent implements OnInit { + private dataService = inject(GridLiteDataService); + + public data: ProductInfo[] = []; + public columns: any[] = []; + public selectedTheme = 'Bootstrap'; + public themes = [ + 'Bootstrap', + 'Bootstrap Dark', + 'Fluent', + 'Fluent Dark', + 'Material', + 'Material Dark', + 'Indigo', + 'Indigo Dark' + ]; + + ngOnInit() { + this.data = this.dataService.generateProducts(50); + + this.columns = [ + { + key: 'name', + headerText: 'Product', + sort: true, + filter: true + }, + { + key: 'price', + headerText: 'Price per item', + sort: true, + filter: true, + type: 'number' + }, + { + key: 'sold', + headerText: 'Items sold', + sort: true, + filter: true, + type: 'number' + }, + { + key: 'total', + headerText: 'Total', + sort: true, + filter: true, + type: 'number' + }, + { + key: 'rating', + headerText: 'User rating', + type: 'number', + sort: true, + filter: true, + cellTemplate: (params: any) => { + const rating = document.createElement('igc-rating'); + rating.setAttribute('readonly', ''); + rating.setAttribute('value', params.value.toString()); + return rating; + } + } + ]; + } + + updateTheme(event: any) { + this.selectedTheme = event.detail.value; + } +} diff --git a/src/app/grid-lite/grid-lite.routes.ts b/src/app/grid-lite/grid-lite.routes.ts new file mode 100644 index 0000000000..86fe9c71bd --- /dev/null +++ b/src/app/grid-lite/grid-lite.routes.ts @@ -0,0 +1,90 @@ +/* eslint-disable max-len */ +import { Routes } from '@angular/router'; +import { GridLiteOverviewComponent } from './grid-lite-overview/grid-lite-overview.component'; +import { GridLiteColumnConfigSimpleComponent } from './grid-lite-column-config-simple/grid-lite-column-config-simple.component'; +import { GridLiteColumnConfigDynamicComponent } from './grid-lite-column-config-dynamic/grid-lite-column-config-dynamic.component'; +import { GridLiteColumnConfigHeadersComponent } from './grid-lite-column-config-headers/grid-lite-column-config-headers.component'; +import { GridLiteDataBindingDynamicComponent } from './grid-lite-data-binding-dynamic/grid-lite-data-binding-dynamic.component'; +import { GridLiteFilteringSimpleComponent } from './grid-lite-filtering-simple/grid-lite-filtering-simple.component'; +import { GridLiteFilteringEventsComponent } from './grid-lite-filtering-events/grid-lite-filtering-events.component'; +import { GridLiteFilteringPipelineComponent } from './grid-lite-filtering-pipeline/grid-lite-filtering-pipeline.component'; +import { GridLiteSortingSimpleComponent } from './grid-lite-sorting-simple/grid-lite-sorting-simple.component'; +import { GridLiteSortingEventsComponent } from './grid-lite-sorting-events/grid-lite-sorting-events.component'; +import { GridLiteSortingGridConfigComponent } from './grid-lite-sorting-grid-config/grid-lite-sorting-grid-config.component'; +import { GridLiteSortingPipelineComponent } from './grid-lite-sorting-pipeline/grid-lite-sorting-pipeline.component'; +import { GridLiteStylingCustomComponent } from './grid-lite-styling-custom/grid-lite-styling-custom.component'; +import { GridLiteStylingThemesComponent } from './grid-lite-styling-themes/grid-lite-styling-themes.component'; +import { gridLiteRoutesData } from './grid-lite-routes-data'; + +export const GridLiteRoutes: Routes = [ + { + path: 'overview', + component: GridLiteOverviewComponent, + data: gridLiteRoutesData['overview'] + }, + { + path: 'column-config-simple', + component: GridLiteColumnConfigSimpleComponent, + data: gridLiteRoutesData['column-config-simple'] + }, + { + path: 'column-config-dynamic', + component: GridLiteColumnConfigDynamicComponent, + data: gridLiteRoutesData['column-config-dynamic'] + }, + { + path: 'column-config-headers', + component: GridLiteColumnConfigHeadersComponent, + data: gridLiteRoutesData['column-config-headers'] + }, + { + path: 'data-binding-dynamic', + component: GridLiteDataBindingDynamicComponent, + data: gridLiteRoutesData['data-binding-dynamic'] + }, + { + path: 'filtering-simple', + component: GridLiteFilteringSimpleComponent, + data: gridLiteRoutesData['filtering-simple'] + }, + { + path: 'filtering-events', + component: GridLiteFilteringEventsComponent, + data: gridLiteRoutesData['filtering-events'] + }, + { + path: 'filtering-pipeline', + component: GridLiteFilteringPipelineComponent, + data: gridLiteRoutesData['filtering-pipeline'] + }, + { + path: 'sorting-simple', + component: GridLiteSortingSimpleComponent, + data: gridLiteRoutesData['sorting-simple'] + }, + { + path: 'sorting-events', + component: GridLiteSortingEventsComponent, + data: gridLiteRoutesData['sorting-events'] + }, + { + path: 'sorting-grid-config', + component: GridLiteSortingGridConfigComponent, + data: gridLiteRoutesData['sorting-grid-config'] + }, + { + path: 'sorting-pipeline', + component: GridLiteSortingPipelineComponent, + data: gridLiteRoutesData['sorting-pipeline'] + }, + { + path: 'styling-custom', + component: GridLiteStylingCustomComponent, + data: gridLiteRoutesData['styling-custom'] + }, + { + path: 'styling-themes', + component: GridLiteStylingThemesComponent, + data: gridLiteRoutesData['styling-themes'] + } +]; diff --git a/src/app/index/index.component.ts b/src/app/index/index.component.ts index ccdc58b214..308647ef8b 100644 --- a/src/app/index/index.component.ts +++ b/src/app/index/index.component.ts @@ -6,6 +6,7 @@ import { filter, map, debounceTime } from 'rxjs/operators'; import { dataDisplayRoutesData } from '../data-display/data-display-routes-data'; import { dataEntriesRoutesData } from '../data-entries/data-entries-routes-data'; import { gridsRoutesData } from '../grid/grid-routes-data'; +import { gridLiteRoutesData } from '../grid-lite/grid-lite-routes-data'; import { hierarchicalGridRoutesData } from '../hierarchical-grid/hierarchical-grid-routes-data'; import { interactionsRoutesData } from '../interactions/interactions-routes-data'; import { layoutsRoutesData } from '../layouts/layouts-routes-data'; @@ -106,6 +107,10 @@ export class IndexComponent implements OnInit, AfterViewInit { path: 'grid', routesData: gridsRoutesData }, + { + path: 'grid-lite', + routesData: gridLiteRoutesData + }, { path: 'hierarchical-grid', routesData: hierarchicalGridRoutesData diff --git a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.html b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.html index 49e1dae43b..98dee27aa5 100644 --- a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.html +++ b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.html @@ -1,28 +1,32 @@
- + - - -

{{ card.title }}

-
{{ card.subtitle }}
-
- - -

{{ card.content }}

-
- - - @for (icon of card.icons; track icon) { - - } - - +
+ + +
+
{{ card.title }}
+

{{ card.subtitle }}

+
+
+ + #artic + #fox + #card + + + + @for (icon of card.icons; track icon; let i = $index) { + + @if (i < 2) { + + } + } + +
-
+ \ No newline at end of file diff --git a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.scss b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.scss index ceb14c46ba..fff5af5c9c 100644 --- a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.scss +++ b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.scss @@ -1,9 +1,77 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$colorful-card: card-theme( - $background: #011627, - $subtitle-text-color: #ecaa53, -); +// CSS variables approach -@include css-vars($colorful-card); +igx-card { + --border-radius: #{rem(8px)}; + --outline-color: #f0f0f0; + --resting-shadow: none; + --hover-shadow: none; + --header-text-color: rgba(0, 0, 0, 0.88); +} + +igx-avatar { + --background: transparent; + --size: #{rem(30px)}; +} + +igx-chip { + --border-radius: #{rem(4px)}; + --background: #fafafa; + --border-color: #d9d9d9; + --hover-background: #d9d9d9; + --focus-background: #d9d9d9; +} + +.igx-icon-button--flat { + --foreground: #00000073; + --hover-foreground: #1677ff; + --hover-background: none; +} + +igx-divider { + --color: #f0f0f0 +} + +// Sass theme approach + +// $custom-card-theme: card-theme( +// $border-radius: rem(8px), +// $outline-color: #f0f0f0, +// $resting-shadow: none, +// $hover-shadow: none, +// $header-text-color: #000000e0, +// ); + +// $custom-avatar-theme: avatar-theme( +// $background: transparent, +// $size: rem(30px) +// ); + +// $custom-chip-theme: chip-theme( +// $border-radius: rem(4px), +// $background: #fafafa, +// $border-color: #d9d9d9, +// $hover-background: #d9d9d9, +// $focus-background: #d9d9d9, +// ); + +// $custom-icon-button-theme: icon-button-theme( +// $foreground: #00000073, +// $hover-foreground: #1677ff, +// $hover-background: none, +// $border-color: transparent +// ); + +// $custom-divider-theme: divider-theme( +// $color: #f0f0f0 +// ); + +// @include css-vars($custom-card-theme); +// @include css-vars($custom-avatar-theme); +// @include css-vars($custom-chip-theme); +// @include css-vars($custom-divider-theme); +// .igx-icon-button--flat { +// @include css-vars($custom-icon-button-theme); +// }; \ No newline at end of file diff --git a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.ts b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.ts index 935be0448f..1ec78186c3 100644 --- a/src/app/layouts/card/card-styling-sample/card-styling-sample.component.ts +++ b/src/app/layouts/card/card-styling-sample/card-styling-sample.component.ts @@ -1,25 +1,40 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { Card } from '../card.blueprint'; -import { IgxCardComponent, IgxCardMediaDirective, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardHeaderSubtitleDirective, IgxCardContentDirective, IgxCardActionsComponent, IgxIconButtonDirective, IgxRippleDirective, IgxSuffixDirective, IgxIconComponent } from 'igniteui-angular'; - +import { + IgxCardComponent, + IgxCardMediaDirective, + IgxCardHeaderComponent, + IgxCardHeaderTitleDirective, + IgxCardHeaderSubtitleDirective, + IgxCardContentDirective, + IgxCardActionsComponent, + IgxIconButtonDirective, + IgxIconComponent, + IgxAvatarComponent, + IgxDividerModule, + IgxIconService, + IgxChipComponent +} from 'igniteui-angular'; @Component({ - selector: 'app-card-styling-sample', - templateUrl: './card-styling-sample.component.html', - styleUrls: ['./card-styling-sample.component.scss'], - imports: [IgxCardComponent, IgxCardMediaDirective, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardHeaderSubtitleDirective, IgxCardContentDirective, IgxCardActionsComponent, IgxIconButtonDirective, IgxRippleDirective, IgxSuffixDirective, IgxIconComponent] + selector: 'app-card-styling-sample', + templateUrl: './card-styling-sample.component.html', + styleUrls: ['./card-styling-sample.component.scss'], + imports: [IgxCardComponent, IgxCardMediaDirective, IgxCardHeaderComponent, + IgxCardHeaderTitleDirective, IgxCardHeaderSubtitleDirective, + IgxCardContentDirective, IgxCardActionsComponent, IgxIconButtonDirective, + IgxIconComponent, IgxAvatarComponent, IgxDividerModule, IgxChipComponent] }) -export class CardStylingSampleComponent { - public card = new Card({ - content: `Hi! I'm Jane, photographer and filmmaker. - Photography is a way of feeling, of touching, - of loving. What you have caught on film is captured forever... - it remembers little things, long after you have - forgotten everything.`, - icons: ['person', 'favorite', 'share'], - imageUrl: 'https://images.unsplash.com/' - + 'photo-1541516160071-4bb0c5af65ba?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80', - subtitle: 'Professional Photographer', - title: 'Jane Doe' - }); +export class CardStylingSampleComponent implements OnInit { + private iconService = inject(IgxIconService) + public ngOnInit() { + this.iconService.addSvgIconFromText('settings-custom', '') + this.iconService.addSvgIconFromText('edit-custom', ''); + this.iconService.addSvgIconFromText('dots', ''); + }; + public card = new Card({ + icons: ['settings-custom', 'edit-custom', 'dots'], + subtitle: 'This is the description', + title: 'Card title' + }); } diff --git a/src/app/layouts/card/card-styling-sample/layout.scss b/src/app/layouts/card/card-styling-sample/layout.scss index d8f5f95f82..c56ee6fee1 100644 --- a/src/app/layouts/card/card-styling-sample/layout.scss +++ b/src/app/layouts/card/card-styling-sample/layout.scss @@ -1,4 +1,79 @@ -.card-wrapper { - max-width: 320px; - min-width: 220px; -} \ No newline at end of file +@use "igniteui-angular/theming" as *; + +:host { + ::ng-deep { + .igx-chip__item { + padding: 0 rem(5px); + height: rem(22px); + } + } +} + +.igx-card { + --ig-font-family: 'alibaba-sans', sans-serif; + + width: rem(300px); + border: none; +} + +.border { + border: rem(1px) solid var(--outline-color); + border-bottom-right-radius: rem(8px); + border-bottom-left-radius: rem(8px); + border-top: none; +} + +.igx-card-header{ + --ig-h6-font-size: 1rem; + --ig-body-1-font-size: #{rem(14px)}; + + width: unset; + padding: unset; + align-items: baseline; + margin: rem(24px) rem(24px) 0 rem(24px); + height: rem(65px); +} + +.igx-card-header__subtitle { + --ig-subtitle-2-font-weight: 400; + --ig-subtitle-2-line-height: #{rem(22px)}; + --ig-subtitle-2-letter-spacing: #{rem(0.5px)}; + --subtitle-text-color: rgba(0, 0, 0, 0.45); + + margin: rem(8px) 0 rem(12px); +} + +.igx-card-content { + padding: 0; + + igx-chip { + --ig-body-2-font-size: #{rem(12px)}; + + padding: rem(5px); + + &:nth-of-type(1) { + margin-left: rem(5px); + } + } + + igx-divider { + margin-top: rem(5px); + } +} + +igx-icon { + --igx-icon-size: #{rem(14px)}; +} + +igx-avatar { + border-radius: rem(20px); +} + +igx-card-actions { + justify-content: space-evenly; + padding: rem(6px) 0; + + igx-divider { + height: rem(24px); + } +} diff --git a/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.html b/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.html index 4a71009af8..afc5c45d12 100644 --- a/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.html +++ b/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.html @@ -1,4 +1,4 @@
- -
- + + \ No newline at end of file diff --git a/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.scss b/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.scss index 7a54891f9c..8768f9008f 100644 --- a/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.scss +++ b/src/app/scheduling/calendar/calendar-styling-sample/calendar-styling-sample.component.scss @@ -1,9 +1,170 @@ @use "layout.scss"; @use "igniteui-angular/theming" as *; -$custom-calendar-theme: calendar-theme( - $header-background: #ecaa53, - $content-background: #011627, -); +// CSS variables approach -@include css-vars($custom-calendar-theme); +:host { + ::ng-deep { + .igx-days-view__date--weekend:not(.igx-days-view__date--inactive) { + --date-hover-background: var(--background-hover); + --date-selected-foreground: var(--primary); + --date-selected-background: #FFF; + --date-selected-border-color: var(--primary); + --date-selected-focus-foreground: var(--primary); + --date-selected-focus-background: var(--background-hover); + --date-selected-focus-border-color: var(--primary); + --date-selected-hover-foreground: var(--primary); + --date-selected-hover-background: var(--background-hover); + --date-selected-hover-border-color: var(--primary); + --date-selected-current-hover-background: var(--background-hover); + --date-selected-current-focus-background: var(--background-hover); + --date-selected-current-background: #FFF; + --date-selected-current-border-color: var(--primary); + --date-selected-current-hover-border-color: var(--primary); + --date-current-hover-background: var(--background-hover); + } + } +} + +igx-calendar { + --date-focus-background: transparent; + --week-number-background: transparent; + --weekend-color: #131E29; + --weekday-color: #556B82; + --week-number-foreground: #556B82; + --inactive-color: #556B82; + --date-current-border-color: var(--current-border); + --date-current-hover-border-color: var(--current-border); + --date-current-focus-border-color: var(--current-border); + --date-current-hover-background: var(--background-weekend); + --date-selected-current-border-color: var(--current-border); + --date-selected-current-background: #FFF; + --date-selected-current-foreground: var(--primary); + --date-selected-current-focus-border-color: var(--current-border); + --date-selected-current-focus-background: var(--background-weekend); + --date-selected-current-focus-foreground: var(--primary); + --date-selected-current-hover-border-color: var(--current-border); + --date-selected-current-hover-background: var(--background-weekend); + --date-selected-current-hover-foreground: var(--primary); + --date-selected-foreground: var(--primary); + --date-selected-background: #FFF; + --date-selected-border-color: var(--primary); + --date-selected-hover-foreground: var(--primary); + --date-selected-hover-background: var(--background-weekend); + --date-selected-hover-border-color: var(--primary); + --date-selected-focus-foreground: var(--primary); + --date-selected-focus-background: var(--background-weekend); + --date-selected-focus-border-color: var(--primary); + --picker-foreground: var(--primary); + --picker-hover-foreground: var(--primary); + --picker-focus-foreground: var(--primary); + --ym-hover-background: var(--background); + --ym-selected-background: #EDF5FF; + --ym-selected-hover-background: #D9EAFF; + --ym-selected-hover-foreground: var(--primary); + --ym-selected-outline-color: var(--primary); + --ym-selected-hover-outline-color: var(--primary); + --ym-selected-focus-outline-color: var(--primary); + --ym-selected-focus-background: #D9EAFF; + --ym-current-foreground: var(--primary); + --ym-current-background: transparent; + --ym-current-outline-color: transparent; + --ym-current-hover-foreground: var(--primary); + --ym-current-hover-background: var(--background); + --ym-current-outline-hover-color: var(--primary); + --ym-selected-current-foreground: var(--primary); + --ym-selected-current-background: #EDF5FF; + --ym-selected-current-outline-color: var(--primary); + --ym-selected-current-hover-foreground: var(--primary); + --ym-selected-current-hover-background: #D9EAFF; + --ym-selected-current-outline-hover-color: var(--primary); + --ym-selected-current-outline-focus-color: var(--primary); +} + +// Sass theme approach + +// $custom-calendar-theme-weekend: calendar-theme( +// $date-hover-background: var(--background-hover), +// $date-selected-foreground: var(--primary), +// $date-selected-background: #FFF, +// $date-selected-border-color: var(--primary), +// $date-selected-focus-foreground: var(--primary), +// $date-selected-focus-background: var(--background-hover), +// $date-selected-focus-border-color: var(--primary), +// $date-selected-hover-foreground: var(--primary), +// $date-selected-hover-background: var(--background-hover), +// $date-selected-hover-border-color: var(--primary), +// $date-selected-current-hover-background: var(--background-hover), +// $date-selected-current-focus-background: var(--background-hover), +// $date-selected-current-background: #FFF, +// $date-selected-current-border-color: var(--primary), +// $date-selected-current-hover-border-color: var(--primary), +// $date-current-hover-background: var(--background-hover) +// ); + +// $custom-calendar-theme: calendar-theme( +// $date-focus-background: transparent, +// $picker-foreground: var(--primary), +// $picker-hover-foreground: var(--primary), +// $picker-focus-foreground: var(--primary), +// $weekday-color: #556B82, +// $weekend-color: #131E29, +// $inactive-color: #556B82, +// $week-number-foreground: #556B82, +// $week-number-background: transparent, +// $ym-selected-current-hover-foreground: var(--primary), +// $ym-selected-current-hover-background: #D9EAFF, +// $ym-hover-background: var(--background), +// $ym-current-foreground: var(--primary), +// $ym-current-background: transparent, +// $ym-current-hover-foreground: var(--primary), +// $ym-current-hover-background: var(--background), +// $ym-selected-current-foreground: var(--primary), +// $ym-selected-current-background: #EDF5FF, +// $ym-selected-background: #EDF5FF, +// $ym-selected-hover-foreground: var(--primary), +// $ym-selected-hover-background: #D9EAFF, +// $ym-current-outline-color: transparent, +// $ym-current-outline-hover-color: var(--primary), +// $ym-selected-outline-color: var(--primary), +// $ym-selected-hover-outline-color: var(--primary), +// $ym-selected-focus-outline-color: var(--primary), +// $ym-selected-current-outline-color: var(--primary), +// $ym-selected-current-outline-hover-color: var(--primary), +// $ym-selected-current-outline-focus-color: var(--primary), +// $date-selected-current-foreground: var(--primary), +// $date-selected-current-background: #FFF, +// $date-selected-current-hover-foreground: var(--primary), +// $date-selected-current-hover-background: var(--background-weekend), +// $date-selected-current-focus-foreground: var(--primary), +// $date-selected-current-focus-background: var(--background-weekend), +// $date-selected-foreground: var(--primary), +// $date-selected-background: #FFF, +// $date-selected-border-color: var(--primary), +// $date-selected-hover-foreground: var(--primary), +// $date-selected-hover-background: var(--background-weekend), +// $date-selected-hover-border-color: var(--primary), +// $date-selected-focus-foreground: var(--primary), +// $date-selected-focus-background: var(--background-weekend), +// $date-selected-focus-border-color: var(--primary), +// $date-current-border-color: var(--current-border), +// $date-current-hover-border-color: var(--current-border), +// $date-current-focus-border-color: var(--current-border), +// $date-selected-current-border-color: var(--current-border), +// $date-selected-current-hover-border-color: var(--current-border), +// $date-selected-current-focus-border-color: var(--current-border), +// $date-current-hover-background: var(--background-weekend), +// $border-radius: rem(8px) +// ); + +// :host { +// ::ng-deep { +// .igx-days-view__date--weekend:not(.igx-days-view__date--inactive) { +// @include css-vars($custom-calendar-theme-weekend); +// } +// } +// } + +// igx-calendar { +// @include css-vars($custom-calendar-theme); +// } diff --git a/src/app/scheduling/calendar/calendar-styling-sample/layout.scss b/src/app/scheduling/calendar/calendar-styling-sample/layout.scss index 538514fc6b..bd4d37889b 100644 --- a/src/app/scheduling/calendar/calendar-styling-sample/layout.scss +++ b/src/app/scheduling/calendar/calendar-styling-sample/layout.scss @@ -1,12 +1,135 @@ @use "igniteui-angular/theming" as *; +:host { + ::ng-deep { + + // Note: This is not the standard approach for styling the component. + // We're using it here solely to mirror the UI5 sample. + + [title="Week"] .igx-days-view__label.igx-days-view__label--week-number { + opacity: 0; + } + + igx-icon { + --color: var(--primary); + --size: #{rem(20px)}; + } + + .igx-calendar-view__item-inner { + color: var(--primary) + } + + .igx-days-view__date--selected span { + font-weight: 700; + } + + .igx-days-view__date--current span { + border-width: rem(2px); + } + + .igx-days-view__date--weekend:not(.igx-days-view__date--inactive):not(.igx-days-view__date--selected) span:not(:hover) { + background: var(--background-weekend); + } + + .igx-days-view__date--active ::after { + border: rem(2px) solid #0032A5; + width: rem(20px); + height: rem(20px); + border-radius: rem(3px); + left: rem(3px); + } + + .igx-days-view__date--active.igx-days-view__date--current :after { + left: rem(2px); + } + + .igx-calendar-view__item:not(.igx-calendar-view__item--selected) .igx-calendar-view__item-inner:hover { + box-shadow: inset 0 0 0 rem(1px) #BCC3CA; + } + + .igx-calendar-view { + padding: 1rem rem(6px); + } + + .igx-calendar-picker__prev { + position: absolute; + } + + .igx-calendar-picker__next { + position: absolute; + right: 0; + } + + .igx-calendar-picker__nav { + position: relative; + left: 0; + bottom: rem(27px); + } + + .igx-calendar-picker__next:hover, + .igx-calendar-picker__prev:hover { + background-color: var(--background); + border-radius: rem(8px); + box-shadow: inset 0 0 0 rem(1px) #BCC3CA; + } + + .igx-calendar-picker__next, + .igx-calendar-picker__prev { + padding: rem(6px); + } + + .igx-calendar-picker { + display: unset; + } + + .igx-calendar-picker__dates { + justify-content: center; + position: relative; + top: rem(4px); + gap: 1rem; + height: 2rem; + + span:not(.igx-calendar__aria-off-screen) { + font-size: rem(14px); + padding: rem(4px) rem(10px); + + &:hover { + background-color: var(--background); + border-radius: rem(8px); + box-shadow: inset 0 0 0 rem(1px) #BCC3CA; + } + } + } + + .igx-calendar__pickers--days { + height: rem(24px); + } + + .igx-calendar-picker { + padding-inline: 1rem; + } + } +} + .calendar-wrapper { - max-width: 600px; - min-width: 200px; - margin: 8px; + max-width: rem(600px); + margin: rem(8px); } -.igx-calendar { - --ig-size: 2; - box-shadow: elevation(4); +igx-calendar { + --current-border: #A100C2; + --primary: #0064D9; + --background: #EAECEE; + --background-weekend: #E8E8E8; + --background-hover: #F5F6F8; + + width: rem(290px); + min-height: rem(282px); + box-sizing: border-box; + padding-top: rem(6px); + box-shadow: elevation(4); + --ig-font-family: Arial, sans-serif; + --ig-subtitle-1-font-weight: 600; + --ig-size: 1; + --ig-radius-factor: 0.4; } \ No newline at end of file