diff --git a/AGENTS.md b/AGENTS.md index 500136c4a0f..5b719511206 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -226,7 +226,7 @@ The samples are located in `packages/samples/react` and demonstrate how to use t - Formatting is enforced via **Prettier** with settings defined in `prettier.config.js` (print width 160, single quotes, tabs). - `.editorconfig` sets `indent_style = tab` and `max_line_length = 160` for code files. Markdown and YAML files use spaces. -- ESLint and Stylelint are run using `pnpm lint`. Pre‑commit hooks run `lint-staged` which formats and lints changed files. +- ESLint and Stylelint are run using `pnpm lint`. Pre‑commit hooks run `lint-staged` which formats and lints changed files. Lint rules should **not** be disabled via inline comments. Instead, describe the problem and work towards a clean solution. - Lists and enumerations in code should be kept in alphanumeric order. This also applies to import specifiers and union type literals. - Commit messages follow the **Conventional Commits** specification. - See also the [Contributing Guide](CONTRIBUTING.md) for more details on coding conventions and best practices. diff --git a/packages/components/AGENTS.md b/packages/components/AGENTS.md index eeb1c676e3a..ec7f5fe71eb 100644 --- a/packages/components/AGENTS.md +++ b/packages/components/AGENTS.md @@ -57,6 +57,14 @@ To make the components easier to learn, property names and their descriptions sh - Whenever possible, keep the types of identical property names the same. - Minimize the number of different properties, descriptions and types. +#### Props Handling + +Every property lives in a dedicated file under `src/schema/props`. The file +contains the prop type, the prop schema and a validator function. Components and +their controllers must import these validators instead of implementing custom +logic. Always use the validator exported from the prop schema to keep behaviour +consistent across components. + #### Open vs Show Use `_open` when the component renders an element on demand, for example a drawer or popover that appears from nothing. Use `_show` when the element already exists in the DOM and you only toggle its visibility. diff --git a/packages/components/src/components/@deprecated/input/controller.ts b/packages/components/src/components/@deprecated/input/controller.ts index e052a7274cf..215fdfb3744 100644 --- a/packages/components/src/components/@deprecated/input/controller.ts +++ b/packages/components/src/components/@deprecated/input/controller.ts @@ -18,23 +18,23 @@ import type { } from '../../../schema'; import { a11yHint, - a11yHintDisabled, devHint, objectObjectHandler, parseJson, setState, validateAccessKey, validateAdjustHeight, + validateDisabled, validateHideMsg, validateHideLabel, validateLabelWithExpertSlot, validateMsg, + validateHint, validateShortKey, - validateTabIndex, validateTooltipAlign, - watchBoolean, watchString, } from '../../../schema'; +import { validateTabIndex } from '../../../schema/props/tab-index'; import { dispatchDomEvent, KolEvent } from '../../../utils/events'; import { ControlledInputController } from '../../input-adapter-leanup/controller'; @@ -66,10 +66,7 @@ export class InputController extends ControlledInputController implements Watche } public validateDisabled(value?: DisabledPropType): void { - watchBoolean(this.component, '_disabled', value); - if (value === true) { - a11yHintDisabled(); - } + validateDisabled(this.component, value); } public validateTooltipAlign(value?: TooltipAlignPropType): void { validateTooltipAlign(this.component, value); @@ -100,7 +97,7 @@ export class InputController extends ControlledInputController implements Watche } public validateHint(value?: HintPropType): void { - watchString(this.component, '_hint', value); + validateHint(this.component, value); } public validateId(value?: string): void { diff --git a/packages/components/src/components/alert/component.tsx b/packages/components/src/components/alert/component.tsx index d685932d766..f57c8f22eb2 100644 --- a/packages/components/src/components/alert/component.tsx +++ b/packages/components/src/components/alert/component.tsx @@ -1,8 +1,17 @@ import type { JSX } from '@stencil/core'; -import { alertTypeOptions, alertVariantOptions, setState, validateHasCloser, validateLabel, watchBoolean, watchValidator } from '../../schema'; +import { setState, validateAlertType, validateAlertVariant, validateHasCloser, validateLabel, watchBoolean } from '../../schema'; import { Component, Element, h, Prop, State, Watch } from '@stencil/core'; import { watchHeadingLevel } from '../heading/validation'; -import type { AlertAPI, AlertStates, AlertType, AlertVariant, HasCloserPropType, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '../../schema'; +import type { + AlertAPI, + AlertStates, + AlertTypePropType, + AlertVariantPropType, + HasCloserPropType, + HeadingLevel, + KoliBriAlertEventCallbacks, + LabelPropType, +} from '../../schema'; import KolAlertFc, { type KolAlertFcProps } from '../../functional-components/Alert'; import { dispatchDomEvent, KolEvent } from '../../utils/events'; @@ -78,12 +87,12 @@ export class KolAlertWc implements AlertAPI { /** * Defines either the type of the component or of the components interactive element. */ - @Prop() public _type?: AlertType = 'default'; + @Prop() public _type?: AlertTypePropType = 'default'; /** * Defines which variant should be used for presentation. */ - @Prop() public _variant?: AlertVariant = 'msg'; + @Prop() public _variant?: AlertVariantPropType = 'msg'; @State() public state: AlertStates = { _level: 0, @@ -137,25 +146,13 @@ export class KolAlertWc implements AlertAPI { } @Watch('_type') - public validateType(value?: AlertType): void { - watchValidator( - this, - '_type', - (value?) => typeof value === 'string' && alertTypeOptions.includes(value), - new Set(`String {${alertTypeOptions.join(', ')}`), - value, - ); + public validateType(value?: AlertTypePropType): void { + validateAlertType(this, value); } @Watch('_variant') - public validateVariant(value?: AlertVariant): void { - watchValidator( - this, - '_variant', - (value?) => typeof value === 'string' && alertVariantOptions.includes(value), - new Set(`AlertVariant {${alertVariantOptions.join(', ')}`), - value, - ); + public validateVariant(value?: AlertVariantPropType): void { + validateAlertVariant(this, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/alert/shadow.tsx b/packages/components/src/components/alert/shadow.tsx index 5d666f80a86..3027d290ddc 100644 --- a/packages/components/src/components/alert/shadow.tsx +++ b/packages/components/src/components/alert/shadow.tsx @@ -1,4 +1,4 @@ -import type { AlertProps, AlertStates, AlertType, AlertVariant, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '../../schema'; +import type { AlertProps, AlertStates, AlertTypePropType, AlertVariantPropType, HeadingLevel, KoliBriAlertEventCallbacks, LabelPropType } from '../../schema'; import type { JSX } from '@stencil/core'; import { Component, h, Prop, State } from '@stencil/core'; import { KolAlertWcTag } from '../../core/component-names'; @@ -59,12 +59,12 @@ export class KolAlert implements AlertProps { /** * Defines either the type of the component or of the components interactive element. */ - @Prop() public _type?: AlertType = 'default'; + @Prop() public _type?: AlertTypePropType = 'default'; /** * Defines which variant should be used for presentation. */ - @Prop() public _variant?: AlertVariant = 'msg'; + @Prop() public _variant?: AlertVariantPropType = 'msg'; @State() public state: AlertStates = { _level: 0, diff --git a/packages/components/src/components/button/component.tsx b/packages/components/src/components/button/component.tsx index 37ebcf700ce..feddeb98571 100644 --- a/packages/components/src/components/button/component.tsx +++ b/packages/components/src/components/button/component.tsx @@ -43,10 +43,10 @@ import { validateIcons, validateLabelWithExpertSlot, validateShortKey, - validateTabIndex, validateTooltipAlign, watchString, } from '../../schema'; +import { validateTabIndex } from '../../schema/props/tab-index'; import type { JSX } from '@stencil/core'; import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core'; diff --git a/packages/components/src/components/combobox/controller.ts b/packages/components/src/components/combobox/controller.ts index d6c5db8caa7..98e5c363c3c 100644 --- a/packages/components/src/components/combobox/controller.ts +++ b/packages/components/src/components/combobox/controller.ts @@ -1,5 +1,5 @@ -import type { ComboboxWatches, ComboboxProps, SuggestionsPropType } from '../../schema'; -import { watchBoolean, validateSuggestions, watchString } from '../../schema'; +import type { ComboboxProps, ComboboxWatches, PlaceholderPropType, RequiredPropType, SuggestionsPropType } from '../../schema'; +import { validatePlaceholder, validateRequired, validateSuggestions, watchString } from '../../schema'; import { InputIconController } from '../@deprecated/input/controller-icon'; @@ -13,11 +13,12 @@ export class ComboboxController extends InputIconController implements ComboboxW this.component = component; } - public validatePlaceholder(value?: string): void { - watchString(this.component, '_placeholder', value); + public validatePlaceholder(value?: PlaceholderPropType): void { + validatePlaceholder(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateSuggestions(value?: SuggestionsPropType): void { diff --git a/packages/components/src/components/combobox/shadow.tsx b/packages/components/src/components/combobox/shadow.tsx index 46bcbfa9f22..5fc93dd7db0 100644 --- a/packages/components/src/components/combobox/shadow.tsx +++ b/packages/components/src/components/combobox/shadow.tsx @@ -1,37 +1,39 @@ import type { JSX } from '@stencil/core'; import { Component, Element, h, Listen, Method, Prop, State, Watch } from '@stencil/core'; +import clsx from 'clsx'; +import { getRenderStates } from '../../functional-component-wrappers/_helpers/getRenderStates'; +import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; +import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; +import type { InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; +import KolInputStateWrapperFc from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; +import CustomSuggestionsOptionFc from '../../functional-components/CustomSuggestionsOption/CustomSuggestionsOption'; +import CustomSuggestionsOptionsGroupFc from '../../functional-components/CustomSuggestionsOptionsGroup'; +import CustomSuggestionsToggleFc from '../../functional-components/CustomSuggestionsToggle'; import type { ComboboxAPI, ComboboxStates, + DisabledPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputTypeOnDefault, LabelWithExpertSlotPropType, MsgPropType, NamePropType, + PlaceholderPropType, + RequiredPropType, ShortKeyPropType, Stringified, SuggestionsPropType, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, W3CInputValue, } from '../../schema'; -import clsx from 'clsx'; +import type { EventDetail } from '../../schema/interfaces/EventDetail'; import { nonce } from '../../utils/dev.utils'; -import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; import { ComboboxController } from './controller'; -import { getRenderStates } from '../../functional-component-wrappers/_helpers/getRenderStates'; -import type { InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; -import KolInputStateWrapperFc from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; -import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; -import CustomSuggestionsToggleFc from '../../functional-components/CustomSuggestionsToggle'; -import CustomSuggestionsOptionFc from '../../functional-components/CustomSuggestionsOption/CustomSuggestionsOption'; -import CustomSuggestionsOptionsGroupFc from '../../functional-components/CustomSuggestionsOptionsGroup'; -import type { EventDetail } from '../../schema/interfaces/EventDetail'; /** * @slot - Die Beschriftung des Eingabefeldes. @@ -490,7 +492,7 @@ export class KolCombobox implements ComboboxAPI { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @@ -561,7 +563,7 @@ export class KolCombobox implements ComboboxAPI { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/heading/validation.ts b/packages/components/src/components/heading/validation.ts index 9d8746d3694..a3a429af00f 100644 --- a/packages/components/src/components/heading/validation.ts +++ b/packages/components/src/components/heading/validation.ts @@ -1,21 +1,8 @@ import type { HeadingLevel } from '../../schema'; -import { headingLevelOptions, watchValidator } from '../../schema'; +import { validateLevel } from '../../schema'; import type { Generic } from 'adopted-style-sheets'; export const watchHeadingLevel = (component: Generic.Element.Component, value?: HeadingLevel): void => { - watchValidator( - component, - '_level', - (value?: HeadingLevel): boolean => { - return typeof value === 'number' && headingLevelOptions.includes(value); - }, - new Set([`Number {${headingLevelOptions.join(', ')}`]), - value, - { - // TODO: options not in the validator - defaultValue: 1, - required: true, - }, - ); + validateLevel(component, value); }; diff --git a/packages/components/src/components/input-checkbox/controller.ts b/packages/components/src/components/input-checkbox/controller.ts index a636a191b14..f6865373460 100644 --- a/packages/components/src/components/input-checkbox/controller.ts +++ b/packages/components/src/components/input-checkbox/controller.ts @@ -2,15 +2,15 @@ import type { CheckedPropType, IndeterminatePropType, InputCheckboxIconsProp, + InputCheckboxIconsPropType, InputCheckboxIconsState, InputCheckboxProps, - InputCheckboxVariant, + InputCheckboxVariantPropType, InputCheckboxWatches, LabelAlignPropType, StencilUnknown, - Stringified, } from '../../schema'; -import { inputCheckboxVariantOptions, isString, setState, validateChecked, validateIndeterminate, validateLabelAlign, watchValidator } from '../../schema'; +import { isString, setState, validateChecked, validateIndeterminate, validateLabelAlign, validateVariantInputCheckbox, watchValidator } from '../../schema'; import { InputCheckboxRadioController } from '../input-radio/controller'; @@ -36,12 +36,13 @@ export class InputCheckboxController extends InputCheckboxRadioController implem this.setFormAssociatedCheckboxValue(this.component.state._value as StencilUnknown); } - public validateIcons(value?: Stringified): void { + public validateIcons(value?: InputCheckboxIconsPropType): void { watchValidator( this.component, '_icons', (value): boolean => { - return typeof value === 'object' && value !== null && (isString(value.checked, 1) || isString(value.indeterminate, 1) || isString(value.unchecked, 1)); + const v = value as Record; + return typeof v === 'object' && v !== null && (isString(v.checked, 1) || isString(v.indeterminate, 1) || isString(v.unchecked, 1)); }, new Set(['InputCheckboxIcons']), value, @@ -71,14 +72,8 @@ export class InputCheckboxController extends InputCheckboxRadioController implem this.setFormAssociatedCheckboxValue(this.component.state._value as StencilUnknown); } - public validateVariant(value?: InputCheckboxVariant): void { - watchValidator( - this.component, - '_variant', - (value): boolean => typeof value === 'string' && inputCheckboxVariantOptions.includes(value), - new Set([`String {${inputCheckboxVariantOptions.join(', ')}`]), - value, - ); + public validateVariant(value?: InputCheckboxVariantPropType): void { + validateVariantInputCheckbox(this.component, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/input-checkbox/shadow.tsx b/packages/components/src/components/input-checkbox/shadow.tsx index cd46faa347e..cef500be138 100644 --- a/packages/components/src/components/input-checkbox/shadow.tsx +++ b/packages/components/src/components/input-checkbox/shadow.tsx @@ -5,37 +5,38 @@ import clsx from 'clsx'; import type { CheckedPropType, + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IdPropType, IndeterminatePropType, InputCheckboxAPI, InputCheckboxIconsProp, InputCheckboxStates, - InputCheckboxVariant, InputTypeOnDefault, LabelAlignPropType, LabelWithExpertSlotPropType, MsgPropType, NamePropType, + RequiredPropType, ShortKeyPropType, StencilUnknown, Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import { nonce } from '../../utils/dev.utils'; import { InputCheckboxController } from './controller'; -import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; +import KolCheckboxStateWrapperFc, { type CheckboxStateWrapperProps } from '../../functional-component-wrappers/CheckboxStateWrapper/CheckboxStateWrapper'; import KolFieldControlStateWrapperFc, { type FieldControlStateWrapperProps, } from '../../functional-component-wrappers/FieldControlStateWrapper/FieldControlStateWrapper'; -import KolCheckboxStateWrapperFc, { type CheckboxStateWrapperProps } from '../../functional-component-wrappers/CheckboxStateWrapper/CheckboxStateWrapper'; +import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; +import type { InputCheckboxVariantPropType } from '../../schema/props/variant-input-checkbox'; /** * @slot expert - Checkbox description. @@ -255,7 +256,7 @@ export class KolInputCheckbox implements InputCheckboxAPI, FocusableElement { /** * Defines which variant should be used for presentation. */ - @Prop() public _variant?: InputCheckboxVariant = 'default'; + @Prop() public _variant?: InputCheckboxVariantPropType = 'default'; @State() public state: InputCheckboxStates = { _checked: false, @@ -354,7 +355,7 @@ export class KolInputCheckbox implements InputCheckboxAPI, FocusableElement { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } @@ -379,7 +380,7 @@ export class KolInputCheckbox implements InputCheckboxAPI, FocusableElement { } @Watch('_variant') - public validateVariant(value?: InputCheckboxVariant): void { + public validateVariant(value?: InputCheckboxVariantPropType): void { this.controller.validateVariant(value); } diff --git a/packages/components/src/components/input-date/controller.ts b/packages/components/src/components/input-date/controller.ts index d44ebea692a..5e5f873d84d 100644 --- a/packages/components/src/components/input-date/controller.ts +++ b/packages/components/src/components/input-date/controller.ts @@ -1,16 +1,17 @@ import type { AutoCompletePropType, InputDateProps, - InputDateType, InputDateWatches, InputTypeOnDefault, Iso8601, NumberString, ReadOnlyPropType, + RequiredPropType, SuggestionsPropType, } from '../../schema'; -import { inputDateTypeOptions, setState, validateReadOnly, validateSuggestions, watchBoolean, watchValidator } from '../../schema'; +import { setState, validateReadOnly, validateRequired, validateSuggestions, watchValidator } from '../../schema'; import { validateAutoComplete } from '../../schema/props/auto-complete'; +import { type InputDateTypePropType, validateTypeInputDate } from '../../schema/props/type-input-date'; import { InputIconController } from '../@deprecated/input/controller-icon'; @@ -41,7 +42,7 @@ export class InputDateController extends InputIconController implements InputDat validateSuggestions(this.component, value); } - public static tryParseToString(value: Iso8601 | Date | null | undefined, type?: InputDateType, step?: string | number): string | null | undefined { + public static tryParseToString(value: Iso8601 | Date | null | undefined, type?: InputDateTypePropType, step?: string | number): string | null | undefined { if (typeof value === 'string' || value === null) { return value; } @@ -185,22 +186,16 @@ export class InputDateController extends InputIconController implements InputDat validateReadOnly(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateStep(value?: number | NumberString): void { this.validateNumber('_step', value); } - public validateType(value?: InputDateType): void { - watchValidator( - this.component, - '_type', - (value): boolean => typeof value === 'string' && inputDateTypeOptions.includes(value), - new Set([`String {${inputDateTypeOptions.join(', ')}`]), - value, - ); + public validateType(value?: InputDateTypePropType): void { + validateTypeInputDate(this.component, value); } public validateValue(value?: Iso8601 | Date | null): void { diff --git a/packages/components/src/components/input-date/shadow.tsx b/packages/components/src/components/input-date/shadow.tsx index d6ef358d2c3..893986bb105 100644 --- a/packages/components/src/components/input-date/shadow.tsx +++ b/packages/components/src/components/input-date/shadow.tsx @@ -5,13 +5,16 @@ import clsx from 'clsx'; import type { AutoCompletePropType, ButtonProps, + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputDateAPI, InputDateStates, - InputDateType, + InputDateTypePropType, InputTypeOnDefault, Iso8601, LabelWithExpertSlotPropType, @@ -19,14 +22,12 @@ import type { NamePropType, NumberString, ReadOnlyPropType, + RequiredPropType, ShortKeyPropType, Stringified, SuggestionsPropType, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import { deprecatedHint } from '../../schema'; @@ -298,7 +299,7 @@ export class KolInputDate implements InputDateAPI, FocusableElement { /** * Defines either the type of the component or of the components interactive element. */ - @Prop() public _type: InputDateType = 'date'; + @Prop() public _type: InputDateTypePropType = 'date'; /** * Defines the value of the input. @@ -400,7 +401,7 @@ export class KolInputDate implements InputDateAPI, FocusableElement { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } @@ -435,7 +436,7 @@ export class KolInputDate implements InputDateAPI, FocusableElement { } @Watch('_type') - public validateType(value?: InputDateType): void { + public validateType(value?: InputDateTypePropType): void { this.controller.validateType(value); } diff --git a/packages/components/src/components/input-email/shadow.tsx b/packages/components/src/components/input-email/shadow.tsx index e394c8cefe0..6e0f9d1daf7 100644 --- a/packages/components/src/components/input-email/shadow.tsx +++ b/packages/components/src/components/input-email/shadow.tsx @@ -5,27 +5,30 @@ import clsx from 'clsx'; import type { AutoCompletePropType, ButtonProps, + DisabledPropType, FocusableElement, + HasCounterPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputEmailAPI, InputEmailStates, InputTypeOnDefault, LabelWithExpertSlotPropType, - MsgPropType, MaxLengthBehaviorPropType, + MsgPropType, MultiplePropType, NamePropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, ShortKeyPropType, Stringified, SuggestionsPropType, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HasCounterPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; @@ -372,17 +375,17 @@ export class KolInputEmail implements InputEmailAPI, FocusableElement { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @Watch('_readOnly') - public validateReadOnly(value?: boolean): void { + public validateReadOnly(value?: ReadOnlyPropType): void { this.controller.validateReadOnly(value); } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/input-file/controller.ts b/packages/components/src/components/input-file/controller.ts index e1430664140..e30b28e6f61 100644 --- a/packages/components/src/components/input-file/controller.ts +++ b/packages/components/src/components/input-file/controller.ts @@ -1,7 +1,7 @@ import type { Generic } from 'adopted-style-sheets'; -import type { InputFileProps, InputFileWatches } from '../../schema'; -import { watchBoolean, watchString } from '../../schema'; +import type { AcceptPropType, InputFileProps, InputFileWatches, MultiplePropType, RequiredPropType } from '../../schema'; +import { validateAccept, validateMultiple, validateRequired } from '../../schema'; import { InputIconController } from '../@deprecated/input/controller-icon'; @@ -13,16 +13,16 @@ export class InputFileController extends InputIconController implements InputFil this.component = component; } - public validateAccept(value?: string): void { - watchString(this.component, '_accept', value); + public validateAccept(value?: AcceptPropType): void { + validateAccept(this.component, value); } - public validateMultiple(value?: boolean): void { - watchBoolean(this.component, '_multiple', value); + public validateMultiple(value?: MultiplePropType): void { + validateMultiple(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/input-file/shadow.tsx b/packages/components/src/components/input-file/shadow.tsx index 1888cb2f741..2e347b62720 100644 --- a/packages/components/src/components/input-file/shadow.tsx +++ b/packages/components/src/components/input-file/shadow.tsx @@ -4,8 +4,11 @@ import clsx from 'clsx'; import type { ButtonProps, + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputFileAPI, @@ -13,23 +16,23 @@ import type { InputTypeOnDefault, LabelWithExpertSlotPropType, MsgPropType, + MultiplePropType, NamePropType, + RequiredPropType, ShortKeyPropType, Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, + AcceptPropType, } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; +import { KolButtonWcTag } from '../../core/component-names'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; -import { InputFileController } from './controller'; +import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; import { translate } from '../../i18n'; -import { KolButtonWcTag } from '../../core/component-names'; +import { nonce } from '../../utils/dev.utils'; +import { InputFileController } from './controller'; /** * @slot - Die Beschriftung des Eingabefeldes. @@ -246,7 +249,7 @@ export class KolInputFile implements InputFileAPI, FocusableElement { } @Watch('_accept') - public validateAccept(value?: string): void { + public validateAccept(value?: AcceptPropType): void { this.controller.validateAccept(value); } @@ -296,7 +299,7 @@ export class KolInputFile implements InputFileAPI, FocusableElement { } @Watch('_multiple') - public validateMultiple(value?: boolean): void { + public validateMultiple(value?: MultiplePropType): void { this.controller.validateMultiple(value); } @@ -311,7 +314,7 @@ export class KolInputFile implements InputFileAPI, FocusableElement { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/input-number/controller.ts b/packages/components/src/components/input-number/controller.ts index 19d20abc149..aef9ad25b19 100644 --- a/packages/components/src/components/input-number/controller.ts +++ b/packages/components/src/components/input-number/controller.ts @@ -1,6 +1,15 @@ -import type { AutoCompletePropType, InputNumberProps, InputNumberWatches, NumberString, SuggestionsPropType } from '../../schema'; -import { validateSuggestions, watchBoolean, watchString } from '../../schema'; +import type { + AutoCompletePropType, + InputNumberProps, + InputNumberWatches, + NumberString, + ReadOnlyPropType, + RequiredPropType, + SuggestionsPropType, +} from '../../schema'; +import { validateReadOnly, validateRequired, validateSuggestions } from '../../schema'; import { validateAutoComplete } from '../../schema/props/auto-complete'; +import { type PlaceholderPropType, validatePlaceholder } from '../../schema/props/placeholder'; import { InputIconController } from '../@deprecated/input/controller-icon'; @@ -29,16 +38,16 @@ export class InputNumberController extends InputIconController implements InputN this.validateNumber('_min', value); } - public validatePlaceholder(value?: string): void { - watchString(this.component, '_placeholder', value); + public validatePlaceholder(value?: PlaceholderPropType): void { + validatePlaceholder(this.component, value); } - public validateReadOnly(value?: boolean): void { - watchBoolean(this.component, '_readOnly', value); + public validateReadOnly(value?: ReadOnlyPropType): void { + validateReadOnly(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateStep(value?: number | NumberString): void { diff --git a/packages/components/src/components/input-number/shadow.tsx b/packages/components/src/components/input-number/shadow.tsx index 163d8824713..3d5ffc52343 100644 --- a/packages/components/src/components/input-number/shadow.tsx +++ b/packages/components/src/components/input-number/shadow.tsx @@ -3,34 +3,37 @@ import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core import clsx from 'clsx'; import type { + AutoCompletePropType, ButtonProps, + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputNumberAPI, InputNumberStates, InputTypeOnDefault, - AutoCompletePropType, LabelWithExpertSlotPropType, MsgPropType, NamePropType, NumberString, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, ShortKeyPropType, Stringified, SuggestionsPropType, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; -import { propagateSubmitEventToForm } from '../form/controller'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; +import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; +import { nonce } from '../../utils/dev.utils'; +import { propagateSubmitEventToForm } from '../form/controller'; import { InputNumberController } from './controller'; /** @@ -376,17 +379,17 @@ export class KolInputNumber implements InputNumberAPI, FocusableElement { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @Watch('_readOnly') - public validateReadOnly(value?: boolean): void { + public validateReadOnly(value?: ReadOnlyPropType): void { this.controller.validateReadOnly(value); } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/input-password/controller.ts b/packages/components/src/components/input-password/controller.ts index 93dbebc392e..76a6cd13b05 100644 --- a/packages/components/src/components/input-password/controller.ts +++ b/packages/components/src/components/input-password/controller.ts @@ -1,5 +1,14 @@ -import type { AutoCompletePropType, HasCounterPropType, InputPasswordProps, InputPasswordWatches, MaxLengthBehaviorPropType } from '../../schema'; -import { validateHasCounter, watchBoolean, watchNumber, watchString } from '../../schema'; +import type { + AutoCompletePropType, + HasCounterPropType, + InputPasswordProps, + InputPasswordWatches, + MaxLengthBehaviorPropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, +} from '../../schema'; +import { validateHasCounter, validateMaxLength, validatePlaceholder, validateReadOnly, validateRequired, validatePattern, watchString } from '../../schema'; import { validateAutoComplete } from '../../schema/props/auto-complete'; import { validateMaxLengthBehavior } from '../../schema/props/max-length-behavior'; import type { PasswordVariantPropType } from '../../schema/props/variant/password-variant'; @@ -41,25 +50,25 @@ export class InputPasswordController extends InputIconController implements Inpu } public validateMaxLength(value?: number): void { - watchNumber(this.component, '_maxLength', value, { - min: 0, + validateMaxLength(this.component, value, { + hooks: { afterPatch: this.afterSyncCharCounter }, }); } public validatePattern(value?: string): void { - watchString(this.component, '_pattern', value); + validatePattern(this.component, value); } - public validatePlaceholder(value?: string): void { - watchString(this.component, '_placeholder', value); + public validatePlaceholder(value?: PlaceholderPropType): void { + validatePlaceholder(this.component, value); } - public validateReadOnly(value?: boolean): void { - watchBoolean(this.component, '_readOnly', value); + public validateReadOnly(value?: ReadOnlyPropType): void { + validateReadOnly(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateValue(value?: string): void { diff --git a/packages/components/src/components/input-password/shadow.tsx b/packages/components/src/components/input-password/shadow.tsx index 133c7dec238..d1513888e9f 100644 --- a/packages/components/src/components/input-password/shadow.tsx +++ b/packages/components/src/components/input-password/shadow.tsx @@ -3,39 +3,42 @@ import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core import clsx from 'clsx'; import type { + AutoCompletePropType, ButtonProps, + DisabledPropType, FocusableElement, + HasCounterPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputPasswordAPI, InputPasswordStates, InputTypeOnDefault, - AutoCompletePropType, LabelWithExpertSlotPropType, MaxLengthBehaviorPropType, MsgPropType, NamePropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, ShortKeyPropType, Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HasCounterPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import { devHint } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; -import { propagateSubmitEventToForm } from '../form/controller'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; import KolInputContainerStateWrapperFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; -import { InputPasswordController } from './controller'; +import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; +import KolIconButtonFc from '../../functional-components/IconButton'; import { translate } from '../../i18n'; import type { PasswordVariantPropType } from '../../schema/props/variant/password-variant'; -import KolIconButtonFc from '../../functional-components/IconButton'; +import { nonce } from '../../utils/dev.utils'; +import { propagateSubmitEventToForm } from '../form/controller'; +import { InputPasswordController } from './controller'; /** * @slot - Die Beschriftung des Eingabefeldes. @@ -401,17 +404,17 @@ export class KolInputPassword implements InputPasswordAPI, FocusableElement { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @Watch('_readOnly') - public validateReadOnly(value?: boolean): void { + public validateReadOnly(value?: ReadOnlyPropType): void { this.controller.validateReadOnly(value); } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/input-radio/controller.ts b/packages/components/src/components/input-radio/controller.ts index f1b2785497a..e0398d510d1 100644 --- a/packages/components/src/components/input-radio/controller.ts +++ b/packages/components/src/components/input-radio/controller.ts @@ -7,6 +7,7 @@ import type { OptionsPropType, PropLabelWithExpertSlot, RadioOption, + RequiredPropType, SelectOption, StencilUnknown, } from '../../schema'; @@ -44,7 +45,7 @@ export class InputCheckboxRadioController extends InputController implements Inp this.component = component; } - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { validateRequired(this.component, value); } diff --git a/packages/components/src/components/input-radio/shadow.tsx b/packages/components/src/components/input-radio/shadow.tsx index be64a2e554e..6974109b7e2 100644 --- a/packages/components/src/components/input-radio/shadow.tsx +++ b/packages/components/src/components/input-radio/shadow.tsx @@ -3,8 +3,11 @@ import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core import clsx from 'clsx'; import type { + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IdPropType, InputRadioAPI, InputRadioStates, @@ -14,23 +17,21 @@ import type { NamePropType, RadioOption, RadioOptionsPropType, + RequiredPropType, StencilUnknown, Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import { nonce } from '../../utils/dev.utils'; -import { InputRadioController } from './controller'; import { propagateSubmitEventToForm } from '../form/controller'; +import { InputRadioController } from './controller'; -import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; import KolFieldControlStateWrapperFc, { type FieldControlStateWrapperProps, } from '../../functional-component-wrappers/FieldControlStateWrapper/FieldControlStateWrapper'; +import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; import KolRadioStateWrapperFc, { type RadioStateWrapperProps } from '../../functional-component-wrappers/RadioStateWrapper/RadioStateWrapper'; import type { OrientationPropType } from '../../schema/props/orientation'; @@ -321,7 +322,7 @@ export class KolInputRadio implements InputRadioAPI, FocusableElement { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/input-text/controller.ts b/packages/components/src/components/input-text/controller.ts index c135f5d0c36..58cdeecdd9f 100644 --- a/packages/components/src/components/input-text/controller.ts +++ b/packages/components/src/components/input-text/controller.ts @@ -1,13 +1,13 @@ import type { InputTextProps, - InputTextType, + InputTextTypePropType, InputTextWatches, PropLabelWithExpertSlot, PropSuggestions, SpellCheckPropType, SuggestionsPropType, } from '../../schema'; -import { inputTextTypeOptions, validateSpellCheck, validateSuggestions, watchValidator } from '../../schema'; +import { validateSpellCheck, validateSuggestions, validateTypeInputText } from '../../schema'; import { InputPasswordController } from '../input-password/controller'; @@ -52,14 +52,8 @@ export class InputTextController extends InputTextEmailController implements Inp validateSpellCheck(this.component, value); } - public validateType(value?: InputTextType): void { - watchValidator( - this.component, - '_type', - (value): boolean => typeof value === 'string' && inputTextTypeOptions.includes(value), - new Set([`String {${inputTextTypeOptions.join(', ')}`]), - value, - ); + public validateType(value?: InputTextTypePropType): void { + validateTypeInputText(this.component, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/input-text/shadow.tsx b/packages/components/src/components/input-text/shadow.tsx index 3f84b73fbc0..d36f5fedc97 100644 --- a/packages/components/src/components/input-text/shadow.tsx +++ b/packages/components/src/components/input-text/shadow.tsx @@ -4,25 +4,28 @@ import clsx from 'clsx'; import type { AccessKeyPropType, + AutoCompletePropType, ButtonProps, + DisabledPropType, FocusableElement, + HasCounterPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputTextAPI, InputTextStates, - InputTextType, + InputTextTypePropType, InputTypeOnDefault, - AutoCompletePropType, LabelWithExpertSlotPropType, MaxLengthBehaviorPropType, MsgPropType, NamePropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, ShortKeyPropType, - DisabledPropType, - HasCounterPropType, - HideLabelPropType, - HintPropType, SpellCheckPropType, Stringified, SuggestionsPropType, @@ -30,11 +33,11 @@ import type { TooltipAlignPropType, } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; -import { propagateSubmitEventToForm } from '../form/controller'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; +import KolInputStateWrapperFc, { type InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; +import { nonce } from '../../utils/dev.utils'; +import { propagateSubmitEventToForm } from '../form/controller'; import { InputTextController } from './controller'; /** @@ -286,7 +289,7 @@ export class KolInputText implements InputTextAPI, FocusableElement { /** * Defines either the type of the component or of the components interactive element. */ - @Prop() public _type?: InputTextType = 'text'; + @Prop() public _type?: InputTextTypePropType = 'text'; /** * Defines the value of the input. @@ -395,17 +398,17 @@ export class KolInputText implements InputTextAPI, FocusableElement { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @Watch('_readOnly') - public validateReadOnly(value?: boolean): void { + public validateReadOnly(value?: ReadOnlyPropType): void { this.controller.validateReadOnly(value); } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } @@ -440,7 +443,7 @@ export class KolInputText implements InputTextAPI, FocusableElement { } @Watch('_type') - public validateType(value?: InputTextType): void { + public validateType(value?: InputTextTypePropType): void { this.controller.validateType(value); } diff --git a/packages/components/src/components/link/component.tsx b/packages/components/src/components/link/component.tsx index 1b4ad790646..c1c17915f1f 100644 --- a/packages/components/src/components/link/component.tsx +++ b/packages/components/src/components/link/component.tsx @@ -45,9 +45,9 @@ import { validateLinkCallbacks, validateLinkTarget, validateShortKey, - validateTabIndex, validateTooltipAlign, } from '../../schema'; +import { validateTabIndex } from '../../schema/props/tab-index'; import type { JSX } from '@stencil/core'; import { Component, Element, h, Host, Method, Prop, State, Watch } from '@stencil/core'; import type { UnsubscribeFunction } from './ariaCurrentService'; diff --git a/packages/components/src/components/modal/shadow.tsx b/packages/components/src/components/modal/shadow.tsx index 127920c9d42..47d9e25a053 100644 --- a/packages/components/src/components/modal/shadow.tsx +++ b/packages/components/src/components/modal/shadow.tsx @@ -1,5 +1,5 @@ import type { KoliBriModalEventCallbacks, LabelPropType, ModalAPI, ModalStates } from '../../schema'; -import { setState, validateLabel, watchString } from '../../schema'; +import { setState, validateLabel, validateWidth } from '../../schema'; import type { JSX } from '@stencil/core'; import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core'; import { dispatchDomEvent, KolEvent } from '../../utils/events'; @@ -137,9 +137,7 @@ export class KolModal implements ModalAPI { @Watch('_width') public validateWidth(value?: string): void { - watchString(this, '_width', value, { - defaultValue: '100%', - }); + validateWidth(this, value); } @Watch('_variant') diff --git a/packages/components/src/components/progress/shadow.tsx b/packages/components/src/components/progress/shadow.tsx index db28d74d86d..9f772ec9bf7 100644 --- a/packages/components/src/components/progress/shadow.tsx +++ b/packages/components/src/components/progress/shadow.tsx @@ -1,9 +1,8 @@ -import type { KoliBriProgressVariantType, LabelPropType, ProgressAPI, ProgressStates } from '../../schema'; -import { KoliBriProgressVariantEnum, validateLabel, watchNumber, watchString, watchValidator } from '../../schema'; +import type { LabelPropType, ProgressAPI, ProgressStates, ProgressVariantPropType } from '../../schema'; +import { validateLabel, validateUnit, validateVariantProgress, watchNumber } from '../../schema'; import { Component, h, Prop, State, Watch } from '@stencil/core'; import type { JSX } from '@stencil/core'; -const VALID_VARIANTS = Object.keys(KoliBriProgressVariantEnum); const CycleSvg = ({ state }: { state: ProgressStates }) => { const fullCircle = 342; @@ -140,7 +139,7 @@ export class KolProgress implements ProgressAPI { /** * Defines which variant should be used for presentation. */ - @Prop() public _variant?: KoliBriProgressVariantType; + @Prop() public _variant?: ProgressVariantPropType; @State() public state: ProgressStates = { _max: 100, @@ -167,7 +166,7 @@ export class KolProgress implements ProgressAPI { @Watch('_unit') public validateUnit(value?: string): void { - watchString(this, '_unit', value); + validateUnit(this, value); } @Watch('_value') @@ -182,8 +181,8 @@ export class KolProgress implements ProgressAPI { } @Watch('_variant') - public validateVariant(value?: KoliBriProgressVariantType): void { - watchValidator(this, '_variant', (value) => typeof value === 'string' && VALID_VARIANTS.includes(value), new Set(VALID_VARIANTS), value); + public validateVariant(value?: ProgressVariantPropType): void { + validateVariantProgress(this, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/quote/shadow.tsx b/packages/components/src/components/quote/shadow.tsx index 129d49cacba..2ceefafea83 100644 --- a/packages/components/src/components/quote/shadow.tsx +++ b/packages/components/src/components/quote/shadow.tsx @@ -1,5 +1,5 @@ -import type { HrefPropType, KoliBriQuoteVariant, LabelPropType, QuoteAPI, QuoteStates } from '../../schema'; -import { koliBriQuoteVariantOptions, showExpertSlot, validateLabel, watchString, watchValidator } from '../../schema'; +import type { HrefPropType, LabelPropType, QuoteAPI, QuotePropType, QuoteStates, QuoteVariantPropType } from '../../schema'; +import { showExpertSlot, validateLabel, validateQuote, validateVariantQuote, watchString } from '../../schema'; import { Component, h, Prop, State, Watch } from '@stencil/core'; import type { JSX } from '@stencil/core'; @@ -31,7 +31,7 @@ export class KolQuote implements QuoteAPI { /** * Defines which variant should be used for presentation. */ - @Prop() public _variant?: KoliBriQuoteVariant = 'inline'; + @Prop() public _variant?: QuoteVariantPropType = 'inline'; @State() public state: QuoteStates = { _href: '', // ⚠ required @@ -52,21 +52,13 @@ export class KolQuote implements QuoteAPI { } @Watch('_quote') - public validateQuote(value?: string): void { - watchString(this, '_quote', value, { - required: true, - }); + public validateQuote(value?: QuotePropType): void { + validateQuote(this, value); } @Watch('_variant') - public validateVariant(value?: KoliBriQuoteVariant): void { - watchValidator( - this, - '_variant', - (value) => typeof value === 'string' && koliBriQuoteVariantOptions.includes(value), - new Set(koliBriQuoteVariantOptions), - value, - ); + public validateVariant(value?: QuoteVariantPropType): void { + validateVariantQuote(this, value); } public componentWillLoad(): void { diff --git a/packages/components/src/components/select/controller.ts b/packages/components/src/components/select/controller.ts index 96a57b4509c..9fa903fe0ba 100644 --- a/packages/components/src/components/select/controller.ts +++ b/packages/components/src/components/select/controller.ts @@ -2,15 +2,17 @@ import type { Optgroup, Option, OptionsWithOptgroupPropType, + RequiredPropType, RowsPropType, SelectOption, SelectProps, SelectWatches, StencilUnknown, Stringified, + MultiplePropType, W3CInputValue, } from '../../schema'; -import { validateOptionsWithOptgroup, validateRows, watchBoolean, watchJsonArrayString } from '../../schema'; +import { validateMultiple, validateOptionsWithOptgroup, validateRequired, validateRows, watchJsonArrayString } from '../../schema'; import { InputIconController } from '../@deprecated/input/controller-icon'; import { fillKeyOptionMap } from '../input-radio/controller'; @@ -86,9 +88,9 @@ export class SelectController extends InputIconController implements SelectWatch }); } - public validateMultiple(value?: boolean): void { + public validateMultiple(value?: MultiplePropType): void { this.assertComponentValueMatchesMultiplicity(value === true); - watchBoolean(this.component, '_multiple', value, { + validateMultiple(this.component, value, { hooks: { afterPatch: this.afterPatchOptions, beforePatch: this.beforePatchOptions, @@ -102,8 +104,8 @@ export class SelectController extends InputIconController implements SelectWatch // } } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateRows(value?: RowsPropType) { diff --git a/packages/components/src/components/select/shadow.tsx b/packages/components/src/components/select/shadow.tsx index e75b5ce1756..1c9f7f33d18 100644 --- a/packages/components/src/components/select/shadow.tsx +++ b/packages/components/src/components/select/shadow.tsx @@ -3,34 +3,36 @@ import { Component, Element, h, Method, Prop, State, Watch } from '@stencil/core import clsx from 'clsx'; import type { + DisabledPropType, FocusableElement, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputTypeOnDefault, LabelWithExpertSlotPropType, MsgPropType, + MultiplePropType, NamePropType, OptionsWithOptgroupPropType, + RequiredPropType, RowsPropType, SelectAPI, SelectStates, ShortKeyPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, StencilUnknown, Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; -import { SelectController } from './controller'; -import { propagateSubmitEventToForm } from '../form/controller'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolSelectStateWrapperFc, { type SelectStateWrapperProps } from '../../functional-component-wrappers/SelectStateWrapper/SelectStateWrapper'; import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; +import KolSelectStateWrapperFc, { type SelectStateWrapperProps } from '../../functional-component-wrappers/SelectStateWrapper/SelectStateWrapper'; +import { nonce } from '../../utils/dev.utils'; +import { propagateSubmitEventToForm } from '../form/controller'; +import { SelectController } from './controller'; /** * @slot - Die Beschriftung des Eingabefeldes. @@ -298,7 +300,7 @@ export class KolSelect implements SelectAPI, FocusableElement { } @Watch('_multiple') - public validateMultiple(value?: boolean): void { + public validateMultiple(value?: MultiplePropType): void { this.controller.validateMultiple(value); } @@ -318,7 +320,7 @@ export class KolSelect implements SelectAPI, FocusableElement { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/single-select/controller.ts b/packages/components/src/components/single-select/controller.ts index 1f50941fb94..9a860dd8709 100644 --- a/packages/components/src/components/single-select/controller.ts +++ b/packages/components/src/components/single-select/controller.ts @@ -1,5 +1,15 @@ -import type { Option, OptionsPropType, SelectOption, SingleSelectProps, SingleSelectWatches, StencilUnknown, W3CInputValue } from '../../schema'; -import { validateOptions, watchBoolean, watchNumber, watchString, watchValidator } from '../../schema'; +import type { + Option, + OptionsPropType, + PlaceholderPropType, + RequiredPropType, + SelectOption, + SingleSelectProps, + SingleSelectWatches, + StencilUnknown, + W3CInputValue, +} from '../../schema'; +import { validateOptions, validatePlaceholder, validateRequired, watchBoolean, watchNumber, watchValidator } from '../../schema'; import { InputIconController } from '../@deprecated/input/controller-icon'; import { fillKeyOptionMap } from '../input-radio/controller'; @@ -38,16 +48,16 @@ export class SingleSelectController extends InputIconController implements Singl }); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateValue(value: StencilUnknown): void { watchValidator(this.component, '_value', (v) => v !== undefined, new Set([`StencilUnknown`]), value); } - public validatePlaceholder(value?: string): void { - watchString(this.component, '_placeholder', value); + public validatePlaceholder(value?: PlaceholderPropType): void { + validatePlaceholder(this.component, value); } public validateHideClearButton(value?: boolean): void { diff --git a/packages/components/src/components/single-select/shadow.tsx b/packages/components/src/components/single-select/shadow.tsx index 31c2b8e308d..569143b2f61 100644 --- a/packages/components/src/components/single-select/shadow.tsx +++ b/packages/components/src/components/single-select/shadow.tsx @@ -1,7 +1,10 @@ import type { JSX } from '@stencil/core'; import { Component, Element, h, Listen, Method, Prop, State, Watch } from '@stencil/core'; import type { + DisabledPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputTypeOnDefault, @@ -10,6 +13,8 @@ import type { NamePropType, Option, OptionsPropType, + PlaceholderPropType, + RequiredPropType, RowsPropType, ShortKeyPropType, SingleSelectAPI, @@ -18,13 +23,11 @@ import type { Stringified, SyncValueBySelectorPropType, TooltipAlignPropType, - DisabledPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; import clsx from 'clsx'; import { KolIconTag } from '../../core/component-names'; +import { getRenderStates } from '../../functional-component-wrappers/_helpers/getRenderStates'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; import KolInputContainerFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; import type { InputStateWrapperProps } from '../../functional-component-wrappers/InputStateWrapper/InputStateWrapper'; @@ -35,7 +38,6 @@ import CustomSuggestionsToggleFc from '../../functional-components/CustomSuggest import { translate } from '../../i18n'; import type { EventDetail } from '../../schema/interfaces/EventDetail'; import { nonce } from '../../utils/dev.utils'; -import { getRenderStates } from '../../functional-component-wrappers/_helpers/getRenderStates'; import { SingleSelectController } from './controller'; /** @@ -583,7 +585,7 @@ export class KolSingleSelect implements SingleSelectAPI { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @@ -650,7 +652,7 @@ export class KolSingleSelect implements SingleSelectAPI { } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/components/table-stateful/shadow.tsx b/packages/components/src/components/table-stateful/shadow.tsx index 07513ab4ccc..1daeb91b64d 100644 --- a/packages/components/src/components/table-stateful/shadow.tsx +++ b/packages/components/src/components/table-stateful/shadow.tsx @@ -29,6 +29,7 @@ import { objectObjectHandler, parseJson, setState, + validateAllowMultiSort, validateLabel, validatePaginationPosition, validateTableData, @@ -149,9 +150,7 @@ export class KolTableStateful implements TableAPI { @Watch('_allowMultiSort') public validateAllowMultiSort(value?: boolean): void { - watchValidator(this, '_allowMultiSort', () => true, new Set(['boolean']), value, { - defaultValue: false, - }); + validateAllowMultiSort(this, value, { defaultValue: false }); } @Watch('_data') diff --git a/packages/components/src/components/textarea/controller.ts b/packages/components/src/components/textarea/controller.ts index f57f5569984..771fac57692 100644 --- a/packages/components/src/components/textarea/controller.ts +++ b/packages/components/src/components/textarea/controller.ts @@ -1,16 +1,27 @@ -import type { CSSResize, MaxLengthBehaviorPropType, RowsPropType, SpellCheckPropType, TextareaProps, TextareaWatches } from '../../schema'; +import type { + HasCounterPropType, + MaxLengthBehaviorPropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, + RowsPropType, + SpellCheckPropType, + TextareaProps, + TextareaResizePropType, + TextareaWatches, +} from '../../schema'; import { - cssResizeOptions, validateHasCounter, + validateMaxLength, validateMaxLengthBehavior, + validatePlaceholder, + validateReadOnly, + validateRequired, + validateResizeTextarea, validateRows, validateSpellCheck, - watchBoolean, - watchNumber, watchString, - watchValidator, } from '../../schema'; -import type { HasCounterPropType } from '../../schema'; import { InputIconController } from '../@deprecated/input/controller-icon'; @@ -40,34 +51,25 @@ export class TextareaController extends InputIconController implements TextareaW } public validateMaxLength(value?: number): void { - watchNumber(this.component, '_maxLength', value, { - min: 0, + validateMaxLength(this.component, value, { + hooks: { afterPatch: this.afterSyncCharCounter }, }); } - public validatePlaceholder(value?: string): void { - watchString(this.component, '_placeholder', value); + public validatePlaceholder(value?: PlaceholderPropType): void { + validatePlaceholder(this.component, value); } - public validateReadOnly(value?: boolean): void { - watchBoolean(this.component, '_readOnly', value); + public validateReadOnly(value?: ReadOnlyPropType): void { + validateReadOnly(this.component, value); } - public validateResize(value?: CSSResize): void { - watchValidator( - this.component, - '_resize', - (value) => typeof value === 'string' && cssResizeOptions.includes(value), - new Set(`String {${cssResizeOptions.join(', ')}`), - value, - { - defaultValue: 'vertical', - }, - ); + public validateResize(value?: TextareaResizePropType): void { + validateResizeTextarea(this.component, value); } - public validateRequired(value?: boolean): void { - watchBoolean(this.component, '_required', value); + public validateRequired(value?: RequiredPropType): void { + validateRequired(this.component, value); } public validateRows(value?: RowsPropType): void { diff --git a/packages/components/src/components/textarea/shadow.tsx b/packages/components/src/components/textarea/shadow.tsx index c3a640704e1..87c344730fb 100644 --- a/packages/components/src/components/textarea/shadow.tsx +++ b/packages/components/src/components/textarea/shadow.tsx @@ -4,9 +4,12 @@ import clsx from 'clsx'; import type { AdjustHeightPropType, - CSSResize, + DisabledPropType, FocusableElement, + HasCounterPropType, + HideLabelPropType, HideMsgPropType, + HintPropType, IconsHorizontalPropType, IdPropType, InputTypeOnDefault, @@ -14,24 +17,24 @@ import type { MaxLengthBehaviorPropType, MsgPropType, NamePropType, + PlaceholderPropType, + ReadOnlyPropType, + RequiredPropType, RowsPropType, ShortKeyPropType, SpellCheckPropType, Stringified, SyncValueBySelectorPropType, TextareaAPI, + TextareaResizePropType, TextareaStates, TooltipAlignPropType, - DisabledPropType, - HasCounterPropType, - HideLabelPropType, - HintPropType, } from '../../schema'; -import { nonce } from '../../utils/dev.utils'; import KolFormFieldStateWrapperFc, { type FormFieldStateWrapperProps } from '../../functional-component-wrappers/FormFieldStateWrapper/FormFieldStateWrapper'; -import KolTextAreaStateWrapperFc, { type TextAreaStateWrapperProps } from '../../functional-component-wrappers/TextAreaStateWrapper/TextAreaStateWrapper'; import KolInputContainerStateWrapperFc from '../../functional-component-wrappers/InputContainerStateWrapper/InputContainerStateWrapper'; +import KolTextAreaStateWrapperFc, { type TextAreaStateWrapperProps } from '../../functional-component-wrappers/TextAreaStateWrapper/TextAreaStateWrapper'; +import { nonce } from '../../utils/dev.utils'; import { TextareaController } from './controller'; /** @@ -222,7 +225,7 @@ export class KolTextarea implements TextareaAPI, FocusableElement { * Defines whether and in which direction the size of the input can be changed by the user. (https://developer.mozilla.org/de/docs/Web/CSS/resize) * In version 3 (v3), horizontal resizing is abolished. The corresponding property is then reduced to the properties `vertical` (default) and `none`. */ - @Prop() public _resize?: CSSResize = 'vertical'; + @Prop() public _resize?: TextareaResizePropType = 'vertical'; /** * Makes the input element required. @@ -364,22 +367,22 @@ export class KolTextarea implements TextareaAPI, FocusableElement { } @Watch('_placeholder') - public validatePlaceholder(value?: string): void { + public validatePlaceholder(value?: PlaceholderPropType): void { this.controller.validatePlaceholder(value); } @Watch('_readOnly') - public validateReadOnly(value?: boolean): void { + public validateReadOnly(value?: ReadOnlyPropType): void { this.controller.validateReadOnly(value); } @Watch('_resize') - public validateResize(value?: CSSResize): void { + public validateResize(value?: TextareaResizePropType): void { this.controller.validateResize(value); } @Watch('_required') - public validateRequired(value?: boolean): void { + public validateRequired(value?: RequiredPropType): void { this.controller.validateRequired(value); } diff --git a/packages/components/src/schema/components/alert.ts b/packages/components/src/schema/components/alert.ts index a85fefa69a8..680041d32f2 100644 --- a/packages/components/src/schema/components/alert.ts +++ b/packages/components/src/schema/components/alert.ts @@ -1,14 +1,8 @@ import type { Generic } from 'adopted-style-sheets'; -import type { HeadingLevel, PropAlert, PropHasCloser, PropLabel } from '../props'; +import type { HeadingLevel, PropAlert, PropAlertType, PropAlertVariant, PropHasCloser, PropLabel } from '../props'; import type { EventCallback } from '../types'; -export const alertTypeOptions = ['default', 'info', 'success', 'warning', 'error'] as const; -export type AlertType = (typeof alertTypeOptions)[number]; - -export const alertVariantOptions = ['card', 'msg'] as const; -export type AlertVariant = (typeof alertVariantOptions)[number]; - export type KoliBriAlertEventCallbacks = { onClose?: EventCallback; }; @@ -17,11 +11,11 @@ type RequiredAlertProps = NonNullable; type OptionalAlertProps = { level: HeadingLevel; on: KoliBriAlertEventCallbacks; - type: AlertType; - variant: AlertVariant; } & PropLabel & PropAlert & - PropHasCloser; + PropHasCloser & + PropAlertType & + PropAlertVariant; type RequiredAlertStates = RequiredAlertProps; type OptionalAlertStates = OptionalAlertProps; diff --git a/packages/components/src/schema/components/input-checkbox.ts b/packages/components/src/schema/components/input-checkbox.ts index 8f3e0e9883b..f138c1f986c 100644 --- a/packages/components/src/schema/components/input-checkbox.ts +++ b/packages/components/src/schema/components/input-checkbox.ts @@ -1,11 +1,15 @@ import type { Generic } from 'adopted-style-sheets'; import type { + InputCheckboxIconsProp, + InputCheckboxIconsState, + InputCheckboxVariantPropType, MsgPropType, + PropAccessKey, PropChecked, PropDisabled, - PropHideMsg, PropHideLabel, + PropHideMsg, PropHint, PropIndeterminate, PropLabelAlign, @@ -13,38 +17,11 @@ import type { PropMsg, PropName, PropRequired, + PropShortKey, PropSyncValueBySelector, PropTouched, - PropShortKey, - PropAccessKey, } from '../props'; -import type { AnyIconFontClass, InputTypeOnDefault, StencilUnknown, Stringified } from '../types'; - -export const inputCheckboxVariantOptions = ['button', 'default', 'switch'] as const; -export type InputCheckboxVariant = (typeof inputCheckboxVariantOptions)[number]; - -export type InputCheckboxIconsProp = - | { - checked: AnyIconFontClass; - indeterminate?: AnyIconFontClass; - unchecked?: AnyIconFontClass; - } - | { - checked?: AnyIconFontClass; - indeterminate: AnyIconFontClass; - unchecked?: AnyIconFontClass; - } - | { - checked?: AnyIconFontClass; - indeterminate?: AnyIconFontClass; - unchecked: AnyIconFontClass; - }; - -export type InputCheckboxIconsState = { - checked: AnyIconFontClass; - indeterminate: AnyIconFontClass; - unchecked: AnyIconFontClass; -}; +import type { InputTypeOnDefault, StencilUnknown, Stringified } from '../types'; type RequiredProps = PropLabelWithExpertSlot; type OptionalProps = { @@ -52,7 +29,7 @@ type OptionalProps = { msg: Stringified; on: InputTypeOnDefault; value: StencilUnknown; - variant: InputCheckboxVariant; + variant: InputCheckboxVariantPropType; } & PropAccessKey & PropChecked & PropDisabled & @@ -71,7 +48,7 @@ type RequiredStates = { icons: InputCheckboxIconsState; id: string; value: StencilUnknown; - variant: InputCheckboxVariant; + variant: InputCheckboxVariantPropType; } & PropChecked & PropHideMsg & PropIndeterminate & diff --git a/packages/components/src/schema/components/input-date.ts b/packages/components/src/schema/components/input-date.ts index 4e45f54fec7..13d44cfc27a 100644 --- a/packages/components/src/schema/components/input-date.ts +++ b/packages/components/src/schema/components/input-date.ts @@ -1,6 +1,7 @@ import type { Generic } from 'adopted-style-sheets'; import type { + InputDateTypePropType, MsgPropType, PropAccessKey, PropAutoComplete, @@ -23,9 +24,6 @@ import type { import type { InputTypeOnDefault, Iso8601, KoliBriHIcons, NumberString, Stringified, W3CInputValue } from '../types'; import type { ButtonProps } from './button'; -export const inputDateTypeOptions = ['date', 'datetime-local', 'month', 'time', 'week'] as const; -export type InputDateType = (typeof inputDateTypeOptions)[number]; - type RequiredProps = PropLabelWithExpertSlot; type OptionalProps = { max: Iso8601 | Date; @@ -34,7 +32,7 @@ type OptionalProps = { on: InputTypeOnDefault; smartButton: Stringified; step: number | NumberString; - type: InputDateType; + type: InputDateTypePropType; value: Iso8601 | Date | null; } & PropAccessKey & PropAutoComplete & @@ -52,7 +50,7 @@ type OptionalProps = { type RequiredStates = { hasValue: boolean; suggestions: W3CInputValue[]; - type: InputDateType; + type: InputDateTypePropType; } & PropLabelWithExpertSlot & PropHideMsg & PropId; diff --git a/packages/components/src/schema/components/input-number.ts b/packages/components/src/schema/components/input-number.ts index 126acaeb851..66ce0c3e4af 100644 --- a/packages/components/src/schema/components/input-number.ts +++ b/packages/components/src/schema/components/input-number.ts @@ -2,6 +2,7 @@ import type { Generic } from 'adopted-style-sheets'; import type { MsgPropType, + PlaceholderPropType, PropAccessKey, PropAutoComplete, PropDisabled, @@ -29,7 +30,7 @@ type OptionalProps = { min: number | NumberString; msg: Stringified; on: InputTypeOnDefault; - placeholder: string; + placeholder: PlaceholderPropType; smartButton: Stringified; step: number | NumberString; value: number | NumberString | null; @@ -57,7 +58,7 @@ type OptionalStates = { max: number; min: number; on: InputTypeOnDefault; - placeholder: string; + placeholder: PlaceholderPropType; smartButton: ButtonProps; step: number; value: number; diff --git a/packages/components/src/schema/components/input-text.ts b/packages/components/src/schema/components/input-text.ts index d63559a667a..dd0d79dcac4 100644 --- a/packages/components/src/schema/components/input-text.ts +++ b/packages/components/src/schema/components/input-text.ts @@ -1,6 +1,7 @@ import type { Generic } from 'adopted-style-sheets'; import type { + InputTextTypePropType, MsgPropType, PropAccessKey, PropAutoComplete, @@ -8,6 +9,7 @@ import type { PropHasCounter, PropHideLabel, PropHideMsg, + PropHint, PropHorizontalIcons, PropId, PropLabelWithExpertSlot, @@ -21,14 +23,10 @@ import type { PropSuggestions, PropSyncValueBySelector, PropTouched, - PropHint, } from '../props'; import type { InputTypeOnDefault, KoliBriHIcons, Stringified, W3CInputValue } from '../types'; import type { ButtonProps } from './button'; -export const inputTextTypeOptions = ['text', 'search', 'url', 'tel'] as const; -export type InputTextType = (typeof inputTextTypeOptions)[number]; - type RequiredProps = PropLabelWithExpertSlot; type OptionalProps = { maxLength: number; @@ -37,7 +35,7 @@ type OptionalProps = { pattern: string; placeholder: string; smartButton: Stringified; - type: InputTextType; + type: InputTextTypePropType; value: string; } & PropAccessKey & PropAutoComplete & @@ -63,7 +61,7 @@ type RequiredStates = { currentLengthDebounced: number; hasValue: boolean; suggestions: W3CInputValue[]; - type: InputTextType; + type: InputTextTypePropType; } & PropHideMsg & PropId & PropLabelWithExpertSlot; diff --git a/packages/components/src/schema/components/progress.ts b/packages/components/src/schema/components/progress.ts index aaf75e3c23f..fa283bd8b70 100644 --- a/packages/components/src/schema/components/progress.ts +++ b/packages/components/src/schema/components/progress.ts @@ -1,7 +1,6 @@ import type { Generic } from 'adopted-style-sheets'; -import type { PropLabel } from '../props'; -import type { KoliBriProgressVariantType } from '../types'; +import type { PropLabel, PropVariantProgress } from '../props'; type RequiredProps = { max: number; @@ -9,16 +8,16 @@ type RequiredProps = { }; type OptionalProps = { unit: string; - variant: KoliBriProgressVariantType; -} & PropLabel; +} & PropLabel & + PropVariantProgress; type RequiredStates = RequiredProps & { liveValue: number; }; type OptionalStates = { unit: string; - variant: KoliBriProgressVariantType; -} & PropLabel; +} & PropLabel & + PropVariantProgress; export type ProgressProps = Generic.Element.Members; export type ProgressStates = Generic.Element.Members; diff --git a/packages/components/src/schema/components/quote.ts b/packages/components/src/schema/components/quote.ts index c447353b7b7..9268743ea2f 100644 --- a/packages/components/src/schema/components/quote.ts +++ b/packages/components/src/schema/components/quote.ts @@ -1,21 +1,16 @@ import type { Generic } from 'adopted-style-sheets'; -import type { PropHref, PropLabel } from '../props'; - -export const koliBriQuoteVariantOptions = ['block', 'inline'] as const; -export type KoliBriQuoteVariant = (typeof koliBriQuoteVariantOptions)[number]; +import type { PropHref, PropLabel, PropVariantQuote } from '../props'; type RequiredProps = { quote: string; } & PropHref; // URL to the source of the quote (cite) -type OptionalProps = { - variant: KoliBriQuoteVariant; -} & PropLabel; +type OptionalProps = PropLabel & PropVariantQuote; type RequiredStates = { quote: string; - variant: KoliBriQuoteVariant; -} & PropHref; // URL to the source of the quote (cite) +} & PropHref & + PropVariantQuote; // URL to the source of the quote (cite) type OptionalStates = PropLabel; export type QuoteProps = Generic.Element.Members; diff --git a/packages/components/src/schema/components/toaster.ts b/packages/components/src/schema/components/toaster.ts index f027e9a8ecb..44db5df0db8 100644 --- a/packages/components/src/schema/components/toaster.ts +++ b/packages/components/src/schema/components/toaster.ts @@ -1,7 +1,7 @@ import type { Generic } from 'adopted-style-sheets'; import type { LabelPropType } from '../props'; -import type { AlertType, AlertVariant } from './alert'; +import type { AlertTypePropType, AlertVariantPropType } from '../props'; const toastStatusOptions = ['adding', 'settled', 'removing'] as const; type ToastStatus = (typeof toastStatusOptions)[number]; @@ -12,8 +12,8 @@ export type Toast = { description?: string; render?: ToastRenderFunction; label: LabelPropType; - type: AlertType; - variant?: AlertVariant; + type: AlertTypePropType; + variant?: AlertVariantPropType; onClose?: () => void; }; @@ -24,7 +24,7 @@ export type ToastState = { }; export type ToasterOptions = { - defaultVariant: AlertVariant; + defaultVariant: AlertVariantPropType; }; type RequiredProps = NonNullable; diff --git a/packages/components/src/schema/index.ts b/packages/components/src/schema/index.ts index 6ef18514c1a..89d3c4fc394 100644 --- a/packages/components/src/schema/index.ts +++ b/packages/components/src/schema/index.ts @@ -6,7 +6,7 @@ import { TagEnum } from './tag-names'; export const KoliBri = new Theme<'kol', keyof typeof KeyEnum, keyof typeof TagEnum>('kol', KeyEnum, TagEnum); export * from './components'; -// export * from './enums'; only for internal use +// export * from './enums'; // only for internal use export * from './props'; export * from './types'; export * from './utils'; diff --git a/packages/components/src/schema/props/accept.ts b/packages/components/src/schema/props/accept.ts new file mode 100644 index 00000000000..0abe05b337f --- /dev/null +++ b/packages/components/src/schema/props/accept.ts @@ -0,0 +1,19 @@ +import type { Generic } from 'adopted-style-sheets'; + +import type { WatchStringOptions } from '../utils'; +import { watchString } from '../utils'; + +/* types */ +export type AcceptPropType = string; + +/** + * Defines which file formats are accepted. + */ +export type PropAccept = { + accept: AcceptPropType; +}; + +/* validator */ +export const validateAccept = (component: Generic.Element.Component, value?: AcceptPropType, options: WatchStringOptions = {}): void => { + watchString(component, '_accept', value, options); +}; diff --git a/packages/components/src/schema/props/alert-type.ts b/packages/components/src/schema/props/alert-type.ts new file mode 100644 index 00000000000..250f7299dd1 --- /dev/null +++ b/packages/components/src/schema/props/alert-type.ts @@ -0,0 +1,23 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const alertTypeOptions = ['default', 'info', 'success', 'warning', 'error'] as const; +export type AlertType = (typeof alertTypeOptions)[number]; + +export type AlertTypePropType = AlertType; + +/** + * Defines the type of the alert component. + */ +export type PropAlertType = { + type: AlertTypePropType; +}; + +const isAlertTypePropType = (value: unknown): value is AlertTypePropType => { + return typeof value === 'string' && alertTypeOptions.includes(value as AlertTypePropType); +}; + +export const validateAlertType = (component: Generic.Element.Component, value?: AlertTypePropType): void => { + watchValidator(component, '_type', isAlertTypePropType, new Set(alertTypeOptions), value); +}; diff --git a/packages/components/src/schema/props/allow-multi-sort.ts b/packages/components/src/schema/props/allow-multi-sort.ts new file mode 100644 index 00000000000..9b9b8069daf --- /dev/null +++ b/packages/components/src/schema/props/allow-multi-sort.ts @@ -0,0 +1,19 @@ +import type { Generic } from 'adopted-style-sheets'; + +import type { WatchBooleanOptions } from '../utils'; +import { watchBoolean } from '../utils'; + +/* types */ +export type AllowMultiSortPropType = boolean; + +/** + * Defines whether to allow multi sort. + */ +export interface PropAllowMultiSort { + allowMultiSort: AllowMultiSortPropType; +} + +/* validator */ +export const validateAllowMultiSort = (component: Generic.Element.Component, value?: AllowMultiSortPropType, options: WatchBooleanOptions = {}): void => { + watchBoolean(component, '_allowMultiSort', value, { defaultValue: false, ...options }); +}; diff --git a/packages/components/src/schema/props/current-length.ts b/packages/components/src/schema/props/current-length.ts new file mode 100644 index 00000000000..6704c4d524b --- /dev/null +++ b/packages/components/src/schema/props/current-length.ts @@ -0,0 +1,16 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchNumberOptions } from '../utils'; +import { watchNumber } from '../utils'; + +export type CurrentLengthPropType = number; + +/** + * Tracks the current length of the input value. + */ +export type PropCurrentLength = { + currentLength: CurrentLengthPropType; +}; + +export const validateCurrentLength = (component: Generic.Element.Component, value?: CurrentLengthPropType, options: WatchNumberOptions = {}): void => { + watchNumber(component, '_currentLength', value, options); +}; diff --git a/packages/components/src/schema/props/has-value.ts b/packages/components/src/schema/props/has-value.ts new file mode 100644 index 00000000000..e43e16d0ba8 --- /dev/null +++ b/packages/components/src/schema/props/has-value.ts @@ -0,0 +1,16 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchBooleanOptions } from '../utils'; +import { watchBoolean } from '../utils'; + +export type HasValuePropType = boolean; + +/** + * Indicates whether the element currently has a value. + */ +export type PropHasValue = { + hasValue: HasValuePropType; +}; + +export const validateHasValue = (component: Generic.Element.Component, value?: HasValuePropType, options: WatchBooleanOptions = {}): void => { + watchBoolean(component, '_hasValue', value, options); +}; diff --git a/packages/components/src/schema/props/icons-input-checkbox.ts b/packages/components/src/schema/props/icons-input-checkbox.ts new file mode 100644 index 00000000000..e14a46bec59 --- /dev/null +++ b/packages/components/src/schema/props/icons-input-checkbox.ts @@ -0,0 +1,59 @@ +import type { Generic } from 'adopted-style-sheets'; + +import type { AnyIconFontClass, Stringified } from '../types'; +import { isString } from '../validators'; +import { watchValidator } from '../utils'; + +export type InputCheckboxIconsProp = + | { + checked: AnyIconFontClass; + indeterminate?: AnyIconFontClass; + unchecked?: AnyIconFontClass; + } + | { + checked?: AnyIconFontClass; + indeterminate: AnyIconFontClass; + unchecked?: AnyIconFontClass; + } + | { + checked?: AnyIconFontClass; + indeterminate?: AnyIconFontClass; + unchecked: AnyIconFontClass; + }; + +export type InputCheckboxIconsState = { + checked: AnyIconFontClass; + indeterminate: AnyIconFontClass; + unchecked: AnyIconFontClass; +}; + +export type InputCheckboxIconsPropType = Stringified; + +export type PropIconsInputCheckbox = { + icons: InputCheckboxIconsPropType; +}; + +export const validateIconsInputCheckbox = (component: Generic.Element.Component, value?: InputCheckboxIconsPropType): void => { + watchValidator( + component, + '_icons', + (value): boolean => + typeof value === 'object' && + value !== null && + (isString((value as Record).checked, 1) || + isString((value as Record).indeterminate, 1) || + isString((value as Record).unchecked, 1)), + new Set(['InputCheckboxIcons']), + value as unknown, + { + hooks: { + beforePatch: (nextValue: unknown, nextState: Map, component: Generic.Element.Component) => { + nextState.set('_icons', { + ...(component.state._icons as InputCheckboxIconsState), + ...(nextValue as InputCheckboxIconsProp), + }); + }, + }, + }, + ); +}; diff --git a/packages/components/src/schema/props/index.ts b/packages/components/src/schema/props/index.ts index 898fd3a37b7..4ee6b56678e 100644 --- a/packages/components/src/schema/props/index.ts +++ b/packages/components/src/schema/props/index.ts @@ -1,10 +1,13 @@ export * from './access-key'; +export * from './accept'; export * from './accordion-callbacks'; export * from './active'; export * from './adjust-height'; export * from './alert'; +export * from './alert-type'; export * from './alt'; export * from './align'; +export * from './allow-multi-sort'; export * from './alternative-button-link-role'; export * from './aria-controls'; export * from './aria-current-value'; @@ -20,6 +23,7 @@ export * from './button-variant'; export * from './checked'; export * from './collapsible'; export * from './color'; +export * from './current-length'; export * from './custom-class'; export * from './details-callbacks'; export * from './disabled'; @@ -29,22 +33,26 @@ export * from './has-closer'; export * from './has-compact-button'; export * from './has-counter'; export * from './has-icons-when-expanded'; +export * from './has-value'; export * from './hide-label'; export * from './hide-msg'; export * from './hint'; export * from './href'; export * from './icons'; +export * from './icons-input-checkbox'; export * from './id'; export * from './image-source'; export * from './image-sizes'; export * from './image-srcset'; export * from './indeterminate'; export * from './label'; +export * from './level'; export * from './label-align'; export * from './link-on-callbacks'; export * from './link-target'; export * from './link-variant'; export * from './loading'; +export * from './max-length'; export * from './max'; export * from './max-length-behavior'; export * from './modal'; @@ -54,10 +62,14 @@ export * from './name'; export * from './open'; export * from './options'; export * from './pagination-position'; +export * from './pattern'; +export * from './placeholder'; export * from './popover-align'; export * from './popover-callbacks'; +export * from './quote'; export * from './read-only'; export * from './required'; +export * from './resize-textarea'; export * from './rows'; export * from './short-key'; export * from './show'; @@ -65,6 +77,7 @@ export * from './spell-check'; export * from './suggestions'; export * from './sync-value-by-selector'; export * from './tab-behavior'; +export * from './tab-index'; export * from './table-callbacks'; export * from './table-data'; export * from './table-data-foot'; @@ -73,4 +86,12 @@ export * from './table-selection'; export * from './toolbar-items'; export * from './tooltip-align'; export * from './touched'; +export * from './type-input-date'; +export * from './type-input-text'; +export * from './unit'; +export * from './variant-alert'; +export * from './variant-input-checkbox'; +export * from './variant-progress'; +export * from './variant-quote'; export * from './variant/spin'; +export * from './width'; diff --git a/packages/components/src/schema/props/level.ts b/packages/components/src/schema/props/level.ts new file mode 100644 index 00000000000..1b9714ec7ce --- /dev/null +++ b/packages/components/src/schema/props/level.ts @@ -0,0 +1,26 @@ +import type { Generic } from 'adopted-style-sheets'; +import { watchValidator } from '../utils'; +import { headingLevelOptions, type HeadingLevel } from './label'; + +export type LevelPropType = HeadingLevel; + +/** + * Sets the heading level of the component. + */ +export type PropLevel = { + level: LevelPropType; +}; + +export const validateLevel = (component: Generic.Element.Component, value?: LevelPropType): void => { + watchValidator( + component, + '_level', + (value?: LevelPropType): boolean => typeof value === 'number' && headingLevelOptions.includes(value), + new Set(headingLevelOptions.map(String)), + value, + { + defaultValue: 1, + required: true, + }, + ); +}; diff --git a/packages/components/src/schema/props/max-length.ts b/packages/components/src/schema/props/max-length.ts new file mode 100644 index 00000000000..bb5ce5ed3b6 --- /dev/null +++ b/packages/components/src/schema/props/max-length.ts @@ -0,0 +1,16 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchNumberOptions } from '../utils'; +import { watchNumber } from '../utils'; + +export type MaxLengthPropType = number; + +/** + * Defines the maximum length of the value. + */ +export type PropMaxLength = { + maxLength: MaxLengthPropType; +}; + +export const validateMaxLength = (component: Generic.Element.Component, value?: MaxLengthPropType, options: WatchNumberOptions = {}): void => { + watchNumber(component, '_maxLength', value, { min: 0, ...options }); +}; diff --git a/packages/components/src/schema/props/multiple.ts b/packages/components/src/schema/props/multiple.ts index 220a38deecf..ab27709055a 100644 --- a/packages/components/src/schema/props/multiple.ts +++ b/packages/components/src/schema/props/multiple.ts @@ -1,6 +1,7 @@ import type { Generic } from 'adopted-style-sheets'; import { watchBoolean } from '../utils'; +import type { WatchBooleanOptions } from '../utils'; /* types */ export type MultiplePropType = boolean; @@ -13,6 +14,6 @@ export type PropMultiple = { }; /* validator */ -export const validateMultiple = (component: Generic.Element.Component, value?: MultiplePropType): void => { - watchBoolean(component, '_multiple', value); +export const validateMultiple = (component: Generic.Element.Component, value?: MultiplePropType, options?: WatchBooleanOptions): void => { + watchBoolean(component, '_multiple', value, options); }; diff --git a/packages/components/src/schema/props/pattern.ts b/packages/components/src/schema/props/pattern.ts new file mode 100644 index 00000000000..a674707ac61 --- /dev/null +++ b/packages/components/src/schema/props/pattern.ts @@ -0,0 +1,16 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchStringOptions } from '../utils'; +import { watchString } from '../utils'; + +export type PatternPropType = string; + +/** + * Defines a validation pattern for the input field. + */ +export type PropPattern = { + pattern: PatternPropType; +}; + +export const validatePattern = (component: Generic.Element.Component, value?: PatternPropType, options: WatchStringOptions = {}): void => { + watchString(component, '_pattern', value, options); +}; diff --git a/packages/components/src/schema/props/placeholder.ts b/packages/components/src/schema/props/placeholder.ts new file mode 100644 index 00000000000..fc437f9fc00 --- /dev/null +++ b/packages/components/src/schema/props/placeholder.ts @@ -0,0 +1,16 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchStringOptions } from '../utils'; +import { watchString } from '../utils'; + +export type PlaceholderPropType = string; + +/** + * Describes placeholder text for an input element. + */ +export type PropPlaceholder = { + placeholder: PlaceholderPropType; +}; + +export const validatePlaceholder = (component: Generic.Element.Component, value?: PlaceholderPropType, options: WatchStringOptions = {}): void => { + watchString(component, '_placeholder', value, options); +}; diff --git a/packages/components/src/schema/props/quote.ts b/packages/components/src/schema/props/quote.ts new file mode 100644 index 00000000000..d18410bd5fc --- /dev/null +++ b/packages/components/src/schema/props/quote.ts @@ -0,0 +1,18 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchString } from '../utils'; + +export type QuotePropType = string; + +/** + * Defines the text of the quote. + */ +export type PropQuote = { + quote: QuotePropType; +}; + +export const validateQuote = (component: Generic.Element.Component, value?: QuotePropType): void => { + watchString(component, '_quote', value, { + required: true, + }); +}; diff --git a/packages/components/src/schema/props/required.ts b/packages/components/src/schema/props/required.ts index b6567a93156..cc75bc9e3e1 100644 --- a/packages/components/src/schema/props/required.ts +++ b/packages/components/src/schema/props/required.ts @@ -3,7 +3,7 @@ import type { Generic } from 'adopted-style-sheets'; import { watchBoolean } from '../utils'; /* types */ -type RequiredPropType = boolean; +export type RequiredPropType = boolean; /** * Makes the input element required. diff --git a/packages/components/src/schema/props/resize-textarea.ts b/packages/components/src/schema/props/resize-textarea.ts new file mode 100644 index 00000000000..0186f316361 --- /dev/null +++ b/packages/components/src/schema/props/resize-textarea.ts @@ -0,0 +1,23 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const textareaResizeOptions = ['vertical', 'none'] as const; +export type TextareaResizePropType = (typeof textareaResizeOptions)[number]; + +/** + * Defines how the textarea can be resized by the user. + */ +export type PropResizeTextarea = { + resize: TextareaResizePropType; +}; + +const isTextareaResizePropType = (value: unknown): value is TextareaResizePropType => { + return typeof value === 'string' && textareaResizeOptions.includes(value as TextareaResizePropType); +}; + +export const validateResizeTextarea = (component: Generic.Element.Component, value?: TextareaResizePropType): void => { + watchValidator(component, '_resize', isTextareaResizePropType, new Set(textareaResizeOptions), value, { + defaultValue: 'vertical', + }); +}; diff --git a/packages/components/src/schema/validators/tab-index.ts b/packages/components/src/schema/props/tab-index.ts similarity index 61% rename from packages/components/src/schema/validators/tab-index.ts rename to packages/components/src/schema/props/tab-index.ts index 83fb349a6f3..fef3d5c9989 100644 --- a/packages/components/src/schema/validators/tab-index.ts +++ b/packages/components/src/schema/props/tab-index.ts @@ -3,11 +3,18 @@ import type { Generic } from 'adopted-style-sheets'; import type { WatchNumberOptions } from '../utils'; import { a11yHint, watchNumber } from '../utils'; +/* types */ +export type TabIndexPropType = number; + /** - * Accessibility hints - * - https://adrianroselli.com/2014/11/dont-use-tabindex-greater-than-0.html + * Defines which tab-index the primary element of the component has. + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex */ +export type PropTabIndex = { + tabIndex: TabIndexPropType; +}; +/* constants */ const options: WatchNumberOptions = { hooks: { afterPatch: (value) => { @@ -18,9 +25,7 @@ const options: WatchNumberOptions = { }, }; -/** - * Diese Methode validiert das Property und setzt den State, wenn es valide ist. - */ -export const validateTabIndex = (component: Generic.Element.Component, value?: number): void => { +/* validator */ +export const validateTabIndex = (component: Generic.Element.Component, value?: TabIndexPropType): void => { watchNumber(component, '_tabIndex', value, options); }; diff --git a/packages/components/src/schema/props/type-input-date.ts b/packages/components/src/schema/props/type-input-date.ts new file mode 100644 index 00000000000..e7be6ac1cf2 --- /dev/null +++ b/packages/components/src/schema/props/type-input-date.ts @@ -0,0 +1,21 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const inputDateTypeOptions = ['date', 'datetime-local', 'month', 'time', 'week'] as const; +export type InputDateTypePropType = (typeof inputDateTypeOptions)[number]; + +/** + * Defines the type of the input-date component. + */ +export type PropTypeInputDate = { + type: InputDateTypePropType; +}; + +const isInputDateTypePropType = (value: unknown): value is InputDateTypePropType => { + return typeof value === 'string' && inputDateTypeOptions.includes(value as InputDateTypePropType); +}; + +export const validateTypeInputDate = (component: Generic.Element.Component, value?: InputDateTypePropType): void => { + watchValidator(component, '_type', isInputDateTypePropType, new Set(inputDateTypeOptions), value); +}; diff --git a/packages/components/src/schema/props/type-input-text.ts b/packages/components/src/schema/props/type-input-text.ts new file mode 100644 index 00000000000..2d709d8d6f0 --- /dev/null +++ b/packages/components/src/schema/props/type-input-text.ts @@ -0,0 +1,21 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const inputTextTypeOptions = ['text', 'search', 'url', 'tel'] as const; +export type InputTextTypePropType = (typeof inputTextTypeOptions)[number]; + +/** + * Defines the type of the input-text component. + */ +export type PropTypeInputText = { + type: InputTextTypePropType; +}; + +const isInputTextTypePropType = (value: unknown): value is InputTextTypePropType => { + return typeof value === 'string' && inputTextTypeOptions.includes(value as InputTextTypePropType); +}; + +export const validateTypeInputText = (component: Generic.Element.Component, value?: InputTextTypePropType): void => { + watchValidator(component, '_type', isInputTextTypePropType, new Set(inputTextTypeOptions), value); +}; diff --git a/packages/components/src/schema/props/unit.ts b/packages/components/src/schema/props/unit.ts new file mode 100644 index 00000000000..ee939cbd558 --- /dev/null +++ b/packages/components/src/schema/props/unit.ts @@ -0,0 +1,18 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchString } from '../utils'; + +/* types */ +export type UnitPropType = string; + +/** + * Defines the unit of the step values (not shown). + */ +export type PropUnit = { + unit: UnitPropType; +}; + +/* validator */ +export const validateUnit = (component: Generic.Element.Component, value?: UnitPropType): void => { + watchString(component, '_unit', value); +}; diff --git a/packages/components/src/schema/props/variant-alert.ts b/packages/components/src/schema/props/variant-alert.ts new file mode 100644 index 00000000000..d9933e316c8 --- /dev/null +++ b/packages/components/src/schema/props/variant-alert.ts @@ -0,0 +1,21 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const alertVariantOptions = ['card', 'msg'] as const; +export type AlertVariantPropType = (typeof alertVariantOptions)[number]; + +/** + * Defines the variant for presenting alerts. + */ +export type PropAlertVariant = { + variant: AlertVariantPropType; +}; + +const isAlertVariantPropType = (value: unknown): value is AlertVariantPropType => { + return typeof value === 'string' && alertVariantOptions.includes(value as AlertVariantPropType); +}; + +export const validateAlertVariant = (component: Generic.Element.Component, value?: AlertVariantPropType): void => { + watchValidator(component, '_variant', isAlertVariantPropType, new Set(alertVariantOptions), value); +}; diff --git a/packages/components/src/schema/props/variant-input-checkbox.ts b/packages/components/src/schema/props/variant-input-checkbox.ts new file mode 100644 index 00000000000..f660a82fa55 --- /dev/null +++ b/packages/components/src/schema/props/variant-input-checkbox.ts @@ -0,0 +1,27 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const inputCheckboxVariantOptions = ['button', 'default', 'switch'] as const; +export type InputCheckboxVariantPropType = (typeof inputCheckboxVariantOptions)[number]; + +/** + * Defines the variant for presenting the input-checkbox component. + */ +export type PropVariantInputCheckbox = { + variant: InputCheckboxVariantPropType; +}; + +const isInputCheckboxVariantPropType = (value: unknown): value is InputCheckboxVariantPropType => { + return typeof value === 'string' && inputCheckboxVariantOptions.includes(value as InputCheckboxVariantPropType); +}; + +export const validateVariantInputCheckbox = (component: Generic.Element.Component, value?: InputCheckboxVariantPropType): void => { + watchValidator( + component, + '_variant', + isInputCheckboxVariantPropType, + new Set(inputCheckboxVariantOptions), + value, + ); +}; diff --git a/packages/components/src/schema/props/variant-progress.ts b/packages/components/src/schema/props/variant-progress.ts new file mode 100644 index 00000000000..fa53ff2a9d8 --- /dev/null +++ b/packages/components/src/schema/props/variant-progress.ts @@ -0,0 +1,21 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const progressVariantOptions = ['bar', 'cycle'] as const; +export type ProgressVariantPropType = (typeof progressVariantOptions)[number]; + +/** + * Defines the variant for displaying the progress component. + */ +export type PropVariantProgress = { + variant: ProgressVariantPropType; +}; + +const isProgressVariantPropType = (value: unknown): value is ProgressVariantPropType => { + return typeof value === 'string' && progressVariantOptions.includes(value as ProgressVariantPropType); +}; + +export const validateVariantProgress = (component: Generic.Element.Component, value?: ProgressVariantPropType): void => { + watchValidator(component, '_variant', isProgressVariantPropType, new Set(progressVariantOptions), value); +}; diff --git a/packages/components/src/schema/props/variant-quote.ts b/packages/components/src/schema/props/variant-quote.ts new file mode 100644 index 00000000000..43f0ce1f195 --- /dev/null +++ b/packages/components/src/schema/props/variant-quote.ts @@ -0,0 +1,21 @@ +import type { Generic } from 'adopted-style-sheets'; + +import { watchValidator } from '../utils'; + +export const quoteVariantOptions = ['block', 'inline'] as const; +export type QuoteVariantPropType = (typeof quoteVariantOptions)[number]; + +/** + * Defines the variant for presenting quotes. + */ +export type PropVariantQuote = { + variant: QuoteVariantPropType; +}; + +const isQuoteVariantPropType = (value: unknown): value is QuoteVariantPropType => { + return typeof value === 'string' && quoteVariantOptions.includes(value as QuoteVariantPropType); +}; + +export const validateVariantQuote = (component: Generic.Element.Component, value?: QuoteVariantPropType): void => { + watchValidator(component, '_variant', isQuoteVariantPropType, new Set(quoteVariantOptions), value); +}; diff --git a/packages/components/src/schema/props/width.ts b/packages/components/src/schema/props/width.ts new file mode 100644 index 00000000000..135cdfdb201 --- /dev/null +++ b/packages/components/src/schema/props/width.ts @@ -0,0 +1,18 @@ +import type { Generic } from 'adopted-style-sheets'; +import type { WatchStringOptions } from '../utils'; +import { watchString } from '../utils'; + +/* types */ +export type WidthPropType = string; + +/** + * Defines the width of the component. (max-width: 100%) + */ +export interface PropWidth { + width: WidthPropType; +} + +/* validator */ +export const validateWidth = (component: Generic.Element.Component, value?: WidthPropType, options?: WatchStringOptions): void => { + watchString(component, '_width', value, { defaultValue: '100%', ...options }); +}; diff --git a/packages/components/src/schema/types/index.ts b/packages/components/src/schema/types/index.ts index 7460f6e6b6d..62619163bfb 100644 --- a/packages/components/src/schema/types/index.ts +++ b/packages/components/src/schema/types/index.ts @@ -7,7 +7,6 @@ export * from './input/iso8601'; export * from './input/numberString'; export * from './input/types'; export * from './modal'; -export * from './progress'; export * from './table'; export * from './table-settings'; export * from './unknown'; diff --git a/packages/components/src/schema/types/progress.ts b/packages/components/src/schema/types/progress.ts deleted file mode 100644 index 6d7ce3961dc..00000000000 --- a/packages/components/src/schema/types/progress.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum KoliBriProgressVariantEnum { - 'bar' = 'bar', - 'cycle' = 'cycle', -} - -export type KoliBriProgressVariantType = `${KoliBriProgressVariantEnum}`; diff --git a/packages/components/src/schema/validators/index.ts b/packages/components/src/schema/validators/index.ts index 032c848bda3..c9496d04793 100644 --- a/packages/components/src/schema/validators/index.ts +++ b/packages/components/src/schema/validators/index.ts @@ -1,5 +1,4 @@ export * from './alignment'; export * from './common'; export * from './options'; -export * from './tab-index'; // export * from './window'; diff --git a/packages/samples/react/src/components/alert/basic.tsx b/packages/samples/react/src/components/alert/basic.tsx index 86f121c836e..71ce6ebab93 100644 --- a/packages/samples/react/src/components/alert/basic.tsx +++ b/packages/samples/react/src/components/alert/basic.tsx @@ -1,16 +1,16 @@ import React from 'react'; import { KolAlert } from '@public-ui/react'; import type { FC } from 'react'; -import type { AlertType, AlertVariant, HeadingLevel } from '@public-ui/components'; +import type { AlertTypePropType, AlertVariantPropType, HeadingLevel } from '@public-ui/components'; import { SampleDescription } from '../SampleDescription'; type PropsByType = { level: HeadingLevel; - type: AlertType; - variant: AlertVariant; + type: AlertTypePropType; + variant: AlertVariantPropType; }; type PropsBasic = { - variant?: AlertVariant; + variant?: AlertVariantPropType; }; const AlertByType: FC = ({ level, type, variant }) => ( diff --git a/packages/samples/react/src/components/toast/basic.tsx b/packages/samples/react/src/components/toast/basic.tsx index 0c43f238972..9ad9946255f 100644 --- a/packages/samples/react/src/components/toast/basic.tsx +++ b/packages/samples/react/src/components/toast/basic.tsx @@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom'; import { ToasterService } from '@public-ui/components'; import { KolButton } from '@public-ui/react'; -import type { AlertType, AlertVariant } from '@public-ui/components'; +import type { AlertTypePropType, AlertVariantPropType } from '@public-ui/components'; import { getRoot } from '../../shares/react-roots'; import { SampleDescription } from '../SampleDescription'; @@ -12,8 +12,8 @@ import type { FC } from 'react'; export const ToastBasic: FC = () => { const [searchParams] = useSearchParams(); - const defaultType = searchParams.get('type') as AlertType; - const defaultVariant = searchParams.get('variant') as AlertVariant; + const defaultType = searchParams.get('type') as AlertTypePropType; + const defaultVariant = searchParams.get('variant') as AlertVariantPropType; const toaster = ToasterService.getInstance(document); const handleButtonClickSimple = () => { void toaster.enqueue({