@kelvininc/ui-components
Version:
Kelvin UI Components
221 lines (215 loc) • 10.7 kB
JavaScript
import { H as proxyCustomElement, I as H, J as createEvent, K as h, L as Host, M as Fragment, t as EIconName, m as EActionButtonType } from './p-BP5CxQcH.js';
import { d as defineCustomElement$4 } from './p-0XA6IHyr.js';
import { d as defineCustomElement$3 } from './p-DFvvqEwa.js';
import { d as defineCustomElement$2 } from './p-DQ7v6WT-.js';
const DEFAULT_MAX_LENGTH = 64;
const DELAYED_BLUR_MS = 200;
const inlineEditableFieldCss = "@charset \"UTF-8\";@property --rotation{syntax:\"<angle>\";initial-value:0deg;inherits:false}@keyframes rotate-border{to{--rotation:360deg}}kv-dropdown-base:not(.hydrated)>[slot=list]{display:none}.inline-editable-field-container{display:inline-flex;align-items:center;width:100%;--margin-top-bottom:var(--spacing-xs);--margin-left-right:var(--spacing-md);--inline-editable-field-background-color-hover:var(--input-background-default);--inline-editable-field-outline-color-hover:var(--input-border-color-default);--inline-editable-field-outline-color-focus:var(--input-border-color-selected);--inline-editable-field-placeholder-color:var(--input-text-text-input-default);--inline-editable-field-min-width:unset;--inline-editable-field-editing-min-width:unset}.inline-editable-field-container__hover .inline-editable-field-slot{border-radius:var(--radius-md);background:var(--inline-editable-field-background-color-hover);outline-color:var(--inline-editable-field-outline-color-hover)}.inline-editable-field-container:not(.inline-editable-field-container__editing) .inline-editable-field-slot[contenteditable]:empty::before{content:attr(data-placeholder);color:var(--inline-editable-field-placeholder-color);pointer-events:none}.inline-editable-field-container__editing .inline-editable-field-slot[contenteditable]{min-width:var(--inline-editable-field-editing-min-width)}.inline-editable-field-slot[contenteditable]{padding:var(--margin-top-bottom) var(--margin-left-right);margin:calc(var(--margin-top-bottom) * -1) calc(var(--margin-left-right) * -1);min-width:var(--inline-editable-field-min-width);white-space:nowrap;overflow:hidden;outline:1px solid transparent;transition:all 0.25s ease-in-out}.inline-editable-field-slot[contenteditable]:hover,.inline-editable-field-slot[contenteditable]:focus{border-radius:var(--radius-md);background:var(--inline-editable-field-background-color-hover);outline-color:var(--inline-editable-field-outline-color-hover)}.inline-editable-field-slot[contenteditable]:focus{outline-color:var(--inline-editable-field-outline-color-focus);text-overflow:unset}.inline-editable-field-slot br{display:none}.inline-editable-field-slot *{display:inline;white-space:nowrap}.inline-editable-field-actions{display:inline-flex;gap:var(--spacing-xs);flex:0;margin-left:calc(var(--margin-left-right) + var(--spacing-md))}.inline-editable-field-actions__focus{width:64px;align-self:flex-end;margin-bottom:calc(var(--margin-top-bottom) * -1)}";
const KvInlineEditableField$1 = /*@__PURE__*/ proxyCustomElement(class KvInlineEditableField extends H {
constructor() {
super();
this.__registerHost();
this.contentEdited = createEvent(this, "contentEdited", 7);
this.contentFocused = createEvent(this, "contentFocused", 7);
this.contentBlured = createEvent(this, "contentBlured", 7);
/**
* The maximum length of the editable field.
*/
this.maxLength = DEFAULT_MAX_LENGTH;
this.isHovering = false;
this.isEditing = false;
this.isSaving = false;
this.isSaveDisabled = false;
this.discardContent = () => {
this.slotEl.innerText = this.value;
};
this.saveChanges = () => {
this.slotEl.blur();
const newValue = this.slotEl.innerText;
if (newValue.length === 0)
return;
if (newValue !== this.value) {
this.isSaving = true;
this.contentEdited.emit(newValue);
}
};
this.handleBlur = () => {
this.slotEl.innerText = this.slotEl.innerText.trim();
this.timeoutID = window.setTimeout(() => {
// if saving button hasn't clicked, discard content
if (!this.isSaving) {
this.discardContent();
}
this.isEditing = false;
this.isSaving = false;
this.contentBlured.emit();
}, DELAYED_BLUR_MS);
};
this.handleFocus = () => {
clearTimeout(this.timeoutID);
this.isEditing = true;
this.contentFocused.emit();
this.checkSaveBtnDisabled();
};
this.handleMaxLength = (event) => {
if (this.maxLength && this.slotEl.innerText.length >= this.maxLength) {
event.preventDefault();
}
};
this.checkSaveBtnDisabled = () => {
this.isSaveDisabled = this.slotEl.innerText.trim().length === 0;
};
}
/**
* Resets the content of the editable field.
*/
async resetContent() {
this.discardContent();
this.slotEl.blur();
}
handleMouseHover() {
this.isHovering = true;
}
handleMouseLeave() {
this.isHovering = false;
}
handleKeyDown(event) {
if (!this.isEditing || this.disabled)
return;
switch (event.key) {
case 'Escape':
this.slotEl.blur();
break;
case 'Enter':
this.saveChanges();
break;
case 'Backspace':
break;
default:
this.handleMaxLength(event);
}
}
handleDisableChange(state) {
if (!this.slotEl)
return;
if (state) {
this.destroyEditableContent();
}
else {
this.initializeEditableContent();
}
}
handlePlaceholderChange(placeholder) {
if (!this.slotEl)
return;
if (placeholder) {
this.slotEl.setAttribute('data-placeholder', placeholder);
}
else {
this.slotEl.removeAttribute('data-placeholder');
}
}
initializeEditableContent() {
this.slotEl.classList.add('inline-editable-field-slot');
this.slotEl.setAttribute('contenteditable', 'true');
if (this.placeholder) {
this.slotEl.setAttribute('data-placeholder', this.placeholder);
}
this.slotEl.addEventListener('blur', this.handleBlur);
this.slotEl.addEventListener('focus', this.handleFocus);
this.slotEl.addEventListener('input', this.checkSaveBtnDisabled);
}
destroyEditableContent() {
if (!this.slotEl)
return;
this.slotEl.classList.remove('inline-editable-field-slot');
this.slotEl.removeAttribute('contenteditable');
this.slotEl.removeAttribute('data-placeholder');
this.slotEl.removeEventListener('blur', this.handleBlur);
this.slotEl.removeEventListener('focus', this.handleFocus);
this.slotEl.removeEventListener('input', this.checkSaveBtnDisabled);
}
componentDidLoad() {
if (this.disabled) {
return;
}
// Filter out the actions div and ensure exactly one editable child element exists
const children = Array.from(this.el.children);
const slottedElements = children.filter(child => !child.classList.contains('inline-editable-field-actions'));
if (slottedElements.length !== 1) {
console.warn('Inline editable field must have exactly one child element to be editable');
return;
}
this.slotEl = slottedElements[0];
this.initializeEditableContent();
}
disconnectedCallback() {
clearTimeout(this.timeoutID);
this.destroyEditableContent();
}
render() {
if (this.disabled) {
return (h(Host, null, h("slot", null)));
}
return (h(Host, { class: {
'inline-editable-field-container': true,
'inline-editable-field-container__hover': this.isHovering,
'inline-editable-field-container__editing': this.isEditing
} }, h("slot", null), h("div", { class: {
'inline-editable-field-actions': true,
'inline-editable-field-actions__focus': this.isEditing
} }, this.isEditing && (h(Fragment, null, h("kv-action-button-icon", { type: EActionButtonType.Tertiary, icon: EIconName.Close, onClickButton: this.discardContent }), h("kv-action-button-icon", { type: EActionButtonType.Tertiary, icon: EIconName.DoneAll, disabled: this.isSaveDisabled, onClickButton: this.saveChanges }))))));
}
get el() { return this; }
static get watchers() { return {
"disabled": ["handleDisableChange"],
"placeholder": ["handlePlaceholderChange"]
}; }
static get style() { return inlineEditableFieldCss; }
}, [260, "kv-inline-editable-field", {
"value": [513],
"disabled": [516],
"maxLength": [514, "max-length"],
"placeholder": [513],
"isHovering": [32],
"isEditing": [32],
"isSaving": [32],
"isSaveDisabled": [32],
"timeoutID": [32],
"resetContent": [64]
}, [[1, "mouseenter", "handleMouseHover"], [1, "mouseleave", "handleMouseLeave"], [4, "keydown", "handleKeyDown"]], {
"disabled": ["handleDisableChange"],
"placeholder": ["handlePlaceholderChange"]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["kv-inline-editable-field", "kv-action-button", "kv-action-button-icon", "kv-icon"];
components.forEach(tagName => { switch (tagName) {
case "kv-inline-editable-field":
if (!customElements.get(tagName)) {
customElements.define(tagName, KvInlineEditableField$1);
}
break;
case "kv-action-button":
if (!customElements.get(tagName)) {
defineCustomElement$4();
}
break;
case "kv-action-button-icon":
if (!customElements.get(tagName)) {
defineCustomElement$3();
}
break;
case "kv-icon":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
} });
}
defineCustomElement$1();
const KvInlineEditableField = KvInlineEditableField$1;
const defineCustomElement = defineCustomElement$1;
export { KvInlineEditableField, defineCustomElement };