Skip to content

Commit f0ccb9e

Browse files
committed
docs: document prop usage
1 parent 93a254f commit f0ccb9e

File tree

13 files changed

+51
-75
lines changed

13 files changed

+51
-75
lines changed

packages/components/AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,11 @@ Use the `condition && <Element />` pattern to render JSX elements only when a co
3535
```
3636

3737
Avoid using `hidden={condition}` unless the element should always be present in the DOM but visually hidden.
38+
39+
### Props Handling
40+
41+
Every property lives in a dedicated file under `src/schema/props`. The file
42+
contains the prop type, the prop schema and a validator function. Components and
43+
their controllers must import these validators instead of implementing custom
44+
logic. Always use the validator exported from the prop schema to keep behaviour
45+
consistent across components.

packages/components/src/components/@deprecated/input/controller.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
validateHideLabel,
2727
validateLabelWithExpertSlot,
2828
validateMsg,
29+
validateHint,
2930
validateShortKey,
3031
validateTabIndex,
3132
validateTooltipAlign,
@@ -96,10 +97,11 @@ export class InputController extends ControlledInputController implements Watche
9697
}
9798

9899
public validateHint(value?: string): void {
99-
watchString(this.component, '_hint', value);
100+
validateHint(this.component, value);
100101
}
101102

102103
public validateId(value?: string): void {
104+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
103105
watchString(this.component, '_id', value, { minLength: 1 });
104106
if (value === '' || typeof value === 'undefined') {
105107
devHint(`A unique ID on the input fields is not strictly required, but it might be relevant for E2E tests.`);

packages/components/src/components/alert/component.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { JSX } from '@stencil/core';
2-
import { alertTypeOptions, alertVariantOptions, setState, validateHasCloser, validateLabel, watchBoolean, watchValidator } from '../../schema';
2+
import { setState, validateAlertType, validateAlertVariant, validateHasCloser, validateLabel, watchBoolean } from '../../schema';
33
import { Component, Element, h, Prop, State, Watch } from '@stencil/core';
44
import { watchHeadingLevel } from '../heading/validation';
55
import type {
@@ -147,24 +147,12 @@ export class KolAlertWc implements AlertAPI {
147147

148148
@Watch('_type')
149149
public validateType(value?: AlertTypePropType): void {
150-
watchValidator(
151-
this,
152-
'_type',
153-
(value?) => typeof value === 'string' && alertTypeOptions.includes(value),
154-
new Set(`String {${alertTypeOptions.join(', ')}`),
155-
value,
156-
);
150+
validateAlertType(this, value);
157151
}
158152

159153
@Watch('_variant')
160154
public validateVariant(value?: AlertVariantPropType): void {
161-
watchValidator(
162-
this,
163-
'_variant',
164-
(value?) => typeof value === 'string' && alertVariantOptions.includes(value),
165-
new Set(`AlertVariant {${alertVariantOptions.join(', ')}`),
166-
value,
167-
);
155+
validateAlertVariant(this, value);
168156
}
169157

170158
public componentWillLoad(): void {

packages/components/src/components/combobox/controller.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComboboxWatches, ComboboxProps, SuggestionsPropType } from '../../schema';
2-
import { watchBoolean, validateSuggestions, watchString } from '../../schema';
2+
import { validatePlaceholder, watchBoolean, validateSuggestions, watchString } from '../../schema';
33

44
import { InputIconController } from '../@deprecated/input/controller-icon';
55

@@ -14,7 +14,7 @@ export class ComboboxController extends InputIconController implements ComboboxW
1414
}
1515

1616
public validatePlaceholder(value?: string): void {
17-
watchString(this.component, '_placeholder', value);
17+
validatePlaceholder(this.component, value);
1818
}
1919
public validateRequired(value?: boolean): void {
2020
watchBoolean(this.component, '_required', value);
@@ -25,6 +25,7 @@ export class ComboboxController extends InputIconController implements ComboboxW
2525
}
2626

2727
public validateValue(value?: string): void {
28+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
2829
watchString(this.component, '_value', value);
2930
}
3031

packages/components/src/components/input-checkbox/controller.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
StencilUnknown,
1111
Stringified,
1212
} from '../../schema';
13-
import { inputCheckboxVariantOptions, isString, setState, validateChecked, validateIndeterminate, validateLabelAlign, watchValidator } from '../../schema';
13+
import { isString, setState, validateChecked, validateIndeterminate, validateLabelAlign, validateVariantInputCheckbox, watchValidator } from '../../schema';
1414

1515
import { InputCheckboxRadioController } from '../input-radio/controller';
1616

@@ -37,10 +37,11 @@ export class InputCheckboxController extends InputCheckboxRadioController implem
3737
}
3838

3939
public validateIcons(value?: Stringified<InputCheckboxIconsProp>): void {
40+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
4041
watchValidator(
4142
this.component,
4243
'_icons',
43-
(value): boolean => {
44+
(value?: Record<string, unknown>): boolean => {
4445
return typeof value === 'object' && value !== null && (isString(value.checked, 1) || isString(value.indeterminate, 1) || isString(value.unchecked, 1));
4546
},
4647
new Set(['InputCheckboxIcons']),
@@ -72,13 +73,7 @@ export class InputCheckboxController extends InputCheckboxRadioController implem
7273
}
7374

7475
public validateVariant(value?: InputCheckboxVariantPropType): void {
75-
watchValidator(
76-
this.component,
77-
'_variant',
78-
(value): boolean => typeof value === 'string' && inputCheckboxVariantOptions.includes(value),
79-
new Set([`String {${inputCheckboxVariantOptions.join(', ')}`]),
80-
value,
81-
);
76+
validateVariantInputCheckbox(this.component, value);
8277
}
8378

8479
public componentWillLoad(): void {

packages/components/src/components/input-date/controller.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
ReadOnlyPropType,
1010
SuggestionsPropType,
1111
} from '../../schema';
12-
import { inputDateTypeOptions, setState, validateReadOnly, validateSuggestions, watchBoolean, watchValidator } from '../../schema';
12+
import { setState, validateReadOnly, validateSuggestions, validateTypeInputDate, watchBoolean, watchValidator } from '../../schema';
1313

1414
import { InputIconController } from '../@deprecated/input/controller-icon';
1515

@@ -33,10 +33,11 @@ export class InputDateController extends InputIconController implements InputDat
3333
}
3434

3535
public validateAutoComplete(value?: InputTypeOnOff): void {
36+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
3637
watchValidator(
3738
this.component,
3839
'_autoComplete',
39-
(value): boolean => typeof value === 'string' && (value === 'on' || value === 'off'),
40+
(value: unknown): boolean => typeof value === 'string' && (value === 'on' || value === 'off'),
4041
new Set(['on | off']),
4142
value,
4243
);
@@ -129,15 +130,19 @@ export class InputDateController extends InputIconController implements InputDat
129130
}
130131

131132
private readonly validateIso8601 = (propName: string, value?: Date | Iso8601 | null, afterPatch?: (v: string) => void) => {
133+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
132134
return watchValidator(
135+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
133136
this.component,
134137
propName,
135-
(value): boolean => value === undefined || value === null || value === '' || this.validateDateString(value),
138+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
139+
(value: unknown): boolean => value === undefined || value === null || value === '' || this.validateDateString(value),
136140
new Set(['Date', 'string{ISO-8601}']),
141+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
137142
InputDateController.tryParseToString(value, this.component._type, this.component._step),
138143
{
139144
hooks: {
140-
afterPatch: (value) => {
145+
afterPatch: (value: string) => {
141146
if (typeof value === 'string' && afterPatch) {
142147
afterPatch(value);
143148
}
@@ -199,13 +204,7 @@ export class InputDateController extends InputIconController implements InputDat
199204
}
200205

201206
public validateType(value?: InputDateTypePropType): void {
202-
watchValidator(
203-
this.component,
204-
'_type',
205-
(value): boolean => typeof value === 'string' && inputDateTypeOptions.includes(value),
206-
new Set([`String {${inputDateTypeOptions.join(', ')}`]),
207-
value,
208-
);
207+
validateTypeInputDate(this.component, value);
209208
}
210209

211210
public validateValue(value?: Iso8601 | Date | null): void {

packages/components/src/components/input-number/controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { InputNumberProps, InputNumberWatches, InputTypeOnOff, NumberString, SuggestionsPropType } from '../../schema';
2-
import { validateSuggestions, watchBoolean, watchString, watchValidator } from '../../schema';
2+
import { validatePlaceholder, validateSuggestions, watchBoolean, watchValidator } from '../../schema';
33

44
import { InputIconController } from '../@deprecated/input/controller-icon';
55

@@ -35,7 +35,7 @@ export class InputNumberController extends InputIconController implements InputN
3535
}
3636

3737
public validatePlaceholder(value?: string): void {
38-
watchString(this.component, '_placeholder', value);
38+
validatePlaceholder(this.component, value);
3939
}
4040

4141
public validateReadOnly(value?: boolean): void {

packages/components/src/components/input-password/controller.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { InputPasswordProps, InputPasswordWatches, InputTypeOnOff } from '../../schema';
2-
import { validateHasCounter, watchBoolean, watchNumber, watchString, watchValidator } from '../../schema';
2+
import { validateHasCounter, validateMaxLength, validatePlaceholder, watchBoolean, watchString, watchValidator } from '../../schema';
33
import type { PasswordVariantPropType } from '../../schema/props/variant/password-variant';
44
import { validatePasswordVariant } from '../../schema/props/variant/password-variant';
55

@@ -44,11 +44,10 @@ export class InputPasswordController extends InputIconController implements Inpu
4444
}
4545

4646
public validateMaxLength(value?: number): void {
47-
watchNumber(this.component, '_maxLength', value, {
47+
validateMaxLength(this.component, value, {
4848
hooks: {
4949
afterPatch: this.afterSyncCharCounter,
5050
},
51-
min: 0,
5251
});
5352
}
5453

@@ -57,7 +56,7 @@ export class InputPasswordController extends InputIconController implements Inpu
5756
}
5857

5958
public validatePlaceholder(value?: string): void {
60-
watchString(this.component, '_placeholder', value);
59+
validatePlaceholder(this.component, value);
6160
}
6261

6362
public validateReadOnly(value?: boolean): void {

packages/components/src/components/input-text/controller.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77
SpellCheckPropType,
88
SuggestionsPropType,
99
} from '../../schema';
10-
import { inputTextTypeOptions, validateSpellCheck, validateSuggestions, watchValidator } from '../../schema';
10+
import { validateSpellCheck, validateSuggestions, validateTypeInputText } from '../../schema';
1111

1212
import { InputPasswordController } from '../input-password/controller';
1313

@@ -53,13 +53,7 @@ export class InputTextController extends InputTextEmailController implements Inp
5353
}
5454

5555
public validateType(value?: InputTextTypePropType): void {
56-
watchValidator(
57-
this.component,
58-
'_type',
59-
(value): boolean => typeof value === 'string' && inputTextTypeOptions.includes(value),
60-
new Set([`String {${inputTextTypeOptions.join(', ')}`]),
61-
value,
62-
);
56+
validateTypeInputText(this.component, value);
6357
}
6458

6559
public componentWillLoad(): void {

packages/components/src/components/progress/shadow.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { LabelPropType, ProgressAPI, ProgressStates, ProgressVariantPropType } from '../../schema';
2-
import { ProgressVariantEnum, validateLabel, watchNumber, watchString, watchValidator } from '../../schema';
2+
import { validateLabel, validateVariantProgress, watchNumber, watchString } from '../../schema';
33
import { Component, h, Prop, State, Watch } from '@stencil/core';
44

55
import type { JSX } from '@stencil/core';
6-
const VALID_VARIANTS = Object.keys(ProgressVariantEnum);
76

87
const CycleSvg = ({ state }: { state: ProgressStates }) => {
98
const fullCircle = 342;
@@ -183,7 +182,7 @@ export class KolProgress implements ProgressAPI {
183182

184183
@Watch('_variant')
185184
public validateVariant(value?: ProgressVariantPropType): void {
186-
watchValidator(this, '_variant', (value) => typeof value === 'string' && VALID_VARIANTS.includes(value), new Set(VALID_VARIANTS), value);
185+
validateVariantProgress(this, value);
187186
}
188187

189188
public componentWillLoad(): void {

0 commit comments

Comments
 (0)