Edit
Displays an input field used for editing a single line of text, rendering as static text on load. It transforms into a text input field when the edit interaction is triggered.
Features
Install
Install the component from your command line.
Anatomy
Import all parts and piece them together.
<script setup lang="ts">import * as edit from "@destyler/edit";import { normalizeProps, useMachine } from "@destyler/vue";import { computed, useId } from "vue";
const [state, send] = useMachine(edit.machine({ id: useId(), placeholder: 'Type something...',}));const api = computed(() => edit.connect(state.value, send, normalizeProps));</script>
<template> <div v-bind="api.getRootProps()"> <div v-bind="api.getAreaProps()"> <input v-bind="api.getInputProps()" /> <span v-bind="api.getPreviewProps()" /> </div> <button v-bind="api.getSubmitTriggerProps()" ></button> <button v-bind="api.getCancelTriggerProps()" ></button> <button v-bind="api.getEditTriggerProps()" ></button> </div> </div></template>
import * as edit from '@destyler/edit'import { normalizeProps, useMachine } from '@destyler/react'import { useId } from 'react'
export default function Edit() {
const [state, send] = useMachine(edit.machine({ id: useId(), placeholder: 'Type something...', }))
const api = edit.connect(state, send, normalizeProps)
return ( <> <div {...api.getRootProps()} > <div {...api.getAreaProps()} > <input {...api.getInputProps()} /> <span {...api.getPreviewProps()} /> </div> <button {...api.getSubmitTriggerProps()} ></button> <button {...api.getCancelTriggerProps()}></button> <button {...api.getEditTriggerProps()}></button> </div> </> )}
<script lang="ts"> import * as edit from "@destyler/edit"; import { normalizeProps, useMachine } from "@destyler/svelte";
const [state, send] = useMachine(edit.machine({ id: crypto.randomUUID(), placeholder: 'Type something...', }))
const api = $derived(edit.connect(state, send, normalizeProps));</script>
<div {...api.getRootProps()} > <div {...api.getAreaProps()}> <input {...api.getInputProps()}/> <span {...api.getPreviewProps()}></span> </div> <button {...api.getSubmitTriggerProps()}></button> <button {...api.getCancelTriggerProps()}></button> <button {...api.getEditTriggerProps()}></button></div>
import * as edit from '@destyler/edit'import { normalizeProps, useMachine } from '@destyler/solid'import { createMemo, createUniqueId } from 'solid-js'
export default function Edit() {
const [state, send] = useMachine(edit.machine({ id: createUniqueId(), placeholder: 'Type something...', }))
const api = createMemo(() => edit.connect(state, send, normalizeProps))
return ( <> <div {...api().getRootProps()}> <div {...api().getAreaProps()} > <input {...api().getInputProps()} /> <span {...api().getPreviewProps()}/> </div> <button {...api().getSubmitTriggerProps()}></button> <button {...api().getCancelTriggerProps()}></button> <button {...api().getEditTriggerProps()}></button> </div> </> )}
Setting the initial value
To set the initial value of the editable, pass the value
property to the machine’s context.
const [state, send] = useMachine( edit.machine({ value: "Hello World", }),)
Listening for value changes
The editable machine supports two ways of listening for value changes:
-
onValueChange
: called when value changes. -
onValueCommit
: called when the value is committed.
const [state, send] = useMachine( edit.machine({ onValueChange(details) { console.log("Value changed", details.value) }, onValueCommit(details) { console.log("Value submitted", details.value) }, }),)
Auto-resizing the editable
To auto-grow the editable as the content changes,
pass the autoResize: true
property to the machine’s context.
const [state, send] = useMachine( edit.machine({ autoResize: true, }),)
Setting a maxWidth
It is a common pattern to set a maximum of the editable as it auto-grows.
To achieve this, set the maxWidth
property of the machine’s context to the desired value.
const [state, send] = useMachine( edit.machine({ autoResize: true, maxWidth: "320px", }),)
When the editable reaches the specified max-width, it’ll clip the preview text with an ellipsis.
Editing with double click
he editable supports two modes of activating the “edit” state:
-
when the preview part is focused (with pointer or keyboard).
-
when the preview part is double-clicked.
To change the mode to “double-click”, set the activationMode: 'dblclick'
property in the machine’s context.
const [state, send] = useMachine( editable.machine({ activationMode: "dblclick", }),)
Styling guide
Earlier, we mentioned that each hover card part has a data-part
attribute added to them to
select and style them in the DOM.
Focused state
When the editable is in the focused mode, we set a data-focus
attribute on the “area” part.
[data-part="area"][data-focus] { /* CSS for the editable's focus state */}
Empty state
When the editable’s value is empty, we set a data-empty
attribute on the “area” part.
[data-part="area"][data-empty] { /* CSS for the editable's focus state */}
Disabled state
When the editable is disabled, we set a data-disabled
attribute on the “area” part.
[data-part="area"][data-disabled] { /* CSS for the editable's focus state */}
Methods and Properties
Machine Context
The edit machine exposes the following context properties:
Partial<{ root: string; area: string; label: string; preview: string; input: string; control: string; submitTrigger: string; cancelTrigger: string; editTrigger: string; }>
boolean
string
string
boolean
ActivationMode
SubmitMode
boolean
boolean
boolean
string
number
boolean
boolean
boolean
(details: ValueChangeDetails) => void
(details: ValueChangeDetails) => void
(details: ValueChangeDetails) => void
(details: EditChangeDetails) => void
string | { edit: string; preview: string; }
IntlTranslations
() => HTMLElement
"ltr" | "rtl"
string
() => Node | ShadowRoot | Document
(event: PointerDownOutsideEvent) => void
(event: FocusOutsideEvent) => void
(event: InteractOutsideEvent) => void
Machine API
The edit api
exposes the following methods:
boolean
boolean
string
string
(value: string) => void
() => void
() => void
() => void
() => void
Data Attributes
Area
data-scope
data-part
data-focus
data-disabled
data-placeholder-shown
Label
data-scope
data-part
data-focus
data-invalid
Input
data-scope
data-part
data-disabled
data-readonly
data-invalid
Preview
data-scope
data-part
data-placeholder-shown
data-readonly
data-disabled
data-invalid
Accessibility
Keyboard Interaction
Enter
Escape