diff --git a/.github/workflows/check_pr_title_cc.yml b/.github/workflows/check_pr_title_cc.yml index 7a5fdb73..65c25beb 100644 --- a/.github/workflows/check_pr_title_cc.yml +++ b/.github/workflows/check_pr_title_cc.yml @@ -3,7 +3,7 @@ name: Check PR Title (Conventional Commits) on: pull_request: types: [opened, synchronize, reopened, edited, labeled, unlabeled] - branches: [master] + branches: [master, next-major] jobs: check-pr-title: diff --git a/api-generator/api-generator.js b/api-generator/api-generator.js index 0c5b19a1..d97e0be6 100644 --- a/api-generator/api-generator.js +++ b/api-generator/api-generator.js @@ -857,40 +857,61 @@ const allowed = (name) => { ); }; +// Handle `typeof SomeArray[number]` — parse the source file and expand string literals to a union. +// Returns null if `t` isn't that shape, or the source array couldn't be resolved. +const expandIndexedAccessArray = (t, project) => { + if ( + t?.type !== 'indexedAccess' || + t.objectType?.type !== 'query' || + t.indexType?.type !== 'intrinsic' || + t.indexType?.name !== 'number' + ) { + return null; + } + + const refName = t.objectType.queryType?.name; + const variable = refName + ? project + ?.getReflectionsByKind(TypeDoc.ReflectionKind.Variable) + ?.find((r) => r.name === refName) + : null; + const sourceFile = variable?.sources?.[0]?.fullFileName; + if (!sourceFile) return null; + + try { + const src = fs.readFileSync(sourceFile, 'utf-8'); + const arrayMatch = src.match( + new RegExp( + `(?:export\\s+)?const\\s+${refName}\\s*=\\s*\\[([\\s\\S]*?)\\]`, + 'm' + ) + ); + if (arrayMatch) { + const items = [...arrayMatch[1].matchAll(/'([^']+)'/g)].map( + (m) => `'${m[1]}'` + ); + if (items.length) return items.join(' | '); + } + } catch (_) {} + + return null; +}; + const getTypesValue = (typeobj, project) => { const { type, children, indexSignature } = typeobj ?? {}; - // 1) Handle `typeof SomeArray[number]` — parse the source file and expand string literals to a union. - if ( - type?.type === 'indexedAccess' && - type.objectType?.type === 'query' && - type.indexType?.type === 'intrinsic' && - type.indexType?.name === 'number' + // 1) Handle `typeof SomeArray[number]`, whether it's the whole type or a member of a + // top-level union (e.g. `typeof SomeArray[number] | ''`) — expand just that member. + if (type?.type === 'indexedAccess') { + const expanded = expandIndexedAccessArray(type, project); + if (expanded) return expanded; + } else if ( + type?.type === 'union' && + type.types?.some((member) => member.type === 'indexedAccess') ) { - const refName = type.objectType.queryType?.name; - const variable = refName - ? project - ?.getReflectionsByKind(TypeDoc.ReflectionKind.Variable) - ?.find((r) => r.name === refName) - : null; - const sourceFile = variable?.sources?.[0]?.fullFileName; - if (sourceFile) { - try { - const src = fs.readFileSync(sourceFile, 'utf-8'); - const arrayMatch = src.match( - new RegExp( - `(?:export\\s+)?const\\s+${refName}\\s*=\\s*\\[([\\s\\S]*?)\\]`, - 'm' - ) - ); - if (arrayMatch) { - const items = [...arrayMatch[1].matchAll(/'([^']+)'/g)].map( - (m) => `'${m[1]}'` - ); - if (items.length) return items.join(' | '); - } - } catch (_) {} - } + return type.types + .map((member) => expandIndexedAccessArray(member, project) ?? `${member}`) + .join(' | '); } // 2) Handle index signatures (e.g., { [key: string]: number }) diff --git a/projects/composition/src/app/api-data/cps-autocomplete.json b/projects/composition/src/app/api-data/cps-autocomplete.json index 89c00a37..7c01352e 100644 --- a/projects/composition/src/app/api-data/cps-autocomplete.json +++ b/projects/composition/src/app/api-data/cps-autocomplete.json @@ -193,7 +193,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -201,7 +201,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value." }, diff --git a/projects/composition/src/app/api-data/cps-button.json b/projects/composition/src/app/api-data/cps-button.json index 33086327..f63c6f6b 100644 --- a/projects/composition/src/app/api-data/cps-button.json +++ b/projects/composition/src/app/api-data/cps-button.json @@ -81,7 +81,7 @@ "name": "icon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Name of the icon on the button." }, diff --git a/projects/composition/src/app/api-data/cps-checkbox.json b/projects/composition/src/app/api-data/cps-checkbox.json index 36e0a10f..c64528a4 100644 --- a/projects/composition/src/app/api-data/cps-checkbox.json +++ b/projects/composition/src/app/api-data/cps-checkbox.json @@ -73,7 +73,7 @@ "name": "icon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Name of the icon." }, diff --git a/projects/composition/src/app/api-data/cps-chip.json b/projects/composition/src/app/api-data/cps-chip.json index f68bbe77..c9042dbc 100644 --- a/projects/composition/src/app/api-data/cps-chip.json +++ b/projects/composition/src/app/api-data/cps-chip.json @@ -17,7 +17,7 @@ "name": "icon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Name of the icon." }, diff --git a/projects/composition/src/app/api-data/cps-dialog.json b/projects/composition/src/app/api-data/cps-dialog.json index 1e72b551..7755a487 100644 --- a/projects/composition/src/app/api-data/cps-dialog.json +++ b/projects/composition/src/app/api-data/cps-dialog.json @@ -95,7 +95,7 @@ "name": "headerIcon", "optional": true, "readonly": false, - "type": "string", + "type": "CpsIconType", "description": "Header icon." }, { diff --git a/projects/composition/src/app/api-data/cps-expansion-panel.json b/projects/composition/src/app/api-data/cps-expansion-panel.json index 12784313..74ea2212 100644 --- a/projects/composition/src/app/api-data/cps-expansion-panel.json +++ b/projects/composition/src/app/api-data/cps-expansion-panel.json @@ -81,7 +81,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Name of the icon in front of the title." } diff --git a/projects/composition/src/app/api-data/cps-icon.json b/projects/composition/src/app/api-data/cps-icon.json index 020a86b2..8aa574ed 100644 --- a/projects/composition/src/app/api-data/cps-icon.json +++ b/projects/composition/src/app/api-data/cps-icon.json @@ -9,7 +9,7 @@ "name": "icon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Name of the icon." }, @@ -17,7 +17,7 @@ "name": "size", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "small", "description": "Size of the icon, it can be of type number denoting pixels, string or 'fill', 'xsmall', 'small', 'normal' or 'large'." }, @@ -45,14 +45,14 @@ "description": "Defines the custom types used by the component or service.", "values": [ { - "name": "IconType", - "value": "'access' | 'access-denied' | 'access-lock' | 'access-unlock' | 'add' | 'add-domain' | 'angle-left' | 'angle-right' | 'attribute' | 'avatar' | 'avatar-top-menu' | 'bell' | 'book' | 'bookmark' | 'browse' | 'burger' | 'burger-arrow' | 'caret-down' | 'change' | 'checked' | 'chevron-down' | 'chevron-down-2' | 'circle' | 'cleansing' | 'close-x' | 'close-x-2' | 'columns' | 'construction' | 'controls' | 'copy' | 'csv' | 'cube' | 'database' | 'datafeed' | 'datepicker' | 'delete' | 'dislike' | 'domain' | 'dots' | 'download' | 'dq' | 'dropdown-menu' | 'edit' | 'expand' | 'export' | 'eye' | 'filter' | 'filter_2' | 'filter-funnel' | 'filter-funnel-filled' | 'follow' | 'graph' | 'grid' | 'grid-view' | 'health' | 'heart' | 'help-circle' | 'home' | 'info-circle' | 'insight' | 'issues' | 'jpeg' | 'json' | 'kafka' | 'kris' | 'last-seen-product' | 'left' | 'like' | 'line-vertical' | 'lock' | 'logout' | 'maximize' | 'measurement' | 'menu-expand' | 'menu-shrink' | 'minimize' | 'minus' | 'moon' | 'move-grabber' | 'open' | 'ownership' | 'path' | 'pdf' | 'pending' | 'plus' | 'projects' | 'question' | 'questions' | 'rectangle-rounded' | 'refresh' | 'remove' | 'right' | 'save' | 'schema' | 'schema_filter' | 'search' | 'settings' | 'smart' | 'sort-icon-asc' | 'sort-icon-desc' | 'star' | 'stepper-completed' | 'success' | 'suggestion' | 'sun' | 'survivorship' | 'table-row-error' | 'table-row-success' | 'table-row-warning' | 'toast-error' | 'toast-info' | 'toast-success' | 'toast-warning' | 'tools' | 'user' | 'users' | 'vector' | 'vector-down' | 'vector-right' | 'vector-up' | 'wallet' | 'warning' | 'widget-button-icon' | 'xls'", - "description": "IconType is used to define the type of the icon." + "name": "CpsIconType", + "value": "'access' | 'access-denied' | 'access-lock' | 'access-unlock' | 'add' | 'add-domain' | 'angle-left' | 'angle-right' | 'attribute' | 'avatar' | 'avatar-top-menu' | 'bell' | 'book' | 'bookmark' | 'browse' | 'burger' | 'burger-arrow' | 'caret-down' | 'change' | 'checked' | 'chevron-down' | 'chevron-down-2' | 'circle' | 'cleansing' | 'close-x' | 'close-x-2' | 'columns' | 'construction' | 'controls' | 'copy' | 'csv' | 'cube' | 'database' | 'datafeed' | 'datepicker' | 'delete' | 'dislike' | 'domain' | 'dots' | 'download' | 'dq' | 'dropdown-menu' | 'edit' | 'expand' | 'export' | 'eye' | 'filter' | 'filter_2' | 'filter-funnel' | 'filter-funnel-filled' | 'follow' | 'graph' | 'grid' | 'grid-view' | 'health' | 'heart' | 'help-circle' | 'home' | 'info-circle' | 'insight' | 'issues' | 'jpeg' | 'json' | 'kafka' | 'kris' | 'last-seen-product' | 'left' | 'like' | 'line-vertical' | 'lock' | 'logout' | 'maximize' | 'measurement' | 'menu-expand' | 'menu-shrink' | 'minimize' | 'minus' | 'moon' | 'move-grabber' | 'open' | 'ownership' | 'path' | 'pdf' | 'pending' | 'plus' | 'projects' | 'question' | 'questions' | 'rectangle-rounded' | 'refresh' | 'remove' | 'right' | 'save' | 'schema' | 'schema_filter' | 'search' | 'settings' | 'smart' | 'sort-icon-asc' | 'sort-icon-desc' | 'star' | 'stepper-completed' | 'success' | 'suggestion' | 'sun' | 'survivorship' | 'table-row-error' | 'table-row-success' | 'table-row-warning' | 'toast-error' | 'toast-info' | 'toast-success' | 'toast-warning' | 'tools' | 'user' | 'users' | 'vector' | 'vector-down' | 'vector-right' | 'vector-up' | 'wallet' | 'warning' | 'widget-button-icon' | 'xls' | \"\"", + "description": "CpsIconType is used to define the type of the icon." }, { - "name": "iconSizeType", + "name": "CpsIconSizeType", "value": "number | string | \"fill\" | \"xsmall\" | \"small\" | \"normal\" | \"large\"", - "description": "iconSizeType is used to define the size of the icon." + "description": "CpsIconSizeType is used to define the size of the icon." } ] } diff --git a/projects/composition/src/app/api-data/cps-info-circle.json b/projects/composition/src/app/api-data/cps-info-circle.json index 758fd0ce..c954a8d9 100644 --- a/projects/composition/src/app/api-data/cps-info-circle.json +++ b/projects/composition/src/app/api-data/cps-info-circle.json @@ -9,7 +9,7 @@ "name": "size", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "small", "description": "Size of the icon, it can be of type number denoting pixels, string or 'fill', 'xsmall', 'small', 'normal' or 'large'." }, diff --git a/projects/composition/src/app/api-data/cps-input.json b/projects/composition/src/app/api-data/cps-input.json index 8f8d1c24..a40cdb82 100644 --- a/projects/composition/src/app/api-data/cps-input.json +++ b/projects/composition/src/app/api-data/cps-input.json @@ -137,7 +137,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -153,7 +153,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value." }, diff --git a/projects/composition/src/app/api-data/cps-select.json b/projects/composition/src/app/api-data/cps-select.json index 5640b67f..f006061d 100644 --- a/projects/composition/src/app/api-data/cps-select.json +++ b/projects/composition/src/app/api-data/cps-select.json @@ -185,7 +185,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -193,7 +193,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value." }, diff --git a/projects/composition/src/app/api-data/cps-sidebar-menu.json b/projects/composition/src/app/api-data/cps-sidebar-menu.json index 46c60d5e..537b976f 100644 --- a/projects/composition/src/app/api-data/cps-sidebar-menu.json +++ b/projects/composition/src/app/api-data/cps-sidebar-menu.json @@ -54,7 +54,7 @@ "values": [ { "name": "CpsSidebarMenuItem", - "value": "{\n \"title\": \"string\",\n \"icon\": \"string\",\n \"url?\": \"string\",\n \"target?\": \"string\",\n \"disabled?\": \"boolean\",\n \"items?\": \"CpsMenuItem[]\"\n}", + "value": "{\n \"title\": \"string\",\n \"icon\": \"CpsIconType\",\n \"url?\": \"string\",\n \"target?\": \"string\",\n \"disabled?\": \"boolean\",\n \"items?\": \"CpsMenuItem[]\"\n}", "description": "CpsSidebarMenuItem is used to define the items of the CpsSidebarMenuComponent." } ] diff --git a/projects/composition/src/app/api-data/cps-table.json b/projects/composition/src/app/api-data/cps-table.json index 92963fc6..21a0d7f0 100644 --- a/projects/composition/src/app/api-data/cps-table.json +++ b/projects/composition/src/app/api-data/cps-table.json @@ -224,7 +224,7 @@ "name": "toolbarIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "Toolbar icon name." }, @@ -432,7 +432,7 @@ "name": "additionalBtnOnSelectIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "AdditionalBtnOnSelect icon." }, @@ -464,7 +464,7 @@ "name": "actionBtnIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "Action button icon." }, diff --git a/projects/composition/src/app/api-data/cps-tree-autocomplete.json b/projects/composition/src/app/api-data/cps-tree-autocomplete.json index f804f5bc..7a2b10be 100644 --- a/projects/composition/src/app/api-data/cps-tree-autocomplete.json +++ b/projects/composition/src/app/api-data/cps-tree-autocomplete.json @@ -145,7 +145,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -153,7 +153,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value, of type number, string, 'fill', 'xsmall', 'small', 'normal' or 'large'." }, diff --git a/projects/composition/src/app/api-data/cps-tree-select.json b/projects/composition/src/app/api-data/cps-tree-select.json index edd768a0..fbd5ec23 100644 --- a/projects/composition/src/app/api-data/cps-tree-select.json +++ b/projects/composition/src/app/api-data/cps-tree-select.json @@ -137,7 +137,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -145,7 +145,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value, of type number, string, 'fill', 'xsmall', 'small', 'normal' or 'large'." }, diff --git a/projects/composition/src/app/api-data/cps-tree-table.json b/projects/composition/src/app/api-data/cps-tree-table.json index 55a6c14d..d53e5a5e 100644 --- a/projects/composition/src/app/api-data/cps-tree-table.json +++ b/projects/composition/src/app/api-data/cps-tree-table.json @@ -216,7 +216,7 @@ "name": "toolbarIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "Toolbar icon name." }, @@ -432,7 +432,7 @@ "name": "additionalBtnOnSelectIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "AdditionalBtnOnSelect icon." }, @@ -464,7 +464,7 @@ "name": "actionBtnIcon", "optional": false, "readonly": false, - "type": "string", + "type": "CpsIconType", "default": "", "description": "Action button icon." }, diff --git a/projects/composition/src/app/api-data/internal.json b/projects/composition/src/app/api-data/internal.json index 601e71c5..8ba390e3 100644 --- a/projects/composition/src/app/api-data/internal.json +++ b/projects/composition/src/app/api-data/internal.json @@ -121,7 +121,7 @@ "name": "prefixIcon", "optional": false, "readonly": false, - "type": "IconType", + "type": "CpsIconType", "default": "", "description": "Icon before input value." }, @@ -129,7 +129,7 @@ "name": "prefixIconSize", "optional": false, "readonly": false, - "type": "iconSizeType", + "type": "CpsIconSizeType", "default": "1.125rem", "description": "Size of icon before input value, of type number, string, 'fill', 'xsmall', 'small', 'normal' or 'large'." }, diff --git a/projects/composition/src/app/api-data/types_map.json b/projects/composition/src/app/api-data/types_map.json index 56d0c694..0bd90fdb 100644 --- a/projects/composition/src/app/api-data/types_map.json +++ b/projects/composition/src/app/api-data/types_map.json @@ -4,8 +4,8 @@ "CpsDatepickerAppearanceType": "datepicker", "CpsDatepickerDateFormat": "datepicker", "CpsDividerType": "divider", - "IconType": "icon", - "iconSizeType": "icon", + "CpsIconType": "icon", + "CpsIconSizeType": "icon", "CpsInputAppearanceType": "input", "CpsMenuItem": "menu", "CpsMenuAttachPosition": "menu", diff --git a/projects/composition/src/app/components/dialog-content/dialog-content.component.ts b/projects/composition/src/app/components/dialog-content/dialog-content.component.ts index 72f872be..cec28294 100644 --- a/projects/composition/src/app/components/dialog-content/dialog-content.component.ts +++ b/projects/composition/src/app/components/dialog-content/dialog-content.component.ts @@ -3,7 +3,8 @@ import { CpsButtonComponent, CpsDialogConfig, CpsDialogRef, - CpsIconComponent + CpsIconComponent, + type CpsIconType } from 'cps-ui-kit'; @Component({ @@ -14,7 +15,7 @@ import { }) export class DialogContentComponent implements OnInit { info = ''; - icon = ''; + icon: CpsIconType = ''; closeDisabled = false; diff --git a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.ts b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.ts index 3ff57547..1cfb0683 100644 --- a/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.ts +++ b/projects/composition/src/app/pages/icons-page/icons-page/icons-page.component.ts @@ -5,7 +5,8 @@ import { CpsInputComponent, CpsNotificationPosition, CpsNotificationService, - iconNames + cpsIconNames, + type CpsIconType } from 'cps-ui-kit'; import ComponentData from '../../../api-data/cps-icon.json'; @@ -24,13 +25,13 @@ import { ComponentDocsViewerComponent } from '../../../components/component-docs host: { class: 'composition-page' } }) export class IconsPageComponent implements OnInit { - filteredIconsList: string[] = []; + filteredIconsList: CpsIconType[] = []; componentData = ComponentData; private _notificationService = inject(CpsNotificationService); ngOnInit() { - this.filteredIconsList = iconNames; + this.filteredIconsList = [...cpsIconNames]; } onSearchChanged(value: string) { @@ -39,7 +40,7 @@ export class IconsPageComponent implements OnInit { private _filterIcons(name: string) { name = name.toLowerCase(); - this.filteredIconsList = iconNames.filter((n) => + this.filteredIconsList = cpsIconNames.filter((n) => n.toLowerCase().includes(name) ); } diff --git a/projects/composition/src/app/pages/tab-group-page/tab-group-page.component.ts b/projects/composition/src/app/pages/tab-group-page/tab-group-page.component.ts index be154885..7544ea00 100644 --- a/projects/composition/src/app/pages/tab-group-page/tab-group-page.component.ts +++ b/projects/composition/src/app/pages/tab-group-page/tab-group-page.component.ts @@ -4,7 +4,8 @@ import { CpsTabGroupComponent, CpsTabComponent, CpsTabChangeEvent, - CpsCheckboxComponent + CpsCheckboxComponent, + type CpsIconType } from 'cps-ui-kit'; import ComponentData from '../../api-data/cps-tab-group.json'; @@ -53,15 +54,16 @@ export class TabGroupPageComponent { tooltipText: `Tooltip of tab ${i + 1}` })); - rightAlignedTabs = [ - { label: 'Tab 1', icon: 'survivorship', id: 'tab1' }, - { label: 'Tab 2', icon: 'kris', id: null }, - { label: 'Tab 3', icon: 'dq', id: null } - ]; + rightAlignedTabs: { label: string; icon: CpsIconType; id: string | null }[] = + [ + { label: 'Tab 1', icon: 'survivorship', id: 'tab1' }, + { label: 'Tab 2', icon: 'kris', id: null }, + { label: 'Tab 3', icon: 'dq', id: null } + ]; stretchedTabs = [{ label: 'Tab 1' }, { label: 'Tab 2' }, { label: 'Tab 3' }]; - subTabs = [ + subTabs: { label: string; icon: CpsIconType; id: string | null }[] = [ { label: 'Tab 1', icon: 'avatar', id: 'tab1' }, { label: 'Tab 2', icon: '', id: null }, { label: 'Tab 3', icon: '', id: null } diff --git a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts index 1b212dd3..e7782582 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-autocomplete/cps-autocomplete.component.ts @@ -32,8 +32,8 @@ import { } from '../../utils/internal/accessibility-utils'; import { CpsIconComponent, - IconType, - iconSizeType + type CpsIconType, + type CpsIconSizeType } from '../cps-icon/cps-icon.component'; import { CpsChipComponent } from '../cps-chip/cps-chip.component'; import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component'; @@ -227,13 +227,13 @@ export class CpsAutocompleteComponent * Icon before input value. * @group Props */ - @Input() prefixIcon: IconType = ''; + @Input() prefixIcon: CpsIconType = ''; /** * Size of icon before input value. * @group Props */ - @Input() prefixIconSize: iconSizeType = '1.125rem'; + @Input() prefixIconSize: CpsIconSizeType = '1.125rem'; /** * When enabled, a loading bar is displayed. diff --git a/projects/cps-ui-kit/src/lib/components/cps-button/cps-button.component.ts b/projects/cps-ui-kit/src/lib/components/cps-button/cps-button.component.ts index f4a78e82..42993e21 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-button/cps-button.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-button/cps-button.component.ts @@ -8,10 +8,13 @@ import { OnChanges, OnInit, Output, - SimpleChanges + type SimpleChanges } from '@angular/core'; import { getCSSColor } from '../../utils/colors-utils'; -import { CpsIconComponent, IconType } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { CpsProgressCircularComponent } from '../cps-progress-circular/cps-progress-circular.component'; import { convertSize, parseSize } from '../../utils/internal/size-utils'; import { logMissingAriaLabelError } from '../../utils/internal/accessibility-utils'; @@ -85,7 +88,7 @@ export class CpsButtonComponent implements OnInit, OnChanges { * Name of the icon on the button. * @group Props */ - @Input() icon: IconType = ''; + @Input() icon: CpsIconType = ''; /** * Position of the icon on the button, it can be 'before' or 'after'. diff --git a/projects/cps-ui-kit/src/lib/components/cps-checkbox/cps-checkbox.component.ts b/projects/cps-ui-kit/src/lib/components/cps-checkbox/cps-checkbox.component.ts index 9995e362..fe6a1890 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-checkbox/cps-checkbox.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-checkbox/cps-checkbox.component.ts @@ -15,7 +15,10 @@ import { import { ControlValueAccessor, NgControl } from '@angular/forms'; import { CpsInfoCircleComponent } from '../cps-info-circle/cps-info-circle.component'; import { CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.directive'; -import { CpsIconComponent, IconType } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { getCSSColor } from '../../utils/colors-utils'; import { logMissingAriaLabelError } from '../../utils/internal/accessibility-utils'; @@ -84,7 +87,7 @@ export class CpsCheckboxComponent * Name of the icon. * @group Props */ - @Input() icon: IconType = ''; + @Input() icon: CpsIconType = ''; /** * Color of the icon. diff --git a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.ts b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.ts index b9115c9c..85657118 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-chip/cps-chip.component.ts @@ -5,7 +5,10 @@ import { OnChanges, Output } from '@angular/core'; -import { CpsIconComponent, IconType } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { CommonModule } from '@angular/common'; /** @@ -29,7 +32,7 @@ export class CpsChipComponent implements OnChanges { * Name of the icon. * @group Props */ - @Input() icon: IconType = ''; + @Input() icon: CpsIconType = ''; /** * Color of the icon. diff --git a/projects/cps-ui-kit/src/lib/components/cps-expansion-panel/cps-expansion-panel.component.ts b/projects/cps-ui-kit/src/lib/components/cps-expansion-panel/cps-expansion-panel.component.ts index 3e317770..6aad07a9 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-expansion-panel/cps-expansion-panel.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-expansion-panel/cps-expansion-panel.component.ts @@ -13,7 +13,10 @@ import { inject, type SimpleChanges } from '@angular/core'; -import { CpsIconComponent, IconType } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { getCSSColor } from '../../utils/colors-utils'; import { convertSize } from '../../utils/internal/size-utils'; import { generateUniqueId } from '../../utils/internal/accessibility-utils'; @@ -126,7 +129,7 @@ export class CpsExpansionPanelComponent * Name of the icon in front of the title. * @group Props */ - @Input() prefixIcon: IconType = ''; + @Input() prefixIcon: CpsIconType = ''; /** * Callback to invoke after a tab gets collapsed. diff --git a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.spec.ts b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.spec.ts index c9a6ce1a..5a81977c 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.spec.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.spec.ts @@ -1,6 +1,6 @@ import { SimpleChange } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CpsIconComponent, ICONS_PATH } from './cps-icon.component'; +import { CpsIconComponent, CPS_ICONS_PATH } from './cps-icon.component'; import { CommonModule } from '@angular/common'; describe('CpsIconComponent', () => { @@ -84,13 +84,13 @@ describe('CpsIconComponent', () => { }); describe('Test assets path injection', () => { - it('should use default path when no ICONS_PATH is provided', () => { + it('should use default path when no CPS_ICONS_PATH is provided', () => { createComponent(); expect(component.url).toBe('assets/'); }); - it('should use injected ICONS_PATH value', () => { - TestBed.overrideProvider(ICONS_PATH, { + it('should use injected CPS_ICONS_PATH value', () => { + TestBed.overrideProvider(CPS_ICONS_PATH, { useValue: 'test-assets/' }); createComponent(); diff --git a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts index e5911db8..b2b607ec 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-icon/cps-icon.component.ts @@ -17,11 +17,11 @@ import { convertSize } from '../../utils/internal/size-utils'; /** * Injection token that is used to provide the path to the icons. */ -export const ICONS_PATH = new InjectionToken( +export const CPS_ICONS_PATH = new InjectionToken( 'Icons path for CpsIconComponent' ); -export const iconNames = [ +export const cpsIconNames = [ 'access', 'access-denied', 'access-lock', @@ -146,19 +146,19 @@ export const iconNames = [ 'warning', 'widget-button-icon', 'xls' -]; +] as const; /** - * IconType is used to define the type of the icon. + * CpsIconType is used to define the type of the icon. * @group Types */ -export type IconType = (typeof iconNames)[number]; +export type CpsIconType = (typeof cpsIconNames)[number] | ''; /** - * iconSizeType is used to define the size of the icon. + * CpsIconSizeType is used to define the size of the icon. * @group Types */ -export type iconSizeType = +export type CpsIconSizeType = | number | string | 'fill' @@ -186,13 +186,13 @@ export class CpsIconComponent implements OnInit, OnChanges { * Name of the icon. * @group Props */ - @Input() icon: IconType = ''; + @Input() icon: CpsIconType = ''; /** * Size of the icon, it can be of type number denoting pixels, string or 'fill', 'xsmall', 'small', 'normal' or 'large'. * @group Props */ - @Input() size: iconSizeType = 'small'; + @Input() size: CpsIconSizeType = 'small'; /** * Color of the icon. @@ -227,7 +227,7 @@ export class CpsIconComponent implements OnInit, OnChanges { } iconColor = 'currentColor'; - url = inject(ICONS_PATH, { optional: true }) ?? 'assets/'; + url = inject(CPS_ICONS_PATH, { optional: true }) ?? 'assets/'; cvtSize = ''; classesList: string[] = ['cps-icon']; diff --git a/projects/cps-ui-kit/src/lib/components/cps-info-circle/cps-info-circle.component.ts b/projects/cps-ui-kit/src/lib/components/cps-info-circle/cps-info-circle.component.ts index 423c4122..a3926874 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-info-circle/cps-info-circle.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-info-circle/cps-info-circle.component.ts @@ -1,8 +1,11 @@ import { Component, Input } from '@angular/core'; -import { CpsIconComponent, iconSizeType } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconSizeType +} from '../cps-icon/cps-icon.component'; import { CpsTooltipDirective, - CpsTooltipPosition + type CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.directive'; /** @@ -20,7 +23,7 @@ export class CpsInfoCircleComponent { * Size of the icon, it can be of type number denoting pixels, string or 'fill', 'xsmall', 'small', 'normal' or 'large'. * @group Props */ - @Input() size: iconSizeType = 'small'; + @Input() size: CpsIconSizeType = 'small'; /** * Tooltip text to provide more info. diff --git a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts index 393e296f..59c1766b 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-input/cps-input.component.ts @@ -10,7 +10,7 @@ import { Optional, Output, Self, - SimpleChanges + type SimpleChanges } from '@angular/core'; import { ControlValueAccessor, NgControl, Validators } from '@angular/forms'; import { Subscription } from 'rxjs'; @@ -18,8 +18,8 @@ import { CpsTooltipPosition } from '../../directives/cps-tooltip/cps-tooltip.dir import { convertSize } from '../../utils/internal/size-utils'; import { CpsIconComponent, - IconType, - iconSizeType + type CpsIconType, + type CpsIconSizeType } from '../cps-icon/cps-icon.component'; import { CpsInfoCircleComponent } from '../cps-info-circle/cps-info-circle.component'; import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component'; @@ -152,7 +152,7 @@ export class CpsInputComponent * Icon before input value. * @group Props */ - @Input() prefixIcon: IconType = ''; + @Input() prefixIcon: CpsIconType = ''; /** * When enabled, prefixIcon is clickable. @@ -164,7 +164,7 @@ export class CpsInputComponent * Size of icon before input value. * @group Props */ - @Input() prefixIconSize: iconSizeType = '1.125rem'; + @Input() prefixIconSize: CpsIconSizeType = '1.125rem'; /** * Aria label for the clickable prefix icon, required when prefixIconClickable is true. diff --git a/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.ts b/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.ts index db1de520..edc3bd7e 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-select/cps-select.component.ts @@ -30,8 +30,8 @@ import { } from '../../utils/internal/accessibility-utils'; import { CpsIconComponent, - iconSizeType, - IconType + type CpsIconSizeType, + type CpsIconType } from '../cps-icon/cps-icon.component'; import { CpsChipComponent } from '../cps-chip/cps-chip.component'; import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component'; @@ -219,13 +219,13 @@ export class CpsSelectComponent * Icon before input value. * @group Props */ - @Input() prefixIcon: IconType = ''; + @Input() prefixIcon: CpsIconType = ''; /** * Size of icon before input value. * @group Props */ - @Input() prefixIconSize: iconSizeType = '1.125rem'; + @Input() prefixIconSize: CpsIconSizeType = '1.125rem'; /** * When enabled, a loading bar is displayed. diff --git a/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.spec.ts b/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.spec.ts index 565f3b95..46b6051a 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.spec.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.spec.ts @@ -18,7 +18,7 @@ describe('CpsSidebarMenuComponent', () => { { title: 'Settings', icon: 'settings', url: '/settings', disabled: true }, { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [ { title: 'Monthly', url: '/reports/monthly' }, { title: 'Annual', url: '/reports/annual' } @@ -92,7 +92,7 @@ describe('CpsSidebarMenuComponent', () => { it('should return false when sub-items have no URLs', () => { const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly' }] }; expect(component.isActive(item)).toBe(false); @@ -101,7 +101,7 @@ describe('CpsSidebarMenuComponent', () => { it('should return true when current URL partially matches a sub-item URL', () => { const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly', url: '/reports/monthly' }] }; jest.spyOn(router, 'url', 'get').mockReturnValue('/reports/monthly'); @@ -111,7 +111,7 @@ describe('CpsSidebarMenuComponent', () => { it('should return false when current URL does not match any sub-item URL', () => { const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly', url: '/reports/monthly' }] }; jest.spyOn(router, 'url', 'get').mockReturnValue('/home'); @@ -122,7 +122,7 @@ describe('CpsSidebarMenuComponent', () => { component.exactRoutes = false; const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Reports', url: '/reports' }] }; jest.spyOn(router, 'url', 'get').mockReturnValue('/reports/monthly'); @@ -133,7 +133,7 @@ describe('CpsSidebarMenuComponent', () => { component.exactRoutes = true; const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Reports', url: '/reports' }] }; jest.spyOn(router, 'url', 'get').mockReturnValue('/reports/monthly'); @@ -144,7 +144,7 @@ describe('CpsSidebarMenuComponent', () => { component.exactRoutes = true; const item: CpsSidebarMenuItem = { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Reports', url: '/reports' }] }; jest.spyOn(router, 'url', 'get').mockReturnValue('/reports'); @@ -174,7 +174,7 @@ describe('CpsSidebarMenuComponent', () => { it('should set focusedItemWithMenu on focusin event', () => { const el = document.createElement('button'); - const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'reports' }; + const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'graph' }; const event = { type: 'focusin', currentTarget: el } as any; component.showMenu(event, mockMenu as CpsMenuComponent, item); expect(component.focusedItemWithMenu).toBe(item); @@ -198,7 +198,7 @@ describe('CpsSidebarMenuComponent', () => { it('should call show again on focusin when menu is already visible', () => { const el = document.createElement('button'); - const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'reports' }; + const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'graph' }; const event = { type: 'focusin', currentTarget: el } as any; (mockMenu.isVisible as jest.Mock).mockReturnValue(true); component.showMenu(event, mockMenu as CpsMenuComponent, item); @@ -224,7 +224,7 @@ describe('CpsSidebarMenuComponent', () => { show: jest.fn(), hide: jest.fn() } as unknown as Pick; - item = { title: 'Reports', icon: 'reports' }; + item = { title: 'Reports', icon: 'graph' }; component.allMenus = { forEach: jest.fn() } as any; }); @@ -302,7 +302,7 @@ describe('CpsSidebarMenuComponent', () => { }); it('should reset focusedItemWithMenu on focusout when hiding', () => { - component.focusedItemWithMenu = { title: 'Test', icon: 'icon' }; + component.focusedItemWithMenu = { title: 'Test', icon: 'star' }; const externalEl = document.createElement('div'); const event = { type: 'focusout', relatedTarget: externalEl } as any; component.leaveMenu(event, mockMenu as any); @@ -310,7 +310,7 @@ describe('CpsSidebarMenuComponent', () => { }); it('should not reset focusedItemWithMenu on mouseleave', () => { - const focusedItem: CpsSidebarMenuItem = { title: 'Test', icon: 'icon' }; + const focusedItem: CpsSidebarMenuItem = { title: 'Test', icon: 'star' }; component.focusedItemWithMenu = focusedItem; const externalEl = document.createElement('div'); const event = { type: 'mouseleave', relatedTarget: externalEl } as any; @@ -355,7 +355,7 @@ describe('CpsSidebarMenuComponent', () => { it('showMenu on focusin should be skipped when _pendingTouch is true', () => { (component as unknown as InternalComponent)._pendingTouch = true; const el = document.createElement('button'); - const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'reports' }; + const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'graph' }; const event = { type: 'focusin', currentTarget: el @@ -389,7 +389,7 @@ describe('CpsSidebarMenuComponent', () => { it('toggleMenu should reset _pendingTouch and open the menu (simulates first tap)', () => { (component as unknown as InternalComponent)._pendingTouch = true; const el = document.createElement('button'); - const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'reports' }; + const item: CpsSidebarMenuItem = { title: 'Reports', icon: 'graph' }; const event = { currentTarget: el } as unknown as MouseEvent; (mockMenu.isVisible as jest.Mock).mockReturnValue(false); component.toggleMenu(event, mockMenu as CpsMenuComponent, item); @@ -612,7 +612,7 @@ describe('CpsSidebarMenuComponent', () => { fixture.componentRef.setInput('items', [ { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly', url: '/reports/monthly' }] } ]); @@ -627,7 +627,7 @@ describe('CpsSidebarMenuComponent', () => { fixture.componentRef.setInput('items', [ { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly', url: '/reports/monthly' }] } ]); @@ -642,7 +642,7 @@ describe('CpsSidebarMenuComponent', () => { fixture.componentRef.setInput('items', [ { title: 'Reports', - icon: 'reports', + icon: 'graph', items: [{ title: 'Monthly', url: '/reports/monthly' }] } ]); diff --git a/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.ts b/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.ts index fbebcda9..2a046d1b 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-sidebar-menu/cps-sidebar-menu.component.ts @@ -14,7 +14,10 @@ import { import { CommonModule, isPlatformBrowser } from '@angular/common'; import { Router, RouterModule } from '@angular/router'; import { CpsMenuComponent, CpsMenuItem } from '../cps-menu/cps-menu.component'; -import { CpsIconComponent } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { convertSize } from '../../utils/internal/size-utils'; import { animate, @@ -34,7 +37,7 @@ import { */ export type CpsSidebarMenuItem = { title: string; - icon: string; + icon: CpsIconType; url?: string; target?: string; disabled?: boolean; diff --git a/projects/cps-ui-kit/src/lib/components/cps-table/cps-table.component.ts b/projects/cps-ui-kit/src/lib/components/cps-table/cps-table.component.ts index 85e6f505..866cf446 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-table/cps-table.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-table/cps-table.component.ts @@ -24,7 +24,10 @@ import { SortEvent } from 'primeng/api'; import { CpsInputComponent } from '../cps-input/cps-input.component'; import { CpsButtonComponent } from '../cps-button/cps-button.component'; import { CpsSelectComponent } from '../cps-select/cps-select.component'; -import { CpsIconComponent } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { CpsMenuComponent, CpsMenuItem } from '../cps-menu/cps-menu.component'; import { CpsLoaderComponent } from '../cps-loader/cps-loader.component'; import { TableRowMenuComponent } from './components/internal/table-row-menu/table-row-menu.component'; @@ -279,7 +282,7 @@ export class CpsTableComponent implements OnInit, AfterViewChecked, OnChanges { * Toolbar icon name. * @group Props */ - @Input() toolbarIcon = ''; + @Input() toolbarIcon: CpsIconType = ''; /** * Toolbar icon color. @@ -435,7 +438,7 @@ export class CpsTableComponent implements OnInit, AfterViewChecked, OnChanges { * AdditionalBtnOnSelect icon. * @group Props */ - @Input() additionalBtnOnSelectIcon = ''; + @Input() additionalBtnOnSelectIcon: CpsIconType = ''; /** * Determines whether additionalBtnOnSelect is disabled. @@ -459,7 +462,7 @@ export class CpsTableComponent implements OnInit, AfterViewChecked, OnChanges { * Action button icon. * @group Props */ - @Input() actionBtnIcon = ''; + @Input() actionBtnIcon: CpsIconType = ''; /** * Determines whether actionBtn is disabled. diff --git a/projects/cps-ui-kit/src/lib/components/cps-tree-table/cps-tree-table.component.ts b/projects/cps-ui-kit/src/lib/components/cps-tree-table/cps-tree-table.component.ts index d1efac84..22a7b684 100644 --- a/projects/cps-ui-kit/src/lib/components/cps-tree-table/cps-tree-table.component.ts +++ b/projects/cps-ui-kit/src/lib/components/cps-tree-table/cps-tree-table.component.ts @@ -37,7 +37,10 @@ import { import { Subscription, fromEvent } from 'rxjs'; import { convertSize } from '../../utils/internal/size-utils'; import { CpsButtonComponent } from '../cps-button/cps-button.component'; -import { CpsIconComponent } from '../cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../cps-icon/cps-icon.component'; import { CpsInputComponent } from '../cps-input/cps-input.component'; import { CpsLoaderComponent } from '../cps-loader/cps-loader.component'; import { CpsMenuItem } from '../cps-menu/cps-menu.component'; @@ -285,7 +288,7 @@ export class CpsTreeTableComponent * Toolbar icon name. * @group Props */ - @Input() toolbarIcon = ''; + @Input() toolbarIcon: CpsIconType = ''; /** * Toolbar icon color. @@ -447,7 +450,7 @@ export class CpsTreeTableComponent * AdditionalBtnOnSelect icon. * @group Props */ - @Input() additionalBtnOnSelectIcon = ''; + @Input() additionalBtnOnSelectIcon: CpsIconType = ''; /** * Determines whether additionalBtnOnSelect is disabled. @@ -471,7 +474,7 @@ export class CpsTreeTableComponent * Action button icon. * @group Props */ - @Input() actionBtnIcon = ''; + @Input() actionBtnIcon: CpsIconType = ''; /** * Determines whether actionBtn is disabled. diff --git a/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts b/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts index c8546346..8b9f011b 100644 --- a/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts +++ b/projects/cps-ui-kit/src/lib/components/internal/cps-base-tree-dropdown/cps-base-tree-dropdown.component.ts @@ -26,7 +26,10 @@ import { import { Subscription } from 'rxjs'; import { Tree } from 'primeng/tree'; import { isEqual } from 'lodash-es'; -import { IconType, iconSizeType } from '../../cps-icon/cps-icon.component'; +import type { + CpsIconType, + CpsIconSizeType +} from '../../cps-icon/cps-icon.component'; import { convertSize } from '../../../utils/internal/size-utils'; import { CpsTooltipPosition } from '../../../directives/cps-tooltip/cps-tooltip.directive'; import { CpsMenuComponent } from '../../cps-menu/cps-menu.component'; @@ -134,13 +137,13 @@ export class CpsBaseTreeDropdownComponent * Icon before input value. * @group Props */ - @Input() prefixIcon: IconType = ''; + @Input() prefixIcon: CpsIconType = ''; /** * Size of icon before input value, of type number, string, 'fill', 'xsmall', 'small', 'normal' or 'large'. * @group Props */ - @Input() prefixIconSize: iconSizeType = '1.125rem'; + @Input() prefixIconSize: CpsIconSizeType = '1.125rem'; /** * When enabled, a loading bar is displayed. diff --git a/projects/cps-ui-kit/src/lib/services/cps-dialog/cps-dialog.service.spec.ts b/projects/cps-ui-kit/src/lib/services/cps-dialog/cps-dialog.service.spec.ts index eb4ea17c..6fba2a09 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-dialog/cps-dialog.service.spec.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-dialog/cps-dialog.service.spec.ts @@ -203,9 +203,9 @@ describe('CpsDialogService', () => { it('should not override headerIcon when already set', () => { const config = new CpsDialogConfig(); - config.headerIcon = 'info'; + config.headerIcon = 'info-circle'; service.openConfirmationDialog(config); - expect(config.headerIcon).toBe('info'); + expect(config.headerIcon).toBe('info-circle'); }); it('should set default headerIconColor to "calm"', () => { diff --git a/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-config.ts b/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-config.ts index 3640c6e9..7b89ffef 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-config.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-config.ts @@ -1,4 +1,5 @@ -import { CpsTooltipPosition } from '../../../directives/cps-tooltip/cps-tooltip.directive'; +import type { CpsTooltipPosition } from '../../../directives/cps-tooltip/cps-tooltip.directive'; +import type { CpsIconType } from '../../../components/cps-icon/cps-icon.component'; /** * Defines the auto-focus target when the dialog opens. @@ -36,7 +37,7 @@ export class CpsDialogConfig { /** * Header icon. */ - headerIcon?: string; + headerIcon?: CpsIconType; /** * Header icon color. */ diff --git a/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-ref.ts b/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-ref.ts index 6569a3f6..19afa8ac 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-ref.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-dialog/utils/cps-dialog-ref.ts @@ -1,5 +1,5 @@ import { Observable, Subject, take } from 'rxjs'; -import { CpsDialogComponent } from '../internal/components/cps-dialog/cps-dialog.component'; +import type { CpsDialogComponent } from '../internal/components/cps-dialog/cps-dialog.component'; /** * Reference to an opened dialog, returned by CpsDialogService.open() and CpsDialogService.openConfirmationDialog(). diff --git a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.html b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.html index effeee5c..9228a845 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.html +++ b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.html @@ -21,7 +21,7 @@ class="cps-toast-content"> diff --git a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.spec.ts b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.spec.ts index 4a59163b..f8ebe881 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.spec.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.spec.ts @@ -139,6 +139,31 @@ describe('CpsToastComponent', () => { expect(component.color).toBe(CpsNotificationType.ERROR); }); + it('should set icon to "toast-info" for INFO type', () => { + setup(defaultConfig, { type: CpsNotificationType.INFO }); + expect(component.icon).toBe('toast-info'); + }); + + it('should set icon to "toast-success" for SUCCESS type', () => { + setup(defaultConfig, { type: CpsNotificationType.SUCCESS }); + expect(component.icon).toBe('toast-success'); + }); + + it('should set icon to "toast-warning" for WARNING type', () => { + setup(defaultConfig, { type: CpsNotificationType.WARNING }); + expect(component.icon).toBe('toast-warning'); + }); + + it('should set icon to "toast-error" for ERROR type', () => { + setup(defaultConfig, { type: CpsNotificationType.ERROR }); + expect(component.icon).toBe('toast-error'); + }); + + it('should default icon to "toast-error" when data has no type', () => { + setup(defaultConfig, {}); + expect(component.icon).toBe('toast-error'); + }); + it('should set maxWidth when config.maxWidth is provided', () => { setup({ ...defaultConfig, maxWidth: '400px' }); expect(component.maxWidth).toBeTruthy(); diff --git a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.ts b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.ts index 02f84eb5..39231ff2 100644 --- a/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.ts +++ b/projects/cps-ui-kit/src/lib/services/cps-notification/internal/components/cps-toast/cps-toast.component.ts @@ -2,6 +2,7 @@ import { AfterViewInit, Component, EventEmitter, + inject, Input, NgZone, OnDestroy, @@ -9,7 +10,10 @@ import { Output } from '@angular/core'; import { CpsButtonComponent } from '../../../../../components/cps-button/cps-button.component'; -import { CpsIconComponent } from '../../../../../components/cps-icon/cps-icon.component'; +import { + CpsIconComponent, + type CpsIconType +} from '../../../../../components/cps-icon/cps-icon.component'; import { CommonModule } from '@angular/common'; import { convertSize } from '../../../../../utils/internal/size-utils'; import { @@ -82,22 +86,25 @@ export class CpsToastComponent implements OnInit, AfterViewInit, OnDestroy { */ @Output() closed = new EventEmitter(); - timeout: any; + timeout: ReturnType | null = null; maxWidth: string | undefined; filled = true; color = ''; + icon: CpsIconType = 'toast-error'; srAnnouncement = ''; + private _ngZone = inject(NgZone); + get isPolite(): boolean { - if (this.data?.type === CpsNotificationType.ERROR) - return !!this.config?.politeError; - if (this.data?.type === CpsNotificationType.WARNING) - return !!this.config?.politeWarning; + if (this.data.type === CpsNotificationType.ERROR) + return !!this.config.politeError; + if (this.data.type === CpsNotificationType.WARNING) + return !!this.config.politeWarning; return true; } get closeAriaLabel(): string { - const type = this.data?.type; + const type = this.data.type; return `Close ${type ? type + ' ' : ''}notification`; } @@ -109,24 +116,29 @@ export class CpsToastComponent implements OnInit, AfterViewInit, OnDestroy { return prefersReducedMotion() ? REDUCED_MOTION_DURATION : '200ms ease-in'; } - // eslint-disable-next-line no-useless-constructor - constructor(private zone: NgZone) {} - ngOnInit(): void { - this.maxWidth = convertSize(this.config?.maxWidth || ''); - this.filled = this.config?.appearance === CpsNotificationAppearance.FILLED; + this.maxWidth = convertSize(this.config.maxWidth || ''); + this.filled = this.config.appearance === CpsNotificationAppearance.FILLED; this.color = - this.data?.type === CpsNotificationType.WARNING + this.data.type === CpsNotificationType.WARNING ? 'warn' - : this.data?.type || CpsNotificationType.ERROR; + : this.data.type || CpsNotificationType.ERROR; + this.icon = ( + { + [CpsNotificationType.ERROR]: 'toast-error', + [CpsNotificationType.WARNING]: 'toast-warning', + [CpsNotificationType.INFO]: 'toast-info', + [CpsNotificationType.SUCCESS]: 'toast-success' + } as const + )[this.data.type ?? CpsNotificationType.ERROR]; } ngAfterViewInit(): void { this.initiateTimeout(); setTimeout(() => { - const type = this.data?.type; - const details = this.data?.details; - this.srAnnouncement = `${type ? type + ': ' : ''}${this.data?.message ?? ''}${details ? '. ' + details : ''}`; + const type = this.data.type; + const details = this.data.details; + this.srAnnouncement = `${type ? type + ': ' : ''}${this.data.message ?? ''}${details ? '. ' + details : ''}`; }); } @@ -140,11 +152,11 @@ export class CpsToastComponent implements OnInit, AfterViewInit, OnDestroy { } initiateTimeout() { - if (this.config?.timeout === 0) return; - this.zone.runOutsideAngular(() => { + if (this.config.timeout === 0) return; + this._ngZone.runOutsideAngular(() => { this.timeout = setTimeout(() => { this.close(); - }, this.config?.timeout || 5000); + }, this.config.timeout || 5000); }); }