mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
breaking(text-input): use native bind:value
, dispatch instead of forward change
, input
events (#1065)
Use the native `bind:value` to fix two-way reactivity. As a result, "type" is read through `$$restProps` because it cannot be dynamic when using `bind:value`. Extend value type to include `null` for the "number" type. This is similar to how `NumberInput` works; `null` represents "no value."
This commit is contained in:
parent
30a5f2c201
commit
989e0f4c65
5 changed files with 92 additions and 72 deletions
|
@ -4167,27 +4167,26 @@ None.
|
||||||
|
|
||||||
### Props
|
### Props
|
||||||
|
|
||||||
| Prop name | Kind | Reactive | Type | Default value | Description |
|
| Prop name | Kind | Reactive | Type | Default value | Description |
|
||||||
| :---------- | :--------------- | :------- | :---------------------------------------- | ------------------------------------------------ | --------------------------------------------- |
|
| :---------- | :--------------- | :------- | :-------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| ref | <code>let</code> | Yes | <code>null | HTMLInputElement</code> | <code>null</code> | Obtain a reference to the input HTML element |
|
| ref | <code>let</code> | Yes | <code>null | HTMLInputElement</code> | <code>null</code> | Obtain a reference to the input HTML element |
|
||||||
| value | <code>let</code> | Yes | <code>number | string</code> | <code>""</code> | Specify the input value |
|
| value | <code>let</code> | Yes | <code>null | number | string</code> | <code>""</code> | Specify the input value.<br /><br />`value` will be set to `null` if type="number"<br />and the value is empty. |
|
||||||
| size | <code>let</code> | No | <code>"sm" | "xl"</code> | <code>undefined</code> | Set the size of the input |
|
| size | <code>let</code> | No | <code>"sm" | "xl"</code> | <code>undefined</code> | Set the size of the input |
|
||||||
| type | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the input type |
|
| placeholder | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the placeholder text |
|
||||||
| placeholder | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the placeholder text |
|
| light | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the light variant |
|
||||||
| light | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the light variant |
|
| disabled | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the input |
|
||||||
| disabled | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the input |
|
| helperText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the helper text |
|
||||||
| helperText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the helper text |
|
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the input element |
|
||||||
| id | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the input element |
|
| name | <code>let</code> | No | <code>string</code> | <code>undefined</code> | Specify a name attribute for the input |
|
||||||
| name | <code>let</code> | No | <code>string</code> | <code>undefined</code> | Specify a name attribute for the input |
|
| labelText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the label text |
|
||||||
| labelText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the label text |
|
| hideLabel | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to visually hide the label text |
|
||||||
| hideLabel | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to visually hide the label text |
|
| invalid | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to indicate an invalid state |
|
||||||
| invalid | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to indicate an invalid state |
|
| invalidText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the invalid state text |
|
||||||
| invalidText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the invalid state text |
|
| warn | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to indicate an warning state |
|
||||||
| warn | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to indicate an warning state |
|
| warnText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the warning state text |
|
||||||
| warnText | <code>let</code> | No | <code>string</code> | <code>""</code> | Specify the warning state text |
|
| required | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to mark the field as required |
|
||||||
| required | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to mark the field as required |
|
| inline | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the inline variant |
|
||||||
| inline | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the inline variant |
|
| readonly | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the read-only variant |
|
||||||
| readonly | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use the read-only variant |
|
|
||||||
|
|
||||||
### Slots
|
### Slots
|
||||||
|
|
||||||
|
@ -4197,18 +4196,18 @@ None.
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
| Event name | Type | Detail |
|
| Event name | Type | Detail |
|
||||||
| :--------- | :-------- | :----- |
|
| :--------- | :--------- | :-------------------------------------------- |
|
||||||
| click | forwarded | -- |
|
| change | dispatched | <code>null | number | string</code> |
|
||||||
| mouseover | forwarded | -- |
|
| input | dispatched | <code>null | number | string</code> |
|
||||||
| mouseenter | forwarded | -- |
|
| click | forwarded | -- |
|
||||||
| mouseleave | forwarded | -- |
|
| mouseover | forwarded | -- |
|
||||||
| change | forwarded | -- |
|
| mouseenter | forwarded | -- |
|
||||||
| input | forwarded | -- |
|
| mouseleave | forwarded | -- |
|
||||||
| keydown | forwarded | -- |
|
| keydown | forwarded | -- |
|
||||||
| keyup | forwarded | -- |
|
| keyup | forwarded | -- |
|
||||||
| focus | forwarded | -- |
|
| focus | forwarded | -- |
|
||||||
| blur | forwarded | -- |
|
| blur | forwarded | -- |
|
||||||
|
|
||||||
## `TextInputSkeleton`
|
## `TextInputSkeleton`
|
||||||
|
|
||||||
|
|
|
@ -11571,25 +11571,14 @@
|
||||||
{
|
{
|
||||||
"name": "value",
|
"name": "value",
|
||||||
"kind": "let",
|
"kind": "let",
|
||||||
"description": "Specify the input value",
|
"description": "Specify the input value.\n\n`value` will be set to `null` if type=\"number\"\nand the value is empty.",
|
||||||
"type": "number | string",
|
"type": "null | number | string",
|
||||||
"value": "\"\"",
|
"value": "\"\"",
|
||||||
"isFunction": false,
|
"isFunction": false,
|
||||||
"isFunctionDeclaration": false,
|
"isFunctionDeclaration": false,
|
||||||
"constant": false,
|
"constant": false,
|
||||||
"reactive": true
|
"reactive": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "type",
|
|
||||||
"kind": "let",
|
|
||||||
"description": "Specify the input type",
|
|
||||||
"type": "string",
|
|
||||||
"value": "\"\"",
|
|
||||||
"isFunction": false,
|
|
||||||
"isFunctionDeclaration": false,
|
|
||||||
"constant": false,
|
|
||||||
"reactive": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "placeholder",
|
"name": "placeholder",
|
||||||
"kind": "let",
|
"kind": "let",
|
||||||
|
@ -11775,12 +11764,20 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"events": [
|
||||||
|
{
|
||||||
|
"type": "dispatched",
|
||||||
|
"name": "change",
|
||||||
|
"detail": "null | number | string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dispatched",
|
||||||
|
"name": "input",
|
||||||
|
"detail": "null | number | string"
|
||||||
|
},
|
||||||
{ "type": "forwarded", "name": "click", "element": "div" },
|
{ "type": "forwarded", "name": "click", "element": "div" },
|
||||||
{ "type": "forwarded", "name": "mouseover", "element": "div" },
|
{ "type": "forwarded", "name": "mouseover", "element": "div" },
|
||||||
{ "type": "forwarded", "name": "mouseenter", "element": "div" },
|
{ "type": "forwarded", "name": "mouseenter", "element": "div" },
|
||||||
{ "type": "forwarded", "name": "mouseleave", "element": "div" },
|
{ "type": "forwarded", "name": "mouseleave", "element": "div" },
|
||||||
{ "type": "forwarded", "name": "change", "element": "input" },
|
|
||||||
{ "type": "forwarded", "name": "input", "element": "input" },
|
|
||||||
{ "type": "forwarded", "name": "keydown", "element": "input" },
|
{ "type": "forwarded", "name": "keydown", "element": "input" },
|
||||||
{ "type": "forwarded", "name": "keyup", "element": "input" },
|
{ "type": "forwarded", "name": "keyup", "element": "input" },
|
||||||
{ "type": "forwarded", "name": "focus", "element": "input" },
|
{ "type": "forwarded", "name": "focus", "element": "input" },
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
|
/**
|
||||||
|
* @event {null | number | string} change
|
||||||
|
* @event {null | number | string} input
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the size of the input
|
* Set the size of the input
|
||||||
* @type {"sm" | "xl"}
|
* @type {"sm" | "xl"}
|
||||||
|
@ -6,14 +11,14 @@
|
||||||
export let size = undefined;
|
export let size = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the input value
|
* Specify the input value.
|
||||||
* @type {number | string}
|
*
|
||||||
|
* `value` will be set to `null` if type="number"
|
||||||
|
* and the value is empty.
|
||||||
|
* @type {null | number | string}
|
||||||
*/
|
*/
|
||||||
export let value = "";
|
export let value = "";
|
||||||
|
|
||||||
/** Specify the input type */
|
|
||||||
export let type = "";
|
|
||||||
|
|
||||||
/** Specify the placeholder text */
|
/** Specify the placeholder text */
|
||||||
export let placeholder = "";
|
export let placeholder = "";
|
||||||
|
|
||||||
|
@ -65,12 +70,29 @@
|
||||||
/** Set to `true` to use the read-only variant */
|
/** Set to `true` to use the read-only variant */
|
||||||
export let readonly = false;
|
export let readonly = false;
|
||||||
|
|
||||||
import { getContext } from "svelte";
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
import WarningFilled16 from "../icons/WarningFilled16.svelte";
|
import WarningFilled16 from "../icons/WarningFilled16.svelte";
|
||||||
import WarningAltFilled16 from "../icons/WarningAltFilled16.svelte";
|
import WarningAltFilled16 from "../icons/WarningAltFilled16.svelte";
|
||||||
import EditOff16 from "../icons/EditOff16.svelte";
|
import EditOff16 from "../icons/EditOff16.svelte";
|
||||||
|
|
||||||
const ctx = getContext("Form");
|
const ctx = getContext("Form");
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function parse(raw) {
|
||||||
|
if ($$restProps.type !== "number") return raw;
|
||||||
|
return raw != "" ? Number(raw) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {(e: Event) => void} */
|
||||||
|
const onInput = (e) => {
|
||||||
|
value = parse(e.target.value);
|
||||||
|
dispatch("input", value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {(e: Event) => void} */
|
||||||
|
const onChange = (e) => {
|
||||||
|
dispatch("change", parse(e.target.value));
|
||||||
|
};
|
||||||
|
|
||||||
$: isFluid = !!ctx && ctx.isFluid;
|
$: isFluid = !!ctx && ctx.isFluid;
|
||||||
$: errorId = `error-${id}`;
|
$: errorId = `error-${id}`;
|
||||||
|
@ -162,8 +184,7 @@
|
||||||
id="{id}"
|
id="{id}"
|
||||||
name="{name}"
|
name="{name}"
|
||||||
placeholder="{placeholder}"
|
placeholder="{placeholder}"
|
||||||
type="{type}"
|
bind:value
|
||||||
value="{value ?? ''}"
|
|
||||||
required="{required}"
|
required="{required}"
|
||||||
readonly="{readonly}"
|
readonly="{readonly}"
|
||||||
class:bx--text-input="{true}"
|
class:bx--text-input="{true}"
|
||||||
|
@ -172,11 +193,8 @@
|
||||||
class:bx--text-input--warn="{warn}"
|
class:bx--text-input--warn="{warn}"
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
class="{size && `bx--text-input--${size}`}"
|
class="{size && `bx--text-input--${size}`}"
|
||||||
on:change
|
on:change="{onChange}"
|
||||||
on:input
|
on:input="{onInput}"
|
||||||
on:input="{({ target }) => {
|
|
||||||
value = type === 'number' ? Number(target.value) : target.value;
|
|
||||||
}}"
|
|
||||||
on:keydown
|
on:keydown
|
||||||
on:keyup
|
on:keyup
|
||||||
on:focus
|
on:focus
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { TextInput, TextInputSkeleton } from "../types";
|
import { TextInput, TextInputSkeleton } from "../types";
|
||||||
|
|
||||||
|
let value = null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TextInput labelText="User name" placeholder="Enter user name..." />
|
<TextInput
|
||||||
|
type="number"
|
||||||
|
labelText="User name"
|
||||||
|
placeholder="Enter user name..."
|
||||||
|
bind:value
|
||||||
|
on:input="{(e) => console.log(e.detail)}"
|
||||||
|
on:change="{(e) => (value = e.detail)}"
|
||||||
|
/>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
labelText="User name"
|
labelText="User name"
|
||||||
|
|
17
types/TextInput/TextInput.svelte.d.ts
vendored
17
types/TextInput/TextInput.svelte.d.ts
vendored
|
@ -10,16 +10,13 @@ export interface TextInputProps
|
||||||
size?: "sm" | "xl";
|
size?: "sm" | "xl";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the input value
|
* Specify the input value.
|
||||||
|
*
|
||||||
|
* `value` will be set to `null` if type="number"
|
||||||
|
* and the value is empty.
|
||||||
* @default ""
|
* @default ""
|
||||||
*/
|
*/
|
||||||
value?: number | string;
|
value?: null | number | string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify the input type
|
|
||||||
* @default ""
|
|
||||||
*/
|
|
||||||
type?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the placeholder text
|
* Specify the placeholder text
|
||||||
|
@ -121,12 +118,12 @@ export interface TextInputProps
|
||||||
export default class TextInput extends SvelteComponentTyped<
|
export default class TextInput extends SvelteComponentTyped<
|
||||||
TextInputProps,
|
TextInputProps,
|
||||||
{
|
{
|
||||||
|
change: CustomEvent<null | number | string>;
|
||||||
|
input: CustomEvent<null | number | string>;
|
||||||
click: WindowEventMap["click"];
|
click: WindowEventMap["click"];
|
||||||
mouseover: WindowEventMap["mouseover"];
|
mouseover: WindowEventMap["mouseover"];
|
||||||
mouseenter: WindowEventMap["mouseenter"];
|
mouseenter: WindowEventMap["mouseenter"];
|
||||||
mouseleave: WindowEventMap["mouseleave"];
|
mouseleave: WindowEventMap["mouseleave"];
|
||||||
change: WindowEventMap["change"];
|
|
||||||
input: WindowEventMap["input"];
|
|
||||||
keydown: WindowEventMap["keydown"];
|
keydown: WindowEventMap["keydown"];
|
||||||
keyup: WindowEventMap["keyup"];
|
keyup: WindowEventMap["keyup"];
|
||||||
focus: WindowEventMap["focus"];
|
focus: WindowEventMap["focus"];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue