@ixfx/components 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.d.ts +213 -117
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +1356 -658
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.js +3 -3
- package/dist/ac-text.js.map +1 -1
- package/dist/{button-B9ztaKyl.js → button-DMt5XWUK.js} +4 -4
- package/dist/{button-B9ztaKyl.js.map → button-DMt5XWUK.js.map} +1 -1
- package/dist/button.js +1 -1
- package/dist/checkbox.d.ts +2 -3
- package/dist/checkbox.d.ts.map +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/{colour-C3MQIjFJ-BJV-QC-3.js → colour-C3MQIjFJ-BLXg8W3U.js} +2 -2
- package/dist/{colour-C3MQIjFJ-BJV-QC-3.js.map → colour-C3MQIjFJ-BLXg8W3U.js.map} +1 -1
- package/dist/{colour-picker-BNqDz4wK.js → colour-picker-K6zu82lm.js} +5 -5
- package/dist/{colour-picker-BNqDz4wK.js.map → colour-picker-K6zu82lm.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +2 -3
- package/dist/crumbs.d.ts.map +1 -1
- package/dist/crumbs.js +10 -10
- package/dist/crumbs.js.map +1 -1
- package/dist/data-display.js +3 -3
- package/dist/{decorate-O4m1U4l3.js → decorate-D7rC1gLP.js} +10 -8
- package/dist/decorate-D7rC1gLP.js.map +1 -0
- package/dist/{defaults-FEZaGiYZ.js → defaults-C7elhuyJ.js} +2 -2
- package/dist/{defaults-FEZaGiYZ.js.map → defaults-C7elhuyJ.js.map} +1 -1
- package/dist/{dist-By5URG0Y.js → dist-BX0OVIm7.js} +2 -2
- package/dist/{dist-By5URG0Y.js.map → dist-BX0OVIm7.js.map} +1 -1
- package/dist/{dist-D7kJgnSE.js → dist-TAGYwaju.js} +1 -1
- package/dist/{dist-D7kJgnSE.js.map → dist-TAGYwaju.js.map} +1 -1
- package/dist/editable-label.d.ts +6 -1
- package/dist/editable-label.d.ts.map +1 -1
- package/dist/editable-label.js +49 -2
- package/dist/editable-label.js.map +1 -1
- package/dist/{hex-editor-gH3mteMr.js → hex-editor-CsN_ySkH.js} +85 -85
- package/dist/hex-editor-CsN_ySkH.js.map +1 -0
- package/dist/{hex-editor-2_s0Ua5t.d.ts → hex-editor-DlfoA65y.d.ts} +5 -5
- package/dist/{hex-editor-2_s0Ua5t.d.ts.map → hex-editor-DlfoA65y.d.ts.map} +1 -1
- package/dist/hex.d.ts +1 -1
- package/dist/hex.js +1 -1
- package/dist/{highlight-CAjwQ4GE.js → highlight-TPbSHruI.js} +3 -3
- package/dist/highlight-TPbSHruI.js.map +1 -0
- package/dist/{icon-CYACf6o8.js → icon-9NWTXtE1.js} +4 -5
- package/dist/icon-9NWTXtE1.js.map +1 -0
- package/dist/icon-CeTDJhC7.d.ts.map +1 -1
- package/dist/icons.js +3 -3
- package/dist/{incr-search-BZawvrfl.js → incr-search-DSKKsk6w.js} +12 -10
- package/dist/incr-search-DSKKsk6w.js.map +1 -0
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +2 -2
- package/dist/{index-CwGkb9s1.d.ts → index--hrxPBkQ.d.ts} +69 -69
- package/dist/index--hrxPBkQ.d.ts.map +1 -0
- package/dist/{index-kY5gxbkI.d.ts → index-DSlPeWLK.d.ts} +15 -15
- package/dist/{index-kY5gxbkI.d.ts.map → index-DSlPeWLK.d.ts.map} +1 -1
- package/dist/{index-V2cJorlA.d.ts → index-hXFn14tM.d.ts} +4 -4
- package/dist/index-hXFn14tM.d.ts.map +1 -0
- package/dist/index.d.ts +109 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +666 -24
- package/dist/index.js.map +1 -1
- package/dist/keyboard-De_vOHLg.js.map +1 -1
- package/dist/{labelled-input-base-BvgH7ldm.js → labelled-input-base-CqPL5rKm.js} +2 -2
- package/dist/labelled-input-base-CqPL5rKm.js.map +1 -0
- package/dist/labelled-radial-input.js +3 -3
- package/dist/labelled-radial-input.js.map +1 -1
- package/dist/labelled-range-input.js +2 -2
- package/dist/led.js +1 -1
- package/dist/{menu-C3eANB5M.js → menu-DJJuCm-5.js} +48 -48
- package/dist/menu-DJJuCm-5.js.map +1 -0
- package/dist/{menu-item-6IU5weHi.js → menu-item-CKRfP0pN.js} +10 -10
- package/dist/menu-item-CKRfP0pN.js.map +1 -0
- package/dist/menu.d.ts +1 -1
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +5 -7
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +14 -14
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.d.ts.map +1 -1
- package/dist/narrowed-text.js +4 -4
- package/dist/narrowed-text.js.map +1 -1
- package/dist/panel.js +2 -2
- package/dist/panel.js.map +1 -1
- package/dist/plots.js +1 -1
- package/dist/polar-pad.d.ts.map +1 -1
- package/dist/polar-pad.js +1 -1
- package/dist/polar-pad.js.map +1 -1
- package/dist/{popup-Ddx9LCzY.js → popup-ImtS9KnS.js} +1 -1
- package/dist/{popup-Ddx9LCzY.js.map → popup-ImtS9KnS.js.map} +1 -1
- package/dist/{prominence-CreDBdCs.js → prominence--ic9uWBl.js} +1 -1
- package/dist/{prominence-CreDBdCs.js.map → prominence--ic9uWBl.js.map} +1 -1
- package/dist/{radial-input-Dbc6fgCK.js → radial-input-DZA6WaFu.js} +14 -14
- package/dist/radial-input-DZA6WaFu.js.map +1 -0
- package/dist/radial-input.js +1 -1
- package/dist/range-input.js +1 -1
- package/dist/range.js +2 -2
- package/dist/{registry-CZEB1YI9.js → registry-Q2gYQCHM.js} +1 -1
- package/dist/{registry-CZEB1YI9.js.map → registry-Q2gYQCHM.js.map} +1 -1
- package/dist/selecthorizontal.js +1 -1
- package/dist/snap-container.js +1 -1
- package/dist/split-layout.js +4 -4
- package/dist/split-layout.js.map +1 -1
- package/dist/swipe.d.ts +1 -2
- package/dist/swipe.d.ts.map +1 -1
- package/dist/swipe.js +2 -2
- package/dist/swipe.js.map +1 -1
- package/dist/tabs.js +2 -2
- package/dist/tabs.js.map +1 -1
- package/dist/{timeline-B62Sz6J_.js → timeline-Cv75Th2U.js} +120 -116
- package/dist/timeline-Cv75Th2U.js.map +1 -0
- package/dist/timeline.d.ts +1 -1
- package/dist/timeline.js +1 -1
- package/dist/tooltip-CwGfb4lp.d.ts.map +1 -1
- package/dist/tree-CvvKbO-f.js +1330 -0
- package/dist/tree-CvvKbO-f.js.map +1 -0
- package/dist/{tree-component-CQpoPo4s.d.ts → tree-component-D8Bg48tt.d.ts} +12 -12
- package/dist/{tree-component-CQpoPo4s.d.ts.map → tree-component-D8Bg48tt.d.ts.map} +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.js +1 -1143
- package/dist/xy-axis-D9uwpGTT.d.ts.map +1 -1
- package/dist/{xy-axis-C7fNxDwY.js → xy-axis-DL0tfJDr.js} +10 -10
- package/dist/{xy-axis-C7fNxDwY.js.map → xy-axis-DL0tfJDr.js.map} +1 -1
- package/dist/xy-pad.js +2 -2
- package/package.json +3 -3
- package/dist/decorate-O4m1U4l3.js.map +0 -1
- package/dist/hex-editor-gH3mteMr.js.map +0 -1
- package/dist/highlight-CAjwQ4GE.js.map +0 -1
- package/dist/icon-CYACf6o8.js.map +0 -1
- package/dist/incr-search-BZawvrfl.js.map +0 -1
- package/dist/index-CwGkb9s1.d.ts.map +0 -1
- package/dist/index-V2cJorlA.d.ts.map +0 -1
- package/dist/labelled-input-base-BvgH7ldm.js.map +0 -1
- package/dist/menu-C3eANB5M.js.map +0 -1
- package/dist/menu-item-6IU5weHi.js.map +0 -1
- package/dist/radial-input-Dbc6fgCK.js.map +0 -1
- package/dist/timeline-B62Sz6J_.js.map +0 -1
- package/dist/tree-data-model-DGvRVOFY.js +0 -190
- package/dist/tree-data-model-DGvRVOFY.js.map +0 -1
- package/dist/tree.js.map +0 -1
- /package/dist/{interaction-CQDQJf2Q.js → interaction-DG7X1rhI.js} +0 -0
package/dist/editable-label.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CSSResult, LitElement } from "lit";
|
|
1
|
+
import { CSSResult, LitElement, PropertyValues } from "lit";
|
|
2
2
|
|
|
3
3
|
//#region src/editable-label/editable-label.d.ts
|
|
4
4
|
type EditableMode = `label` | `editor`;
|
|
@@ -36,6 +36,8 @@ declare class EditableLabel extends LitElement {
|
|
|
36
36
|
protected get _contentEl(): HTMLElement | undefined;
|
|
37
37
|
/** Snapshot of value taken when editing begins; restored on cancel. */
|
|
38
38
|
protected _prevValue: string;
|
|
39
|
+
connectedCallback(): void;
|
|
40
|
+
disconnectedCallback(): void;
|
|
39
41
|
protected _hovering: boolean;
|
|
40
42
|
protected _transientShowingValue: boolean;
|
|
41
43
|
protected _transientTimer: number | undefined;
|
|
@@ -47,6 +49,7 @@ declare class EditableLabel extends LitElement {
|
|
|
47
49
|
protected _requestDisplayUpdate(): void;
|
|
48
50
|
/** Called by subclasses when user interacts (drag, keyboard, etc) to temporarily show value in transient mode */
|
|
49
51
|
protected _onUserInteraction(): void;
|
|
52
|
+
protected _handleClick: () => void;
|
|
50
53
|
protected _handleFocus: () => void;
|
|
51
54
|
protected _handleBlur: () => void;
|
|
52
55
|
protected _handleKeydown: (e: KeyboardEvent) => void;
|
|
@@ -59,6 +62,8 @@ declare class EditableLabel extends LitElement {
|
|
|
59
62
|
protected _shouldUseDisplayText(): boolean;
|
|
60
63
|
protected _isAllowedInput(char: string): boolean;
|
|
61
64
|
private _defaultValidator;
|
|
65
|
+
render(): import("lit").TemplateResult<1>;
|
|
66
|
+
updated(changed: PropertyValues): void;
|
|
62
67
|
static styles: CSSResult[];
|
|
63
68
|
}
|
|
64
69
|
declare global {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-label.d.ts","names":[],"sources":["../src/editable-label/editable-label.ts"],"mappings":";;;KAmCY,YAAA;AAAA,KACA,SAAA;AAAA,KACA,gBAAA;AAAA,KAEA,yBAAA;EAAA,SACD,KAAK;AAAA;AAAA,KAEJ,wBAAA,GAA2B,WAAW,CAAC,yBAAA;AAAA,cAGtC,aAAA,SAAsB,UAAA;EACJ,IAAA,EAAM,YAAA;EACmB,SAAA,EAAW,SAAA;EACpC,KAAA;EACe,QAAA;EAChC,WAAA;
|
|
1
|
+
{"version":3,"file":"editable-label.d.ts","names":[],"sources":["../src/editable-label/editable-label.ts"],"mappings":";;;KAmCY,YAAA;AAAA,KACA,SAAA;AAAA,KACA,gBAAA;AAAA,KAEA,yBAAA;EAAA,SACD,KAAK;AAAA;AAAA,KAEJ,wBAAA,GAA2B,WAAW,CAAC,yBAAA;AAAA,cAGtC,aAAA,SAAsB,UAAA;EACJ,IAAA,EAAM,YAAA;EACmB,SAAA,EAAW,SAAA;EACpC,KAAA;EACe,QAAA;EAChC,WAAA;EAH0C;EAMb,WAAA;EALZ;;;;;;;EAckB,gBAAA,EAAkB,gBAAA;EASjC;EANuB,WAAA;EASvB;EAN0B,cAAA;EAQvC;EALa,SAAA,IAAa,KAAA;EAOjB;EAJI,SAAA,IAAa,KAAA;EAAA,UAE1B,QAAA;EAAA,cAEL,UAAA,CAAA,GAAc,WAAA;EAqBlB;EAAA,UAhBA,UAAA;EAED,iBAAA,CAAA;EAMA,oBAAA,CAAA;EAAA,UAQC,SAAA;EAAA,UACA,sBAAA;EAAA,UACA,eAAA;EAAA,UACA,sBAAA;EAAA,UAEA,oBAAA,CAAA;EAAA,QAOF,aAAA;EAAA,QAWA,aAAA;EAAA,UAOE,0BAAA,CAAA;EAAA,UAUA,qBAAA,CAAA;EAsCA;EAAA,UA5BA,kBAAA,CAAA;EAAA,UAWA,YAAA;EAAA,UAMA,YAAA;EAAA,UAMA,WAAA;EAAA,UAKA,cAAA,GAAkB,CAAA,EAAG,aAAA;EAAA,UAgBrB,kBAAA,GAAsB,CAAA,EAAG,UAAA;EAAA,UAQzB,YAAA;EAAA,UAeA,UAAA,CAAA;EAAA,UAMA,UAAA,CAAA;EAAA,UAsBA,WAAA,CAAA;EAAA,UAMA,eAAA,CAAA;EAAA,UAcA,qBAAA,CAAA;EAAA,UAoBA,eAAA,CAAgB,IAAA;EAAA,QASlB,iBAAA;EAWC,MAAA,CAAA,iBAAM,cAAA;EAgBN,OAAA,CAAQ,OAAA,EAAS,cAAA;EAAA,OAcV,MAAA,EAAQ,SAAA;AAAA;AAAA,QA8FlB,MAAA;EAAA,UACI,qBAAA;IACR,qBAAA,EAAuB,aAAa;EAAA;AAAA"}
|
package/dist/editable-label.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as safeCustomElement, t as __decorate } from "./decorate-
|
|
2
|
-
import { LitElement, css } from "lit";
|
|
1
|
+
import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
|
|
2
|
+
import { LitElement, css, html, nothing } from "lit";
|
|
3
3
|
import { property, state } from "lit/decorators.js";
|
|
4
4
|
//#region src/editable-label/editable-label.ts
|
|
5
5
|
let EditableLabel = class EditableLabel extends LitElement {
|
|
@@ -33,6 +33,9 @@ let EditableLabel = class EditableLabel extends LitElement {
|
|
|
33
33
|
this._hovering = false;
|
|
34
34
|
this._startTransientRevertTimer();
|
|
35
35
|
};
|
|
36
|
+
this._handleClick = () => {
|
|
37
|
+
if (this.mode === `label` && !this.disabled && !this._editing) this._beginEdit();
|
|
38
|
+
};
|
|
36
39
|
this._handleFocus = () => {
|
|
37
40
|
if (this.mode === `editor` && !this.disabled && !this._editing) this._beginEdit();
|
|
38
41
|
};
|
|
@@ -68,6 +71,17 @@ let EditableLabel = class EditableLabel extends LitElement {
|
|
|
68
71
|
get _contentEl() {
|
|
69
72
|
return this.renderRoot?.querySelector(`.content`) ?? void 0;
|
|
70
73
|
}
|
|
74
|
+
connectedCallback() {
|
|
75
|
+
super.connectedCallback();
|
|
76
|
+
this.addEventListener(`mouseenter`, this._onMouseEnter);
|
|
77
|
+
this.addEventListener(`mouseleave`, this._onMouseLeave);
|
|
78
|
+
}
|
|
79
|
+
disconnectedCallback() {
|
|
80
|
+
super.disconnectedCallback();
|
|
81
|
+
this.removeEventListener(`mouseenter`, this._onMouseEnter);
|
|
82
|
+
this.removeEventListener(`mouseleave`, this._onMouseLeave);
|
|
83
|
+
this._clearTransientTimer();
|
|
84
|
+
}
|
|
71
85
|
_clearTransientTimer() {
|
|
72
86
|
if (this._transientTimer !== void 0) {
|
|
73
87
|
clearTimeout(this._transientTimer);
|
|
@@ -161,6 +175,32 @@ let EditableLabel = class EditableLabel extends LitElement {
|
|
|
161
175
|
default: return true;
|
|
162
176
|
}
|
|
163
177
|
}
|
|
178
|
+
render() {
|
|
179
|
+
const isEditor = this.mode === `editor`;
|
|
180
|
+
return html`<div
|
|
181
|
+
class="content"
|
|
182
|
+
contenteditable=${this._editing ? `plaintext-only` : `false`}
|
|
183
|
+
data-placeholder=${this.placeholder}
|
|
184
|
+
tabindex=${isEditor && !this._editing ? `0` : nothing}
|
|
185
|
+
@click=${this._handleClick}
|
|
186
|
+
@focus=${this._handleFocus}
|
|
187
|
+
@blur=${this._handleBlur}
|
|
188
|
+
@keydown=${this._handleKeydown}
|
|
189
|
+
@beforeinput=${this._handleBeforeInput}
|
|
190
|
+
@input=${this._handleInput}
|
|
191
|
+
>${this._editing ? nothing : this._getDisplayText()}</div>`;
|
|
192
|
+
}
|
|
193
|
+
updated(changed) {
|
|
194
|
+
super.updated(changed);
|
|
195
|
+
if (changed.has(`_editing`) && this._editing) {
|
|
196
|
+
const el = this._contentEl;
|
|
197
|
+
if (el) {
|
|
198
|
+
el.textContent = this.value;
|
|
199
|
+
el.focus();
|
|
200
|
+
_selectAll(el);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
164
204
|
static {
|
|
165
205
|
this.styles = [css`
|
|
166
206
|
:host {
|
|
@@ -273,6 +313,13 @@ __decorate([property({ attribute: false })], EditableLabel.prototype, "validator
|
|
|
273
313
|
__decorate([property({ attribute: false })], EditableLabel.prototype, "formatter", void 0);
|
|
274
314
|
__decorate([state()], EditableLabel.prototype, "_editing", void 0);
|
|
275
315
|
EditableLabel = __decorate([safeCustomElement(`ixfx-editable-label`)], EditableLabel);
|
|
316
|
+
function _selectAll(el) {
|
|
317
|
+
const range = document.createRange();
|
|
318
|
+
range.selectNodeContents(el);
|
|
319
|
+
const sel = window.getSelection();
|
|
320
|
+
sel?.removeAllRanges();
|
|
321
|
+
sel?.addRange(range);
|
|
322
|
+
}
|
|
276
323
|
//#endregion
|
|
277
324
|
export { EditableLabel };
|
|
278
325
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-label.js","names":["customElement"],"sources":["../src/editable-label/editable-label.ts"],"sourcesContent":["/**\n * <ixfx-editable-label> — inline editable text label.\n *\n * Two display modes:\n * label (default) — renders as plain text until clicked, then becomes an editable box.\n * editor — always renders as an editable box; becomes active on focus/click.\n *\n * Entry modes (filter characters as typed):\n * free (default) — no restrictions\n * text — alphabetical characters and spaces only\n * number — digits, decimal point, minus sign\n * percent — digits, decimal point, percent sign\n *\n * Properties (not attributes):\n * validator (value: string) => boolean — override commit validation; default uses entry-mode rules\n * formatter (value: string) => string — transform committed value for display\n *\n * Events:\n * input — CustomEvent<{ value: string }>, bubbles + composed; fired as value changes during editing\n * change — CustomEvent<{ value: string }>, bubbles + composed; fired when value is committed\n *\n * CSS variables:\n * --label-font-size defaults to var(--text-m, 12px)\n * --label-font-family defaults to var(--font-family, system-ui, sans-serif)\n * --label-color defaults to var(--surface-2-text)\n * --label-muted-color placeholder colour, defaults to var(--surface-muted-text)\n * --label-padding defaults to var(--space-xs, 3px) var(--space-s, 4px)\n * --label-radius defaults to var(--radius-s, 3px)\n * --label-align text alignment: left | center (default) | right\n */\nimport type { CSSResult } from 'lit';\nimport { css, html, LitElement } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type EditableMode = `label` | `editor`;\nexport type EntryMode = `free` | `text` | `number` | `percent`;\nexport type DisplayTextLogic = `hidden` | `show` | `override` | `transient`;\n\nexport type EditableLabelChangeDetail = {\n readonly value: string;\n};\nexport type EditableLabelChangeEvent = CustomEvent<EditableLabelChangeDetail>;\n\n@customElement(`ixfx-editable-label`)\nexport class EditableLabel extends LitElement {\n @property({ reflect: true }) mode: EditableMode = `label`;\n @property({ attribute: `entry-mode`, reflect: true }) entryMode: EntryMode = `free`;\n @property({ reflect: true }) value = ``;\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property() placeholder = ``;\n\n /** Override displayed text. Bypasses formatter and value. When editing, shows raw value. */\n @property({ attribute: `display-text` }) displayText?: string;\n\n /**\n * Controls when displayText is shown:\n * - 'hidden' (default): never use displayText\n * - 'show': show displayText instead of formatted value, but hide while editing; revert after disappearDelay\n * - 'override': always show displayText, even when editing\n * - 'transient': show displayText by default, switch to formatted value after appearDelay on hover/interaction; revert after disappearDelay\n */\n @property({ attribute: `display-text-logic` }) displayTextLogic: DisplayTextLogic = `hidden`;\n\n /** Delay before showing value in transient mode (ms). Default: 50 */\n @property({ type: Number, attribute: `appear-delay` }) appearDelay = 50;\n\n /** Delay before reverting to displayText after editing ends (ms). Default: 1000 */\n @property({ type: Number, attribute: `disappear-delay` }) disappearDelay = 1000;\n\n /** Override commit validation. Return true to accept, false to reject (reverts). */\n @property({ attribute: false }) validator?: (value: string) => boolean;\n\n /** Transform the committed value for display. Does not affect the stored value. */\n @property({ attribute: false }) formatter?: (value: string) => string;\n\n @state() protected _editing = false;\n\n protected get _contentEl(): HTMLElement | undefined {\n return this.renderRoot?.querySelector<HTMLElement>(`.content`) ?? undefined;\n }\n\n /** Snapshot of value taken when editing begins; restored on cancel. */\n protected _prevValue = ``;\n\n // ── Transient display state ─────────────────────────────────────────────────\n protected _hovering = false;\n protected _transientShowingValue = false;\n protected _transientTimer: number | undefined = undefined;\n protected _showModeWaitingToHide = false;\n\n protected _clearTransientTimer(): void {\n if (this._transientTimer !== undefined) {\n clearTimeout(this._transientTimer);\n this._transientTimer = undefined;\n }\n }\n\n private _onMouseEnter = (): void => {\n if (this.displayTextLogic !== `transient`)\n return;\n this._hovering = true;\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n this._transientShowingValue = true;\n this._requestDisplayUpdate();\n }, this.appearDelay);\n };\n\n private _onMouseLeave = (): void => {\n if (this.displayTextLogic !== `transient`)\n return;\n this._hovering = false;\n this._startTransientRevertTimer();\n };\n\n protected _startTransientRevertTimer(): void {\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n if (!this._hovering && this.displayTextLogic === `transient`) {\n this._transientShowingValue = false;\n this._requestDisplayUpdate();\n }\n }, this.disappearDelay);\n }\n\n protected _requestDisplayUpdate(): void {\n if (!this._editing) {\n const el = this._contentEl;\n if (el) {\n el.textContent = this._getDisplayText();\n }\n }\n }\n\n /** Called by subclasses when user interacts (drag, keyboard, etc) to temporarily show value in transient mode */\n protected _onUserInteraction(): void {\n if (this.displayTextLogic !== `transient`)\n return;\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n this._transientShowingValue = true;\n this._startTransientRevertTimer();\n this._requestDisplayUpdate();\n }, this.appearDelay);\n };\n\n protected _handleFocus = (): void => {\n if (this.mode === `editor` && !this.disabled && !this._editing) {\n this._beginEdit();\n }\n };\n\n protected _handleBlur = (): void => {\n if (this._editing)\n this._tryCommit();\n };\n\n protected _handleKeydown = (e: KeyboardEvent): void => {\n if (!this._editing)\n return;\n if (e.key === `Enter`) {\n e.preventDefault();\n this._tryCommit();\n if (this.mode === `editor`)\n this._contentEl?.blur();\n } else if (e.key === `Escape`) {\n e.preventDefault();\n this._cancelEdit();\n if (this.mode === `editor`)\n this._contentEl?.blur();\n }\n };\n\n protected _handleBeforeInput = (e: InputEvent): void => {\n if (e.inputType !== `insertText` || !e.data)\n return;\n if (!this._isAllowedInput(e.data)) {\n e.preventDefault();\n }\n };\n\n protected _handleInput = (): void => {\n if (!this._editing)\n return;\n\n const raw = this._contentEl?.textContent?.trim() ?? ``;\n\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`input`, {\n detail: { value: raw },\n bubbles: true,\n composed: true,\n }));\n };\n\n // ── Core logic ───────────────────────────────────────────────────────────\n\n protected _beginEdit(): void {\n this._prevValue = this.value;\n this._editing = true;\n this.removeAttribute(`invalid`);\n }\n\n protected _tryCommit(): void {\n let raw = this._contentEl?.textContent?.trim() ?? ``;\n if (this.entryMode === `percent`)\n raw = raw.replaceAll(`%`, ``).trim();\n const validate = this.validator ?? this._defaultValidator.bind(this);\n if (validate(raw)) {\n this.removeAttribute(`invalid`);\n const prev = this.value;\n this.value = raw;\n this._editing = false;\n if (raw !== prev) {\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`change`, {\n detail: { value: raw },\n bubbles: true,\n composed: true,\n }));\n }\n } else {\n this._cancelEdit();\n }\n }\n\n protected _cancelEdit(): void {\n this.value = this._prevValue;\n this._editing = false;\n this.removeAttribute(`invalid`);\n }\n\n protected _getDisplayText(): string {\n const useDisplayText = this._shouldUseDisplayText();\n if (useDisplayText && this.displayText !== undefined && this.displayText !== ``) {\n return this.displayText;\n }\n if (!this.value)\n return ``;\n if (this.formatter)\n return this.formatter(this.value);\n if (this.entryMode === `percent`)\n return `${this.value}%`;\n return this.value;\n }\n\n protected _shouldUseDisplayText(): boolean {\n if (this.displayTextLogic === `hidden`)\n return false;\n if (this.displayTextLogic === `override`)\n return true;\n if (this.displayTextLogic === `show`) {\n if (this._editing)\n return false;\n return this._showModeWaitingToHide;\n }\n if (this.displayTextLogic === `transient`) {\n if (this._editing)\n return false;\n if (this._transientShowingValue)\n return false;\n return true;\n }\n return false;\n }\n\n protected _isAllowedInput(char: string): boolean {\n switch (this.entryMode) {\n case `text`: return /^[a-z\\s]$/i.test(char);\n case `number`: return /^[\\d.\\-]$/.test(char);\n case `percent`: return /^[\\d.%]$/.test(char);\n default: return true;\n }\n }\n\n private _defaultValidator(value: string): boolean {\n switch (this.entryMode) {\n case `text`: return /^[a-z\\s]*$/i.test(value);\n case `number`: return value === `` || /^-?\\d*(?:\\.\\d*)?$/.test(value);\n case `percent`: return value === `` || /^\\d*(?:\\.\\d*)?$/.test(value);\n default: return true;\n } // asdf\n }\n\n // ── Styles ───────────────────────────────────────────────────────────────\n\n static override styles: CSSResult[] = [css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n --_font-size: var(--label-font-size, var(--text-m, 12px));\n --_font-family: var(--label-font-family, var(--font-family, system-ui, sans-serif));\n --_color: var(--label-color, var(--surface-2-text));\n --_muted: var(--label-muted-color, var(--surface-muted-text, oklch(55% 0.02 240)));\n --_padding: var(--label-padding, var(--space-xs, 3px) var(--space-s, 4px));\n --_radius: var(--label-radius, var(--radius-s, 3px));\n --_align: var(--label-align, center);\n --_min-width: var(--label-min-width, 1ch);\n }\n\n .content {\n box-sizing: border-box;\n width: 100%;\n text-align: var(--_align);\n outline: none;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: var(--_min-width);\n font-family: var(--_font-family);\n font-size: var(--_font-size);\n color: var(--_color);\n padding: var(--_padding);\n border: 1px solid transparent;\n border-radius: var(--_radius);\n cursor: pointer;\n transition:\n background var(--transition, 0.15s ease-out),\n border-color var(--transition, 0.15s ease-out);\n }\n\n /* Remove overflow clipping while editing so the cursor is never hidden */\n .content[contenteditable=\"plaintext-only\"] {\n overflow: visible;\n text-overflow: clip;\n }\n\n /* ── Label mode ── */\n :host([mode=\"label\"]) .content {\n background: transparent;\n }\n\n :host([mode=\"label\"]) .content[contenteditable=\"plaintext-only\"] {\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n cursor: text;\n }\n\n /* ── Editor mode — always shows box ── */\n :host([mode=\"editor\"]) .content {\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n }\n\n :host([mode=\"editor\"]) .content[contenteditable=\"plaintext-only\"] {\n border-color: var(--accent, oklch(60% 0.15 140));\n cursor: text;\n }\n\n /* ── Placeholder ── */\n .content:empty::before {\n content: attr(data-placeholder);\n color: var(--_muted);\n pointer-events: none;\n }\n\n /* ── Invalid ── */\n :host([invalid]) .content {\n border-color: var(--error, oklch(60% 0.15 20));\n }\n\n /* ── Disabled ── */\n :host([disabled]) .content {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n `];\n}\n\nfunction _selectAll(el: HTMLElement): void {\n const range = document.createRange();\n range.selectNodeContents(el);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-editable-label': EditableLabel;\n }\n}\n"],"mappings":";;;;AA6CO,IAAA,gBAAA,MAAM,sBAAsB,WAAW;;;cACM;mBAC2B;eACxC;kBACkB;qBAC7B;0BAY0D;qBAGf;wBAGM;kBAQ7C;oBAOP;mBAGD;gCACa;yBACa,KAAA;gCACb;6BASC;GAClC,IAAI,KAAK,qBAAqB,aAC5B;GACF,KAAK,YAAY;GACjB,KAAK,qBAAqB;GAC1B,KAAK,kBAAkB,OAAO,iBAAiB;IAC7C,KAAK,yBAAyB;IAC9B,KAAK,sBAAsB;GAC7B,GAAG,KAAK,WAAW;EACrB;6BAEoC;GAClC,IAAI,KAAK,qBAAqB,aAC5B;GACF,KAAK,YAAY;GACjB,KAAK,2BAA2B;EAClC;4BAiCqC;GACnC,IAAI,KAAK,SAAS,YAAY,CAAC,KAAK,YAAY,CAAC,KAAK,UACpD,KAAK,WAAW;EAEpB;2BAEoC;GAClC,IAAI,KAAK,UACP,KAAK,WAAW;EACpB;yBAE4B,MAA2B;GACrD,IAAI,CAAC,KAAK,UACR;GACF,IAAI,EAAE,QAAQ,SAAS;IACrB,EAAE,eAAe;IACjB,KAAK,WAAW;IAChB,IAAI,KAAK,SAAS,UAChB,KAAK,YAAY,KAAK;GAC1B,OAAO,IAAI,EAAE,QAAQ,UAAU;IAC7B,EAAE,eAAe;IACjB,KAAK,YAAY;IACjB,IAAI,KAAK,SAAS,UAChB,KAAK,YAAY,KAAK;GAC1B;EACF;6BAEgC,MAAwB;GACtD,IAAI,EAAE,cAAc,gBAAgB,CAAC,EAAE,MACrC;GACF,IAAI,CAAC,KAAK,gBAAgB,EAAE,IAAI,GAC9B,EAAE,eAAe;EAErB;4BAEqC;GACnC,IAAI,CAAC,KAAK,UACR;GAEF,MAAM,MAAM,KAAK,YAAY,aAAa,KAAK,KAAK;GAEpD,KAAK,cAAc,IAAI,YAAuC,SAAS;IACrE,QAAQ,EAAE,OAAO,IAAI;IACrB,SAAS;IACT,UAAU;GACZ,CAAC,CAAC;EACJ;;CAnHA,IAAc,aAAsC;EAClD,OAAO,KAAK,YAAY,cAA2B,UAAU,KAAK,KAAA;CACpE;CAWA,uBAAuC;EACrC,IAAI,KAAK,oBAAoB,KAAA,GAAW;GACtC,aAAa,KAAK,eAAe;GACjC,KAAK,kBAAkB,KAAA;EACzB;CACF;CAoBA,6BAA6C;EAC3C,KAAK,qBAAqB;EAC1B,KAAK,kBAAkB,OAAO,iBAAiB;GAC7C,IAAI,CAAC,KAAK,aAAa,KAAK,qBAAqB,aAAa;IAC5D,KAAK,yBAAyB;IAC9B,KAAK,sBAAsB;GAC7B;EACF,GAAG,KAAK,cAAc;CACxB;CAEA,wBAAwC;EACtC,IAAI,CAAC,KAAK,UAAU;GAClB,MAAM,KAAK,KAAK;GAChB,IAAI,IACF,GAAG,cAAc,KAAK,gBAAgB;EAE1C;CACF;;CAGA,qBAAqC;EACnC,IAAI,KAAK,qBAAqB,aAC5B;EACF,KAAK,qBAAqB;EAC1B,KAAK,kBAAkB,OAAO,iBAAiB;GAC7C,KAAK,yBAAyB;GAC9B,KAAK,2BAA2B;GAChC,KAAK,sBAAsB;EAC7B,GAAG,KAAK,WAAW;CACrB;CAoDA,aAA6B;EAC3B,KAAK,aAAa,KAAK;EACvB,KAAK,WAAW;EAChB,KAAK,gBAAgB,SAAS;CAChC;CAEA,aAA6B;EAC3B,IAAI,MAAM,KAAK,YAAY,aAAa,KAAK,KAAK;EAClD,IAAI,KAAK,cAAc,WACrB,MAAM,IAAI,WAAW,KAAK,EAAE,EAAE,KAAK;EAErC,KADiB,KAAK,aAAa,KAAK,kBAAkB,KAAK,IAAI,GACtD,GAAG,GAAG;GACjB,KAAK,gBAAgB,SAAS;GAC9B,MAAM,OAAO,KAAK;GAClB,KAAK,QAAQ;GACb,KAAK,WAAW;GAChB,IAAI,QAAQ,MACV,KAAK,cAAc,IAAI,YAAuC,UAAU;IACtE,QAAQ,EAAE,OAAO,IAAI;IACrB,SAAS;IACT,UAAU;GACZ,CAAC,CAAC;EAEN,OACE,KAAK,YAAY;CAErB;CAEA,cAA8B;EAC5B,KAAK,QAAQ,KAAK;EAClB,KAAK,WAAW;EAChB,KAAK,gBAAgB,SAAS;CAChC;CAEA,kBAAoC;EAElC,IADuB,KAAK,sBACX,KAAK,KAAK,gBAAgB,KAAA,KAAa,KAAK,gBAAgB,IAC3E,OAAO,KAAK;EAEd,IAAI,CAAC,KAAK,OACR,OAAO;EACT,IAAI,KAAK,WACP,OAAO,KAAK,UAAU,KAAK,KAAK;EAClC,IAAI,KAAK,cAAc,WACrB,OAAO,GAAG,KAAK,MAAM;EACvB,OAAO,KAAK;CACd;CAEA,wBAA2C;EACzC,IAAI,KAAK,qBAAqB,UAC5B,OAAO;EACT,IAAI,KAAK,qBAAqB,YAC5B,OAAO;EACT,IAAI,KAAK,qBAAqB,QAAQ;GACpC,IAAI,KAAK,UACP,OAAO;GACT,OAAO,KAAK;EACd;EACA,IAAI,KAAK,qBAAqB,aAAa;GACzC,IAAI,KAAK,UACP,OAAO;GACT,IAAI,KAAK,wBACP,OAAO;GACT,OAAO;EACT;EACA,OAAO;CACT;CAEA,gBAA0B,MAAuB;EAC/C,QAAQ,KAAK,WAAb;GACE,KAAK,QAAQ,OAAO,aAAa,KAAK,IAAI;GAC1C,KAAK,UAAU,OAAO,YAAY,KAAK,IAAI;GAC3C,KAAK,WAAW,OAAO,WAAW,KAAK,IAAI;GAC3C,SAAS,OAAO;EAClB;CACF;CAEA,kBAA0B,OAAwB;EAChD,QAAQ,KAAK,WAAb;GACE,KAAK,QAAQ,OAAO,cAAc,KAAK,KAAK;GAC5C,KAAK,UAAU,OAAO,UAAU,MAAM,oBAAoB,KAAK,KAAK;GACpE,KAAK,WAAW,OAAO,UAAU,MAAM,kBAAkB,KAAK,KAAK;GACnE,SAAS,OAAO;EAClB;CACF;;gBAIsC,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFzC;;AACH;YAnUG,SAAS,EAAE,SAAS,KAAK,CAAC,CAAA,GAAA,cAAA,WAAA,QAAA,KAAA,CAAA;YAC1B,SAAS;CAAE,WAAW;CAAc,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,aAAA,KAAA,CAAA;YACnD,SAAS,EAAE,SAAS,KAAK,CAAC,CAAA,GAAA,cAAA,WAAA,SAAA,KAAA,CAAA;YAC1B,SAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,YAAA,KAAA,CAAA;YACzC,SAAS,CAAA,GAAA,cAAA,WAAA,eAAA,KAAA,CAAA;YAGT,SAAS,EAAE,WAAW,eAAe,CAAC,CAAA,GAAA,cAAA,WAAA,eAAA,KAAA,CAAA;YAStC,SAAS,EAAE,WAAW,qBAAqB,CAAC,CAAA,GAAA,cAAA,WAAA,oBAAA,KAAA,CAAA;YAG5C,SAAS;CAAE,MAAM;CAAQ,WAAW;AAAe,CAAC,CAAA,GAAA,cAAA,WAAA,eAAA,KAAA,CAAA;YAGpD,SAAS;CAAE,MAAM;CAAQ,WAAW;AAAkB,CAAC,CAAA,GAAA,cAAA,WAAA,kBAAA,KAAA,CAAA;YAGvD,SAAS,EAAE,WAAW,MAAM,CAAC,CAAA,GAAA,cAAA,WAAA,aAAA,KAAA,CAAA;YAG7B,SAAS,EAAE,WAAW,MAAM,CAAC,CAAA,GAAA,cAAA,WAAA,aAAA,KAAA,CAAA;YAE7B,MAAM,CAAA,GAAA,cAAA,WAAA,YAAA,KAAA,CAAA;4BAhCRA,kBAAc,qBAAqB,CAAA,GAAA,aAAA"}
|
|
1
|
+
{"version":3,"file":"editable-label.js","names":["customElement"],"sources":["../src/editable-label/editable-label.ts"],"sourcesContent":["/**\n * <ixfx-editable-label> — inline editable text label.\n *\n * Two display modes:\n * label (default) — renders as plain text until clicked, then becomes an editable box.\n * editor — always renders as an editable box; becomes active on focus/click.\n *\n * Entry modes (filter characters as typed):\n * free (default) — no restrictions\n * text — alphabetical characters and spaces only\n * number — digits, decimal point, minus sign\n * percent — digits, decimal point, percent sign\n *\n * Properties (not attributes):\n * validator (value: string) => boolean — override commit validation; default uses entry-mode rules\n * formatter (value: string) => string — transform committed value for display\n *\n * Events:\n * input — CustomEvent<{ value: string }>, bubbles + composed; fired as value changes during editing\n * change — CustomEvent<{ value: string }>, bubbles + composed; fired when value is committed\n *\n * CSS variables:\n * --label-font-size defaults to var(--text-m, 12px)\n * --label-font-family defaults to var(--font-family, system-ui, sans-serif)\n * --label-color defaults to var(--surface-2-text)\n * --label-muted-color placeholder colour, defaults to var(--surface-muted-text)\n * --label-padding defaults to var(--space-xs, 3px) var(--space-s, 4px)\n * --label-radius defaults to var(--radius-s, 3px)\n * --label-align text alignment: left | center (default) | right\n */\nimport type { CSSResult, PropertyValues } from 'lit';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type EditableMode = `label` | `editor`;\nexport type EntryMode = `free` | `text` | `number` | `percent`;\nexport type DisplayTextLogic = `hidden` | `show` | `override` | `transient`;\n\nexport type EditableLabelChangeDetail = {\n readonly value: string;\n};\nexport type EditableLabelChangeEvent = CustomEvent<EditableLabelChangeDetail>;\n\n@customElement(`ixfx-editable-label`)\nexport class EditableLabel extends LitElement {\n @property({ reflect: true }) mode: EditableMode = `label`;\n @property({ attribute: `entry-mode`, reflect: true }) entryMode: EntryMode = `free`;\n @property({ reflect: true }) value = ``;\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property() placeholder = ``;\n\n /** Override displayed text. Bypasses formatter and value. When editing, shows raw value. */\n @property({ attribute: `display-text` }) displayText?: string;\n\n /**\n * Controls when displayText is shown:\n * - 'hidden' (default): never use displayText\n * - 'show': show displayText instead of formatted value, but hide while editing; revert after disappearDelay\n * - 'override': always show displayText, even when editing\n * - 'transient': show displayText by default, switch to formatted value after appearDelay on hover/interaction; revert after disappearDelay\n */\n @property({ attribute: `display-text-logic` }) displayTextLogic: DisplayTextLogic = `hidden`;\n\n /** Delay before showing value in transient mode (ms). Default: 50 */\n @property({ type: Number, attribute: `appear-delay` }) appearDelay = 50;\n\n /** Delay before reverting to displayText after editing ends (ms). Default: 1000 */\n @property({ type: Number, attribute: `disappear-delay` }) disappearDelay = 1000;\n\n /** Override commit validation. Return true to accept, false to reject (reverts). */\n @property({ attribute: false }) validator?: (value: string) => boolean;\n\n /** Transform the committed value for display. Does not affect the stored value. */\n @property({ attribute: false }) formatter?: (value: string) => string;\n\n @state() protected _editing = false;\n\n protected get _contentEl(): HTMLElement | undefined {\n return this.renderRoot?.querySelector<HTMLElement>(`.content`) ?? undefined;\n }\n\n /** Snapshot of value taken when editing begins; restored on cancel. */\n protected _prevValue = ``;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`mouseenter`, this._onMouseEnter);\n this.addEventListener(`mouseleave`, this._onMouseLeave);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`mouseenter`, this._onMouseEnter);\n this.removeEventListener(`mouseleave`, this._onMouseLeave);\n this._clearTransientTimer();\n }\n\n // ── Transient display state ─────────────────────────────────────────────────\n protected _hovering = false;\n protected _transientShowingValue = false;\n protected _transientTimer: number | undefined = undefined;\n protected _showModeWaitingToHide = false;\n\n protected _clearTransientTimer(): void {\n if (this._transientTimer !== undefined) {\n clearTimeout(this._transientTimer);\n this._transientTimer = undefined;\n }\n }\n\n private _onMouseEnter = (): void => {\n if (this.displayTextLogic !== `transient`)\n return;\n this._hovering = true;\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n this._transientShowingValue = true;\n this._requestDisplayUpdate();\n }, this.appearDelay);\n };\n\n private _onMouseLeave = (): void => {\n if (this.displayTextLogic !== `transient`)\n return;\n this._hovering = false;\n this._startTransientRevertTimer();\n };\n\n protected _startTransientRevertTimer(): void {\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n if (!this._hovering && this.displayTextLogic === `transient`) {\n this._transientShowingValue = false;\n this._requestDisplayUpdate();\n }\n }, this.disappearDelay);\n }\n\n protected _requestDisplayUpdate(): void {\n if (!this._editing) {\n const el = this._contentEl;\n if (el) {\n el.textContent = this._getDisplayText();\n }\n }\n }\n\n /** Called by subclasses when user interacts (drag, keyboard, etc) to temporarily show value in transient mode */\n protected _onUserInteraction(): void {\n if (this.displayTextLogic !== `transient`)\n return;\n this._clearTransientTimer();\n this._transientTimer = window.setTimeout(() => {\n this._transientShowingValue = true;\n this._startTransientRevertTimer();\n this._requestDisplayUpdate();\n }, this.appearDelay);\n };\n\n protected _handleClick = (): void => {\n if (this.mode === `label` && !this.disabled && !this._editing) {\n this._beginEdit();\n }\n };\n\n protected _handleFocus = (): void => {\n if (this.mode === `editor` && !this.disabled && !this._editing) {\n this._beginEdit();\n }\n };\n\n protected _handleBlur = (): void => {\n if (this._editing)\n this._tryCommit();\n };\n\n protected _handleKeydown = (e: KeyboardEvent): void => {\n if (!this._editing)\n return;\n if (e.key === `Enter`) {\n e.preventDefault();\n this._tryCommit();\n if (this.mode === `editor`)\n this._contentEl?.blur();\n } else if (e.key === `Escape`) {\n e.preventDefault();\n this._cancelEdit();\n if (this.mode === `editor`)\n this._contentEl?.blur();\n }\n };\n\n protected _handleBeforeInput = (e: InputEvent): void => {\n if (e.inputType !== `insertText` || !e.data)\n return;\n if (!this._isAllowedInput(e.data)) {\n e.preventDefault();\n }\n };\n\n protected _handleInput = (): void => {\n if (!this._editing)\n return;\n\n const raw = this._contentEl?.textContent?.trim() ?? ``;\n\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`input`, {\n detail: { value: raw },\n bubbles: true,\n composed: true,\n }));\n };\n\n // ── Core logic ───────────────────────────────────────────────────────────\n\n protected _beginEdit(): void {\n this._prevValue = this.value;\n this._editing = true;\n this.removeAttribute(`invalid`);\n }\n\n protected _tryCommit(): void {\n let raw = this._contentEl?.textContent?.trim() ?? ``;\n if (this.entryMode === `percent`)\n raw = raw.replaceAll(`%`, ``).trim();\n const validate = this.validator ?? this._defaultValidator.bind(this);\n if (validate(raw)) {\n this.removeAttribute(`invalid`);\n const prev = this.value;\n this.value = raw;\n this._editing = false;\n if (raw !== prev) {\n this.dispatchEvent(new CustomEvent<EditableLabelChangeDetail>(`change`, {\n detail: { value: raw },\n bubbles: true,\n composed: true,\n }));\n }\n } else {\n this._cancelEdit();\n }\n }\n\n protected _cancelEdit(): void {\n this.value = this._prevValue;\n this._editing = false;\n this.removeAttribute(`invalid`);\n }\n\n protected _getDisplayText(): string {\n const useDisplayText = this._shouldUseDisplayText();\n if (useDisplayText && this.displayText !== undefined && this.displayText !== ``) {\n return this.displayText;\n }\n if (!this.value)\n return ``;\n if (this.formatter)\n return this.formatter(this.value);\n if (this.entryMode === `percent`)\n return `${this.value}%`;\n return this.value;\n }\n\n protected _shouldUseDisplayText(): boolean {\n if (this.displayTextLogic === `hidden`)\n return false;\n if (this.displayTextLogic === `override`)\n return true;\n if (this.displayTextLogic === `show`) {\n if (this._editing)\n return false;\n return this._showModeWaitingToHide;\n }\n if (this.displayTextLogic === `transient`) {\n if (this._editing)\n return false;\n if (this._transientShowingValue)\n return false;\n return true;\n }\n return false;\n }\n\n protected _isAllowedInput(char: string): boolean {\n switch (this.entryMode) {\n case `text`: return /^[a-z\\s]$/i.test(char);\n case `number`: return /^[\\d.\\-]$/.test(char);\n case `percent`: return /^[\\d.%]$/.test(char);\n default: return true;\n }\n }\n\n private _defaultValidator(value: string): boolean {\n switch (this.entryMode) {\n case `text`: return /^[a-z\\s]*$/i.test(value);\n case `number`: return value === `` || /^-?\\d*(?:\\.\\d*)?$/.test(value);\n case `percent`: return value === `` || /^\\d*(?:\\.\\d*)?$/.test(value);\n default: return true;\n } // asdf\n }\n\n // ── Render ───────────────────────────────────────────────────────────────\n\n override render() {\n const isEditor = this.mode === `editor`;\n return html`<div\n class=\"content\"\n contenteditable=${this._editing ? `plaintext-only` : `false`}\n data-placeholder=${this.placeholder}\n tabindex=${isEditor && !this._editing ? `0` : nothing}\n @click=${this._handleClick}\n @focus=${this._handleFocus}\n @blur=${this._handleBlur}\n @keydown=${this._handleKeydown}\n @beforeinput=${this._handleBeforeInput}\n @input=${this._handleInput}\n >${this._editing ? nothing : this._getDisplayText()}</div>`;\n }\n\n override updated(changed: PropertyValues): void {\n super.updated(changed);\n if (changed.has(`_editing`) && this._editing) {\n const el = this._contentEl;\n if (el) {\n el.textContent = this.value;\n el.focus();\n _selectAll(el);\n }\n }\n }\n\n // ── Styles ───────────────────────────────────────────────────────────────\n\n static override styles: CSSResult[] = [css`\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n --_font-size: var(--label-font-size, var(--text-m, 12px));\n --_font-family: var(--label-font-family, var(--font-family, system-ui, sans-serif));\n --_color: var(--label-color, var(--surface-2-text));\n --_muted: var(--label-muted-color, var(--surface-muted-text, oklch(55% 0.02 240)));\n --_padding: var(--label-padding, var(--space-xs, 3px) var(--space-s, 4px));\n --_radius: var(--label-radius, var(--radius-s, 3px));\n --_align: var(--label-align, center);\n --_min-width: var(--label-min-width, 1ch);\n }\n\n .content {\n box-sizing: border-box;\n width: 100%;\n text-align: var(--_align);\n outline: none;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: var(--_min-width);\n font-family: var(--_font-family);\n font-size: var(--_font-size);\n color: var(--_color);\n padding: var(--_padding);\n border: 1px solid transparent;\n border-radius: var(--_radius);\n cursor: pointer;\n transition:\n background var(--transition, 0.15s ease-out),\n border-color var(--transition, 0.15s ease-out);\n }\n\n /* Remove overflow clipping while editing so the cursor is never hidden */\n .content[contenteditable=\"plaintext-only\"] {\n overflow: visible;\n text-overflow: clip;\n }\n\n /* ── Label mode ── */\n :host([mode=\"label\"]) .content {\n background: transparent;\n }\n\n :host([mode=\"label\"]) .content[contenteditable=\"plaintext-only\"] {\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n cursor: text;\n }\n\n /* ── Editor mode — always shows box ── */\n :host([mode=\"editor\"]) .content {\n background: var(--surface-4, oklch(22% 0.02 240));\n border: var(--border, 1px solid oklch(25% 0.02 240));\n }\n\n :host([mode=\"editor\"]) .content[contenteditable=\"plaintext-only\"] {\n border-color: var(--accent, oklch(60% 0.15 140));\n cursor: text;\n }\n\n /* ── Placeholder ── */\n .content:empty::before {\n content: attr(data-placeholder);\n color: var(--_muted);\n pointer-events: none;\n }\n\n /* ── Invalid ── */\n :host([invalid]) .content {\n border-color: var(--error, oklch(60% 0.15 20));\n }\n\n /* ── Disabled ── */\n :host([disabled]) .content {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n `];\n}\n\nfunction _selectAll(el: HTMLElement): void {\n const range = document.createRange();\n range.selectNodeContents(el);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-editable-label': EditableLabel;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as safeCustomElement, t as __decorate } from "./decorate-
|
|
2
|
-
import { t as colour_exports } from "./colour-C3MQIjFJ-
|
|
1
|
+
import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
|
|
2
|
+
import { t as colour_exports } from "./colour-C3MQIjFJ-BLXg8W3U.js";
|
|
3
3
|
import { LitElement, css, html } from "lit";
|
|
4
4
|
import { property, state } from "lit/decorators.js";
|
|
5
|
-
import { styleMap } from "lit/directives/style-map.js";
|
|
6
5
|
import { repeat } from "lit/directives/repeat.js";
|
|
6
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
7
7
|
//#region src/hex/colour.ts
|
|
8
8
|
const WHITESPACE_BYTES = new Set([
|
|
9
9
|
9,
|
|
@@ -13,45 +13,45 @@ const WHITESPACE_BYTES = new Set([
|
|
|
13
13
|
13,
|
|
14
14
|
32
|
|
15
15
|
]);
|
|
16
|
-
|
|
16
|
+
function isControlByte(byte) {
|
|
17
17
|
return byte < 32 && byte !== 9 && byte !== 10 && byte !== 11 && byte !== 12 && byte !== 13;
|
|
18
|
-
}
|
|
19
|
-
|
|
18
|
+
}
|
|
19
|
+
function isPrintableAscii(byte) {
|
|
20
20
|
return byte >= 32 && byte <= 126;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (byte === 0) return
|
|
24
|
-
if (WHITESPACE_BYTES.has(byte)) return
|
|
25
|
-
if (isControlByte(byte)) return
|
|
26
|
-
if (isPrintableAscii(byte)) return
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
21
|
+
}
|
|
22
|
+
function getAsciiClass(byte) {
|
|
23
|
+
if (byte === 0) return `byte-null`;
|
|
24
|
+
if (WHITESPACE_BYTES.has(byte)) return `byte-whitespace`;
|
|
25
|
+
if (isControlByte(byte)) return `byte-control`;
|
|
26
|
+
if (isPrintableAscii(byte)) return `byte-printable`;
|
|
27
|
+
return `byte-other`;
|
|
28
|
+
}
|
|
29
|
+
function createShadeMap(nullColour, maxColour, stepStart, stepEnd) {
|
|
30
30
|
const cssSteps = colour_exports.createSteps(stepStart, stepEnd, { steps: 16 }).map(colour_exports.toCssColour);
|
|
31
31
|
return { forByte: (byte) => {
|
|
32
32
|
if (byte === 0) return nullColour;
|
|
33
33
|
if (byte === 255) return maxColour;
|
|
34
34
|
return cssSteps[byte >> 4];
|
|
35
35
|
} };
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/hex/data.ts
|
|
39
|
-
|
|
39
|
+
function createHexStore(data) {
|
|
40
40
|
return {
|
|
41
41
|
data: new Uint8Array(data),
|
|
42
42
|
changeset: /* @__PURE__ */ new Set()
|
|
43
43
|
};
|
|
44
|
-
}
|
|
45
|
-
|
|
44
|
+
}
|
|
45
|
+
function readByte(store, pos) {
|
|
46
46
|
return store.data[pos] ?? 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
47
|
+
}
|
|
48
|
+
function length(store) {
|
|
49
49
|
return store.data.length;
|
|
50
|
-
}
|
|
51
|
-
|
|
50
|
+
}
|
|
51
|
+
function clamp(value) {
|
|
52
52
|
return Math.max(0, Math.min(255, value));
|
|
53
|
-
}
|
|
54
|
-
|
|
53
|
+
}
|
|
54
|
+
function writeByte(store, pos, value) {
|
|
55
55
|
const clampedValue = clamp(value);
|
|
56
56
|
const before = store.data[pos];
|
|
57
57
|
const diff = new Map([[pos, {
|
|
@@ -61,8 +61,8 @@ const writeByte = (store, pos, value) => {
|
|
|
61
61
|
store.data[pos] = clampedValue;
|
|
62
62
|
store.changeset.add(pos);
|
|
63
63
|
return diff;
|
|
64
|
-
}
|
|
65
|
-
|
|
64
|
+
}
|
|
65
|
+
function writeBytes(store, entries) {
|
|
66
66
|
const diff = /* @__PURE__ */ new Map();
|
|
67
67
|
entries.forEach((value, pos) => {
|
|
68
68
|
const clampedValue = clamp(value);
|
|
@@ -75,8 +75,8 @@ const writeBytes = (store, entries) => {
|
|
|
75
75
|
store.changeset.add(pos);
|
|
76
76
|
});
|
|
77
77
|
return diff;
|
|
78
|
-
}
|
|
79
|
-
|
|
78
|
+
}
|
|
79
|
+
function applyDiff(store, diff) {
|
|
80
80
|
const reverse = /* @__PURE__ */ new Map();
|
|
81
81
|
diff.forEach((entry, pos) => {
|
|
82
82
|
const before = store.data[pos];
|
|
@@ -88,8 +88,8 @@ const applyDiff = (store, diff) => {
|
|
|
88
88
|
store.changeset.add(pos);
|
|
89
89
|
});
|
|
90
90
|
return reverse;
|
|
91
|
-
}
|
|
92
|
-
|
|
91
|
+
}
|
|
92
|
+
function reverseDiff(diff) {
|
|
93
93
|
const reversed = /* @__PURE__ */ new Map();
|
|
94
94
|
diff.forEach((entry, pos) => {
|
|
95
95
|
reversed.set(pos, {
|
|
@@ -98,52 +98,52 @@ const reverseDiff = (diff) => {
|
|
|
98
98
|
});
|
|
99
99
|
});
|
|
100
100
|
return reversed;
|
|
101
|
-
}
|
|
102
|
-
|
|
101
|
+
}
|
|
102
|
+
function getChangeset(store) {
|
|
103
103
|
return store.changeset;
|
|
104
|
-
}
|
|
104
|
+
}
|
|
105
105
|
//#endregion
|
|
106
106
|
//#region src/hex/diff.ts
|
|
107
|
-
|
|
107
|
+
function createUndoRedoStack() {
|
|
108
108
|
return {
|
|
109
109
|
undos: [],
|
|
110
110
|
redos: []
|
|
111
111
|
};
|
|
112
|
-
}
|
|
113
|
-
|
|
112
|
+
}
|
|
113
|
+
function push(stack, diff) {
|
|
114
114
|
stack.undos.push(diff);
|
|
115
115
|
stack.redos = [];
|
|
116
|
-
}
|
|
117
|
-
|
|
116
|
+
}
|
|
117
|
+
function undo(stack) {
|
|
118
118
|
const diff = stack.undos.pop();
|
|
119
119
|
if (diff) stack.redos.push(diff);
|
|
120
120
|
return diff;
|
|
121
|
-
}
|
|
122
|
-
|
|
121
|
+
}
|
|
122
|
+
function redo(stack) {
|
|
123
123
|
const diff = stack.redos.pop();
|
|
124
124
|
if (diff) stack.undos.push(diff);
|
|
125
125
|
return diff;
|
|
126
|
-
}
|
|
126
|
+
}
|
|
127
127
|
//#endregion
|
|
128
128
|
//#region src/hex/selection.ts
|
|
129
129
|
const bytesPerRow = (columns) => columns * 4;
|
|
130
130
|
const min = (a, b) => a < b ? a : b;
|
|
131
131
|
const max = (a, b) => a > b ? a : b;
|
|
132
|
-
|
|
132
|
+
function clampPos(pos, dataLength) {
|
|
133
133
|
return Math.max(0, Math.min(pos, dataLength - 1));
|
|
134
|
-
}
|
|
135
|
-
|
|
134
|
+
}
|
|
135
|
+
function getSelectedPositions(sel, columns) {
|
|
136
136
|
if (!sel) return [];
|
|
137
137
|
const bpr = bytesPerRow(columns);
|
|
138
|
-
if (sel.kind ===
|
|
139
|
-
if (sel.kind ===
|
|
138
|
+
if (sel.kind === `single`) return [sel.pos];
|
|
139
|
+
if (sel.kind === `contiguous`) {
|
|
140
140
|
const start = min(sel.start, sel.end);
|
|
141
141
|
const end = max(sel.start, sel.end);
|
|
142
142
|
const positions = [];
|
|
143
143
|
for (let i = start; i <= end; i++) positions.push(i);
|
|
144
144
|
return positions;
|
|
145
145
|
}
|
|
146
|
-
if (sel.kind ===
|
|
146
|
+
if (sel.kind === `rectangular`) {
|
|
147
147
|
const positions = [];
|
|
148
148
|
for (let row = 0; row < sel.height; row++) for (let col = 0; col < sel.width; col++) {
|
|
149
149
|
const y = sel.y + row;
|
|
@@ -154,17 +154,17 @@ const getSelectedPositions = (sel, columns) => {
|
|
|
154
154
|
return positions;
|
|
155
155
|
}
|
|
156
156
|
return [];
|
|
157
|
-
}
|
|
158
|
-
|
|
157
|
+
}
|
|
158
|
+
function selectionContains(sel, pos, columns) {
|
|
159
159
|
if (!sel) return false;
|
|
160
160
|
const bpr = bytesPerRow(columns);
|
|
161
|
-
if (sel.kind ===
|
|
162
|
-
if (sel.kind ===
|
|
161
|
+
if (sel.kind === `single`) return pos === sel.pos;
|
|
162
|
+
if (sel.kind === `contiguous`) {
|
|
163
163
|
const start = min(sel.start, sel.end);
|
|
164
164
|
const end = max(sel.start, sel.end);
|
|
165
165
|
return pos >= start && pos <= end;
|
|
166
166
|
}
|
|
167
|
-
if (sel.kind ===
|
|
167
|
+
if (sel.kind === `rectangular`) {
|
|
168
168
|
const row = Math.floor(pos / bpr);
|
|
169
169
|
const col = pos % bpr;
|
|
170
170
|
const x = sel.x;
|
|
@@ -174,59 +174,59 @@ const selectionContains = (sel, pos, columns) => {
|
|
|
174
174
|
return row >= y && row < y + height && col >= x && col < x + width;
|
|
175
175
|
}
|
|
176
176
|
return false;
|
|
177
|
-
}
|
|
178
|
-
|
|
177
|
+
}
|
|
178
|
+
function getCursorPos(sel, dir, columns, dataLength) {
|
|
179
179
|
let currentPos;
|
|
180
180
|
if (!sel) currentPos = 0;
|
|
181
|
-
else if (sel.kind ===
|
|
182
|
-
else if (sel.kind ===
|
|
183
|
-
else if (sel.kind ===
|
|
181
|
+
else if (sel.kind === `single`) currentPos = sel.pos;
|
|
182
|
+
else if (sel.kind === `contiguous`) currentPos = max(sel.start, sel.end);
|
|
183
|
+
else if (sel.kind === `rectangular`) currentPos = sel.y * bytesPerRow(columns) + sel.x + sel.width - 1;
|
|
184
184
|
else currentPos = 0;
|
|
185
185
|
const bpr = bytesPerRow(columns);
|
|
186
186
|
let newPos;
|
|
187
187
|
switch (dir) {
|
|
188
|
-
case
|
|
188
|
+
case `left`:
|
|
189
189
|
newPos = currentPos - 1;
|
|
190
190
|
break;
|
|
191
|
-
case
|
|
191
|
+
case `right`:
|
|
192
192
|
newPos = currentPos + 1;
|
|
193
193
|
break;
|
|
194
|
-
case
|
|
194
|
+
case `up`:
|
|
195
195
|
newPos = currentPos - bpr;
|
|
196
196
|
break;
|
|
197
|
-
case
|
|
197
|
+
case `down`:
|
|
198
198
|
newPos = currentPos + bpr;
|
|
199
199
|
break;
|
|
200
200
|
default: newPos = currentPos;
|
|
201
201
|
}
|
|
202
202
|
return clampPos(newPos, dataLength);
|
|
203
|
-
}
|
|
204
|
-
|
|
203
|
+
}
|
|
204
|
+
function moveSelection(sel, dir, columns, dataLength) {
|
|
205
205
|
return {
|
|
206
|
-
kind:
|
|
206
|
+
kind: `single`,
|
|
207
207
|
pos: getCursorPos(sel, dir, columns, dataLength)
|
|
208
208
|
};
|
|
209
|
-
}
|
|
210
|
-
|
|
209
|
+
}
|
|
210
|
+
function extendRectangular(sel, dir, columns, _dataLength, anchorX = 0, anchorY = 0) {
|
|
211
211
|
const bpr = bytesPerRow(columns);
|
|
212
212
|
let x;
|
|
213
213
|
let y;
|
|
214
214
|
let width;
|
|
215
215
|
let height;
|
|
216
|
-
if (!sel || sel.kind ===
|
|
217
|
-
const pos = sel?.kind ===
|
|
216
|
+
if (!sel || sel.kind === `single`) {
|
|
217
|
+
const pos = sel?.kind === `single` ? sel.pos : 0;
|
|
218
218
|
x = pos % bpr;
|
|
219
219
|
y = Math.floor(pos / bpr);
|
|
220
220
|
width = 1;
|
|
221
221
|
height = 1;
|
|
222
|
-
} else if (sel.kind ===
|
|
222
|
+
} else if (sel.kind === `contiguous`) {
|
|
223
223
|
const start = min(sel.start, sel.end);
|
|
224
224
|
const end = max(sel.start, sel.end);
|
|
225
225
|
x = start % bpr;
|
|
226
226
|
y = Math.floor(start / bpr);
|
|
227
227
|
width = end - start + 1;
|
|
228
228
|
height = 1;
|
|
229
|
-
} else if (sel.kind ===
|
|
229
|
+
} else if (sel.kind === `rectangular`) {
|
|
230
230
|
x = sel.x;
|
|
231
231
|
y = sel.y;
|
|
232
232
|
width = sel.width;
|
|
@@ -237,10 +237,10 @@ const extendRectangular = (sel, dir, columns, _dataLength, anchorX = 0, anchorY
|
|
|
237
237
|
width = 1;
|
|
238
238
|
height = 1;
|
|
239
239
|
}
|
|
240
|
-
const effectiveAnchorX = anchorX > 0 || sel?.kind ===
|
|
241
|
-
const effectiveAnchorY = anchorY > 0 || sel?.kind ===
|
|
240
|
+
const effectiveAnchorX = anchorX > 0 || sel?.kind === `rectangular` ? anchorX : x;
|
|
241
|
+
const effectiveAnchorY = anchorY > 0 || sel?.kind === `rectangular` ? anchorY : y;
|
|
242
242
|
switch (dir) {
|
|
243
|
-
case
|
|
243
|
+
case `left`:
|
|
244
244
|
if (x > effectiveAnchorX) width -= 1;
|
|
245
245
|
else if (x === effectiveAnchorX && width > 1) {
|
|
246
246
|
x -= 1;
|
|
@@ -250,10 +250,10 @@ const extendRectangular = (sel, dir, columns, _dataLength, anchorX = 0, anchorY
|
|
|
250
250
|
width += 1;
|
|
251
251
|
}
|
|
252
252
|
break;
|
|
253
|
-
case
|
|
253
|
+
case `right`:
|
|
254
254
|
if (x + width < bpr) width += 1;
|
|
255
255
|
break;
|
|
256
|
-
case
|
|
256
|
+
case `up`:
|
|
257
257
|
if (y > effectiveAnchorY) height -= 1;
|
|
258
258
|
else if (y === effectiveAnchorY && height > 1) {
|
|
259
259
|
y -= 1;
|
|
@@ -263,22 +263,22 @@ const extendRectangular = (sel, dir, columns, _dataLength, anchorX = 0, anchorY
|
|
|
263
263
|
height += 1;
|
|
264
264
|
}
|
|
265
265
|
break;
|
|
266
|
-
case
|
|
266
|
+
case `down`:
|
|
267
267
|
height += 1;
|
|
268
268
|
break;
|
|
269
269
|
}
|
|
270
270
|
return {
|
|
271
|
-
kind:
|
|
271
|
+
kind: `rectangular`,
|
|
272
272
|
x,
|
|
273
273
|
y,
|
|
274
274
|
width,
|
|
275
275
|
height
|
|
276
276
|
};
|
|
277
|
-
}
|
|
278
|
-
|
|
277
|
+
}
|
|
278
|
+
function selectionFromPointerRange(start, end, mode, columns) {
|
|
279
279
|
const bpr = bytesPerRow(columns);
|
|
280
|
-
if (mode ===
|
|
281
|
-
kind:
|
|
280
|
+
if (mode === `contiguous`) return {
|
|
281
|
+
kind: `contiguous`,
|
|
282
282
|
start: min(start, end),
|
|
283
283
|
end: max(start, end)
|
|
284
284
|
};
|
|
@@ -287,13 +287,13 @@ const selectionFromPointerRange = (start, end, mode, columns) => {
|
|
|
287
287
|
const endX = end % bpr;
|
|
288
288
|
const endY = Math.floor(end / bpr);
|
|
289
289
|
return {
|
|
290
|
-
kind:
|
|
290
|
+
kind: `rectangular`,
|
|
291
291
|
x: min(startX, endX),
|
|
292
292
|
y: min(startY, endY),
|
|
293
293
|
width: Math.abs(endX - startX) + 1,
|
|
294
294
|
height: Math.abs(endY - startY) + 1
|
|
295
295
|
};
|
|
296
|
-
}
|
|
296
|
+
}
|
|
297
297
|
//#endregion
|
|
298
298
|
//#region src/hex/hex-editor.ts
|
|
299
299
|
let IxfxHexEditorElement = class IxfxHexEditorElement extends LitElement {
|
|
@@ -1144,4 +1144,4 @@ IxfxHexEditorElement = __decorate([safeCustomElement(`ixfx-hex-editor`)], IxfxHe
|
|
|
1144
1144
|
//#endregion
|
|
1145
1145
|
export { IxfxHexEditorElement as t };
|
|
1146
1146
|
|
|
1147
|
-
//# sourceMappingURL=hex-editor-
|
|
1147
|
+
//# sourceMappingURL=hex-editor-CsN_ySkH.js.map
|