@ixfx/components 0.7.0 → 0.7.2
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 +259 -44
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +828 -125
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/ac-text.js +1 -1
- package/dist/{ac-token-BAa6ke09.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-BAa6ke09.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/ac-token.js +1 -1
- package/dist/{button-Dat2yHAU.js → button-DsFbV4XD.js} +3 -3
- package/dist/{button-Dat2yHAU.js.map → button-DsFbV4XD.js.map} +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/button.js +1 -1
- package/dist/{colour-picker-BSDBL-QL.js → colour-picker-Ddsk-7E_.js} +2 -2
- package/dist/{colour-picker-BSDBL-QL.js.map → colour-picker-Ddsk-7E_.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.js +1 -1
- package/dist/{data-grid-C8qIo1-u.d.ts → data-grid-Bh4YrQGK.d.ts} +2 -2
- package/dist/{data-grid-C8qIo1-u.d.ts.map → data-grid-Bh4YrQGK.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +1 -1
- package/dist/{defaults-BkWCPJFL.js → defaults-BJwDsMH4.js} +26 -2
- package/dist/defaults-BJwDsMH4.js.map +1 -0
- package/dist/{hex-editor-Bk6rxhfg.js → hex-editor-BiRfwTz1.js} +2 -2
- package/dist/{hex-editor-Bk6rxhfg.js.map → hex-editor-BiRfwTz1.js.map} +1 -1
- package/dist/hex.js +1 -1
- package/dist/{icon-DpA9x2Ve.d.ts → icon-CDGprSdE.d.ts} +1 -12
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/{icon-CvnPanhA.js → icon-DcEEGQa_.js} +37 -8
- package/dist/icon-DcEEGQa_.js.map +1 -0
- package/dist/icons.d.ts +3 -3
- package/dist/icons.js +4 -4
- package/dist/icons.js.map +1 -1
- package/dist/{index-CKtLhgYj.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-CKtLhgYj.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/{index-BtGFYfaK.d.ts → index-CS9yM8L-.d.ts} +14 -4
- package/dist/index-CS9yM8L-.d.ts.map +1 -0
- package/dist/{index-CG2vIgPv.d.ts → index-UvnoZUAo.d.ts} +4 -4
- package/dist/{index-CG2vIgPv.d.ts.map → index-UvnoZUAo.d.ts.map} +1 -1
- package/dist/index.d.ts +231 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +701 -110
- package/dist/index.js.map +1 -1
- package/dist/labelled-radial-input.d.ts +1 -1
- package/dist/labelled-radial-input.js +1 -1
- package/dist/{labelled-slider-input-DzigjMwP.js → labelled-slider-input-BInB5GKL.js} +3 -3
- package/dist/{labelled-slider-input-DzigjMwP.js.map → labelled-slider-input-BInB5GKL.js.map} +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/labelled-slider-input.js +1 -1
- package/dist/{menu-BjRvlgPy.js → menu-CXDFJxNm.js} +3 -3
- package/dist/{menu-BjRvlgPy.js.map → menu-CXDFJxNm.js.map} +1 -1
- package/dist/{menu-item-Bs2MYyHq.d.ts → menu-item-CZi9vy5O.d.ts} +4 -2
- package/dist/menu-item-CZi9vy5O.d.ts.map +1 -0
- package/dist/{menu-item-B-zYrTTi.js → menu-item-D2S4i8u1.js} +16 -4
- package/dist/menu-item-D2S4i8u1.js.map +1 -0
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -1
- package/dist/notifier.js +2 -2
- package/dist/notifier.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/plots.js +1 -1
- package/dist/polar-pad.d.ts +2 -2
- package/dist/polar-pad.js +1 -1
- package/dist/{radial-input-Dp5qz0ly.js → radial-input-BfA3GO0H.js} +2 -2
- package/dist/{radial-input-Dp5qz0ly.js.map → radial-input-BfA3GO0H.js.map} +1 -1
- package/dist/{radial-input-DXMN55Nz.d.ts → radial-input-DU6t2hYO.d.ts} +3 -3
- package/dist/{radial-input-DXMN55Nz.d.ts.map → radial-input-DU6t2hYO.d.ts.map} +1 -1
- package/dist/radial-input.d.ts +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.d.ts +2 -2
- package/dist/range-input.js +1 -1
- package/dist/range.d.ts +2 -2
- package/dist/range.js +1 -1
- package/dist/registry-BEtb8_wB.js +46 -0
- package/dist/registry-BEtb8_wB.js.map +1 -0
- package/dist/select-horiz.d.ts +2 -2
- package/dist/select-horiz.js +1 -1
- package/dist/{slider-input-De4eoT11.js → slider-input-Bl1hFE89.js} +2 -2
- package/dist/{slider-input-De4eoT11.js.map → slider-input-Bl1hFE89.js.map} +1 -1
- package/dist/{slider-input-BfRUW2ZB.d.ts → slider-input-BxURAAmD.d.ts} +3 -3
- package/dist/{slider-input-BfRUW2ZB.d.ts.map → slider-input-BxURAAmD.d.ts.map} +1 -1
- package/dist/slider-input.d.ts +1 -1
- package/dist/slider-input.js +1 -1
- package/dist/swipe.d.ts +2 -2
- package/dist/swipe.js +1 -1
- package/dist/{tab-list-MPwq_1Jj.d.ts → tab-list-CGyPt07Z.d.ts} +9 -2
- package/dist/tab-list-CGyPt07Z.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +32 -13
- package/dist/tabs.js.map +1 -1
- package/dist/{titlebar-DaCfpliv.d.ts → titlebar-Bj5pfdw_.d.ts} +2 -2
- package/dist/{titlebar-DaCfpliv.d.ts.map → titlebar-Bj5pfdw_.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/titlebar.js +1 -1
- package/dist/tooltip-BlvBUQxx.d.ts.map +1 -1
- package/dist/wheel-nudge-By5s_ioH.d.ts +31 -0
- package/dist/wheel-nudge-By5s_ioH.d.ts.map +1 -0
- package/dist/{wheel-nudge-BlSCe_hD.js → wheel-nudge-D5rmht3v.js} +6 -1
- package/dist/wheel-nudge-D5rmht3v.js.map +1 -0
- package/dist/{xy-axis-CxHC8z5E.js → xy-axis-DWizs0bt.js} +3 -3
- package/dist/xy-axis-DWizs0bt.js.map +1 -0
- package/dist/xy-pad.d.ts +2 -2
- package/dist/xy-pad.js +1 -1
- package/docs-user/dock.md +166 -15
- package/docs-user/icons.md +4 -0
- package/docs-user/index.json +2 -2
- package/docs-user/tabs.md +20 -0
- package/docs-user/user-theming.md +109 -0
- package/package.json +1 -1
- package/dist/defaults-BkWCPJFL.js.map +0 -1
- package/dist/icon-CvnPanhA.js.map +0 -1
- package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
- package/dist/index-BtGFYfaK.d.ts.map +0 -1
- package/dist/menu-item-B-zYrTTi.js.map +0 -1
- package/dist/menu-item-Bs2MYyHq.d.ts.map +0 -1
- package/dist/registry-CkW7q09Q.js +0 -21
- package/dist/registry-CkW7q09Q.js.map +0 -1
- package/dist/tab-list-MPwq_1Jj.d.ts.map +0 -1
- package/dist/wheel-nudge-BlSCe_hD.js.map +0 -1
- package/dist/wheel-nudge-DGrNzWuE.d.ts +0 -29
- package/dist/wheel-nudge-DGrNzWuE.d.ts.map +0 -1
- package/dist/xy-axis-CxHC8z5E.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as WheelNudgeConsumer, t as WheelDirection } from "./wheel-nudge-By5s_ioH.js";
|
|
2
2
|
import { LitElement, PropertyValues } from "lit";
|
|
3
3
|
//#region src/slider-input/types.d.ts
|
|
4
4
|
/**
|
|
@@ -89,7 +89,7 @@ interface SliderInputElementEventMap {
|
|
|
89
89
|
}
|
|
90
90
|
//#endregion
|
|
91
91
|
//#region src/slider-input/slider-input.d.ts
|
|
92
|
-
declare const SliderInputElement_base: (new (...args: any[]) =>
|
|
92
|
+
declare const SliderInputElement_base: typeof LitElement & (new (...args: any[]) => WheelNudgeConsumer);
|
|
93
93
|
declare class SliderInputElement extends SliderInputElement_base {
|
|
94
94
|
#private;
|
|
95
95
|
valueA: number;
|
|
@@ -170,4 +170,4 @@ interface SliderInputElement {
|
|
|
170
170
|
}
|
|
171
171
|
//#endregion
|
|
172
172
|
export { SliderValueMode as _, SliderInputChangeDetail as a, SliderInputInputDetail as c, SliderLaneType as d, SliderMarkerStyle as f, SliderValueDrag as g, SliderValueCFollow as h, SliderHandleKey as i, SliderInputInputEvent as l, SliderSingleStyle as m, SliderChangedField as n, SliderInputChangeEvent as o, SliderOrientation as p, SliderCrossover as r, SliderInputElementEventMap as s, SliderInputElement as t, SliderLaneData as u };
|
|
173
|
-
//# sourceMappingURL=slider-input-
|
|
173
|
+
//# sourceMappingURL=slider-input-BxURAAmD.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slider-input-
|
|
1
|
+
{"version":3,"file":"slider-input-BxURAAmD.d.ts","names":[],"sources":["../src/slider-input/types.ts","../src/slider-input/slider-input.ts"],"mappings":";;;;;;KAIY;KACA;KACA;KACA;KACA;KACA;;;;;;;KAOA;KACA;KACA;;;;;;;UAQK;EACf;EACA,MAAM;;;;;EAKN;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;KAOU;;;;;;;;UASK;WACN;WACA;;WAEA;;WAEA;WACA;WACA;;WAEA;WACA;;WAEA,UAAU;;UAGJ;WACN;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,UAAU;;KAGT,wBAAwB,YAAY;KACpC,yBAAyB,YAAY;UAEhC;EACf,OAAO;EACP,QAAQ;;;;;cCZG,2BAA2B;;EAGtC;EAGA;;;;;;EAQA;EAGA;EAGA;EAGA;EAGA;EAGA,WAAW;EAGX,aAAa;EAGb,aAAa;EAGb,aAAa;;;;;;EAQb,cAAc;EAGd,WAAW;EAGX,WAAW;;;;;;;EASX,cAAc;EAGd;EAGA;;;;;;;;;;;;;EAeA;;EAyFS;EAiFT,QACE,aACA;IACE;IACA;IACA;IACA,OAAO;IACP;IACA;;EAgBJ,aAAa,aAAa;EAQ1B,aAAa,aAAa,kBAAkB;EAW5C,WAAW;EAKX,YAAY,oBAAoB;EAIhC,QAAQ,cAAc;EA0nCb,iBAAiB,WAAW,gBAAgB,OAAO;YAoXzC,WAAW,SAAS;EAsE9B;YA2JU,QAAQ,SAAS;EAkB3B;SAiBO,sBAAM;;QAqJhB;YACI;IACR,qBAAqB;;;UAKR;EACf,oBAAoB,gBAAgB,4BAClC,MAAM,GACN,WAAW,MAAM,oBAAoB,OAAO,2BAA2B,aACvE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB"}
|
package/dist/slider-input.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as SliderInputElement } from "./slider-input-
|
|
1
|
+
import { t as SliderInputElement } from "./slider-input-BxURAAmD.js";
|
|
2
2
|
export { SliderInputElement };
|
package/dist/slider-input.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as SliderInputElement } from "./slider-input-
|
|
1
|
+
import { t as SliderInputElement } from "./slider-input-Bl1hFE89.js";
|
|
2
2
|
export { SliderInputElement };
|
package/dist/swipe.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as WheelNudgeConsumer, t as WheelDirection } from "./wheel-nudge-By5s_ioH.js";
|
|
2
2
|
import { CSSResultGroup, LitElement, html } from "lit";
|
|
3
3
|
//#region src/swipe/swipe.d.ts
|
|
4
4
|
type SwipeInputDetail = {
|
|
@@ -16,7 +16,7 @@ declare global {
|
|
|
16
16
|
'ixfx-swipe': SwipeElement;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
declare const SwipeElement_base: (new (...args: any[]) =>
|
|
19
|
+
declare const SwipeElement_base: typeof LitElement & (new (...args: any[]) => WheelNudgeConsumer);
|
|
20
20
|
declare class SwipeElement extends SwipeElement_base {
|
|
21
21
|
#private;
|
|
22
22
|
barSpacing: number;
|
package/dist/swipe.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
|
|
2
2
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
3
3
|
import { t as prominenceStyles } from "./prominence-DlFShic3.js";
|
|
4
|
-
import { t as WheelNudgeMixin } from "./wheel-nudge-
|
|
4
|
+
import { t as WheelNudgeMixin } from "./wheel-nudge-D5rmht3v.js";
|
|
5
5
|
import { LitElement, css, html, svg } from "lit";
|
|
6
6
|
import { property } from "lit/decorators.js";
|
|
7
7
|
//#region src/swipe/swipe.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./icon-
|
|
1
|
+
import "./icon-CDGprSdE.js";
|
|
2
2
|
import { LitElement, PropertyValues } from "lit";
|
|
3
3
|
import { CommandRegistry } from "@clinth/ui-commands";
|
|
4
4
|
//#region src/tabs/tab-list-item.d.ts
|
|
@@ -20,12 +20,19 @@ declare class TabListItemElement extends LitElement {
|
|
|
20
20
|
private _hasToolbarContent;
|
|
21
21
|
private _resizeObserver?;
|
|
22
22
|
private _commandCleanup?;
|
|
23
|
+
private _labelObserver;
|
|
23
24
|
connectedCallback(): void;
|
|
24
25
|
disconnectedCallback(): void;
|
|
25
26
|
updated(changed: PropertyValues): void;
|
|
26
27
|
private _syncTooltipAttrs;
|
|
27
28
|
private _syncCommandListener;
|
|
28
29
|
private _onToolbarSlotChange;
|
|
30
|
+
private _onLabelSlotChange;
|
|
31
|
+
/**
|
|
32
|
+
* Mirror the default-slot text into `.label[data-label]` for the `::after`
|
|
33
|
+
* width sizer. Slotted toolbar content is excluded.
|
|
34
|
+
*/
|
|
35
|
+
private _syncLabelSizer;
|
|
29
36
|
private _updateToolbarContent;
|
|
30
37
|
firstUpdated(): void;
|
|
31
38
|
render(): import("lit").TemplateResult<1>;
|
|
@@ -79,4 +86,4 @@ declare global {
|
|
|
79
86
|
}
|
|
80
87
|
//#endregion
|
|
81
88
|
export { TabListReorderDetail as a, TabListElement as i, TabListChangeEvent as n, TabListReorderEvent as o, TabListDragMode as r, TabListItemElement as s, TabListChangeDetail as t };
|
|
82
|
-
//# sourceMappingURL=tab-list-
|
|
89
|
+
//# sourceMappingURL=tab-list-CGyPt07Z.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-list-CGyPt07Z.d.ts","names":[],"sources":["../src/tabs/tab-list-item.ts","../src/tabs/tab-list.ts"],"mappings":";;;;;;;;;;;cAiBa,2BAA2B;EAEtC;EAGA;EAGA;EAGA;EAGA;EAGA,UAAU;UAEO;UACA;UACT;UACA;UACA;EAEC;EAgBA;EAcA,QAAQ,SAAS;UAQlB;UAUA;UAWA;UAIA;;;;;UAQA;UAiBA;EAKC;EAKA,wBAAM;UA8BP;SAWQ,sBAAM;;QAmKhB;YACI;IACR,sBAAsB;;;;;;;;;;KC3Ud;WACD;WACA;WACA;;KAGC,qBAAqB,YAAY;KAEjC;WACD;WACA;WACA;;KAGC,sBAAsB,YAAY;KAElC;cAMC,uBAAuB;;EAElC;EAGA;EAGA;EAGA;EAGA;EAGA,UAAU;EA4BD,wBAAM;EAsDN;EAUA,QAAQ,mBAAmB;EAoGpC,sBAAkB;EAwBlB,cAAc,IAAI;SAwaX,sBAAM;;QAyKP;YACI;IACR,iBAAiB"}
|
package/dist/tabs.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-
|
|
1
|
+
import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-CGyPt07Z.js";
|
|
2
2
|
export { TabListChangeDetail, TabListChangeEvent, TabListDragMode, TabListElement, TabListReorderDetail, TabListReorderEvent };
|
package/dist/tabs.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
|
|
2
2
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
3
|
+
import { t as scrollFadeStyles } from "./scroll-fade-CAs1EabA.js";
|
|
3
4
|
import { t as createDragGhost } from "./drag-ghost-DtSDvjri.js";
|
|
4
5
|
import { LitElement, css, html, nothing } from "lit";
|
|
5
6
|
import { property } from "lit/decorators.js";
|
|
@@ -60,14 +61,12 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
60
61
|
if (!el) return;
|
|
61
62
|
if (!this.#isVertical) {
|
|
62
63
|
if (event.deltaY === 0 || el.scrollWidth <= el.clientWidth) return;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (el.scrollLeft !== prev) event.preventDefault();
|
|
64
|
+
el.scrollLeft = el.scrollLeft + event.deltaY;
|
|
65
|
+
event.preventDefault();
|
|
66
66
|
} else {
|
|
67
67
|
if (event.deltaX === 0 || el.scrollHeight <= el.clientHeight) return;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (el.scrollTop !== prev) event.preventDefault();
|
|
68
|
+
el.scrollTop = el.scrollTop + event.deltaX;
|
|
69
|
+
event.preventDefault();
|
|
71
70
|
}
|
|
72
71
|
};
|
|
73
72
|
this.#onSlotClick = (event) => {
|
|
@@ -154,8 +153,11 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
154
153
|
return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;
|
|
155
154
|
}
|
|
156
155
|
get #containerClass() {
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
return [
|
|
157
|
+
this.scrollable ? `${this.orientation} scrollable` : this.orientation,
|
|
158
|
+
this.scrollable ? this.#isVertical ? `scroll-fade-y` : `scroll-fade-x` : ``,
|
|
159
|
+
this.dragMode === `reorder` ? `reorder` : ``
|
|
160
|
+
].filter(Boolean).join(` `);
|
|
159
161
|
}
|
|
160
162
|
render() {
|
|
161
163
|
const caretStyle = this.#computeCaretStyle();
|
|
@@ -437,7 +439,11 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
437
439
|
return this.shadowRoot?.getElementById(`container`) ?? null;
|
|
438
440
|
}
|
|
439
441
|
static {
|
|
440
|
-
this.styles = [
|
|
442
|
+
this.styles = [
|
|
443
|
+
themeFallbacks,
|
|
444
|
+
scrollFadeStyles(`x`),
|
|
445
|
+
scrollFadeStyles(`y`),
|
|
446
|
+
css`
|
|
441
447
|
:host {
|
|
442
448
|
display: inline-block;
|
|
443
449
|
--activated-colour: var(--accent);
|
|
@@ -520,8 +526,12 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
520
526
|
overflow: hidden;
|
|
521
527
|
}
|
|
522
528
|
#container.horizontal.scrollable {
|
|
523
|
-
overflow-x:
|
|
529
|
+
overflow-x: scroll;
|
|
524
530
|
--allow-overflow: visible;
|
|
531
|
+
scrollbar-width: none;
|
|
532
|
+
}
|
|
533
|
+
#container.horizontal.scrollable::-webkit-scrollbar {
|
|
534
|
+
display: none;
|
|
525
535
|
}
|
|
526
536
|
#container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {
|
|
527
537
|
flex-shrink: 0;
|
|
@@ -534,9 +544,13 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
534
544
|
flex-direction: column-reverse;
|
|
535
545
|
}
|
|
536
546
|
#container.vertical-stack.scrollable {
|
|
537
|
-
overflow-y:
|
|
547
|
+
overflow-y: scroll;
|
|
538
548
|
max-height: var(--scroll-max-height);
|
|
539
549
|
--allow-overflow: visible;
|
|
550
|
+
scrollbar-width: none;
|
|
551
|
+
}
|
|
552
|
+
#container.vertical-stack.scrollable::-webkit-scrollbar {
|
|
553
|
+
display: none;
|
|
540
554
|
}
|
|
541
555
|
#container.vertical-side {
|
|
542
556
|
flex-direction: column;
|
|
@@ -546,9 +560,13 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
546
560
|
flex-direction: column-reverse;
|
|
547
561
|
}
|
|
548
562
|
#container.vertical-side.scrollable {
|
|
549
|
-
overflow-y:
|
|
563
|
+
overflow-y: scroll;
|
|
550
564
|
max-height: var(--scroll-max-height);
|
|
551
565
|
--allow-overflow: visible;
|
|
566
|
+
scrollbar-width: none;
|
|
567
|
+
}
|
|
568
|
+
#container.vertical-side.scrollable::-webkit-scrollbar {
|
|
569
|
+
display: none;
|
|
552
570
|
}
|
|
553
571
|
|
|
554
572
|
::slotted(ixfx-tab-list-item) {
|
|
@@ -591,7 +609,8 @@ let TabListElement = class TabListElement extends LitElement {
|
|
|
591
609
|
::slotted(.activated) {
|
|
592
610
|
--colour: var(--activated-colour);
|
|
593
611
|
}
|
|
594
|
-
`
|
|
612
|
+
`
|
|
613
|
+
];
|
|
595
614
|
}
|
|
596
615
|
};
|
|
597
616
|
__decorate([property({ type: String })], TabListElement.prototype, "orientation", void 0);
|
package/dist/tabs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":["#items","#syncIndicatorColors","#syncHideLabels","#isVertical","#selectPrevious","#selectNext","#dragState","#abortDrag","#endDrag","#containerEl","#suppressNextClick","#findDragTarget","#onPointerMove","#onPointerUp","#onPointerCancel","#beginDrag","#computeGapIndex","#commitDrag","#containerClass","#computeCaretStyle","#onKeyUp","#onSlotClick","#onPointerDown","#onKeyDown","#onWheel","#onSlotChange","#onToolbarSlotChange","#isSelected","#createGhost","customElement"],"sources":["../src/tabs/tab-list.ts"],"sourcesContent":["import type { PropertyValues } from \"lit\";\nimport type { DragGhost } from \"../util/drag-ghost.js\";\nimport type { TabListItemElement } from \"./tab-list-item.js\";\nimport { css, html, LitElement, nothing } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { themeFallbacks } from \"../styles/fallbacks.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\nimport { createDragGhost } from \"../util/drag-ghost.js\";\n\n/**\n * Events\n * 'change' - new tab selected { previous:string, selected:string, for:string }\n * 'reorder' - tab moved within the list { id:string, fromIndex:number, toIndex:number }\n */\nexport type TabListChangeDetail = {\n readonly previous: string | undefined;\n readonly selected: string;\n readonly for: string;\n};\n\nexport type TabListChangeEvent = CustomEvent<TabListChangeDetail>;\n\nexport type TabListReorderDetail = {\n readonly id: string;\n readonly fromIndex: number;\n readonly toIndex: number;\n};\n\nexport type TabListReorderEvent = CustomEvent<TabListReorderDetail>;\n\nexport type TabListDragMode = `off` | `reorder`;\n\n/** Pointer movement threshold (px) before a press becomes a drag. */\nconst DRAG_THRESHOLD_PX = 5;\n\n@customElement(`ixfx-tab-list`)\nexport class TabListElement extends LitElement {\n @property({ type: String })\n orientation: `horizontal` | `vertical-stack` | `vertical-side` = `horizontal`;\n\n @property({ type: Boolean })\n flip = false;\n\n @property({ type: Boolean })\n scrollable = false;\n\n @property({ type: Boolean, attribute: `hide-labels` })\n hideLabels = false;\n\n @property({ type: Boolean, reflect: true })\n shrink = false;\n\n @property({ type: String, attribute: `drag-mode` })\n dragMode: TabListDragMode = `off`;\n\n #items: TabListItemElement[] = [];\n\n // ── Drag state (not reactive) ────────────────────────────────────────\n #dragState: {\n pointerId: number;\n source: TabListItemElement;\n fromIndex: number;\n startX: number;\n startY: number;\n active: boolean;\n ghost: DragGhost | null;\n gapIndex: number | undefined;\n } | null = null;\n\n #suppressNextClick = false;\n\n get #isVertical(): boolean {\n return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;\n }\n\n get #containerClass(): string {\n const base = this.scrollable ? `${this.orientation} scrollable` : this.orientation;\n return this.dragMode === `reorder` ? `${base} reorder` : base;\n }\n\n override render() {\n const caretStyle = this.#computeCaretStyle();\n return html`\n <div class=\"outer ${this.orientation}\">\n <div\n tabindex=0\n @keyup=${this.#onKeyUp}\n @click=${this.#onSlotClick}\n @pointerdown=${this.#onPointerDown}\n @keydown=${this.#onKeyDown}\n @wheel=${this.#onWheel}\n id=\"container\"\n class=${this.#containerClass}\n >\n <slot @slotchange=${this.#onSlotChange}></slot>\n ${caretStyle\n ? html`<div class=\"drop-caret\" style=${caretStyle}></div>`\n : nothing}\n </div>\n <div class=\"list-toolbar ${this.orientation}\" part=\"list-toolbar\">\n <slot name=\"toolbar\" @slotchange=${this.#onToolbarSlotChange}></slot>\n </div>\n </div>`;\n }\n\n #onSlotChange = () => {\n this.updateComplete.then(() => {\n this.#items = (this.shadowRoot?.querySelector(`slot:not([name])`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n this.#syncHideLabels();\n });\n };\n\n #onToolbarSlotChange = () => {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"toolbar\"]`) as HTMLSlotElement | null;\n const assigned = slot?.assignedElements() ?? [];\n const has = assigned.length > 0;\n this.toggleAttribute(`has-toolbar`, has);\n const toolbarDiv = this.shadowRoot?.querySelector(`.list-toolbar`) as HTMLElement | null;\n if (toolbarDiv)\n toolbarDiv.hidden = !has;\n\n // Force ixfx-toolbar to re-measure after slot assignment\n if (has) {\n const toolbar = assigned[0];\n if (toolbar?.tagName === `IXFX-TOOLBAR`) {\n requestAnimationFrame(() => {\n (toolbar as any)?._scheduleMeasure?.();\n });\n }\n }\n };\n\n override firstUpdated() {\n this.updateComplete.then(() => {\n if (this.#items.length > 0) {\n this.#syncIndicatorColors();\n this.#syncHideLabels();\n }\n this.#onToolbarSlotChange();\n });\n }\n\n override updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n this.classList.toggle(`scrollable`, this.scrollable);\n if (changedProperties.has(`dragMode`)) {\n this.toggleAttribute(`drag-mode`, this.dragMode !== `off`);\n }\n if (changedProperties.has(`hideLabels`)) {\n this.#syncHideLabels();\n }\n }\n\n #syncHideLabels() {\n for (const item of this.#items) {\n if (this.hideLabels) {\n item.setAttribute(`hide-labels`, ``);\n } else {\n item.removeAttribute(`hide-labels`);\n }\n }\n }\n\n #syncIndicatorColors() {\n for (const item of this.#items) {\n item.style.setProperty(`--indicator-color-bottom`, `transparent`);\n item.style.setProperty(`--indicator-color-top`, `transparent`);\n item.style.setProperty(`--indicator-color-left`, `transparent`);\n item.style.setProperty(`--indicator-color-right`, `transparent`);\n\n if (item.hasAttribute(`selected`)) {\n if (this.orientation === `horizontal` && !this.flip) {\n item.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n item.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n item.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n item.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n }\n }\n\n #onKeyUp = (event: KeyboardEvent) => {\n const key = event.key;\n if (this.#isVertical) {\n if (key === `ArrowUp`) {\n this.#selectPrevious();\n } else if (key === `ArrowDown`) {\n this.#selectNext();\n }\n } else {\n if (key === `ArrowRight`) {\n this.#selectNext();\n } else if (key === `ArrowLeft`) {\n this.#selectPrevious();\n }\n }\n };\n\n // Escape during drag aborts it (and tears down listeners / releases capture)\n #onKeyDown = (event: KeyboardEvent): void => {\n const state = this.#dragState;\n if (event.key !== `Escape` || !state?.active)\n return;\n event.preventDefault();\n const pointerId = state.pointerId;\n this.#abortDrag();\n this.#endDrag(pointerId);\n };\n\n /**\n * Translate vertical wheel deltas into horizontal scroll on a scrollable\n * horizontal list (and vice-versa for vertical lists). Without this, the\n * default browser behaviour only scrolls horizontally with Shift+wheel or a\n * physical horizontal wheel — neither of which most users reach for on a\n * VS Code-style tab strip.\n *\n * Only kicks in when the list is actually scrollable (overflow content\n * present), and is a no-op when nothing is scrollable in that direction.\n */\n #onWheel = (event: WheelEvent): void => {\n if (!this.scrollable)\n return;\n const el = this.#containerEl;\n if (!el)\n return;\n\n if (!this.#isVertical) {\n // Horizontal list: vertical wheel → horizontal scroll.\n if (event.deltaY === 0 || el.scrollWidth <= el.clientWidth)\n return;\n const prev = el.scrollLeft;\n el.scrollLeft = prev + event.deltaY;\n if (el.scrollLeft !== prev)\n event.preventDefault();\n } else {\n // Vertical list: vertical wheel is already native; only intervene when\n // a horizontal wheel is supplied (e.g. trackpad two-finger horizontal).\n if (event.deltaX === 0 || el.scrollHeight <= el.clientHeight)\n return;\n const prev = el.scrollTop;\n el.scrollTop = prev + event.deltaX;\n if (el.scrollTop !== prev)\n event.preventDefault();\n }\n };\n\n getSelectedElement() {\n for (const el of this.#items) {\n if (this.#isSelected(el))\n return el;\n }\n // Fallback: #items may not be populated yet (slotchange hasn't fired).\n // Query the slot directly to find the selected element.\n const slot = this.shadowRoot?.querySelector(`slot`);\n if (slot) {\n const els = (slot as HTMLSlotElement).assignedElements({ flatten: true });\n for (const el of els) {\n if (this.#isSelected(el as HTMLElement))\n return el as TabListItemElement;\n }\n }\n }\n\n #isSelected(el: HTMLElement) {\n const v = el.getAttribute(`selected`);\n if (v === null)\n return false;\n return (el.hasAttribute(`selected`));\n }\n\n selectElement(el: HTMLElement) {\n const existing = this.getSelectedElement();\n if (existing) {\n existing.removeAttribute(`selected`);\n existing.style.setProperty(`--indicator-color-bottom`, `transparent`);\n existing.style.setProperty(`--indicator-color-top`, `transparent`);\n existing.style.setProperty(`--indicator-color-left`, `transparent`);\n existing.style.setProperty(`--indicator-color-right`, `transparent`);\n }\n\n el.setAttribute(`selected`, ``);\n\n if (this.orientation === `horizontal` && !this.flip) {\n el.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n el.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n el.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n el.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n\n #selectNext() {\n let found = false;\n for (const el of this.#items) {\n if (this.#isSelected(el) && !found) {\n found = true;\n } else if (found) {\n this.selectElement(el);\n break;\n }\n }\n }\n\n #selectPrevious() {\n let prev: HTMLElement | undefined;\n for (const el of this.#items) {\n if (this.#isSelected(el) && prev) {\n this.selectElement(prev);\n } else {\n prev = el;\n }\n }\n }\n\n #onSlotClick = (event: MouseEvent) => {\n if (this.#suppressNextClick) {\n this.#suppressNextClick = false;\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n this.focus();\n const t = (event.target as HTMLElement).closest(`ixfx-tab-list-item`);\n if (!t)\n return;\n const previous = this.getSelectedElement();\n this.selectElement(t);\n\n const forId = t.getAttribute(`for`);\n const previousId = previous?.id;\n this.dispatchEvent(new CustomEvent<TabListChangeDetail>(`change`, {\n bubbles: true,\n detail: {\n previous: previousId,\n selected: t.id,\n for: forId ?? ``,\n },\n }));\n };\n\n // ── Drag handling ────────────────────────────────────────────────────\n\n /**\n * Walk composedPath looking for the nearest ancestor tab-list-item, but bail\n * if the path goes through a `.close-btn` or `.toolbar` (so close/toolbar\n * buttons always win — same delegation pattern used by tooltip-controller).\n */\n #findDragTarget(event: PointerEvent): TabListItemElement | null {\n if (this.dragMode === `off`)\n return null;\n\n const path = event.composedPath();\n let item: TabListItemElement | null = null;\n for (const node of path) {\n if (!(node instanceof HTMLElement))\n continue;\n if (node.classList.contains(`close-btn`) || node.classList.contains(`toolbar`)) {\n return null;\n }\n if (!item && node.tagName === `IXFX-TAB-LIST-ITEM`) {\n item = node as TabListItemElement;\n }\n }\n return item;\n }\n\n #onPointerDown = (event: PointerEvent): void => {\n if (this.dragMode !== `reorder`)\n return;\n if (event.button !== 0)\n return;\n const target = this.#findDragTarget(event);\n if (!target)\n return;\n\n const fromIndex = this.#items.indexOf(target);\n if (fromIndex < 0)\n return;\n\n // Don't capture the pointer yet — doing so on pointerdown would redirect\n // the trailing click event to the capture target (the container), so the\n // click handler would see a container DIV as its target instead of the\n // tab-list-item and `closest('ixfx-tab-list-item')` would return null.\n // We capture only once the drag actually activates (#beginDrag). Until\n // then, an ordinary press still produces a normal click on the tab.\n\n this.#dragState = {\n pointerId: event.pointerId,\n source: target,\n fromIndex,\n startX: event.clientX,\n startY: event.clientY,\n active: false,\n ghost: null,\n gapIndex: undefined,\n };\n\n // Listen at window level for move/up so we don't lose events if the\n // pointer exits the host before pointerup fires.\n window.addEventListener(`pointermove`, this.#onPointerMove);\n window.addEventListener(`pointerup`, this.#onPointerUp);\n window.addEventListener(`pointercancel`, this.#onPointerCancel);\n };\n\n #onPointerMove = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n\n const dx = event.clientX - state.startX;\n const dy = event.clientY - state.startY;\n const distance = Math.hypot(dx, dy);\n\n if (!state.active) {\n if (distance < DRAG_THRESHOLD_PX)\n return;\n this.#beginDrag(event);\n }\n\n state.ghost?.move(event.clientX, event.clientY);\n\n const gap = this.#computeGapIndex(event.clientX, event.clientY);\n if (gap !== state.gapIndex) {\n state.gapIndex = gap;\n this.requestUpdate();\n }\n };\n\n #onPointerUp = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n\n if (state.active) {\n const gap = this.#computeGapIndex(event.clientX, event.clientY);\n this.#commitDrag(state.source, state.fromIndex, gap);\n }\n this.#endDrag(event.pointerId);\n };\n\n #onPointerCancel = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n this.#abortDrag();\n this.#endDrag(event.pointerId);\n };\n\n #beginDrag(event: PointerEvent): void {\n const state = this.#dragState;\n if (!state || state.active)\n return;\n\n // Now that we know we're dragging, capture the pointer so pointermove/up\n // events keep flowing even if the pointer leaves the host element.\n try {\n this.#containerEl?.setPointerCapture(event.pointerId);\n } catch {\n // setPointerCapture can throw if pointer is already captured elsewhere;\n // fall through — window listeners still catch move/up.\n }\n\n state.active = true;\n state.source.setAttribute(`drag-source`, ``);\n\n state.ghost = this.#createGhost(state.source);\n if (state.ghost) {\n state.ghost.move(event.clientX, event.clientY);\n }\n }\n\n #abortDrag(): void {\n const state = this.#dragState;\n if (!state)\n return;\n state.source.removeAttribute(`drag-source`);\n if (state.gapIndex !== undefined) {\n state.gapIndex = undefined;\n this.requestUpdate();\n }\n // Caller is responsible for invoking #endDrag to release pointer capture,\n // tear down listeners, and destroy the ghost.\n }\n\n #endDrag(pointerId: number): void {\n const state = this.#dragState;\n if (!state)\n return;\n\n state.ghost?.destroy();\n state.ghost = null;\n this.#dragState = null;\n\n window.removeEventListener(`pointermove`, this.#onPointerMove);\n window.removeEventListener(`pointerup`, this.#onPointerUp);\n window.removeEventListener(`pointercancel`, this.#onPointerCancel);\n\n try {\n this.#containerEl?.releasePointerCapture(pointerId);\n } catch { /* already released */ }\n\n // #dragState is a private field, not a Lit-reactive property — setting it\n // to null doesn't trigger a re-render on its own. Without this, the caret\n // (and any other drag-time UI) would remain in the DOM after the drag\n // ends, even though the next render would clear them.\n this.requestUpdate();\n }\n\n #commitDrag(source: TabListItemElement, fromIndex: number, gapIndex: number | undefined): void {\n source.removeAttribute(`drag-source`);\n\n // gapIndex is an index into the without-source siblings array: 0 = before\n // the first sibling, siblings.length = after the last. The siblings array\n // already excludes source, so we can insert directly at that position\n // using siblings[gapIndex] as the reference (or null to append).\n const siblings = this.#items.filter(el => el !== source);\n const target = gapIndex === undefined\n ? siblings.length\n : Math.max(0, Math.min(gapIndex, siblings.length));\n\n const parent = source.parentNode;\n if (!parent)\n return;\n\n const ref = siblings[target] ?? null;\n parent.insertBefore(source, ref);\n\n const toIndex = Array.prototype.indexOf.call(parent.children, source);\n if (toIndex === fromIndex) {\n // Dropped in the same gap the item already occupies — no reorder, and no\n // click suppression (a real click on the same tab is still meaningful).\n return;\n }\n\n // Refresh cached #items so subsequent drags / queries see the new order\n // (slotchange does NOT fire on reorder, only on add/remove).\n this.#items = (this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n\n // A real reorder just happened. The trailing click event (which the\n // browser still fires after pointerup) would re-select whatever is under\n // the release point — not what the user wanted. Suppress it.\n this.#suppressNextClick = true;\n\n this.dispatchEvent(new CustomEvent<TabListReorderDetail>(`reorder`, {\n bubbles: true,\n detail: {\n id: source.id,\n fromIndex,\n toIndex,\n },\n }));\n }\n\n #createGhost(source: TabListItemElement): DragGhost | null {\n const content = document.createElement(`span`);\n content.style.display = `inline-flex`;\n content.style.alignItems = `center`;\n content.style.gap = `var(--space-xs, 4px)`;\n content.style.minWidth = `0`;\n\n const iconName = source.iconName;\n if (iconName) {\n const icon = document.createElement(`ixfx-icon`) as HTMLElement & { name: string };\n icon.name = iconName;\n content.appendChild(icon);\n }\n\n // Reconstruct label text from light-DOM children that aren't slotted.\n // We want the text content of the source item, excluding `slot=\"toolbar\"`\n // descendants (the close button lives inside the item's shadow DOM, not\n // its light DOM, so it isn't part of childNodes here).\n const label = document.createElement(`span`);\n label.textContent = (source.textContent ?? ``).trim();\n label.style.overflow = `hidden`;\n label.style.textOverflow = `ellipsis`;\n label.style.whiteSpace = `nowrap`;\n content.appendChild(label);\n\n try {\n return createDragGhost({ anchor: source, content });\n } catch {\n return null;\n }\n }\n\n /**\n * Compute the index of the gap nearest the pointer, ignoring the source item.\n * Returns 0..#items.length-1; undefined if no siblings.\n *\n * Per the plan: drag-mode=\"reorder\" has \"no sense of breaking out\", so the\n * perpendicular axis is ignored — the pointer always resolves to some gap.\n */\n #computeGapIndex(clientX: number, clientY: number): number | undefined {\n const state = this.#dragState;\n if (!state)\n return undefined;\n const siblings = this.#items.filter(el => el !== state.source);\n if (siblings.length === 0)\n return 0;\n\n const useX = !this.#isVertical;\n\n let bestGap = 0;\n let bestDist = Infinity;\n\n // For each sibling, decide: gap is \"before this sibling\" or \"after\" based\n // on which side of the midpoint the pointer is on. Pick the gap whose\n // position (the midpoint if \"before\", the edge if \"after\") is closest to\n // the pointer on the relevant axis.\n for (let i = 0; i < siblings.length; i++) {\n const rect = siblings[i].getBoundingClientRect();\n const start = useX ? rect.left : rect.top;\n const end = useX ? rect.right : rect.bottom;\n const mid = (start + end) / 2;\n const pos = useX ? clientX : clientY;\n\n // Two candidate gaps: before this sibling (at `start`) and after (at `end`).\n // \"Before\" gap index = i; \"after\" gap index = i + 1.\n const dStart = Math.abs(pos - start);\n const dMid = Math.abs(pos - mid);\n const dEnd = Math.abs(pos - end);\n\n // Heuristic: if pointer is left/above midpoint, prefer the \"before\" gap;\n // otherwise prefer the \"after\" gap. Within those, the closer edge wins.\n const preferBefore = pos < mid;\n if (preferBefore) {\n // Gap i (before this sibling)\n if (dStart < bestDist) {\n bestDist = dStart;\n bestGap = i;\n }\n } else {\n // Gap i+1 (after this sibling)\n if (dEnd < bestDist) {\n bestDist = dEnd;\n bestGap = i + 1;\n }\n }\n // The midpoint-distance is mostly redundant with the above but handles\n // ties near the boundary cleanly — no-op for the chosen gap.\n void dMid;\n }\n\n return bestGap;\n }\n\n #computeCaretStyle(): string | undefined {\n const state = this.#dragState;\n if (!state?.active || state.gapIndex === undefined)\n return undefined;\n\n const siblings = this.#items.filter(el => el !== state.source);\n if (siblings.length === 0)\n return undefined;\n\n const useX = !this.#isVertical;\n const containerRect = this.#containerEl?.getBoundingClientRect();\n if (!containerRect)\n return undefined;\n\n const gap = Math.max(0, Math.min(state.gapIndex, siblings.length));\n let rect: DOMRect | null = null;\n if (gap < siblings.length) {\n rect = siblings[gap].getBoundingClientRect();\n } else {\n // After the last sibling: use its trailing edge\n const last = siblings[siblings.length - 1].getBoundingClientRect();\n rect = last;\n }\n\n if (useX) {\n const x = (gap < siblings.length ? rect.left : rect.right) - containerRect.left;\n const y = 0;\n const h = containerRect.height;\n const w = 2;\n return `transform: translate(${x - w / 2}px, ${y}px); width: ${w}px; height: ${h}px;`;\n } else {\n const y = (gap < siblings.length ? rect.top : rect.bottom) - containerRect.top;\n const x = 0;\n const w = containerRect.width;\n const h = 2;\n return `transform: translate(${x}px, ${y - h / 2}px); width: ${w}px; height: ${h}px;`;\n }\n }\n\n get #containerEl(): HTMLElement | null {\n return this.shadowRoot?.getElementById(`container`) ?? null;\n }\n\n static styles = [themeFallbacks, css`\n :host {\n display: inline-block;\n --activated-colour: var(--accent);\n --colour: var(--surface-3-text);\n --scroll-max-height: 200px;\n --allow-overflow: hidden;\n color: var(--colour);\n border: var(--border, none);\n border-color: var(--surface-5);\n border-radius: var(--radius-l, 8px) var(--radius-l, 8px) 0 0;\n\n }\n :host(.scrollable) {\n max-height: var(--scroll-max-height);\n }\n :host([hide-labels]) {\n display: inline-flex;\n width: auto;\n }\n text {\n user-select:none;\n }\n .outer {\n display: flex;\n width: 100%;\n height: 100%;\n gap: var(--space-s);\n align-items: stretch;\n box-sizing: border-box;\n }\n .outer.horizontal {\n flex-direction: row;\n align-items: center;\n }\n .outer.vertical-stack,\n .outer.vertical-side {\n flex-direction: column;\n }\n .list-toolbar {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n flex: 0 0 auto;\n width: max-content;\n max-width: 50%;\n overflow: visible;\n }\n .list-toolbar.horizontal ::slotted(*:not(ixfx-toolbar)) {\n margin-left: auto;\n }\n .list-toolbar[hidden] {\n display: none !important;\n }\n .list-toolbar[hidden] {\n display: none !important;\n }\n ::slotted(ixfx-toolbar) {\n --toolbar-bg: transparent;\n --toolbar-border: none;\n --toolbar-padding: 0;\n width: max-content;\n max-width: 100%;\n min-width: 150px;\n flex-shrink: 0;\n }\n #container {\n display:flex;\n position: relative;\n flex: 1 1 0%;\n min-width: 0;\n min-height: 0;\n }\n .outer.vertical-stack #container,\n .outer.vertical-side #container {\n flex: 1 1 auto;\n height: 100%;\n }\n #container.horizontal {\n flex-direction: row;\n overflow: hidden;\n }\n #container.horizontal.scrollable {\n overflow-x: auto;\n --allow-overflow: visible;\n }\n #container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {\n flex-shrink: 0;\n }\n #container.vertical-stack {\n flex-direction: column;\n height: 100%;\n }\n #container.vertical-stack.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-stack.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n #container.vertical-side {\n flex-direction: column;\n height: 100%;\n }\n #container.vertical-side.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-side.scrollable {\n overflow-y: auto;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n }\n\n ::slotted(ixfx-tab-list-item) {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n :host([shrink]) ::slotted(ixfx-tab-list-item) {\n flex: 0 0 auto;\n }\n\n #container.vertical-side ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-lr;\n text-orientation: mixed;\n }\n #container.vertical-side.flip ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n /* Drag affordances — opt-in via drag-mode=\"reorder\" on the host (list). */\n #container.reorder ::slotted(ixfx-tab-list-item) {\n cursor: grab;\n }\n :host([drag-mode]) ::slotted(ixfx-tab-list-item[drag-source]) {\n cursor: grabbing;\n opacity: 0.4;\n transition: opacity var(--transition, 0.15s ease-out);\n }\n\n /* Insertion caret shown during an active drag. */\n .drop-caret {\n position: absolute;\n background: var(--accent);\n border-radius: 1px;\n pointer-events: none;\n z-index: 1;\n }\n\n ::slotted(.activated) {\n --colour: var(--activated-colour);\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-tab-list\": TabListElement;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tabs.js","names":["#items","#syncIndicatorColors","#syncHideLabels","#isVertical","#selectPrevious","#selectNext","#dragState","#abortDrag","#endDrag","#containerEl","#suppressNextClick","#findDragTarget","#onPointerMove","#onPointerUp","#onPointerCancel","#beginDrag","#computeGapIndex","#commitDrag","#containerClass","#computeCaretStyle","#onKeyUp","#onSlotClick","#onPointerDown","#onKeyDown","#onWheel","#onSlotChange","#onToolbarSlotChange","#isSelected","#createGhost","customElement"],"sources":["../src/tabs/tab-list.ts"],"sourcesContent":["import type { PropertyValues } from \"lit\";\nimport type { DragGhost } from \"../util/drag-ghost.js\";\nimport type { TabListItemElement } from \"./tab-list-item.js\";\nimport { css, html, LitElement, nothing } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { themeFallbacks } from \"../styles/fallbacks.js\";\nimport { scrollFadeStyles } from \"../styles/scroll-fade.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\nimport { createDragGhost } from \"../util/drag-ghost.js\";\n\n/**\n * Events\n * 'change' - new tab selected { previous:string, selected:string, for:string }\n * 'reorder' - tab moved within the list { id:string, fromIndex:number, toIndex:number }\n */\nexport type TabListChangeDetail = {\n readonly previous: string | undefined;\n readonly selected: string;\n readonly for: string;\n};\n\nexport type TabListChangeEvent = CustomEvent<TabListChangeDetail>;\n\nexport type TabListReorderDetail = {\n readonly id: string;\n readonly fromIndex: number;\n readonly toIndex: number;\n};\n\nexport type TabListReorderEvent = CustomEvent<TabListReorderDetail>;\n\nexport type TabListDragMode = `off` | `reorder`;\n\n/** Pointer movement threshold (px) before a press becomes a drag. */\nconst DRAG_THRESHOLD_PX = 5;\n\n@customElement(`ixfx-tab-list`)\nexport class TabListElement extends LitElement {\n @property({ type: String })\n orientation: `horizontal` | `vertical-stack` | `vertical-side` = `horizontal`;\n\n @property({ type: Boolean })\n flip = false;\n\n @property({ type: Boolean })\n scrollable = false;\n\n @property({ type: Boolean, attribute: `hide-labels` })\n hideLabels = false;\n\n @property({ type: Boolean, reflect: true })\n shrink = false;\n\n @property({ type: String, attribute: `drag-mode` })\n dragMode: TabListDragMode = `off`;\n\n #items: TabListItemElement[] = [];\n\n // ── Drag state (not reactive) ────────────────────────────────────────\n #dragState: {\n pointerId: number;\n source: TabListItemElement;\n fromIndex: number;\n startX: number;\n startY: number;\n active: boolean;\n ghost: DragGhost | null;\n gapIndex: number | undefined;\n } | null = null;\n\n #suppressNextClick = false;\n\n get #isVertical(): boolean {\n return this.orientation === `vertical-stack` || this.orientation === `vertical-side`;\n }\n\n get #containerClass(): string {\n const base = this.scrollable ? `${this.orientation} scrollable` : this.orientation;\n const fadeClass = this.scrollable ? (this.#isVertical ? `scroll-fade-y` : `scroll-fade-x`) : ``;\n return [base, fadeClass, this.dragMode === `reorder` ? `reorder` : ``].filter(Boolean).join(` `);\n }\n\n override render() {\n const caretStyle = this.#computeCaretStyle();\n return html`\n <div class=\"outer ${this.orientation}\">\n <div\n tabindex=0\n @keyup=${this.#onKeyUp}\n @click=${this.#onSlotClick}\n @pointerdown=${this.#onPointerDown}\n @keydown=${this.#onKeyDown}\n @wheel=${this.#onWheel}\n id=\"container\"\n class=${this.#containerClass}\n >\n <slot @slotchange=${this.#onSlotChange}></slot>\n ${caretStyle\n ? html`<div class=\"drop-caret\" style=${caretStyle}></div>`\n : nothing}\n </div>\n <div class=\"list-toolbar ${this.orientation}\" part=\"list-toolbar\">\n <slot name=\"toolbar\" @slotchange=${this.#onToolbarSlotChange}></slot>\n </div>\n </div>`;\n }\n\n #onSlotChange = () => {\n this.updateComplete.then(() => {\n this.#items = (this.shadowRoot?.querySelector(`slot:not([name])`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n this.#syncHideLabels();\n });\n };\n\n #onToolbarSlotChange = () => {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"toolbar\"]`) as HTMLSlotElement | null;\n const assigned = slot?.assignedElements() ?? [];\n const has = assigned.length > 0;\n this.toggleAttribute(`has-toolbar`, has);\n const toolbarDiv = this.shadowRoot?.querySelector(`.list-toolbar`) as HTMLElement | null;\n if (toolbarDiv)\n toolbarDiv.hidden = !has;\n\n // Force ixfx-toolbar to re-measure after slot assignment\n if (has) {\n const toolbar = assigned[0];\n if (toolbar?.tagName === `IXFX-TOOLBAR`) {\n requestAnimationFrame(() => {\n (toolbar as any)?._scheduleMeasure?.();\n });\n }\n }\n };\n\n override firstUpdated() {\n this.updateComplete.then(() => {\n if (this.#items.length > 0) {\n this.#syncIndicatorColors();\n this.#syncHideLabels();\n }\n this.#onToolbarSlotChange();\n });\n }\n\n override updated(changedProperties: PropertyValues): void {\n super.updated(changedProperties);\n this.classList.toggle(`scrollable`, this.scrollable);\n if (changedProperties.has(`dragMode`)) {\n this.toggleAttribute(`drag-mode`, this.dragMode !== `off`);\n }\n if (changedProperties.has(`hideLabels`)) {\n this.#syncHideLabels();\n }\n }\n\n #syncHideLabels() {\n for (const item of this.#items) {\n if (this.hideLabels) {\n item.setAttribute(`hide-labels`, ``);\n } else {\n item.removeAttribute(`hide-labels`);\n }\n }\n }\n\n #syncIndicatorColors() {\n for (const item of this.#items) {\n item.style.setProperty(`--indicator-color-bottom`, `transparent`);\n item.style.setProperty(`--indicator-color-top`, `transparent`);\n item.style.setProperty(`--indicator-color-left`, `transparent`);\n item.style.setProperty(`--indicator-color-right`, `transparent`);\n\n if (item.hasAttribute(`selected`)) {\n if (this.orientation === `horizontal` && !this.flip) {\n item.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n item.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n item.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n item.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n }\n }\n\n #onKeyUp = (event: KeyboardEvent) => {\n const key = event.key;\n if (this.#isVertical) {\n if (key === `ArrowUp`) {\n this.#selectPrevious();\n } else if (key === `ArrowDown`) {\n this.#selectNext();\n }\n } else {\n if (key === `ArrowRight`) {\n this.#selectNext();\n } else if (key === `ArrowLeft`) {\n this.#selectPrevious();\n }\n }\n };\n\n // Escape during drag aborts it (and tears down listeners / releases capture)\n #onKeyDown = (event: KeyboardEvent): void => {\n const state = this.#dragState;\n if (event.key !== `Escape` || !state?.active)\n return;\n event.preventDefault();\n const pointerId = state.pointerId;\n this.#abortDrag();\n this.#endDrag(pointerId);\n };\n\n /**\n * Translate vertical wheel deltas into horizontal scroll on a scrollable\n * horizontal list (and vice-versa for vertical lists). Without this, the\n * default browser behaviour only scrolls horizontally with Shift+wheel or a\n * physical horizontal wheel — neither of which most users reach for on a\n * VS Code-style tab strip.\n *\n * Only kicks in when the list is actually scrollable (overflow content\n * present), and is a no-op when nothing is scrollable in that direction.\n */\n #onWheel = (event: WheelEvent): void => {\n if (!this.scrollable)\n return;\n const el = this.#containerEl;\n if (!el)\n return;\n\n if (!this.#isVertical) {\n if (event.deltaY === 0 || el.scrollWidth <= el.clientWidth)\n return;\n el.scrollLeft = el.scrollLeft + event.deltaY;\n event.preventDefault();\n } else {\n if (event.deltaX === 0 || el.scrollHeight <= el.clientHeight)\n return;\n el.scrollTop = el.scrollTop + event.deltaX;\n event.preventDefault();\n }\n };\n\n getSelectedElement() {\n for (const el of this.#items) {\n if (this.#isSelected(el))\n return el;\n }\n // Fallback: #items may not be populated yet (slotchange hasn't fired).\n // Query the slot directly to find the selected element.\n const slot = this.shadowRoot?.querySelector(`slot`);\n if (slot) {\n const els = (slot as HTMLSlotElement).assignedElements({ flatten: true });\n for (const el of els) {\n if (this.#isSelected(el as HTMLElement))\n return el as TabListItemElement;\n }\n }\n }\n\n #isSelected(el: HTMLElement) {\n const v = el.getAttribute(`selected`);\n if (v === null)\n return false;\n return (el.hasAttribute(`selected`));\n }\n\n selectElement(el: HTMLElement) {\n const existing = this.getSelectedElement();\n if (existing) {\n existing.removeAttribute(`selected`);\n existing.style.setProperty(`--indicator-color-bottom`, `transparent`);\n existing.style.setProperty(`--indicator-color-top`, `transparent`);\n existing.style.setProperty(`--indicator-color-left`, `transparent`);\n existing.style.setProperty(`--indicator-color-right`, `transparent`);\n }\n\n el.setAttribute(`selected`, ``);\n\n if (this.orientation === `horizontal` && !this.flip) {\n el.style.setProperty(`--indicator-color-bottom`, `var(--accent)`);\n } else if (this.orientation === `horizontal` && this.flip) {\n el.style.setProperty(`--indicator-color-top`, `var(--accent)`);\n } else if (this.#isVertical && !this.flip) {\n el.style.setProperty(`--indicator-color-right`, `var(--accent)`);\n } else if (this.#isVertical && this.flip) {\n el.style.setProperty(`--indicator-color-left`, `var(--accent)`);\n }\n }\n\n #selectNext() {\n let found = false;\n for (const el of this.#items) {\n if (this.#isSelected(el) && !found) {\n found = true;\n } else if (found) {\n this.selectElement(el);\n break;\n }\n }\n }\n\n #selectPrevious() {\n let prev: HTMLElement | undefined;\n for (const el of this.#items) {\n if (this.#isSelected(el) && prev) {\n this.selectElement(prev);\n } else {\n prev = el;\n }\n }\n }\n\n #onSlotClick = (event: MouseEvent) => {\n if (this.#suppressNextClick) {\n this.#suppressNextClick = false;\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n this.focus();\n const t = (event.target as HTMLElement).closest(`ixfx-tab-list-item`);\n if (!t)\n return;\n const previous = this.getSelectedElement();\n this.selectElement(t);\n\n const forId = t.getAttribute(`for`);\n const previousId = previous?.id;\n this.dispatchEvent(new CustomEvent<TabListChangeDetail>(`change`, {\n bubbles: true,\n detail: {\n previous: previousId,\n selected: t.id,\n for: forId ?? ``,\n },\n }));\n };\n\n // ── Drag handling ────────────────────────────────────────────────────\n\n /**\n * Walk composedPath looking for the nearest ancestor tab-list-item, but bail\n * if the path goes through a `.close-btn` or `.toolbar` (so close/toolbar\n * buttons always win — same delegation pattern used by tooltip-controller).\n */\n #findDragTarget(event: PointerEvent): TabListItemElement | null {\n if (this.dragMode === `off`)\n return null;\n\n const path = event.composedPath();\n let item: TabListItemElement | null = null;\n for (const node of path) {\n if (!(node instanceof HTMLElement))\n continue;\n if (node.classList.contains(`close-btn`) || node.classList.contains(`toolbar`)) {\n return null;\n }\n if (!item && node.tagName === `IXFX-TAB-LIST-ITEM`) {\n item = node as TabListItemElement;\n }\n }\n return item;\n }\n\n #onPointerDown = (event: PointerEvent): void => {\n if (this.dragMode !== `reorder`)\n return;\n if (event.button !== 0)\n return;\n const target = this.#findDragTarget(event);\n if (!target)\n return;\n\n const fromIndex = this.#items.indexOf(target);\n if (fromIndex < 0)\n return;\n\n // Don't capture the pointer yet — doing so on pointerdown would redirect\n // the trailing click event to the capture target (the container), so the\n // click handler would see a container DIV as its target instead of the\n // tab-list-item and `closest('ixfx-tab-list-item')` would return null.\n // We capture only once the drag actually activates (#beginDrag). Until\n // then, an ordinary press still produces a normal click on the tab.\n\n this.#dragState = {\n pointerId: event.pointerId,\n source: target,\n fromIndex,\n startX: event.clientX,\n startY: event.clientY,\n active: false,\n ghost: null,\n gapIndex: undefined,\n };\n\n // Listen at window level for move/up so we don't lose events if the\n // pointer exits the host before pointerup fires.\n window.addEventListener(`pointermove`, this.#onPointerMove);\n window.addEventListener(`pointerup`, this.#onPointerUp);\n window.addEventListener(`pointercancel`, this.#onPointerCancel);\n };\n\n #onPointerMove = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n\n const dx = event.clientX - state.startX;\n const dy = event.clientY - state.startY;\n const distance = Math.hypot(dx, dy);\n\n if (!state.active) {\n if (distance < DRAG_THRESHOLD_PX)\n return;\n this.#beginDrag(event);\n }\n\n state.ghost?.move(event.clientX, event.clientY);\n\n const gap = this.#computeGapIndex(event.clientX, event.clientY);\n if (gap !== state.gapIndex) {\n state.gapIndex = gap;\n this.requestUpdate();\n }\n };\n\n #onPointerUp = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n\n if (state.active) {\n const gap = this.#computeGapIndex(event.clientX, event.clientY);\n this.#commitDrag(state.source, state.fromIndex, gap);\n }\n this.#endDrag(event.pointerId);\n };\n\n #onPointerCancel = (event: PointerEvent): void => {\n const state = this.#dragState;\n if (!state || event.pointerId !== state.pointerId)\n return;\n this.#abortDrag();\n this.#endDrag(event.pointerId);\n };\n\n #beginDrag(event: PointerEvent): void {\n const state = this.#dragState;\n if (!state || state.active)\n return;\n\n // Now that we know we're dragging, capture the pointer so pointermove/up\n // events keep flowing even if the pointer leaves the host element.\n try {\n this.#containerEl?.setPointerCapture(event.pointerId);\n } catch {\n // setPointerCapture can throw if pointer is already captured elsewhere;\n // fall through — window listeners still catch move/up.\n }\n\n state.active = true;\n state.source.setAttribute(`drag-source`, ``);\n\n state.ghost = this.#createGhost(state.source);\n if (state.ghost) {\n state.ghost.move(event.clientX, event.clientY);\n }\n }\n\n #abortDrag(): void {\n const state = this.#dragState;\n if (!state)\n return;\n state.source.removeAttribute(`drag-source`);\n if (state.gapIndex !== undefined) {\n state.gapIndex = undefined;\n this.requestUpdate();\n }\n // Caller is responsible for invoking #endDrag to release pointer capture,\n // tear down listeners, and destroy the ghost.\n }\n\n #endDrag(pointerId: number): void {\n const state = this.#dragState;\n if (!state)\n return;\n\n state.ghost?.destroy();\n state.ghost = null;\n this.#dragState = null;\n\n window.removeEventListener(`pointermove`, this.#onPointerMove);\n window.removeEventListener(`pointerup`, this.#onPointerUp);\n window.removeEventListener(`pointercancel`, this.#onPointerCancel);\n\n try {\n this.#containerEl?.releasePointerCapture(pointerId);\n } catch { /* already released */ }\n\n // #dragState is a private field, not a Lit-reactive property — setting it\n // to null doesn't trigger a re-render on its own. Without this, the caret\n // (and any other drag-time UI) would remain in the DOM after the drag\n // ends, even though the next render would clear them.\n this.requestUpdate();\n }\n\n #commitDrag(source: TabListItemElement, fromIndex: number, gapIndex: number | undefined): void {\n source.removeAttribute(`drag-source`);\n\n // gapIndex is an index into the without-source siblings array: 0 = before\n // the first sibling, siblings.length = after the last. The siblings array\n // already excludes source, so we can insert directly at that position\n // using siblings[gapIndex] as the reference (or null to append).\n const siblings = this.#items.filter(el => el !== source);\n const target = gapIndex === undefined\n ? siblings.length\n : Math.max(0, Math.min(gapIndex, siblings.length));\n\n const parent = source.parentNode;\n if (!parent)\n return;\n\n const ref = siblings[target] ?? null;\n parent.insertBefore(source, ref);\n\n const toIndex = Array.prototype.indexOf.call(parent.children, source);\n if (toIndex === fromIndex) {\n // Dropped in the same gap the item already occupies — no reorder, and no\n // click suppression (a real click on the same tab is still meaningful).\n return;\n }\n\n // Refresh cached #items so subsequent drags / queries see the new order\n // (slotchange does NOT fire on reorder, only on add/remove).\n this.#items = (this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement)\n ?.assignedElements({ flatten: true }) as TabListItemElement[] ?? [];\n this.#syncIndicatorColors();\n\n // A real reorder just happened. The trailing click event (which the\n // browser still fires after pointerup) would re-select whatever is under\n // the release point — not what the user wanted. Suppress it.\n this.#suppressNextClick = true;\n\n this.dispatchEvent(new CustomEvent<TabListReorderDetail>(`reorder`, {\n bubbles: true,\n detail: {\n id: source.id,\n fromIndex,\n toIndex,\n },\n }));\n }\n\n #createGhost(source: TabListItemElement): DragGhost | null {\n const content = document.createElement(`span`);\n content.style.display = `inline-flex`;\n content.style.alignItems = `center`;\n content.style.gap = `var(--space-xs, 4px)`;\n content.style.minWidth = `0`;\n\n const iconName = source.iconName;\n if (iconName) {\n const icon = document.createElement(`ixfx-icon`) as HTMLElement & { name: string };\n icon.name = iconName;\n content.appendChild(icon);\n }\n\n // Reconstruct label text from light-DOM children that aren't slotted.\n // We want the text content of the source item, excluding `slot=\"toolbar\"`\n // descendants (the close button lives inside the item's shadow DOM, not\n // its light DOM, so it isn't part of childNodes here).\n const label = document.createElement(`span`);\n label.textContent = (source.textContent ?? ``).trim();\n label.style.overflow = `hidden`;\n label.style.textOverflow = `ellipsis`;\n label.style.whiteSpace = `nowrap`;\n content.appendChild(label);\n\n try {\n return createDragGhost({ anchor: source, content });\n } catch {\n return null;\n }\n }\n\n /**\n * Compute the index of the gap nearest the pointer, ignoring the source item.\n * Returns 0..#items.length-1; undefined if no siblings.\n *\n * Per the plan: drag-mode=\"reorder\" has \"no sense of breaking out\", so the\n * perpendicular axis is ignored — the pointer always resolves to some gap.\n */\n #computeGapIndex(clientX: number, clientY: number): number | undefined {\n const state = this.#dragState;\n if (!state)\n return undefined;\n const siblings = this.#items.filter(el => el !== state.source);\n if (siblings.length === 0)\n return 0;\n\n const useX = !this.#isVertical;\n\n let bestGap = 0;\n let bestDist = Infinity;\n\n // For each sibling, decide: gap is \"before this sibling\" or \"after\" based\n // on which side of the midpoint the pointer is on. Pick the gap whose\n // position (the midpoint if \"before\", the edge if \"after\") is closest to\n // the pointer on the relevant axis.\n for (let i = 0; i < siblings.length; i++) {\n const rect = siblings[i].getBoundingClientRect();\n const start = useX ? rect.left : rect.top;\n const end = useX ? rect.right : rect.bottom;\n const mid = (start + end) / 2;\n const pos = useX ? clientX : clientY;\n\n // Two candidate gaps: before this sibling (at `start`) and after (at `end`).\n // \"Before\" gap index = i; \"after\" gap index = i + 1.\n const dStart = Math.abs(pos - start);\n const dMid = Math.abs(pos - mid);\n const dEnd = Math.abs(pos - end);\n\n // Heuristic: if pointer is left/above midpoint, prefer the \"before\" gap;\n // otherwise prefer the \"after\" gap. Within those, the closer edge wins.\n const preferBefore = pos < mid;\n if (preferBefore) {\n // Gap i (before this sibling)\n if (dStart < bestDist) {\n bestDist = dStart;\n bestGap = i;\n }\n } else {\n // Gap i+1 (after this sibling)\n if (dEnd < bestDist) {\n bestDist = dEnd;\n bestGap = i + 1;\n }\n }\n // The midpoint-distance is mostly redundant with the above but handles\n // ties near the boundary cleanly — no-op for the chosen gap.\n void dMid;\n }\n\n return bestGap;\n }\n\n #computeCaretStyle(): string | undefined {\n const state = this.#dragState;\n if (!state?.active || state.gapIndex === undefined)\n return undefined;\n\n const siblings = this.#items.filter(el => el !== state.source);\n if (siblings.length === 0)\n return undefined;\n\n const useX = !this.#isVertical;\n const containerRect = this.#containerEl?.getBoundingClientRect();\n if (!containerRect)\n return undefined;\n\n const gap = Math.max(0, Math.min(state.gapIndex, siblings.length));\n let rect: DOMRect | null = null;\n if (gap < siblings.length) {\n rect = siblings[gap].getBoundingClientRect();\n } else {\n // After the last sibling: use its trailing edge\n const last = siblings[siblings.length - 1].getBoundingClientRect();\n rect = last;\n }\n\n if (useX) {\n const x = (gap < siblings.length ? rect.left : rect.right) - containerRect.left;\n const y = 0;\n const h = containerRect.height;\n const w = 2;\n return `transform: translate(${x - w / 2}px, ${y}px); width: ${w}px; height: ${h}px;`;\n } else {\n const y = (gap < siblings.length ? rect.top : rect.bottom) - containerRect.top;\n const x = 0;\n const w = containerRect.width;\n const h = 2;\n return `transform: translate(${x}px, ${y - h / 2}px); width: ${w}px; height: ${h}px;`;\n }\n }\n\n get #containerEl(): HTMLElement | null {\n return this.shadowRoot?.getElementById(`container`) ?? null;\n }\n\n static styles = [themeFallbacks, scrollFadeStyles(`x`), scrollFadeStyles(`y`), css`\n :host {\n display: inline-block;\n --activated-colour: var(--accent);\n --colour: var(--surface-3-text);\n --scroll-max-height: 200px;\n --allow-overflow: hidden;\n color: var(--colour);\n border: var(--border, none);\n border-color: var(--surface-5);\n border-radius: var(--radius-l, 8px) var(--radius-l, 8px) 0 0;\n\n }\n :host(.scrollable) {\n max-height: var(--scroll-max-height);\n }\n :host([hide-labels]) {\n display: inline-flex;\n width: auto;\n }\n text {\n user-select:none;\n }\n .outer {\n display: flex;\n width: 100%;\n height: 100%;\n gap: var(--space-s);\n align-items: stretch;\n box-sizing: border-box;\n }\n .outer.horizontal {\n flex-direction: row;\n align-items: center;\n }\n .outer.vertical-stack,\n .outer.vertical-side {\n flex-direction: column;\n }\n .list-toolbar {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n flex: 0 0 auto;\n width: max-content;\n max-width: 50%;\n overflow: visible;\n }\n .list-toolbar.horizontal ::slotted(*:not(ixfx-toolbar)) {\n margin-left: auto;\n }\n .list-toolbar[hidden] {\n display: none !important;\n }\n .list-toolbar[hidden] {\n display: none !important;\n }\n ::slotted(ixfx-toolbar) {\n --toolbar-bg: transparent;\n --toolbar-border: none;\n --toolbar-padding: 0;\n width: max-content;\n max-width: 100%;\n min-width: 150px;\n flex-shrink: 0;\n }\n #container {\n display:flex;\n position: relative;\n flex: 1 1 0%;\n min-width: 0;\n min-height: 0;\n }\n .outer.vertical-stack #container,\n .outer.vertical-side #container {\n flex: 1 1 auto;\n height: 100%;\n }\n #container.horizontal {\n flex-direction: row;\n overflow: hidden;\n }\n #container.horizontal.scrollable {\n overflow-x: scroll;\n --allow-overflow: visible;\n scrollbar-width: none;\n }\n #container.horizontal.scrollable::-webkit-scrollbar {\n display: none;\n }\n #container.horizontal.scrollable ::slotted(ixfx-tab-list-item) {\n flex-shrink: 0;\n }\n #container.vertical-stack {\n flex-direction: column;\n height: 100%;\n }\n #container.vertical-stack.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-stack.scrollable {\n overflow-y: scroll;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n scrollbar-width: none;\n }\n #container.vertical-stack.scrollable::-webkit-scrollbar {\n display: none;\n }\n #container.vertical-side {\n flex-direction: column;\n height: 100%;\n }\n #container.vertical-side.flip {\n flex-direction: column-reverse;\n }\n #container.vertical-side.scrollable {\n overflow-y: scroll;\n max-height: var(--scroll-max-height);\n --allow-overflow: visible;\n scrollbar-width: none;\n }\n #container.vertical-side.scrollable::-webkit-scrollbar {\n display: none;\n }\n\n ::slotted(ixfx-tab-list-item) {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n :host([shrink]) ::slotted(ixfx-tab-list-item) {\n flex: 0 0 auto;\n }\n\n #container.vertical-side ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-lr;\n text-orientation: mixed;\n }\n #container.vertical-side.flip ::slotted(ixfx-tab-list-item) {\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n /* Drag affordances — opt-in via drag-mode=\"reorder\" on the host (list). */\n #container.reorder ::slotted(ixfx-tab-list-item) {\n cursor: grab;\n }\n :host([drag-mode]) ::slotted(ixfx-tab-list-item[drag-source]) {\n cursor: grabbing;\n opacity: 0.4;\n transition: opacity var(--transition, 0.15s ease-out);\n }\n\n /* Insertion caret shown during an active drag. */\n .drop-caret {\n position: absolute;\n background: var(--accent);\n border-radius: 1px;\n pointer-events: none;\n z-index: 1;\n }\n\n ::slotted(.activated) {\n --colour: var(--activated-colour);\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-tab-list\": TabListElement;\n }\n}\n"],"mappings":";;;;;;;;AAkCA,MAAM,oBAAoB;AAGnB,IAAM,iBAAN,MAAM,uBAAuB,WAAW;;;EAEoB,KAAA,cAAA;EAG1D,KAAA,OAAA;EAGM,KAAA,aAAA;EAGA,KAAA,aAAA;EAGJ,KAAA,SAAA;EAGmB,KAAA,WAAA;EAEG,KAAA,SAAA,CAAC;EAYrB,KAAA,aAAA;EAEU,KAAA,qBAAA;EAqCC,KAAA,sBAAA;GACpB,KAAK,eAAe,WAAW;IAC7B,KAAKA,UAAU,KAAK,YAAY,cAAc,kBAAkB,EAAA,EAC5D,iBAAiB,EAAE,SAAS,KAAK,CAAC,KAA6B,CAAC;IACpE,KAAKC,qBAAqB;IAC1B,KAAKC,gBAAgB;GACvB,CAAC;EACH;EAE6B,KAAA,6BAAA;GAE3B,MAAM,YADO,KAAK,YAAY,cAAc,sBAAsB,EAAA,EAC3C,iBAAiB,KAAK,CAAC;GAC9C,MAAM,MAAM,SAAS,SAAS;GAC9B,KAAK,gBAAgB,eAAe,GAAG;GACvC,MAAM,aAAa,KAAK,YAAY,cAAc,eAAe;GACjE,IAAI,YACF,WAAW,SAAS,CAAC;GAGvB,IAAI,KAAK;IACP,MAAM,UAAU,SAAS;IACzB,IAAI,SAAS,YAAY,gBACvB,4BAA4B;KAC1B,SAAkB,mBAAmB;IACvC,CAAC;GAEL;EACF;EAsDY,KAAA,YAAA,UAAyB;GACnC,MAAM,MAAM,MAAM;GAClB,IAAI,KAAKC,aAAa;IACpB,IAAI,QAAQ,WACV,KAAKC,gBAAgB;SAChB,IAAI,QAAQ,aACjB,KAAKC,YAAY;GAErB,OACE,IAAI,QAAQ,cACV,KAAKA,YAAY;QACZ,IAAI,QAAQ,aACjB,KAAKD,gBAAgB;EAG3B;EAGc,KAAA,cAAA,UAA+B;GAC3C,MAAM,QAAQ,KAAKE;GACnB,IAAI,MAAM,QAAQ,YAAY,CAAC,OAAO,QACpC;GACF,MAAM,eAAe;GACrB,MAAM,YAAY,MAAM;GACxB,KAAKC,WAAW;GAChB,KAAKC,SAAS,SAAS;EACzB;EAYY,KAAA,YAAA,UAA4B;GACtC,IAAI,CAAC,KAAK,YACR;GACF,MAAM,KAAK,KAAKC;GAChB,IAAI,CAAC,IACH;GAEF,IAAI,CAAC,KAAKN,aAAa;IACrB,IAAI,MAAM,WAAW,KAAK,GAAG,eAAe,GAAG,aAC7C;IACF,GAAG,aAAa,GAAG,aAAa,MAAM;IACtC,MAAM,eAAe;GACvB,OAAO;IACL,IAAI,MAAM,WAAW,KAAK,GAAG,gBAAgB,GAAG,cAC9C;IACF,GAAG,YAAY,GAAG,YAAY,MAAM;IACpC,MAAM,eAAe;GACvB;EACF;EAwEgB,KAAA,gBAAA,UAAsB;GACpC,IAAI,KAAKO,oBAAoB;IAC3B,KAAKA,qBAAqB;IAC1B,MAAM,eAAe;IACrB,MAAM,gBAAgB;IACtB;GACF;GAEA,KAAK,MAAM;GACX,MAAM,IAAK,MAAM,OAAuB,QAAQ,oBAAoB;GACpE,IAAI,CAAC,GACH;GACF,MAAM,WAAW,KAAK,mBAAmB;GACzC,KAAK,cAAc,CAAC;GAEpB,MAAM,QAAQ,EAAE,aAAa,KAAK;GAClC,MAAM,aAAa,UAAU;GAC7B,KAAK,cAAc,IAAI,YAAiC,UAAU;IAChE,SAAS;IACT,QAAQ;KACN,UAAU;KACV,UAAU,EAAE;KACZ,KAAK,SAAS;IAChB;GACF,CAAC,CAAC;EACJ;EA4BkB,KAAA,kBAAA,UAA8B;GAC9C,IAAI,KAAK,aAAa,WACpB;GACF,IAAI,MAAM,WAAW,GACnB;GACF,MAAM,SAAS,KAAKC,gBAAgB,KAAK;GACzC,IAAI,CAAC,QACH;GAEF,MAAM,YAAY,KAAKX,OAAO,QAAQ,MAAM;GAC5C,IAAI,YAAY,GACd;GASF,KAAKM,aAAa;IAChB,WAAW,MAAM;IACjB,QAAQ;IACR;IACA,QAAQ,MAAM;IACd,QAAQ,MAAM;IACd,QAAQ;IACR,OAAO;IACP,UAAU,KAAA;GACZ;GAIA,OAAO,iBAAiB,eAAe,KAAKM,cAAc;GAC1D,OAAO,iBAAiB,aAAa,KAAKC,YAAY;GACtD,OAAO,iBAAiB,iBAAiB,KAAKC,gBAAgB;EAChE;EAEkB,KAAA,kBAAA,UAA8B;GAC9C,MAAM,QAAQ,KAAKR;GACnB,IAAI,CAAC,SAAS,MAAM,cAAc,MAAM,WACtC;GAEF,MAAM,KAAK,MAAM,UAAU,MAAM;GACjC,MAAM,KAAK,MAAM,UAAU,MAAM;GACjC,MAAM,WAAW,KAAK,MAAM,IAAI,EAAE;GAElC,IAAI,CAAC,MAAM,QAAQ;IACjB,IAAI,WAAW,mBACb;IACF,KAAKS,WAAW,KAAK;GACvB;GAEA,MAAM,OAAO,KAAK,MAAM,SAAS,MAAM,OAAO;GAE9C,MAAM,MAAM,KAAKC,iBAAiB,MAAM,SAAS,MAAM,OAAO;GAC9D,IAAI,QAAQ,MAAM,UAAU;IAC1B,MAAM,WAAW;IACjB,KAAK,cAAc;GACrB;EACF;EAEgB,KAAA,gBAAA,UAA8B;GAC5C,MAAM,QAAQ,KAAKV;GACnB,IAAI,CAAC,SAAS,MAAM,cAAc,MAAM,WACtC;GAEF,IAAI,MAAM,QAAQ;IAChB,MAAM,MAAM,KAAKU,iBAAiB,MAAM,SAAS,MAAM,OAAO;IAC9D,KAAKC,YAAY,MAAM,QAAQ,MAAM,WAAW,GAAG;GACrD;GACA,KAAKT,SAAS,MAAM,SAAS;EAC/B;EAEoB,KAAA,oBAAA,UAA8B;GAChD,MAAM,QAAQ,KAAKF;GACnB,IAAI,CAAC,SAAS,MAAM,cAAc,MAAM,WACtC;GACF,KAAKC,WAAW;GAChB,KAAKC,SAAS,MAAM,SAAS;EAC/B;;CAzYA;CAGA;CAWA;CAEA,IAAIL,cAAuB;EACzB,OAAO,KAAK,gBAAgB,oBAAoB,KAAK,gBAAgB;CACvE;CAEA,IAAIe,kBAA0B;EAG5B,OAAO;GAFM,KAAK,aAAa,GAAG,KAAK,YAAY,eAAe,KAAK;GACrD,KAAK,aAAc,KAAKf,cAAc,kBAAkB,kBAAmB;GACpE,KAAK,aAAa,YAAY,YAAY;EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CACjG;CAEA,SAAkB;EAChB,MAAM,aAAa,KAAKgB,mBAAmB;EAC3C,OAAO,IAAI;wBACS,KAAK,YAAY;;;iBAGxB,KAAKC,SAAS;iBACd,KAAKC,aAAa;uBACZ,KAAKC,eAAe;mBACxB,KAAKC,WAAW;iBAClB,KAAKC,SAAS;;gBAEf,KAAKN,gBAAgB;;4BAET,KAAKO,cAAc;UACrC,aACE,IAAI,iCAAiC,WAAW,WAChD,QAAQ;;iCAEa,KAAK,YAAY;2CACP,KAAKC,qBAAqB;;;CAGnE;CAEA;CASA;CAoBA,eAAwB;EACtB,KAAK,eAAe,WAAW;GAC7B,IAAI,KAAK1B,OAAO,SAAS,GAAG;IAC1B,KAAKC,qBAAqB;IAC1B,KAAKC,gBAAgB;GACvB;GACA,KAAKwB,qBAAqB;EAC5B,CAAC;CACH;CAEA,QAAiB,mBAAyC;EACxD,MAAM,QAAQ,iBAAiB;EAC/B,KAAK,UAAU,OAAO,cAAc,KAAK,UAAU;EACnD,IAAI,kBAAkB,IAAI,UAAU,GAClC,KAAK,gBAAgB,aAAa,KAAK,aAAa,KAAK;EAE3D,IAAI,kBAAkB,IAAI,YAAY,GACpC,KAAKxB,gBAAgB;CAEzB;CAEA,kBAAkB;EAChB,KAAK,MAAM,QAAQ,KAAKF,QACtB,IAAI,KAAK,YACP,KAAK,aAAa,eAAe,EAAE;OAEnC,KAAK,gBAAgB,aAAa;CAGxC;CAEA,uBAAuB;EACrB,KAAK,MAAM,QAAQ,KAAKA,QAAQ;GAC9B,KAAK,MAAM,YAAY,4BAA4B,aAAa;GAChE,KAAK,MAAM,YAAY,yBAAyB,aAAa;GAC7D,KAAK,MAAM,YAAY,0BAA0B,aAAa;GAC9D,KAAK,MAAM,YAAY,2BAA2B,aAAa;GAE/D,IAAI,KAAK,aAAa,UAAU,GAAG;IACjC,IAAI,KAAK,gBAAgB,gBAAgB,CAAC,KAAK,MAC7C,KAAK,MAAM,YAAY,4BAA4B,eAAe;SAC7D,IAAI,KAAK,gBAAgB,gBAAgB,KAAK,MACnD,KAAK,MAAM,YAAY,yBAAyB,eAAe;SAC1D,IAAI,KAAKG,eAAe,CAAC,KAAK,MACnC,KAAK,MAAM,YAAY,2BAA2B,eAAe;SAC5D,IAAI,KAAKA,eAAe,KAAK,MAClC,KAAK,MAAM,YAAY,0BAA0B,eAAe;GAEpE;EACF;CACF;CAEA;CAkBA;;;;;;;;;;;CAoBA;CAoBA,qBAAqB;EACnB,KAAK,MAAM,MAAM,KAAKH,QACpB,IAAI,KAAK2B,YAAY,EAAE,GACrB,OAAO;EAIX,MAAM,OAAO,KAAK,YAAY,cAAc,MAAM;EAClD,IAAI,MAAM;GACR,MAAM,MAAO,KAAyB,iBAAiB,EAAE,SAAS,KAAK,CAAC;GACxE,KAAK,MAAM,MAAM,KACf,IAAI,KAAKA,YAAY,EAAiB,GACpC,OAAO;EAEb;CACF;CAEA,YAAY,IAAiB;EAE3B,IADU,GAAG,aAAa,UACtB,MAAM,MACR,OAAO;EACT,OAAQ,GAAG,aAAa,UAAU;CACpC;CAEA,cAAc,IAAiB;EAC7B,MAAM,WAAW,KAAK,mBAAmB;EACzC,IAAI,UAAU;GACZ,SAAS,gBAAgB,UAAU;GACnC,SAAS,MAAM,YAAY,4BAA4B,aAAa;GACpE,SAAS,MAAM,YAAY,yBAAyB,aAAa;GACjE,SAAS,MAAM,YAAY,0BAA0B,aAAa;GAClE,SAAS,MAAM,YAAY,2BAA2B,aAAa;EACrE;EAEA,GAAG,aAAa,YAAY,EAAE;EAE9B,IAAI,KAAK,gBAAgB,gBAAgB,CAAC,KAAK,MAC7C,GAAG,MAAM,YAAY,4BAA4B,eAAe;OAC3D,IAAI,KAAK,gBAAgB,gBAAgB,KAAK,MACnD,GAAG,MAAM,YAAY,yBAAyB,eAAe;OACxD,IAAI,KAAKxB,eAAe,CAAC,KAAK,MACnC,GAAG,MAAM,YAAY,2BAA2B,eAAe;OAC1D,IAAI,KAAKA,eAAe,KAAK,MAClC,GAAG,MAAM,YAAY,0BAA0B,eAAe;CAElE;CAEA,cAAc;EACZ,IAAI,QAAQ;EACZ,KAAK,MAAM,MAAM,KAAKH,QACpB,IAAI,KAAK2B,YAAY,EAAE,KAAK,CAAC,OAC3B,QAAQ;OACH,IAAI,OAAO;GAChB,KAAK,cAAc,EAAE;GACrB;EACF;CAEJ;CAEA,kBAAkB;EAChB,IAAI;EACJ,KAAK,MAAM,MAAM,KAAK3B,QACpB,IAAI,KAAK2B,YAAY,EAAE,KAAK,MAC1B,KAAK,cAAc,IAAI;OAEvB,OAAO;CAGb;CAEA;;;;;;CAkCA,gBAAgB,OAAgD;EAC9D,IAAI,KAAK,aAAa,OACpB,OAAO;EAET,MAAM,OAAO,MAAM,aAAa;EAChC,IAAI,OAAkC;EACtC,KAAK,MAAM,QAAQ,MAAM;GACvB,IAAI,EAAE,gBAAgB,cACpB;GACF,IAAI,KAAK,UAAU,SAAS,WAAW,KAAK,KAAK,UAAU,SAAS,SAAS,GAC3E,OAAO;GAET,IAAI,CAAC,QAAQ,KAAK,YAAY,sBAC5B,OAAO;EAEX;EACA,OAAO;CACT;CAEA;CAsCA;CAwBA;CAYA;CAQA,WAAW,OAA2B;EACpC,MAAM,QAAQ,KAAKrB;EACnB,IAAI,CAAC,SAAS,MAAM,QAClB;EAIF,IAAI;GACF,KAAKG,cAAc,kBAAkB,MAAM,SAAS;EACtD,QAAQ,CAGR;EAEA,MAAM,SAAS;EACf,MAAM,OAAO,aAAa,eAAe,EAAE;EAE3C,MAAM,QAAQ,KAAKmB,aAAa,MAAM,MAAM;EAC5C,IAAI,MAAM,OACR,MAAM,MAAM,KAAK,MAAM,SAAS,MAAM,OAAO;CAEjD;CAEA,aAAmB;EACjB,MAAM,QAAQ,KAAKtB;EACnB,IAAI,CAAC,OACH;EACF,MAAM,OAAO,gBAAgB,aAAa;EAC1C,IAAI,MAAM,aAAa,KAAA,GAAW;GAChC,MAAM,WAAW,KAAA;GACjB,KAAK,cAAc;EACrB;CAGF;CAEA,SAAS,WAAyB;EAChC,MAAM,QAAQ,KAAKA;EACnB,IAAI,CAAC,OACH;EAEF,MAAM,OAAO,QAAQ;EACrB,MAAM,QAAQ;EACd,KAAKA,aAAa;EAElB,OAAO,oBAAoB,eAAe,KAAKM,cAAc;EAC7D,OAAO,oBAAoB,aAAa,KAAKC,YAAY;EACzD,OAAO,oBAAoB,iBAAiB,KAAKC,gBAAgB;EAEjE,IAAI;GACF,KAAKL,cAAc,sBAAsB,SAAS;EACpD,QAAQ,CAAyB;EAMjC,KAAK,cAAc;CACrB;CAEA,YAAY,QAA4B,WAAmB,UAAoC;EAC7F,OAAO,gBAAgB,aAAa;EAMpC,MAAM,WAAW,KAAKT,OAAO,QAAO,OAAM,OAAO,MAAM;EACvD,MAAM,SAAS,aAAa,KAAA,IACxB,SAAS,SACT,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,SAAS,MAAM,CAAC;EAEnD,MAAM,SAAS,OAAO;EACtB,IAAI,CAAC,QACH;EAEF,MAAM,MAAM,SAAS,WAAW;EAChC,OAAO,aAAa,QAAQ,GAAG;EAE/B,MAAM,UAAU,MAAM,UAAU,QAAQ,KAAK,OAAO,UAAU,MAAM;EACpE,IAAI,YAAY,WAGd;EAKF,KAAKA,UAAU,KAAK,YAAY,cAAc,MAAM,EAAA,EAChD,iBAAiB,EAAE,SAAS,KAAK,CAAC,KAA6B,CAAC;EACpE,KAAKC,qBAAqB;EAK1B,KAAKS,qBAAqB;EAE1B,KAAK,cAAc,IAAI,YAAkC,WAAW;GAClE,SAAS;GACT,QAAQ;IACN,IAAI,OAAO;IACX;IACA;GACF;EACF,CAAC,CAAC;CACJ;CAEA,aAAa,QAA8C;EACzD,MAAM,UAAU,SAAS,cAAc,MAAM;EAC7C,QAAQ,MAAM,UAAU;EACxB,QAAQ,MAAM,aAAa;EAC3B,QAAQ,MAAM,MAAM;EACpB,QAAQ,MAAM,WAAW;EAEzB,MAAM,WAAW,OAAO;EACxB,IAAI,UAAU;GACZ,MAAM,OAAO,SAAS,cAAc,WAAW;GAC/C,KAAK,OAAO;GACZ,QAAQ,YAAY,IAAI;EAC1B;EAMA,MAAM,QAAQ,SAAS,cAAc,MAAM;EAC3C,MAAM,eAAe,OAAO,eAAe,GAAA,CAAI,KAAK;EACpD,MAAM,MAAM,WAAW;EACvB,MAAM,MAAM,eAAe;EAC3B,MAAM,MAAM,aAAa;EACzB,QAAQ,YAAY,KAAK;EAEzB,IAAI;GACF,OAAO,gBAAgB;IAAE,QAAQ;IAAQ;GAAQ,CAAC;EACpD,QAAQ;GACN,OAAO;EACT;CACF;;;;;;;;CASA,iBAAiB,SAAiB,SAAqC;EACrE,MAAM,QAAQ,KAAKJ;EACnB,IAAI,CAAC,OACH,OAAO,KAAA;EACT,MAAM,WAAW,KAAKN,OAAO,QAAO,OAAM,OAAO,MAAM,MAAM;EAC7D,IAAI,SAAS,WAAW,GACtB,OAAO;EAET,MAAM,OAAO,CAAC,KAAKG;EAEnB,IAAI,UAAU;EACd,IAAI,WAAW;EAMf,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GACxC,MAAM,OAAO,SAAS,EAAE,CAAC,sBAAsB;GAC/C,MAAM,QAAQ,OAAO,KAAK,OAAO,KAAK;GACtC,MAAM,MAAM,OAAO,KAAK,QAAQ,KAAK;GACrC,MAAM,OAAO,QAAQ,OAAO;GAC5B,MAAM,MAAM,OAAO,UAAU;GAI7B,MAAM,SAAS,KAAK,IAAI,MAAM,KAAK;GACtB,KAAK,IAAI,MAAM,GAAG;GAC/B,MAAM,OAAO,KAAK,IAAI,MAAM,GAAG;GAK/B,IADqB,MAAM,KAGrB;QAAA,SAAS,UAAU;KACrB,WAAW;KACX,UAAU;IACZ;UAGA,IAAI,OAAO,UAAU;IACnB,WAAW;IACX,UAAU,IAAI;GAChB;EAKJ;EAEA,OAAO;CACT;CAEA,qBAAyC;EACvC,MAAM,QAAQ,KAAKG;EACnB,IAAI,CAAC,OAAO,UAAU,MAAM,aAAa,KAAA,GACvC,OAAO,KAAA;EAET,MAAM,WAAW,KAAKN,OAAO,QAAO,OAAM,OAAO,MAAM,MAAM;EAC7D,IAAI,SAAS,WAAW,GACtB,OAAO,KAAA;EAET,MAAM,OAAO,CAAC,KAAKG;EACnB,MAAM,gBAAgB,KAAKM,cAAc,sBAAsB;EAC/D,IAAI,CAAC,eACH,OAAO,KAAA;EAET,MAAM,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,UAAU,SAAS,MAAM,CAAC;EACjE,IAAI,OAAuB;EAC3B,IAAI,MAAM,SAAS,QACjB,OAAO,SAAS,IAAI,CAAC,sBAAsB;OAI3C,OADa,SAAS,SAAS,SAAS,EAAE,CAAC,sBACjC;EAGZ,IAAI,MAAM;GACR,MAAM,KAAK,MAAM,SAAS,SAAS,KAAK,OAAO,KAAK,SAAS,cAAc;GAC3E,MAAM,IAAI;GACV,MAAM,IAAI,cAAc;GACxB,MAAM,IAAI;GACV,OAAO,wBAAwB,IAAI,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE;EACnF,OAAO;GACL,MAAM,KAAK,MAAM,SAAS,SAAS,KAAK,MAAM,KAAK,UAAU,cAAc;GAC3E,MAAM,IAAI;GACV,MAAM,IAAI,cAAc;GACxB,MAAM,IAAI;GACV,OAAO,wBAAwB,EAAE,MAAM,IAAI,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE;EACnF;CACF;CAEA,IAAIA,eAAmC;EACrC,OAAO,KAAK,YAAY,eAAe,WAAW,KAAK;CACzD;;EAEgB,KAAA,SAAA;GAAC;GAAgB,iBAAiB,GAAG;GAAG,iBAAiB,GAAG;GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsKjF;;AACH;AAvzBG,WAAA,CAAA,SAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,eAAA,WAAA,eAAA,KAAA,CAAA;AAGzB,WAAA,CAAA,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,GAAA,eAAA,WAAA,QAAA,KAAA,CAAA;AAG1B,WAAA,CAAA,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,GAAA,eAAA,WAAA,cAAA,KAAA,CAAA;AAG1B,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,WAAW;AAAc,CAAC,CAAA,GAAA,eAAA,WAAA,cAAA,KAAA,CAAA;AAGpD,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,eAAA,WAAA,UAAA,KAAA,CAAA;AAGzC,WAAA,CAAA,SAAS;CAAE,MAAM;CAAQ,WAAW;AAAY,CAAC,CAAA,GAAA,eAAA,WAAA,YAAA,KAAA,CAAA;AAjBnDoB,iBAAAA,WAAAA,CAAAA,kBAAc,eAAe,CAAA,GAAA,cAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./icon-
|
|
1
|
+
import "./icon-CDGprSdE.js";
|
|
2
2
|
import { LitElement } from "lit";
|
|
3
3
|
//#region src/titlebar/titlebar.d.ts
|
|
4
4
|
type TitlebarOrientation = `horizontal` | `vertical`;
|
|
@@ -47,4 +47,4 @@ interface TitlebarElement {
|
|
|
47
47
|
}
|
|
48
48
|
//#endregion
|
|
49
49
|
export { TitlebarToggleDetail as a, TitlebarVariant as c, TitlebarOrientation as i, TitlebarElement as n, TitlebarToggleEvent as o, TitlebarElementEventMap as r, TitlebarToggleInteraction as s, TitlebarCloseEvent as t };
|
|
50
|
-
//# sourceMappingURL=titlebar-
|
|
50
|
+
//# sourceMappingURL=titlebar-Bj5pfdw_.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"titlebar-
|
|
1
|
+
{"version":3,"file":"titlebar-Bj5pfdw_.d.ts","names":[],"sources":["../src/titlebar/titlebar.ts"],"mappings":";;;KAOY;KACA;KACA;UAEK;WACN;;KAGC,sBAAsB,YAAY;KAClC,qBAAqB;UAEhB;EACf,QAAQ;EACR,OAAO;;;;;;;;;;cAYI,wBAAwB;EACP;EACwB;EACiB,aAAa;EACjB,SAAS;EAC7C;;EAEe;EACA;EACiB,mBAAmB;UAExE;UAaA;UASA;YAIW,wBAAM;SAoDT,sBAAM;;QAmNhB;YACI;IACR,iBAAiB;;;UAIJ;EACf,oBAAoB,gBAAgB,yBAClC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB"}
|
package/dist/titlebar.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TitlebarToggleDetail, c as TitlebarVariant, i as TitlebarOrientation, n as TitlebarElement, o as TitlebarToggleEvent, r as TitlebarElementEventMap, s as TitlebarToggleInteraction, t as TitlebarCloseEvent } from "./titlebar-
|
|
1
|
+
import { a as TitlebarToggleDetail, c as TitlebarVariant, i as TitlebarOrientation, n as TitlebarElement, o as TitlebarToggleEvent, r as TitlebarElementEventMap, s as TitlebarToggleInteraction, t as TitlebarCloseEvent } from "./titlebar-Bj5pfdw_.js";
|
|
2
2
|
export { TitlebarCloseEvent, TitlebarElement, TitlebarElementEventMap, TitlebarOrientation, TitlebarToggleDetail, TitlebarToggleEvent, TitlebarToggleInteraction, TitlebarVariant };
|
package/dist/titlebar.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
|
|
2
2
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
3
|
-
import "./icon-
|
|
3
|
+
import "./icon-DcEEGQa_.js";
|
|
4
4
|
import { LitElement, css, html, nothing } from "lit";
|
|
5
5
|
import { property } from "lit/decorators.js";
|
|
6
6
|
//#region src/titlebar/titlebar.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip-BlvBUQxx.d.ts","names":[],"sources":["../src/util/tooltip.ts"],"mappings":";;KAQY,uBAAuB;KACvB;cAoCC,uBAAuB;;EACzB;SAKF,kBAAmB;SAEnB,kBAAkB;EAYzB,oBAAoB;EAGpB,aAAa;EAGb;EAGA;EAGA;
|
|
1
|
+
{"version":3,"file":"tooltip-BlvBUQxx.d.ts","names":[],"sources":["../src/util/tooltip.ts"],"mappings":";;KAQY,uBAAuB;KACvB;cAoCC,uBAAuB;;EACzB;SAKF,kBAAmB;SAEnB,kBAAkB;EAYzB,oBAAoB;EAGpB,aAAa;EAGb;EAGA;EAGA;YAgBU,wBAAM;YA+BN;;QAKJ;YACI;IACR,gBAAgB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
//#region src/mixins/wheel-nudge.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Direction of a wheel tick. `+1` for `deltaY < 0` (wheel up/away), `-1` for
|
|
5
|
+
* `deltaY > 0` (wheel down/toward).
|
|
6
|
+
*/
|
|
7
|
+
type WheelDirection = 1 | -1;
|
|
8
|
+
/**
|
|
9
|
+
* Abstract surface a consumer of {@link WheelNudgeMixin} may override.
|
|
10
|
+
*
|
|
11
|
+
* `_applyWheelDelta` is called once per handled wheel tick. The consumer is
|
|
12
|
+
* expected to reuse its existing arrow-key step math (typically a shared
|
|
13
|
+
* `_stepByDelta(direction, effectiveStep)` private method) and call it here.
|
|
14
|
+
* The mixin ships a no-op default so `override` in a consumer always has a
|
|
15
|
+
* base member to attach to.
|
|
16
|
+
*
|
|
17
|
+
* `_shouldHandleWheel` may be overridden to restrict when the wheel acts
|
|
18
|
+
* (e.g. editable-number rejects while the user is typing).
|
|
19
|
+
*
|
|
20
|
+
* Both are declared here as methods (not arrow-function properties) so a
|
|
21
|
+
* consumer's `override _applyWheelDelta() {}` stays method-compatible with
|
|
22
|
+
* the base — see the `ts/method-signature-style` override in `eslint.config.js`,
|
|
23
|
+
* which stops the linter rewriting these back to property signatures.
|
|
24
|
+
*/
|
|
25
|
+
interface WheelNudgeConsumer {
|
|
26
|
+
_applyWheelDelta(direction: WheelDirection, event: WheelEvent): void;
|
|
27
|
+
_shouldHandleWheel(): boolean;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { WheelNudgeConsumer as n, WheelDirection as t };
|
|
31
|
+
//# sourceMappingURL=wheel-nudge-By5s_ioH.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wheel-nudge-By5s_ioH.d.ts","names":[],"sources":["../src/mixins/wheel-nudge.ts"],"mappings":";;;;;;KASY;;;;;;;;;;;;;;;;;;UAmBK;EACf,iBAAiB,WAAW,gBAAgB,OAAO;EACnD"}
|
|
@@ -73,6 +73,11 @@ function WheelNudgeMixin(superClass) {
|
|
|
73
73
|
if (root && root.activeElement !== null) return true;
|
|
74
74
|
return false;
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Apply one wheel tick. No-op by default — consumers override this to run
|
|
78
|
+
* their arrow-key step math (see {@link WheelNudgeConsumer}).
|
|
79
|
+
*/
|
|
80
|
+
_applyWheelDelta(_direction, _event) {}
|
|
76
81
|
}
|
|
77
82
|
__decorate([property({
|
|
78
83
|
type: Boolean,
|
|
@@ -83,4 +88,4 @@ function WheelNudgeMixin(superClass) {
|
|
|
83
88
|
//#endregion
|
|
84
89
|
export { WheelNudgeMixin as t };
|
|
85
90
|
|
|
86
|
-
//# sourceMappingURL=wheel-nudge-
|
|
91
|
+
//# sourceMappingURL=wheel-nudge-D5rmht3v.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wheel-nudge-D5rmht3v.js","names":[],"sources":["../src/mixins/wheel-nudge.ts"],"sourcesContent":["import type { LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\n\ntype Constructor<T = object> = new (...args: any[]) => T;\n\n/**\n * Direction of a wheel tick. `+1` for `deltaY < 0` (wheel up/away), `-1` for\n * `deltaY > 0` (wheel down/toward).\n */\nexport type WheelDirection = 1 | -1;\n\n/**\n * Abstract surface a consumer of {@link WheelNudgeMixin} may override.\n *\n * `_applyWheelDelta` is called once per handled wheel tick. The consumer is\n * expected to reuse its existing arrow-key step math (typically a shared\n * `_stepByDelta(direction, effectiveStep)` private method) and call it here.\n * The mixin ships a no-op default so `override` in a consumer always has a\n * base member to attach to.\n *\n * `_shouldHandleWheel` may be overridden to restrict when the wheel acts\n * (e.g. editable-number rejects while the user is typing).\n *\n * Both are declared here as methods (not arrow-function properties) so a\n * consumer's `override _applyWheelDelta() {}` stays method-compatible with\n * the base — see the `ts/method-signature-style` override in `eslint.config.js`,\n * which stops the linter rewriting these back to property signatures.\n */\nexport interface WheelNudgeConsumer {\n _applyWheelDelta(direction: WheelDirection, event: WheelEvent): void;\n _shouldHandleWheel(): boolean;\n}\n\n/**\n * Mixin that adds mousewheel support with an optional `lighttouch` hover mode.\n *\n * Activation rule:\n * - If the host's `disabled` property is truthy → ignore.\n * - Otherwise, handle if EITHER:\n * • `lighttouch` is true AND the pointer is currently over the host, OR\n * • the host (or anything in its shadow tree) currently has focus.\n *\n * Direction convention: `deltaY < 0` (wheel up/away) → +1 step; `deltaY > 0` → -1 step.\n *\n * Consumers must implement `_applyWheelDelta(direction, event)` (see\n * {@link WheelNudgeConsumer}). The mixin calls `event.preventDefault()` only when\n * the activation rule accepts the event, so page scroll is suppressed during\n * interaction without blocking wheel events over empty space.\n *\n * Usage:\n *\n * ```ts\n * class MyInput extends WheelNudgeMixin(LitElement) {\n * protected _applyWheelDelta(direction, event) {\n * const step = resolveAxisStep(this.range, this.stops, this.step, event.shiftKey);\n * this._stepByDelta(direction, step);\n * }\n * }\n * ```\n */\nexport function WheelNudgeMixin<T extends Constructor<LitElement>>(superClass: T): T & Constructor<WheelNudgeConsumer> {\n class WheelNudgeMixinClass extends superClass implements WheelNudgeConsumer {\n /**\n * When true, the wheel adjusts the value simply when the pointer is hovering\n * over the host (no focus required). When false (default), the host must\n * have focus for the wheel to act.\n */\n @property({ type: Boolean, reflect: true })\n lighttouch = false;\n\n /**\n * Imperative hover flag — not Lit-reactive (avoids update churn for what\n * is purely an interaction-time predicate).\n */\n _isHovering = false;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`pointerenter`, this._onPointerEnter);\n this.addEventListener(`pointerleave`, this._onPointerLeave);\n this.addEventListener(`wheel`, this._onWheel, { passive: false });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`pointerenter`, this._onPointerEnter);\n this.removeEventListener(`pointerleave`, this._onPointerLeave);\n this.removeEventListener(`wheel`, this._onWheel);\n this._isHovering = false;\n }\n\n _onPointerEnter = (): void => {\n this._isHovering = true;\n };\n\n _onPointerLeave = (): void => {\n this._isHovering = false;\n };\n\n /**\n * Override to restrict when wheel is handled (e.g. editable-number rejects\n * while the user is typing). Default: respect `disabled`, then apply the\n * focus-or-lighttouch rule described on the mixin.\n */\n _shouldHandleWheel(): boolean {\n const anyThis = this as unknown as { disabled?: boolean };\n if (anyThis.disabled)\n return false;\n if (this.lighttouch && this._isHovering)\n return true;\n if (this.matches?.(`:focus, :focus-within`))\n return true;\n const root = this.renderRoot;\n if (root && (root as ShadowRoot).activeElement !== null)\n return true;\n return false;\n }\n\n /**\n * Apply one wheel tick. No-op by default — consumers override this to run\n * their arrow-key step math (see {@link WheelNudgeConsumer}).\n */\n _applyWheelDelta(_direction: WheelDirection, _event: WheelEvent): void {\n // Intentionally empty; overridden by consumers.\n }\n\n _onWheel = (event: WheelEvent): void => {\n if (!this._shouldHandleWheel())\n return;\n event.preventDefault();\n // Some browsers (notably when the user holds Shift) send `deltaY=0`\n // and route the scroll into `deltaX` instead. Use whichever axis\n // actually moved so the direction sign matches the user's intent.\n const delta = event.deltaY !== 0 ? event.deltaY : event.deltaX;\n const direction: WheelDirection = delta < 0 ? 1 : -1;\n this._applyWheelDelta(direction, event);\n };\n }\n return WheelNudgeMixinClass;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,gBAAmD,YAAoD;CACrH,MAAM,6BAA6B,WAAyC;;;GAO7D,KAAA,aAAA;GAMC,KAAA,cAAA;GAiBgB,KAAA,wBAAA;IAC5B,KAAK,cAAc;GACrB;GAE8B,KAAA,wBAAA;IAC5B,KAAK,cAAc;GACrB;GA6BY,KAAA,YAAA,UAA4B;IACtC,IAAI,CAAC,KAAK,mBAAmB,GAC3B;IACF,MAAM,eAAe;IAKrB,MAAM,aADQ,MAAM,WAAW,IAAI,MAAM,SAAS,MAAM,UACd,IAAI,IAAI;IAClD,KAAK,iBAAiB,WAAW,KAAK;GACxC;;EA5DA,oBAAmC;GACjC,MAAM,kBAAkB;GACxB,KAAK,iBAAiB,gBAAgB,KAAK,eAAe;GAC1D,KAAK,iBAAiB,gBAAgB,KAAK,eAAe;GAC1D,KAAK,iBAAiB,SAAS,KAAK,UAAU,EAAE,SAAS,MAAM,CAAC;EAClE;EAEA,uBAAsC;GACpC,MAAM,qBAAqB;GAC3B,KAAK,oBAAoB,gBAAgB,KAAK,eAAe;GAC7D,KAAK,oBAAoB,gBAAgB,KAAK,eAAe;GAC7D,KAAK,oBAAoB,SAAS,KAAK,QAAQ;GAC/C,KAAK,cAAc;EACrB;;;;;;EAeA,qBAA8B;GAE5B,IAAI,KAAQ,UACV,OAAO;GACT,IAAI,KAAK,cAAc,KAAK,aAC1B,OAAO;GACT,IAAI,KAAK,UAAU,uBAAuB,GACxC,OAAO;GACT,MAAM,OAAO,KAAK;GAClB,IAAI,QAAS,KAAoB,kBAAkB,MACjD,OAAO;GACT,OAAO;EACT;;;;;EAMA,iBAAiB,YAA4B,QAA0B,CAEvE;CAaF;CAtEG,WAAA,CAAA,SAAS;EAAE,MAAM;EAAS,SAAS;CAAK,CAAC,CAAA,GAAA,qBAAA,WAAA,cAAA,KAAA,CAAA;CAuE5C,OAAO;AACT"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
2
|
-
import {
|
|
2
|
+
import { i as hasIcon } from "./registry-BEtb8_wB.js";
|
|
3
3
|
import "./icons.js";
|
|
4
4
|
import { LitElement, css, html, nothing, svg } from "lit";
|
|
5
5
|
import { property, state } from "lit/decorators.js";
|
|
@@ -309,7 +309,7 @@ let TooltipElement = class TooltipElement extends LitElement {
|
|
|
309
309
|
#renderIcon() {
|
|
310
310
|
if (!this.icon) return nothing;
|
|
311
311
|
if (this.icon.startsWith(`<svg`)) return html`<span class="tooltip-icon" style="display:inline-flex;align-items:center;margin-right:0.25em">${unsafeHTML(this.icon)}</span>`;
|
|
312
|
-
if (!
|
|
312
|
+
if (!hasIcon(this.icon)) return nothing;
|
|
313
313
|
return html`<ixfx-icon class="tooltip-icon" style="margin-right:0.25em" name="${this.icon}"></ixfx-icon>`;
|
|
314
314
|
}
|
|
315
315
|
render() {
|
|
@@ -1846,4 +1846,4 @@ PlotXyAxis = __decorate([safeCustomElement(`ixfx-plot-xy-axis`)], PlotXyAxis);
|
|
|
1846
1846
|
//#endregion
|
|
1847
1847
|
export { TooltipElement as a, computeColour as c, PlotMultiAxis as i, parseColourScaleAttr as l, PlotSingleAxis as n, PlotDataSeries as o, PlotHistogram as r, applyAgeModification as s, PlotXyAxis as t, readBaseColour as u };
|
|
1848
1848
|
|
|
1849
|
-
//# sourceMappingURL=xy-axis-
|
|
1849
|
+
//# sourceMappingURL=xy-axis-DWizs0bt.js.map
|