@ixfx/components 0.9.6 → 0.9.8
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 +100 -64
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +382 -253
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +2 -2
- package/dist/ac-text.js +2 -2
- package/dist/ac-token.js +2 -2
- package/dist/checkbox.js +1 -1
- package/dist/{colour-picker-CSxwUmtE.js → colour-picker-R73i0QTP.js} +2 -2
- package/dist/{colour-picker-CSxwUmtE.js.map → colour-picker-R73i0QTP.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.js +2 -2
- package/dist/data-display.js +1 -1
- package/dist/{data-grid-DIHhfsqS.d.ts → data-grid-BUeZjnvj.d.ts} +38 -1
- package/dist/data-grid-BUeZjnvj.d.ts.map +1 -0
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +156 -26
- package/dist/data-grid.js.map +1 -1
- package/dist/detail-list.js +2 -2
- package/dist/editable-label.js +1 -1
- package/dist/{fallbacks-BcKGq-2F.js → fallbacks-DQ_5OsmR.js} +2 -2
- package/dist/{fallbacks-BcKGq-2F.js.map → fallbacks-DQ_5OsmR.js.map} +1 -1
- package/dist/{grid-list-mL0GJTQR.js → grid-list-40blkeza.js} +5 -232
- package/dist/grid-list-40blkeza.js.map +1 -0
- package/dist/{grid-list-CSw1VMXT.d.ts → grid-list-lTwg4lp7.d.ts} +3 -66
- package/dist/grid-list-lTwg4lp7.d.ts.map +1 -0
- package/dist/grid-list.d.ts +1 -1
- package/dist/grid-list.js +1 -1
- package/dist/{icon-Dy33gu4Z.js → icon-BCJJYEpm.js} +2 -2
- package/dist/{icon-Dy33gu4Z.js.map → icon-BCJJYEpm.js.map} +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/labelled-radial-input.js +2 -2
- package/dist/{labelled-slider-input-aEYDvW2S.js → labelled-slider-input-CF2RtzgG.js} +3 -3
- package/dist/{labelled-slider-input-aEYDvW2S.js.map → labelled-slider-input-CF2RtzgG.js.map} +1 -1
- package/dist/labelled-slider-input.js +1 -1
- package/dist/{menu-CMXhIaNZ.js → menu-C8a-84S5.js} +4 -4
- package/dist/{menu-CMXhIaNZ.js.map → menu-C8a-84S5.js.map} +1 -1
- package/dist/{menu-item-BYGQzyCe.js → menu-item-DzizkMH-.js} +3 -3
- package/dist/{menu-item-BYGQzyCe.js.map → menu-item-DzizkMH-.js.map} +1 -1
- package/dist/menu.js +2 -2
- package/dist/miller.js +1 -1
- package/dist/narrowed-text.js +1 -1
- package/dist/notifier.js +1 -1
- package/dist/pan-text-CoYmt2qd.d.ts +67 -0
- package/dist/pan-text-CoYmt2qd.d.ts.map +1 -0
- package/dist/pan-text-CqtvjPyK.js +235 -0
- package/dist/pan-text-CqtvjPyK.js.map +1 -0
- package/dist/panel.js +1 -1
- package/dist/polar-pad.js +1 -1
- package/dist/{radial-input-DyxfbNzD.js → radial-input-KMVltQfe.js} +2 -2
- package/dist/{radial-input-DyxfbNzD.js.map → radial-input-KMVltQfe.js.map} +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.js +1 -1
- package/dist/range.js +1 -1
- package/dist/select-horiz.js +1 -1
- package/dist/{slider-input-Cb5uSV42.js → slider-input-ByHdotzp.js} +2 -2
- package/dist/{slider-input-Cb5uSV42.js.map → slider-input-ByHdotzp.js.map} +1 -1
- package/dist/slider-input.js +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/{split-layout-Bx0g8k8-.js → split-layout-3yBOEVZW.js} +2 -2
- package/dist/{split-layout-Bx0g8k8-.js.map → split-layout-3yBOEVZW.js.map} +1 -1
- package/dist/split-layout.js +1 -1
- package/dist/style.css +2 -2
- package/dist/swipe.js +1 -1
- package/dist/tabs.js +1 -1
- package/dist/{timeline-THyvH8xy.js → timeline-CFlBFFGZ.js} +2 -2
- package/dist/{timeline-THyvH8xy.js.map → timeline-CFlBFFGZ.js.map} +1 -1
- package/dist/timeline.js +1 -1
- package/dist/titlebar.js +2 -2
- package/dist/{tree-DAFBO_MF.js → tree-CVj7TIk2.js} +2 -2
- package/dist/{tree-DAFBO_MF.js.map → tree-CVj7TIk2.js.map} +1 -1
- package/dist/tree.js +1 -1
- package/dist/vertical-list.js +1 -1
- package/dist/xy-pad.js +1 -1
- package/docs-user/data-grid.md +59 -0
- package/docs-user/index.json +2 -2
- package/package.json +1 -1
- package/dist/data-grid-DIHhfsqS.d.ts.map +0 -1
- package/dist/grid-list-CSw1VMXT.d.ts.map +0 -1
- package/dist/grid-list-mL0GJTQR.js.map +0 -1
package/bundle/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import { Colour } from "@ixfx/visual";
|
|
|
8
8
|
import { Trees } from "@ixfx/collections";
|
|
9
9
|
import { clamp, clamper, rangeStream, round, scaler } from "@ixfx/numbers";
|
|
10
10
|
import { repeat } from "lit/directives/repeat.js";
|
|
11
|
-
import { createRef, ref } from "lit/directives/ref.js";
|
|
12
11
|
import { classMap } from "lit/directives/class-map.js";
|
|
12
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
13
13
|
import { Easings } from "@ixfx/modulation";
|
|
14
14
|
import "@clinth/vcanvas";
|
|
15
15
|
import { keyed } from "lit/directives/keyed.js";
|
|
@@ -1344,7 +1344,7 @@ const _themeFallbacksCss = i$3`
|
|
|
1344
1344
|
@property --item-border-tickled {
|
|
1345
1345
|
syntax: '*';
|
|
1346
1346
|
inherits: true;
|
|
1347
|
-
initial-value: 1px solid
|
|
1347
|
+
initial-value: 1px solid oklch(19% 0.02 240);
|
|
1348
1348
|
}
|
|
1349
1349
|
@property --item-border-selected {
|
|
1350
1350
|
syntax: '*';
|
|
@@ -13900,6 +13900,233 @@ var menu_exports = /* @__PURE__ */ __exportAll({
|
|
|
13900
13900
|
menuFromTreeToElements: () => menuFromTreeToElements
|
|
13901
13901
|
});
|
|
13902
13902
|
//#endregion
|
|
13903
|
+
//#region src/pan-text/pan-text.ts
|
|
13904
|
+
const SPEED = 45;
|
|
13905
|
+
const END_PADDING = 4;
|
|
13906
|
+
const START_DELAY = 300;
|
|
13907
|
+
const END_DWELL = 2e3;
|
|
13908
|
+
const RESET_DURATION = 400;
|
|
13909
|
+
const PAN_EASING = `cubic-bezier(0.25, 0.46, 0.45, 0.94)`;
|
|
13910
|
+
let PanTextElement = class PanTextElement extends i {
|
|
13911
|
+
constructor(..._args) {
|
|
13912
|
+
super(..._args);
|
|
13913
|
+
this.direction = `end`;
|
|
13914
|
+
this.disabled = false;
|
|
13915
|
+
this.mode = `hover`;
|
|
13916
|
+
this._isOverflowing = false;
|
|
13917
|
+
this._isHovering = false;
|
|
13918
|
+
this._loopActive = false;
|
|
13919
|
+
this._loopAtEnd = false;
|
|
13920
|
+
this._overflow = 0;
|
|
13921
|
+
this._resizeObserver = null;
|
|
13922
|
+
this._loopTimer = 0;
|
|
13923
|
+
this._onMouseEnter = () => {
|
|
13924
|
+
this._isHovering = true;
|
|
13925
|
+
};
|
|
13926
|
+
this._onMouseLeave = () => {
|
|
13927
|
+
this._isHovering = false;
|
|
13928
|
+
};
|
|
13929
|
+
this._measure = () => {
|
|
13930
|
+
if (this._isHovering || this._loopAtEnd) return;
|
|
13931
|
+
const el = this._textEl;
|
|
13932
|
+
if (!el) return;
|
|
13933
|
+
this._overflow = Math.max(0, el.scrollWidth - el.clientWidth);
|
|
13934
|
+
const overflowing = this._overflow > 0;
|
|
13935
|
+
this.classList.toggle(`is-overflowing`, overflowing);
|
|
13936
|
+
if (overflowing !== this._isOverflowing) this._isOverflowing = overflowing;
|
|
13937
|
+
if (this._loopActive && this.mode === `loop` && !this.disabled && overflowing && this._loopTimer === 0) this._scheduleLoopPan(START_DELAY);
|
|
13938
|
+
if (!overflowing && this._loopAtEnd) {
|
|
13939
|
+
this._loopAtEnd = false;
|
|
13940
|
+
this.requestUpdate();
|
|
13941
|
+
}
|
|
13942
|
+
};
|
|
13943
|
+
}
|
|
13944
|
+
connectedCallback() {
|
|
13945
|
+
super.connectedCallback();
|
|
13946
|
+
this._resizeObserver = new ResizeObserver(() => this._measure());
|
|
13947
|
+
this.addEventListener(`mouseenter`, this._onMouseEnter);
|
|
13948
|
+
this.addEventListener(`mouseleave`, this._onMouseLeave);
|
|
13949
|
+
}
|
|
13950
|
+
disconnectedCallback() {
|
|
13951
|
+
super.disconnectedCallback();
|
|
13952
|
+
this._clearLoopTimer();
|
|
13953
|
+
this._loopActive = false;
|
|
13954
|
+
this._loopAtEnd = false;
|
|
13955
|
+
this._resizeObserver?.disconnect();
|
|
13956
|
+
this._resizeObserver = null;
|
|
13957
|
+
this.removeEventListener(`mouseenter`, this._onMouseEnter);
|
|
13958
|
+
this.removeEventListener(`mouseleave`, this._onMouseLeave);
|
|
13959
|
+
}
|
|
13960
|
+
firstUpdated() {
|
|
13961
|
+
this._measure();
|
|
13962
|
+
this._resizeObserver?.observe(this);
|
|
13963
|
+
document.fonts?.ready.then(() => this._measure());
|
|
13964
|
+
if (this.mode === `loop`) this.startLoop();
|
|
13965
|
+
}
|
|
13966
|
+
updated(changed) {
|
|
13967
|
+
if (changed.has(`mode`)) {
|
|
13968
|
+
if (this.mode === `loop`) this.startLoop();
|
|
13969
|
+
else this.stopLoop();
|
|
13970
|
+
}
|
|
13971
|
+
if (changed.has(`disabled`) && this.disabled) this.stopLoop();
|
|
13972
|
+
this._measure();
|
|
13973
|
+
}
|
|
13974
|
+
/**
|
|
13975
|
+
* Whether a loop pan is currently active (between `startLoop()` and `stopLoop()`).
|
|
13976
|
+
*/
|
|
13977
|
+
get looping() {
|
|
13978
|
+
return this._loopActive;
|
|
13979
|
+
}
|
|
13980
|
+
/**
|
|
13981
|
+
* Begin looping: pan to the end, dwell there for 2 seconds, reset to the
|
|
13982
|
+
* start and pan again, repeating until `stopLoop()` is called. A no-op when
|
|
13983
|
+
* `disabled`, when there is nothing to reveal, or under reduced-motion.
|
|
13984
|
+
*/
|
|
13985
|
+
startLoop() {
|
|
13986
|
+
if (this.disabled || this._prefersReducedMotion()) return;
|
|
13987
|
+
this._loopActive = true;
|
|
13988
|
+
this._loopAtEnd = false;
|
|
13989
|
+
this.requestUpdate();
|
|
13990
|
+
if (this._isOverflowing && this._loopTimer === 0) this._scheduleLoopPan(START_DELAY);
|
|
13991
|
+
}
|
|
13992
|
+
/**
|
|
13993
|
+
* Stop a loop started with `startLoop()` and snap back to the rest position.
|
|
13994
|
+
*/
|
|
13995
|
+
stopLoop() {
|
|
13996
|
+
if (!this._loopActive && !this._loopAtEnd && this._loopTimer === 0) return;
|
|
13997
|
+
this._clearLoopTimer();
|
|
13998
|
+
this._loopActive = false;
|
|
13999
|
+
this._loopAtEnd = false;
|
|
14000
|
+
this.requestUpdate();
|
|
14001
|
+
}
|
|
14002
|
+
_prefersReducedMotion() {
|
|
14003
|
+
return globalThis.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches ?? false;
|
|
14004
|
+
}
|
|
14005
|
+
_panDuration() {
|
|
14006
|
+
return Math.max(1.5, (this._overflow + END_PADDING) / SPEED);
|
|
14007
|
+
}
|
|
14008
|
+
_clearLoopTimer() {
|
|
14009
|
+
if (this._loopTimer !== 0) {
|
|
14010
|
+
clearTimeout(this._loopTimer);
|
|
14011
|
+
this._loopTimer = 0;
|
|
14012
|
+
}
|
|
14013
|
+
}
|
|
14014
|
+
_scheduleLoopPan(delay) {
|
|
14015
|
+
this._clearLoopTimer();
|
|
14016
|
+
this._loopTimer = window.setTimeout(() => {
|
|
14017
|
+
this._loopTimer = 0;
|
|
14018
|
+
if (!this._loopActive || this.disabled || !this._isOverflowing) return;
|
|
14019
|
+
this._loopAtEnd = true;
|
|
14020
|
+
this.requestUpdate();
|
|
14021
|
+
const dwell = this._panDuration() * 1e3 + END_DWELL;
|
|
14022
|
+
this._loopTimer = window.setTimeout(() => {
|
|
14023
|
+
this._loopTimer = 0;
|
|
14024
|
+
if (!this._loopActive) return;
|
|
14025
|
+
this._loopAtEnd = false;
|
|
14026
|
+
this.requestUpdate();
|
|
14027
|
+
this._scheduleLoopPan(700);
|
|
14028
|
+
}, dwell);
|
|
14029
|
+
}, delay);
|
|
14030
|
+
}
|
|
14031
|
+
_textStyle() {
|
|
14032
|
+
if (!this._isOverflowing) return ``;
|
|
14033
|
+
const distance = this._overflow + END_PADDING;
|
|
14034
|
+
const duration = Math.max(1.5, distance / SPEED);
|
|
14035
|
+
const revealEnd = this.direction === `end`;
|
|
14036
|
+
const restX = revealEnd ? 0 : -distance;
|
|
14037
|
+
const hoverX = revealEnd ? -distance : 0;
|
|
14038
|
+
if (this._loopActive && this.mode === `loop`) {
|
|
14039
|
+
if (this._loopAtEnd) return [
|
|
14040
|
+
`transform: translateX(${hoverX}px)`,
|
|
14041
|
+
`transition: transform ${duration}s ${PAN_EASING}`,
|
|
14042
|
+
`overflow: visible`,
|
|
14043
|
+
`text-overflow: clip`
|
|
14044
|
+
].join(`; `);
|
|
14045
|
+
return [
|
|
14046
|
+
`transform: translateX(${restX}px)`,
|
|
14047
|
+
`transition: transform ${RESET_DURATION}ms ${PAN_EASING}`,
|
|
14048
|
+
revealEnd ? `` : `overflow: visible; text-overflow: clip`
|
|
14049
|
+
].filter(Boolean).join(`; `);
|
|
14050
|
+
}
|
|
14051
|
+
if (this._isHovering) return [
|
|
14052
|
+
`transform: translateX(${hoverX}px)`,
|
|
14053
|
+
`transition: transform ${duration}s ${PAN_EASING} ${START_DELAY}ms`,
|
|
14054
|
+
`overflow: visible`,
|
|
14055
|
+
`text-overflow: clip`
|
|
14056
|
+
].join(`; `);
|
|
14057
|
+
return [
|
|
14058
|
+
`transform: translateX(${restX}px)`,
|
|
14059
|
+
`transition: transform 400ms ${PAN_EASING}`,
|
|
14060
|
+
revealEnd ? `` : `overflow: visible; text-overflow: clip`
|
|
14061
|
+
].filter(Boolean).join(`; `);
|
|
14062
|
+
}
|
|
14063
|
+
render() {
|
|
14064
|
+
const textClasses = {
|
|
14065
|
+
"is-overflowing": this._isOverflowing,
|
|
14066
|
+
"is-hovering": this._isHovering
|
|
14067
|
+
};
|
|
14068
|
+
return b`
|
|
14069
|
+
<span class="text ${classMap(textClasses)}" part="text" style=${this._textStyle()}>
|
|
14070
|
+
<slot @slotchange=${this._measure}></slot>
|
|
14071
|
+
</span>
|
|
14072
|
+
`;
|
|
14073
|
+
}
|
|
14074
|
+
static {
|
|
14075
|
+
this.styles = [themeFallbacks, i$3`
|
|
14076
|
+
/* Renders like plain inline text: no colours, border, padding or margin
|
|
14077
|
+
of its own — it only adds the clipping needed to pan on hover. */
|
|
14078
|
+
:host {
|
|
14079
|
+
display: inline-block;
|
|
14080
|
+
overflow: hidden;
|
|
14081
|
+
white-space: nowrap;
|
|
14082
|
+
max-width: 100%;
|
|
14083
|
+
box-sizing: border-box;
|
|
14084
|
+
font: inherit;
|
|
14085
|
+
color: inherit;
|
|
14086
|
+
}
|
|
14087
|
+
|
|
14088
|
+
:host([disabled]) {
|
|
14089
|
+
opacity: var(--disabled-opacity, 0.5);
|
|
14090
|
+
pointer-events: none;
|
|
14091
|
+
}
|
|
14092
|
+
|
|
14093
|
+
.text {
|
|
14094
|
+
display: block;
|
|
14095
|
+
overflow: hidden;
|
|
14096
|
+
text-overflow: ellipsis;
|
|
14097
|
+
white-space: nowrap;
|
|
14098
|
+
will-change: transform;
|
|
14099
|
+
}
|
|
14100
|
+
|
|
14101
|
+
@media (prefers-reduced-motion: reduce) {
|
|
14102
|
+
.text {
|
|
14103
|
+
transition: none !important;
|
|
14104
|
+
transform: none !important;
|
|
14105
|
+
}
|
|
14106
|
+
}
|
|
14107
|
+
`];
|
|
14108
|
+
}
|
|
14109
|
+
};
|
|
14110
|
+
__decorate([property({
|
|
14111
|
+
type: String,
|
|
14112
|
+
attribute: `direction`
|
|
14113
|
+
})], PanTextElement.prototype, "direction", void 0);
|
|
14114
|
+
__decorate([property({
|
|
14115
|
+
type: Boolean,
|
|
14116
|
+
attribute: `disabled`
|
|
14117
|
+
})], PanTextElement.prototype, "disabled", void 0);
|
|
14118
|
+
__decorate([property({
|
|
14119
|
+
type: String,
|
|
14120
|
+
attribute: `mode`,
|
|
14121
|
+
reflect: true
|
|
14122
|
+
})], PanTextElement.prototype, "mode", void 0);
|
|
14123
|
+
__decorate([state()], PanTextElement.prototype, "_isOverflowing", void 0);
|
|
14124
|
+
__decorate([state()], PanTextElement.prototype, "_isHovering", void 0);
|
|
14125
|
+
__decorate([state()], PanTextElement.prototype, "_loopActive", void 0);
|
|
14126
|
+
__decorate([state()], PanTextElement.prototype, "_loopAtEnd", void 0);
|
|
14127
|
+
__decorate([query(`.text`)], PanTextElement.prototype, "_textEl", void 0);
|
|
14128
|
+
PanTextElement = __decorate([safeCustomElement(`ixfx-pan-text`)], PanTextElement);
|
|
14129
|
+
//#endregion
|
|
13903
14130
|
//#region src/data-grid/data-grid.ts
|
|
13904
14131
|
let DataGridElement = class DataGridElement extends i {
|
|
13905
14132
|
constructor(..._args) {
|
|
@@ -13913,12 +14140,16 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
13913
14140
|
this.getRowKey = (r, i) => r.key ?? r.id ?? String(i);
|
|
13914
14141
|
this.editable = false;
|
|
13915
14142
|
this.editability = `user`;
|
|
14143
|
+
this.cellOverflow = `ellipsis`;
|
|
14144
|
+
this.zebraStripes = false;
|
|
13916
14145
|
this.groupBy = null;
|
|
13917
14146
|
this.allowGrouping = false;
|
|
13918
14147
|
this.crossGroupSelection = false;
|
|
13919
14148
|
this.columnMenu = `auto`;
|
|
13920
14149
|
this.itemsDraggable = false;
|
|
13921
14150
|
this._columnFormatters = /* @__PURE__ */ new Map();
|
|
14151
|
+
this._resizingColKey = void 0;
|
|
14152
|
+
this._animatingColKeys = /* @__PURE__ */ new Set();
|
|
13922
14153
|
this._selectedKeys = /* @__PURE__ */ new Set();
|
|
13923
14154
|
this._scrollTop = 0;
|
|
13924
14155
|
this._scrollLeft = 0;
|
|
@@ -14199,6 +14430,14 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14199
14430
|
--data-grid-header-bg: var(--surface-2);
|
|
14200
14431
|
--data-grid-border: var(--border);
|
|
14201
14432
|
--data-grid-header-text: var(--surface-3-text);
|
|
14433
|
+
--data-grid-reorder-handle-width: 10px;
|
|
14434
|
+
/* How strongly the alternate ("zebra") row stands out from the base row
|
|
14435
|
+
background when [zebra-stripes] is set - a color-mix() percentage. */
|
|
14436
|
+
--data-grid-zebra-intensity: 6%;
|
|
14437
|
+
/* Duration of the width transition when a column is auto-sized via
|
|
14438
|
+
autoSizeColumn(). Read back in JS (_columnResizeAnimationMs) to know
|
|
14439
|
+
when the animation has finished, so keep it a plain time value. */
|
|
14440
|
+
--data-grid-column-resize-duration: 180ms;
|
|
14202
14441
|
position: relative;
|
|
14203
14442
|
display: block;
|
|
14204
14443
|
overflow: hidden;
|
|
@@ -14227,11 +14466,28 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14227
14466
|
box-sizing: border-box;
|
|
14228
14467
|
}
|
|
14229
14468
|
.header-cell[data-tickled] { background: var(--surface-5); }
|
|
14469
|
+
/* Applied to a header-cell / cell while its column is animating towards
|
|
14470
|
+
an autoSizeColumn() target width. */
|
|
14471
|
+
.header-cell.width-animating, .cell.width-animating {
|
|
14472
|
+
transition: width var(--data-grid-column-resize-duration, 180ms) ease-out;
|
|
14473
|
+
}
|
|
14474
|
+
@media (prefers-reduced-motion: reduce) {
|
|
14475
|
+
.header-cell.width-animating, .cell.width-animating { transition: none; }
|
|
14476
|
+
}
|
|
14230
14477
|
.header-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
14231
14478
|
.sort-icon { font-size: 10px; opacity: 0.7; }
|
|
14232
|
-
.resize-handle {
|
|
14233
|
-
|
|
14234
|
-
|
|
14479
|
+
.resize-handle {
|
|
14480
|
+
position: absolute; right: -4px; top: 0; bottom: 0; width: 8px; cursor: col-resize; z-index: 1;
|
|
14481
|
+
display: flex; align-items: stretch; justify-content: center;
|
|
14482
|
+
}
|
|
14483
|
+
.resize-handle::before {
|
|
14484
|
+
content: ''; width: 2px; margin: 2px 0; border-radius: 1px; background: var(--split-gutter-color, transparent);
|
|
14485
|
+
transition: background-color var(--transition, 0.15s ease-out);
|
|
14486
|
+
}
|
|
14487
|
+
.resize-handle:hover::before { background: var(--split-gutter-hover-color, var(--surface-6)); }
|
|
14488
|
+
.resize-handle[data-active]::before { background: var(--split-gutter-active-color, var(--accent)); }
|
|
14489
|
+
.reorder-handle { cursor: grab; opacity: 0.5; display: inline-flex; align-items: center; }
|
|
14490
|
+
.reorder-handle .ixfx-handle { --ixfx-handle-length: 14px; --ixfx-handle-thickness: var(--data-grid-reorder-handle-width, 10px); --ixfx-handle-dot-size: 3px; }
|
|
14235
14491
|
.flyout-trigger { flex-shrink: 0; width: 36px; display: flex; align-items: center; justify-content: center; cursor: pointer; border-left: var(--border-subtle); background: var(--data-grid-header-bg); }
|
|
14236
14492
|
.viewport { flex: 1; overflow: auto; position: relative; }
|
|
14237
14493
|
.spacer { position: relative; }
|
|
@@ -14239,14 +14495,28 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14239
14495
|
position: absolute; left: 0; right: 0; display: flex; align-items: stretch;
|
|
14240
14496
|
gap: 0;
|
|
14241
14497
|
height: var(--data-grid-row-height);
|
|
14242
|
-
|
|
14243
|
-
|
|
14498
|
+
/* Border width is always 1px, even when not visually shown (transparent),
|
|
14499
|
+
so hover/selection never changes the box size and shifts content. */
|
|
14500
|
+
border: 1px solid transparent;
|
|
14244
14501
|
background: var(--item-bg);
|
|
14245
14502
|
border-radius: var(--item-border-radius);
|
|
14246
14503
|
padding: 0;
|
|
14247
14504
|
box-sizing: border-box;
|
|
14505
|
+
/* Only background transitions - hover ("tickled") no longer changes
|
|
14506
|
+
border, so there is nothing else to animate. */
|
|
14507
|
+
transition: background var(--transition, 0.1s ease-out);
|
|
14248
14508
|
}
|
|
14249
|
-
|
|
14509
|
+
/* Zebra striping: alternate rows tint towards the text colour, which
|
|
14510
|
+
lightens in dark themes and darkens in light themes - so it reads as
|
|
14511
|
+
"more contrast" either way. The zebra-odd class is only applied when
|
|
14512
|
+
zebraStripes is set (see render()). Declared before .tickled /
|
|
14513
|
+
.selected so those states (same specificity) still win when a striped
|
|
14514
|
+
row is also hovered or selected. */
|
|
14515
|
+
.row.item.zebra-odd {
|
|
14516
|
+
background: color-mix(in oklch, transparent calc(100% - var(--data-grid-zebra-intensity, 6%)), var(--surface-3-text) var(--data-grid-zebra-intensity, 6%));
|
|
14517
|
+
}
|
|
14518
|
+
/* Hover: background only, no border change (avoids layout shift + colour flash). */
|
|
14519
|
+
.row.item.tickled { background: var(--item-bg-tickled); color: var(--item-text-tickled); }
|
|
14250
14520
|
.row.item.selected { background: var(--item-bg-selected); border: var(--item-border-selected); color: var(--item-text-selected); }
|
|
14251
14521
|
.row.item.selected.tickled { background: var(--item-bg-selected-tickled); }
|
|
14252
14522
|
.row.item.dragging-origin { opacity: 0.6; }
|
|
@@ -14295,6 +14565,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14295
14565
|
`
|
|
14296
14566
|
];
|
|
14297
14567
|
}
|
|
14568
|
+
#viewportResizeObserver;
|
|
14298
14569
|
#nativeDragging;
|
|
14299
14570
|
#dragOriginKey;
|
|
14300
14571
|
#postDragSuppressTimer;
|
|
@@ -14412,6 +14683,8 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14412
14683
|
clearTimeout(this.#postDragSuppressTimer);
|
|
14413
14684
|
this.#postDragSuppressTimer = 0;
|
|
14414
14685
|
}
|
|
14686
|
+
this.#viewportResizeObserver?.disconnect();
|
|
14687
|
+
this.#viewportResizeObserver = void 0;
|
|
14415
14688
|
}
|
|
14416
14689
|
/**
|
|
14417
14690
|
* Dispatch a command to this grid — routes through the command registry so
|
|
@@ -14421,14 +14694,35 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14421
14694
|
this.#searchRegistry?.invoke(commandId, args);
|
|
14422
14695
|
}
|
|
14423
14696
|
firstUpdated() {
|
|
14424
|
-
new ResizeObserver(() =>
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14697
|
+
this.#viewportResizeObserver = new ResizeObserver(() => this.#measureViewport());
|
|
14698
|
+
this.#viewportResizeObserver.observe(this._viewportEl);
|
|
14699
|
+
this.#measureViewport();
|
|
14700
|
+
}
|
|
14701
|
+
/**
|
|
14702
|
+
* Re-read the viewport's size and update `_viewportH`/`_viewportW` if it
|
|
14703
|
+
* changed. A zero-sized read (e.g. while hosted in a hidden/inactive dock
|
|
14704
|
+
* tab) is ignored so it never clobbers the last known-good geometry — the
|
|
14705
|
+
* observer fires again with the real size once the host becomes visible.
|
|
14706
|
+
*/
|
|
14707
|
+
#measureViewport() {
|
|
14708
|
+
if (!this._viewportEl) return;
|
|
14709
|
+
const w = this._viewportEl.clientWidth;
|
|
14710
|
+
const h = this._viewportEl.clientHeight;
|
|
14711
|
+
if (w <= 0 || h <= 0) return;
|
|
14712
|
+
if (w === this._viewportW && h === this._viewportH) return;
|
|
14713
|
+
this._viewportW = w;
|
|
14714
|
+
this._viewportH = h;
|
|
14715
|
+
}
|
|
14716
|
+
/**
|
|
14717
|
+
* Force a fresh re-measure of the viewport and re-render. Normally
|
|
14718
|
+
* unnecessary — a `ResizeObserver` tracks the viewport automatically — but
|
|
14719
|
+
* gives a consumer an escape hatch to recover if an ancestor's
|
|
14720
|
+
* layout/visibility changes without the observer noticing (matches
|
|
14721
|
+
* `ixfx-grid-list`'s `refreshLayout()`).
|
|
14722
|
+
*/
|
|
14723
|
+
refreshLayout() {
|
|
14724
|
+
this.#measureViewport();
|
|
14725
|
+
this.requestUpdate();
|
|
14432
14726
|
}
|
|
14433
14727
|
updated(changed) {
|
|
14434
14728
|
super.updated(changed);
|
|
@@ -15091,7 +15385,13 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15091
15385
|
composed: true
|
|
15092
15386
|
}));
|
|
15093
15387
|
}
|
|
15094
|
-
|
|
15388
|
+
/**
|
|
15389
|
+
* Measure the width a column would need to show its header label and every
|
|
15390
|
+
* row's (formatted) value without truncation, clamped to `minWidth`/`maxWidth`.
|
|
15391
|
+
* Values are measured from their formatted string via canvas `measureText` -
|
|
15392
|
+
* accurate for plain text, an estimate for anything else.
|
|
15393
|
+
*/
|
|
15394
|
+
_measureAutoWidth(col) {
|
|
15095
15395
|
const cs = getComputedStyle(this);
|
|
15096
15396
|
const font = `${cs.fontSize} ${cs.fontFamily}`;
|
|
15097
15397
|
const ctx = document.createElement(`canvas`).getContext(`2d`);
|
|
@@ -15106,12 +15406,15 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15106
15406
|
for (const r of this.rows) {
|
|
15107
15407
|
const v = r[col.key];
|
|
15108
15408
|
if (v === null || v === void 0 || v === ``) continue;
|
|
15109
|
-
const w = measure(String(v)) + cellPad;
|
|
15409
|
+
const w = measure(String(this._formatValue(v, col, r))) + cellPad;
|
|
15110
15410
|
if (w > maxW) maxW = w;
|
|
15111
15411
|
}
|
|
15112
15412
|
const min = col.minWidth ?? 40;
|
|
15113
15413
|
const max = col.maxWidth ?? 600;
|
|
15114
|
-
|
|
15414
|
+
return Math.max(min, Math.min(max, maxW));
|
|
15415
|
+
}
|
|
15416
|
+
_autoSizeColumn(col) {
|
|
15417
|
+
const w = this._measureAutoWidth(col);
|
|
15115
15418
|
col.width = w;
|
|
15116
15419
|
this.requestUpdate();
|
|
15117
15420
|
this.dispatchEvent(new CustomEvent(`datagrid-column-resize`, {
|
|
@@ -15123,11 +15426,50 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15123
15426
|
composed: true
|
|
15124
15427
|
}));
|
|
15125
15428
|
}
|
|
15429
|
+
/**
|
|
15430
|
+
* Resize a single column, by key, to fit its contents (header label + every
|
|
15431
|
+
* row's formatted value), animating the width change smoothly. Only works
|
|
15432
|
+
* for plain columns - one with a custom `renderer` can't be measured
|
|
15433
|
+
* reliably from its raw value, so it's left untouched. Returns `false` (and
|
|
15434
|
+
* does nothing) if the column doesn't exist, isn't resizable, or has a
|
|
15435
|
+
* `renderer`.
|
|
15436
|
+
*/
|
|
15437
|
+
autoSizeColumn(key) {
|
|
15438
|
+
const col = this.columns.find((c) => c.key === key);
|
|
15439
|
+
if (!col || col.resizable === false || col.renderer) return false;
|
|
15440
|
+
const target = this._measureAutoWidth(col);
|
|
15441
|
+
if ((col.width ?? 150) === target) return true;
|
|
15442
|
+
this._animatingColKeys = new Set(this._animatingColKeys).add(key);
|
|
15443
|
+
requestAnimationFrame(() => {
|
|
15444
|
+
col.width = target;
|
|
15445
|
+
this.requestUpdate();
|
|
15446
|
+
this.dispatchEvent(new CustomEvent(`datagrid-column-resize`, {
|
|
15447
|
+
detail: {
|
|
15448
|
+
key,
|
|
15449
|
+
width: target
|
|
15450
|
+
},
|
|
15451
|
+
bubbles: true,
|
|
15452
|
+
composed: true
|
|
15453
|
+
}));
|
|
15454
|
+
window.setTimeout(() => {
|
|
15455
|
+
const next = new Set(this._animatingColKeys);
|
|
15456
|
+
next.delete(key);
|
|
15457
|
+
this._animatingColKeys = next;
|
|
15458
|
+
}, this._columnResizeAnimationMs());
|
|
15459
|
+
});
|
|
15460
|
+
return true;
|
|
15461
|
+
}
|
|
15462
|
+
_columnResizeAnimationMs() {
|
|
15463
|
+
const raw = getComputedStyle(this).getPropertyValue(`--data-grid-column-resize-duration`).trim();
|
|
15464
|
+
const ms = raw.endsWith(`ms`) ? Number.parseFloat(raw) : raw.endsWith(`s`) ? Number.parseFloat(raw) * 1e3 : Number.parseFloat(raw);
|
|
15465
|
+
return (Number.isFinite(ms) && ms > 0 ? ms : 180) + 30;
|
|
15466
|
+
}
|
|
15126
15467
|
_onResizePointerDown(e, col) {
|
|
15127
15468
|
e.preventDefault();
|
|
15128
15469
|
e.stopPropagation();
|
|
15129
15470
|
const startX = e.clientX;
|
|
15130
15471
|
const startW = col.width ?? 150;
|
|
15472
|
+
this._resizingColKey = col.key;
|
|
15131
15473
|
const onMove = (ev) => {
|
|
15132
15474
|
col.width = Math.max(col.minWidth ?? 40, Math.min(col.maxWidth ?? 600, startW + ev.clientX - startX));
|
|
15133
15475
|
this.requestUpdate();
|
|
@@ -15135,6 +15477,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15135
15477
|
const onUp = (ev) => {
|
|
15136
15478
|
window.removeEventListener(`pointermove`, onMove);
|
|
15137
15479
|
window.removeEventListener(`pointerup`, onUp);
|
|
15480
|
+
this._resizingColKey = void 0;
|
|
15138
15481
|
const w = Math.max(col.minWidth ?? 40, Math.min(col.maxWidth ?? 600, startW + ev.clientX - startX));
|
|
15139
15482
|
this.dispatchEvent(new CustomEvent(`datagrid-column-resize`, {
|
|
15140
15483
|
detail: {
|
|
@@ -15186,20 +15529,20 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15186
15529
|
const visibleFlat = this._flat.slice(startRow, endRow);
|
|
15187
15530
|
const showCheckbox = this.interactionMode === `checked`;
|
|
15188
15531
|
return b`
|
|
15189
|
-
<div class="grid"
|
|
15532
|
+
<div class="grid">
|
|
15190
15533
|
<div class="header-bar">
|
|
15191
15534
|
<div class="header-scroll">
|
|
15192
15535
|
${showCheckbox ? b`<div class="header-cell checkbox-col"></div>` : A}
|
|
15193
15536
|
${repeat(this._visibleColumns, (c) => c.key, (col, idx) => b`
|
|
15194
|
-
<div class="header-cell" style="width:${col.width ?? 150}px" ?drag-source=${this._drag?.active && this._drag.sourceCol.key === col.key}
|
|
15537
|
+
<div class="header-cell ${this._animatingColKeys.has(col.key) ? `width-animating` : ``}" style="width:${col.width ?? 150}px" ?drag-source=${this._drag?.active && this._drag.sourceCol.key === col.key}
|
|
15195
15538
|
@click=${() => this._onHeaderClick(col)}
|
|
15196
15539
|
@pointerenter=${() => this._tickled.handlePointerEnter(col.key)}>
|
|
15197
15540
|
${col.reorderable !== false ? b`<span class="reorder-handle" draggable="false"
|
|
15198
15541
|
@pointerdown=${(e) => this._beginHeaderDrag(e, col, idx)}
|
|
15199
|
-
><span class="ixfx-handle" data-handle="dotted" data-shape="
|
|
15542
|
+
><span class="ixfx-handle" data-handle="dotted" data-shape="vertical" part="reorder-handle"></span></span>` : A}
|
|
15200
15543
|
<span class="header-label">${col.label}</span>
|
|
15201
15544
|
${this.sortState?.key === col.key ? b`<span class="sort-icon">${this.sortState.direction === `asc` ? `▲` : `▼`}</span>` : A}
|
|
15202
|
-
${col.resizable !== false ? b`<span class="resize-handle" @pointerdown=${(e) => this._onResizePointerDown(e, col)} @click=${(e) => e.stopPropagation()} @dblclick=${(e) => {
|
|
15545
|
+
${col.resizable !== false ? b`<span class="resize-handle" ?data-active=${this._resizingColKey === col.key} @pointerdown=${(e) => this._onResizePointerDown(e, col)} @click=${(e) => e.stopPropagation()} @dblclick=${(e) => {
|
|
15203
15546
|
e.preventDefault();
|
|
15204
15547
|
e.stopPropagation();
|
|
15205
15548
|
this._autoSizeColumn(col);
|
|
@@ -15270,7 +15613,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15270
15613
|
const selected = this._selectedKeys.has(rowKey);
|
|
15271
15614
|
const tickled = this._tickled.isTickled(rowKey);
|
|
15272
15615
|
return b`
|
|
15273
|
-
<div class="row item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${this.#enteringRowKeys.has(rowKey) ? `entering` : ``} ${this.#nativeDragging && rowKey === this.#dragOriginKey ? `dragging-origin` : ``}" style="top:${absIdx * rh}px; height:${rh}px"
|
|
15616
|
+
<div class="row item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${this.zebraStripes && absIdx2 % 2 === 1 ? `zebra-odd` : ``} ${this.#enteringRowKeys.has(rowKey) ? `entering` : ``} ${this.#nativeDragging && rowKey === this.#dragOriginKey ? `dragging-origin` : ``}" style="top:${absIdx * rh}px; height:${rh}px"
|
|
15274
15617
|
data-key=${rowKey}
|
|
15275
15618
|
draggable=${this.#nativeDrag.draggableAttr}
|
|
15276
15619
|
@click=${(e) => {
|
|
@@ -15376,7 +15719,9 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15376
15719
|
const rendered = col.renderer ? col.renderer(row, col, absIdx2) : displayVal;
|
|
15377
15720
|
const cellContent = col.renderer ? rendered : displayVal;
|
|
15378
15721
|
const textEditable = this._isEditable(row, col) && this._isTextEditor(col);
|
|
15379
|
-
|
|
15722
|
+
const indent = col.align !== `right` && col.align !== `center` && col.reorderable !== false ? `padding-left:calc(var(--space-s) + var(--data-grid-reorder-handle-width, 10px) + var(--space-xs));` : ``;
|
|
15723
|
+
const canPan = this.cellOverflow === `pan-text` && !col.renderer && (selected || tickled);
|
|
15724
|
+
return b`<div class="cell ${textEditable ? `editable-text` : ``} ${this._animatingColKeys.has(col.key) ? `width-animating` : ``}" data-col=${col.key} style="width:${col.width ?? 150}px; justify-content:${col.align === `right` ? `flex-end` : col.align === `center` ? `center` : `flex-start`}; ${indent}"
|
|
15380
15725
|
@click=${(e) => {
|
|
15381
15726
|
this._lastClickedCell = {
|
|
15382
15727
|
rowKey,
|
|
@@ -15398,7 +15743,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15398
15743
|
composed: true
|
|
15399
15744
|
}));
|
|
15400
15745
|
}}
|
|
15401
|
-
>${cellContent}</div>`;
|
|
15746
|
+
>${canPan ? b`<ixfx-pan-text mode="loop">${cellContent}</ixfx-pan-text>` : cellContent}</div>`;
|
|
15402
15747
|
})}
|
|
15403
15748
|
</div>
|
|
15404
15749
|
`;
|
|
@@ -15432,6 +15777,15 @@ __decorate([property({
|
|
|
15432
15777
|
type: String,
|
|
15433
15778
|
reflect: true
|
|
15434
15779
|
})], DataGridElement.prototype, "editability", void 0);
|
|
15780
|
+
__decorate([property({
|
|
15781
|
+
type: String,
|
|
15782
|
+
attribute: `cell-overflow`
|
|
15783
|
+
})], DataGridElement.prototype, "cellOverflow", void 0);
|
|
15784
|
+
__decorate([property({
|
|
15785
|
+
type: Boolean,
|
|
15786
|
+
attribute: `zebra-stripes`,
|
|
15787
|
+
reflect: true
|
|
15788
|
+
})], DataGridElement.prototype, "zebraStripes", void 0);
|
|
15435
15789
|
__decorate([property({ attribute: false })], DataGridElement.prototype, "groupBy", void 0);
|
|
15436
15790
|
__decorate([property({
|
|
15437
15791
|
type: Boolean,
|
|
@@ -15462,6 +15816,8 @@ __decorate([property({
|
|
|
15462
15816
|
reflect: true
|
|
15463
15817
|
})], DataGridElement.prototype, "itemsDraggable", void 0);
|
|
15464
15818
|
__decorate([property({ attribute: false })], DataGridElement.prototype, "dragPreviewRenderer", void 0);
|
|
15819
|
+
__decorate([state()], DataGridElement.prototype, "_resizingColKey", void 0);
|
|
15820
|
+
__decorate([state()], DataGridElement.prototype, "_animatingColKeys", void 0);
|
|
15465
15821
|
__decorate([state()], DataGridElement.prototype, "_selectedKeys", void 0);
|
|
15466
15822
|
__decorate([state()], DataGridElement.prototype, "_scrollTop", void 0);
|
|
15467
15823
|
__decorate([state()], DataGridElement.prototype, "_scrollLeft", void 0);
|
|
@@ -22672,233 +23028,6 @@ var DataGridListSource = class {
|
|
|
22672
23028
|
}
|
|
22673
23029
|
};
|
|
22674
23030
|
//#endregion
|
|
22675
|
-
//#region src/pan-text/pan-text.ts
|
|
22676
|
-
const SPEED = 45;
|
|
22677
|
-
const END_PADDING = 4;
|
|
22678
|
-
const START_DELAY = 300;
|
|
22679
|
-
const END_DWELL = 2e3;
|
|
22680
|
-
const RESET_DURATION = 400;
|
|
22681
|
-
const PAN_EASING = `cubic-bezier(0.25, 0.46, 0.45, 0.94)`;
|
|
22682
|
-
let PanTextElement = class PanTextElement extends i {
|
|
22683
|
-
constructor(..._args) {
|
|
22684
|
-
super(..._args);
|
|
22685
|
-
this.direction = `end`;
|
|
22686
|
-
this.disabled = false;
|
|
22687
|
-
this.mode = `hover`;
|
|
22688
|
-
this._isOverflowing = false;
|
|
22689
|
-
this._isHovering = false;
|
|
22690
|
-
this._loopActive = false;
|
|
22691
|
-
this._loopAtEnd = false;
|
|
22692
|
-
this._overflow = 0;
|
|
22693
|
-
this._resizeObserver = null;
|
|
22694
|
-
this._loopTimer = 0;
|
|
22695
|
-
this._onMouseEnter = () => {
|
|
22696
|
-
this._isHovering = true;
|
|
22697
|
-
};
|
|
22698
|
-
this._onMouseLeave = () => {
|
|
22699
|
-
this._isHovering = false;
|
|
22700
|
-
};
|
|
22701
|
-
this._measure = () => {
|
|
22702
|
-
if (this._isHovering || this._loopAtEnd) return;
|
|
22703
|
-
const el = this._textEl;
|
|
22704
|
-
if (!el) return;
|
|
22705
|
-
this._overflow = Math.max(0, el.scrollWidth - el.clientWidth);
|
|
22706
|
-
const overflowing = this._overflow > 0;
|
|
22707
|
-
this.classList.toggle(`is-overflowing`, overflowing);
|
|
22708
|
-
if (overflowing !== this._isOverflowing) this._isOverflowing = overflowing;
|
|
22709
|
-
if (this._loopActive && this.mode === `loop` && !this.disabled && overflowing && this._loopTimer === 0) this._scheduleLoopPan(START_DELAY);
|
|
22710
|
-
if (!overflowing && this._loopAtEnd) {
|
|
22711
|
-
this._loopAtEnd = false;
|
|
22712
|
-
this.requestUpdate();
|
|
22713
|
-
}
|
|
22714
|
-
};
|
|
22715
|
-
}
|
|
22716
|
-
connectedCallback() {
|
|
22717
|
-
super.connectedCallback();
|
|
22718
|
-
this._resizeObserver = new ResizeObserver(() => this._measure());
|
|
22719
|
-
this.addEventListener(`mouseenter`, this._onMouseEnter);
|
|
22720
|
-
this.addEventListener(`mouseleave`, this._onMouseLeave);
|
|
22721
|
-
}
|
|
22722
|
-
disconnectedCallback() {
|
|
22723
|
-
super.disconnectedCallback();
|
|
22724
|
-
this._clearLoopTimer();
|
|
22725
|
-
this._loopActive = false;
|
|
22726
|
-
this._loopAtEnd = false;
|
|
22727
|
-
this._resizeObserver?.disconnect();
|
|
22728
|
-
this._resizeObserver = null;
|
|
22729
|
-
this.removeEventListener(`mouseenter`, this._onMouseEnter);
|
|
22730
|
-
this.removeEventListener(`mouseleave`, this._onMouseLeave);
|
|
22731
|
-
}
|
|
22732
|
-
firstUpdated() {
|
|
22733
|
-
this._measure();
|
|
22734
|
-
this._resizeObserver?.observe(this);
|
|
22735
|
-
document.fonts?.ready.then(() => this._measure());
|
|
22736
|
-
if (this.mode === `loop`) this.startLoop();
|
|
22737
|
-
}
|
|
22738
|
-
updated(changed) {
|
|
22739
|
-
if (changed.has(`mode`)) {
|
|
22740
|
-
if (this.mode === `loop`) this.startLoop();
|
|
22741
|
-
else this.stopLoop();
|
|
22742
|
-
}
|
|
22743
|
-
if (changed.has(`disabled`) && this.disabled) this.stopLoop();
|
|
22744
|
-
this._measure();
|
|
22745
|
-
}
|
|
22746
|
-
/**
|
|
22747
|
-
* Whether a loop pan is currently active (between `startLoop()` and `stopLoop()`).
|
|
22748
|
-
*/
|
|
22749
|
-
get looping() {
|
|
22750
|
-
return this._loopActive;
|
|
22751
|
-
}
|
|
22752
|
-
/**
|
|
22753
|
-
* Begin looping: pan to the end, dwell there for 2 seconds, reset to the
|
|
22754
|
-
* start and pan again, repeating until `stopLoop()` is called. A no-op when
|
|
22755
|
-
* `disabled`, when there is nothing to reveal, or under reduced-motion.
|
|
22756
|
-
*/
|
|
22757
|
-
startLoop() {
|
|
22758
|
-
if (this.disabled || this._prefersReducedMotion()) return;
|
|
22759
|
-
this._loopActive = true;
|
|
22760
|
-
this._loopAtEnd = false;
|
|
22761
|
-
this.requestUpdate();
|
|
22762
|
-
if (this._isOverflowing && this._loopTimer === 0) this._scheduleLoopPan(START_DELAY);
|
|
22763
|
-
}
|
|
22764
|
-
/**
|
|
22765
|
-
* Stop a loop started with `startLoop()` and snap back to the rest position.
|
|
22766
|
-
*/
|
|
22767
|
-
stopLoop() {
|
|
22768
|
-
if (!this._loopActive && !this._loopAtEnd && this._loopTimer === 0) return;
|
|
22769
|
-
this._clearLoopTimer();
|
|
22770
|
-
this._loopActive = false;
|
|
22771
|
-
this._loopAtEnd = false;
|
|
22772
|
-
this.requestUpdate();
|
|
22773
|
-
}
|
|
22774
|
-
_prefersReducedMotion() {
|
|
22775
|
-
return globalThis.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches ?? false;
|
|
22776
|
-
}
|
|
22777
|
-
_panDuration() {
|
|
22778
|
-
return Math.max(1.5, (this._overflow + END_PADDING) / SPEED);
|
|
22779
|
-
}
|
|
22780
|
-
_clearLoopTimer() {
|
|
22781
|
-
if (this._loopTimer !== 0) {
|
|
22782
|
-
clearTimeout(this._loopTimer);
|
|
22783
|
-
this._loopTimer = 0;
|
|
22784
|
-
}
|
|
22785
|
-
}
|
|
22786
|
-
_scheduleLoopPan(delay) {
|
|
22787
|
-
this._clearLoopTimer();
|
|
22788
|
-
this._loopTimer = window.setTimeout(() => {
|
|
22789
|
-
this._loopTimer = 0;
|
|
22790
|
-
if (!this._loopActive || this.disabled || !this._isOverflowing) return;
|
|
22791
|
-
this._loopAtEnd = true;
|
|
22792
|
-
this.requestUpdate();
|
|
22793
|
-
const dwell = this._panDuration() * 1e3 + END_DWELL;
|
|
22794
|
-
this._loopTimer = window.setTimeout(() => {
|
|
22795
|
-
this._loopTimer = 0;
|
|
22796
|
-
if (!this._loopActive) return;
|
|
22797
|
-
this._loopAtEnd = false;
|
|
22798
|
-
this.requestUpdate();
|
|
22799
|
-
this._scheduleLoopPan(700);
|
|
22800
|
-
}, dwell);
|
|
22801
|
-
}, delay);
|
|
22802
|
-
}
|
|
22803
|
-
_textStyle() {
|
|
22804
|
-
if (!this._isOverflowing) return ``;
|
|
22805
|
-
const distance = this._overflow + END_PADDING;
|
|
22806
|
-
const duration = Math.max(1.5, distance / SPEED);
|
|
22807
|
-
const revealEnd = this.direction === `end`;
|
|
22808
|
-
const restX = revealEnd ? 0 : -distance;
|
|
22809
|
-
const hoverX = revealEnd ? -distance : 0;
|
|
22810
|
-
if (this._loopActive && this.mode === `loop`) {
|
|
22811
|
-
if (this._loopAtEnd) return [
|
|
22812
|
-
`transform: translateX(${hoverX}px)`,
|
|
22813
|
-
`transition: transform ${duration}s ${PAN_EASING}`,
|
|
22814
|
-
`overflow: visible`,
|
|
22815
|
-
`text-overflow: clip`
|
|
22816
|
-
].join(`; `);
|
|
22817
|
-
return [
|
|
22818
|
-
`transform: translateX(${restX}px)`,
|
|
22819
|
-
`transition: transform ${RESET_DURATION}ms ${PAN_EASING}`,
|
|
22820
|
-
revealEnd ? `` : `overflow: visible; text-overflow: clip`
|
|
22821
|
-
].filter(Boolean).join(`; `);
|
|
22822
|
-
}
|
|
22823
|
-
if (this._isHovering) return [
|
|
22824
|
-
`transform: translateX(${hoverX}px)`,
|
|
22825
|
-
`transition: transform ${duration}s ${PAN_EASING} ${START_DELAY}ms`,
|
|
22826
|
-
`overflow: visible`,
|
|
22827
|
-
`text-overflow: clip`
|
|
22828
|
-
].join(`; `);
|
|
22829
|
-
return [
|
|
22830
|
-
`transform: translateX(${restX}px)`,
|
|
22831
|
-
`transition: transform 400ms ${PAN_EASING}`,
|
|
22832
|
-
revealEnd ? `` : `overflow: visible; text-overflow: clip`
|
|
22833
|
-
].filter(Boolean).join(`; `);
|
|
22834
|
-
}
|
|
22835
|
-
render() {
|
|
22836
|
-
const textClasses = {
|
|
22837
|
-
"is-overflowing": this._isOverflowing,
|
|
22838
|
-
"is-hovering": this._isHovering
|
|
22839
|
-
};
|
|
22840
|
-
return b`
|
|
22841
|
-
<span class="text ${classMap(textClasses)}" part="text" style=${this._textStyle()}>
|
|
22842
|
-
<slot @slotchange=${this._measure}></slot>
|
|
22843
|
-
</span>
|
|
22844
|
-
`;
|
|
22845
|
-
}
|
|
22846
|
-
static {
|
|
22847
|
-
this.styles = [themeFallbacks, i$3`
|
|
22848
|
-
/* Renders like plain inline text: no colours, border, padding or margin
|
|
22849
|
-
of its own — it only adds the clipping needed to pan on hover. */
|
|
22850
|
-
:host {
|
|
22851
|
-
display: inline-block;
|
|
22852
|
-
overflow: hidden;
|
|
22853
|
-
white-space: nowrap;
|
|
22854
|
-
max-width: 100%;
|
|
22855
|
-
box-sizing: border-box;
|
|
22856
|
-
font: inherit;
|
|
22857
|
-
color: inherit;
|
|
22858
|
-
}
|
|
22859
|
-
|
|
22860
|
-
:host([disabled]) {
|
|
22861
|
-
opacity: var(--disabled-opacity, 0.5);
|
|
22862
|
-
pointer-events: none;
|
|
22863
|
-
}
|
|
22864
|
-
|
|
22865
|
-
.text {
|
|
22866
|
-
display: block;
|
|
22867
|
-
overflow: hidden;
|
|
22868
|
-
text-overflow: ellipsis;
|
|
22869
|
-
white-space: nowrap;
|
|
22870
|
-
will-change: transform;
|
|
22871
|
-
}
|
|
22872
|
-
|
|
22873
|
-
@media (prefers-reduced-motion: reduce) {
|
|
22874
|
-
.text {
|
|
22875
|
-
transition: none !important;
|
|
22876
|
-
transform: none !important;
|
|
22877
|
-
}
|
|
22878
|
-
}
|
|
22879
|
-
`];
|
|
22880
|
-
}
|
|
22881
|
-
};
|
|
22882
|
-
__decorate([property({
|
|
22883
|
-
type: String,
|
|
22884
|
-
attribute: `direction`
|
|
22885
|
-
})], PanTextElement.prototype, "direction", void 0);
|
|
22886
|
-
__decorate([property({
|
|
22887
|
-
type: Boolean,
|
|
22888
|
-
attribute: `disabled`
|
|
22889
|
-
})], PanTextElement.prototype, "disabled", void 0);
|
|
22890
|
-
__decorate([property({
|
|
22891
|
-
type: String,
|
|
22892
|
-
attribute: `mode`,
|
|
22893
|
-
reflect: true
|
|
22894
|
-
})], PanTextElement.prototype, "mode", void 0);
|
|
22895
|
-
__decorate([state()], PanTextElement.prototype, "_isOverflowing", void 0);
|
|
22896
|
-
__decorate([state()], PanTextElement.prototype, "_isHovering", void 0);
|
|
22897
|
-
__decorate([state()], PanTextElement.prototype, "_loopActive", void 0);
|
|
22898
|
-
__decorate([state()], PanTextElement.prototype, "_loopAtEnd", void 0);
|
|
22899
|
-
__decorate([query(`.text`)], PanTextElement.prototype, "_textEl", void 0);
|
|
22900
|
-
PanTextElement = __decorate([safeCustomElement(`ixfx-pan-text`)], PanTextElement);
|
|
22901
|
-
//#endregion
|
|
22902
23031
|
//#region src/grid-list/grid-list.ts
|
|
22903
23032
|
const ITEM_SELECTOR$1 = `:scope > *`;
|
|
22904
23033
|
const MIN_ITEM_SIZE = 16;
|