From d5d4a0eb9ac45c444432e4816ee21fa17c8d8c2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=87etin?=
<69278826+cetincakiroglu@users.noreply.github.com>
Date: Wed, 17 Jul 2024 17:03:58 +0300
Subject: [PATCH] Theming | Add radioButton, remove label and labelStyleClass,
fixes #16043
---
.../components/radiobutton/radiobutton.css | 38 -----
src/app/components/radiobutton/radiobutton.ts | 108 +++++--------
.../radiobutton/style/radiobuttonstyle.ts | 145 ++++++++++++++++++
.../showcase/doc/radiobutton/invaliddoc.ts | 4 +-
src/assets/showcase/styles/primeng.css | 1 -
5 files changed, 185 insertions(+), 111 deletions(-)
delete mode 100755 src/app/components/radiobutton/radiobutton.css
create mode 100644 src/app/components/radiobutton/style/radiobuttonstyle.ts
diff --git a/src/app/components/radiobutton/radiobutton.css b/src/app/components/radiobutton/radiobutton.css
deleted file mode 100755
index 7bd8a90360e..00000000000
--- a/src/app/components/radiobutton/radiobutton.css
+++ /dev/null
@@ -1,38 +0,0 @@
-@layer primeng {
- .p-radiobutton {
- display: inline-flex;
- cursor: pointer;
- user-select: none;
- vertical-align: bottom;
- position: relative;
- }
-
- .p-radiobutton-box {
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .p-radiobutton-icon {
- -webkit-backface-visibility: hidden;
- backface-visibility: hidden;
- transform: translateZ(0) scale(0.1);
- border-radius: 50%;
- visibility: hidden;
- }
-
- .p-radiobutton-box.p-highlight .p-radiobutton-icon {
- transform: translateZ(0) scale(1, 1);
- visibility: visible;
- }
-
- p-radiobutton {
- display: inline-flex;
- vertical-align: bottom;
- align-items: center;
- }
-
- .p-radiobutton-label {
- line-height: 1;
- }
-}
diff --git a/src/app/components/radiobutton/radiobutton.ts b/src/app/components/radiobutton/radiobutton.ts
index 14cd436f516..56ad36afca1 100755
--- a/src/app/components/radiobutton/radiobutton.ts
+++ b/src/app/components/radiobutton/radiobutton.ts
@@ -1,9 +1,10 @@
import { CommonModule } from '@angular/common';
-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Injectable, Injector, Input, NgModule, OnDestroy, OnInit, Output, ViewChild, booleanAttribute, forwardRef, numberAttribute } from '@angular/core';
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Injectable, Injector, Input, NgModule, OnDestroy, OnInit, Output, ViewChild, booleanAttribute, forwardRef, inject, numberAttribute } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import { Nullable } from 'primeng/ts-helpers';
import { AutoFocusModule } from 'primeng/autofocus';
-
+import { BaseComponent } from 'primeng/basecomponent';
+import { RadioButtonStyle } from './style/radiobuttonstyle';
import { RadioButtonClickEvent } from './radiobutton.interface';
import { PrimeNGConfig } from 'primeng/api';
@@ -57,56 +58,41 @@ export class RadioControlRegistry {
[ngClass]="{
'p-radiobutton p-component': true,
'p-radiobutton-checked': checked,
- 'p-radiobutton-disabled': disabled,
- 'p-radiobutton-focused': focused,
+ 'p-disabled': disabled,
'p-variant-filled': variant === 'filled' || config.inputStyle() === 'filled'
}"
[class]="styleClass"
[attr.data-pc-name]="'radiobutton'"
[attr.data-pc-section]="'root'"
- (click)="handleClick($event, input, true)"
>
-
-
-
-
-
`,
- providers: [RADIO_VALUE_ACCESSOR],
- changeDetection: ChangeDetectionStrategy.OnPush,
- host: {
- class: 'p-element'
- }
+ providers: [RADIO_VALUE_ACCESSOR, RadioButtonStyle],
+ changeDetection: ChangeDetectionStrategy.OnPush
})
-export class RadioButton implements ControlValueAccessor, OnInit, OnDestroy {
+export class RadioButton extends BaseComponent implements ControlValueAccessor, OnInit, OnDestroy {
/**
* Value of the radiobutton.
* @group Props
@@ -127,11 +113,6 @@ export class RadioButton implements ControlValueAccessor, OnInit, OnDestroy {
* @group Props
*/
@Input({ transform: booleanAttribute }) disabled: boolean | undefined;
- /**
- * Label of the radiobutton.
- * @group Props
- */
- @Input() label: string | undefined;
/**
* Specifies the input variant of the component.
* @group Props
@@ -167,11 +148,6 @@ export class RadioButton implements ControlValueAccessor, OnInit, OnDestroy {
* @group Props
*/
@Input() styleClass: string | undefined;
- /**
- * Style class of the label.
- * @group Props
- */
- @Input() labelStyleClass: string | undefined;
/**
* When present, it specifies that the component should automatically get focus on load.
* @group Props
@@ -208,36 +184,27 @@ export class RadioButton implements ControlValueAccessor, OnInit, OnDestroy {
control: Nullable;
- constructor(
- public cd: ChangeDetectorRef,
- private injector: Injector,
- private registry: RadioControlRegistry,
- public config: PrimeNGConfig
- ) {}
+ _componentStyle = inject(RadioButtonStyle);
+
+ injector = inject(Injector);
+
+ registry = inject(RadioControlRegistry);
ngOnInit() {
+ super.ngOnInit();
this.control = this.injector.get(NgControl);
this.checkName();
this.registry.add(this.control, this);
}
- handleClick(event: Event, radioButton: HTMLElement, focus: boolean) {
- event.preventDefault();
-
- if (this.disabled) {
- return;
- }
-
- this.select(event);
-
- if (focus) {
- radioButton.focus();
+ onChange(event) {
+ if (!this.disabled) {
+ this.select(event);
}
}
select(event: Event) {
if (!this.disabled) {
- this.inputViewChild.nativeElement.checked = true;
this.checked = true;
this.onModelChange(this.value);
this.registry.select(this);
@@ -289,6 +256,7 @@ export class RadioButton implements ControlValueAccessor, OnInit, OnDestroy {
ngOnDestroy() {
this.registry.remove(this);
+ super.ngOnDestroy();
}
private checkName() {
diff --git a/src/app/components/radiobutton/style/radiobuttonstyle.ts b/src/app/components/radiobutton/style/radiobuttonstyle.ts
new file mode 100644
index 00000000000..d2b24f06165
--- /dev/null
+++ b/src/app/components/radiobutton/style/radiobuttonstyle.ts
@@ -0,0 +1,145 @@
+import { Injectable } from '@angular/core';
+import { BaseStyle } from 'primeng/base';
+
+const theme = ({ dt }) => `
+.p-radiobutton {
+ position: relative;
+ display: inline-flex;
+ user-select: none;
+ vertical-align: bottom;
+ width: ${dt('radiobutton.width')};
+ height: ${dt('radiobutton.height')};
+}
+
+.p-radiobutton-input {
+ cursor: pointer;
+ appearance: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+ opacity: 0;
+ z-index: 1;
+ outline: 0 none;
+ border: 1px solid transparent;
+ border-radius: 50%;
+}
+
+.p-radiobutton-box {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 50%;
+ border: 1px solid ${dt('radiobutton.border.color')};
+ background: ${dt('radiobutton.background')};
+ width: ${dt('radiobutton.width')};
+ height: ${dt('radiobutton.height')};
+ transition: background ${dt('radiobutton.transition.duration')}, color ${dt('radiobutton.transition.duration')}, border-color ${dt('radiobutton.transition.duration')}, box-shadow ${dt('radiobutton.transition.duration')}, outline-color ${dt(
+ 'radiobutton.transition.duration'
+)};
+ outline-color: transparent;
+ box-shadow: ${dt('radiobutton.shadow')};
+}
+
+.p-radiobutton-icon {
+ transition-duration: ${dt('radiobutton.transition.duration')};
+ background: transparent;
+ font-size: ${dt('radiobutton.icon.size')};
+ width: ${dt('radiobutton.icon.size')};
+ height: ${dt('radiobutton.icon.size')};
+ border-radius: 50%;
+ backface-visibility: hidden;
+ transform: translateZ(0) scale(0.1);
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:hover) .p-radiobutton-box {
+ border-color: ${dt('radiobutton.hover.border.color')};
+}
+
+.p-radiobutton-checked .p-radiobutton-box {
+ border-color: ${dt('radiobutton.checked.border.color')};
+ background: ${dt('radiobutton.checked.background')};
+}
+
+.p-radiobutton-checked .p-radiobutton-box .p-radiobutton-icon {
+ background: ${dt('radiobutton.icon.checked.color')};
+ transform: translateZ(0) scale(1, 1);
+ visibility: visible;
+}
+
+.p-radiobutton-checked:not(.p-disabled):has(.p-radiobutton-input:hover) .p-radiobutton-box {
+ border-color: ${dt('radiobutton.checked.hover.border.color')};
+ background: ${dt('radiobutton.checked.hover.background')};
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:hover).p-radiobutton-checked .p-radiobutton-box .p-radiobutton-icon {
+ background: ${dt('radiobutton.icon.checked.hover.color')};
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:focus-visible) .p-radiobutton-box {
+ border-color: ${dt('radiobutton.focus.border.color')};
+ box-shadow: ${dt('radiobutton.focus.ring.shadow')};
+ outline: ${dt('radiobutton.focus.ring.width')} ${dt('radiobutton.focus.ring.style')} ${dt('radiobutton.focus.ring.color')};
+ outline-offset: ${dt('radiobutton.focus.ring.offset')};
+}
+
+.p-radiobutton-checked:not(.p-disabled):has(.p-radiobutton-input:focus-visible) .p-radiobutton-box {
+ border-color: ${dt('radiobutton.checked.focus.border.color')};
+}
+
+.p-radiobutton.ng-invalid.ng-dirty > .p-radiobutton-box {
+ border-color: ${dt('radiobutton.invalid.border.color')};
+}
+
+.p-radiobutton.p-variant-filled .p-radiobutton-box {
+ background: ${dt('radiobutton.filled.background')};
+}
+
+.p-radiobutton.p-variant-filled.p-radiobutton-checked .p-radiobutton-box {
+ background: ${dt('radiobutton.checked.background')};
+}
+
+.p-radiobutton.p-variant-filled:not(.p-disabled):has(.p-radiobutton-input:hover).p-radiobutton-checked .p-radiobutton-box {
+ background: ${dt('radiobutton.checked.hover.background')};
+}
+
+.p-radiobutton.p-disabled {
+ opacity: 1;
+}
+
+.p-radiobutton.p-disabled .p-radiobutton-box {
+ background: ${dt('radiobutton.disabled.background')};
+ border-color: ${dt('radiobutton.checked.disabled.border.color')};
+}
+
+.p-radiobutton-checked.p-disabled .p-radiobutton-box .p-radiobutton-icon {
+ background: ${dt('radiobutton.icon.disabled.color')};
+}
+`;
+
+const classes = {
+ root: ({ instance, props }) => [
+ 'p-radiobutton p-component',
+ {
+ 'p-radiobutton-checked': instance.checked,
+ 'p-disabled': props.disabled,
+ 'p-invalid': props.invalid,
+ 'p-variant-filled': props.variant ? props.variant === 'filled' : instance.$primevue.config.inputStyle === 'filled' || instance.$primevue.config.inputVariant === 'filled'
+ }
+ ],
+ box: 'p-radiobutton-box',
+ input: 'p-radiobutton-input',
+ icon: 'p-radiobutton-icon'
+};
+
+@Injectable()
+export class RadioButtonStyle extends BaseStyle {
+ name = 'radiobutton';
+
+ theme = theme;
+
+ classes = classes;
+}
diff --git a/src/app/showcase/doc/radiobutton/invaliddoc.ts b/src/app/showcase/doc/radiobutton/invaliddoc.ts
index 7b95c0b4e68..eea99b63a23 100644
--- a/src/app/showcase/doc/radiobutton/invaliddoc.ts
+++ b/src/app/showcase/doc/radiobutton/invaliddoc.ts
@@ -8,13 +8,13 @@ import { Code } from '@domain/code';
Invalid state style is added using the ng-invalid and ng-dirty class to indicate a failed validation.
`
})
export class InvalidDoc {
- checked: any;
+ checked: any = false;
code: Code = {
basic: ``,
diff --git a/src/assets/showcase/styles/primeng.css b/src/assets/showcase/styles/primeng.css
index ec8404b80f0..48beb6050ea 100755
--- a/src/assets/showcase/styles/primeng.css
+++ b/src/assets/showcase/styles/primeng.css
@@ -1,5 +1,4 @@
@import '../../../app/components/common/common.css';
@import '../../../app/components/password/password.css';
-@import '../../../app/components/radiobutton/radiobutton.css';
@import '../../../app/components/ripple/ripple.css';
@import '../../../app/components/tooltip/tooltip.css';
\ No newline at end of file