diff --git a/example/src/pages/textfield/Textfield.svelte b/example/src/pages/textfield/Textfield.svelte index 8f16a79..89c7a25 100644 --- a/example/src/pages/textfield/Textfield.svelte +++ b/example/src/pages/textfield/Textfield.svelte @@ -1,5 +1,17 @@ +
+ +
+
{ + return text.startsWith('SW'); + }; + let type = 'default'; $: outlined = type === 'outlined'; diff --git a/example/src/pages/textfield/code.md b/example/src/pages/textfield/code.md index f3620e3..77bfd67 100644 --- a/example/src/pages/textfield/code.md +++ b/example/src/pages/textfield/code.md @@ -1,4 +1,15 @@ ```xml + + + import { Textfield } from 'svelte-mui'; + const startsWithSW = text => { + return text.startsWith('SW'); + } + + let value = ''; + let secretWord = ''; -``` +``` \ No newline at end of file diff --git a/example/src/pages/textfield/props.js b/example/src/pages/textfield/props.js index be5da32..976d7bf 100644 --- a/example/src/pages/textfield/props.js +++ b/example/src/pages/textfield/props.js @@ -60,4 +60,10 @@ export default [ type: '[number, string]', desc: 'Input value', }, + { + name: 'validator', + def: "null (*)", + type: 'Function', + desc: "A callback to check the value of the Textfield against. It takes a single argument, the value of the Textfield, and should return 'true' or 'false'.

When false is returned, the Textfield is marked as invalid and displays the '*' sign and the 'error' string if there is one. When no 'error' is provided the 'help' is displayed using the error color..

When 'required' is set and no validator is given, a default callback is attached that checks if the length of the trimmed string is bigger than 0.


Note:'required' must be set in order for the validator to be available", + }, ]; diff --git a/package.json b/package.json index ded5fd2..147f3ad 100644 --- a/package.json +++ b/package.json @@ -45,4 +45,4 @@ "index.mjs", "index.js" ] -} \ No newline at end of file +} diff --git a/src/Textfield.svelte b/src/Textfield.svelte index 56fa03f..b7df546 100644 --- a/src/Textfield.svelte +++ b/src/Textfield.svelte @@ -3,6 +3,7 @@ class:filled class:dirty class:disabled + class:invalid {style} {title} > @@ -11,7 +12,7 @@
{label} - {#if required && !value.length} + {#if required} * {/if}
@@ -21,9 +22,11 @@ {/if} {#if !!message || !!error} -
-
{error || message}
-
+ {#if hasError} +
{error}{error ? '' : message}
+ {:else} +
{message}
+ {/if} {/if}
@@ -46,8 +49,10 @@ messagePersist, message, error, + validator, + invalid }; - + let defaultValidator = v => (""+v).trim().length > 0; let value = ''; let disabled = false; let required = false; @@ -60,6 +65,9 @@ let messagePersist = false; let message = ''; let error = ''; + let invalid = false; + let validator = required ? defaultValidator : null; + let hasError = false; let placeholder; @@ -82,12 +90,21 @@ !other.readonly && delete other.readonly; !other.disabled && delete other.disabled; + other.required && validator == null && (validator = defaultValidator); + !other.required && validator == defaultValidator && (validator = null); + !other.required && delete other.required; + delete other.class; other.type = allowedTypes.indexOf(other.type) < 0 ? 'text' : other.type; placeholder = other.placeholder; attrs = other; } + $: { + invalid = validator ? !validator(value) : false; + hasError = required ? (invalid && value.length) : invalid; + } + $: dirty = (typeof value === 'string' && value.length > 0) || typeof value === 'number' || @@ -135,6 +152,7 @@ left: 0.125em; color: #ff5252; } + .input { box-sizing: border-box; font: inherit; @@ -170,6 +188,7 @@ .input:required { box-shadow: none; } + .invalid input, .input:invalid { box-shadow: none; } @@ -263,17 +282,22 @@ color: rgba(0, 0, 0, 0.3755); /* postcss-custom-properties: ignore next */ color: var(--label, rgba(0, 0, 0, 0.3755)); - opacity: 0; + opacity: 1; overflow: hidden; max-width: 90%; white-space: nowrap; } - .persist, - .error, - .input:focus ~ .help { + + .help.message { + opacity: 0; + } + + input:focus ~ .help.message, + .help.message.persist { opacity: 1; } + .error { color: #ff5252; }