@zag-js/editable
Version:
Core logic for the editable widget implemented as a state machine
277 lines (275 loc) • 9.96 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/editable.connect.ts
var editable_connect_exports = {};
__export(editable_connect_exports, {
connect: () => connect
});
module.exports = __toCommonJS(editable_connect_exports);
var import_dom_query = require("@zag-js/dom-query");
var import_editable = require("./editable.anatomy.js");
var dom = __toESM(require("./editable.dom.js"));
function connect(service, normalize) {
const { state, context, send, prop, scope, computed } = service;
const disabled = !!prop("disabled");
const interactive = computed("isInteractive");
const readOnly = !!prop("readOnly");
const required = !!prop("required");
const invalid = !!prop("invalid");
const autoResize = !!prop("autoResize");
const translations = prop("translations");
const editing = state.matches("edit");
const placeholderProp = prop("placeholder");
const placeholder = typeof placeholderProp === "string" ? { edit: placeholderProp, preview: placeholderProp } : placeholderProp;
const value = context.get("value");
const empty = value.trim() === "";
const valueText = empty ? placeholder?.preview ?? "" : value;
return {
editing,
empty,
value,
valueText,
setValue(value2) {
send({ type: "VALUE.SET", value: value2, src: "setValue" });
},
clearValue() {
send({ type: "VALUE.SET", value: "", src: "clearValue" });
},
edit() {
if (!interactive) return;
send({ type: "EDIT" });
},
cancel() {
if (!interactive) return;
send({ type: "CANCEL" });
},
submit() {
if (!interactive) return;
send({ type: "SUBMIT" });
},
getRootProps() {
return normalize.element({
...import_editable.parts.root.attrs,
id: dom.getRootId(scope),
dir: prop("dir")
});
},
getAreaProps() {
return normalize.element({
...import_editable.parts.area.attrs,
id: dom.getAreaId(scope),
dir: prop("dir"),
style: autoResize ? { display: "inline-grid" } : void 0,
"data-focus": (0, import_dom_query.dataAttr)(editing),
"data-disabled": (0, import_dom_query.dataAttr)(disabled),
"data-placeholder-shown": (0, import_dom_query.dataAttr)(empty)
});
},
getLabelProps() {
return normalize.label({
...import_editable.parts.label.attrs,
id: dom.getLabelId(scope),
dir: prop("dir"),
htmlFor: dom.getInputId(scope),
"data-focus": (0, import_dom_query.dataAttr)(editing),
"data-invalid": (0, import_dom_query.dataAttr)(invalid),
"data-required": (0, import_dom_query.dataAttr)(required),
onClick() {
if (editing) return;
const previewEl = dom.getPreviewEl(scope);
previewEl?.focus({ preventScroll: true });
}
});
},
getInputProps() {
return normalize.input({
...import_editable.parts.input.attrs,
dir: prop("dir"),
"aria-label": translations?.input,
name: prop("name"),
form: prop("form"),
id: dom.getInputId(scope),
hidden: autoResize ? void 0 : !editing,
placeholder: placeholder?.edit,
maxLength: prop("maxLength"),
required: prop("required"),
disabled,
"data-disabled": (0, import_dom_query.dataAttr)(disabled),
readOnly,
"data-readonly": (0, import_dom_query.dataAttr)(readOnly),
"aria-invalid": (0, import_dom_query.ariaAttr)(invalid),
"data-invalid": (0, import_dom_query.dataAttr)(invalid),
"data-autoresize": (0, import_dom_query.dataAttr)(autoResize),
defaultValue: value,
size: autoResize ? 1 : void 0,
onChange(event) {
send({
type: "VALUE.SET",
src: "input.change",
value: event.currentTarget.value
});
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if ((0, import_dom_query.isComposingEvent)(event)) return;
const keyMap = {
Escape() {
send({ type: "CANCEL" });
event.preventDefault();
},
Enter(event2) {
if (!computed("submitOnEnter")) return;
const { localName } = event2.currentTarget;
if (localName === "textarea") {
const submitMod = (0, import_dom_query.isApple)() ? event2.metaKey : event2.ctrlKey;
if (!submitMod) return;
send({ type: "SUBMIT", src: "keydown.enter" });
return;
}
if (localName === "input" && !event2.shiftKey && !event2.metaKey) {
send({ type: "SUBMIT", src: "keydown.enter" });
event2.preventDefault();
}
}
};
const exec = keyMap[event.key];
if (exec) {
exec(event);
}
},
style: autoResize ? {
gridArea: "1 / 1 / auto / auto",
visibility: !editing ? "hidden" : void 0
} : void 0
});
},
getPreviewProps() {
return normalize.element({
id: dom.getPreviewId(scope),
...import_editable.parts.preview.attrs,
dir: prop("dir"),
"data-placeholder-shown": (0, import_dom_query.dataAttr)(empty),
"aria-readonly": (0, import_dom_query.ariaAttr)(readOnly),
"data-readonly": (0, import_dom_query.dataAttr)(disabled),
"data-disabled": (0, import_dom_query.dataAttr)(disabled),
"aria-disabled": (0, import_dom_query.ariaAttr)(disabled),
"aria-invalid": (0, import_dom_query.ariaAttr)(invalid),
"data-invalid": (0, import_dom_query.dataAttr)(invalid),
"aria-label": translations?.edit,
"data-autoresize": (0, import_dom_query.dataAttr)(autoResize),
children: valueText,
hidden: autoResize ? void 0 : editing,
tabIndex: interactive ? 0 : void 0,
onClick() {
if (!interactive) return;
if (prop("activationMode") !== "click") return;
send({ type: "EDIT", src: "click" });
},
onFocus() {
if (!interactive) return;
if (prop("activationMode") !== "focus") return;
send({ type: "EDIT", src: "focus" });
},
onDoubleClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
if (prop("activationMode") !== "dblclick") return;
send({ type: "EDIT", src: "dblclick" });
},
style: autoResize ? {
whiteSpace: "pre",
gridArea: "1 / 1 / auto / auto",
visibility: editing ? "hidden" : void 0,
// in event the preview overflow's the parent element
overflow: "hidden",
textOverflow: "ellipsis"
} : void 0
});
},
getEditTriggerProps() {
return normalize.button({
...import_editable.parts.editTrigger.attrs,
id: dom.getEditTriggerId(scope),
dir: prop("dir"),
"aria-label": translations?.edit,
hidden: editing,
type: "button",
disabled,
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
send({ type: "EDIT", src: "edit.click" });
}
});
},
getControlProps() {
return normalize.element({
id: dom.getControlId(scope),
...import_editable.parts.control.attrs,
dir: prop("dir")
});
},
getSubmitTriggerProps() {
return normalize.button({
...import_editable.parts.submitTrigger.attrs,
dir: prop("dir"),
id: dom.getSubmitTriggerId(scope),
"aria-label": translations?.submit,
hidden: !editing,
disabled,
type: "button",
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
send({ type: "SUBMIT", src: "submit.click" });
}
});
},
getCancelTriggerProps() {
return normalize.button({
...import_editable.parts.cancelTrigger.attrs,
dir: prop("dir"),
"aria-label": translations?.cancel,
id: dom.getCancelTriggerId(scope),
hidden: !editing,
type: "button",
disabled,
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
send({ type: "CANCEL", src: "cancel.click" });
}
});
}
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
connect
});