From 5fcc7b0dfafa766f991e19308fd546ce20ebbada Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Tue, 30 Apr 2024 16:38:41 +0200 Subject: [PATCH 01/29] fix: a11y issue for all form components --- .../src/components/checkbox/checkbox.lite.tsx | 53 +++++++++---------- .../src/components/input/input.lite.tsx | 50 ++++++++--------- .../src/components/radio/radio.lite.tsx | 5 +- .../src/components/select/select.lite.tsx | 51 +++++++++--------- .../src/components/textarea/textarea.lite.tsx | 46 ++++++++-------- 5 files changed, 102 insertions(+), 103 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 65ec3f5de64..47c8c8da085 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -9,7 +9,6 @@ import { import { DBCheckboxProps, DBCheckboxState } from './model'; import { cls, uuid } from '../../utils'; import { - DEFAULT_ID, DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, DEFAULT_MESSAGE_ID_SUFFIX, @@ -29,11 +28,16 @@ export default function DBCheckbox(props: DBCheckboxProps) { // jscpd:ignore-start const state = useStore({ initialized: false, - _id: DEFAULT_ID, - _messageId: DEFAULT_ID + DEFAULT_MESSAGE_ID_SUFFIX, - _validMessageId: DEFAULT_ID + DEFAULT_VALID_MESSAGE_ID_SUFFIX, - _invalidMessageId: DEFAULT_ID + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: '', + _id: 'checkbox-' + uuid(), + _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, + _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, + _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + _descByIds: + this._messageId + + ' ' + + this._validMessageId + + ' ' + + this._invalidMessageId, handleChange: (event: ChangeEvent) => { if (props.onChange) { @@ -78,33 +82,27 @@ export default function DBCheckbox(props: DBCheckboxProps) { onMount(() => { state.initialized = true; - state._id = props.id || 'checkbox-' + uuid(); + state._id = props.id || state._id; }); onUpdate(() => { - if (state.initialized && state._id) { - state._messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; - state._validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; - state._invalidMessageId = + if (state._id) { + const messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; + const validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; + const invalidMessageId = state._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX; + state._messageId = messageId; + state._validMessageId = validMessageId; + state._invalidMessageId = invalidMessageId; + + state._descByIds = [ + messageId, + validMessageId, + invalidMessageId + ].join(' '); } - }, [state._id, state.initialized]); + }, [state._id]); - onUpdate(() => { - const descByIds = [state._validMessageId, state._invalidMessageId]; - if (props.message) { - descByIds.push(state._messageId); - } - state._descByIds = descByIds.join(' '); - }, [ - props.message, - state._messageId, - state._validMessageId, - state._invalidMessageId - ]); - // jscpd:ignore-end - - // TODO we have to check how to update on every change.. onUpdate(() => { if (state.initialized && document && state._id) { const checkboxElement = document?.getElementById( @@ -124,6 +122,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { } } }, [state.initialized, props.indeterminate, props.checked]); + // jscpd:ignore-end return (
(null); // jscpd:ignore-start const state = useStore({ - _id: DEFAULT_ID, - _messageId: DEFAULT_ID + DEFAULT_MESSAGE_ID_SUFFIX, - _validMessageId: DEFAULT_ID + DEFAULT_VALID_MESSAGE_ID_SUFFIX, - _invalidMessageId: DEFAULT_ID + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: '', - _dataListId: DEFAULT_ID, + _id: 'input-' + uuid(), + _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, + _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, + _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + _descByIds: + this._messageId + + ' ' + + this._validMessageId + + ' ' + + this._invalidMessageId, + _dataListId: `datalist-` + uuid(), defaultValues: { label: DEFAULT_LABEL, placeholder: ' ' @@ -96,31 +100,27 @@ export default function DBInput(props: DBInputProps) { }); onMount(() => { - state._id = props.id || 'input-' + uuid(); - state._dataListId = props.dataListId || `datalist-${uuid()}`; + state._id = props.id ?? state._id; + state._dataListId = props.dataListId ?? state._dataListId; }); onUpdate(() => { if (state._id) { - state._messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; - state._validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; - state._invalidMessageId = + const messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; + const validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; + const invalidMessageId = state._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX; - } - }, [state._id]); + state._messageId = messageId; + state._validMessageId = validMessageId; + state._invalidMessageId = invalidMessageId; - onUpdate(() => { - const descByIds = [state._validMessageId, state._invalidMessageId]; - if (props.message) { - descByIds.push(state._messageId); + state._descByIds = [ + messageId, + validMessageId, + invalidMessageId + ].join(' '); } - state._descByIds = descByIds.join(' '); - }, [ - props.message, - state._messageId, - state._validMessageId, - state._invalidMessageId - ]); + }, [state._id]); return (
({ initialized: false, - _id: DEFAULT_ID, + _id: 'radio-' + uuid(), handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); @@ -55,7 +54,7 @@ export default function DBRadio(props: DBRadioProps) { onMount(() => { state.initialized = true; - state._id = props.id || 'radio-' + uuid(); + state._id = props.id ?? state._id; }); // jscpd:ignore-end diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index d9947f50db0..51c22b98ca6 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -10,7 +10,6 @@ import { import { DBSelectOptionType, DBSelectProps, DBSelectState } from './model'; import { cls, uuid } from '../../utils'; import { - DEFAULT_ID, DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, DEFAULT_LABEL, @@ -31,12 +30,17 @@ export default function DBSelect(props: DBSelectProps) { const ref = useRef(null); // jscpd:ignore-start const state = useStore({ - _id: DEFAULT_ID, - _messageId: DEFAULT_ID + DEFAULT_MESSAGE_ID_SUFFIX, - _validMessageId: DEFAULT_ID + DEFAULT_VALID_MESSAGE_ID_SUFFIX, - _invalidMessageId: DEFAULT_ID + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: '', - _placeholderId: DEFAULT_ID + DEFAULT_PLACEHOLDER_ID_SUFFIX, + _id: 'select-' + uuid(), + _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, + _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, + _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + _descByIds: + this._messageId + + ' ' + + this._validMessageId + + ' ' + + this._invalidMessageId, + _placeholderId: this._id + DEFAULT_PLACEHOLDER_ID_SUFFIX, handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); @@ -87,31 +91,28 @@ export default function DBSelect(props: DBSelectProps) { }); onMount(() => { - state._id = props.id || 'select-' + uuid(); + state._id = props.id || state._id; }); onUpdate(() => { if (state._id) { - state._placeholderId = state._id + DEFAULT_PLACEHOLDER_ID_SUFFIX; - state._messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; - state._validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; - state._invalidMessageId = + const messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; + const validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; + const invalidMessageId = state._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX; - } - }, [state._id]); + const placeholderId = state._id + DEFAULT_PLACEHOLDER_ID_SUFFIX; + state._messageId = messageId; + state._validMessageId = validMessageId; + state._invalidMessageId = invalidMessageId; - onUpdate(() => { - const descByIds = [state._validMessageId, state._invalidMessageId]; - if (props.message) { - descByIds.push(state._messageId); + state._descByIds = [ + messageId, + validMessageId, + invalidMessageId, + placeholderId + ].join(' '); } - state._descByIds = descByIds.join(' '); - }, [ - props.message, - state._messageId, - state._validMessageId, - state._invalidMessageId - ]); + }, [state._id]); return (
(null); // jscpd:ignore-start const state = useStore({ - _id: DEFAULT_ID, - _messageId: DEFAULT_ID + DEFAULT_MESSAGE_ID_SUFFIX, - _validMessageId: DEFAULT_ID + DEFAULT_VALID_MESSAGE_ID_SUFFIX, - _invalidMessageId: DEFAULT_ID + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: '', + _id: 'textarea-' + uuid(), + _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, + _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, + _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + _descByIds: + this._messageId + + ' ' + + this._validMessageId + + ' ' + + this._invalidMessageId, defaultValues: { label: DEFAULT_LABEL, placeholder: ' ', @@ -90,30 +94,26 @@ export default function DBTextarea(props: DBTextareaProps) { }); onMount(() => { - state._id = props.id || 'textarea-' + uuid(); + state._id = props.id || state._id; }); onUpdate(() => { if (state._id) { - state._messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; - state._validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; - state._invalidMessageId = + const messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; + const validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; + const invalidMessageId = state._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX; - } - }, [state._id]); + state._messageId = messageId; + state._validMessageId = validMessageId; + state._invalidMessageId = invalidMessageId; - onUpdate(() => { - const descByIds = [state._validMessageId, state._invalidMessageId]; - if (props.message) { - descByIds.push(state._messageId); + state._descByIds = [ + messageId, + validMessageId, + invalidMessageId + ].join(' '); } - state._descByIds = descByIds.join(' '); - }, [ - props.message, - state._messageId, - state._validMessageId, - state._invalidMessageId - ]); + }, [state._id]); return (
Date: Tue, 30 Apr 2024 16:43:27 +0200 Subject: [PATCH 02/29] fix: a11y issue for switch --- packages/components/src/components/switch/switch.lite.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/switch/switch.lite.tsx b/packages/components/src/components/switch/switch.lite.tsx index f4df30ce26b..318a1b1e012 100644 --- a/packages/components/src/components/switch/switch.lite.tsx +++ b/packages/components/src/components/switch/switch.lite.tsx @@ -14,7 +14,7 @@ export default function DBSwitch(props: DBSwitchProps) { const ref = useRef(null); // jscpd:ignore-start const state = useStore({ - _id: DEFAULT_ID, + _id: 'switch-' + uuid(), initialized: false, handleChange: (event: ChangeEvent) => { if (props.onChange) { @@ -47,7 +47,7 @@ export default function DBSwitch(props: DBSwitchProps) { }); onMount(() => { - state._id = props.id || 'switch-' + uuid(); + state._id = props.id || state._id; }); // jscpd:ignore-end From dabcf9427db9934df6234f561a4f2beceb86f03e Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Wed, 8 May 2024 16:55:19 +0200 Subject: [PATCH 03/29] fix: issue from PR --- .../src/components/checkbox/checkbox.lite.tsx | 27 ++++++++------- .../src/components/input/input.lite.tsx | 30 +++++++++------- .../src/components/select/select.lite.tsx | 34 ++++++++++--------- .../src/components/textarea/textarea.lite.tsx | 29 +++++++++------- 4 files changed, 66 insertions(+), 54 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 6fad8cbe9b5..a982f0e71a2 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -32,13 +32,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: - this._messageId + - ' ' + - this._validMessageId + - ' ' + - this._invalidMessageId, - + _descByIds: this._messageId, handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); @@ -48,6 +42,19 @@ export default function DBCheckbox(props: DBCheckboxProps) { props.change(event); } handleFrameworkEvent(this, event, 'checked'); + + if (!ref?.validity.valid || props.customValidity === 'invalid') { + state._descByIds = state._invalidMessageId; + } else if ( + props.customValidity === 'valid' || + (ref?.validity.valid && props.required) + ) { + state._descByIds = state._validMessageId; + } else if (props.message) { + state._descByIds = state._messageId; + } else { + state._descByIds = ''; + } }, handleBlur: (event: InteractionEvent) => { if (props.onBlur) { @@ -93,12 +100,6 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; - - state._descByIds = [ - messageId, - validMessageId, - invalidMessageId - ].join(' '); } }, [state._id]); diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 16e2743af02..2693b1ff5ba 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -38,13 +38,8 @@ export default function DBInput(props: DBInputProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: - this._messageId + - ' ' + - this._validMessageId + - ' ' + - this._invalidMessageId, _dataListId: `datalist-` + uuid(), + _descByIds: this._messageId, defaultValues: { label: DEFAULT_LABEL, placeholder: ' ' @@ -57,6 +52,23 @@ export default function DBInput(props: DBInputProps) { if (props.input) { props.input(event); } + + if (!ref?.validity.valid || props.customValidity === 'invalid') { + state._descByIds = state._invalidMessageId; + } else if ( + props.customValidity === 'valid' || + (ref?.validity.valid && + (props.required || + props.minLength || + props.maxLength || + props.pattern)) + ) { + state._descByIds = state._validMessageId; + } else if (props.message) { + state._descByIds = state._messageId; + } else { + state._descByIds = ''; + } }, handleChange: (event: ChangeEvent) => { if (props.onChange) { @@ -113,12 +125,6 @@ export default function DBInput(props: DBInputProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; - - state._descByIds = [ - messageId, - validMessageId, - invalidMessageId - ].join(' '); } }, [state._id]); diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 51c22b98ca6..57dda666571 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -34,13 +34,8 @@ export default function DBSelect(props: DBSelectProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: - this._messageId + - ' ' + - this._validMessageId + - ' ' + - this._invalidMessageId, _placeholderId: this._id + DEFAULT_PLACEHOLDER_ID_SUFFIX, + _descByIds: this._placeholderId + ' ' + this._messageId, handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); @@ -56,6 +51,21 @@ export default function DBSelect(props: DBSelectProps) { } handleFrameworkEvent(this, event); + + if (!ref?.validity.valid || props.customValidity === 'invalid') { + state._descByIds = + this._placeholderId + ' ' + state._invalidMessageId; + } else if ( + props.customValidity === 'valid' || + (ref?.validity.valid && props.required) + ) { + state._descByIds = + this._placeholderId + ' ' + state._validMessageId; + } else if (props.message) { + state._descByIds = this._placeholderId + ' ' + state._messageId; + } else { + state._descByIds = this._placeholderId; + } }, handleBlur: (event: InteractionEvent) => { if (props.onBlur) { @@ -104,13 +114,7 @@ export default function DBSelect(props: DBSelectProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; - - state._descByIds = [ - messageId, - validMessageId, - invalidMessageId, - placeholderId - ].join(' '); + state._invalidMessageId = placeholderId; } }, [state._id]); @@ -142,9 +146,7 @@ export default function DBSelect(props: DBSelectProps) { onFocus={(event: InteractionEvent) => state.handleFocus(event) } - aria-describedby={ - (props.message && state._messageId) || state._placeholderId - }> + aria-describedby={state._descByIds}> {/* Empty option for floating label */} diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index 2e052da8689..a63136a996d 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -32,12 +32,7 @@ export default function DBTextarea(props: DBTextareaProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: - this._messageId + - ' ' + - this._validMessageId + - ' ' + - this._invalidMessageId, + _descByIds: this._messageId, defaultValues: { label: DEFAULT_LABEL, placeholder: ' ', @@ -51,6 +46,20 @@ export default function DBTextarea(props: DBTextareaProps) { if (props.input) { props.input(event); } + + if (!ref?.validity.valid || props.customValidity === 'invalid') { + state._descByIds = state._invalidMessageId; + } else if ( + props.customValidity === 'valid' || + (ref?.validity.valid && + (props.required || props.minLength || props.maxLength)) + ) { + state._descByIds = state._validMessageId; + } else if (props.message) { + state._descByIds = state._messageId; + } else { + state._descByIds = ''; + } }, handleChange: (event: ChangeEvent) => { if (props.onChange) { @@ -106,12 +115,6 @@ export default function DBTextarea(props: DBTextareaProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; - - state._descByIds = [ - messageId, - validMessageId, - invalidMessageId - ].join(' '); } }, [state._id]); @@ -152,7 +155,7 @@ export default function DBTextarea(props: DBTextareaProps) { state.handleFocus(event) } value={props.value} - aria-describedby={props.message && state._messageId} + aria-describedby={state._descByIds} placeholder={ props.placeholder ?? state.defaultValues.placeholder } From 28d00c9ce3d20dbfc94ae286f47a0f060420e282 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Wed, 8 May 2024 17:24:12 +0200 Subject: [PATCH 04/29] fix: issue with vue --- packages/components/src/components/checkbox/checkbox.lite.tsx | 2 +- packages/components/src/components/input/input.lite.tsx | 2 +- packages/components/src/components/textarea/textarea.lite.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index a982f0e71a2..1750b3c2315 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -32,7 +32,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: this._messageId, + _descByIds: `${this._messageId}`, handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 2693b1ff5ba..c8aa974b45f 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -39,7 +39,7 @@ export default function DBInput(props: DBInputProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _dataListId: `datalist-` + uuid(), - _descByIds: this._messageId, + _descByIds: `${this._messageId}`, defaultValues: { label: DEFAULT_LABEL, placeholder: ' ' diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index a63136a996d..ec2404b8702 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -32,7 +32,7 @@ export default function DBTextarea(props: DBTextareaProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _descByIds: this._messageId, + _descByIds: `${this._messageId}`, defaultValues: { label: DEFAULT_LABEL, placeholder: ' ', From 91b2e607811613599d91d3ef771eb0f24bb009cf Mon Sep 17 00:00:00 2001 From: Nicolas Merget <104347736+nmerget@users.noreply.github.com> Date: Fri, 10 May 2024 08:57:51 +0200 Subject: [PATCH 05/29] Update packages/components/src/components/select/select.lite.tsx Co-authored-by: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> --- packages/components/src/components/select/select.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 57dda666571..3b4e54f04a5 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -114,7 +114,7 @@ export default function DBSelect(props: DBSelectProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; - state._invalidMessageId = placeholderId; + state._placeholderId = placeholderId; } }, [state._id]); From ded12f94a398d706b5cf7ca16a8e68ae54d63d25 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 10 May 2024 09:19:30 +0200 Subject: [PATCH 06/29] Update checkbox.lite.tsx --- packages/components/src/components/checkbox/checkbox.lite.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 1750b3c2315..4245db326ef 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -32,6 +32,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string _descByIds: `${this._messageId}`, handleChange: (event: ChangeEvent) => { if (props.onChange) { From 286eae3f172b71df853ced1705f79ebdec51b98f Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 10 May 2024 09:19:44 +0200 Subject: [PATCH 07/29] Update input.lite.tsx --- packages/components/src/components/input/input.lite.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index c8aa974b45f..1af6fa70a86 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -39,6 +39,7 @@ export default function DBInput(props: DBInputProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _dataListId: `datalist-` + uuid(), + // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string _descByIds: `${this._messageId}`, defaultValues: { label: DEFAULT_LABEL, From 524e89227888c27185ea6eef68151948b78a55e1 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 10 May 2024 09:19:53 +0200 Subject: [PATCH 08/29] Update textarea.lite.tsx --- packages/components/src/components/textarea/textarea.lite.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index ec2404b8702..38bff5d6487 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -32,6 +32,7 @@ export default function DBTextarea(props: DBTextareaProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, + // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string _descByIds: `${this._messageId}`, defaultValues: { label: DEFAULT_LABEL, From 4ad533c456b42cddf38a43923fe79bb6d703631e Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 10 May 2024 09:20:34 +0200 Subject: [PATCH 09/29] Update input.lite.tsx --- packages/components/src/components/input/input.lite.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 1af6fa70a86..e3e929ede32 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -38,7 +38,7 @@ export default function DBInput(props: DBInputProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _dataListId: `datalist-` + uuid(), + _dataListId: 'datalist-' + uuid(), // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string _descByIds: `${this._messageId}`, defaultValues: { From 613e97141a097fa3fb2cba778f62f36511bafc3f Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Fri, 10 May 2024 10:44:20 +0200 Subject: [PATCH 10/29] fix: issues from PR --- packages/components/src/components/input/input.lite.tsx | 3 ++- packages/components/src/shared/constants.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index c8aa974b45f..62844bafdb0 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -10,6 +10,7 @@ import { import { cls, uuid } from '../../utils'; import { DBInputProps, DBInputState } from './model'; import { + DEFAULT_DATALIST_ID_SUFFIX, DEFAULT_INVALID_MESSAGE, DEFAULT_INVALID_MESSAGE_ID_SUFFIX, DEFAULT_LABEL, @@ -38,7 +39,7 @@ export default function DBInput(props: DBInputProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - _dataListId: `datalist-` + uuid(), + _dataListId: this._id + DEFAULT_DATALIST_ID_SUFFIX, _descByIds: `${this._messageId}`, defaultValues: { label: DEFAULT_LABEL, diff --git a/packages/components/src/shared/constants.ts b/packages/components/src/shared/constants.ts index 682cd0b3e76..7307b53366a 100644 --- a/packages/components/src/shared/constants.ts +++ b/packages/components/src/shared/constants.ts @@ -5,6 +5,7 @@ export const DEFAULT_MESSAGE_ID_SUFFIX: string = '-message'; export const DEFAULT_VALID_MESSAGE_ID_SUFFIX: string = '-valid-message'; export const DEFAULT_INVALID_MESSAGE_ID_SUFFIX: string = '-invalid-message'; export const DEFAULT_PLACEHOLDER_ID_SUFFIX: string = '-placeholder'; +export const DEFAULT_DATALIST_ID_SUFFIX: string = '-placeholder'; export const DEFAULT_VALID_MESSAGE: string = 'TODO: Add a validMessage'; export const DEFAULT_INVALID_MESSAGE: string = 'TODO: Add an invalidMessage'; From 315e2e0a2308d501bbceb18c55d2a7a954d61a03 Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Fri, 10 May 2024 15:16:04 +0200 Subject: [PATCH 11/29] fix: issues with form-components --- .../components/scripts/post-build/angular.js | 8 ++ .../scripts/post-build/components.js | 7 ++ packages/components/scripts/post-build/vue.js | 14 ++++ .../src/components/checkbox/checkbox.lite.tsx | 22 +++--- .../src/components/checkbox/model.ts | 16 ++-- .../src/components/input/input.lite.tsx | 54 ++++++------- .../components/src/components/input/model.ts | 4 +- .../components/src/components/select/model.ts | 16 +++- .../src/components/select/select.lite.tsx | 75 +++++++++++++------ .../src/components/textarea/model.ts | 6 +- .../src/components/textarea/textarea.lite.tsx | 53 ++++++------- packages/components/src/shared/model.ts | 6 +- .../checkbox/checkbox.component.html | 1 - .../src/components/select/index.tsx | 35 +++++---- showcases/shared/select.json | 6 +- .../src/components/textarea/Textarea.vue | 2 +- 16 files changed, 196 insertions(+), 129 deletions(-) diff --git a/packages/components/scripts/post-build/angular.js b/packages/components/scripts/post-build/angular.js index 58fd1d6a614..5bb1364a035 100644 --- a/packages/components/scripts/post-build/angular.js +++ b/packages/components/scripts/post-build/angular.js @@ -17,6 +17,14 @@ const changeFile = (component, input) => { return line.replace(': ElementRef', ': ElementRef | undefined'); } + // We need to remove "nativeElement" in template part, because it only exists in ts + if ( + line.includes('ref.nativeElement') && + (line.includes('{{') || line.includes('}}')) + ) { + return line.replace('.nativeElement', ''); + } + if (line.includes('.nativeElement') && !line.includes('=')) { return line.replace('.nativeElement', '?.nativeElement'); } diff --git a/packages/components/scripts/post-build/components.js b/packages/components/scripts/post-build/components.js index 385ee0eed31..a894e0e6f23 100644 --- a/packages/components/scripts/post-build/components.js +++ b/packages/components/scripts/post-build/components.js @@ -153,6 +153,13 @@ const getComponents = () => [ { name: 'select', + overwrites: { + react: [ + // React not allowing selected for options + { from: 'selected={option.selected}', to: '' }, + { from: 'selected={optgroupOption.selected}', to: '' } + ] + }, config: { vue: { vModel: [{ modelValue: 'value', binding: ':value' }] diff --git a/packages/components/scripts/post-build/vue.js b/packages/components/scripts/post-build/vue.js index 5c049d5697a..7ae46779655 100644 --- a/packages/components/scripts/post-build/vue.js +++ b/packages/components/scripts/post-build/vue.js @@ -64,6 +64,20 @@ module.exports = (tmp) => { } ]; + // This is a workaround for valid/invalidMessages resetting values + [ + 'HTMLSelectElement', + 'HTMLInputElement', + 'HTMLTextAreaElement' + ].forEach((element) => { + replacements.push({ + from: `handleInput(event: InputEvent<${element}>) {`, + to: + `handleInput(event: InputEvent<${element}>) {\n` + + 'this._value = (event.target as any).value;' + }); + }); + Replace.sync({ files: vueFile, processor(input) { diff --git a/packages/components/src/components/checkbox/checkbox.lite.tsx b/packages/components/src/components/checkbox/checkbox.lite.tsx index 4245db326ef..98faf63fb8f 100644 --- a/packages/components/src/components/checkbox/checkbox.lite.tsx +++ b/packages/components/src/components/checkbox/checkbox.lite.tsx @@ -32,8 +32,7 @@ export default function DBCheckbox(props: DBCheckboxProps) { _messageId: this._id + DEFAULT_MESSAGE_ID_SUFFIX, _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, - // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string - _descByIds: `${this._messageId}`, + _descByIds: '', handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); @@ -78,12 +77,9 @@ export default function DBCheckbox(props: DBCheckboxProps) { getValidMessage: () => { return props.validMessage || DEFAULT_VALID_MESSAGE; }, + getInvalidMessage: () => { - return ( - props.invalidMessage || - ref?.validationMessage || - DEFAULT_INVALID_MESSAGE - ); + return ''; } }); @@ -101,6 +97,10 @@ export default function DBCheckbox(props: DBCheckboxProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; + + if (props.message) { + state._descByIds = messageId; + } } }, [state._id]); @@ -120,6 +120,8 @@ export default function DBCheckbox(props: DBCheckboxProps) { // It has no accessibility or UX implications. (https://mui.com/material-ui/react-checkbox/) checkboxElement.indeterminate = props.indeterminate; } + + state.initialized = false; } } }, [state.initialized, props.indeterminate, props.checked]); @@ -172,14 +174,16 @@ export default function DBCheckbox(props: DBCheckboxProps) { id={state._validMessageId} size="small" semantic="successful"> - {state.getValidMessage()} + {props.validMessage ?? DEFAULT_VALID_MESSAGE} - {state.getInvalidMessage()} + {props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE}
); diff --git a/packages/components/src/components/checkbox/model.ts b/packages/components/src/components/checkbox/model.ts index 7a6f324ffac..27d2af17afe 100644 --- a/packages/components/src/components/checkbox/model.ts +++ b/packages/components/src/components/checkbox/model.ts @@ -1,16 +1,15 @@ import { + ChangeEventProps, + ChangeEventState, FocusEventProps, FocusEventState, - ChangeEventState, - ChangeEventProps, - GlobalProps, - GlobalState, + FormCheckProps, + FormMessageProps, FormProps, FormState, - FormCheckProps, + GlobalProps, + GlobalState, InitializedState, - FormMessageProps, - FormMessageState, SizeProps } from '../../shared/model'; @@ -37,5 +36,4 @@ export type DBCheckboxState = DBCheckboxDefaultState & ChangeEventState & FocusEventState & FormState & - InitializedState & - FormMessageState; + InitializedState; diff --git a/packages/components/src/components/input/input.lite.tsx b/packages/components/src/components/input/input.lite.tsx index 0f1435ec5b4..f5fa68745f9 100644 --- a/packages/components/src/components/input/input.lite.tsx +++ b/packages/components/src/components/input/input.lite.tsx @@ -40,8 +40,8 @@ export default function DBInput(props: DBInputProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _dataListId: this._id + DEFAULT_DATALIST_ID_SUFFIX, - // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string - _descByIds: `${this._messageId}`, + _descByIds: 'none', + _value: '', defaultValues: { label: DEFAULT_LABEL, placeholder: ' ' @@ -54,6 +54,17 @@ export default function DBInput(props: DBInputProps) { if (props.input) { props.input(event); } + }, + handleChange: (event: ChangeEvent) => { + if (props.onChange) { + props.onChange(event); + } + + if (props.change) { + props.change(event); + } + + handleFrameworkEvent(this, event); if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; @@ -69,19 +80,8 @@ export default function DBInput(props: DBInputProps) { } else if (props.message) { state._descByIds = state._messageId; } else { - state._descByIds = ''; - } - }, - handleChange: (event: ChangeEvent) => { - if (props.onChange) { - props.onChange(event); + state._descByIds = 'none'; } - - if (props.change) { - props.change(event); - } - - handleFrameworkEvent(this, event); }, handleBlur: (event: InteractionEvent) => { if (props.onBlur) { @@ -100,16 +100,6 @@ export default function DBInput(props: DBInputProps) { if (props.focus) { props.focus(event); } - }, - getValidMessage: () => { - return props.validMessage || DEFAULT_VALID_MESSAGE; - }, - getInvalidMessage: () => { - return ( - props.invalidMessage || - ref?.validationMessage || - DEFAULT_INVALID_MESSAGE - ); } }); @@ -127,9 +117,17 @@ export default function DBInput(props: DBInputProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; + + if (props.message) { + state._descByIds = messageId; + } } }, [state._id]); + onUpdate(() => { + state._value = props.value; + }, [props.value]); + return (
- {state.getValidMessage()} + {props.validMessage ?? DEFAULT_VALID_MESSAGE} - {state.getInvalidMessage()} + {props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE}
); diff --git a/packages/components/src/components/input/model.ts b/packages/components/src/components/input/model.ts index 075a8e810bf..df2ba2b5a19 100644 --- a/packages/components/src/components/input/model.ts +++ b/packages/components/src/components/input/model.ts @@ -4,7 +4,6 @@ import { FocusEventProps, FocusEventState, FormMessageProps, - FormMessageState, FormProps, FormState, FormTextProps, @@ -77,5 +76,4 @@ export type DBInputState = DBInputDefaultState & InputEventState & ChangeEventState & FocusEventState & - FormState & - FormMessageState; + FormState; diff --git a/packages/components/src/components/select/model.ts b/packages/components/src/components/select/model.ts index dc60d3dcc5d..6af02821be7 100644 --- a/packages/components/src/components/select/model.ts +++ b/packages/components/src/components/select/model.ts @@ -6,12 +6,14 @@ import { FocusEventProps, FocusEventState, FormMessageProps, - FormMessageState, FormProps, FormState, GlobalProps, GlobalState, - IconProps + IconProps, + InitializedState, + InputEventProps, + InputEventState } from '../../shared/model'; export interface DBSelectDefaultProps { @@ -35,9 +37,13 @@ export type DBSelectOptionType = { /** * Disables this option */ - // Disables this option disabled?: boolean; + /** + * Selects this option + */ + selected?: boolean; + /** * If the value is different from the label you want to show to the user. */ @@ -59,6 +65,7 @@ export type DBSelectProps = DBSelectDefaultProps & ClickEventProps & ChangeEventProps & FocusEventProps & + InputEventProps & FormProps & IconProps & FormMessageProps; @@ -73,5 +80,6 @@ export type DBSelectState = DBSelectDefaultState & ClickEventState & ChangeEventState & FocusEventState & + InputEventState & FormState & - FormMessageState; + InitializedState; diff --git a/packages/components/src/components/select/select.lite.tsx b/packages/components/src/components/select/select.lite.tsx index 3b4e54f04a5..eab8b0f78fc 100644 --- a/packages/components/src/components/select/select.lite.tsx +++ b/packages/components/src/components/select/select.lite.tsx @@ -19,7 +19,12 @@ import { DEFAULT_VALID_MESSAGE_ID_SUFFIX } from '../../shared/constants'; import { DBInfotext } from '../infotext'; -import { ChangeEvent, ClickEvent, InteractionEvent } from '../../shared/model'; +import { + ChangeEvent, + ClickEvent, + InputEvent, + InteractionEvent +} from '../../shared/model'; import { handleFrameworkEvent } from '../../utils/form-components'; useMetadata({ @@ -35,12 +40,24 @@ export default function DBSelect(props: DBSelectProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, _placeholderId: this._id + DEFAULT_PLACEHOLDER_ID_SUFFIX, - _descByIds: this._placeholderId + ' ' + this._messageId, + // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string + _descByIds: 'none', + _value: '', + initialized: false, handleClick: (event: ClickEvent) => { if (props.onClick) { props.onClick(event); } }, + handleInput: (event: InputEvent) => { + if (props.onInput) { + props.onInput(event); + } + + if (props.input) { + props.input(event); + } + }, handleChange: (event: ChangeEvent) => { if (props.onChange) { props.onChange(event); @@ -53,18 +70,16 @@ export default function DBSelect(props: DBSelectProps) { handleFrameworkEvent(this, event); if (!ref?.validity.valid || props.customValidity === 'invalid') { - state._descByIds = - this._placeholderId + ' ' + state._invalidMessageId; + state._descByIds = state._invalidMessageId; } else if ( props.customValidity === 'valid' || (ref?.validity.valid && props.required) ) { - state._descByIds = - this._placeholderId + ' ' + state._validMessageId; + state._descByIds = state._validMessageId; } else if (props.message) { - state._descByIds = this._placeholderId + ' ' + state._messageId; + state._descByIds = state._messageId; } else { - state._descByIds = this._placeholderId; + state._descByIds = state._placeholderId; } }, handleBlur: (event: InteractionEvent) => { @@ -87,25 +102,16 @@ export default function DBSelect(props: DBSelectProps) { }, getOptionLabel: (option: DBSelectOptionType) => { return option.label ?? option.value.toString(); - }, - getValidMessage: () => { - return props.validMessage || DEFAULT_VALID_MESSAGE; - }, - getInvalidMessage: () => { - return ( - props.invalidMessage || - ref?.validationMessage || - DEFAULT_INVALID_MESSAGE - ); } }); onMount(() => { state._id = props.id || state._id; + state.initialized = true; }); onUpdate(() => { - if (state._id) { + if (state._id && state.initialized) { const messageId = state._id + DEFAULT_MESSAGE_ID_SUFFIX; const validMessageId = state._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX; const invalidMessageId = @@ -115,8 +121,20 @@ export default function DBSelect(props: DBSelectProps) { state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; state._placeholderId = placeholderId; + + if (props.message) { + state._descByIds = messageId; + } else { + state._descByIds = placeholderId; + } + + state.initialized = false; } - }, [state._id]); + }, [state._id, state.initialized]); + + onUpdate(() => { + state._value = props.value; + }, [props.value]); return (
) => + state.handleInput(event) + } onClick={(event: ClickEvent) => state.handleClick(event) } @@ -163,6 +184,9 @@ export default function DBSelect(props: DBSelectProps) {
); diff --git a/packages/components/src/components/textarea/model.ts b/packages/components/src/components/textarea/model.ts index 865bbefb608..74d9f868182 100644 --- a/packages/components/src/components/textarea/model.ts +++ b/packages/components/src/components/textarea/model.ts @@ -4,12 +4,11 @@ import { FocusEventProps, FocusEventState, FormMessageProps, - FormMessageState, FormProps, FormState, + FormTextProps, GlobalProps, GlobalState, - FormTextProps, InputEventProps, InputEventState } from '../../shared/model'; @@ -54,5 +53,4 @@ export type DBTextareaState = DBTextareaDefaultState & InputEventState & FocusEventState & FormState & - GlobalState & - FormMessageState; + GlobalState; diff --git a/packages/components/src/components/textarea/textarea.lite.tsx b/packages/components/src/components/textarea/textarea.lite.tsx index 38bff5d6487..e90aba0b1a4 100644 --- a/packages/components/src/components/textarea/textarea.lite.tsx +++ b/packages/components/src/components/textarea/textarea.lite.tsx @@ -33,7 +33,8 @@ export default function DBTextarea(props: DBTextareaProps) { _validMessageId: this._id + DEFAULT_VALID_MESSAGE_ID_SUFFIX, _invalidMessageId: this._id + DEFAULT_INVALID_MESSAGE_ID_SUFFIX, // Workaround for Vue output: TS for Vue would think that it could be a function, and by this we clarify that it's a string - _descByIds: `${this._messageId}`, + _descByIds: 'none', + _value: '', defaultValues: { label: DEFAULT_LABEL, placeholder: ' ', @@ -47,6 +48,17 @@ export default function DBTextarea(props: DBTextareaProps) { if (props.input) { props.input(event); } + }, + handleChange: (event: ChangeEvent) => { + if (props.onChange) { + props.onChange(event); + } + + if (props.change) { + props.change(event); + } + + handleFrameworkEvent(this, event); if (!ref?.validity.valid || props.customValidity === 'invalid') { state._descByIds = state._invalidMessageId; @@ -59,19 +71,8 @@ export default function DBTextarea(props: DBTextareaProps) { } else if (props.message) { state._descByIds = state._messageId; } else { - state._descByIds = ''; - } - }, - handleChange: (event: ChangeEvent) => { - if (props.onChange) { - props.onChange(event); + state._descByIds = 'none'; } - - if (props.change) { - props.change(event); - } - - handleFrameworkEvent(this, event); }, handleBlur: (event: InteractionEvent) => { if (props.onBlur) { @@ -90,16 +91,6 @@ export default function DBTextarea(props: DBTextareaProps) { if (props.focus) { props.focus(event); } - }, - getValidMessage: () => { - return props.validMessage || DEFAULT_VALID_MESSAGE; - }, - getInvalidMessage: () => { - return ( - props.invalidMessage || - ref?.validationMessage || - DEFAULT_INVALID_MESSAGE - ); } }); @@ -116,9 +107,17 @@ export default function DBTextarea(props: DBTextareaProps) { state._messageId = messageId; state._validMessageId = validMessageId; state._invalidMessageId = invalidMessageId; + + if (props.message) { + state._descByIds = messageId; + } } }, [state._id]); + onUpdate(() => { + state._value = props.value; + }, [props.value]); + return (
) => state.handleFocus(event) } - value={props.value} + value={props.value ?? state._value} aria-describedby={state._descByIds} placeholder={ props.placeholder ?? state.defaultValues.placeholder @@ -177,14 +176,16 @@ export default function DBTextarea(props: DBTextareaProps) { id={state._validMessageId} size="small" semantic="successful"> - {state.getValidMessage()} + {props.validMessage ?? DEFAULT_VALID_MESSAGE} - {state.getInvalidMessage()} + {props.invalidMessage ?? + ref?.validationMessage ?? + DEFAULT_INVALID_MESSAGE}
); diff --git a/packages/components/src/shared/model.ts b/packages/components/src/shared/model.ts index a36d5f33a43..4c466b57c7c 100644 --- a/packages/components/src/shared/model.ts +++ b/packages/components/src/shared/model.ts @@ -212,11 +212,6 @@ export type FormCheckProps = { variant?: 'hidden'; }; -export type FormMessageState = { - getValidMessage: () => string; - getInvalidMessage: () => string; -}; - export type FormMessageProps = { /** * Change the variant of the label to float or hidden @@ -315,6 +310,7 @@ export type FormState = { _validMessageId?: string; _invalidMessageId?: string; _descByIds?: string; + _value?: string; }; export type InitializedState = { diff --git a/showcases/angular-showcase/src/app/components/checkbox/checkbox.component.html b/showcases/angular-showcase/src/app/components/checkbox/checkbox.component.html index dea5accbc28..e8db0875678 100644 --- a/showcases/angular-showcase/src/app/components/checkbox/checkbox.component.html +++ b/showcases/angular-showcase/src/app/components/checkbox/checkbox.component.html @@ -14,7 +14,6 @@ [label]="exampleProps.label" [disabled]="exampleProps.disabled" [checked]="exampleProps.checked" - [value]="exampleProps.value" [required]="exampleProps.required" [indeterminate]="exampleProps.indeterminate" [variant]="exampleProps.variant" diff --git a/showcases/react-showcase/src/components/select/index.tsx b/showcases/react-showcase/src/components/select/index.tsx index 965c2dd1e91..d16ce81d6a9 100644 --- a/showcases/react-showcase/src/components/select/index.tsx +++ b/showcases/react-showcase/src/components/select/index.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { DBSelect } from '../../../../../output/react/src'; import DefaultComponent from '../index'; import defaultComponentVariants from '../../../../shared/select.json'; @@ -14,20 +15,26 @@ const getSelect = ({ value, required, variant -}: DBSelectProps) => ( - - {children} - -); +}: DBSelectProps) => { + const [mValue, setValue] = useState(value); + return ( + { + setValue(event.target.value); + }} + message={message} + required={required}> + {children} + + ); +}; const SelectComponent = () => { return ( diff --git a/showcases/shared/select.json b/showcases/shared/select.json index 9218ec97392..97db35611e9 100644 --- a/showcases/shared/select.json +++ b/showcases/shared/select.json @@ -185,7 +185,8 @@ "props": { "options": [ { - "value": "Filled" + "value": "Filled", + "selected": true }, { "value": "Option 2" @@ -244,7 +245,8 @@ "props": { "options": [ { - "value": "Filled" + "value": "Filled", + "selected": true }, { "value": "Option 2" diff --git a/showcases/vue-showcase/src/components/textarea/Textarea.vue b/showcases/vue-showcase/src/components/textarea/Textarea.vue index f0a5a070e80..b5b43f6043c 100644 --- a/showcases/vue-showcase/src/components/textarea/Textarea.vue +++ b/showcases/vue-showcase/src/components/textarea/Textarea.vue @@ -1,7 +1,7 @@