From 4bff8a28239a504014e848910e8520b761e73c6e Mon Sep 17 00:00:00 2001
From: taiga-family-bot <140712314+taiga-family-bot@users.noreply.github.com>
Date: Mon, 3 Jun 2024 23:33:23 +0300
Subject: [PATCH 1/7] chore(deps): update taiga-ui (#7612)
---
package-lock.json | 29 +++++++++++++++--------------
package.json | 4 ++--
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index c2dde3eee18f..47d2ad26e2d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,8 +30,8 @@
"@schematics/angular": "16.2.12",
"@taiga-ui/browserslist-config": "0.6.0",
"@taiga-ui/commitlint-config": "0.7.5",
- "@taiga-ui/cspell-config": "0.40.0",
- "@taiga-ui/eslint-plugin-experience": "0.75.3",
+ "@taiga-ui/cspell-config": "0.40.1",
+ "@taiga-ui/eslint-plugin-experience": "0.75.4",
"@taiga-ui/prettier-config": "0.11.9",
"@taiga-ui/stylelint-config": "0.22.3",
"@taiga-ui/tsconfig": "0.17.0",
@@ -9054,16 +9054,17 @@
"link": true
},
"node_modules/@taiga-ui/cspell-config": {
- "version": "0.40.0",
- "resolved": "https://registry.npmjs.org/@taiga-ui/cspell-config/-/cspell-config-0.40.0.tgz",
- "integrity": "sha512-mNcKBiNRJtFsIJId24gF4b7Dwa65p/YKEgQOItCzrRxILGsd6zJ6FlLwyhBVxinC/W+OdQFxFaWFFW3jQGwmAg==",
+ "version": "0.40.1",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/cspell-config/-/cspell-config-0.40.1.tgz",
+ "integrity": "sha512-uy8KmM+k/Z7QAuGx2LdQUsSNw4x0Ac7ovXCtNfxO79fEjQG6RE7jHuoBbhPSneRJbX6iJjsPejWiOeZNsOFkTA==",
"dev": true,
+ "license": "Apache-2.0",
"peerDependencies": {
"@cspell/dict-ar": "^1.1.0",
"@cspell/dict-lorem-ipsum": "^4.0.0",
"@cspell/dict-ru_ru": "^2.2.1",
"@cspell/dict-scientific-terms-us": "^3.0.1",
- "cspell": "^8.8.3"
+ "cspell": "^8.8.4"
}
},
"node_modules/@taiga-ui/demo": {
@@ -9088,9 +9089,9 @@
}
},
"node_modules/@taiga-ui/eslint-plugin-experience": {
- "version": "0.75.3",
- "resolved": "https://registry.npmjs.org/@taiga-ui/eslint-plugin-experience/-/eslint-plugin-experience-0.75.3.tgz",
- "integrity": "sha512-yPaFhbIYNnEpoMIOpb3EyRPv7L1z+QICczltYmxKcuqpFUALlKEAf8KGuWqMnRlhKupRL0lCwNb/f2TfcPRvOA==",
+ "version": "0.75.4",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/eslint-plugin-experience/-/eslint-plugin-experience-0.75.4.tgz",
+ "integrity": "sha512-4ntWlhSP2H300G2PyusBT1cGn36+uE6VY2owWPNAWTHT0tei/9NZowyzyFKg11ltMXOZLJ3vpX6zP1I0UWJRog==",
"dev": true,
"peerDependencies": {
"@angular-eslint/eslint-plugin": "^18.0.1",
@@ -9098,11 +9099,11 @@
"@angular-eslint/template-parser": "^18.0.1",
"@babel/eslint-parser": "^7.24.6",
"@babel/eslint-plugin": "^7.24.6",
- "@typescript-eslint/eslint-plugin": "^7.11.0",
- "@typescript-eslint/parser": "^7.11.0",
- "@typescript-eslint/types": "^7.11.0",
- "@typescript-eslint/typescript-estree": "^7.11.0",
- "@typescript-eslint/utils": "^7.11.0",
+ "@typescript-eslint/eslint-plugin": "^7.12.0",
+ "@typescript-eslint/parser": "^7.12.0",
+ "@typescript-eslint/types": "^7.12.0",
+ "@typescript-eslint/typescript-estree": "^7.12.0",
+ "@typescript-eslint/utils": "^7.12.0",
"babel-plugin-macros": "^3.1.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
diff --git a/package.json b/package.json
index f67ca9afed90..a641f4ceae22 100644
--- a/package.json
+++ b/package.json
@@ -118,8 +118,8 @@
"@schematics/angular": "16.2.12",
"@taiga-ui/browserslist-config": "0.6.0",
"@taiga-ui/commitlint-config": "0.7.5",
- "@taiga-ui/cspell-config": "0.40.0",
- "@taiga-ui/eslint-plugin-experience": "0.75.3",
+ "@taiga-ui/cspell-config": "0.40.1",
+ "@taiga-ui/eslint-plugin-experience": "0.75.4",
"@taiga-ui/prettier-config": "0.11.9",
"@taiga-ui/stylelint-config": "0.22.3",
"@taiga-ui/tsconfig": "0.17.0",
From bf37dc358beddea4927c01d597c35cb5cebe6861 Mon Sep 17 00:00:00 2001
From: taiga-family-bot <140712314+taiga-family-bot@users.noreply.github.com>
Date: Tue, 4 Jun 2024 04:02:47 +0300
Subject: [PATCH 2/7] chore(deps): update dependency @types/node to v20.14.1
(#7613)
---
package-lock.json | 9 +++++----
package.json | 2 +-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 47d2ad26e2d4..979f8983625a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -38,7 +38,7 @@
"@tinkoff/ng-event-plugins": "3.2.0",
"@types/glob": "8.1.0",
"@types/loader-utils": "2.0.6",
- "@types/node": "20.14.0",
+ "@types/node": "20.14.1",
"@types/webpack-env": "1.18.5",
"cpy-cli": "5.0.0",
"glob": "10.4.1",
@@ -9648,9 +9648,10 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.14.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.0.tgz",
- "integrity": "sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA==",
+ "version": "20.14.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.1.tgz",
+ "integrity": "sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA==",
+ "license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
diff --git a/package.json b/package.json
index a641f4ceae22..ff8d27452184 100644
--- a/package.json
+++ b/package.json
@@ -126,7 +126,7 @@
"@tinkoff/ng-event-plugins": "3.2.0",
"@types/glob": "8.1.0",
"@types/loader-utils": "2.0.6",
- "@types/node": "20.14.0",
+ "@types/node": "20.14.1",
"@types/webpack-env": "1.18.5",
"cpy-cli": "5.0.0",
"glob": "10.4.1",
From 850f6a06ab253fe24aef8b61936992115b65892b Mon Sep 17 00:00:00 2001
From: Nikita Barsukov
Date: Tue, 4 Jun 2024 12:10:03 +0300
Subject: [PATCH 3/7] chore: include inputs/outputs of host directive
`ActiveZone` in `DropdownOpen`'s API (#7615)
---
.../core/directives/dropdown/dropdown-open.directive.ts | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/projects/core/directives/dropdown/dropdown-open.directive.ts b/projects/core/directives/dropdown/dropdown-open.directive.ts
index a15b0be2a2c6..2da21c1c789b 100644
--- a/projects/core/directives/dropdown/dropdown-open.directive.ts
+++ b/projects/core/directives/dropdown/dropdown-open.directive.ts
@@ -49,7 +49,14 @@ function shouldClose(
@Directive({
standalone: true,
selector: '[tuiDropdownOpen],[tuiDropdownOpenChange]',
- hostDirectives: [TuiObscuredDirective, TuiActiveZoneDirective],
+ hostDirectives: [
+ TuiObscuredDirective,
+ {
+ directive: TuiActiveZoneDirective,
+ inputs: ['tuiActiveZoneParent'],
+ outputs: ['tuiActiveZoneChange'],
+ },
+ ],
providers: [
TuiDropdownDriver,
tuiAsDriver(TuiDropdownDriver),
From ccaf5a648a2679f4b4b95c146838f61fdbda3293 Mon Sep 17 00:00:00 2001
From: Alex Inkin
Date: Tue, 4 Jun 2024 17:10:48 +0800
Subject: [PATCH 4/7] refactor(addon-commerce): `InputCard` migrate to new
textfield (#7581)
Signed-off-by: waterplea
Co-authored-by: taiga-family-bot
---
.../abstract-input-card.ts | 5 +-
.../components/input-card-grouped/index.ts | 1 +
.../input-card-grouped.component.ts | 2 +-
.../test/input-card-grouped.component.spec.ts | 8 +-
.../components/input-card/index.ts | 3 +-
.../input-card/input-card.component.ts | 135 ---
.../input-card/input-card.directive.ts | 75 ++
.../input-card/input-card.options.ts | 4 +-
.../input-card/input-card.style.less | 19 -
.../input-card/input-card.template.html | 28 -
.../test/input-card.component.spec.ts | 231 -----
.../components/input-cvc/index.ts | 2 +-
.../input-cvc/input-cvc.component.ts | 102 --
.../input-cvc/input-cvc.directive.ts | 43 +
.../components/input-cvc/input-cvc.style.less | 15 -
.../input-cvc/input-cvc.template.html | 24 -
.../test/input-cvc.component.spec.ts | 74 --
.../components/input-expire/index.ts | 2 +-
.../input-expire/input-expire.component.ts | 77 --
.../input-expire/input-expire.directive.ts | 33 +
.../input-expire/input-expire.style.less | 13 -
.../input-expire/input-expire.template.html | 23 -
.../test/input-expire.component.spec.ts | 46 -
.../thumbnail-card.component.ts | 1 -
.../utils/payment-system-icons.ts | 6 +-
projects/cdk/constants/used-icons.ts | 6 +-
.../steps/constants/identifiers-to-replace.ts | 6 +-
.../textfield/textfield.component.ts | 9 +-
.../components/textfield/textfield.module.ts | 2 +-
.../components/textfield/textfield.style.less | 2 +
.../styles/theme/appearance/textfield.less | 2 +-
.../tests/addon-commerce/input-expire.spec.ts | 8 +-
.../utils/page-objects/input-card.po.ts | 9 +-
.../components/cell/examples/3/index.ts | 3 +-
.../input-card/examples/1/index.html | 60 +-
.../input-card/examples/1/index.less | 14 +
.../components/input-card/examples/1/index.ts | 45 +-
.../input-card/examples/2/index.html | 16 +
.../components/input-card/examples/2/index.ts | 26 +
.../input-card/examples/import/import.md | 8 +-
.../input-card/examples/import/template.md | 27 +-
.../modules/components/input-card/index.html | 204 +---
.../modules/components/input-card/index.less | 23 -
.../modules/components/input-card/index.ts | 128 +--
.../components/input/examples/4/index.html | 16 +-
.../components/input/examples/4/index.ts | 16 +-
.../components/label/examples/4/index.ts | 4 +-
.../components/textfield/examples/1/index.ts | 4 +-
.../components/textfield/examples/2/index.ts | 4 +-
.../components/textfield/examples/3/index.ts | 4 +-
.../textfield/examples/import/import.md | 4 +-
projects/demo/used-icons.ts | 2 +-
projects/icons/all.ts | 62 +-
projects/icons/src/tuiIconAmexOutline.svg | 11 +
.../icons/src/tuiIconDinersClubOutline.svg | 15 +
projects/icons/src/tuiIconDiscoverOutline.svg | 14 +
.../icons/src/tuiIconElectronMonoOutline.svg | 72 +-
projects/icons/src/tuiIconElectronOutline.svg | 23 +
projects/icons/src/tuiIconHumoOutline.svg | 955 ++++++++++++++++++
projects/icons/src/tuiIconJCBOutline.svg | 20 +
projects/icons/src/tuiIconMaestroOutline.svg | 16 +
.../icons/src/tuiIconMastercardOutline.svg | 19 +
projects/icons/src/tuiIconMirMonoOutline.svg | 32 +-
projects/icons/src/tuiIconMirOutline.svg | 26 +
projects/icons/src/tuiIconRuPayOutline.svg | 38 +
projects/icons/src/tuiIconUnionPayOutline.svg | 24 +
projects/icons/src/tuiIconUzcardOutline.svg | 29 +
projects/icons/src/tuiIconVerveOutline.svg | 24 +
projects/icons/src/tuiIconVisaMonoOutline.svg | 34 +-
projects/icons/src/tuiIconVisaOutline.svg | 7 +
70 files changed, 1706 insertions(+), 1339 deletions(-)
rename projects/addon-commerce/components/{input-card => input-card-grouped}/abstract-input-card.ts (93%)
delete mode 100644 projects/addon-commerce/components/input-card/input-card.component.ts
create mode 100644 projects/addon-commerce/components/input-card/input-card.directive.ts
delete mode 100644 projects/addon-commerce/components/input-card/input-card.style.less
delete mode 100644 projects/addon-commerce/components/input-card/input-card.template.html
delete mode 100644 projects/addon-commerce/components/input-card/test/input-card.component.spec.ts
delete mode 100644 projects/addon-commerce/components/input-cvc/input-cvc.component.ts
create mode 100644 projects/addon-commerce/components/input-cvc/input-cvc.directive.ts
delete mode 100644 projects/addon-commerce/components/input-cvc/input-cvc.style.less
delete mode 100644 projects/addon-commerce/components/input-cvc/input-cvc.template.html
delete mode 100644 projects/addon-commerce/components/input-cvc/test/input-cvc.component.spec.ts
delete mode 100644 projects/addon-commerce/components/input-expire/input-expire.component.ts
create mode 100644 projects/addon-commerce/components/input-expire/input-expire.directive.ts
delete mode 100644 projects/addon-commerce/components/input-expire/input-expire.style.less
delete mode 100644 projects/addon-commerce/components/input-expire/input-expire.template.html
delete mode 100644 projects/addon-commerce/components/input-expire/test/input-expire.component.spec.ts
create mode 100644 projects/demo/src/modules/components/input-card/examples/1/index.less
create mode 100644 projects/demo/src/modules/components/input-card/examples/2/index.html
create mode 100644 projects/demo/src/modules/components/input-card/examples/2/index.ts
delete mode 100644 projects/demo/src/modules/components/input-card/index.less
create mode 100644 projects/icons/src/tuiIconAmexOutline.svg
create mode 100644 projects/icons/src/tuiIconDinersClubOutline.svg
create mode 100644 projects/icons/src/tuiIconDiscoverOutline.svg
create mode 100644 projects/icons/src/tuiIconElectronOutline.svg
create mode 100644 projects/icons/src/tuiIconHumoOutline.svg
create mode 100644 projects/icons/src/tuiIconJCBOutline.svg
create mode 100644 projects/icons/src/tuiIconMaestroOutline.svg
create mode 100644 projects/icons/src/tuiIconMastercardOutline.svg
create mode 100644 projects/icons/src/tuiIconMirOutline.svg
create mode 100644 projects/icons/src/tuiIconRuPayOutline.svg
create mode 100644 projects/icons/src/tuiIconUnionPayOutline.svg
create mode 100644 projects/icons/src/tuiIconUzcardOutline.svg
create mode 100644 projects/icons/src/tuiIconVerveOutline.svg
create mode 100644 projects/icons/src/tuiIconVisaOutline.svg
diff --git a/projects/addon-commerce/components/input-card/abstract-input-card.ts b/projects/addon-commerce/components/input-card-grouped/abstract-input-card.ts
similarity index 93%
rename from projects/addon-commerce/components/input-card/abstract-input-card.ts
rename to projects/addon-commerce/components/input-card-grouped/abstract-input-card.ts
index 43d9dfafff09..1744c30b2f20 100644
--- a/projects/addon-commerce/components/input-card/abstract-input-card.ts
+++ b/projects/addon-commerce/components/input-card-grouped/abstract-input-card.ts
@@ -1,12 +1,11 @@
import {Directive, EventEmitter, inject, Input, Output} from '@angular/core';
+import type {TuiInputCardOptions} from '@taiga-ui/addon-commerce/components/input-card';
import type {TuiPaymentSystem} from '@taiga-ui/addon-commerce/types';
import {TUI_PAYMENT_SYSTEM_ICONS} from '@taiga-ui/addon-commerce/utils';
import type {TuiFocusableElementAccessor, TuiNativeFocusableElement} from '@taiga-ui/cdk';
import {AbstractTuiNullableControl, tuiPure} from '@taiga-ui/cdk';
import type {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
-import type {TuiInputCardOptions} from './input-card.options';
-
@Directive()
export abstract class AbstractTuiInputCard<
T,
@@ -23,7 +22,7 @@ export abstract class AbstractTuiInputCard<
public cardSrc: PolymorpheusContent;
@Input()
- public autocompleteEnabled = this.options.autocompleteEnabled;
+ public autocompleteEnabled = this.options.autocomplete;
@Output()
public readonly binChange = new EventEmitter();
diff --git a/projects/addon-commerce/components/input-card-grouped/index.ts b/projects/addon-commerce/components/input-card-grouped/index.ts
index f6f45ce8efee..f633d64886bd 100644
--- a/projects/addon-commerce/components/input-card-grouped/index.ts
+++ b/projects/addon-commerce/components/input-card-grouped/index.ts
@@ -1,3 +1,4 @@
+export * from './abstract-input-card';
export * from './input-card-grouped.component';
export * from './input-card-grouped.options';
export * from './input-card-grouped.providers';
diff --git a/projects/addon-commerce/components/input-card-grouped/input-card-grouped.component.ts b/projects/addon-commerce/components/input-card-grouped/input-card-grouped.component.ts
index d0911fd87e73..49b9fb09400b 100644
--- a/projects/addon-commerce/components/input-card-grouped/input-card-grouped.component.ts
+++ b/projects/addon-commerce/components/input-card-grouped/input-card-grouped.component.ts
@@ -17,7 +17,6 @@ import {MaskitoDirective} from '@maskito/angular';
import type {MaskitoOptions} from '@maskito/core';
import {maskitoDateOptionsGenerator} from '@maskito/kit';
import {ResizeObserverModule} from '@ng-web-apis/resize-observer';
-import {AbstractTuiInputCard} from '@taiga-ui/addon-commerce/components/input-card';
import {TUI_CARD_MASK} from '@taiga-ui/addon-commerce/constants';
import {TuiFormatCardPipe} from '@taiga-ui/addon-commerce/pipes';
import type {TuiCard, TuiCodeCVCLength} from '@taiga-ui/addon-commerce/types';
@@ -56,6 +55,7 @@ import {TuiChevronDirective} from '@taiga-ui/kit';
import type {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus';
+import {AbstractTuiInputCard} from './abstract-input-card';
import type {TuiInputCardGroupedOptions} from './input-card-grouped.options';
import {TUI_INPUT_CARD_GROUPED_OPTIONS} from './input-card-grouped.options';
import {TUI_INPUT_CARD_GROUPED_TEXTS} from './input-card-grouped.providers';
diff --git a/projects/addon-commerce/components/input-card-grouped/test/input-card-grouped.component.spec.ts b/projects/addon-commerce/components/input-card-grouped/test/input-card-grouped.component.spec.ts
index c3bcef157784..2a1484698618 100644
--- a/projects/addon-commerce/components/input-card-grouped/test/input-card-grouped.component.spec.ts
+++ b/projects/addon-commerce/components/input-card-grouped/test/input-card-grouped.component.spec.ts
@@ -206,8 +206,8 @@ describe('InputCardGrouped', () => {
it('input-card-grouped have a default icon', () => {
expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.defaultIcon).toBe('tuiIconVisaMono');
- expect(testComponent.component.icon).toBe('tuiIconVisaMono');
+ expect(testComponent.component.defaultIcon).toBe('tuiIconVisa');
+ expect(testComponent.component.icon).toBe('tuiIconVisa');
expect(testComponent.control.value).toEqual({card: '4111 1111 1111 1111'});
expect(expectCardOutlet()).toBeFalsy();
@@ -219,7 +219,7 @@ describe('InputCardGrouped', () => {
testComponent.component.cardSrc = 'tuiIconMastercard';
expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.defaultIcon).toBe('tuiIconVisaMono');
+ expect(testComponent.component.defaultIcon).toBe('tuiIconVisa');
expect(testComponent.component.icon).toBe('tuiIconMastercard');
expect(testComponent.control.value).toEqual({card: '4111 1111 1111 1111'});
@@ -233,7 +233,7 @@ describe('InputCardGrouped', () => {
fixture.componentInstance.customIconTemplate;
expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.defaultIcon).toBe('tuiIconVisaMono');
+ expect(testComponent.component.defaultIcon).toBe('tuiIconVisa');
expect(testComponent.component.icon).toBeInstanceOf(TemplateRef);
expect(testComponent.control.value).toEqual({card: '4111 1111 1111 1111'});
diff --git a/projects/addon-commerce/components/input-card/index.ts b/projects/addon-commerce/components/input-card/index.ts
index 26d1774d17e1..8eb9ce2646d3 100644
--- a/projects/addon-commerce/components/input-card/index.ts
+++ b/projects/addon-commerce/components/input-card/index.ts
@@ -1,3 +1,2 @@
-export * from './abstract-input-card';
-export * from './input-card.component';
+export * from './input-card.directive';
export * from './input-card.options';
diff --git a/projects/addon-commerce/components/input-card/input-card.component.ts b/projects/addon-commerce/components/input-card/input-card.component.ts
deleted file mode 100644
index ebe14a686809..000000000000
--- a/projects/addon-commerce/components/input-card/input-card.component.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import type {AfterViewInit} from '@angular/core';
-import {
- ChangeDetectionStrategy,
- Component,
- HostBinding,
- inject,
- ViewChild,
-} from '@angular/core';
-import {MaskitoDirective, MaskitoPipe} from '@maskito/angular';
-import type {MaskitoOptions} from '@maskito/core';
-import {TUI_CARD_MASK} from '@taiga-ui/addon-commerce/constants';
-import {tuiAsControl, tuiAsFocusableItemAccessor} from '@taiga-ui/cdk';
-import type {TuiSizeL, TuiSizeS, TuiTextfieldHost} from '@taiga-ui/core';
-import {
- TUI_TEXTFIELD_SIZE,
- tuiAsTextfieldHost,
- TuiPrimitiveTextfieldComponent,
- TuiPrimitiveTextfieldModule,
- TuiSvgComponent,
- TuiTextfieldControllerModule,
-} from '@taiga-ui/core';
-
-import {AbstractTuiInputCard} from './abstract-input-card';
-import {TUI_INPUT_CARD_OPTIONS} from './input-card.options';
-
-@Component({
- standalone: true,
- selector: 'tui-input-card',
- imports: [
- TuiPrimitiveTextfieldModule,
- TuiTextfieldControllerModule,
- MaskitoDirective,
- MaskitoPipe,
- TuiSvgComponent,
- ],
- templateUrl: './input-card.template.html',
- styleUrls: ['./input-card.style.less'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- providers: [
- tuiAsFocusableItemAccessor(TuiInputCardComponent),
- tuiAsControl(TuiInputCardComponent),
- tuiAsTextfieldHost(TuiInputCardComponent),
- ],
-})
-export class TuiInputCardComponent
- extends AbstractTuiInputCard
- implements AfterViewInit, TuiTextfieldHost
-{
- @ViewChild(TuiPrimitiveTextfieldComponent)
- private readonly input?: TuiPrimitiveTextfieldComponent;
-
- private readonly textfieldSize = inject(TUI_TEXTFIELD_SIZE);
-
- protected readonly maskOptions: MaskitoOptions = {
- mask: TUI_CARD_MASK,
- };
-
- constructor() {
- super(inject(TUI_INPUT_CARD_OPTIONS));
- }
-
- public get card(): string {
- return this.value ?? '';
- }
-
- public get nativeFocusableElement(): HTMLInputElement | null {
- return this.input?.nativeFocusableElement ?? null;
- }
-
- public get focused(): boolean {
- return !!this.input && this.input.focused;
- }
-
- public get inputMode(): TuiTextfieldHost['inputMode'] {
- return 'text';
- }
-
- public override get value(): string {
- return super.value ?? '';
- }
-
- public override set value(value: string | null) {
- super.value = value ?? '';
- }
-
- public process(_input: HTMLInputElement): void {}
-
- public onValueChange(value: string): void {
- const parsed = value.split(' ').join('');
- const currentBin = this.bin;
-
- this.value = parsed;
-
- const newBin = this.bin;
-
- if (currentBin !== newBin) {
- this.binChange.emit(newBin);
- }
- }
-
- public onFocused(focused: boolean): void {
- this.updateFocused(focused);
- }
-
- public ngAfterViewInit(): void {
- if (!this.nativeFocusableElement) {
- return;
- }
-
- this.nativeFocusableElement.inputMode = 'numeric';
- this.nativeFocusableElement.placeholder =
- this.nativeFocusableElement.placeholder || '0000 0000 0000 0000';
- }
-
- public override writeValue(value: string | null): void {
- const currentBin = this.bin;
-
- super.writeValue(value);
-
- const newBin = this.bin;
-
- if (currentBin !== newBin) {
- this.binChange.emit(newBin);
- }
- }
-
- @HostBinding('attr.data-size')
- protected get size(): TuiSizeL | TuiSizeS {
- return this.textfieldSize.size;
- }
-
- protected override getFallbackValue(): string {
- return '';
- }
-}
diff --git a/projects/addon-commerce/components/input-card/input-card.directive.ts b/projects/addon-commerce/components/input-card/input-card.directive.ts
new file mode 100644
index 000000000000..527cfda84823
--- /dev/null
+++ b/projects/addon-commerce/components/input-card/input-card.directive.ts
@@ -0,0 +1,75 @@
+import type {OnInit} from '@angular/core';
+import {Directive, inject, Input, Output} from '@angular/core';
+import {DefaultValueAccessor, NgControl} from '@angular/forms';
+import {MaskitoDirective} from '@maskito/angular';
+import {TUI_CARD_MASK} from '@taiga-ui/addon-commerce/constants';
+import type {TuiPaymentSystem} from '@taiga-ui/addon-commerce/types';
+import {TUI_PAYMENT_SYSTEM_ICONS} from '@taiga-ui/addon-commerce/utils';
+import {tuiControlValue, tuiPure} from '@taiga-ui/cdk';
+import {TUI_ICON_RESOLVER} from '@taiga-ui/core';
+import {distinctUntilChanged, map, skip, startWith, switchMap, timer} from 'rxjs';
+
+import {TUI_INPUT_CARD_OPTIONS} from './input-card.options';
+
+@Directive({
+ standalone: true,
+ selector: 'input[tuiInputCard]',
+ host: {
+ inputmode: 'numeric',
+ placeholder: '0000 0000 0000 0000',
+ '[autocomplete]': 'autocomplete ? "cc-number" : "off"',
+ '[style.background-image]': 'backgroundImage',
+ },
+ hostDirectives: [MaskitoDirective],
+})
+export class TuiInputCard implements OnInit {
+ private readonly icons = inject(TUI_PAYMENT_SYSTEM_ICONS);
+ private readonly options = inject(TUI_INPUT_CARD_OPTIONS);
+ private readonly resolver = inject(TUI_ICON_RESOLVER);
+ private readonly control = inject(NgControl);
+ private readonly mask = inject(MaskitoDirective);
+ private readonly accessor = inject(DefaultValueAccessor, {
+ self: true,
+ optional: true,
+ });
+
+ @Input()
+ public autocomplete = this.options.autocomplete;
+
+ @Input()
+ public icon: string | null = null;
+
+ @Output()
+ public readonly binChange = timer(0).pipe(
+ switchMap(() => tuiControlValue(this.control)),
+ map(value => (value.length < 6 ? null : value.replace(' ', '').slice(0, 6))),
+ startWith(null),
+ distinctUntilChanged(),
+ skip(1),
+ );
+
+ public ngOnInit(): void {
+ this.mask.options = {mask: TUI_CARD_MASK};
+ this.mask.ngOnChanges();
+
+ if (!this.accessor) {
+ return;
+ }
+
+ const onChanges = this.accessor.onChange.bind(this.accessor);
+
+ this.accessor.onChange = (value: string) => onChanges(value.replaceAll(' ', ''));
+ }
+
+ protected get backgroundImage(): string | null {
+ const system = this.getPaymentSystem(this.control.value);
+ const url = this.icon || (system && this.resolver(this.icons[system]));
+
+ return url && this.icon !== '' ? `url(${url})` : null;
+ }
+
+ @tuiPure
+ private getPaymentSystem(value: string): TuiPaymentSystem | null {
+ return this.options.paymentSystemHandler(value);
+ }
+}
diff --git a/projects/addon-commerce/components/input-card/input-card.options.ts b/projects/addon-commerce/components/input-card/input-card.options.ts
index a6d43909563a..9bd53a1610fa 100644
--- a/projects/addon-commerce/components/input-card/input-card.options.ts
+++ b/projects/addon-commerce/components/input-card/input-card.options.ts
@@ -6,7 +6,7 @@ import {tuiCreateToken, tuiProvideOptions} from '@taiga-ui/cdk';
import type {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
export interface TuiInputCardOptions {
- readonly autocompleteEnabled: boolean;
+ readonly autocomplete: boolean;
cardSrc: PolymorpheusContent;
readonly paymentSystemHandler: TuiHandler<
string | null | undefined,
@@ -17,7 +17,7 @@ export interface TuiInputCardOptions {
export const TUI_INPUT_CARD_DEFAULT_OPTIONS: TuiInputCardOptions = {
cardSrc: '',
paymentSystemHandler: tuiGetPaymentSystem,
- autocompleteEnabled: false,
+ autocomplete: false,
};
export const TUI_INPUT_CARD_OPTIONS = tuiCreateToken(TUI_INPUT_CARD_DEFAULT_OPTIONS);
diff --git a/projects/addon-commerce/components/input-card/input-card.style.less b/projects/addon-commerce/components/input-card/input-card.style.less
deleted file mode 100644
index bc699072ff3a..000000000000
--- a/projects/addon-commerce/components/input-card/input-card.style.less
+++ /dev/null
@@ -1,19 +0,0 @@
-@import '@taiga-ui/core/styles/taiga-ui-local';
-
-:host {
- display: block;
- border-radius: var(--tui-radius-m);
- text-align: left;
-}
-
-.t-input {
- border-radius: inherit;
- text-align: inherit;
-}
-
-.t-payment-system {
- width: 2rem;
- height: 2rem;
- // Visa logo color
- color: #1434cb;
-}
diff --git a/projects/addon-commerce/components/input-card/input-card.template.html b/projects/addon-commerce/components/input-card/input-card.template.html
deleted file mode 100644
index f742c29cf78f..000000000000
--- a/projects/addon-commerce/components/input-card/input-card.template.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
diff --git a/projects/addon-commerce/components/input-card/test/input-card.component.spec.ts b/projects/addon-commerce/components/input-card/test/input-card.component.spec.ts
deleted file mode 100644
index 58b9b35acb7f..000000000000
--- a/projects/addon-commerce/components/input-card/test/input-card.component.spec.ts
+++ /dev/null
@@ -1,231 +0,0 @@
-import {Component, TemplateRef, ViewChild} from '@angular/core';
-import type {ComponentFixture} from '@angular/core/testing';
-import {TestBed} from '@angular/core/testing';
-import {FormControl, ReactiveFormsModule} from '@angular/forms';
-import {TuiInputCardComponent} from '@taiga-ui/addon-commerce';
-import type {Mock} from 'jest-mock';
-
-describe('InputCard', () => {
- @Component({
- template: `
-
-
-
-
-
- `,
- })
- class TestComponent {
- @ViewChild(TuiInputCardComponent, {static: true})
- public component!: TuiInputCardComponent;
-
- @ViewChild('customIconTemplateRef', {read: TemplateRef})
- public customIconTemplateRef!: TemplateRef;
-
- public control = new FormControl('');
-
- public onBinChange: (event: string | null) => void = jest.fn();
- }
-
- let fixture: ComponentFixture;
- let testComponent: TestComponent;
-
- beforeEach(async () => {
- TestBed.configureTestingModule({
- imports: [ReactiveFormsModule, TuiInputCardComponent],
- declarations: [TestComponent],
- });
- await TestBed.compileComponents();
- fixture = TestBed.createComponent(TestComponent);
- testComponent = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- describe('focusable', () => {
- it('touched', () => {
- testComponent.component.onFocused(true);
-
- expect(testComponent.component.control?.touched).toBe(false);
-
- testComponent.component.onFocused(false);
-
- expect(testComponent.component.control?.touched).toBe(true);
- });
- });
-
- describe('binChange', () => {
- it('Less than 6 characters', () => {
- testComponent.control.setValue('12345');
-
- expect(testComponent.onBinChange).not.toHaveBeenCalled();
- });
-
- it('6 and more characters', () => {
- testComponent.control.setValue('123456789');
-
- expect(testComponent.onBinChange).toHaveBeenCalledWith('123456');
- });
-
- it('trigger onBinChange only when bin has changed', () => {
- testComponent.component.onValueChange('1234 5678 1111 2222');
-
- expect(testComponent.onBinChange).toHaveBeenCalledWith('123456');
- expect(testComponent.component.value).toBe('1234567811112222');
- expect(testComponent.component.bin).toBe('123456');
-
- testComponent.component.onValueChange('2222 4444 5555 6666');
- expect(testComponent.onBinChange).toHaveBeenCalledTimes(2);
-
- testComponent.component.onValueChange('2222 4444 5555 6666');
- expect(testComponent.onBinChange).toHaveBeenCalledTimes(2);
- });
-
- it('The value has changed, the first 6 characters are unchanged', () => {
- testComponent.control.setValue('123456789');
- (testComponent.onBinChange as Mock).mockClear();
- testComponent.control.setValue('123456987');
-
- expect(testComponent.onBinChange).not.toHaveBeenCalled();
- });
-
- it('The value has changed, the first 6 characters have changed', () => {
- testComponent.control.setValue('123456789');
- (testComponent.onBinChange as Mock).mockClear();
- testComponent.control.setValue('654321789');
-
- expect(testComponent.onBinChange).toHaveBeenCalledWith('654321');
- });
-
- it('The value has changed to less than 6 characters', () => {
- testComponent.control.setValue('123456789');
- (testComponent.onBinChange as Mock).mockClear();
- testComponent.control.setValue('123');
-
- expect(testComponent.onBinChange).toHaveBeenCalledWith(null);
- });
- });
-
- describe('paymentSystem', () => {
- it('visa', () => {
- testComponent.control.setValue('4111 1111 1111 1111');
-
- expect(testComponent.component.paymentSystem).toBe('visa');
- });
-
- it('electron', () => {
- testComponent.control.setValue('4917300800000000');
-
- expect(testComponent.component.paymentSystem).toBe('electron');
- });
-
- it('mir', () => {
- testComponent.control.setValue('2200654321000000');
-
- expect(testComponent.component.paymentSystem).toBe('mir');
- });
-
- it('mastercard', () => {
- testComponent.control.setValue('5500 0000 0000 0004');
-
- expect(testComponent.component.paymentSystem).toBe('mastercard');
- });
-
- it('maestro', () => {
- testComponent.control.setValue('6759649826438453');
-
- expect(testComponent.component.paymentSystem).toBe('maestro');
- });
- });
-
- describe('Formatting', () => {
- it('4', async () => {
- await testFormat('1234', '1234');
- });
-
- it('7', async () => {
- await testFormat('1234567', '1234 567');
- });
-
- it('10', async () => {
- await testFormat('1234567890', '1234 5678 90');
- });
-
- it('12', async () => {
- await testFormat('123456789012', '1234 5678 9012');
- });
-
- it('13', async () => {
- await testFormat('4000000000000', '4000 0000 0000 0');
- });
-
- it('14', async () => {
- await testFormat('40000000000000', '4000 0000 0000 00');
- });
-
- it('15', async () => {
- await testFormat('400000000000000', '4000 0000 0000 000');
- });
-
- it('16', async () => {
- await testFormat('4000000000000000', '4000 0000 0000 0000');
- });
-
- it('17', async () => {
- await testFormat('40000000000000000', '4000 0000 0000 0000 0');
- });
-
- it('18', async () => {
- await testFormat('400000000000000000', '4000 0000 0000 0000 00');
- });
-
- it('19', async () => {
- await testFormat('4000000000000000000', '4000 0000 0000 0000 000');
- });
- });
-
- describe('customIconSource', () => {
- beforeEach(() => testComponent.control.setValue('4111 1111 1111 1111'));
-
- it('input-card component has a default icon', () => {
- expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.icon).toBe('tuiIconVisaMono');
- expect(testComponent.control.value).toBe('4111 1111 1111 1111');
- });
-
- it('input-card component has a tuiIconElectron icon', () => {
- testComponent.component.cardSrc = 'tuiIconElectron';
- expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.icon).toBe('tuiIconElectron');
- expect(testComponent.control.value).toBe('4111 1111 1111 1111');
- });
-
- it('input-card component has an icon source as TemplateRef', () => {
- testComponent.component.cardSrc =
- fixture.componentInstance.customIconTemplateRef;
- expect(testComponent.control.valid).toBe(true);
- expect(testComponent.component.icon).toBeInstanceOf(TemplateRef);
- expect(testComponent.control.value).toBe('4111 1111 1111 1111');
- });
- });
-
- async function testFormat(value: string, formatted: string): Promise {
- testComponent.control.setValue(value);
- fixture.detectChanges();
-
- await fixture.whenStable();
-
- fixture.detectChanges();
-
- await fixture.whenStable();
-
- fixture.detectChanges();
- expect(getValue()).toBe(formatted);
- }
-
- function getValue(): string {
- return testComponent.component.nativeFocusableElement?.value || '';
- }
-});
diff --git a/projects/addon-commerce/components/input-cvc/index.ts b/projects/addon-commerce/components/input-cvc/index.ts
index 9dda6b14d3f0..90fb4e1f4d63 100644
--- a/projects/addon-commerce/components/input-cvc/index.ts
+++ b/projects/addon-commerce/components/input-cvc/index.ts
@@ -1 +1 @@
-export * from './input-cvc.component';
+export * from './input-cvc.directive';
diff --git a/projects/addon-commerce/components/input-cvc/input-cvc.component.ts b/projects/addon-commerce/components/input-cvc/input-cvc.component.ts
deleted file mode 100644
index 194755f3bf40..000000000000
--- a/projects/addon-commerce/components/input-cvc/input-cvc.component.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import {
- ChangeDetectionStrategy,
- Component,
- HostBinding,
- inject,
- Input,
- ViewChild,
-} from '@angular/core';
-import {MaskitoDirective} from '@maskito/angular';
-import type {MaskitoOptions} from '@maskito/core';
-import type {TuiCodeCVCLength} from '@taiga-ui/addon-commerce/types';
-import type {TuiFocusableElementAccessor, TuiNativeFocusableElement} from '@taiga-ui/cdk';
-import {
- AbstractTuiControl,
- TUI_DIGIT_REGEXP,
- tuiAsControl,
- tuiAsFocusableItemAccessor,
-} from '@taiga-ui/cdk';
-import type {TuiSizeL, TuiSizeS} from '@taiga-ui/core';
-import {
- TUI_TEXTFIELD_LABEL_OUTSIDE,
- TUI_TEXTFIELD_SIZE,
- TuiPrimitiveTextfieldComponent,
- TuiPrimitiveTextfieldModule,
-} from '@taiga-ui/core';
-
-@Component({
- standalone: true,
- selector: 'tui-input-cvc',
- imports: [TuiPrimitiveTextfieldModule, MaskitoDirective],
- templateUrl: './input-cvc.template.html',
- styleUrls: ['./input-cvc.style.less'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- providers: [
- tuiAsFocusableItemAccessor(TuiInputCVCComponent),
- tuiAsControl(TuiInputCVCComponent),
- ],
-})
-export class TuiInputCVCComponent
- extends AbstractTuiControl
- implements TuiFocusableElementAccessor
-{
- @ViewChild(TuiPrimitiveTextfieldComponent)
- private readonly input?: TuiPrimitiveTextfieldComponent;
-
- private readonly textfieldLabelOutside = inject(TUI_TEXTFIELD_LABEL_OUTSIDE);
- private readonly textfieldSize = inject(TUI_TEXTFIELD_SIZE);
-
- @Input()
- public autocompleteEnabled = false;
-
- @Input()
- public hidden = true;
-
- public exampleText = '000';
-
- public maskOptions: MaskitoOptions = {
- mask: new Array(3).fill(TUI_DIGIT_REGEXP),
- };
-
- @Input()
- public set length(length: TuiCodeCVCLength) {
- this.exampleText = '0'.repeat(length);
- this.maskOptions = {
- mask: new Array(length).fill(TUI_DIGIT_REGEXP),
- };
- }
-
- public get nativeFocusableElement(): TuiNativeFocusableElement | null {
- return this.input?.nativeFocusableElement ?? null;
- }
-
- public get focused(): boolean {
- return !!this.input && this.input.focused;
- }
-
- @HostBinding('attr.data-size')
- protected get size(): TuiSizeL | TuiSizeS {
- return this.textfieldSize.size;
- }
-
- protected get autocomplete(): string {
- return this.autocompleteEnabled ? 'cc-csc' : 'off';
- }
-
- protected get computedPlaceholder(): string {
- return this.textfieldLabelOutside.labelOutside ? '' : this.exampleText;
- }
-
- protected onFocused(focused: boolean): void {
- this.updateFocused(focused);
- }
-
- /** deprecated use 'value' setter */
- protected onValueChange(value: string): void {
- this.value = value;
- }
-
- protected getFallbackValue(): string {
- return '';
- }
-}
diff --git a/projects/addon-commerce/components/input-cvc/input-cvc.directive.ts b/projects/addon-commerce/components/input-cvc/input-cvc.directive.ts
new file mode 100644
index 000000000000..db83d6480cea
--- /dev/null
+++ b/projects/addon-commerce/components/input-cvc/input-cvc.directive.ts
@@ -0,0 +1,43 @@
+import type {OnChanges, OnInit} from '@angular/core';
+import {Directive, inject, Input} from '@angular/core';
+import {MaskitoDirective} from '@maskito/angular';
+import {TUI_INPUT_CARD_OPTIONS} from '@taiga-ui/addon-commerce/components/input-card';
+import {TUI_DIGIT_REGEXP} from '@taiga-ui/cdk';
+
+@Directive({
+ standalone: true,
+ selector: 'input[tuiInputCVC]',
+ host: {
+ inputmode: 'numeric',
+ '[autocomplete]': 'autocomplete ? "cc-csc" : "off"',
+ '[placeholder]': '"0".repeat(length)',
+ '[style.-webkit-text-security]': 'hidden ? "disc" : null',
+ '(copy.prevent)': '(0)',
+ },
+ hostDirectives: [MaskitoDirective],
+})
+export class TuiInputCVC implements OnInit, OnChanges {
+ private readonly mask = inject(MaskitoDirective);
+
+ @Input()
+ public autocomplete = inject(TUI_INPUT_CARD_OPTIONS).autocomplete;
+
+ @Input()
+ public hidden = true;
+
+ @Input()
+ public length: 3 | 4 = 3;
+
+ public ngOnInit(): void {
+ this.refresh();
+ }
+
+ public ngOnChanges(): void {
+ this.refresh();
+ }
+
+ private refresh(): void {
+ this.mask.options = {mask: new Array(this.length).fill(TUI_DIGIT_REGEXP)};
+ this.mask.ngOnChanges();
+ }
+}
diff --git a/projects/addon-commerce/components/input-cvc/input-cvc.style.less b/projects/addon-commerce/components/input-cvc/input-cvc.style.less
deleted file mode 100644
index b4ad0a1aa6fd..000000000000
--- a/projects/addon-commerce/components/input-cvc/input-cvc.style.less
+++ /dev/null
@@ -1,15 +0,0 @@
-:host {
- display: block;
- max-width: 11rem;
- border-radius: var(--tui-radius-m);
- text-align: left;
-}
-
-.t-input {
- border-radius: inherit;
- text-align: inherit;
-
- &_hidden {
- -webkit-text-security: disc;
- }
-}
diff --git a/projects/addon-commerce/components/input-cvc/input-cvc.template.html b/projects/addon-commerce/components/input-cvc/input-cvc.template.html
deleted file mode 100644
index 48391db1729c..000000000000
--- a/projects/addon-commerce/components/input-cvc/input-cvc.template.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
diff --git a/projects/addon-commerce/components/input-cvc/test/input-cvc.component.spec.ts b/projects/addon-commerce/components/input-cvc/test/input-cvc.component.spec.ts
deleted file mode 100644
index 80c4da971500..000000000000
--- a/projects/addon-commerce/components/input-cvc/test/input-cvc.component.spec.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import {Component, ViewChild} from '@angular/core';
-import type {ComponentFixture} from '@angular/core/testing';
-import {TestBed} from '@angular/core/testing';
-import {FormControl, ReactiveFormsModule} from '@angular/forms';
-import {TuiInputCVCComponent} from '@taiga-ui/addon-commerce';
-import {TUI_DIGIT_REGEXP} from '@taiga-ui/cdk';
-
-describe('InputCVC', () => {
- @Component({
- template: `
-
-
- `,
- })
- class TestComponent {
- @ViewChild('default')
- public default!: TuiInputCVCComponent;
-
- @ViewChild('custom')
- public custom!: TuiInputCVCComponent;
-
- public control = new FormControl('');
- }
-
- let fixture: ComponentFixture;
- let testComponent: TestComponent;
-
- beforeEach(async () => {
- TestBed.configureTestingModule({
- imports: [ReactiveFormsModule, TuiInputCVCComponent],
- declarations: [TestComponent],
- });
- await TestBed.compileComponents();
- fixture = TestBed.createComponent(TestComponent);
- testComponent = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- describe('Default', () => {
- it('exampleText', () => {
- expect(testComponent.default.exampleText).toBe('000');
- });
-
- it('MaskOptions', () => {
- expect(testComponent.default.maskOptions).toEqual({
- mask: [TUI_DIGIT_REGEXP, TUI_DIGIT_REGEXP, TUI_DIGIT_REGEXP],
- });
- });
- });
-
- describe('Modified', () => {
- it('exampleText', () => {
- expect(testComponent.custom.exampleText).toBe('0000');
- });
-
- it('MaskOptions', () => {
- expect(testComponent.custom.maskOptions).toEqual({
- mask: [
- TUI_DIGIT_REGEXP,
- TUI_DIGIT_REGEXP,
- TUI_DIGIT_REGEXP,
- TUI_DIGIT_REGEXP,
- ],
- });
- });
- });
-});
diff --git a/projects/addon-commerce/components/input-expire/index.ts b/projects/addon-commerce/components/input-expire/index.ts
index 5228ec51fc73..6dd428c4e352 100644
--- a/projects/addon-commerce/components/input-expire/index.ts
+++ b/projects/addon-commerce/components/input-expire/index.ts
@@ -1 +1 @@
-export * from './input-expire.component';
+export * from './input-expire.directive';
diff --git a/projects/addon-commerce/components/input-expire/input-expire.component.ts b/projects/addon-commerce/components/input-expire/input-expire.component.ts
deleted file mode 100644
index e35c76adf4e9..000000000000
--- a/projects/addon-commerce/components/input-expire/input-expire.component.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import {
- ChangeDetectionStrategy,
- Component,
- HostBinding,
- inject,
- Input,
- ViewChild,
-} from '@angular/core';
-import {MaskitoDirective} from '@maskito/angular';
-import {maskitoDateOptionsGenerator} from '@maskito/kit';
-import type {TuiFocusableElementAccessor} from '@taiga-ui/cdk';
-import {
- AbstractTuiControl,
- tuiAsControl,
- tuiAsFocusableItemAccessor,
-} from '@taiga-ui/cdk';
-import type {TuiSizeL, TuiSizeS} from '@taiga-ui/core';
-import {
- TUI_TEXTFIELD_SIZE,
- TuiPrimitiveTextfieldComponent,
- TuiPrimitiveTextfieldModule,
-} from '@taiga-ui/core';
-
-@Component({
- standalone: true,
- selector: 'tui-input-expire',
- imports: [TuiPrimitiveTextfieldModule, MaskitoDirective],
- templateUrl: './input-expire.template.html',
- styleUrls: ['./input-expire.style.less'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- providers: [
- tuiAsFocusableItemAccessor(TuiInputExpireComponent),
- tuiAsControl(TuiInputExpireComponent),
- ],
-})
-export class TuiInputExpireComponent
- extends AbstractTuiControl
- implements TuiFocusableElementAccessor
-{
- @ViewChild(TuiPrimitiveTextfieldComponent)
- private readonly input?: TuiPrimitiveTextfieldComponent;
-
- private readonly textfieldSize = inject(TUI_TEXTFIELD_SIZE);
-
- protected readonly maskOptions = maskitoDateOptionsGenerator({
- mode: 'mm/yy',
- separator: '/',
- });
-
- @Input()
- public autocompleteEnabled = false;
-
- public get nativeFocusableElement(): HTMLInputElement | null {
- return this.input?.nativeFocusableElement ?? null;
- }
-
- public get focused(): boolean {
- return !!this.input && this.input.focused;
- }
-
- @HostBinding('attr.data-size')
- protected get size(): TuiSizeL | TuiSizeS {
- return this.textfieldSize.size;
- }
-
- protected get autocomplete(): string {
- return this.autocompleteEnabled ? 'cc-exp' : 'off';
- }
-
- protected onFocused(focused: boolean): void {
- this.updateFocused(focused);
- }
-
- protected getFallbackValue(): string {
- return '';
- }
-}
diff --git a/projects/addon-commerce/components/input-expire/input-expire.directive.ts b/projects/addon-commerce/components/input-expire/input-expire.directive.ts
new file mode 100644
index 000000000000..985f19ee70da
--- /dev/null
+++ b/projects/addon-commerce/components/input-expire/input-expire.directive.ts
@@ -0,0 +1,33 @@
+import type {OnInit} from '@angular/core';
+import {Directive, inject, Input} from '@angular/core';
+import {MaskitoDirective} from '@maskito/angular';
+import {maskitoDateOptionsGenerator} from '@maskito/kit';
+import {TUI_INPUT_CARD_OPTIONS} from '@taiga-ui/addon-commerce/components/input-card';
+
+const MASK = maskitoDateOptionsGenerator({
+ mode: 'mm/yy',
+ separator: '/',
+});
+
+@Directive({
+ standalone: true,
+ selector: 'input[tuiInputExpire]',
+ host: {
+ inputmode: 'numeric',
+ placeholder: '00/00',
+ translate: 'no',
+ '[autocomplete]': 'autocomplete ? "cc-exp" : "off"',
+ },
+ hostDirectives: [MaskitoDirective],
+})
+export class TuiInputExpire implements OnInit {
+ private readonly mask = inject(MaskitoDirective);
+
+ @Input()
+ public autocomplete = inject(TUI_INPUT_CARD_OPTIONS).autocomplete;
+
+ public ngOnInit(): void {
+ this.mask.options = MASK;
+ this.mask.ngOnChanges();
+ }
+}
diff --git a/projects/addon-commerce/components/input-expire/input-expire.style.less b/projects/addon-commerce/components/input-expire/input-expire.style.less
deleted file mode 100644
index 8133891bc40c..000000000000
--- a/projects/addon-commerce/components/input-expire/input-expire.style.less
+++ /dev/null
@@ -1,13 +0,0 @@
-@import '@taiga-ui/core/styles/taiga-ui-local';
-
-:host {
- display: block;
- max-width: 11rem;
- border-radius: var(--tui-radius-m);
- text-align: left;
-}
-
-.t-input {
- border-radius: inherit;
- text-align: inherit;
-}
diff --git a/projects/addon-commerce/components/input-expire/input-expire.template.html b/projects/addon-commerce/components/input-expire/input-expire.template.html
deleted file mode 100644
index 1d3f33f9de8f..000000000000
--- a/projects/addon-commerce/components/input-expire/input-expire.template.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
diff --git a/projects/addon-commerce/components/input-expire/test/input-expire.component.spec.ts b/projects/addon-commerce/components/input-expire/test/input-expire.component.spec.ts
deleted file mode 100644
index 6e4db593eee6..000000000000
--- a/projects/addon-commerce/components/input-expire/test/input-expire.component.spec.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import {Component, ViewChild} from '@angular/core';
-import type {ComponentFixture} from '@angular/core/testing';
-import {TestBed} from '@angular/core/testing';
-import {FormsModule} from '@angular/forms';
-import {By} from '@angular/platform-browser';
-import {TuiInputExpireComponent} from '@taiga-ui/addon-commerce';
-
-describe('InputExpire', () => {
- @Component({
- template: `
-
- `,
- })
- class TestComponent {
- @ViewChild(TuiInputExpireComponent)
- public input!: TuiInputExpireComponent;
-
- public value = '';
- }
-
- let fixture: ComponentFixture;
- let testComponent: TestComponent;
- let input: HTMLInputElement;
-
- beforeEach(async () => {
- TestBed.configureTestingModule({
- imports: [FormsModule, TuiInputExpireComponent],
- declarations: [TestComponent],
- });
- await TestBed.compileComponents();
- fixture = TestBed.createComponent(TestComponent);
- testComponent = fixture.componentInstance;
- fixture.detectChanges();
- input = fixture.debugElement.query(By.css('input')).nativeElement;
-
- await fixture.whenStable();
- });
-
- it('does not change the correct input', () => {
- input.value = '12/12';
- input.dispatchEvent(new Event('input', {bubbles: true}));
-
- expect(testComponent.value).toBe('12/12');
- expect(input.value).toBe('12/12');
- });
-});
diff --git a/projects/addon-commerce/components/thumbnail-card/thumbnail-card.component.ts b/projects/addon-commerce/components/thumbnail-card/thumbnail-card.component.ts
index 438cb587e7ba..e1ec15a8ae1c 100644
--- a/projects/addon-commerce/components/thumbnail-card/thumbnail-card.component.ts
+++ b/projects/addon-commerce/components/thumbnail-card/thumbnail-card.component.ts
@@ -37,7 +37,6 @@ export class TuiThumbnailCardComponent {
@Input()
public iconRight = '';
- // TODO: Revisit this approach in 4.0 when icons are moved away from InputCard options
protected get isMono(): boolean {
switch (this.paymentSystem) {
case 'mir':
diff --git a/projects/addon-commerce/utils/payment-system-icons.ts b/projects/addon-commerce/utils/payment-system-icons.ts
index 1b5cbcf69bac..48668a26ede1 100644
--- a/projects/addon-commerce/utils/payment-system-icons.ts
+++ b/projects/addon-commerce/utils/payment-system-icons.ts
@@ -4,9 +4,9 @@ import {tuiCreateToken} from '@taiga-ui/cdk';
export const TUI_PAYMENT_SYSTEM_ICONS: InjectionToken> =
tuiCreateToken({
- mir: 'tuiIconMirMono',
- visa: 'tuiIconVisaMono',
- electron: 'tuiIconElectronMono',
+ mir: 'tuiIconMir',
+ visa: 'tuiIconVisa',
+ electron: 'tuiIconElectron',
mastercard: 'tuiIconMastercard',
maestro: 'tuiIconMaestro',
amex: 'tuiIconAmex',
diff --git a/projects/cdk/constants/used-icons.ts b/projects/cdk/constants/used-icons.ts
index cf0726954e7a..2ed1667232a7 100644
--- a/projects/cdk/constants/used-icons.ts
+++ b/projects/cdk/constants/used-icons.ts
@@ -5,9 +5,9 @@
* Array of icons used in taiga-ui components
*/
export const TUI_USED_ICONS = [
- 'tuiIconMirMono',
- 'tuiIconVisaMono',
- 'tuiIconElectronMono',
+ 'tuiIconMir',
+ 'tuiIconVisa',
+ 'tuiIconElectron',
'tuiIconMastercard',
'tuiIconMaestro',
'tuiIconAmex',
diff --git a/projects/cdk/schematics/ng-update/v4/steps/constants/identifiers-to-replace.ts b/projects/cdk/schematics/ng-update/v4/steps/constants/identifiers-to-replace.ts
index 1083941ecaff..4bd9f79ee2f0 100644
--- a/projects/cdk/schematics/ng-update/v4/steps/constants/identifiers-to-replace.ts
+++ b/projects/cdk/schematics/ng-update/v4/steps/constants/identifiers-to-replace.ts
@@ -1349,7 +1349,7 @@ export const IDENTIFIERS_TO_REPLACE: ReplacementIdentifierMulti[] = [
moduleSpecifier: '@taiga-ui/addon-commerce',
},
to: {
- name: 'TuiInputCardComponent',
+ name: 'TuiInputCard',
moduleSpecifier: '@taiga-ui/addon-mobile',
},
},
@@ -1369,7 +1369,7 @@ export const IDENTIFIERS_TO_REPLACE: ReplacementIdentifierMulti[] = [
moduleSpecifier: '@taiga-ui/addon-commerce',
},
to: {
- name: 'TuiInputCVCComponent',
+ name: 'TuiInputCVC',
moduleSpecifier: '@taiga-ui/addon-mobile',
},
},
@@ -1379,7 +1379,7 @@ export const IDENTIFIERS_TO_REPLACE: ReplacementIdentifierMulti[] = [
moduleSpecifier: '@taiga-ui/addon-commerce',
},
to: {
- name: 'TuiInputExpireComponent',
+ name: 'TuiInputExpire',
moduleSpecifier: '@taiga-ui/addon-mobile',
},
},
diff --git a/projects/core/components/textfield/textfield.component.ts b/projects/core/components/textfield/textfield.component.ts
index a4c571e13d72..4e1f589e3bed 100644
--- a/projects/core/components/textfield/textfield.component.ts
+++ b/projects/core/components/textfield/textfield.component.ts
@@ -42,17 +42,10 @@ export interface TuiTextfieldContext extends TuiContext {
readonly active: boolean;
}
-// TODO: Move to legacy package before 4.0
@Component({
standalone: true,
selector: 'tui-textfield',
- imports: [
- CommonModule,
- ResizeObserverModule,
- TuiTextfieldDirective,
- TuiButtonDirective,
- PolymorpheusModule,
- ],
+ imports: [CommonModule, ResizeObserverModule, TuiButtonDirective, PolymorpheusModule],
templateUrl: './textfield.template.html',
styleUrls: ['./textfield.style.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
diff --git a/projects/core/components/textfield/textfield.module.ts b/projects/core/components/textfield/textfield.module.ts
index 24e66e61e84f..5326f2e4e0d3 100644
--- a/projects/core/components/textfield/textfield.module.ts
+++ b/projects/core/components/textfield/textfield.module.ts
@@ -23,4 +23,4 @@ import {TuiTextfieldOptionsDirective} from './textfield.options';
TuiTextfieldOptionsDirective,
],
})
-export class TuiTextfieldModule {}
+export class TuiTextfield {}
diff --git a/projects/core/components/textfield/textfield.style.less b/projects/core/components/textfield/textfield.style.less
index 25409c4ba3cd..fc7c354cf75c 100644
--- a/projects/core/components/textfield/textfield.style.less
+++ b/projects/core/components/textfield/textfield.style.less
@@ -154,6 +154,7 @@
::ng-deep input,
::ng-deep select {
pointer-events: auto;
+ background: padding-box transparent no-repeat center right 1rem / 2rem;
&:read-only ~ .t-filler {
display: none;
@@ -225,6 +226,7 @@
.t-content {
display: flex;
+ align-items: center;
gap: 0.25rem;
margin-inline-start: auto;
}
diff --git a/projects/core/styles/theme/appearance/textfield.less b/projects/core/styles/theme/appearance/textfield.less
index a541a3d903a9..90bccd074efd 100644
--- a/projects/core/styles/theme/appearance/textfield.less
+++ b/projects/core/styles/theme/appearance/textfield.less
@@ -5,7 +5,7 @@
--t-shadow: 0 0.125rem 0.1875rem rgba(0, 0, 0, 0.1);
- background: var(--tui-base-01);
+ background-color: var(--tui-base-01);
color: var(--tui-text-01);
box-shadow: var(--t-shadow);
outline: 1px solid var(--tui-base-03);
diff --git a/projects/demo-playwright/tests/addon-commerce/input-expire.spec.ts b/projects/demo-playwright/tests/addon-commerce/input-expire.spec.ts
index 21a7316edb2b..989448724b09 100644
--- a/projects/demo-playwright/tests/addon-commerce/input-expire.spec.ts
+++ b/projects/demo-playwright/tests/addon-commerce/input-expire.spec.ts
@@ -1,4 +1,4 @@
-import {TuiDocumentationPagePO, tuiGoto, TuiInputCardPO} from '@demo-playwright/utils';
+import {tuiGoto, TuiInputCardPO} from '@demo-playwright/utils';
import type {Locator} from '@playwright/test';
import {expect, test} from '@playwright/test';
@@ -6,11 +6,9 @@ test.describe('InputExpire', () => {
let expiryTextfield: Locator;
test.beforeEach(async ({page}) => {
- await tuiGoto(page, 'components/input-card/API');
+ await tuiGoto(page, 'components/input-card');
- const {apiPageExample} = new TuiDocumentationPagePO(page);
-
- expiryTextfield = new TuiInputCardPO(apiPageExample).expiryTextfield;
+ expiryTextfield = new TuiInputCardPO(page).expiryTextfield;
await expect(expiryTextfield).toBeEmpty();
});
diff --git a/projects/demo-playwright/utils/page-objects/input-card.po.ts b/projects/demo-playwright/utils/page-objects/input-card.po.ts
index 9115ba669c65..c6df4b7a21aa 100644
--- a/projects/demo-playwright/utils/page-objects/input-card.po.ts
+++ b/projects/demo-playwright/utils/page-objects/input-card.po.ts
@@ -1,10 +1,7 @@
-import type {Locator} from '@playwright/test';
+import type {Page} from '@playwright/test';
export class TuiInputCardPO {
- public readonly expiryTextfield = this.host
- .locator('tui-input-expire')
- .locator('input')
- .first();
+ public readonly expiryTextfield = this.page.locator('input[tuiInputExpire]').first();
- constructor(private readonly host: Locator) {}
+ constructor(private readonly page: Page) {}
}
diff --git a/projects/demo/src/modules/components/cell/examples/3/index.ts b/projects/demo/src/modules/components/cell/examples/3/index.ts
index 3e3e35daaad9..e88ada68338d 100644
--- a/projects/demo/src/modules/components/cell/examples/3/index.ts
+++ b/projects/demo/src/modules/components/cell/examples/3/index.ts
@@ -3,7 +3,7 @@ import {FormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {TuiThumbnailCardComponent} from '@taiga-ui/addon-commerce';
-import {TuiIconComponent} from '@taiga-ui/core';
+import {TuiIconComponent, TuiTitleDirective} from '@taiga-ui/core';
import {
TuiAvatarComponent,
TuiAvatarStackComponent,
@@ -25,6 +25,7 @@ import {TuiCellDirective} from '@taiga-ui/layout';
TuiCheckboxComponent,
TuiThumbnailCardComponent,
FormsModule,
+ TuiTitleDirective,
],
templateUrl: './index.html',
styleUrls: ['./index.less'],
diff --git a/projects/demo/src/modules/components/input-card/examples/1/index.html b/projects/demo/src/modules/components/input-card/examples/1/index.html
index 805297f5b609..5147c657562a 100644
--- a/projects/demo/src/modules/components/input-card/examples/1/index.html
+++ b/projects/demo/src/modules/components/input-card/examples/1/index.html
@@ -1,31 +1,35 @@
-
- form
- tag is used for better autocomplete
-
-
+{{ form.value | json }}
diff --git a/projects/demo/src/modules/components/input-card/examples/1/index.less b/projects/demo/src/modules/components/input-card/examples/1/index.less
new file mode 100644
index 000000000000..322ee68f16a6
--- /dev/null
+++ b/projects/demo/src/modules/components/input-card/examples/1/index.less
@@ -0,0 +1,14 @@
+form {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+section {
+ display: flex;
+ gap: inherit;
+
+ tui-textfield {
+ flex: 1;
+ }
+}
diff --git a/projects/demo/src/modules/components/input-card/examples/1/index.ts b/projects/demo/src/modules/components/input-card/examples/1/index.ts
index cbd8be9bf33f..968f0f95f75f 100644
--- a/projects/demo/src/modules/components/input-card/examples/1/index.ts
+++ b/projects/demo/src/modules/components/input-card/examples/1/index.ts
@@ -1,31 +1,50 @@
-import {Component} from '@angular/core';
+import {AsyncPipe, JsonPipe} from '@angular/common';
+import {Component, inject} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {
- TuiInputCardComponent,
- TuiInputCVCComponent,
- TuiInputExpireComponent,
+ tuiCreateLuhnValidator,
+ TuiInputCard,
+ tuiInputCardOptionsProvider,
+ TuiInputCVC,
+ TuiInputExpire,
} from '@taiga-ui/addon-commerce';
-import {TuiGroupDirective, TuiPrimitiveTextfieldModule} from '@taiga-ui/core';
+import {
+ TuiAlertService,
+ TuiErrorComponent,
+ TuiTextfield,
+ tuiTextfieldOptionsProvider,
+} from '@taiga-ui/core';
+import {TuiFieldErrorPipe} from '@taiga-ui/kit';
@Component({
standalone: true,
imports: [
- TuiGroupDirective,
ReactiveFormsModule,
- TuiInputCardComponent,
- TuiInputExpireComponent,
- TuiInputCVCComponent,
- TuiPrimitiveTextfieldModule,
+ TuiTextfield,
+ TuiInputCVC,
+ TuiInputExpire,
+ TuiInputCard,
+ TuiErrorComponent,
+ TuiFieldErrorPipe,
+ AsyncPipe,
+ JsonPipe,
],
templateUrl: './index.html',
+ styleUrls: ['./index.less'],
encapsulation,
changeDetection,
+ providers: [
+ tuiInputCardOptionsProvider({autocomplete: true}),
+ tuiTextfieldOptionsProvider({cleaner: false}),
+ ],
})
export default class ExampleComponent {
+ private readonly alerts = inject(TuiAlertService);
+
protected readonly form = new FormGroup({
- card: new FormControl(''),
+ card: new FormControl('', tuiCreateLuhnValidator('Card number is invalid')),
expire: new FormControl(''),
cvc: new FormControl(''),
});
@@ -55,4 +74,8 @@ export default class ExampleComponent {
return 'https://ng-web-apis.github.io/dist/assets/images/payment-request.svg';
}
}
+
+ protected onBinChange(bin: string | null): void {
+ this.alerts.open(String(bin), {label: '(binChange)'}).subscribe();
+ }
}
diff --git a/projects/demo/src/modules/components/input-card/examples/2/index.html b/projects/demo/src/modules/components/input-card/examples/2/index.html
new file mode 100644
index 000000000000..d33444dcc3cb
--- /dev/null
+++ b/projects/demo/src/modules/components/input-card/examples/2/index.html
@@ -0,0 +1,16 @@
+
+ Card number
+
+
+
diff --git a/projects/demo/src/modules/components/input-card/examples/2/index.ts b/projects/demo/src/modules/components/input-card/examples/2/index.ts
new file mode 100644
index 000000000000..5d4e69fcf3c8
--- /dev/null
+++ b/projects/demo/src/modules/components/input-card/examples/2/index.ts
@@ -0,0 +1,26 @@
+import {NgIf} from '@angular/common';
+import {Component} from '@angular/core';
+import {FormsModule} from '@angular/forms';
+import {changeDetection} from '@demo/emulate/change-detection';
+import {encapsulation} from '@demo/emulate/encapsulation';
+import {TuiInputCard, TuiThumbnailCardComponent} from '@taiga-ui/addon-commerce';
+import {TuiTextfield} from '@taiga-ui/core';
+import {TuiCheckboxComponent} from '@taiga-ui/kit';
+
+@Component({
+ standalone: true,
+ imports: [
+ NgIf,
+ FormsModule,
+ TuiTextfield,
+ TuiInputCard,
+ TuiThumbnailCardComponent,
+ TuiCheckboxComponent,
+ ],
+ templateUrl: './index.html',
+ encapsulation,
+ changeDetection,
+})
+export default class ExampleComponent {
+ protected card = '1234123412341234';
+}
diff --git a/projects/demo/src/modules/components/input-card/examples/import/import.md b/projects/demo/src/modules/components/input-card/examples/import/import.md
index 430657a4ae58..9c2974a88f04 100644
--- a/projects/demo/src/modules/components/input-card/examples/import/import.md
+++ b/projects/demo/src/modules/components/input-card/examples/import/import.md
@@ -1,5 +1,5 @@
```ts
-import {TuiInputCardComponent, TuiInputCVCComponent, TuiInputExpireComponent} from '@taiga-ui/addon-commerce';
+import {TuiInputCard, TuiInputCVC, TuiInputExpire} from '@taiga-ui/addon-commerce';
// ...
@@ -7,9 +7,9 @@ import {TuiInputCardComponent, TuiInputCVCComponent, TuiInputExpireComponent} fr
standalone: true,
imports: [
// ...
- TuiInputCardComponent,
- TuiInputCVCComponent,
- TuiInputExpireComponent,
+ TuiInputCard,
+ TuiInputCVC,
+ TuiInputExpire,
],
// ...
})
diff --git a/projects/demo/src/modules/components/input-card/examples/import/template.md b/projects/demo/src/modules/components/input-card/examples/import/template.md
index 9903b3ae2d69..8c6ec7286601 100644
--- a/projects/demo/src/modules/components/input-card/examples/import/template.md
+++ b/projects/demo/src/modules/components/input-card/examples/import/template.md
@@ -1,7 +1,28 @@
```html
- Card number
- Expire date
- CVC/CVV
+
+ Card number
+
+
+
+ Expire date
+
+
+
+ CVC/CVV
+
+
```
diff --git a/projects/demo/src/modules/components/input-card/index.html b/projects/demo/src/modules/components/input-card/index.html
index 36dd4550ffe2..54ea47424148 100644
--- a/projects/demo/src/modules/components/input-card/index.html
+++ b/projects/demo/src/modules/components/input-card/index.html
@@ -10,192 +10,38 @@
InputExpire
and
InputCVC
- to input a card
+ to input a card. Use
+ tuiCreateLuhnValidator(message)
+ to create a
+ Validator
+ that uses Luhn algorithm
-
-
-
-
-
-
-
- Card number
-
-
- Expire date
-
-
- CVC/CVV
-
-
-
-
-
-
+ [content]="1 | tuiExample"
+ >
- Add
- tuiCreateLuhnValidator(customMessage?)
- to control validators to validate it with Luhn algorithm
+ form
+ tag is used for better autocomplete support
-
-
-
- TuiInputCardComponent
-
-
-
- Disabled state (use
- formControl.disable()
- )
-
-
- SVG card icon
-
-
- BIN value (card first 6 symbols)
-
-
-
-
-
-
-
- TuiInputExpireComponent
-
-
-
- Disabled state (use
- formControl.disable()
- )
-
-
- Browser autocomplete of card
-
-
-
-
-
+
-
- TuiInputCVCComponent
-
-
-
- Disabled state (use
- formControl.disable()
- )
-
-
- Browser autocomplete of card
-
-
- Code length
-
-
-
-
-
-
+
+
+ Pass empty string to disable
+ icon
+ if you want to use custom content instead.
+
+
-
+
diff --git a/projects/demo/src/modules/components/input-card/index.less b/projects/demo/src/modules/components/input-card/index.less
deleted file mode 100644
index af1f592a06ab..000000000000
--- a/projects/demo/src/modules/components/input-card/index.less
+++ /dev/null
@@ -1,23 +0,0 @@
-@import '@taiga-ui/core/styles/taiga-ui-local';
-
-.form {
- display: flex;
- flex-wrap: wrap;
-}
-
-.control {
- flex: 1;
- margin-bottom: 0.25rem;
-
- &:not(:last-child) {
- margin-right: 1.25rem;
- }
-}
-
-.error {
- min-width: 100%;
-}
-
-.title {
- font: var(--tui-font-heading-5);
-}
diff --git a/projects/demo/src/modules/components/input-card/index.ts b/projects/demo/src/modules/components/input-card/index.ts
index c044f4ea863c..926e795dfdb3 100644
--- a/projects/demo/src/modules/components/input-card/index.ts
+++ b/projects/demo/src/modules/components/input-card/index.ts
@@ -1,133 +1,11 @@
-import {Component, ViewChild} from '@angular/core';
-import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
+import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {TuiDemo} from '@demo/utils';
-import type {TuiCodeCVCLength} from '@taiga-ui/addon-commerce';
-import {
- tuiCreateLuhnValidator,
- TuiInputCardComponent,
- TuiInputCVCComponent,
- TuiInputExpireComponent,
-} from '@taiga-ui/addon-commerce';
-import {TuiDocDocumentationPropertyConnectorDirective} from '@taiga-ui/addon-doc';
-import {tuiProvide} from '@taiga-ui/cdk';
-import type {TuiHintOptions} from '@taiga-ui/core';
-import {TuiErrorComponent, TuiHint, TuiTextfieldControllerModule} from '@taiga-ui/core';
-import {TuiAccordion, TuiFieldErrorPipe} from '@taiga-ui/kit';
-
-import {ABSTRACT_PROPS_ACCESSOR} from '../abstract/abstract-props-accessor';
-import {AbstractExampleTuiControl} from '../abstract/control';
-import {InheritedDocumentationComponent} from '../abstract/inherited-documentation';
@Component({
standalone: true,
- imports: [
- TuiDemo,
- TuiHint,
- ReactiveFormsModule,
- TuiInputCardComponent,
- TuiInputExpireComponent,
- TuiTextfieldControllerModule,
- TuiInputCVCComponent,
- TuiErrorComponent,
- TuiFieldErrorPipe,
- TuiAccordion,
- InheritedDocumentationComponent,
- ],
+ imports: [TuiDemo],
templateUrl: './index.html',
- styleUrls: ['./index.less'],
changeDetection,
- providers: [tuiProvide(ABSTRACT_PROPS_ACCESSOR, PageComponent)],
})
-export default class PageComponent extends AbstractExampleTuiControl {
- @ViewChild('documentationPropertyBinChange', {
- read: TuiDocDocumentationPropertyConnectorDirective,
- })
- protected binChangeProperty?: TuiDocDocumentationPropertyConnectorDirective;
-
- protected card = '';
-
- protected readonly lengthVariants: TuiCodeCVCLength[] = [3, 4];
-
- protected length = this.lengthVariants[0];
-
- protected hintContentCVC = null;
-
- protected hintDirectionCVC: TuiHintOptions['direction'] = 'bottom-left';
-
- protected hintAppearanceCVC = '';
-
- protected readonly cards: Record = {
- common: 'https://ng-web-apis.github.io/dist/assets/images/common.svg',
- universal: 'https://ng-web-apis.github.io/dist/assets/images/universal.svg',
- intersection:
- 'https://ng-web-apis.github.io/dist/assets/images/intersection-observer.svg',
- mutation:
- 'https://ng-web-apis.github.io/dist/assets/images/mutation-observer.svg',
- };
-
- protected cardSrcVariants = Object.keys(this.cards);
-
- protected cardSrcSelected: string | null = null;
-
- protected autocompleteEnabledCard = false;
-
- protected autocompleteEnabledCVC = false;
-
- protected autocompleteEnabledExpire = false;
-
- public control = new FormGroup({
- card: new FormControl('', [
- Validators.required,
- tuiCreateLuhnValidator('Invalid card number'),
- ]),
- expire: new FormControl('', Validators.required),
- cvc: new FormControl('', Validators.required),
- });
-
- public override cleaner = false;
-
- public override exampleText = '0000 0000 0000 0000';
-
- protected get cardSrc(): string | null {
- return this.cardSrcSelected === null ? null : this.cards[this.cardSrcSelected];
- }
-
- protected get disabledCard(): boolean {
- return this.isDisabled('card');
- }
-
- protected set disabledCard(value: boolean) {
- this.toggleDisabled(value, 'card');
- }
-
- protected get disabledExpire(): boolean {
- return this.isDisabled('expire');
- }
-
- protected set disabledExpire(value: boolean) {
- this.toggleDisabled(value, 'expire');
- }
-
- protected get disabledCVC(): boolean {
- return this.isDisabled('cvc');
- }
-
- protected set disabledCVC(value: boolean) {
- this.toggleDisabled(value, 'cvc');
- }
-
- protected isDisabled(control: string): boolean {
- return this.control.get(control)!.disabled;
- }
-
- protected toggleDisabled(value: boolean, control: string): void {
- if (value) {
- this.control.get(control)!.disable();
-
- return;
- }
-
- this.control.get(control)!.enable();
- }
-}
+export default class PageComponent {}
diff --git a/projects/demo/src/modules/components/input/examples/4/index.html b/projects/demo/src/modules/components/input/examples/4/index.html
index 880aff5488fc..be3cc510e7df 100644
--- a/projects/demo/src/modules/components/input/examples/4/index.html
+++ b/projects/demo/src/modules/components/input/examples/4/index.html
@@ -60,11 +60,13 @@
-
- Card number
-
+
+ Card number
+
+
diff --git a/projects/demo/src/modules/components/input/examples/4/index.ts b/projects/demo/src/modules/components/input/examples/4/index.ts
index 1e2147366026..a16ffe33b86f 100644
--- a/projects/demo/src/modules/components/input/examples/4/index.ts
+++ b/projects/demo/src/modules/components/input/examples/4/index.ts
@@ -4,13 +4,14 @@ import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {assets} from '@demo/utils';
-import {
- TuiAmountPipe,
- TuiCurrency,
- TuiInputCardComponent,
-} from '@taiga-ui/addon-commerce';
+import {TuiAmountPipe, TuiCurrency, TuiInputCard} from '@taiga-ui/addon-commerce';
import {TUI_DEFAULT_MATCHER, tuiControlValue, TuiLetDirective} from '@taiga-ui/cdk';
-import {TuiDataList, TuiInitialsPipe, TuiTextfieldControllerModule} from '@taiga-ui/core';
+import {
+ TuiDataList,
+ TuiInitialsPipe,
+ TuiTextfield,
+ TuiTextfieldControllerModule,
+} from '@taiga-ui/core';
import {TuiAvatarComponent, TuiDataListWrapper} from '@taiga-ui/kit';
import {TuiInputModule} from '@taiga-ui/legacy';
import type {PolymorpheusContent} from '@tinkoff/ng-polymorpheus';
@@ -112,7 +113,8 @@ const USERS = [
TuiInitialsPipe,
TuiDataListWrapper,
TuiAmountPipe,
- TuiInputCardComponent,
+ TuiTextfield,
+ TuiInputCard,
],
templateUrl: './index.html',
styleUrls: ['./index.less'],
diff --git a/projects/demo/src/modules/components/label/examples/4/index.ts b/projects/demo/src/modules/components/label/examples/4/index.ts
index 98ad5887ce74..3dede02024a3 100644
--- a/projects/demo/src/modules/components/label/examples/4/index.ts
+++ b/projects/demo/src/modules/components/label/examples/4/index.ts
@@ -2,11 +2,11 @@ import {Component} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
-import {TuiTextfieldModule} from '@taiga-ui/core';
+import {TuiTextfield} from '@taiga-ui/core';
@Component({
standalone: true,
- imports: [ReactiveFormsModule, TuiTextfieldModule],
+ imports: [ReactiveFormsModule, TuiTextfield],
templateUrl: './index.html',
encapsulation,
changeDetection,
diff --git a/projects/demo/src/modules/components/textfield/examples/1/index.ts b/projects/demo/src/modules/components/textfield/examples/1/index.ts
index 9cd635e5866d..affaabe194c0 100644
--- a/projects/demo/src/modules/components/textfield/examples/1/index.ts
+++ b/projects/demo/src/modules/components/textfield/examples/1/index.ts
@@ -2,12 +2,12 @@ import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
-import {TuiIconComponent, TuiTextfieldModule} from '@taiga-ui/core';
+import {TuiIconComponent, TuiTextfield} from '@taiga-ui/core';
import {TuiTooltipModule} from '@taiga-ui/experimental';
@Component({
standalone: true,
- imports: [FormsModule, TuiTextfieldModule, TuiIconComponent, TuiTooltipModule],
+ imports: [FormsModule, TuiTextfield, TuiIconComponent, TuiTooltipModule],
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
diff --git a/projects/demo/src/modules/components/textfield/examples/2/index.ts b/projects/demo/src/modules/components/textfield/examples/2/index.ts
index 765e4d0be297..da2d78fff513 100644
--- a/projects/demo/src/modules/components/textfield/examples/2/index.ts
+++ b/projects/demo/src/modules/components/textfield/examples/2/index.ts
@@ -2,12 +2,12 @@ import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
-import {TuiIconComponent, TuiTextfieldModule} from '@taiga-ui/core';
+import {TuiIconComponent, TuiTextfield} from '@taiga-ui/core';
import {TuiTooltipModule} from '@taiga-ui/experimental';
@Component({
standalone: true,
- imports: [FormsModule, TuiTextfieldModule, TuiIconComponent, TuiTooltipModule],
+ imports: [FormsModule, TuiTextfield, TuiIconComponent, TuiTooltipModule],
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
diff --git a/projects/demo/src/modules/components/textfield/examples/3/index.ts b/projects/demo/src/modules/components/textfield/examples/3/index.ts
index d1cb32a62432..cdd2431f7e41 100644
--- a/projects/demo/src/modules/components/textfield/examples/3/index.ts
+++ b/projects/demo/src/modules/components/textfield/examples/3/index.ts
@@ -2,7 +2,7 @@ import {Component} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
-import {TuiDropdownModule, TuiIconComponent, TuiTextfieldModule} from '@taiga-ui/core';
+import {TuiDropdownModule, TuiIconComponent, TuiTextfield} from '@taiga-ui/core';
import {TuiTooltipModule} from '@taiga-ui/experimental';
import {
TuiChevronDirective,
@@ -15,7 +15,7 @@ import {
imports: [
FormsModule,
TuiDropdownModule,
- TuiTextfieldModule,
+ TuiTextfield,
TuiIconComponent,
TuiTooltipModule,
TuiChevronDirective,
diff --git a/projects/demo/src/modules/components/textfield/examples/import/import.md b/projects/demo/src/modules/components/textfield/examples/import/import.md
index 2ab7b9469b16..588f8ff36550 100644
--- a/projects/demo/src/modules/components/textfield/examples/import/import.md
+++ b/projects/demo/src/modules/components/textfield/examples/import/import.md
@@ -1,13 +1,13 @@
```ts
import {Component} from '@angular/core';
-import {TuiTextfieldModule} from '@taiga-ui/core';
+import {TuiTextfield} from '@taiga-ui/core';
// ...
@Component({
standalone: true,
imports: [
// ...
- TuiTextfieldModule,
+ TuiTextfield,
],
})
export class MyComponent {}
diff --git a/projects/demo/used-icons.ts b/projects/demo/used-icons.ts
index 5a308c255d70..e67f6abd150d 100644
--- a/projects/demo/used-icons.ts
+++ b/projects/demo/used-icons.ts
@@ -96,6 +96,7 @@ export const TUI_USED_ICONS = [
'tuiIconAliPay',
'tuiIconAmazonPay',
'tuiIconAndroidPay',
+ 'tuiIconDollarSign',
'tuiIconFileLarge',
'tuiIconDropletLarge',
'tuiIconUploadCloudLarge',
@@ -110,7 +111,6 @@ export const TUI_USED_ICONS = [
'tuiIconXCircle',
'tuiIconCheckCircleLarge',
'tuiIconExternalLink',
- 'tuiIconDollarSign',
'tuiIconDownload',
'tuiIconEyeOffLarge',
'tuiIconEdit2',
diff --git a/projects/icons/all.ts b/projects/icons/all.ts
index 4ea3bb293eb1..37a83982b4ef 100644
--- a/projects/icons/all.ts
+++ b/projects/icons/all.ts
@@ -102,6 +102,9 @@ const tuiIconAmazonPay =
const tuiIconAmex =
' ';
+const tuiIconAmexOutline =
+ ' ';
+
const tuiIconAnchor =
' ';
@@ -906,6 +909,9 @@ const tuiIconDesktopLarge =
const tuiIconDinersClub =
' ';
+const tuiIconDinersClubOutline =
+ ' ';
+
const tuiIconDisc =
' ';
@@ -918,6 +924,9 @@ const tuiIconDiscOutline =
const tuiIconDiscover =
' ';
+const tuiIconDiscoverOutline =
+ ' ';
+
const tuiIconDislikeLarge =
' ';
@@ -1039,7 +1048,10 @@ const tuiIconElectronMono =
' ';
const tuiIconElectronMonoOutline =
- ' ';
+ ' ';
+
+const tuiIconElectronOutline =
+ ' ';
const tuiIconExpand =
' ';
@@ -1416,6 +1428,9 @@ const tuiIconHrOutline =
const tuiIconHumo =
' ';
+const tuiIconHumoOutline =
+ ' ';
+
const tuiIconImage =
' ';
@@ -1476,6 +1491,9 @@ const tuiIconItalicOutline =
const tuiIconJCB =
' ';
+const tuiIconJCBOutline =
+ ' ';
+
const tuiIconKey =
' ';
@@ -1596,6 +1614,9 @@ const tuiIconMaestro =
const tuiIconMaestroMono =
' ';
+const tuiIconMaestroOutline =
+ ' ';
+
const tuiIconMail =
' ';
@@ -1629,6 +1650,9 @@ const tuiIconMastercard =
const tuiIconMastercardMono =
' ';
+const tuiIconMastercardOutline =
+ ' ';
+
const tuiIconMaximize =
' ';
@@ -1753,7 +1777,10 @@ const tuiIconMirMono =
' ';
const tuiIconMirMonoOutline =
- ' ';
+ ' ';
+
+const tuiIconMirOutline =
+ ' ';
const tuiIconMobile =
' ';
@@ -2184,6 +2211,9 @@ const tuiIconRssOutline =
const tuiIconRuPay =
' ';
+const tuiIconRuPayOutline =
+ ' ';
+
const tuiIconSamsungPay =
' ';
@@ -2787,6 +2817,9 @@ const tuiIconUndoOutline =
const tuiIconUnionPay =
' ';
+const tuiIconUnionPayOutline =
+ ' ';
+
const tuiIconUnlinkLarge =
' ';
@@ -2877,9 +2910,15 @@ const tuiIconUsersOutline =
const tuiIconUzcard =
' ';
+const tuiIconUzcardOutline =
+ ' ';
+
const tuiIconVerve =
' ';
+const tuiIconVerveOutline =
+ ' ';
+
const tuiIconVideo =
' ';
@@ -2908,7 +2947,10 @@ const tuiIconVisaMono =
' ';
const tuiIconVisaMonoOutline =
- ' ';
+ ' ';
+
+const tuiIconVisaOutline =
+ ' ';
const tuiIconVoicemail =
' ';
@@ -3114,6 +3156,7 @@ export {
tuiIconAlignRightOutline,
tuiIconAmazonPay,
tuiIconAmex,
+ tuiIconAmexOutline,
tuiIconAnchor,
tuiIconAnchorLarge,
tuiIconAnchorOutline,
@@ -3382,10 +3425,12 @@ export {
tuiIconDeleteOutline,
tuiIconDesktopLarge,
tuiIconDinersClub,
+ tuiIconDinersClubOutline,
tuiIconDisc,
tuiIconDiscLarge,
tuiIconDiscOutline,
tuiIconDiscover,
+ tuiIconDiscoverOutline,
tuiIconDislikeLarge,
tuiIconDivide,
tuiIconDivideCircle,
@@ -3427,6 +3472,7 @@ export {
tuiIconElectron,
tuiIconElectronMono,
tuiIconElectronMonoOutline,
+ tuiIconElectronOutline,
tuiIconExpand,
tuiIconExternal,
tuiIconExternalLarge,
@@ -3552,6 +3598,7 @@ export {
tuiIconHrLarge,
tuiIconHrOutline,
tuiIconHumo,
+ tuiIconHumoOutline,
tuiIconImage,
tuiIconImageLarge,
tuiIconImageOutline,
@@ -3572,6 +3619,7 @@ export {
tuiIconItalicLarge,
tuiIconItalicOutline,
tuiIconJCB,
+ tuiIconJCBOutline,
tuiIconKey,
tuiIconKeyLarge,
tuiIconKeyOutline,
@@ -3612,6 +3660,7 @@ export {
tuiIconLogOutOutline,
tuiIconMaestro,
tuiIconMaestroMono,
+ tuiIconMaestroOutline,
tuiIconMail,
tuiIconMailLarge,
tuiIconMailOutline,
@@ -3623,6 +3672,7 @@ export {
tuiIconMapPinOutline,
tuiIconMastercard,
tuiIconMastercardMono,
+ tuiIconMastercardOutline,
tuiIconMaximize,
tuiIconMaximize2,
tuiIconMaximize2Large,
@@ -3665,6 +3715,7 @@ export {
tuiIconMir,
tuiIconMirMono,
tuiIconMirMonoOutline,
+ tuiIconMirOutline,
tuiIconMobile,
tuiIconMobileLarge,
tuiIconMonitor,
@@ -3808,6 +3859,7 @@ export {
tuiIconRssLarge,
tuiIconRssOutline,
tuiIconRuPay,
+ tuiIconRuPayOutline,
tuiIconSamsungPay,
tuiIconSave,
tuiIconSaveLarge,
@@ -4009,6 +4061,7 @@ export {
tuiIconUndoLarge,
tuiIconUndoOutline,
tuiIconUnionPay,
+ tuiIconUnionPayOutline,
tuiIconUnlinkLarge,
tuiIconUnlinkOutline,
tuiIconUnlock,
@@ -4039,7 +4092,9 @@ export {
tuiIconUsersLarge,
tuiIconUsersOutline,
tuiIconUzcard,
+ tuiIconUzcardOutline,
tuiIconVerve,
+ tuiIconVerveOutline,
tuiIconVideo,
tuiIconVideoLarge,
tuiIconVideoOff,
@@ -4050,6 +4105,7 @@ export {
tuiIconVisa,
tuiIconVisaMono,
tuiIconVisaMonoOutline,
+ tuiIconVisaOutline,
tuiIconVoicemail,
tuiIconVoicemailLarge,
tuiIconVoicemailOutline,
diff --git a/projects/icons/src/tuiIconAmexOutline.svg b/projects/icons/src/tuiIconAmexOutline.svg
new file mode 100644
index 000000000000..6b7c153a40ff
--- /dev/null
+++ b/projects/icons/src/tuiIconAmexOutline.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconDinersClubOutline.svg b/projects/icons/src/tuiIconDinersClubOutline.svg
new file mode 100644
index 000000000000..d8b2a58f7b26
--- /dev/null
+++ b/projects/icons/src/tuiIconDinersClubOutline.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconDiscoverOutline.svg b/projects/icons/src/tuiIconDiscoverOutline.svg
new file mode 100644
index 000000000000..0342bc3e0373
--- /dev/null
+++ b/projects/icons/src/tuiIconDiscoverOutline.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconElectronMonoOutline.svg b/projects/icons/src/tuiIconElectronMonoOutline.svg
index 42f717a1d2a4..8c4bc45596fd 100644
--- a/projects/icons/src/tuiIconElectronMonoOutline.svg
+++ b/projects/icons/src/tuiIconElectronMonoOutline.svg
@@ -1,51 +1,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconElectronOutline.svg b/projects/icons/src/tuiIconElectronOutline.svg
new file mode 100644
index 000000000000..1ab6b59a7e9c
--- /dev/null
+++ b/projects/icons/src/tuiIconElectronOutline.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconHumoOutline.svg b/projects/icons/src/tuiIconHumoOutline.svg
new file mode 100644
index 000000000000..2ca2f27b6a94
--- /dev/null
+++ b/projects/icons/src/tuiIconHumoOutline.svg
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconJCBOutline.svg b/projects/icons/src/tuiIconJCBOutline.svg
new file mode 100644
index 000000000000..6f32589f8891
--- /dev/null
+++ b/projects/icons/src/tuiIconJCBOutline.svg
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconMaestroOutline.svg b/projects/icons/src/tuiIconMaestroOutline.svg
new file mode 100644
index 000000000000..4eb8ff971285
--- /dev/null
+++ b/projects/icons/src/tuiIconMaestroOutline.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconMastercardOutline.svg b/projects/icons/src/tuiIconMastercardOutline.svg
new file mode 100644
index 000000000000..f74fe1a3b7ba
--- /dev/null
+++ b/projects/icons/src/tuiIconMastercardOutline.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconMirMonoOutline.svg b/projects/icons/src/tuiIconMirMonoOutline.svg
index 77add71825ad..1d5b2b1167ab 100644
--- a/projects/icons/src/tuiIconMirMonoOutline.svg
+++ b/projects/icons/src/tuiIconMirMonoOutline.svg
@@ -1,28 +1,6 @@
-
-
-
-
-
-
-
-
+
+
diff --git a/projects/icons/src/tuiIconMirOutline.svg b/projects/icons/src/tuiIconMirOutline.svg
new file mode 100644
index 000000000000..46d63e539d80
--- /dev/null
+++ b/projects/icons/src/tuiIconMirOutline.svg
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconRuPayOutline.svg b/projects/icons/src/tuiIconRuPayOutline.svg
new file mode 100644
index 000000000000..dcfe2b1384bc
--- /dev/null
+++ b/projects/icons/src/tuiIconRuPayOutline.svg
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconUnionPayOutline.svg b/projects/icons/src/tuiIconUnionPayOutline.svg
new file mode 100644
index 000000000000..0433fe0ed1ed
--- /dev/null
+++ b/projects/icons/src/tuiIconUnionPayOutline.svg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconUzcardOutline.svg b/projects/icons/src/tuiIconUzcardOutline.svg
new file mode 100644
index 000000000000..9acd7d43f1e1
--- /dev/null
+++ b/projects/icons/src/tuiIconUzcardOutline.svg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconVerveOutline.svg b/projects/icons/src/tuiIconVerveOutline.svg
new file mode 100644
index 000000000000..0b52f57baa2a
--- /dev/null
+++ b/projects/icons/src/tuiIconVerveOutline.svg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/projects/icons/src/tuiIconVisaMonoOutline.svg b/projects/icons/src/tuiIconVisaMonoOutline.svg
index 7290c395f1fb..b9af41071f8a 100644
--- a/projects/icons/src/tuiIconVisaMonoOutline.svg
+++ b/projects/icons/src/tuiIconVisaMonoOutline.svg
@@ -1,29 +1,7 @@
-
-
-
-
-
-
-
-
+
+
diff --git a/projects/icons/src/tuiIconVisaOutline.svg b/projects/icons/src/tuiIconVisaOutline.svg
new file mode 100644
index 000000000000..e72c559b8a01
--- /dev/null
+++ b/projects/icons/src/tuiIconVisaOutline.svg
@@ -0,0 +1,7 @@
+
+
+
From 9601fd67a827aa998e265add48b0a9b4e5a236a3 Mon Sep 17 00:00:00 2001
From: Nikita Barsukov
Date: Tue, 4 Jun 2024 12:20:24 +0300
Subject: [PATCH 5/7] refactor(core): use `childNodes.length` instead of
`textContent` to detect label for `Textfield` (#7616)
---
projects/core/components/textfield/textfield.component.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/projects/core/components/textfield/textfield.component.ts b/projects/core/components/textfield/textfield.component.ts
index 4e1f589e3bed..340aefa8836e 100644
--- a/projects/core/components/textfield/textfield.component.ts
+++ b/projects/core/components/textfield/textfield.component.ts
@@ -147,6 +147,6 @@ export class TuiTextfieldComponent
}
protected get hasLabel(): boolean {
- return Boolean(this.label?.nativeElement?.textContent?.trim());
+ return Boolean(this.label?.nativeElement?.childNodes.length);
}
}
From e51a2b93b5bbaee028d1cdb1f2916ab272a83830 Mon Sep 17 00:00:00 2001
From: Vladimir Potekhin <46284632+vladimirpotekhin@users.noreply.github.com>
Date: Tue, 4 Jun 2024 12:22:10 +0300
Subject: [PATCH 6/7] fix(core): close `Hint` and `Dropdown` when host is
detached from dom (#7614)
---
.../directives/dropdown/dropdown.component.ts | 6 +-
.../core/directives/hint/hint.component.ts | 6 ++
projects/demo-cypress/src/tests/hint.cy.ts | 67 +++++++++++++++++++
3 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 projects/demo-cypress/src/tests/hint.cy.ts
diff --git a/projects/core/directives/dropdown/dropdown.component.ts b/projects/core/directives/dropdown/dropdown.component.ts
index 578f2e2fbc10..64886be951e3 100644
--- a/projects/core/directives/dropdown/dropdown.component.ts
+++ b/projects/core/directives/dropdown/dropdown.component.ts
@@ -67,7 +67,11 @@ export class TuiDropdownComponent implements OnInit {
takeUntilDestroyed(),
)
.subscribe(([top, left]) => {
- this.update(top, left);
+ if (this.directive.el.isConnected) {
+ this.update(top, left);
+ } else {
+ this.directive.toggle(false);
+ }
});
public ngOnInit(): void {
diff --git a/projects/core/directives/hint/hint.component.ts b/projects/core/directives/hint/hint.component.ts
index b4c31f7d7566..41bafb130023 100644
--- a/projects/core/directives/hint/hint.component.ts
+++ b/projects/core/directives/hint/hint.component.ts
@@ -117,6 +117,12 @@ export class TuiHintComponent {
@tuiPure
private update(top: number, left: number): void {
+ if (!this.hover.el.isConnected) {
+ this.hover.toggle(false);
+
+ return;
+ }
+
const {height, width} = this.el.getBoundingClientRect();
const rect = this.accessor.getClientRect();
const viewport = this.viewport.getClientRect();
diff --git a/projects/demo-cypress/src/tests/hint.cy.ts b/projects/demo-cypress/src/tests/hint.cy.ts
new file mode 100644
index 000000000000..2506ea9409ae
--- /dev/null
+++ b/projects/demo-cypress/src/tests/hint.cy.ts
@@ -0,0 +1,67 @@
+import {Component, Input} from '@angular/core';
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+import {TuiSwipeDirective} from '@taiga-ui/cdk';
+import {TuiHint, TuiRootComponent} from '@taiga-ui/core';
+import {NG_EVENT_PLUGINS} from '@tinkoff/ng-event-plugins';
+import type {MountResponse} from 'cypress/angular';
+
+describe('TuiHint', () => {
+ let component: TestComponent;
+ let wrapper: MountResponse;
+
+ @Component({
+ selector: 'my-host',
+ template: `
+
+
+
+ `,
+ })
+ class HostComponent {
+ @Input()
+ public hideElement = false;
+ }
+
+ @Component({
+ template: `
+
+
+ button
+
+
+ `,
+ })
+ class TestComponent {
+ public hide = false;
+ }
+
+ beforeEach(() =>
+ cy
+ .mount(TestComponent, {
+ imports: [
+ BrowserAnimationsModule,
+ TuiRootComponent,
+ TuiSwipeDirective,
+ TuiHint,
+ ],
+ declarations: [HostComponent],
+ providers: [NG_EVENT_PLUGINS],
+ })
+ .then(wrap => {
+ component = wrap.component;
+ wrapper = wrap;
+ }),
+ );
+
+ it('hint should hidden when detached from dom', () => {
+ cy.get('button').trigger('mouseenter');
+ cy.get('tui-hint')
+ .should('exist')
+ .then(() => {
+ component.hide = true;
+ wrapper.fixture.detectChanges();
+
+ cy.get('tui-hint').should('not.exist');
+ });
+ });
+});
From ed55717aa4adfeb4ba7312941d8234aa467a1d9a Mon Sep 17 00:00:00 2001
From: taiga-family-bot <140712314+taiga-family-bot@users.noreply.github.com>
Date: Tue, 4 Jun 2024 12:37:04 +0300
Subject: [PATCH 7/7] chore(deps): update taiga-ui to v0.94.0 (#7618)
---
package-lock.json | 65 +++++++++++++++++++++++++----------------------
package.json | 14 +++++-----
2 files changed, 42 insertions(+), 37 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 979f8983625a..7154cc22e5e6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,13 +28,13 @@
"@nx/jest": "18.3.4",
"@nx/workspace": "18.3.4",
"@schematics/angular": "16.2.12",
- "@taiga-ui/browserslist-config": "0.6.0",
- "@taiga-ui/commitlint-config": "0.7.5",
- "@taiga-ui/cspell-config": "0.40.1",
- "@taiga-ui/eslint-plugin-experience": "0.75.4",
- "@taiga-ui/prettier-config": "0.11.9",
- "@taiga-ui/stylelint-config": "0.22.3",
- "@taiga-ui/tsconfig": "0.17.0",
+ "@taiga-ui/browserslist-config": "0.94.0",
+ "@taiga-ui/commitlint-config": "0.94.0",
+ "@taiga-ui/cspell-config": "0.94.0",
+ "@taiga-ui/eslint-plugin-experience": "0.94.0",
+ "@taiga-ui/prettier-config": "0.94.0",
+ "@taiga-ui/stylelint-config": "0.94.0",
+ "@taiga-ui/tsconfig": "0.94.0",
"@tinkoff/ng-event-plugins": "3.2.0",
"@types/glob": "8.1.0",
"@types/loader-utils": "2.0.6",
@@ -9030,20 +9030,22 @@
"link": true
},
"node_modules/@taiga-ui/browserslist-config": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@taiga-ui/browserslist-config/-/browserslist-config-0.6.0.tgz",
- "integrity": "sha512-lCbOPwSH3FsZx0rKQvqsTmR8SSBvuKauqO616cQJmS9R4PdmbT4eHW1OIwmCTIRO1BN6qLeMjqq4mlq3JjqeBw==",
- "dev": true
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/browserslist-config/-/browserslist-config-0.94.0.tgz",
+ "integrity": "sha512-aLM1p8DRXO+zjPmlcWEmnAXebYRdhbYUlX/9H/VC194ohIul3FOFoZSrN4bJ6/Rb6sHXJEXYqQV3zBHR1VRsYQ==",
+ "dev": true,
+ "license": "Apache-2.0"
},
"node_modules/@taiga-ui/cdk": {
"resolved": "projects/cdk",
"link": true
},
"node_modules/@taiga-ui/commitlint-config": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/@taiga-ui/commitlint-config/-/commitlint-config-0.7.5.tgz",
- "integrity": "sha512-igi0fdyG6KsQ259cCFG2zU1Svd3KKD/0aSiwPJIMglqMhaj+TIqMezbX7d3XYcWwnrQftSovV0jBA/DuII5dhA==",
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/commitlint-config/-/commitlint-config-0.94.0.tgz",
+ "integrity": "sha512-IGD9DCIx7Dilq3gaJ7io6vl9rXX6DyqdSE+y13h5syiGnHrlRa5XzrYL8JM0YseXU6UIDy55WjBImn6TMfPtEA==",
"dev": true,
+ "license": "Apache-2.0",
"peerDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2"
@@ -9054,9 +9056,9 @@
"link": true
},
"node_modules/@taiga-ui/cspell-config": {
- "version": "0.40.1",
- "resolved": "https://registry.npmjs.org/@taiga-ui/cspell-config/-/cspell-config-0.40.1.tgz",
- "integrity": "sha512-uy8KmM+k/Z7QAuGx2LdQUsSNw4x0Ac7ovXCtNfxO79fEjQG6RE7jHuoBbhPSneRJbX6iJjsPejWiOeZNsOFkTA==",
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/cspell-config/-/cspell-config-0.94.0.tgz",
+ "integrity": "sha512-Bmpg3xokETcGpLJ3ehWsshvgqYw9HP8rzK6v4hCC3fAVT2qlReDW/O4pHlkEmVXYXkOmCM5n24FUaviNBdyalQ==",
"dev": true,
"license": "Apache-2.0",
"peerDependencies": {
@@ -9089,9 +9091,9 @@
}
},
"node_modules/@taiga-ui/eslint-plugin-experience": {
- "version": "0.75.4",
- "resolved": "https://registry.npmjs.org/@taiga-ui/eslint-plugin-experience/-/eslint-plugin-experience-0.75.4.tgz",
- "integrity": "sha512-4ntWlhSP2H300G2PyusBT1cGn36+uE6VY2owWPNAWTHT0tei/9NZowyzyFKg11ltMXOZLJ3vpX6zP1I0UWJRog==",
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/eslint-plugin-experience/-/eslint-plugin-experience-0.94.0.tgz",
+ "integrity": "sha512-/bI5TUBTxFG0zV5V5Wm7LhxumxfeLt3CuJIsU8eEdaLl8eGvTtU0bjLDbEnp85Pg5WjQ5rm9zrwxqF3aE5Ej3A==",
"dev": true,
"peerDependencies": {
"@angular-eslint/eslint-plugin": "^18.0.1",
@@ -9154,10 +9156,11 @@
"link": true
},
"node_modules/@taiga-ui/prettier-config": {
- "version": "0.11.9",
- "resolved": "https://registry.npmjs.org/@taiga-ui/prettier-config/-/prettier-config-0.11.9.tgz",
- "integrity": "sha512-co9io3CBgSpHkclOZGZVMsPISTpLh9NSN6INJR+rC7NKadxs4PBaanji6HsuIA29GztIQ/OX1TOLW2QzzNQkOw==",
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/prettier-config/-/prettier-config-0.94.0.tgz",
+ "integrity": "sha512-iW/daJTFryAy4sfLYXCWMC9to+TfE6B4JwzspmG0HhLNMlEIQzwKhAV09BXUt4PHnpZfqdmdKzwaIPMRWWDyUA==",
"dev": true,
+ "license": "Apache-2.0",
"peerDependencies": {
"@prettier/plugin-xml": "^3.4.1",
"prettier": "^3.3.0",
@@ -9168,10 +9171,11 @@
}
},
"node_modules/@taiga-ui/stylelint-config": {
- "version": "0.22.3",
- "resolved": "https://registry.npmjs.org/@taiga-ui/stylelint-config/-/stylelint-config-0.22.3.tgz",
- "integrity": "sha512-QXb37gSmNIfa41I4nJG4rAF0rEzabN5jccz/WNNReWSi8esDjEGvUBdzxmUzDsDjnyWnqa4ItwC7Fzee88bFfQ==",
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/stylelint-config/-/stylelint-config-0.94.0.tgz",
+ "integrity": "sha512-Hzgk4AvHZ787duHH8hYNqjzO48KFvJ2AdRfUTHmERSKLUqMrieUPMNbDPdRO3zhl3kR8XAeF6wk4uLFdi1qsSA==",
"dev": true,
+ "license": "Apache-2.0",
"peerDependencies": {
"@miller-svt/stylelint-no-px": "^1.0.1",
"postcss": "^8.4.38",
@@ -9190,10 +9194,11 @@
"link": true
},
"node_modules/@taiga-ui/tsconfig": {
- "version": "0.17.0",
- "resolved": "https://registry.npmjs.org/@taiga-ui/tsconfig/-/tsconfig-0.17.0.tgz",
- "integrity": "sha512-q5lPtI7kSdf/k4Z8xXatNUEHVmKTUoaU/DRBmz1Fd+SMLbecR6V/qX1uQ5Fm4IcJBCEC13a36SrI9qTYDamv+Q==",
- "dev": true
+ "version": "0.94.0",
+ "resolved": "https://registry.npmjs.org/@taiga-ui/tsconfig/-/tsconfig-0.94.0.tgz",
+ "integrity": "sha512-yVGP2gPyXQxOb8FkU3HJv9bu9xxg+FDWPcEx0ahdCrGHfXDcG0VN0nbjhBqOwFkE+MN08aP5Dzoe8gf0gCbdUg==",
+ "dev": true,
+ "license": "Apache-2.0"
},
"node_modules/@tinkoff/ng-dompurify": {
"version": "4.0.0",
diff --git a/package.json b/package.json
index ff8d27452184..52f4c51667f8 100644
--- a/package.json
+++ b/package.json
@@ -116,13 +116,13 @@
"@nx/jest": "18.3.4",
"@nx/workspace": "18.3.4",
"@schematics/angular": "16.2.12",
- "@taiga-ui/browserslist-config": "0.6.0",
- "@taiga-ui/commitlint-config": "0.7.5",
- "@taiga-ui/cspell-config": "0.40.1",
- "@taiga-ui/eslint-plugin-experience": "0.75.4",
- "@taiga-ui/prettier-config": "0.11.9",
- "@taiga-ui/stylelint-config": "0.22.3",
- "@taiga-ui/tsconfig": "0.17.0",
+ "@taiga-ui/browserslist-config": "0.94.0",
+ "@taiga-ui/commitlint-config": "0.94.0",
+ "@taiga-ui/cspell-config": "0.94.0",
+ "@taiga-ui/eslint-plugin-experience": "0.94.0",
+ "@taiga-ui/prettier-config": "0.94.0",
+ "@taiga-ui/stylelint-config": "0.94.0",
+ "@taiga-ui/tsconfig": "0.94.0",
"@tinkoff/ng-event-plugins": "3.2.0",
"@types/glob": "8.1.0",
"@types/loader-utils": "2.0.6",