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, }),)When using autoresize, the input and preview elements should not have any styles.
Use all: unset if needed and pass any styles to the “area” element since its shared by the input and preview elements.
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; }>booleanstringstringbooleanActivationModeSubmitModebooleanbooleanbooleanstringnumberbooleanbooleanboolean(details: ValueChangeDetails) => void(details: ValueChangeDetails) => void(details: ValueChangeDetails) => void(details: EditChangeDetails) => voidstring | { edit: string; preview: string; }IntlTranslations() => HTMLElement"ltr" | "rtl"string() => Node | ShadowRoot | Document(event: PointerDownOutsideEvent) => void(event: FocusOutsideEvent) => void(event: InteractOutsideEvent) => voidMachine API
The edit api exposes the following methods:
booleanbooleanstringstring(value: string) => void() => void() => void() => void() => voidData Attributes
Area
data-scopedata-partdata-focusdata-disableddata-placeholder-shownLabel
data-scopedata-partdata-focusdata-invalidInput
data-scopedata-partdata-disableddata-readonlydata-invaliddata-autoresizePreview
data-scopedata-partdata-placeholder-showndata-readonlydata-disableddata-invaliddata-autoresizeAccessibility
Keyboard Interaction
EnterEscape