@ixfx/components 0.4.3 → 0.4.4
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 +395 -1176
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +7699 -20648
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +12 -7
- package/dist/ac-text.d.ts.map +1 -1
- package/dist/ac-text.js +2 -3
- package/dist/ac-text.js.map +1 -1
- package/dist/{button-C3fLMKUv.js → button-DxYee1ZH.js} +2 -2
- package/dist/{button-C3fLMKUv.js.map → button-DxYee1ZH.js.map} +1 -1
- package/dist/button.d.ts +1 -2
- package/dist/button.d.ts.map +1 -1
- package/dist/button.js +1 -2
- package/dist/checkbox.d.ts +0 -1
- package/dist/checkbox.d.ts.map +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/{colour-picker-0sgAha1T.js → colour-picker-BacNRabo.js} +14 -16
- package/dist/colour-picker-BacNRabo.js.map +1 -0
- package/dist/colour-picker.d.ts +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +5 -2
- package/dist/crumbs.d.ts.map +1 -1
- package/dist/crumbs.js +45 -20
- package/dist/crumbs.js.map +1 -1
- package/dist/data-display.d.ts +1 -2
- package/dist/data-display.d.ts.map +1 -1
- package/dist/data-display.js +25 -23
- package/dist/data-display.js.map +1 -1
- package/dist/{data-provider-DgI909FP.js → data-provider-35TyWclX.js} +2 -2
- package/dist/data-provider-35TyWclX.js.map +1 -0
- package/dist/{decorate-DdjvVHS-.js → decorate-VRK8rslU.js} +2 -2
- package/dist/{decorate-DdjvVHS-.js.map → decorate-VRK8rslU.js.map} +1 -1
- package/dist/editable-label.d.ts +1 -2
- package/dist/editable-label.d.ts.map +1 -1
- package/dist/editable-label.js +1 -1
- package/dist/editable-label.js.map +1 -1
- package/dist/{hex-editor-WZrjRtvL.js → hex-editor-Bk6rxhfg.js} +9 -11
- package/dist/hex-editor-Bk6rxhfg.js.map +1 -0
- package/dist/{hex-editor-CMIxtNgT.d.ts → hex-editor-Caq8vNQk.d.ts} +2 -3
- package/dist/hex-editor-Caq8vNQk.d.ts.map +1 -0
- package/dist/hex.d.ts +1 -1
- package/dist/hex.js +1 -1
- package/dist/highlight-B-eQrhhb.js.map +1 -1
- package/dist/{icon-Ndo40kNO.js → icon-B22XVlCt.js} +6 -4
- package/dist/{icon-Ndo40kNO.js.map → icon-B22XVlCt.js.map} +1 -1
- package/dist/{icon-Bd5BiU4b.d.ts → icon-DpA9x2Ve.d.ts} +2 -3
- package/dist/icon-DpA9x2Ve.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/icons.js +1 -1
- package/dist/{incr-search-CeERfijK.js → incr-search-2pz21xtR.js} +9 -6
- package/dist/incr-search-2pz21xtR.js.map +1 -0
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +1 -1
- package/dist/{index-CowKi2mo.d.ts → index-BeuCXtiO.d.ts} +3 -4
- package/dist/index-BeuCXtiO.d.ts.map +1 -0
- package/dist/{index-D87kRcEs.d.ts → index-BtGFYfaK.d.ts} +2 -1
- package/dist/index-BtGFYfaK.d.ts.map +1 -0
- package/dist/{index-s_IhSnwc.d.ts → index-CoqtMSd9.d.ts} +6 -4
- package/dist/index-CoqtMSd9.d.ts.map +1 -0
- package/dist/{index-9fGVAg1d.d.ts → index-Cxwxtj6g.d.ts} +3 -3
- package/dist/index-Cxwxtj6g.d.ts.map +1 -0
- package/dist/index-D_ftz_IT.d.ts +184 -0
- package/dist/index-D_ftz_IT.d.ts.map +1 -0
- package/dist/{index-_RTQSKHi.d.ts → index-DfEkTGvT.d.ts} +11 -11
- package/dist/index-DfEkTGvT.d.ts.map +1 -0
- package/dist/index.d.ts +44 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +304 -3075
- package/dist/index.js.map +1 -1
- package/dist/keyboard-B5xD7Fz-.js +36 -0
- package/dist/keyboard-B5xD7Fz-.js.map +1 -0
- package/dist/{labelled-input-base-ORb1rGq6.d.ts → labelled-input-base-DiTme1JO.d.ts} +1 -2
- package/dist/labelled-input-base-DiTme1JO.d.ts.map +1 -0
- package/dist/{labelled-input-base-9K_w3oLj.js → labelled-input-base-hoKGwyKT.js} +2 -2
- package/dist/{labelled-input-base-9K_w3oLj.js.map → labelled-input-base-hoKGwyKT.js.map} +1 -1
- package/dist/labelled-radial-input.d.ts +5 -4
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-radial-input.js +7 -3
- package/dist/labelled-radial-input.js.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-range-input.js +27 -3
- package/dist/labelled-range-input.js.map +1 -1
- package/dist/led.d.ts +1 -2
- package/dist/led.d.ts.map +1 -1
- package/dist/led.js +1 -1
- package/dist/led.js.map +1 -1
- package/dist/{menu-vjoiHZ13.js → menu-g6yd7ddN.js} +8 -9
- package/dist/menu-g6yd7ddN.js.map +1 -0
- package/dist/{menu-item-COx-Azgj.d.ts → menu-item-DSyf9f_L.d.ts} +4 -4
- package/dist/menu-item-DSyf9f_L.d.ts.map +1 -0
- package/dist/{menu-item-BrIuORYD.js → menu-item-NUKwJ4s5.js} +3 -4
- package/dist/{menu-item-BrIuORYD.js.map → menu-item-NUKwJ4s5.js.map} +1 -1
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +8 -5
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +22 -24
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.d.ts +7 -3
- package/dist/narrowed-text.d.ts.map +1 -1
- package/dist/narrowed-text.js +73 -47
- package/dist/narrowed-text.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/panel.d.ts.map +1 -1
- package/dist/panel.js +2 -2
- package/dist/panel.js.map +1 -1
- package/dist/plots.d.ts +2 -2
- package/dist/plots.js +1 -1
- package/dist/polar-pad.d.ts +15 -3
- package/dist/polar-pad.d.ts.map +1 -1
- package/dist/polar-pad.js +64 -11
- package/dist/polar-pad.js.map +1 -1
- package/dist/{radial-input-CpQPs1Mp.d.ts → radial-input-DXMN55Nz.d.ts} +6 -4
- package/dist/radial-input-DXMN55Nz.d.ts.map +1 -0
- package/dist/{radial-input-DZ7eQCcM.js → radial-input-DxCrt_NE.js} +41 -19
- package/dist/radial-input-DxCrt_NE.js.map +1 -0
- package/dist/radial-input.d.ts +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.d.ts +15 -4
- package/dist/range-input.d.ts.map +1 -1
- package/dist/range-input.js +23 -2
- package/dist/range-input.js.map +1 -1
- package/dist/range.d.ts +15 -4
- package/dist/range.d.ts.map +1 -1
- package/dist/range.js +23 -2
- package/dist/range.js.map +1 -1
- package/dist/selecthorizontal.d.ts +1 -2
- package/dist/selecthorizontal.d.ts.map +1 -1
- package/dist/selecthorizontal.js +1 -1
- package/dist/selecthorizontal.js.map +1 -1
- package/dist/slider-input-DFpG23bS.js +1592 -0
- package/dist/slider-input-DFpG23bS.js.map +1 -0
- package/dist/slider-input-XppH3vcy.d.ts +160 -0
- package/dist/slider-input-XppH3vcy.d.ts.map +1 -0
- package/dist/slider-input.d.ts +2 -0
- package/dist/slider-input.js +2 -0
- package/dist/snap-container.d.ts +1 -2
- package/dist/snap-container.d.ts.map +1 -1
- package/dist/snap-container.js +6 -5
- package/dist/snap-container.js.map +1 -1
- package/dist/split-layout.d.ts +1 -2
- package/dist/split-layout.d.ts.map +1 -1
- package/dist/split-layout.js +6 -4
- package/dist/split-layout.js.map +1 -1
- package/dist/swipe.d.ts +12 -2
- package/dist/swipe.d.ts.map +1 -1
- package/dist/swipe.js +22 -3
- package/dist/swipe.js.map +1 -1
- package/dist/{tab-list-DLzb-m-I.d.ts → tab-list-BohmbvqF.d.ts} +14 -5
- package/dist/tab-list-BohmbvqF.d.ts.map +1 -0
- package/dist/tab-list-DzknpdSo.js +592 -0
- package/dist/tab-list-DzknpdSo.js.map +1 -0
- package/dist/tabs.d.ts +2 -2
- package/dist/tabs.js +1 -208
- package/dist/{tickled-controller-BjYCzGrU.d.ts → tickled-controller-BF2Ea0DE.d.ts} +2 -31
- package/dist/tickled-controller-BF2Ea0DE.d.ts.map +1 -0
- package/dist/tickled-styles-fNDdqf6l.js.map +1 -1
- package/dist/{timeline-2OFtN4Ta.js → timeline-B2fgDL4U.js} +37 -1438
- package/dist/timeline-B2fgDL4U.js.map +1 -0
- package/dist/timeline.d.ts +1 -1
- package/dist/timeline.js +1 -1
- package/dist/{tooltip-RGVIwHrZ.d.ts → tooltip-BlvBUQxx.d.ts} +3 -3
- package/dist/tooltip-BlvBUQxx.d.ts.map +1 -0
- package/dist/{tree-D84RUgFC.js → tree-BnvzhsAw.js} +8 -9
- package/dist/tree-BnvzhsAw.js.map +1 -0
- package/dist/{tree-component-BaCSPWg1.d.ts → tree-component-DCmmKZ4j.d.ts} +8 -124
- package/dist/tree-component-DCmmKZ4j.d.ts.map +1 -0
- package/dist/tree.d.ts +10 -4
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/types-DO3gt5vg.d.ts +130 -0
- package/dist/types-DO3gt5vg.d.ts.map +1 -0
- package/dist/wheel-nudge-BlSCe_hD.js +86 -0
- package/dist/wheel-nudge-BlSCe_hD.js.map +1 -0
- package/dist/wheel-nudge-DGrNzWuE.d.ts +29 -0
- package/dist/wheel-nudge-DGrNzWuE.d.ts.map +1 -0
- package/dist/{xy-axis-BeWRMmbo.d.ts → xy-axis-5KhVTNoX.d.ts} +30 -7
- package/dist/xy-axis-5KhVTNoX.d.ts.map +1 -0
- package/dist/xy-axis-CxHC8z5E.js +1849 -0
- package/dist/xy-axis-CxHC8z5E.js.map +1 -0
- package/dist/xy-pad.d.ts +13 -2
- package/dist/xy-pad.d.ts.map +1 -1
- package/dist/xy-pad.js +47 -6
- package/dist/xy-pad.js.map +1 -1
- package/docs-user/radial-input.md +2 -2
- package/package.json +21 -20
- package/dist/colour-C3MQIjFJ-vRCdr8W-.js +0 -3732
- package/dist/colour-C3MQIjFJ-vRCdr8W-.js.map +0 -1
- package/dist/colour-picker-0sgAha1T.js.map +0 -1
- package/dist/data-provider-DgI909FP.js.map +0 -1
- package/dist/dist-CA13FvMn.js +0 -980
- package/dist/dist-CA13FvMn.js.map +0 -1
- package/dist/hex-editor-CMIxtNgT.d.ts.map +0 -1
- package/dist/hex-editor-WZrjRtvL.js.map +0 -1
- package/dist/icon-Bd5BiU4b.d.ts.map +0 -1
- package/dist/incr-search-CeERfijK.js.map +0 -1
- package/dist/index-9fGVAg1d.d.ts.map +0 -1
- package/dist/index-CowKi2mo.d.ts.map +0 -1
- package/dist/index-D87kRcEs.d.ts.map +0 -1
- package/dist/index-DgXpCg_G.d.ts +0 -1244
- package/dist/index-DgXpCg_G.d.ts.map +0 -1
- package/dist/index-_RTQSKHi.d.ts.map +0 -1
- package/dist/index-s_IhSnwc.d.ts.map +0 -1
- package/dist/keyboard-CimiEskD.js +0 -20
- package/dist/keyboard-CimiEskD.js.map +0 -1
- package/dist/labelled-input-base-ORb1rGq6.d.ts.map +0 -1
- package/dist/menu-item-COx-Azgj.d.ts.map +0 -1
- package/dist/menu-vjoiHZ13.js.map +0 -1
- package/dist/radial-input-CpQPs1Mp.d.ts.map +0 -1
- package/dist/radial-input-DZ7eQCcM.js.map +0 -1
- package/dist/tab-list-DLzb-m-I.d.ts.map +0 -1
- package/dist/tabs.js.map +0 -1
- package/dist/tickled-controller-BjYCzGrU.d.ts.map +0 -1
- package/dist/timeline-2OFtN4Ta.js.map +0 -1
- package/dist/tooltip-RGVIwHrZ.d.ts.map +0 -1
- package/dist/tree-D84RUgFC.js.map +0 -1
- package/dist/tree-component-BaCSPWg1.d.ts.map +0 -1
- package/dist/types-DSfbtHs3.d.ts +0 -8
- package/dist/types-DSfbtHs3.d.ts.map +0 -1
- package/dist/xy-axis-BeWRMmbo.d.ts.map +0 -1
- package/dist/xy-axis-no0OL_O1.js +0 -7893
- package/dist/xy-axis-no0OL_O1.js.map +0 -1
- /package/bundle/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
- /package/dist/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
package/dist/tabs.js
CHANGED
|
@@ -1,209 +1,2 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { n as safeCustomElement, t as __decorate } from "./decorate-DdjvVHS-.js";
|
|
3
|
-
import { LitElement, css, html } from "lit";
|
|
4
|
-
import { property } from "lit/decorators.js";
|
|
5
|
-
//#region src/tabs/tab-list.ts
|
|
6
|
-
let TabListElement = class TabListElement extends LitElement {
|
|
7
|
-
constructor(..._args) {
|
|
8
|
-
super(..._args);
|
|
9
|
-
this.orientation = `horizontal`;
|
|
10
|
-
this.flip = false;
|
|
11
|
-
this.scrollable = false;
|
|
12
|
-
this.#items = [];
|
|
13
|
-
this.#onSlotChange = () => {
|
|
14
|
-
this.updateComplete.then(() => {
|
|
15
|
-
this.#items = (this.shadowRoot?.querySelector(`slot`))?.assignedElements({ flatten: true }) ?? [];
|
|
16
|
-
this.#syncIndicatorColors();
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
this.#onKeyUp = (event) => {
|
|
20
|
-
const key = event.key;
|
|
21
|
-
if (this.#isVertical) {
|
|
22
|
-
if (key === `ArrowUp`) this.#selectPrevious();
|
|
23
|
-
else if (key === `ArrowDown`) this.#selectNext();
|
|
24
|
-
} else if (key === `ArrowRight`) this.#selectNext();
|
|
25
|
-
else if (key === `ArrowLeft`) this.#selectPrevious();
|
|
26
|
-
};
|
|
27
|
-
this.#onSlotClick = (event) => {
|
|
28
|
-
this.focus();
|
|
29
|
-
const t = event.target.closest(`ixfx-tab-list-item`);
|
|
30
|
-
if (!t) return;
|
|
31
|
-
const previous = this.getSelectedElement();
|
|
32
|
-
this.selectElement(t);
|
|
33
|
-
const forId = t.getAttribute(`for`);
|
|
34
|
-
const previousId = previous?.id;
|
|
35
|
-
this.dispatchEvent(new CustomEvent(`change`, {
|
|
36
|
-
bubbles: true,
|
|
37
|
-
detail: {
|
|
38
|
-
previous: previousId,
|
|
39
|
-
selected: t.id,
|
|
40
|
-
for: forId ?? ``
|
|
41
|
-
}
|
|
42
|
-
}));
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
#items;
|
|
46
|
-
get #isVertical() {
|
|
47
|
-
return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;
|
|
48
|
-
}
|
|
49
|
-
get #containerClass() {
|
|
50
|
-
return this.scrollable ? `${this.orientation} scrollable` : this.orientation;
|
|
51
|
-
}
|
|
52
|
-
render() {
|
|
53
|
-
return html`
|
|
54
|
-
<div
|
|
55
|
-
tabindex=0
|
|
56
|
-
@keyup=${this.#onKeyUp}
|
|
57
|
-
@click=${this.#onSlotClick}
|
|
58
|
-
id="container"
|
|
59
|
-
class=${this.#containerClass}
|
|
60
|
-
>
|
|
61
|
-
<slot @slotchange=${this.#onSlotChange}></slot>
|
|
62
|
-
</div>`;
|
|
63
|
-
}
|
|
64
|
-
#onSlotChange;
|
|
65
|
-
firstUpdated() {
|
|
66
|
-
this.updateComplete.then(() => {
|
|
67
|
-
if (this.#items.length > 0) this.#syncIndicatorColors();
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
updated(changedProperties) {
|
|
71
|
-
super.updated(changedProperties);
|
|
72
|
-
this.classList.toggle(`scrollable`, this.scrollable);
|
|
73
|
-
}
|
|
74
|
-
#syncIndicatorColors() {
|
|
75
|
-
for (const item of this.#items) {
|
|
76
|
-
item.style.setProperty(`--indicator-color-bottom`, `transparent`);
|
|
77
|
-
item.style.setProperty(`--indicator-color-top`, `transparent`);
|
|
78
|
-
item.style.setProperty(`--indicator-color-left`, `transparent`);
|
|
79
|
-
item.style.setProperty(`--indicator-color-right`, `transparent`);
|
|
80
|
-
if (item.hasAttribute(`selected`)) {
|
|
81
|
-
if (this.orientation === `horizontal` && !this.flip) item.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);
|
|
82
|
-
else if (this.orientation === `horizontal` && this.flip) item.style.setProperty(`--indicator-color-top`, `var(--accent)`);
|
|
83
|
-
else if (this.#isVertical && !this.flip) item.style.setProperty(`--indicator-color-right`, `var(--accent)`);
|
|
84
|
-
else if (this.#isVertical && this.flip) item.style.setProperty(`--indicator-color-left`, `var(--accent)`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
#onKeyUp;
|
|
89
|
-
getSelectedElement() {
|
|
90
|
-
for (const el of this.#items) if (this.#isSelected(el)) return el;
|
|
91
|
-
const slot = this.shadowRoot?.querySelector(`slot`);
|
|
92
|
-
if (slot) {
|
|
93
|
-
const els = slot.assignedElements({ flatten: true });
|
|
94
|
-
for (const el of els) if (this.#isSelected(el)) return el;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
#isSelected(el) {
|
|
98
|
-
if (el.getAttribute(`selected`) === null) return false;
|
|
99
|
-
return el.hasAttribute(`selected`);
|
|
100
|
-
}
|
|
101
|
-
selectElement(el) {
|
|
102
|
-
const existing = this.getSelectedElement();
|
|
103
|
-
if (existing) {
|
|
104
|
-
existing.removeAttribute(`selected`);
|
|
105
|
-
existing.style.setProperty(`--indicator-color-bottom`, `transparent`);
|
|
106
|
-
existing.style.setProperty(`--indicator-color-top`, `transparent`);
|
|
107
|
-
existing.style.setProperty(`--indicator-color-left`, `transparent`);
|
|
108
|
-
existing.style.setProperty(`--indicator-color-right`, `transparent`);
|
|
109
|
-
}
|
|
110
|
-
el.setAttribute(`selected`, ``);
|
|
111
|
-
if (this.orientation === `horizontal` && !this.flip) el.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);
|
|
112
|
-
else if (this.orientation === `horizontal` && this.flip) el.style.setProperty(`--indicator-color-top`, `var(--accent)`);
|
|
113
|
-
else if (this.#isVertical && !this.flip) el.style.setProperty(`--indicator-color-right`, `var(--accent)`);
|
|
114
|
-
else if (this.#isVertical && this.flip) el.style.setProperty(`--indicator-color-left`, `var(--accent)`);
|
|
115
|
-
}
|
|
116
|
-
#selectNext() {
|
|
117
|
-
let found = false;
|
|
118
|
-
for (const el of this.#items) if (this.#isSelected(el) && !found) found = true;
|
|
119
|
-
else if (found) {
|
|
120
|
-
this.selectElement(el);
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
#selectPrevious() {
|
|
125
|
-
let prev;
|
|
126
|
-
for (const el of this.#items) if (this.#isSelected(el) && prev) this.selectElement(prev);
|
|
127
|
-
else prev = el;
|
|
128
|
-
}
|
|
129
|
-
#onSlotClick;
|
|
130
|
-
static {
|
|
131
|
-
this.styles = [themeFallbacks, css`
|
|
132
|
-
:host {
|
|
133
|
-
display: inline-block;
|
|
134
|
-
--activated-colour: var(--accent);
|
|
135
|
-
--colour: var(--surface-4);
|
|
136
|
-
--scroll-max-height: 200px;
|
|
137
|
-
--allow-overflow: hidden;
|
|
138
|
-
}
|
|
139
|
-
:host(.scrollable) {
|
|
140
|
-
max-height: var(--scroll-max-height);
|
|
141
|
-
}
|
|
142
|
-
text {
|
|
143
|
-
user-select:none;
|
|
144
|
-
}
|
|
145
|
-
#container {
|
|
146
|
-
display:flex;
|
|
147
|
-
}
|
|
148
|
-
#container.horizontal {
|
|
149
|
-
flex-direction: row;
|
|
150
|
-
overflow: hidden;
|
|
151
|
-
}
|
|
152
|
-
#container.horizontal.scrollable {
|
|
153
|
-
overflow-x: auto;
|
|
154
|
-
--allow-overflow: visible;
|
|
155
|
-
}
|
|
156
|
-
#container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {
|
|
157
|
-
flex-shrink: 0;
|
|
158
|
-
}
|
|
159
|
-
#container.vertical-stack {
|
|
160
|
-
flex-direction: column;
|
|
161
|
-
}
|
|
162
|
-
#container.vertical-stack.flip {
|
|
163
|
-
flex-direction: column-reverse;
|
|
164
|
-
}
|
|
165
|
-
#container.vertical-stack.scrollable {
|
|
166
|
-
overflow-y: auto;
|
|
167
|
-
max-height: var(--scroll-max-height);
|
|
168
|
-
--allow-overflow: visible;
|
|
169
|
-
}
|
|
170
|
-
#container.vertical-side {
|
|
171
|
-
flex-direction: column;
|
|
172
|
-
}
|
|
173
|
-
#container.vertical-side.flip {
|
|
174
|
-
flex-direction: column-reverse;
|
|
175
|
-
}
|
|
176
|
-
#container.vertical-side.scrollable {
|
|
177
|
-
overflow-y: auto;
|
|
178
|
-
max-height: var(--scroll-max-height);
|
|
179
|
-
--allow-overflow: visible;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
::slotted(ixfx-tab-list-item) {
|
|
183
|
-
flex: 1 1 auto;
|
|
184
|
-
min-width: 0;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
#container.vertical-side ::slotted(ixfx-tab-list-item) {
|
|
188
|
-
writing-mode: vertical-lr;
|
|
189
|
-
text-orientation: mixed;
|
|
190
|
-
}
|
|
191
|
-
#container.vertical-side.flip ::slotted(ixfx-tab-list-item) {
|
|
192
|
-
writing-mode: vertical-rl;
|
|
193
|
-
text-orientation: mixed;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
::slotted(.activated) {
|
|
197
|
-
--colour: var(--activated-colour);
|
|
198
|
-
}
|
|
199
|
-
`];
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
__decorate([property({ type: String })], TabListElement.prototype, "orientation", void 0);
|
|
203
|
-
__decorate([property({ type: Boolean })], TabListElement.prototype, "flip", void 0);
|
|
204
|
-
__decorate([property({ type: Boolean })], TabListElement.prototype, "scrollable", void 0);
|
|
205
|
-
TabListElement = __decorate([safeCustomElement(`ixfx-tab-list`)], TabListElement);
|
|
206
|
-
//#endregion
|
|
1
|
+
import { t as TabListElement } from "./tab-list-DzknpdSo.js";
|
|
207
2
|
export { TabListElement };
|
|
208
|
-
|
|
209
|
-
//# sourceMappingURL=tabs.js.map
|
|
@@ -1,33 +1,4 @@
|
|
|
1
1
|
import { ReactiveController, ReactiveControllerHost } from "lit";
|
|
2
|
-
|
|
3
|
-
//#region node_modules/.pnpm/@ixfx+collections@0.56.13/node_modules/@ixfx/collections/dist/index-rrpZOWbs.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Traversable Tree.
|
|
6
|
-
*
|
|
7
|
-
* Creatable from:
|
|
8
|
-
* {@link Trees.FromObject.asDynamicTraversable}: Create based on dynamic reading of an object
|
|
9
|
-
* {@link Trees.TraversableTree}: Create based on an {@link Trees.TreeNode}, a {@link Trees.TraversableTree} or an object (same as calling asDynamicTraversable).
|
|
10
|
-
* Use {@link Trees.isTraversable} to check if an object is this type.
|
|
11
|
-
*/
|
|
12
|
-
type TraversableTree<TValue> = {
|
|
13
|
-
/**
|
|
14
|
-
* Direct children of node
|
|
15
|
-
*/
|
|
16
|
-
children: () => IterableIterator<TraversableTree<TValue>>;
|
|
17
|
-
/**
|
|
18
|
-
* Direct parent of node
|
|
19
|
-
*/
|
|
20
|
-
getParent: () => TraversableTree<TValue> | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* Value of node
|
|
23
|
-
*/
|
|
24
|
-
getValue: () => TValue;
|
|
25
|
-
/**
|
|
26
|
-
* Object reference that acts as the identity of the node
|
|
27
|
-
*/
|
|
28
|
-
getIdentity: () => any;
|
|
29
|
-
};
|
|
30
|
-
//#endregion
|
|
31
2
|
//#region src/interaction/tickled-controller.d.ts
|
|
32
3
|
/**
|
|
33
4
|
* Represents an item that can be tickled (highlighted via hover or keyboard navigation)
|
|
@@ -214,5 +185,5 @@ declare class TickledController<T = number> implements ReactiveController {
|
|
|
214
185
|
setInputMode(mode: InputMode): void;
|
|
215
186
|
}
|
|
216
187
|
//#endregion
|
|
217
|
-
export {
|
|
218
|
-
//# sourceMappingURL=tickled-controller-
|
|
188
|
+
export { TickledController as t };
|
|
189
|
+
//# sourceMappingURL=tickled-controller-BF2Ea0DE.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickled-controller-BF2Ea0DE.d.ts","names":[],"sources":["../src/interaction/tickled-controller.ts"],"mappings":";;;;;KAKY,YAAY;;;;WAIb,IAAI;;;;WAKJ;;;;;KAMC;;;;KAKA,wBAAwB;;;;EAIlC,gBAAgB,cAAc,YAAY;;;;;;EAO1C,YAAY,IAAI;;;;;;;;;;;;;;;;;;;;;;;EAwBhB;;;;EAKA,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyDR,kBAAkB,uBAAuB;UAC5C;UACA;UACA;UACA;iBAEO;iBACA;iBACA;iBACA;EAEH,YAAA,MAAM,wBAAwB,QAAQ,wBAAwB;EAO1E;EASA;;;;MAOI,aAAa;;;;MAOb,aAAa;;;;EAOjB,UAAU,IAAI;;;;;;iBASC;;;;;aAiBJ;;;;;;EASX,mBAAmB,IAAI;;;;;;EAiCvB,mBAAmB,IAAI;;;;;;;EAYvB,yBAAyB,oDAAoD;;;;;EAyD7E,WAAW,IAAI;;;;;;EAmBf;;;;;EAmBA,aAAa,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tickled-styles-fNDdqf6l.js","names":[],"sources":["../src/interaction/tickled-controller.ts","../src/interaction/tickled-styles.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * Represents an item that can be tickled (highlighted via hover or keyboard navigation)\n */\nexport type TickledItem<T = unknown> = {\n /**\n * Unique identifier for the item (e.g., index, id, path)\n */\n readonly id: T;\n\n /**\n * Whether the item is currently enabled/interactive\n */\n readonly enabled?: boolean;\n};\n\n/**\n * Input mode determines which mechanism controls the tickled state\n */\nexport type InputMode = `keyboard` | `mouse`;\n\n/**\n * Configuration for TickledController\n */\nexport type TickledControllerConfig<T> = {\n /**\n * Function to retrieve all items that can be tickled\n */\n getItems: () => ReadonlyArray<TickledItem<T>>;\n\n /**\n * Optional callback when an item becomes tickled\n * Use this for side effects like opening submenus\n * @param id - The id of the newly tickled item, or undefined if nothing is tickled\n */\n onTickle?: (id: T | undefined) => void;\n\n /**\n * Optional callback fired after any state change (tickled id or input mode)\n * Use this to sync DOM attributes for slotted content that can't use reactive rendering\n *\n * For components that render items directly, this is usually not needed as\n * Lit's reactive rendering will handle updates automatically via requestUpdate()\n *\n * @example\n * ```ts\n * onStateChange: () => {\n * // Sync data-tickled attributes for slotted items\n * const items = this.getItems();\n * items.forEach((item, i) => {\n * if (this.tickled.isTickled(i)) {\n * item.setAttribute('data-tickled', '');\n * } else {\n * item.removeAttribute('data-tickled');\n * }\n * });\n * }\n * ```\n */\n onStateChange?: () => void;\n\n /**\n * Optional initial input mode (defaults to 'mouse')\n */\n initialInputMode?: InputMode;\n};\n\n/**\n * ReactiveController that manages \"tickled\" state for interactive lists.\n *\n * A \"tickled\" item is one that is under active attention via hover (mouse mode)\n * or keyboard focus (keyboard mode). Only one item can be tickled at a time.\n *\n * The input mode determines which mechanism controls tickled state:\n * - Mouse mode: hover controls tickled, keyboard navigation ignored\n * - Keyboard mode: keyboard navigation controls tickled, hover ignored\n *\n * Last interaction wins - any mouse hover switches to mouse mode, any keyboard\n * navigation switches to keyboard mode.\n *\n * ## Global Mouse Tracking\n *\n * This controller uses a singleton global `pointermove` listener to track actual\n * mouse movement. This prevents `pointerenter` events caused by content scrolling\n * from incorrectly switching to mouse mode when the user is actually using keyboard\n * navigation.\n *\n * @example\n * ```ts\n * class MyList extends LitElement {\n * private tickled = new TickledController(this, {\n * getItems: () => this.items.map((item, i) => ({ id: i, enabled: !item.disabled })),\n * onTickle: (id) => {\n * // Optional: perform side effect when item is tickled\n * console.log('Tickled item:', id);\n * }\n * });\n *\n * render() {\n * return html`\n * <ul @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}>\n * ${this.items.map((item, i) => html`\n * <li\n * class=\"item ${this.tickled.isTickled(i) ? 'tickled' : ''}\"\n * @pointerenter=${() => this.tickled.handlePointerEnter(i)}\n * >${item.label}</li>\n * `)}\n * </ul>\n * `;\n * }\n *\n * private handleKeyDown(e: KeyboardEvent) {\n * if (e.key === 'ArrowDown') {\n * this.tickled.handleKeyboardNavigation('next');\n * } else if (e.key === 'ArrowUp') {\n * this.tickled.handleKeyboardNavigation('previous');\n * }\n * }\n * }\n * ```\n */\nexport class TickledController<T = number> implements ReactiveController {\n private host: ReactiveControllerHost;\n private config: TickledControllerConfig<T>;\n private _tickledId: T | undefined = undefined;\n private _inputMode: InputMode;\n\n private static _lastMouseClientX: number = Number.NaN;\n private static _lastMouseClientY: number = Number.NaN;\n private static _mouseMovedSinceKeyboard: boolean = true;\n private static _globalListenerAttached: boolean = false;\n\n constructor(host: ReactiveControllerHost, config: TickledControllerConfig<T>) {\n this.host = host;\n this.config = config;\n this._inputMode = config.initialInputMode ?? `mouse`;\n host.addController(this);\n }\n\n hostConnected(): void {\n if (!TickledController._globalListenerAttached) {\n document.addEventListener(`pointermove`, (e: PointerEvent) => {\n TickledController.handleGlobalPointerMove(e.clientX, e.clientY);\n }, { passive: true });\n TickledController._globalListenerAttached = true;\n }\n }\n\n hostDisconnected(): void {\n // No-op: global listener persists for the lifetime of the page\n }\n\n /**\n * Get the current input mode\n */\n get inputMode(): InputMode {\n return this._inputMode;\n }\n\n /**\n * Get the currently tickled item id\n */\n get tickledId(): T | undefined {\n return this._tickledId;\n }\n\n /**\n * Check if a specific item is tickled\n */\n isTickled(id: T): boolean {\n return this._tickledId === id;\n }\n\n /**\n * Handle global pointer move event.\n * Called automatically by the global listener.\n * Tracks mouse movement to distinguish real hover from content scrolling.\n */\n private static handleGlobalPointerMove(clientX: number, clientY: number): void {\n if (!Number.isNaN(TickledController._lastMouseClientX)) {\n if (\n clientX !== TickledController._lastMouseClientX\n || clientY !== TickledController._lastMouseClientY\n ) {\n TickledController._mouseMovedSinceKeyboard = true;\n }\n }\n TickledController._lastMouseClientX = clientX;\n TickledController._lastMouseClientY = clientY;\n }\n\n /**\n * Check if actual mouse movement has occurred since last keyboard interaction.\n * Used to distinguish real hover/leave from content-scrolling-induced events.\n */\n static get hasMouseMovedSinceKeyboard(): boolean {\n return TickledController._mouseMovedSinceKeyboard;\n }\n\n /**\n * Handle pointer enter event on an item (mouse hover).\n * Only processes if actual mouse movement is detected (not content scrolling).\n * Switches to mouse mode and tickles the item.\n */\n handlePointerEnter(id: T): void {\n if (!TickledController._mouseMovedSinceKeyboard) {\n return;\n }\n\n const items = this.config.getItems();\n const item = items.find(item => item.id === id);\n if (item && item.enabled === false) {\n return;\n }\n\n const modeChanged = this._inputMode !== `mouse`;\n this._inputMode = `mouse`;\n\n const previousId = this._tickledId;\n this._tickledId = id;\n\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if ((previousId !== id || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Handle pointer leave event on an item.\n * Only clears tickled state if actual mouse movement is detected.\n * @param _e The pointer event (not used, but kept for API compatibility)\n */\n handlePointerLeave(_e: PointerEvent): void {\n if (TickledController._mouseMovedSinceKeyboard) {\n this.clearTickled();\n }\n }\n\n /**\n * Handle keyboard navigation.\n * Switches to keyboard mode and moves tickled state.\n *\n * @param direction - 'next', 'previous', 'first', 'last', or specific id\n */\n handleKeyboardNavigation(direction: `next` | `previous` | `first` | `last` | T): void {\n const modeChanged = this._inputMode !== `keyboard`;\n this._inputMode = `keyboard`;\n\n const items = this.config.getItems();\n const enabledItems = items.filter(item => item.enabled !== false);\n\n if (enabledItems.length === 0) {\n return;\n }\n\n let newId: T | undefined;\n\n if (direction === `first`) {\n newId = enabledItems[0].id;\n } else if (direction === `last`) {\n newId = enabledItems.at(-1)?.id;\n } else if (direction === `next` || direction === `previous`) {\n const currentIndex = enabledItems.findIndex(item => item.id === this._tickledId);\n\n if (currentIndex === -1) {\n newId = direction === `next` ? enabledItems[0].id : enabledItems.at(-1)?.id;\n } else {\n const delta = direction === `next` ? 1 : -1;\n const newIndex = currentIndex + delta;\n\n if (newIndex >= 0 && newIndex < enabledItems.length) {\n newId = enabledItems[newIndex].id;\n }\n // If newIndex is out of bounds, keep current tickled item\n }\n } else {\n const item = enabledItems.find(item => item.id === direction);\n if (item) {\n newId = item.id;\n }\n }\n\n if (newId !== undefined) {\n const previousId = this._tickledId;\n this._tickledId = newId;\n this.host.requestUpdate();\n\n if (previousId !== newId && this.config.onTickle) {\n this.config.onTickle(newId);\n }\n\n if ((previousId !== newId || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the tickled item (useful for programmatic control).\n * Does NOT change input mode.\n */\n setTickled(id: T | undefined): void {\n const previousId = this._tickledId;\n this._tickledId = id;\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if (previousId !== id && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Clear the tickled state (e.g., on pointer leave).\n * Note: For pointer leave events, prefer using handlePointerLeave() which\n * checks for actual mouse movement.\n */\n clearTickled(): void {\n if (this._tickledId !== undefined) {\n this._tickledId = undefined;\n this.host.requestUpdate();\n\n if (this.config.onTickle) {\n this.config.onTickle(undefined);\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the input mode.\n * When switching to keyboard mode, resets the mouse movement tracking.\n */\n setInputMode(mode: InputMode): void {\n if (this._inputMode !== mode) {\n this._inputMode = mode;\n this.host.requestUpdate();\n\n if (mode === `keyboard`) {\n TickledController._mouseMovedSinceKeyboard = false;\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n}\n","import { css } from 'lit';\n\n/**\n * Shared CSS styles for tickled interaction pattern.\n *\n * Tickled state is controlled via the `.tickled` CSS class (applied by TickledController).\n * The `tickledItemStyles` provides base styling that all tickled components should use.\n *\n * ## CSS Variable Contract\n *\n * **Style variables (default values defined in `tickledItemStyles`):**\n * - `--item-bg`: Default background (default: transparent)\n * - `--item-bg-tickled`: Background when tickled (default: rgba(0, 0, 0, 0.06))\n * - `--item-bg-selected`: Background when selected (default: rgba(25, 118, 210, 1))\n * - `--item-bg-selected-tickled`: Background when selected AND tickled (default: rgba(21, 101, 192, 1))\n * - `--item-border`: Border style (default: 1px solid transparent)\n * - `--item-border-tickled`: Border when tickled (default: 1px solid var(--accent))\n * - `--item-border-selected`: Border when selected (default: 1px solid rgba(25, 118, 210, 1))\n * - `--item-text-tickled`: Text color when tickled (default: inherit)\n * - `--item-text-selected`: Text color when selected (default: #fff)\n * - `--item-padding`: Item padding (default: 4px 8px)\n * - `--item-border-radius`: Border radius (default: 4px)\n * - `--item-icon-spacing`: Gap between icon and text (default: 4px)\n *\n * ## Usage\n *\n * Components should import both `tickledStyles` and `tickledItemStyles`:\n *\n * ```ts\n * import { tickledStyles, tickledItemStyles } from '../interaction/index.js';\n *\n * class MyComponent extends LitElement {\n * static styles = [\n * tickledStyles,\n * tickledItemStyles,\n * css`\n * :host {\n * --item-bg-tickled: #e0e0e0;\n * --item-bg-selected: #1976d2;\n * }\n * `\n * ];\n * }\n * ```\n */\n\nexport const tickledStyles = css`\n /**\n * No suppression needed - tickled styling is always active.\n */\n`;\n\n/**\n * Shared item styling for tickled components.\n *\n * Provides base styles for interactive items with tickled and selected states.\n * Components should import this in addition to `tickledStyles` and can override\n * CSS variables to customize appearance.\n */\nexport const tickledItemStyles = css`\n .item {\n display: inline-flex;\n align-items: center;\n gap: var(--item-icon-spacing);\n padding: var(--item-padding);\n background: var(--item-bg);\n border: var(--item-border);\n border-radius: var(--item-border-radius);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: background var(--transition, 0.1s ease-out), border-color var(--transition, 0.1s ease-out);\n }\n\n .item.tickled {\n background: var(--item-bg-tickled);\n border-color: var(--item-border-tickled);\n color: var(--item-text-tickled);\n }\n\n .item.selected {\n background: var(--item-bg-selected);\n border-color: var(--item-border-selected);\n color: var(--item-text-selected);\n }\n\n .item.selected.tickled {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n`;"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0HA,IAAa,oBAAb,MAAa,kBAA4D;;2BAM5B;;;2BACA;;;kCACQ;;;iCACD;;CAElD,YAAY,MAA8B,QAAoC;oBAR1C,KAAA;EASlC,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,aAAa,OAAO,oBAAoB;EAC7C,KAAK,cAAc,IAAI;CACzB;CAEA,gBAAsB;EACpB,IAAI,CAAC,kBAAkB,yBAAyB;GAC9C,SAAS,iBAAiB,gBAAgB,MAAoB;IAC5D,kBAAkB,wBAAwB,EAAE,SAAS,EAAE,OAAO;GAChE,GAAG,EAAE,SAAS,KAAK,CAAC;GACpB,kBAAkB,0BAA0B;EAC9C;CACF;CAEA,mBAAyB,CAEzB;;;;CAKA,IAAI,YAAuB;EACzB,OAAO,KAAK;CACd;;;;CAKA,IAAI,YAA2B;EAC7B,OAAO,KAAK;CACd;;;;CAKA,UAAU,IAAgB;EACxB,OAAO,KAAK,eAAe;CAC7B;;;;;;CAOA,OAAe,wBAAwB,SAAiB,SAAuB;EAC7E,IAAI,CAAC,OAAO,MAAM,kBAAkB,iBAAiB;OAEjD,YAAY,kBAAkB,qBAC3B,YAAY,kBAAkB,mBAEjC,kBAAkB,2BAA2B;EAAA;EAGjD,kBAAkB,oBAAoB;EACtC,kBAAkB,oBAAoB;CACxC;;;;;CAMA,WAAW,6BAAsC;EAC/C,OAAO,kBAAkB;CAC3B;;;;;;CAOA,mBAAmB,IAAa;EAC9B,IAAI,CAAC,kBAAkB,0BACrB;EAIF,MAAM,OADQ,KAAK,OAAO,SACT,EAAE,MAAK,SAAQ,KAAK,OAAO,EAAE;EAC9C,IAAI,QAAQ,KAAK,YAAY,OAC3B;EAGF,MAAM,cAAc,KAAK,eAAe;EACxC,KAAK,aAAa;EAElB,MAAM,aAAa,KAAK;EACxB,KAAK,aAAa;EAElB,KAAK,KAAK,cAAc;EAExB,IAAI,eAAe,MAAM,KAAK,OAAO,UACnC,KAAK,OAAO,SAAS,EAAE;EAGzB,KAAK,eAAe,MAAM,gBAAgB,KAAK,OAAO,eACpD,KAAK,OAAO,cAAc;CAE9B;;;;;;CAOA,mBAAmB,IAAwB;EACzC,IAAI,kBAAkB,0BACpB,KAAK,aAAa;CAEtB;;;;;;;CAQA,yBAAyB,WAA6D;EACpF,MAAM,cAAc,KAAK,eAAe;EACxC,KAAK,aAAa;EAGlB,MAAM,eADQ,KAAK,OAAO,SACD,EAAE,QAAO,SAAQ,KAAK,YAAY,KAAK;EAEhE,IAAI,aAAa,WAAW,GAC1B;EAGF,IAAI;EAEJ,IAAI,cAAc,SAChB,QAAQ,aAAa,GAAG;OACnB,IAAI,cAAc,QACvB,QAAQ,aAAa,GAAG,EAAE,GAAG;OACxB,IAAI,cAAc,UAAU,cAAc,YAAY;GAC3D,MAAM,eAAe,aAAa,WAAU,SAAQ,KAAK,OAAO,KAAK,UAAU;GAE/E,IAAI,iBAAiB,IACnB,QAAQ,cAAc,SAAS,aAAa,GAAG,KAAK,aAAa,GAAG,EAAE,GAAG;QACpE;IAEL,MAAM,WAAW,gBADH,cAAc,SAAS,IAAI;IAGzC,IAAI,YAAY,KAAK,WAAW,aAAa,QAC3C,QAAQ,aAAa,UAAU;GAGnC;EACF,OAAO;GACL,MAAM,OAAO,aAAa,MAAK,SAAQ,KAAK,OAAO,SAAS;GAC5D,IAAI,MACF,QAAQ,KAAK;EAEjB;EAEA,IAAI,UAAU,KAAA,GAAW;GACvB,MAAM,aAAa,KAAK;GACxB,KAAK,aAAa;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,eAAe,SAAS,KAAK,OAAO,UACtC,KAAK,OAAO,SAAS,KAAK;GAG5B,KAAK,eAAe,SAAS,gBAAgB,KAAK,OAAO,eACvD,KAAK,OAAO,cAAc;EAE9B;CACF;;;;;CAMA,WAAW,IAAyB;EAClC,MAAM,aAAa,KAAK;EACxB,KAAK,aAAa;EAClB,KAAK,KAAK,cAAc;EAExB,IAAI,eAAe,MAAM,KAAK,OAAO,UACnC,KAAK,OAAO,SAAS,EAAE;EAGzB,IAAI,eAAe,MAAM,KAAK,OAAO,eACnC,KAAK,OAAO,cAAc;CAE9B;;;;;;CAOA,eAAqB;EACnB,IAAI,KAAK,eAAe,KAAA,GAAW;GACjC,KAAK,aAAa,KAAA;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,KAAK,OAAO,UACd,KAAK,OAAO,SAAS,KAAA,CAAS;GAGhC,IAAI,KAAK,OAAO,eACd,KAAK,OAAO,cAAc;EAE9B;CACF;;;;;CAMA,aAAa,MAAuB;EAClC,IAAI,KAAK,eAAe,MAAM;GAC5B,KAAK,aAAa;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,SAAS,YACX,kBAAkB,2BAA2B;GAG/C,IAAI,KAAK,OAAO,eACd,KAAK,OAAO,cAAc;EAE9B;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzTA,MAAa,gBAAgB,GAAG;;;;;;;;;;;;AAahC,MAAa,oBAAoB,GAAG"}
|
|
1
|
+
{"version":3,"file":"tickled-styles-fNDdqf6l.js","names":[],"sources":["../src/interaction/tickled-controller.ts","../src/interaction/tickled-styles.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * Represents an item that can be tickled (highlighted via hover or keyboard navigation)\n */\nexport type TickledItem<T = unknown> = {\n /**\n * Unique identifier for the item (e.g., index, id, path)\n */\n readonly id: T;\n\n /**\n * Whether the item is currently enabled/interactive\n */\n readonly enabled?: boolean;\n};\n\n/**\n * Input mode determines which mechanism controls the tickled state\n */\nexport type InputMode = `keyboard` | `mouse`;\n\n/**\n * Configuration for TickledController\n */\nexport type TickledControllerConfig<T> = {\n /**\n * Function to retrieve all items that can be tickled\n */\n getItems: () => ReadonlyArray<TickledItem<T>>;\n\n /**\n * Optional callback when an item becomes tickled\n * Use this for side effects like opening submenus\n * @param id - The id of the newly tickled item, or undefined if nothing is tickled\n */\n onTickle?: (id: T | undefined) => void;\n\n /**\n * Optional callback fired after any state change (tickled id or input mode)\n * Use this to sync DOM attributes for slotted content that can't use reactive rendering\n *\n * For components that render items directly, this is usually not needed as\n * Lit's reactive rendering will handle updates automatically via requestUpdate()\n *\n * @example\n * ```ts\n * onStateChange: () => {\n * // Sync data-tickled attributes for slotted items\n * const items = this.getItems();\n * items.forEach((item, i) => {\n * if (this.tickled.isTickled(i)) {\n * item.setAttribute('data-tickled', '');\n * } else {\n * item.removeAttribute('data-tickled');\n * }\n * });\n * }\n * ```\n */\n onStateChange?: () => void;\n\n /**\n * Optional initial input mode (defaults to 'mouse')\n */\n initialInputMode?: InputMode;\n};\n\n/**\n * ReactiveController that manages \"tickled\" state for interactive lists.\n *\n * A \"tickled\" item is one that is under active attention via hover (mouse mode)\n * or keyboard focus (keyboard mode). Only one item can be tickled at a time.\n *\n * The input mode determines which mechanism controls tickled state:\n * - Mouse mode: hover controls tickled, keyboard navigation ignored\n * - Keyboard mode: keyboard navigation controls tickled, hover ignored\n *\n * Last interaction wins - any mouse hover switches to mouse mode, any keyboard\n * navigation switches to keyboard mode.\n *\n * ## Global Mouse Tracking\n *\n * This controller uses a singleton global `pointermove` listener to track actual\n * mouse movement. This prevents `pointerenter` events caused by content scrolling\n * from incorrectly switching to mouse mode when the user is actually using keyboard\n * navigation.\n *\n * @example\n * ```ts\n * class MyList extends LitElement {\n * private tickled = new TickledController(this, {\n * getItems: () => this.items.map((item, i) => ({ id: i, enabled: !item.disabled })),\n * onTickle: (id) => {\n * // Optional: perform side effect when item is tickled\n * console.log('Tickled item:', id);\n * }\n * });\n *\n * render() {\n * return html`\n * <ul @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}>\n * ${this.items.map((item, i) => html`\n * <li\n * class=\"item ${this.tickled.isTickled(i) ? 'tickled' : ''}\"\n * @pointerenter=${() => this.tickled.handlePointerEnter(i)}\n * >${item.label}</li>\n * `)}\n * </ul>\n * `;\n * }\n *\n * private handleKeyDown(e: KeyboardEvent) {\n * if (e.key === 'ArrowDown') {\n * this.tickled.handleKeyboardNavigation('next');\n * } else if (e.key === 'ArrowUp') {\n * this.tickled.handleKeyboardNavigation('previous');\n * }\n * }\n * }\n * ```\n */\nexport class TickledController<T = number> implements ReactiveController {\n private host: ReactiveControllerHost;\n private config: TickledControllerConfig<T>;\n private _tickledId: T | undefined = undefined;\n private _inputMode: InputMode;\n\n private static _lastMouseClientX: number = Number.NaN;\n private static _lastMouseClientY: number = Number.NaN;\n private static _mouseMovedSinceKeyboard: boolean = true;\n private static _globalListenerAttached: boolean = false;\n\n constructor(host: ReactiveControllerHost, config: TickledControllerConfig<T>) {\n this.host = host;\n this.config = config;\n this._inputMode = config.initialInputMode ?? `mouse`;\n host.addController(this);\n }\n\n hostConnected(): void {\n if (!TickledController._globalListenerAttached) {\n document.addEventListener(`pointermove`, (e: PointerEvent) => {\n TickledController.handleGlobalPointerMove(e.clientX, e.clientY);\n }, { passive: true });\n TickledController._globalListenerAttached = true;\n }\n }\n\n hostDisconnected(): void {\n // No-op: global listener persists for the lifetime of the page\n }\n\n /**\n * Get the current input mode\n */\n get inputMode(): InputMode {\n return this._inputMode;\n }\n\n /**\n * Get the currently tickled item id\n */\n get tickledId(): T | undefined {\n return this._tickledId;\n }\n\n /**\n * Check if a specific item is tickled\n */\n isTickled(id: T): boolean {\n return this._tickledId === id;\n }\n\n /**\n * Handle global pointer move event.\n * Called automatically by the global listener.\n * Tracks mouse movement to distinguish real hover from content scrolling.\n */\n private static handleGlobalPointerMove(clientX: number, clientY: number): void {\n if (!Number.isNaN(TickledController._lastMouseClientX)) {\n if (\n clientX !== TickledController._lastMouseClientX\n || clientY !== TickledController._lastMouseClientY\n ) {\n TickledController._mouseMovedSinceKeyboard = true;\n }\n }\n TickledController._lastMouseClientX = clientX;\n TickledController._lastMouseClientY = clientY;\n }\n\n /**\n * Check if actual mouse movement has occurred since last keyboard interaction.\n * Used to distinguish real hover/leave from content-scrolling-induced events.\n */\n static get hasMouseMovedSinceKeyboard(): boolean {\n return TickledController._mouseMovedSinceKeyboard;\n }\n\n /**\n * Handle pointer enter event on an item (mouse hover).\n * Only processes if actual mouse movement is detected (not content scrolling).\n * Switches to mouse mode and tickles the item.\n */\n handlePointerEnter(id: T): void {\n if (!TickledController._mouseMovedSinceKeyboard) {\n return;\n }\n\n const items = this.config.getItems();\n const item = items.find(item => item.id === id);\n if (item && item.enabled === false) {\n return;\n }\n\n const modeChanged = this._inputMode !== `mouse`;\n this._inputMode = `mouse`;\n\n const previousId = this._tickledId;\n this._tickledId = id;\n\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if ((previousId !== id || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Handle pointer leave event on an item.\n * Only clears tickled state if actual mouse movement is detected.\n * @param _e The pointer event (not used, but kept for API compatibility)\n */\n handlePointerLeave(_e: PointerEvent): void {\n if (TickledController._mouseMovedSinceKeyboard) {\n this.clearTickled();\n }\n }\n\n /**\n * Handle keyboard navigation.\n * Switches to keyboard mode and moves tickled state.\n *\n * @param direction - 'next', 'previous', 'first', 'last', or specific id\n */\n handleKeyboardNavigation(direction: `next` | `previous` | `first` | `last` | T): void {\n const modeChanged = this._inputMode !== `keyboard`;\n this._inputMode = `keyboard`;\n\n const items = this.config.getItems();\n const enabledItems = items.filter(item => item.enabled !== false);\n\n if (enabledItems.length === 0) {\n return;\n }\n\n let newId: T | undefined;\n\n if (direction === `first`) {\n newId = enabledItems[0].id;\n } else if (direction === `last`) {\n newId = enabledItems.at(-1)?.id;\n } else if (direction === `next` || direction === `previous`) {\n const currentIndex = enabledItems.findIndex(item => item.id === this._tickledId);\n\n if (currentIndex === -1) {\n newId = direction === `next` ? enabledItems[0].id : enabledItems.at(-1)?.id;\n } else {\n const delta = direction === `next` ? 1 : -1;\n const newIndex = currentIndex + delta;\n\n if (newIndex >= 0 && newIndex < enabledItems.length) {\n newId = enabledItems[newIndex].id;\n }\n // If newIndex is out of bounds, keep current tickled item\n }\n } else {\n const item = enabledItems.find(item => item.id === direction);\n if (item) {\n newId = item.id;\n }\n }\n\n if (newId !== undefined) {\n const previousId = this._tickledId;\n this._tickledId = newId;\n this.host.requestUpdate();\n\n if (previousId !== newId && this.config.onTickle) {\n this.config.onTickle(newId);\n }\n\n if ((previousId !== newId || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the tickled item (useful for programmatic control).\n * Does NOT change input mode.\n */\n setTickled(id: T | undefined): void {\n const previousId = this._tickledId;\n this._tickledId = id;\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if (previousId !== id && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Clear the tickled state (e.g., on pointer leave).\n * Note: For pointer leave events, prefer using handlePointerLeave() which\n * checks for actual mouse movement.\n */\n clearTickled(): void {\n if (this._tickledId !== undefined) {\n this._tickledId = undefined;\n this.host.requestUpdate();\n\n if (this.config.onTickle) {\n this.config.onTickle(undefined);\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the input mode.\n * When switching to keyboard mode, resets the mouse movement tracking.\n */\n setInputMode(mode: InputMode): void {\n if (this._inputMode !== mode) {\n this._inputMode = mode;\n this.host.requestUpdate();\n\n if (mode === `keyboard`) {\n TickledController._mouseMovedSinceKeyboard = false;\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n}\n","import { css } from 'lit';\n\n/**\n * Shared CSS styles for tickled interaction pattern.\n *\n * Tickled state is controlled via the `.tickled` CSS class (applied by TickledController).\n * The `tickledItemStyles` provides base styling that all tickled components should use.\n *\n * ## CSS Variable Contract\n *\n * **Style variables (default values defined in `tickledItemStyles`):**\n * - `--item-bg`: Default background (default: transparent)\n * - `--item-bg-tickled`: Background when tickled (default: rgba(0, 0, 0, 0.06))\n * - `--item-bg-selected`: Background when selected (default: rgba(25, 118, 210, 1))\n * - `--item-bg-selected-tickled`: Background when selected AND tickled (default: rgba(21, 101, 192, 1))\n * - `--item-border`: Border style (default: 1px solid transparent)\n * - `--item-border-tickled`: Border when tickled (default: 1px solid var(--accent))\n * - `--item-border-selected`: Border when selected (default: 1px solid rgba(25, 118, 210, 1))\n * - `--item-text-tickled`: Text color when tickled (default: inherit)\n * - `--item-text-selected`: Text color when selected (default: #fff)\n * - `--item-padding`: Item padding (default: 4px 8px)\n * - `--item-border-radius`: Border radius (default: 4px)\n * - `--item-icon-spacing`: Gap between icon and text (default: 4px)\n *\n * ## Usage\n *\n * Components should import both `tickledStyles` and `tickledItemStyles`:\n *\n * ```ts\n * import { tickledStyles, tickledItemStyles } from '../interaction/index.js';\n *\n * class MyComponent extends LitElement {\n * static styles = [\n * tickledStyles,\n * tickledItemStyles,\n * css`\n * :host {\n * --item-bg-tickled: #e0e0e0;\n * --item-bg-selected: #1976d2;\n * }\n * `\n * ];\n * }\n * ```\n */\n\nexport const tickledStyles = css`\n /**\n * No suppression needed - tickled styling is always active.\n */\n`;\n\n/**\n * Shared item styling for tickled components.\n *\n * Provides base styles for interactive items with tickled and selected states.\n * Components should import this in addition to `tickledStyles` and can override\n * CSS variables to customize appearance.\n */\nexport const tickledItemStyles = css`\n .item {\n display: inline-flex;\n align-items: center;\n gap: var(--item-icon-spacing);\n padding: var(--item-padding);\n background: var(--item-bg);\n border: var(--item-border);\n border-radius: var(--item-border-radius);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: background var(--transition, 0.1s ease-out), border-color var(--transition, 0.1s ease-out);\n }\n\n .item.tickled {\n background: var(--item-bg-tickled);\n border-color: var(--item-border-tickled);\n color: var(--item-text-tickled);\n }\n\n .item.selected {\n background: var(--item-bg-selected);\n border-color: var(--item-border-selected);\n color: var(--item-text-selected);\n }\n\n .item.selected.tickled {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n`;"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0HA,IAAa,oBAAb,MAAa,kBAA4D;;EAM5B,KAAA,oBAAA;;;EACA,KAAA,oBAAA;;;EACQ,KAAA,2BAAA;;;EACD,KAAA,0BAAA;;CAElD,YAAY,MAA8B,QAAoC;EAR1C,KAAA,aAAA,KAAA;EASlC,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,aAAa,OAAO,oBAAoB;EAC7C,KAAK,cAAc,IAAI;CACzB;CAEA,gBAAsB;EACpB,IAAI,CAAC,kBAAkB,yBAAyB;GAC9C,SAAS,iBAAiB,gBAAgB,MAAoB;IAC5D,kBAAkB,wBAAwB,EAAE,SAAS,EAAE,OAAO;GAChE,GAAG,EAAE,SAAS,KAAK,CAAC;GACpB,kBAAkB,0BAA0B;EAC9C;CACF;CAEA,mBAAyB,CAEzB;;;;CAKA,IAAI,YAAuB;EACzB,OAAO,KAAK;CACd;;;;CAKA,IAAI,YAA2B;EAC7B,OAAO,KAAK;CACd;;;;CAKA,UAAU,IAAgB;EACxB,OAAO,KAAK,eAAe;CAC7B;;;;;;CAOA,OAAe,wBAAwB,SAAiB,SAAuB;EAC7E,IAAI,CAAC,OAAO,MAAM,kBAAkB,iBAAiB,GAEjD;OAAA,YAAY,kBAAkB,qBAC3B,YAAY,kBAAkB,mBAEjC,kBAAkB,2BAA2B;EAAA;EAGjD,kBAAkB,oBAAoB;EACtC,kBAAkB,oBAAoB;CACxC;;;;;CAMA,WAAW,6BAAsC;EAC/C,OAAO,kBAAkB;CAC3B;;;;;;CAOA,mBAAmB,IAAa;EAC9B,IAAI,CAAC,kBAAkB,0BACrB;EAIF,MAAM,OADQ,KAAK,OAAO,SACT,CAAC,CAAC,MAAK,SAAQ,KAAK,OAAO,EAAE;EAC9C,IAAI,QAAQ,KAAK,YAAY,OAC3B;EAGF,MAAM,cAAc,KAAK,eAAe;EACxC,KAAK,aAAa;EAElB,MAAM,aAAa,KAAK;EACxB,KAAK,aAAa;EAElB,KAAK,KAAK,cAAc;EAExB,IAAI,eAAe,MAAM,KAAK,OAAO,UACnC,KAAK,OAAO,SAAS,EAAE;EAGzB,KAAK,eAAe,MAAM,gBAAgB,KAAK,OAAO,eACpD,KAAK,OAAO,cAAc;CAE9B;;;;;;CAOA,mBAAmB,IAAwB;EACzC,IAAI,kBAAkB,0BACpB,KAAK,aAAa;CAEtB;;;;;;;CAQA,yBAAyB,WAA6D;EACpF,MAAM,cAAc,KAAK,eAAe;EACxC,KAAK,aAAa;EAGlB,MAAM,eADQ,KAAK,OAAO,SACD,CAAC,CAAC,QAAO,SAAQ,KAAK,YAAY,KAAK;EAEhE,IAAI,aAAa,WAAW,GAC1B;EAGF,IAAI;EAEJ,IAAI,cAAc,SAChB,QAAQ,aAAa,EAAE,CAAC;OACnB,IAAI,cAAc,QACvB,QAAQ,aAAa,GAAG,EAAE,CAAC,EAAE;OACxB,IAAI,cAAc,UAAU,cAAc,YAAY;GAC3D,MAAM,eAAe,aAAa,WAAU,SAAQ,KAAK,OAAO,KAAK,UAAU;GAE/E,IAAI,iBAAiB,IACnB,QAAQ,cAAc,SAAS,aAAa,EAAE,CAAC,KAAK,aAAa,GAAG,EAAE,CAAC,EAAE;QACpE;IAEL,MAAM,WAAW,gBADH,cAAc,SAAS,IAAI;IAGzC,IAAI,YAAY,KAAK,WAAW,aAAa,QAC3C,QAAQ,aAAa,SAAS,CAAC;GAGnC;EACF,OAAO;GACL,MAAM,OAAO,aAAa,MAAK,SAAQ,KAAK,OAAO,SAAS;GAC5D,IAAI,MACF,QAAQ,KAAK;EAEjB;EAEA,IAAI,UAAU,KAAA,GAAW;GACvB,MAAM,aAAa,KAAK;GACxB,KAAK,aAAa;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,eAAe,SAAS,KAAK,OAAO,UACtC,KAAK,OAAO,SAAS,KAAK;GAG5B,KAAK,eAAe,SAAS,gBAAgB,KAAK,OAAO,eACvD,KAAK,OAAO,cAAc;EAE9B;CACF;;;;;CAMA,WAAW,IAAyB;EAClC,MAAM,aAAa,KAAK;EACxB,KAAK,aAAa;EAClB,KAAK,KAAK,cAAc;EAExB,IAAI,eAAe,MAAM,KAAK,OAAO,UACnC,KAAK,OAAO,SAAS,EAAE;EAGzB,IAAI,eAAe,MAAM,KAAK,OAAO,eACnC,KAAK,OAAO,cAAc;CAE9B;;;;;;CAOA,eAAqB;EACnB,IAAI,KAAK,eAAe,KAAA,GAAW;GACjC,KAAK,aAAa,KAAA;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,KAAK,OAAO,UACd,KAAK,OAAO,SAAS,KAAA,CAAS;GAGhC,IAAI,KAAK,OAAO,eACd,KAAK,OAAO,cAAc;EAE9B;CACF;;;;;CAMA,aAAa,MAAuB;EAClC,IAAI,KAAK,eAAe,MAAM;GAC5B,KAAK,aAAa;GAClB,KAAK,KAAK,cAAc;GAExB,IAAI,SAAS,YACX,kBAAkB,2BAA2B;GAG/C,IAAI,KAAK,OAAO,eACd,KAAK,OAAO,cAAc;EAE9B;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzTA,MAAa,gBAAgB,GAAG;;;;;;;;;;;;AAahC,MAAa,oBAAoB,GAAG"}
|