Refactor #5612 - InputSwitch / ToggleSwitch

pull/5677/head
tugcekucukoglu 2024-04-18 17:15:29 +03:00
parent 1428cc12df
commit f240b953b4
16 changed files with 384 additions and 263 deletions

View File

@ -2,207 +2,54 @@
*
* InputSwitch is used to select a boolean value.
*
* [Live Demo](https://www.primevue.org/inputswitch/)
* [Live Demo](https://www.primevue.org/toggleswitch/)
*
* @module inputswitch
*
*/
import { ComponentHooks } from '../basecomponent';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type InputSwitchPassThroughOptionType = InputSwitchPassThroughAttributes | ((options: InputSwitchPassThroughMethodOptions) => InputSwitchPassThroughAttributes | string) | string | null | undefined;
import * as ToggleSwitch from '../toggleswitch';
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
/**
* Custom passthrough(pt) option method.
*/
export interface InputSwitchPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: InputSwitchProps;
/**
* Defines current options.
*/
context: InputSwitchContext;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
export interface InputSwitchPassThroughMethodOptions extends ToggleSwitch.ToggleSwitchPassThroughMethodOptions {}
/**
* Custom passthrough(pt) options.
* @see {@link InputSwitchProps.pt}
*/
export interface InputSwitchPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: InputSwitchPassThroughOptionType;
/**
* Used to pass attributes to the input's DOM element.
*/
input?: InputSwitchPassThroughOptionType;
/**
* Used to pass attributes to the slider's DOM element.
*/
slider?: InputSwitchPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
export interface InputSwitchPassThroughOptions extends ToggleSwitch.ToggleSwitchPassThroughOptions {}
/**
* Custom passthrough attributes for each DOM elements
*/
export interface InputSwitchPassThroughAttributes {
[key: string]: any;
}
export interface InputSwitchPassThroughAttributes extends ToggleSwitch.ToggleSwitchPassThroughAttributes {}
/**
* Defines valid properties in InputSwitch component.
*/
export interface InputSwitchProps {
/**
* Specifies whether a inputswitch should be checked or not.
* @defaultValue false
*/
modelValue?: boolean | string | undefined;
/**
* Value in checked state.
* @defaultValue true
*/
trueValue?: any;
/**
* Value in unchecked state.
* @defaultValue false
*/
falseValue?: any;
/**
* When present, it specifies that the component should have invalid state style.
* @defaultValue false
*/
invalid?: boolean | undefined;
/**
* When present, it specifies that the component should be disabled.
* @defaultValue false
*/
disabled?: boolean | undefined;
/**
* When present, it specifies that an input field is read-only.
* @default false
*/
readonly?: boolean | undefined;
/**
* Index of the element in tabbing order.
*/
tabindex?: number | undefined;
/**
* Identifier of the underlying input element.
*/
inputId?: string | undefined;
/**
* Style class of the input field.
*/
inputClass?: string | object | undefined;
/**
* Inline style of the input field.
*/
inputStyle?: object | undefined;
/**
* Establishes relationships between the component and label(s) where its value should be one or more element IDs.
*/
ariaLabelledby?: string | undefined;
/**
* Establishes a string value that labels the component.
*/
ariaLabel?: string | undefined;
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {InputSwitchPassThroughOptions}
*/
pt?: PassThrough<InputSwitchPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
/**
* When enabled, it removes component related styles in the core.
* @defaultValue false
*/
unstyled?: boolean;
}
export interface InputSwitchProps extends ToggleSwitch.ToggleSwitchProps {}
/**
* Defines current options in InputSwitch component.
*/
export interface InputSwitchContext {
/**
* Current checked state of the item as a boolean.
* @defaultValue false
*/
checked: boolean;
/**
* Current disabled state of the item as a boolean.
* @defaultValue false
*/
disabled: boolean;
}
export interface InputSwitchContext extends ToggleSwitch.ToggleSwitchContext {}
export interface InputSwitchSlots {}
export interface InputSwitchSlots extends ToggleSwitch.ToggleSwitchSlots {}
/**
* Defines valid emits in InputSwitch component.
*/
export interface InputSwitchEmits {
/**
* Emitted when the value changes.
* @param {boolean} value - New value.
*/
'update:modelValue'(value: boolean): void;
/**
* Callback to invoke on value change.
* @param {Event} event - Browser event.
*/
change(event: Event): void;
/**
* Callback to invoke when the component receives focus.
* @param {Event} event - Browser event.
*/
focus(event: Event): void;
/**
* Callback to invoke when the component loses focus.
* @param {Event} event - Browser event.
*/
blur(event: Event): void;
}
export interface InputSwitchEmits extends ToggleSwitch.ToggleSwitchEmits {}
/**
* @deprecated Deprecated since v4. Use ToggleSwitch component instead.
*
* **PrimeVue - InputSwitch**
*
* _InputSwitch is used to select a boolean value._
*
* [Live Demo](https://www.primevue.org/inputswitch/)
* [Live Demo](https://www.primevue.org/toggleswitch/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*

View File

@ -1,66 +1,11 @@
<template>
<div :class="cx('root')" :style="sx('root')" v-bind="getPTOptions('root')" :data-p-highlight="checked" :data-p-disabled="disabled">
<input
:id="inputId"
type="checkbox"
role="switch"
:class="[cx('input'), inputClass]"
:style="inputStyle"
:checked="checked"
:tabindex="tabindex"
:disabled="disabled"
:readonly="readonly"
:aria-checked="checked"
:aria-labelledby="ariaLabelledby"
:aria-label="ariaLabel"
:aria-invalid="invalid || undefined"
@focus="onFocus"
@blur="onBlur"
@change="onChange"
v-bind="getPTOptions('input')"
/>
<span :class="cx('slider')" v-bind="getPTOptions('slider')"></span>
</div>
</template>
<script>
import BaseInputSwitch from './BaseInputSwitch.vue';
import ToggleSwitch from 'primevue/toggleswitch';
export default {
name: 'InputSwitch',
extends: BaseInputSwitch,
inheritAttrs: false,
emits: ['update:modelValue', 'change', 'focus', 'blur'],
methods: {
getPTOptions(key) {
const _ptm = key === 'root' ? this.ptmi : this.ptm;
return _ptm(key, {
context: {
checked: this.checked,
disabled: this.disabled
}
});
},
onChange(event) {
if (!this.disabled && !this.readonly) {
const newValue = this.checked ? this.falseValue : this.trueValue;
this.$emit('update:modelValue', newValue);
this.$emit('change', event);
}
},
onFocus(event) {
this.$emit('focus', event);
},
onBlur(event) {
this.$emit('blur', event);
}
},
computed: {
checked() {
return this.modelValue === this.trueValue;
}
extends: ToggleSwitch,
mounted() {
console.warn('Deprecated since v4. Use ToggleSwitch component instead.');
}
};
</script>

View File

@ -1,3 +1,3 @@
import { BaseStyle } from '../../base/style';
import { ToggleSwitchStyle } from '../../toggleswitch/style/ToggleSwitchStyle';
export interface InputSwitchStyle extends BaseStyle {}
export interface InputSwitchStyle extends ToggleSwitchStyle {}

View File

@ -1,24 +1,5 @@
import BaseStyle from 'primevue/base/style';
const inlineStyles = {
root: { position: 'relative' }
};
const classes = {
root: ({ instance, props }) => [
'p-toggleswitch p-component',
{
'p-toggleswitch-checked': instance.checked,
'p-disabled': props.disabled,
'p-invalid': props.invalid
}
],
input: 'p-toggleswitch-input',
slider: 'p-toggleswitch-slider'
};
export default BaseStyle.extend({
name: 'inputswitch',
classes,
inlineStyles
name: 'inputswitch'
});

View File

@ -19,7 +19,7 @@ export default {
opacity: 0;
z-index: 1;
outline: 0 none;
border-radius: ${dt('inputswitch.border.radius')};
border-radius: ${dt('toggleswitch.border.radius')};
}
.p-toggleswitch-slider {
@ -30,9 +30,9 @@ export default {
right: 0;
bottom: 0;
border: 0 none;
background: ${dt('inputswitch.background')};
background: ${dt('toggleswitch.background')};
transition: background ${dt('transition.duration')}, color ${dt('transition.duration')}, border-color ${dt('transition.duration')}, box-shadow ${dt('transition.duration')}, outline-color ${dt('transition.duration')};
border-radius: ${dt('inputswitch.border.radius')};
border-radius: ${dt('toggleswitch.border.radius')};
outline-color: transparent;
}
@ -40,38 +40,38 @@ export default {
position: absolute;
content: "";
top: 50%;
background: ${dt('inputswitch.handle.background')};
background: ${dt('toggleswitch.handle.background')};
width: 1rem;
height: 1rem;
left: 0.25rem;
margin-top: -0.5rem;
border-radius: ${dt('inputswitch.handle.border.radius')};
border-radius: ${dt('toggleswitch.handle.border.radius')};
transition: all ${dt('transition.duration')};
}
.p-toggleswitch.p-toggleswitch-checked .p-toggleswitch-slider {
background: ${dt('inputswitch.checked.background')};
background: ${dt('toggleswitch.checked.background')};
}
.p-toggleswitch.p-toggleswitch-checked .p-toggleswitch-slider:before {
background: ${dt('inputswitch.handle.checked.background')};
background: ${dt('toggleswitch.handle.checked.background')};
left: 1.25rem;
}
.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover) .p-toggleswitch-slider {
background: ${dt('inputswitch.hover.background')};
background: ${dt('toggleswitch.hover.background')};
}
.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover) .p-toggleswitch-slider:before {
background: ${dt('inputswitch.handle.hover.background')};
background: ${dt('toggleswitch.handle.hover.background')};
}
.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover).p-toggleswitch-checked .p-toggleswitch-slider {
background: ${dt('inputswitch.checked.hover.background')};
background: ${dt('toggleswitch.checked.hover.background')};
}
.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover).p-toggleswitch-checked .p-toggleswitch-slider:before {
background: ${dt('inputswitch.handle.checked.hover.background')};
background: ${dt('toggleswitch.handle.checked.hover.background')};
}
.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:focus-visible) .p-toggleswitch-slider {
@ -80,11 +80,11 @@ export default {
}
.p-toggleswitch.p-invalid > .p-toggleswitch-slider {
background: ${dt('inputswitch.invalid.background')};
background: ${dt('toggleswitch.invalid.background')};
}
.p-toggleswitch.p-invalid > .p-toggleswitch-slider:before {
background: ${dt('inputswitch.handle.invalid.background')};
background: ${dt('toggleswitch.handle.invalid.background')};
}
`
};

View File

@ -1,9 +1,9 @@
<script>
import BaseComponent from 'primevue/basecomponent';
import InputSwitchStyle from 'primevue/inputswitch/style';
import ToggleSwitchStyle from 'primevue/toggleswitch/style';
export default {
name: 'BaseInputSwitch',
name: 'BaseToggleSwitch',
extends: BaseComponent,
props: {
modelValue: {
@ -55,7 +55,7 @@ export default {
default: null
}
},
style: InputSwitchStyle,
style: ToggleSwitchStyle,
provide() {
return {
$parentInstance: this

220
components/lib/toggleswitch/ToggleSwitch.d.ts vendored Executable file
View File

@ -0,0 +1,220 @@
/**
*
* ToggleSwitch is used to select a boolean value.
*
* [Live Demo](https://www.primevue.org/toggleswitch/)
*
* @module toggleswitch
*
*/
import { ComponentHooks } from '../basecomponent';
import { PassThroughOptions } from '../passthrough';
import { ClassComponent, DesignToken, GlobalComponentConstructor, PassThrough } from '../ts-helpers';
export declare type ToggleSwitchPassThroughOptionType = ToggleSwitchPassThroughAttributes | ((options: ToggleSwitchPassThroughMethodOptions) => ToggleSwitchPassThroughAttributes | string) | string | null | undefined;
/**
* Custom passthrough(pt) option method.
*/
export interface ToggleSwitchPassThroughMethodOptions {
/**
* Defines instance.
*/
instance: any;
/**
* Defines valid properties.
*/
props: ToggleSwitchProps;
/**
* Defines current options.
*/
context: ToggleSwitchContext;
/**
* Defines valid attributes.
*/
attrs: any;
/**
* Defines parent options.
*/
parent: any;
/**
* Defines passthrough(pt) options in global config.
*/
global: object | undefined;
}
/**
* Custom passthrough(pt) options.
* @see {@link ToggleSwitchProps.pt}
*/
export interface ToggleSwitchPassThroughOptions {
/**
* Used to pass attributes to the root's DOM element.
*/
root?: ToggleSwitchPassThroughOptionType;
/**
* Used to pass attributes to the input's DOM element.
*/
input?: ToggleSwitchPassThroughOptionType;
/**
* Used to pass attributes to the slider's DOM element.
*/
slider?: ToggleSwitchPassThroughOptionType;
/**
* Used to manage all lifecycle hooks.
* @see {@link BaseComponent.ComponentHooks}
*/
hooks?: ComponentHooks;
}
/**
* Custom passthrough attributes for each DOM elements
*/
export interface ToggleSwitchPassThroughAttributes {
[key: string]: any;
}
/**
* Defines valid properties in ToggleSwitch component.
*/
export interface ToggleSwitchProps {
/**
* Specifies whether a toggleswitch should be checked or not.
* @defaultValue false
*/
modelValue?: boolean | string | undefined;
/**
* Value in checked state.
* @defaultValue true
*/
trueValue?: any;
/**
* Value in unchecked state.
* @defaultValue false
*/
falseValue?: any;
/**
* When present, it specifies that the component should have invalid state style.
* @defaultValue false
*/
invalid?: boolean | undefined;
/**
* When present, it specifies that the component should be disabled.
* @defaultValue false
*/
disabled?: boolean | undefined;
/**
* When present, it specifies that an input field is read-only.
* @default false
*/
readonly?: boolean | undefined;
/**
* Index of the element in tabbing order.
*/
tabindex?: number | undefined;
/**
* Identifier of the underlying input element.
*/
inputId?: string | undefined;
/**
* Style class of the input field.
*/
inputClass?: string | object | undefined;
/**
* Inline style of the input field.
*/
inputStyle?: object | undefined;
/**
* Establishes relationships between the component and label(s) where its value should be one or more element IDs.
*/
ariaLabelledby?: string | undefined;
/**
* Establishes a string value that labels the component.
*/
ariaLabel?: string | undefined;
/**
* It generates scoped CSS variables using design tokens for the component.
*/
dt?: DesignToken<any>;
/**
* Used to pass attributes to DOM elements inside the component.
* @type {ToggleSwitchPassThroughOptions}
*/
pt?: PassThrough<ToggleSwitchPassThroughOptions>;
/**
* Used to configure passthrough(pt) options of the component.
* @type {PassThroughOptions}
*/
ptOptions?: PassThroughOptions;
/**
* When enabled, it removes component related styles in the core.
* @defaultValue false
*/
unstyled?: boolean;
}
/**
* Defines current options in ToggleSwitch component.
*/
export interface ToggleSwitchContext {
/**
* Current checked state of the item as a boolean.
* @defaultValue false
*/
checked: boolean;
/**
* Current disabled state of the item as a boolean.
* @defaultValue false
*/
disabled: boolean;
}
export interface ToggleSwitchSlots {}
/**
* Defines valid emits in ToggleSwitch component.
*/
export interface ToggleSwitchEmits {
/**
* Emitted when the value changes.
* @param {boolean} value - New value.
*/
'update:modelValue'(value: boolean): void;
/**
* Callback to invoke on value change.
* @param {Event} event - Browser event.
*/
change(event: Event): void;
/**
* Callback to invoke when the component receives focus.
* @param {Event} event - Browser event.
*/
focus(event: Event): void;
/**
* Callback to invoke when the component loses focus.
* @param {Event} event - Browser event.
*/
blur(event: Event): void;
}
/**
* **PrimeVue - ToggleSwitch**
*
* _ToggleSwitch is used to select a boolean value._
*
* [Live Demo](https://www.primevue.org/toggleswitch/)
* --- ---
* ![PrimeVue](https://primefaces.org/cdn/primevue/images/logo-100.png)
*
* @group Component
*
*/
declare class ToggleSwitch extends ClassComponent<ToggleSwitchProps, ToggleSwitchSlots, ToggleSwitchEmits> {}
declare module 'vue' {
export interface GlobalComponents {
ToggleSwitch: GlobalComponentConstructor<ToggleSwitch>;
}
}
export default ToggleSwitch;

View File

@ -0,0 +1,20 @@
import { mount } from '@vue/test-utils';
import ToggleSwitch from './ToggleSwitch.vue';
describe('ToggleSwitch.vue', () => {
it('should exist', async () => {
const wrapper = mount(ToggleSwitch);
expect(wrapper.find('.p-toggleswitch.p-component').exists()).toBe(true);
expect(wrapper.find('.p-toggleswitch-slider').exists()).toBe(true);
await wrapper.vm.onChange({});
expect(wrapper.emitted()['update:modelValue'][0]).toEqual([true]);
await wrapper.setProps({ modelValue: true });
expect(wrapper.vm.checked).toBe(true);
expect(wrapper.find('.p-toggleswitch').classes()).toContain('p-highlight');
});
});

View File

@ -0,0 +1,66 @@
<template>
<div :class="cx('root')" :style="sx('root')" v-bind="getPTOptions('root')" :data-p-highlight="checked" :data-p-disabled="disabled">
<input
:id="inputId"
type="checkbox"
role="switch"
:class="[cx('input'), inputClass]"
:style="inputStyle"
:checked="checked"
:tabindex="tabindex"
:disabled="disabled"
:readonly="readonly"
:aria-checked="checked"
:aria-labelledby="ariaLabelledby"
:aria-label="ariaLabel"
:aria-invalid="invalid || undefined"
@focus="onFocus"
@blur="onBlur"
@change="onChange"
v-bind="getPTOptions('input')"
/>
<span :class="cx('slider')" v-bind="getPTOptions('slider')"></span>
</div>
</template>
<script>
import BaseToggleSwitch from './BaseToggleSwitch.vue';
export default {
name: 'ToggleSwitch',
extends: BaseToggleSwitch,
inheritAttrs: false,
emits: ['update:modelValue', 'change', 'focus', 'blur'],
methods: {
getPTOptions(key) {
const _ptm = key === 'root' ? this.ptmi : this.ptm;
return _ptm(key, {
context: {
checked: this.checked,
disabled: this.disabled
}
});
},
onChange(event) {
if (!this.disabled && !this.readonly) {
const newValue = this.checked ? this.falseValue : this.trueValue;
this.$emit('update:modelValue', newValue);
this.$emit('change', event);
}
},
onFocus(event) {
this.$emit('focus', event);
},
onBlur(event) {
this.$emit('blur', event);
}
},
computed: {
checked() {
return this.modelValue === this.trueValue;
}
}
};
</script>

View File

@ -0,0 +1,9 @@
{
"main": "./toggleswitch.cjs.js",
"module": "./toggleswitch.esm.js",
"unpkg": "./toggleswitch.min.js",
"types": "./ToggleSwitch.d.ts",
"browser": {
"./sfc": "./ToggleSwitch.vue"
}
}

View File

@ -0,0 +1,3 @@
import { BaseStyle } from '../../base/style';
export interface ToggleSwitchStyle extends BaseStyle {}

View File

@ -0,0 +1,24 @@
import BaseStyle from 'primevue/base/style';
const inlineStyles = {
root: { position: 'relative' }
};
const classes = {
root: ({ instance, props }) => [
'p-toggleswitch p-component',
{
'p-toggleswitch-checked': instance.checked,
'p-disabled': props.disabled,
'p-invalid': props.invalid
}
],
input: 'p-toggleswitch-input',
slider: 'p-toggleswitch-slider'
};
export default BaseStyle.extend({
name: 'toggleswitch',
classes,
inlineStyles
});

View File

@ -0,0 +1,6 @@
{
"main": "./toggleswitchstyle.cjs.js",
"module": "./toggleswitchstyle.esm.js",
"unpkg": "./toggleswitchstyle.min.js",
"types": "./ToggleSwitchStyle.d.ts"
}