@ixfx/components 0.6.1 → 0.6.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.
Files changed (64) hide show
  1. package/bundle/index.d.ts +178 -56
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +1130 -628
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +1 -1
  6. package/dist/{ac-token-DVbmHmky.d.ts → ac-token-BAa6ke09.d.ts} +2 -2
  7. package/dist/{ac-token-DVbmHmky.d.ts.map → ac-token-BAa6ke09.d.ts.map} +1 -1
  8. package/dist/ac-token.d.ts +1 -1
  9. package/dist/button.d.ts +1 -1
  10. package/dist/button.d.ts.map +1 -1
  11. package/dist/colour-picker.d.ts +1 -1
  12. package/dist/crumbs.d.ts +1 -1
  13. package/dist/{data-grid-BeAkORz2.d.ts → data-grid-C8qIo1-u.d.ts} +2 -2
  14. package/dist/{data-grid-BeAkORz2.d.ts.map → data-grid-C8qIo1-u.d.ts.map} +1 -1
  15. package/dist/data-grid.d.ts +1 -1
  16. package/dist/{grouped-item-lister-CNLMgdIr.d.ts → grouped-item-lister-_pMDwIo1.d.ts} +2 -2
  17. package/dist/{grouped-item-lister-CNLMgdIr.d.ts.map → grouped-item-lister-_pMDwIo1.d.ts.map} +1 -1
  18. package/dist/grouped-item-lister.d.ts +1 -1
  19. package/dist/{icon-BUwP1CZ1.d.ts → icon-DpA9x2Ve.d.ts} +2 -2
  20. package/dist/icon-DpA9x2Ve.d.ts.map +1 -0
  21. package/dist/icons.d.ts +2 -2
  22. package/dist/{index-RqMh1i-O.d.ts → index-BtGFYfaK.d.ts} +2 -2
  23. package/dist/{index-RqMh1i-O.d.ts.map → index-BtGFYfaK.d.ts.map} +1 -1
  24. package/dist/{index-ovq_GTdl.d.ts → index-CKtLhgYj.d.ts} +3 -3
  25. package/dist/{index-ovq_GTdl.d.ts.map → index-CKtLhgYj.d.ts.map} +1 -1
  26. package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -2
  27. package/dist/{index-BUB5SICW.d.ts.map → index-CoqtMSd9.d.ts.map} +1 -1
  28. package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -2
  29. package/dist/{index-BOUaDIW-.d.ts.map → index-tq6f8007.d.ts.map} +1 -1
  30. package/dist/index.d.ts +180 -58
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +840 -337
  33. package/dist/index.js.map +1 -1
  34. package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -2
  35. package/dist/{labelled-input-base-Dp_9KP0G.d.ts.map → labelled-input-base-DiTme1JO.d.ts.map} +1 -1
  36. package/dist/labelled-radial-input.d.ts +3 -3
  37. package/dist/labelled-radial-input.d.ts.map +1 -1
  38. package/dist/labelled-range-input.d.ts +1 -1
  39. package/dist/{menu-item-BG5w7fi4.d.ts → menu-item-Bs2MYyHq.d.ts} +2 -2
  40. package/dist/{menu-item-BG5w7fi4.d.ts.map → menu-item-Bs2MYyHq.d.ts.map} +1 -1
  41. package/dist/menu.d.ts +2 -2
  42. package/dist/panel.d.ts +1 -1
  43. package/dist/polar-pad.d.ts +1 -1
  44. package/dist/{radial-input-BhZeyyP-.d.ts → radial-input-DXMN55Nz.d.ts} +2 -2
  45. package/dist/{radial-input-BhZeyyP-.d.ts.map → radial-input-DXMN55Nz.d.ts.map} +1 -1
  46. package/dist/radial-input.d.ts +1 -1
  47. package/dist/range-input.d.ts +1 -1
  48. package/dist/range.d.ts +1 -1
  49. package/dist/select-horiz.d.ts +1 -1
  50. package/dist/{slider-input-TidGhvXt.d.ts → slider-input-XppH3vcy.d.ts} +2 -2
  51. package/dist/{slider-input-TidGhvXt.d.ts.map → slider-input-XppH3vcy.d.ts.map} +1 -1
  52. package/dist/slider-input.d.ts +1 -1
  53. package/dist/swipe.d.ts +1 -1
  54. package/dist/{tab-list-Beuh2nom.d.ts → tab-list-D_1cYhB_.d.ts} +2 -2
  55. package/dist/{tab-list-Beuh2nom.d.ts.map → tab-list-D_1cYhB_.d.ts.map} +1 -1
  56. package/dist/tabs.d.ts +1 -1
  57. package/dist/wheel-nudge-BlSCe_hD.js.map +1 -1
  58. package/dist/{wheel-nudge-DgMTRYlh.d.ts → wheel-nudge-DGrNzWuE.d.ts} +3 -3
  59. package/dist/wheel-nudge-DGrNzWuE.d.ts.map +1 -0
  60. package/dist/xy-pad.d.ts +1 -1
  61. package/docs-user/index.json +2 -2
  62. package/package.json +2 -1
  63. package/dist/icon-BUwP1CZ1.d.ts.map +0 -1
  64. package/dist/wheel-nudge-DgMTRYlh.d.ts.map +0 -1
package/bundle/index.js CHANGED
@@ -25228,6 +25228,431 @@ __decorate([property({
25228
25228
  })], SliderInputElement.prototype, "disabled", void 0);
25229
25229
  SliderInputElement = __decorate([safeCustomElement(`ixfx-slider-input`)], SliderInputElement);
25230
25230
  //#endregion
25231
+ //#region src/sliding-number/sliding-number.ts
25232
+ const REEL_DIGITS = Array.from({ length: 30 }, (_, index) => index % 10);
25233
+ const SECTION_RANK = {
25234
+ lead: 0,
25235
+ integer: 1,
25236
+ decimal: 2,
25237
+ fraction: 3,
25238
+ trail: 4
25239
+ };
25240
+ function mod(n, m) {
25241
+ return (n % m + m) % m;
25242
+ }
25243
+ /** Parse a CSS time token (`0.7s`, `700ms`, `0`) to milliseconds. */
25244
+ function millis(value) {
25245
+ const s = value.trim();
25246
+ if (s === ``) return 0;
25247
+ if (s.endsWith(`ms`)) return Number.parseFloat(s) || 0;
25248
+ if (s.endsWith(`s`)) return (Number.parseFloat(s) || 0) * 1e3;
25249
+ return Number.parseFloat(s) || 0;
25250
+ }
25251
+ let SlidingNumberElement = class SlidingNumberElement extends i {
25252
+ constructor(..._args) {
25253
+ super(..._args);
25254
+ this.value = 0;
25255
+ this.prefix = ``;
25256
+ this.suffix = ``;
25257
+ this.trend = `auto`;
25258
+ this.noAnimate = false;
25259
+ this.respectMotionPreference = true;
25260
+ this._cells = [];
25261
+ this._formatted = ``;
25262
+ this._ready = false;
25263
+ this._pendingSpins = [];
25264
+ this._pendingDir = `none`;
25265
+ this._reelAnims = /* @__PURE__ */ new Map();
25266
+ this._reapTimer = 0;
25267
+ }
25268
+ connectedCallback() {
25269
+ super.connectedCallback();
25270
+ if (!this.hasAttribute(`role`)) this.setAttribute(`role`, `img`);
25271
+ }
25272
+ disconnectedCallback() {
25273
+ super.disconnectedCallback();
25274
+ for (const anim of this._reelAnims.values()) anim.cancel();
25275
+ this._reelAnims.clear();
25276
+ if (this._reapTimer) clearTimeout(this._reapTimer);
25277
+ }
25278
+ _motionOK() {
25279
+ if (this.noAnimate) return false;
25280
+ if (this.respectMotionPreference && typeof window !== `undefined` && window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches) return false;
25281
+ return true;
25282
+ }
25283
+ _timing(kind) {
25284
+ const cs = getComputedStyle(this);
25285
+ return {
25286
+ duration: this._motionOK() ? millis(cs.getPropertyValue(`--sliding-number-${kind}-duration`)) : 0,
25287
+ easing: cs.getPropertyValue(`--sliding-number-${kind}-easing`).trim() || `ease`
25288
+ };
25289
+ }
25290
+ _numberFormat() {
25291
+ try {
25292
+ return new Intl.NumberFormat(this.locales || void 0, this.format || void 0);
25293
+ } catch {
25294
+ return new Intl.NumberFormat(this.locales || void 0);
25295
+ }
25296
+ }
25297
+ _resolveDir(first) {
25298
+ switch (this.trend) {
25299
+ case `up`:
25300
+ case `increasing`: return `up`;
25301
+ case `down`:
25302
+ case `decreasing`: return `down`;
25303
+ case `none`: return `none`;
25304
+ default:
25305
+ if (first || this._prevValue === void 0 || this.value === this._prevValue) return `none`;
25306
+ return this.value > this._prevValue ? `up` : `down`;
25307
+ }
25308
+ }
25309
+ /** Split the formatted value into positioned cells. */
25310
+ _buildCells(parts) {
25311
+ const intRaw = [];
25312
+ const fractionChars = [];
25313
+ const lead = [];
25314
+ const trail = [];
25315
+ let decimalChar = ``;
25316
+ let sawInteger = false;
25317
+ let sawDecimal = false;
25318
+ for (const part of parts) switch (part.type) {
25319
+ case `integer`:
25320
+ sawInteger = true;
25321
+ for (const c of part.value) intRaw.push({
25322
+ digit: true,
25323
+ char: c
25324
+ });
25325
+ break;
25326
+ case `group`:
25327
+ intRaw.push({
25328
+ digit: false,
25329
+ char: part.value
25330
+ });
25331
+ break;
25332
+ case `decimal`:
25333
+ sawDecimal = true;
25334
+ decimalChar = part.value;
25335
+ break;
25336
+ case `fraction`:
25337
+ for (const c of part.value) fractionChars.push(c);
25338
+ break;
25339
+ default: (sawInteger || sawDecimal ? trail : lead).push(part.value);
25340
+ }
25341
+ const cells = [];
25342
+ const totalIntDigits = intRaw.filter((x) => x.digit).length;
25343
+ lead.forEach((char, index) => {
25344
+ cells.push({
25345
+ key: `lead:${index}`,
25346
+ kind: `symbol`,
25347
+ section: `lead`,
25348
+ char,
25349
+ pos: index - 100,
25350
+ phase: `active`
25351
+ });
25352
+ });
25353
+ let seen = 0;
25354
+ for (const item of intRaw) if (item.digit) {
25355
+ const place = totalIntDigits - 1 - seen;
25356
+ seen++;
25357
+ cells.push({
25358
+ key: `int:${place}`,
25359
+ kind: `digit`,
25360
+ section: `integer`,
25361
+ char: item.char,
25362
+ pos: -place,
25363
+ phase: `active`
25364
+ });
25365
+ } else {
25366
+ const place = totalIntDigits - seen;
25367
+ cells.push({
25368
+ key: `grp:${place}`,
25369
+ kind: `symbol`,
25370
+ section: `integer`,
25371
+ char: item.char,
25372
+ pos: -place + .5,
25373
+ phase: `active`
25374
+ });
25375
+ }
25376
+ if (sawDecimal) cells.push({
25377
+ key: `decimal`,
25378
+ kind: `symbol`,
25379
+ section: `decimal`,
25380
+ char: decimalChar,
25381
+ pos: 0,
25382
+ phase: `active`
25383
+ });
25384
+ fractionChars.forEach((char, index) => {
25385
+ cells.push({
25386
+ key: `frac:${index}`,
25387
+ kind: `digit`,
25388
+ section: `fraction`,
25389
+ char,
25390
+ pos: index + 1,
25391
+ phase: `active`
25392
+ });
25393
+ });
25394
+ trail.forEach((char, index) => {
25395
+ cells.push({
25396
+ key: `trail:${index}`,
25397
+ kind: `symbol`,
25398
+ section: `trail`,
25399
+ char,
25400
+ pos: index + 100,
25401
+ phase: `active`
25402
+ });
25403
+ });
25404
+ return cells;
25405
+ }
25406
+ willUpdate(changed) {
25407
+ if (![
25408
+ `value`,
25409
+ `format`,
25410
+ `locales`,
25411
+ `prefix`,
25412
+ `suffix`,
25413
+ `noAnimate`
25414
+ ].some((p) => changed.has(p)) && this._ready) return;
25415
+ const nf = this._numberFormat();
25416
+ this._formatted = `${this.prefix}${nf.format(this.value)}${this.suffix}`;
25417
+ this.setAttribute(`aria-label`, this._formatted);
25418
+ this.toggleAttribute(`data-static`, !this._motionOK());
25419
+ const first = !this._ready;
25420
+ const motionOK = this._motionOK() && !first;
25421
+ const next = this._buildCells(nf.formatToParts(this.value));
25422
+ const nextKeys = new Set(next.map((c) => c.key));
25423
+ const prev = this._cells.filter((c) => c.phase !== `leave`);
25424
+ const prevByKey = new Map(prev.map((c) => [c.key, c]));
25425
+ const dir = this._resolveDir(first);
25426
+ const spins = [];
25427
+ const merged = [];
25428
+ for (const cell of next) {
25429
+ const before = prevByKey.get(cell.key);
25430
+ if (before) {
25431
+ if (motionOK && cell.kind === `digit` && before.char !== cell.char) spins.push({
25432
+ key: cell.key,
25433
+ from: Number(before.char),
25434
+ to: Number(cell.char)
25435
+ });
25436
+ merged.push({
25437
+ ...cell,
25438
+ phase: `active`
25439
+ });
25440
+ } else merged.push({
25441
+ ...cell,
25442
+ phase: motionOK ? `enter` : `active`
25443
+ });
25444
+ }
25445
+ if (motionOK) {
25446
+ for (const cell of prev) if (!nextKeys.has(cell.key)) merged.push({
25447
+ ...cell,
25448
+ phase: `leave`
25449
+ });
25450
+ }
25451
+ merged.sort((a, b) => SECTION_RANK[a.section] - SECTION_RANK[b.section] || a.pos - b.pos);
25452
+ this._cells = merged;
25453
+ this._pendingSpins = spins;
25454
+ this._pendingDir = dir;
25455
+ }
25456
+ updated() {
25457
+ for (const spin of this._pendingSpins) this._spin(spin.key, spin.from, spin.to, this._pendingDir);
25458
+ this._pendingSpins = [];
25459
+ if (this._cells.some((c) => c.phase === `enter`)) requestAnimationFrame(() => requestAnimationFrame(() => {
25460
+ let changed = false;
25461
+ for (const cell of this._cells) if (cell.phase === `enter`) {
25462
+ cell.phase = `active`;
25463
+ changed = true;
25464
+ }
25465
+ if (changed) {
25466
+ this._cells = [...this._cells];
25467
+ this.requestUpdate();
25468
+ }
25469
+ }));
25470
+ if (this._cells.some((c) => c.phase === `leave`)) {
25471
+ if (this._reapTimer) clearTimeout(this._reapTimer);
25472
+ this._reapTimer = window.setTimeout(() => {
25473
+ this._reapTimer = 0;
25474
+ const kept = this._cells.filter((c) => c.phase !== `leave`);
25475
+ if (kept.length !== this._cells.length) {
25476
+ this._cells = kept;
25477
+ this.requestUpdate();
25478
+ }
25479
+ }, this._timing(`transform`).duration + 120);
25480
+ }
25481
+ this._prevValue = this.value;
25482
+ this._ready = true;
25483
+ }
25484
+ _spin(key, fromDigit, toDigit, dir) {
25485
+ const reel = this.renderRoot.querySelector(`[data-key="${key}"] .reel`);
25486
+ if (!reel) return;
25487
+ const fromOffset = 10 + fromDigit;
25488
+ let toOffset;
25489
+ if (dir === `up`) toOffset = fromOffset + mod(toDigit - fromDigit, 10);
25490
+ else if (dir === `down`) toOffset = fromOffset - mod(fromDigit - toDigit, 10);
25491
+ else toOffset = [
25492
+ toDigit,
25493
+ 10 + toDigit,
25494
+ 20 + toDigit
25495
+ ].reduce((best, candidate) => Math.abs(candidate - fromOffset) < Math.abs(best - fromOffset) ? candidate : best);
25496
+ const { duration, easing } = this._timing(`spin`);
25497
+ this._reelAnims.get(key)?.cancel();
25498
+ if (duration === 0) {
25499
+ reel.style.setProperty(`--o`, String(10 + toDigit));
25500
+ return;
25501
+ }
25502
+ const anim = reel.animate([{ transform: `translateY(calc(-1em * ${fromOffset}))` }, { transform: `translateY(calc(-1em * ${toOffset}))` }], {
25503
+ duration,
25504
+ easing,
25505
+ fill: `both`
25506
+ });
25507
+ this._reelAnims.set(key, anim);
25508
+ anim.finished.then(() => {
25509
+ reel.style.setProperty(`--o`, String(10 + toDigit));
25510
+ anim.cancel();
25511
+ this._reelAnims.delete(key);
25512
+ }).catch(() => {});
25513
+ }
25514
+ _renderCell(cell) {
25515
+ if (cell.kind === `digit`) return b`
25516
+ <span class="cell digit" part="digit" data-key=${cell.key} data-phase=${cell.phase}>
25517
+ <span class="reel" style=${`--o:${10 + Number(cell.char)}`}>
25518
+ ${REEL_DIGITS.map((d) => b`<span>${d}</span>`)}
25519
+ </span>
25520
+ </span>
25521
+ `;
25522
+ return b`
25523
+ <span class="cell symbol" part="symbol" data-key=${cell.key} data-phase=${cell.phase}>${cell.char}</span>
25524
+ `;
25525
+ }
25526
+ render() {
25527
+ const section = (name) => this._cells.filter((c) => c.section === name);
25528
+ const integer = [...section(`integer`)].reverse();
25529
+ return b`
25530
+ ${this.prefix ? b`<span class="affix" part="prefix">${this.prefix}</span>` : A}
25531
+ <span class="number" part="number" aria-hidden="true">
25532
+ <span class="run lead">${section(`lead`).map((c) => this._renderCell(c))}</span>
25533
+ <span class="run integer" part="integer">
25534
+ ${repeat(integer, (c) => c.key, (c) => this._renderCell(c))}
25535
+ </span>
25536
+ ${section(`decimal`).map((c) => this._renderCell(c))}
25537
+ <span class="run fraction" part="fraction">
25538
+ ${repeat(section(`fraction`), (c) => c.key, (c) => this._renderCell(c))}
25539
+ </span>
25540
+ <span class="run trail">${section(`trail`).map((c) => this._renderCell(c))}</span>
25541
+ </span>
25542
+ ${this.suffix ? b`<span class="affix" part="suffix">${this.suffix}</span>` : A}
25543
+ `;
25544
+ }
25545
+ static {
25546
+ this.styles = i$3`
25547
+ :host {
25548
+ --sliding-number-spin-duration: 0.7s;
25549
+ --sliding-number-spin-easing: cubic-bezier(0.16, 1, 0.3, 1);
25550
+ --sliding-number-transform-duration: 0.5s;
25551
+ --sliding-number-transform-easing: cubic-bezier(0.16, 1, 0.3, 1);
25552
+ --sliding-number-opacity-duration: 0.35s;
25553
+ --sliding-number-digit-width: 1ch;
25554
+
25555
+ display: inline-flex;
25556
+ align-items: flex-end;
25557
+ line-height: 1;
25558
+ font-variant-numeric: tabular-nums;
25559
+ }
25560
+
25561
+ .number,
25562
+ .run {
25563
+ display: inline-flex;
25564
+ /* Every cell is exactly 1em tall, so aligning bottom edges keeps
25565
+ every glyph on the same line without relying on synthesised
25566
+ flex baselines (which break under overflow: hidden). */
25567
+ align-items: flex-end;
25568
+ white-space: nowrap;
25569
+ }
25570
+
25571
+ .affix {
25572
+ line-height: 1;
25573
+ }
25574
+
25575
+ /* Integer digits stack right-to-left so the units column (next to the
25576
+ decimal point) stays put while higher places grow outward. */
25577
+ .run.integer {
25578
+ flex-direction: row-reverse;
25579
+ }
25580
+
25581
+ .cell {
25582
+ display: block;
25583
+ height: 1em;
25584
+ line-height: 1;
25585
+ text-align: center;
25586
+ overflow: hidden;
25587
+ transition:
25588
+ width var(--sliding-number-transform-duration) var(--sliding-number-transform-easing),
25589
+ max-width var(--sliding-number-transform-duration) var(--sliding-number-transform-easing),
25590
+ opacity var(--sliding-number-opacity-duration) var(--sliding-number-transform-easing);
25591
+ }
25592
+
25593
+ .cell.digit {
25594
+ position: relative;
25595
+ width: var(--sliding-number-digit-width);
25596
+ }
25597
+
25598
+ .cell.symbol {
25599
+ max-width: 4ch;
25600
+ }
25601
+
25602
+ .cell[data-phase='enter'],
25603
+ .cell[data-phase='leave'] {
25604
+ opacity: 0;
25605
+ }
25606
+
25607
+ .cell.digit[data-phase='enter'],
25608
+ .cell.digit[data-phase='leave'] {
25609
+ width: 0;
25610
+ }
25611
+
25612
+ .cell.symbol[data-phase='enter'],
25613
+ .cell.symbol[data-phase='leave'] {
25614
+ max-width: 0;
25615
+ }
25616
+
25617
+ .reel {
25618
+ position: absolute;
25619
+ inset: 0 0 auto 0;
25620
+ display: flex;
25621
+ flex-direction: column;
25622
+ will-change: transform;
25623
+ transform: translateY(calc(-1em * var(--o, 10)));
25624
+ }
25625
+
25626
+ .reel > span {
25627
+ display: block;
25628
+ height: 1em;
25629
+ line-height: 1;
25630
+ text-align: center;
25631
+ }
25632
+
25633
+ :host([data-static]) .cell {
25634
+ transition: none;
25635
+ }
25636
+ `;
25637
+ }
25638
+ };
25639
+ __decorate([property({ type: Number })], SlidingNumberElement.prototype, "value", void 0);
25640
+ __decorate([property({ type: String })], SlidingNumberElement.prototype, "locales", void 0);
25641
+ __decorate([property({ type: Object })], SlidingNumberElement.prototype, "format", void 0);
25642
+ __decorate([property({ type: String })], SlidingNumberElement.prototype, "prefix", void 0);
25643
+ __decorate([property({ type: String })], SlidingNumberElement.prototype, "suffix", void 0);
25644
+ __decorate([property({ type: String })], SlidingNumberElement.prototype, "trend", void 0);
25645
+ __decorate([property({
25646
+ type: Boolean,
25647
+ attribute: `no-animate`
25648
+ })], SlidingNumberElement.prototype, "noAnimate", void 0);
25649
+ __decorate([property({
25650
+ type: Boolean,
25651
+ attribute: false
25652
+ })], SlidingNumberElement.prototype, "respectMotionPreference", void 0);
25653
+ __decorate([state()], SlidingNumberElement.prototype, "_cells", void 0);
25654
+ SlidingNumberElement = __decorate([safeCustomElement(`ixfx-sliding-number`)], SlidingNumberElement);
25655
+ //#endregion
25231
25656
  //#region src/snackbar/snackbar.ts
25232
25657
  let _instanceCounter = 0;
25233
25658
  let SnackbarElement = class SnackbarElement extends i {
@@ -26606,410 +27031,103 @@ __decorate([property({ type: Number })], SwipeElement.prototype, "debounceMs", v
26606
27031
  __decorate([property({ type: Number })], SwipeElement.prototype, "retractDurationMs", void 0);
26607
27032
  SwipeElement = __decorate([safeCustomElement(`ixfx-swipe`)], SwipeElement);
26608
27033
  //#endregion
26609
- //#region src/toolbar/toolbar.ts
26610
- var _ToolbarElement;
26611
- let ToolbarElement = class ToolbarElement extends i {
26612
- static {
26613
- _ToolbarElement = this;
26614
- }
27034
+ //#region src/tabs/tab-list-item.ts
27035
+ let TabListItemElement = class TabListItemElement extends i {
26615
27036
  constructor(..._args) {
26616
27037
  super(..._args);
26617
- this.orientation = `horizontal`;
26618
- this.layout = `one-line`;
26619
- this.verticalWriting = `auto`;
26620
- this.showGroupLabels = false;
26621
- this.invisibleGroups = false;
26622
- this._overflowCount = 0;
26623
- this._ro = null;
26624
- this._anchor = `--toolbar-${_ToolbarElement._cnt++}`;
26625
- this._sizes = /* @__PURE__ */ new WeakMap();
26626
- this._measureQueued = false;
27038
+ this.closeable = false;
27039
+ this.hideLabels = false;
27040
+ this.iconName = void 0;
27041
+ this.description = void 0;
27042
+ this.commandActive = void 0;
27043
+ this.registry = void 0;
27044
+ this._compact = false;
27045
+ this._hasToolbarContent = false;
27046
+ this._onToolbarSlotChange = () => {
27047
+ this._updateToolbarContent();
27048
+ };
26627
27049
  }
26628
- static {
26629
- this._cnt = 0;
27050
+ connectedCallback() {
27051
+ super.connectedCallback();
27052
+ this._resizeObserver = new ResizeObserver(([entry]) => {
27053
+ this._compact = entry.contentRect.width < 64;
27054
+ });
27055
+ this._resizeObserver.observe(this);
27056
+ (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.addEventListener(`slotchange`, this._onToolbarSlotChange);
27057
+ }
27058
+ disconnectedCallback() {
27059
+ super.disconnectedCallback();
27060
+ this._resizeObserver?.disconnect();
27061
+ this._resizeObserver = void 0;
27062
+ this._commandCleanup?.();
27063
+ this._commandCleanup = void 0;
27064
+ (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.removeEventListener(`slotchange`, this._onToolbarSlotChange);
27065
+ }
27066
+ updated(changed) {
27067
+ super.updated(changed);
27068
+ this._syncTooltipAttrs();
27069
+ if (changed.has(`registry`) || changed.has(`commandActive`)) this._syncCommandListener();
27070
+ }
27071
+ _syncTooltipAttrs() {
27072
+ if (this.description) {
27073
+ this.setAttribute(`data-tooltip`, this.description);
27074
+ this.setAttribute(`data-tooltip-anchor`, `top`);
27075
+ } else {
27076
+ this.removeAttribute(`data-tooltip`);
27077
+ this.removeAttribute(`data-tooltip-anchor`);
27078
+ }
27079
+ }
27080
+ _syncCommandListener() {
27081
+ this._commandCleanup?.();
27082
+ this._commandCleanup = void 0;
27083
+ if (this.registry && this.commandActive) this._commandCleanup = this.registry.addOnInvokeHandler((id) => {
27084
+ if (id === this.commandActive) this.click();
27085
+ });
27086
+ }
27087
+ _updateToolbarContent() {
27088
+ const slot = this.shadowRoot?.querySelector(`slot[name="toolbar"]`);
27089
+ this._hasToolbarContent = (slot?.assignedElements().length ?? 0) > 0;
27090
+ }
27091
+ firstUpdated() {
27092
+ this._updateToolbarContent();
27093
+ }
27094
+ render() {
27095
+ const showLabel = !this.hideLabels || !this.iconName;
27096
+ const hasActions = this.closeable || this._hasToolbarContent;
27097
+ return b`
27098
+ <div>
27099
+ ${this.iconName ? b`<ixfx-icon name="${this.iconName}"></ixfx-icon>` : A}
27100
+ ${showLabel ? b`<span class="label"><slot></slot></span>` : A}
27101
+ ${hasActions ? b`
27102
+ <div class="actions">
27103
+ <div class="toolbar"><slot name="toolbar"></slot></div>
27104
+ ${this.closeable ? b`
27105
+ <button
27106
+ class="close-btn"
27107
+ type="button"
27108
+ aria-label="Close tab"
27109
+ @click=${this._onCloseClick}
27110
+ >
27111
+ <ixfx-icon name="close"></ixfx-icon>
27112
+ </button>
27113
+ ` : A}
27114
+ </div>
27115
+ ` : A}
27116
+ </div>
27117
+ `;
27118
+ }
27119
+ _onCloseClick(e) {
27120
+ e.stopPropagation();
27121
+ this.dispatchEvent(new CustomEvent(`close`, {
27122
+ bubbles: true,
27123
+ composed: true
27124
+ }));
27125
+ this.remove();
26630
27126
  }
26631
27127
  static {
26632
27128
  this.styles = [
26633
27129
  themeFallbacks,
26634
- popupSurfaceStyles,
26635
- i$3`
26636
- :host {
26637
- --toolbar-gap: var(--space-s);
26638
- --toolbar-group-gap: var(--space-m);
26639
- display: block;
26640
- container-type: inline-size;
26641
- }
26642
- :host([orientation="vertical-left"]),
26643
- :host([orientation="vertical-right"]) {
26644
- container-type: normal;
26645
- width: max-content;
26646
- }
26647
- :host([orientation="vertical-left"]),
26648
- :host([orientation="vertical-right"]) { height: 100%; }
26649
- :host([orientation="vertical-left"]) .inner,
26650
- :host([orientation="vertical-right"]) .inner { height: 100%; box-sizing: border-box; width: max-content; }
26651
- .inner {
26652
- display: flex;
26653
- gap: var(--toolbar-gap);
26654
- background: var(--toolbar-bg, var(--surface-2));
26655
- padding: var(--toolbar-padding, var(--space-s));
26656
- border: var(--toolbar-border, var(--border-subtle));
26657
- border-radius: var(--radius-s);
26658
- align-items: center;
26659
- }
26660
- :host([orientation="horizontal"]) .inner { flex-direction: row; justify-content: flex-start; }
26661
- :host([orientation="vertical-left"]) .inner { flex-direction: column-reverse; align-items: stretch; }
26662
- :host([orientation="vertical-right"]) .inner { flex-direction: column; align-items: stretch; }
26663
- :host([layout="wrap"]) .inner { flex-wrap: wrap; }
26664
- :host([layout="one-line"]) .inner { flex-wrap: nowrap; overflow: hidden; }
26665
- :host([orientation="vertical-left"][vertical-writing="auto"]) ::slotted(*) { writing-mode: sideways-lr; }
26666
- :host([orientation="vertical-right"][vertical-writing="auto"]) ::slotted(*) { writing-mode: vertical-lr; }
26667
- :host([vertical-writing="up"]) ::slotted(*) { writing-mode: vertical-rl; text-orientation: upright; }
26668
- :host([vertical-writing="down"]) ::slotted(*) { writing-mode: vertical-lr; }
26669
- :host([vertical-writing="none"]) ::slotted(*) { writing-mode: horizontal-tb; }
26670
- ::slotted(*) { flex: 0 0 auto; }
26671
- ::slotted([grow]), ::slotted(ixfx-toolbar-group[grow]) { flex: 1 1 auto; }
26672
- ::slotted([hidden]) { display: none !important; }
26673
- :host([invisible-groups]) ::slotted(ixfx-toolbar-group) { --toolbar-group-border: none; }
26674
- .overflow-btn {
26675
- anchor-name: var(--anchor-name);
26676
- flex-shrink: 0;
26677
- background: var(--surface-3);
26678
- border: var(--border);
26679
- border-radius: var(--radius-s);
26680
- padding: var(--space-xs) var(--space-s);
26681
- cursor: pointer;
26682
- display: none;
26683
- }
26684
- .overflow-btn[visible] { display: inline-flex; }
26685
- .overflow-popover {
26686
- position: fixed;
26687
- top: anchor(bottom);
26688
- left: anchor(right);
26689
- position-anchor: var(--anchor-name);
26690
- position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
26691
- margin: 8px;
26692
- max-height: min(60vh, 400px);
26693
- max-width: min(90vw, 320px);
26694
- overflow: auto;
26695
- overscroll-behavior: contain;
26696
- z-index: 100;
26697
- padding: var(--space-s);
26698
- flex-direction: column;
26699
- gap: var(--space-s);
26700
- }
26701
- .overflow-popover:popover-open { display: flex; }
26702
- .overflow-popover ::slotted(*) { writing-mode: horizontal-tb; text-orientation: mixed; }
26703
- `
26704
- ];
26705
- }
26706
- connectedCallback() {
26707
- super.connectedCallback();
26708
- this.style.setProperty(`--anchor-name`, this._anchor);
26709
- }
26710
- firstUpdated() {
26711
- this._slot.addEventListener(`slotchange`, () => this._scheduleMeasure());
26712
- this._ro = new ResizeObserver(() => this._scheduleMeasure());
26713
- this._ro.observe(this._inner);
26714
- this._scheduleMeasure();
26715
- this._updateGroupLabels();
26716
- }
26717
- updated(changed) {
26718
- if (changed.has(`showGroupLabels`)) this._updateGroupLabels();
26719
- }
26720
- _updateGroupLabels() {
26721
- for (const child of Array.from(this.children)) if (child.tagName === `IXFX-TOOLBAR-GROUP`) {
26722
- if (this.showGroupLabels) child.setAttribute(`show-label`, ``);
26723
- else child.removeAttribute(`show-label`);
26724
- }
26725
- }
26726
- disconnectedCallback() {
26727
- super.disconnectedCallback();
26728
- this._ro?.disconnect();
26729
- }
26730
- /** Coalesce measure passes into one per frame; prevents slotchange feedback loops. */
26731
- _scheduleMeasure() {
26732
- if (this._measureQueued) return;
26733
- this._measureQueued = true;
26734
- requestAnimationFrame(() => {
26735
- this._measureQueued = false;
26736
- this._measure();
26737
- });
26738
- }
26739
- _measure() {
26740
- const children = Array.from(this.children);
26741
- const isGrow = (el) => el.hasAttribute(`grow`) || el.matches(`[grow]`);
26742
- const overflowable = children.filter((el) => !isGrow(el));
26743
- const isHoriz = this.orientation === `horizontal`;
26744
- if (this.layout !== `one-line`) {
26745
- let mutated = false;
26746
- for (const el of children) {
26747
- if (el.getAttribute(`slot`) === `overflow`) {
26748
- el.removeAttribute(`slot`);
26749
- mutated = true;
26750
- }
26751
- if (el.hasAttribute(`hidden`)) {
26752
- el.removeAttribute(`hidden`);
26753
- mutated = true;
26754
- }
26755
- }
26756
- if (this._overflowCount !== 0) {
26757
- this._overflowCount = 0;
26758
- mutated = true;
26759
- }
26760
- if (mutated) this.requestUpdate();
26761
- return;
26762
- }
26763
- if (!this._inner) return;
26764
- const cs = getComputedStyle(this._inner);
26765
- const gap = (isHoriz ? Number.parseFloat(cs.columnGap) : Number.parseFloat(cs.rowGap)) || 0;
26766
- const available = isHoriz ? this._inner.clientWidth : this._inner.clientHeight;
26767
- const btnSize = 36;
26768
- const inMain = overflowable.filter((el) => el.getAttribute(`slot`) !== `overflow`);
26769
- const inOverflow = overflowable.filter((el) => el.getAttribute(`slot`) === `overflow`);
26770
- let cum = 0;
26771
- inMain.forEach((el, i) => {
26772
- const s = isHoriz ? el.offsetWidth : el.offsetHeight;
26773
- if (s > 0) this._sizes.set(el, s);
26774
- cum += (i ? gap : 0) + (this._sizes.get(el) ?? s);
26775
- });
26776
- const btnAllowance = inOverflow.length > 0 ? gap + btnSize : 0;
26777
- let mutated = false;
26778
- while (inMain.length > 0 && cum + btnAllowance > available) {
26779
- const last = inMain[inMain.length - 1];
26780
- const s = this._sizes.get(last) ?? 0;
26781
- last.setAttribute(`slot`, `overflow`);
26782
- inMain.pop();
26783
- inOverflow.unshift(last);
26784
- cum -= (inMain.length ? gap : 0) + s;
26785
- mutated = true;
26786
- }
26787
- while (inOverflow.length > 0) {
26788
- const first = inOverflow[0];
26789
- const s = this._sizes.get(first);
26790
- if (s === void 0) break;
26791
- const addGap = inMain.length ? gap : 0;
26792
- const nextBtnAllowance = inOverflow.length > 1 ? gap + btnSize : 0;
26793
- if (cum + addGap + s + nextBtnAllowance > available) break;
26794
- first.removeAttribute(`slot`);
26795
- inOverflow.shift();
26796
- inMain.push(first);
26797
- cum += addGap + s;
26798
- mutated = true;
26799
- }
26800
- const newCount = inOverflow.length;
26801
- if (newCount !== this._overflowCount) {
26802
- this._overflowCount = newCount;
26803
- mutated = true;
26804
- }
26805
- if (mutated) this.requestUpdate();
26806
- }
26807
- _toggleOverflow() {
26808
- try {
26809
- this._popover.togglePopover();
26810
- } catch {
26811
- this._popover.showPopover();
26812
- }
26813
- }
26814
- render() {
26815
- const hasOverflow = this._overflowCount > 0;
26816
- return b`
26817
- <div class="inner" role="toolbar" aria-orientation=${this.orientation}>
26818
- <slot></slot>
26819
- <button class="overflow-btn" ?visible=${hasOverflow} @click=${this._toggleOverflow} aria-label="More" aria-haspopup="true" aria-expanded=${this._popover?.matches(`:popover-open`) ?? false}>⋯</button>
26820
- </div>
26821
- <div class="overflow-popover popup-surface" popover="auto" @click=${(e) => e.stopPropagation()}>
26822
- <slot name="overflow"></slot>
26823
- </div>
26824
- `;
26825
- }
26826
- };
26827
- __decorate([property({
26828
- type: String,
26829
- reflect: true
26830
- })], ToolbarElement.prototype, "orientation", void 0);
26831
- __decorate([property({
26832
- type: String,
26833
- reflect: true
26834
- })], ToolbarElement.prototype, "layout", void 0);
26835
- __decorate([property({
26836
- type: String,
26837
- attribute: `vertical-writing`,
26838
- reflect: true
26839
- })], ToolbarElement.prototype, "verticalWriting", void 0);
26840
- __decorate([property({
26841
- type: Boolean,
26842
- attribute: `show-group-labels`,
26843
- reflect: true
26844
- })], ToolbarElement.prototype, "showGroupLabels", void 0);
26845
- __decorate([property({
26846
- type: Boolean,
26847
- attribute: `invisible-groups`,
26848
- reflect: true
26849
- })], ToolbarElement.prototype, "invisibleGroups", void 0);
26850
- __decorate([state()], ToolbarElement.prototype, "_overflowCount", void 0);
26851
- __decorate([query(`.inner`)], ToolbarElement.prototype, "_inner", void 0);
26852
- __decorate([query(`.overflow-popover`)], ToolbarElement.prototype, "_popover", void 0);
26853
- __decorate([query(`slot`)], ToolbarElement.prototype, "_slot", void 0);
26854
- ToolbarElement = _ToolbarElement = __decorate([safeCustomElement(`ixfx-toolbar`)], ToolbarElement);
26855
- //#endregion
26856
- //#region src/toolbar/toolbar-group.ts
26857
- let ToolbarGroupElement = class ToolbarGroupElement extends i {
26858
- constructor(..._args) {
26859
- super(..._args);
26860
- this.label = ``;
26861
- this.grow = false;
26862
- }
26863
- static {
26864
- this.styles = [themeFallbacks, i$3`
26865
- :host {
26866
- display: flex;
26867
- flex-direction: column;
26868
- align-items: var(--toolbar-group-align-items, center);
26869
- justify-content: var(--toolbar-group-justify-content, flex-start);
26870
- gap: var(--toolbar-gap, var(--space-s));
26871
- padding: var(--space-xs);
26872
- border: 1px solid var(--border-subtle, var(--border));
26873
- border-radius: var(--radius-s);
26874
- background: var(--surface-3);
26875
- min-width: 0;
26876
- }
26877
- :host(:not([label])) {
26878
- border: none;
26879
- background: transparent;
26880
- padding: 0;
26881
- }
26882
- .label-row {
26883
- display: none;
26884
- font-size: var(--text-s, 12px);
26885
- color: var(--surface-muted-text);
26886
- padding-inline: var(--space-xs);
26887
- white-space: nowrap;
26888
- border-bottom: 1px solid var(--border-subtle);
26889
- margin-bottom: var(--space-xs);
26890
- }
26891
- :host([label][show-label]) .label-row { display: block; }
26892
- :host(:not([label])) .label-row { display: none; }
26893
- :host([grow]) { flex: 1 1 auto; min-width: 0; }
26894
- :host([hidden]) { display: none !important; }
26895
- .components { display: flex; }
26896
- ::slotted(*) { flex: 0 0 auto; }
26897
- ::slotted([grow]) { flex: 1 1 auto; }
26898
- `];
26899
- }
26900
- render() {
26901
- return b`
26902
- <div class="label-row">${this.label}</div>
26903
- <div class="components">
26904
- <slot></slot>
26905
- </div>
26906
- `;
26907
- }
26908
- };
26909
- __decorate([property({ type: String })], ToolbarGroupElement.prototype, "label", void 0);
26910
- __decorate([property({
26911
- type: Boolean,
26912
- reflect: true
26913
- })], ToolbarGroupElement.prototype, "grow", void 0);
26914
- ToolbarGroupElement = __decorate([safeCustomElement(`ixfx-toolbar-group`)], ToolbarGroupElement);
26915
- //#endregion
26916
- //#region src/tabs/tab-list-item.ts
26917
- let TabListItemElement = class TabListItemElement extends i {
26918
- constructor(..._args) {
26919
- super(..._args);
26920
- this.closeable = false;
26921
- this.hideLabels = false;
26922
- this.iconName = void 0;
26923
- this.description = void 0;
26924
- this.commandActive = void 0;
26925
- this.registry = void 0;
26926
- this._compact = false;
26927
- this._hasToolbarContent = false;
26928
- this._onToolbarSlotChange = () => {
26929
- this._updateToolbarContent();
26930
- };
26931
- }
26932
- connectedCallback() {
26933
- super.connectedCallback();
26934
- this._resizeObserver = new ResizeObserver(([entry]) => {
26935
- this._compact = entry.contentRect.width < 64;
26936
- });
26937
- this._resizeObserver.observe(this);
26938
- (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.addEventListener(`slotchange`, this._onToolbarSlotChange);
26939
- }
26940
- disconnectedCallback() {
26941
- super.disconnectedCallback();
26942
- this._resizeObserver?.disconnect();
26943
- this._resizeObserver = void 0;
26944
- this._commandCleanup?.();
26945
- this._commandCleanup = void 0;
26946
- (this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.removeEventListener(`slotchange`, this._onToolbarSlotChange);
26947
- }
26948
- updated(changed) {
26949
- super.updated(changed);
26950
- this._syncTooltipAttrs();
26951
- if (changed.has(`registry`) || changed.has(`commandActive`)) this._syncCommandListener();
26952
- }
26953
- _syncTooltipAttrs() {
26954
- if (this.description) {
26955
- this.setAttribute(`data-tooltip`, this.description);
26956
- this.setAttribute(`data-tooltip-anchor`, `top`);
26957
- } else {
26958
- this.removeAttribute(`data-tooltip`);
26959
- this.removeAttribute(`data-tooltip-anchor`);
26960
- }
26961
- }
26962
- _syncCommandListener() {
26963
- this._commandCleanup?.();
26964
- this._commandCleanup = void 0;
26965
- if (this.registry && this.commandActive) this._commandCleanup = this.registry.addOnInvokeHandler((id) => {
26966
- if (id === this.commandActive) this.click();
26967
- });
26968
- }
26969
- _updateToolbarContent() {
26970
- const slot = this.shadowRoot?.querySelector(`slot[name="toolbar"]`);
26971
- this._hasToolbarContent = (slot?.assignedElements().length ?? 0) > 0;
26972
- }
26973
- firstUpdated() {
26974
- this._updateToolbarContent();
26975
- }
26976
- render() {
26977
- const showLabel = !this.hideLabels || !this.iconName;
26978
- const hasActions = this.closeable || this._hasToolbarContent;
26979
- return b`
26980
- <div>
26981
- ${this.iconName ? b`<ixfx-icon name="${this.iconName}"></ixfx-icon>` : A}
26982
- ${showLabel ? b`<span class="label"><slot></slot></span>` : A}
26983
- ${hasActions ? b`
26984
- <div class="actions">
26985
- <div class="toolbar"><slot name="toolbar"></slot></div>
26986
- ${this.closeable ? b`
26987
- <button
26988
- class="close-btn"
26989
- type="button"
26990
- aria-label="Close tab"
26991
- @click=${this._onCloseClick}
26992
- >
26993
- <ixfx-icon name="close"></ixfx-icon>
26994
- </button>
26995
- ` : A}
26996
- </div>
26997
- ` : A}
26998
- </div>
26999
- `;
27000
- }
27001
- _onCloseClick(e) {
27002
- e.stopPropagation();
27003
- this.dispatchEvent(new CustomEvent(`close`, {
27004
- bubbles: true,
27005
- composed: true
27006
- }));
27007
- this.remove();
27008
- }
27009
- static {
27010
- this.styles = [
27011
- themeFallbacks,
27012
- prominenceStyles,
27130
+ prominenceStyles,
27013
27131
  i$3`
27014
27132
  :host {
27015
27133
  --selected-tab-color: var(--ixfx-selected-tab-color, var(--surface-2-text));
@@ -28082,8 +28200,85 @@ let TabPanelsElement = class TabPanelsElement extends i {
28082
28200
  `;
28083
28201
  }
28084
28202
  };
28085
- __decorate([queryAssignedElements()], TabPanelsElement.prototype, "_listItems", void 0);
28086
- TabPanelsElement = __decorate([safeCustomElement(`ixfx-tab-panels`)], TabPanelsElement);
28203
+ __decorate([queryAssignedElements()], TabPanelsElement.prototype, "_listItems", void 0);
28204
+ TabPanelsElement = __decorate([safeCustomElement(`ixfx-tab-panels`)], TabPanelsElement);
28205
+ //#endregion
28206
+ //#region src/text-shimmer/text-shimmer.ts
28207
+ let TextShimmerElement = class TextShimmerElement extends i {
28208
+ constructor(..._args) {
28209
+ super(..._args);
28210
+ this.text = ``;
28211
+ this.paused = false;
28212
+ }
28213
+ render() {
28214
+ return b`<span class="shimmer" part="text"
28215
+ >${this.text === `` ? b`<slot></slot>` : this.text}</span
28216
+ >`;
28217
+ }
28218
+ static {
28219
+ this.styles = i$3`
28220
+ :host {
28221
+ --text-shimmer-color: var(--surface-3-text, #888);
28222
+ --text-shimmer-gradient-color: var(--surface-2-text, #fff);
28223
+ --text-shimmer-duration: 2s;
28224
+ --text-shimmer-spread: 15%;
28225
+
28226
+ display: inline-block;
28227
+ color: var(--text-shimmer-color);
28228
+ }
28229
+
28230
+ .shimmer {
28231
+ background-image: linear-gradient(
28232
+ 90deg,
28233
+ var(--text-shimmer-color) 0%,
28234
+ var(--text-shimmer-color) calc(50% - var(--text-shimmer-spread)),
28235
+ var(--text-shimmer-gradient-color) 50%,
28236
+ var(--text-shimmer-color) calc(50% + var(--text-shimmer-spread)),
28237
+ var(--text-shimmer-color) 100%
28238
+ );
28239
+ background-size: 250% 100%;
28240
+ background-repeat: no-repeat;
28241
+ -webkit-background-clip: text;
28242
+ background-clip: text;
28243
+ color: transparent;
28244
+ -webkit-text-fill-color: transparent;
28245
+ animation: ixfx-text-shimmer-sweep var(--text-shimmer-duration) linear infinite;
28246
+ }
28247
+
28248
+ /* Sweep the highlight band from the right edge to the left edge. */
28249
+ @keyframes ixfx-text-shimmer-sweep {
28250
+ from {
28251
+ background-position: 100% center;
28252
+ }
28253
+ to {
28254
+ background-position: 0% center;
28255
+ }
28256
+ }
28257
+
28258
+ :host([paused]) .shimmer {
28259
+ animation: none;
28260
+ background-image: none;
28261
+ color: var(--text-shimmer-color);
28262
+ -webkit-text-fill-color: var(--text-shimmer-color);
28263
+ }
28264
+
28265
+ @media (prefers-reduced-motion: reduce) {
28266
+ .shimmer {
28267
+ animation: none;
28268
+ background-image: none;
28269
+ color: var(--text-shimmer-color);
28270
+ -webkit-text-fill-color: var(--text-shimmer-color);
28271
+ }
28272
+ }
28273
+ `;
28274
+ }
28275
+ };
28276
+ __decorate([property({ type: String })], TextShimmerElement.prototype, "text", void 0);
28277
+ __decorate([property({
28278
+ type: Boolean,
28279
+ reflect: true
28280
+ })], TextShimmerElement.prototype, "paused", void 0);
28281
+ TextShimmerElement = __decorate([safeCustomElement(`ixfx-text-shimmer`)], TextShimmerElement);
28087
28282
  //#endregion
28088
28283
  //#region src/timeline/timeline-controller.ts
28089
28284
  /**
@@ -29573,262 +29768,569 @@ let IxfxTimelineElement = class IxfxTimelineElement extends i {
29573
29768
  if (needsVerticalZoomReset) this.#initVerticalZoomToFit();
29574
29769
  if (needsLayoutRecompute) this.#recomputeTrackLayout();
29575
29770
  }
29576
- /**
29577
- * updated runs after render — for DOM side-effects only (syncing vcanvas,
29578
- * scrolling, invalidating canvas, dispatching events).
29579
- */
29580
- updated(changedProps) {
29581
- if (changedProps.has(`_ppu`) || changedProps.has(`_viewRange`) || changedProps.has(`min`) || changedProps.has(`max`)) {
29582
- this.#syncVCanvas();
29583
- this.#invalidateCanvas();
29584
- }
29585
- if (changedProps.has(`events`) || changedProps.has(`userScale`) || changedProps.has(`altMajorBg`) || changedProps.has(`gridMode`) || changedProps.has(`minorStep`)) this.#invalidateCanvas();
29586
- if (changedProps.has(`_trackLayout`)) {
29587
- this.#syncVCanvasVertical();
29588
- this.#positionTabs();
29589
- this.#invalidateCanvas();
29590
- }
29591
- if (changedProps.has(`_vViewRange`) || changedProps.has(`_vScale`)) {
29592
- this.#syncVerticalScroll();
29593
- this.#invalidateCanvas();
29594
- }
29595
- if (this._tickledId !== this.#prevTickledId) {
29596
- this.#prevTickledId = this._tickledId;
29597
- this.dispatchEvent(new CustomEvent(`tickle-change`, {
29598
- detail: { event: this.tickledEvent },
29599
- bubbles: true,
29600
- composed: true
29601
- }));
29602
- }
29771
+ /**
29772
+ * updated runs after render — for DOM side-effects only (syncing vcanvas,
29773
+ * scrolling, invalidating canvas, dispatching events).
29774
+ */
29775
+ updated(changedProps) {
29776
+ if (changedProps.has(`_ppu`) || changedProps.has(`_viewRange`) || changedProps.has(`min`) || changedProps.has(`max`)) {
29777
+ this.#syncVCanvas();
29778
+ this.#invalidateCanvas();
29779
+ }
29780
+ if (changedProps.has(`events`) || changedProps.has(`userScale`) || changedProps.has(`altMajorBg`) || changedProps.has(`gridMode`) || changedProps.has(`minorStep`)) this.#invalidateCanvas();
29781
+ if (changedProps.has(`_trackLayout`)) {
29782
+ this.#syncVCanvasVertical();
29783
+ this.#positionTabs();
29784
+ this.#invalidateCanvas();
29785
+ }
29786
+ if (changedProps.has(`_vViewRange`) || changedProps.has(`_vScale`)) {
29787
+ this.#syncVerticalScroll();
29788
+ this.#invalidateCanvas();
29789
+ }
29790
+ if (this._tickledId !== this.#prevTickledId) {
29791
+ this.#prevTickledId = this._tickledId;
29792
+ this.dispatchEvent(new CustomEvent(`tickle-change`, {
29793
+ detail: { event: this.tickledEvent },
29794
+ bubbles: true,
29795
+ composed: true
29796
+ }));
29797
+ }
29798
+ }
29799
+ render() {
29800
+ const totalBaseHeight = this.#getTotalBaseHeight();
29801
+ return b`
29802
+ <div class="content-wrapper">
29803
+ <div class="content-area">
29804
+ <div class="v-axis-zone"
29805
+ @pointerdown=${this.#onVAxisPointerDown}
29806
+ @pointermove=${this.#onVAxisPointerMove}
29807
+ @pointerup=${this.#onVAxisPointerUp}
29808
+ @pointercancel=${this.#onVAxisPointerUp}
29809
+ ></div>
29810
+ <div class="tab-column">
29811
+ ${this._internalTracks.filter((t) => !t.hidden).map((t) => {
29812
+ if (!this._trackLayout.find((l) => l.trackKey === t.key)) return A;
29813
+ return b`
29814
+ <ixfx-timeline-track-tab
29815
+ .label=${t.label}
29816
+ track-key="${t.key}"
29817
+ ?resizable=${this.trackHeight !== `none`}
29818
+ ?reorderable=${this.reorderable}
29819
+ @click=${(e) => this.selectTrack(t.key, e.shiftKey)}
29820
+ @track-resize-move=${this.#onTrackResizeMove}
29821
+ @track-resize=${this.#onTrackResizeEnd}
29822
+ ></ixfx-timeline-track-tab>
29823
+ `;
29824
+ })}
29825
+ </div>
29826
+ <x-vcanvas></x-vcanvas>
29827
+ </div>
29828
+ <div class="v-zoom">
29829
+ <ixfx-range-multi
29830
+ orientation="vertical"
29831
+ min="0"
29832
+ max="${totalBaseHeight}"
29833
+ a="${this._vViewRange.min}"
29834
+ b="${this._vViewRange.max}"
29835
+ step="any"
29836
+ crossover="stop"
29837
+ resize-mode="bipolar-flex"
29838
+ @input=${this.#onVZoomInput}
29839
+ ></ixfx-range-multi>
29840
+ </div>
29841
+ </div>
29842
+
29843
+ <div class="h-zoom">
29844
+ <ixfx-range-multi
29845
+ min="${this.min}"
29846
+ max="${this.max}"
29847
+ a="${this._viewRange.min}"
29848
+ b="${this._viewRange.max}"
29849
+ crossover="stop"
29850
+ resize-mode="bipolar-flex"
29851
+ @input=${this.#onHZoomInput}
29852
+ ></ixfx-range-multi>
29853
+ </div>
29854
+
29855
+ <div class="meta-resizer ${this.metaEnabled ? `visible` : ``}"></div>
29856
+ <div class="meta-area ${this.metaEnabled ? `visible` : ``}" style="height:${this._metaHeight}px"></div>
29857
+ `;
29858
+ }
29859
+ /** Compute initial ppu to fit 80% of the range, then derive viewRange */
29860
+ #initZoomToFit() {
29861
+ const vpWidth = this.#getViewportWidth();
29862
+ const totalSpan = this.max - this.min;
29863
+ const zoomFactor = .8;
29864
+ this._ppu = totalSpan > 0 ? vpWidth / (totalSpan * zoomFactor) : 1;
29865
+ this._viewRange = {
29866
+ min: this.min,
29867
+ max: this.min + totalSpan * zoomFactor
29868
+ };
29869
+ this.#syncVCanvas();
29870
+ }
29871
+ #syncVCanvas() {
29872
+ if (!this.#vcanvas) return;
29873
+ const totalSpan = this.max - this.min;
29874
+ this.#vcanvas.logicalWidth = totalSpan * this._ppu;
29875
+ this.#syncVCanvasVertical();
29876
+ this.#syncVCanvasScroll();
29877
+ }
29878
+ /** Sync logicalHeight and logicalScrollTop to the vcanvas */
29879
+ #syncVCanvasVertical() {
29880
+ if (!this.#vcanvas) return;
29881
+ const totalHeight = this._trackLayout.reduce((sum, tl) => sum + tl.height, 0);
29882
+ const canvasHeight = Math.max(totalHeight, 40) + this.#axisHeight;
29883
+ this.#vcanvas.logicalHeight = canvasHeight;
29884
+ this.#vcanvas.logicalScrollTop = this.#vScrollOffset;
29885
+ }
29886
+ #syncVCanvasScroll() {
29887
+ if (!this.#vcanvas) return;
29888
+ this.#vcanvas.logicalScrollLeft = (this._viewRange.min - this.min) * this._ppu;
29889
+ }
29890
+ #invalidateCanvas() {
29891
+ this.#vcanvas?.invalidateAll();
29892
+ }
29893
+ /** Called by ResizeObserver when vcanvas/content-area changes size */
29894
+ #onResize;
29895
+ #drawCallback;
29896
+ #onScrollVirtual;
29897
+ #recomputeTrackLayout() {
29898
+ const layout = [];
29899
+ let y = this.#axisHeight;
29900
+ for (const track of this._internalTracks) {
29901
+ if (track.hidden) continue;
29902
+ const baseHeight = this._trackHeightOverrides.get(track.key) ?? track.height ?? this.defaultTrackHeight;
29903
+ const height = Math.round(baseHeight * this._vScale);
29904
+ layout.push({
29905
+ trackKey: track.key,
29906
+ y,
29907
+ height
29908
+ });
29909
+ y += height;
29910
+ }
29911
+ this._trackLayout = layout;
29912
+ }
29913
+ /**
29914
+ * Range slider handler.
29915
+ * Slider controls zoom (via span) + pan (via position).
29916
+ * Derive ppu from the span the slider produces.
29917
+ */
29918
+ #onHZoomInput;
29919
+ /**
29920
+ * Vertical range slider handler.
29921
+ * Slider controls vertical zoom (via span) + vertical pan (via position).
29922
+ * Derive _vScale from the span the slider produces.
29923
+ */
29924
+ #onVZoomInput;
29925
+ #onVAxisPointerDown;
29926
+ #onVAxisPointerMove;
29927
+ #onVAxisPointerUp;
29928
+ /** Sync vertical scroll position to vcanvas logicalScrollTop */
29929
+ #syncVerticalScroll() {
29930
+ this.#syncVCanvasVertical();
29931
+ this.#positionTabs();
29932
+ }
29933
+ /**
29934
+ * Position track tabs in the .tab-column via absolute CSS positioning.
29935
+ * Applies a vertical translateY to offset for the current vertical scroll.
29936
+ */
29937
+ #positionTabs() {
29938
+ const tabColumn = this.shadowRoot?.querySelector(`.tab-column`);
29939
+ if (!tabColumn) return;
29940
+ const scrollTop = this.#vcanvas?.logicalScrollTop ?? 0;
29941
+ tabColumn.style.transform = `translateY(${-scrollTop}px)`;
29942
+ for (const layout of this._trackLayout) {
29943
+ const tab = tabColumn.querySelector(`ixfx-timeline-track-tab[track-key="${layout.trackKey}"]`);
29944
+ if (!tab) continue;
29945
+ tab.style.top = `${layout.y}px`;
29946
+ tab.style.height = `${layout.height}px`;
29947
+ }
29948
+ }
29949
+ /** Read the tab width from the CSS custom property */
29950
+ get #tabWidth() {
29951
+ const raw = getComputedStyle(this).getPropertyValue(`--timeline-tab-width`).trim();
29952
+ return Number.parseInt(raw, 10) || 120;
29953
+ }
29954
+ /** Live preview during drag — update heights but don't fire public event */
29955
+ #onTrackResizeMove;
29956
+ /** Final resize on pointerup — apply height and fire public event */
29957
+ #onTrackResizeEnd;
29958
+ /**
29959
+ * Apply track height based on the current `trackHeight` mode.
29960
+ * - `fixed`: sets `defaultTrackHeight` (all tracks change uniformly)
29961
+ * - `free`: sets per-track override in `_trackHeightOverrides`
29962
+ * - `none`: should never be called (resize is disabled)
29963
+ */
29964
+ #applyTrackResize(trackKey, height) {
29965
+ if (this.trackHeight === `fixed`) this.defaultTrackHeight = height;
29966
+ else if (this.trackHeight === `free`) {
29967
+ const next = new Map(this._trackHeightOverrides);
29968
+ next.set(trackKey, height);
29969
+ this._trackHeightOverrides = next;
29970
+ }
29971
+ }
29972
+ #fireSelectionChange() {
29973
+ this.dispatchEvent(new CustomEvent(`selection-change`, {
29974
+ detail: { selectedIds: [...this._selectedIds] },
29975
+ bubbles: true,
29976
+ composed: true
29977
+ }));
29978
+ }
29979
+ };
29980
+ __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "tracks", void 0);
29981
+ __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "events", void 0);
29982
+ __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "min", void 0);
29983
+ __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "max", void 0);
29984
+ __decorate([property({
29985
+ type: String,
29986
+ attribute: `track-height`
29987
+ })], IxfxTimelineElement.prototype, "trackHeight", void 0);
29988
+ __decorate([property({
29989
+ type: String,
29990
+ attribute: `user-scale`
29991
+ })], IxfxTimelineElement.prototype, "userScale", void 0);
29992
+ __decorate([property({ type: Boolean })], IxfxTimelineElement.prototype, "reorderable", void 0);
29993
+ __decorate([property({
29994
+ type: Boolean,
29995
+ attribute: `meta`
29996
+ })], IxfxTimelineElement.prototype, "metaEnabled", void 0);
29997
+ __decorate([property({
29998
+ type: Boolean,
29999
+ attribute: `alt-major-bg`
30000
+ })], IxfxTimelineElement.prototype, "altMajorBg", void 0);
30001
+ __decorate([property({
30002
+ type: Number,
30003
+ attribute: `default-track-height`
30004
+ })], IxfxTimelineElement.prototype, "defaultTrackHeight", void 0);
30005
+ __decorate([property({
30006
+ type: String,
30007
+ attribute: `grid-mode`
30008
+ })], IxfxTimelineElement.prototype, "gridMode", void 0);
30009
+ __decorate([property({
30010
+ type: Number,
30011
+ attribute: `minor-step`
30012
+ })], IxfxTimelineElement.prototype, "minorStep", void 0);
30013
+ __decorate([property({ type: Object })], IxfxTimelineElement.prototype, "onDragging", void 0);
30014
+ __decorate([state()], IxfxTimelineElement.prototype, "_ppu", void 0);
30015
+ __decorate([state()], IxfxTimelineElement.prototype, "_viewRange", void 0);
30016
+ __decorate([state()], IxfxTimelineElement.prototype, "_vViewRange", void 0);
30017
+ __decorate([state()], IxfxTimelineElement.prototype, "_vScale", void 0);
30018
+ __decorate([state()], IxfxTimelineElement.prototype, "_selectedIds", void 0);
30019
+ __decorate([state()], IxfxTimelineElement.prototype, "_tickledId", void 0);
30020
+ __decorate([state()], IxfxTimelineElement.prototype, "_drag", void 0);
30021
+ __decorate([state()], IxfxTimelineElement.prototype, "_metaHeight", void 0);
30022
+ __decorate([state()], IxfxTimelineElement.prototype, "_trackHeightOverrides", void 0);
30023
+ __decorate([state()], IxfxTimelineElement.prototype, "_trackLayout", void 0);
30024
+ __decorate([state()], IxfxTimelineElement.prototype, "_internalEvents", void 0);
30025
+ __decorate([state()], IxfxTimelineElement.prototype, "_internalTracks", void 0);
30026
+ IxfxTimelineElement = __decorate([safeCustomElement(`ixfx-timeline`)], IxfxTimelineElement);
30027
+ //#endregion
30028
+ //#region src/toolbar/toolbar-group.ts
30029
+ let ToolbarGroupElement = class ToolbarGroupElement extends i {
30030
+ constructor(..._args) {
30031
+ super(..._args);
30032
+ this.label = ``;
30033
+ this.grow = false;
30034
+ }
30035
+ static {
30036
+ this.styles = [themeFallbacks, i$3`
30037
+ :host {
30038
+ display: flex;
30039
+ flex-direction: column;
30040
+ align-items: var(--toolbar-group-align-items, center);
30041
+ justify-content: var(--toolbar-group-justify-content, flex-start);
30042
+ gap: var(--toolbar-gap, var(--space-s));
30043
+ padding: var(--space-xs);
30044
+ border: 1px solid var(--border-subtle, var(--border));
30045
+ border-radius: var(--radius-s);
30046
+ background: var(--surface-3);
30047
+ min-width: 0;
30048
+ }
30049
+ :host(:not([label])) {
30050
+ border: none;
30051
+ background: transparent;
30052
+ padding: 0;
30053
+ }
30054
+ .label-row {
30055
+ display: none;
30056
+ font-size: var(--text-s, 12px);
30057
+ color: var(--surface-muted-text);
30058
+ padding-inline: var(--space-xs);
30059
+ white-space: nowrap;
30060
+ border-bottom: 1px solid var(--border-subtle);
30061
+ margin-bottom: var(--space-xs);
30062
+ }
30063
+ :host([label][show-label]) .label-row { display: block; }
30064
+ :host(:not([label])) .label-row { display: none; }
30065
+ :host([grow]) { flex: 1 1 auto; min-width: 0; }
30066
+ :host([hidden]) { display: none !important; }
30067
+ .components { display: flex; }
30068
+ ::slotted(*) { flex: 0 0 auto; }
30069
+ ::slotted([grow]) { flex: 1 1 auto; }
30070
+ `];
29603
30071
  }
29604
30072
  render() {
29605
- const totalBaseHeight = this.#getTotalBaseHeight();
29606
30073
  return b`
29607
- <div class="content-wrapper">
29608
- <div class="content-area">
29609
- <div class="v-axis-zone"
29610
- @pointerdown=${this.#onVAxisPointerDown}
29611
- @pointermove=${this.#onVAxisPointerMove}
29612
- @pointerup=${this.#onVAxisPointerUp}
29613
- @pointercancel=${this.#onVAxisPointerUp}
29614
- ></div>
29615
- <div class="tab-column">
29616
- ${this._internalTracks.filter((t) => !t.hidden).map((t) => {
29617
- if (!this._trackLayout.find((l) => l.trackKey === t.key)) return A;
29618
- return b`
29619
- <ixfx-timeline-track-tab
29620
- .label=${t.label}
29621
- track-key="${t.key}"
29622
- ?resizable=${this.trackHeight !== `none`}
29623
- ?reorderable=${this.reorderable}
29624
- @click=${(e) => this.selectTrack(t.key, e.shiftKey)}
29625
- @track-resize-move=${this.#onTrackResizeMove}
29626
- @track-resize=${this.#onTrackResizeEnd}
29627
- ></ixfx-timeline-track-tab>
29628
- `;
29629
- })}
29630
- </div>
29631
- <x-vcanvas></x-vcanvas>
29632
- </div>
29633
- <div class="v-zoom">
29634
- <ixfx-range-multi
29635
- orientation="vertical"
29636
- min="0"
29637
- max="${totalBaseHeight}"
29638
- a="${this._vViewRange.min}"
29639
- b="${this._vViewRange.max}"
29640
- step="any"
29641
- crossover="stop"
29642
- resize-mode="bipolar-flex"
29643
- @input=${this.#onVZoomInput}
29644
- ></ixfx-range-multi>
29645
- </div>
29646
- </div>
29647
-
29648
- <div class="h-zoom">
29649
- <ixfx-range-multi
29650
- min="${this.min}"
29651
- max="${this.max}"
29652
- a="${this._viewRange.min}"
29653
- b="${this._viewRange.max}"
29654
- crossover="stop"
29655
- resize-mode="bipolar-flex"
29656
- @input=${this.#onHZoomInput}
29657
- ></ixfx-range-multi>
30074
+ <div class="label-row">${this.label}</div>
30075
+ <div class="components">
30076
+ <slot></slot>
29658
30077
  </div>
29659
-
29660
- <div class="meta-resizer ${this.metaEnabled ? `visible` : ``}"></div>
29661
- <div class="meta-area ${this.metaEnabled ? `visible` : ``}" style="height:${this._metaHeight}px"></div>
29662
30078
  `;
29663
30079
  }
29664
- /** Compute initial ppu to fit 80% of the range, then derive viewRange */
29665
- #initZoomToFit() {
29666
- const vpWidth = this.#getViewportWidth();
29667
- const totalSpan = this.max - this.min;
29668
- const zoomFactor = .8;
29669
- this._ppu = totalSpan > 0 ? vpWidth / (totalSpan * zoomFactor) : 1;
29670
- this._viewRange = {
29671
- min: this.min,
29672
- max: this.min + totalSpan * zoomFactor
29673
- };
29674
- this.#syncVCanvas();
30080
+ };
30081
+ __decorate([property({ type: String })], ToolbarGroupElement.prototype, "label", void 0);
30082
+ __decorate([property({
30083
+ type: Boolean,
30084
+ reflect: true
30085
+ })], ToolbarGroupElement.prototype, "grow", void 0);
30086
+ ToolbarGroupElement = __decorate([safeCustomElement(`ixfx-toolbar-group`)], ToolbarGroupElement);
30087
+ //#endregion
30088
+ //#region src/toolbar/toolbar.ts
30089
+ var _ToolbarElement;
30090
+ let ToolbarElement = class ToolbarElement extends i {
30091
+ static {
30092
+ _ToolbarElement = this;
29675
30093
  }
29676
- #syncVCanvas() {
29677
- if (!this.#vcanvas) return;
29678
- const totalSpan = this.max - this.min;
29679
- this.#vcanvas.logicalWidth = totalSpan * this._ppu;
29680
- this.#syncVCanvasVertical();
29681
- this.#syncVCanvasScroll();
30094
+ constructor(..._args) {
30095
+ super(..._args);
30096
+ this.orientation = `horizontal`;
30097
+ this.layout = `one-line`;
30098
+ this.verticalWriting = `auto`;
30099
+ this.showGroupLabels = false;
30100
+ this.invisibleGroups = false;
30101
+ this._overflowCount = 0;
30102
+ this._ro = null;
30103
+ this._anchor = `--toolbar-${_ToolbarElement._cnt++}`;
30104
+ this._sizes = /* @__PURE__ */ new WeakMap();
30105
+ this._measureQueued = false;
29682
30106
  }
29683
- /** Sync logicalHeight and logicalScrollTop to the vcanvas */
29684
- #syncVCanvasVertical() {
29685
- if (!this.#vcanvas) return;
29686
- const totalHeight = this._trackLayout.reduce((sum, tl) => sum + tl.height, 0);
29687
- const canvasHeight = Math.max(totalHeight, 40) + this.#axisHeight;
29688
- this.#vcanvas.logicalHeight = canvasHeight;
29689
- this.#vcanvas.logicalScrollTop = this.#vScrollOffset;
30107
+ static {
30108
+ this._cnt = 0;
30109
+ }
30110
+ static {
30111
+ this.styles = [
30112
+ themeFallbacks,
30113
+ popupSurfaceStyles,
30114
+ i$3`
30115
+ :host {
30116
+ --toolbar-gap: var(--space-s);
30117
+ --toolbar-group-gap: var(--space-m);
30118
+ display: block;
30119
+ container-type: inline-size;
30120
+ }
30121
+ :host([orientation="vertical-left"]),
30122
+ :host([orientation="vertical-right"]) {
30123
+ container-type: normal;
30124
+ width: max-content;
30125
+ }
30126
+ :host([orientation="vertical-left"]),
30127
+ :host([orientation="vertical-right"]) { height: 100%; }
30128
+ :host([orientation="vertical-left"]) .inner,
30129
+ :host([orientation="vertical-right"]) .inner { height: 100%; box-sizing: border-box; width: max-content; }
30130
+ .inner {
30131
+ display: flex;
30132
+ gap: var(--toolbar-gap);
30133
+ background: var(--toolbar-bg, var(--surface-2));
30134
+ padding: var(--toolbar-padding, var(--space-s));
30135
+ border: var(--toolbar-border, var(--border-subtle));
30136
+ border-radius: var(--radius-s);
30137
+ align-items: center;
30138
+ }
30139
+ :host([orientation="horizontal"]) .inner { flex-direction: row; justify-content: flex-start; }
30140
+ :host([orientation="vertical-left"]) .inner { flex-direction: column-reverse; align-items: stretch; }
30141
+ :host([orientation="vertical-right"]) .inner { flex-direction: column; align-items: stretch; }
30142
+ :host([layout="wrap"]) .inner { flex-wrap: wrap; }
30143
+ :host([layout="one-line"]) .inner { flex-wrap: nowrap; overflow: hidden; }
30144
+ :host([orientation="vertical-left"][vertical-writing="auto"]) ::slotted(*) { writing-mode: sideways-lr; }
30145
+ :host([orientation="vertical-right"][vertical-writing="auto"]) ::slotted(*) { writing-mode: vertical-lr; }
30146
+ :host([vertical-writing="up"]) ::slotted(*) { writing-mode: vertical-rl; text-orientation: upright; }
30147
+ :host([vertical-writing="down"]) ::slotted(*) { writing-mode: vertical-lr; }
30148
+ :host([vertical-writing="none"]) ::slotted(*) { writing-mode: horizontal-tb; }
30149
+ ::slotted(*) { flex: 0 0 auto; }
30150
+ ::slotted([grow]), ::slotted(ixfx-toolbar-group[grow]) { flex: 1 1 auto; }
30151
+ ::slotted([hidden]) { display: none !important; }
30152
+ :host([invisible-groups]) ::slotted(ixfx-toolbar-group) { --toolbar-group-border: none; }
30153
+ .overflow-btn {
30154
+ anchor-name: var(--anchor-name);
30155
+ flex-shrink: 0;
30156
+ background: var(--surface-3);
30157
+ border: var(--border);
30158
+ border-radius: var(--radius-s);
30159
+ padding: var(--space-xs) var(--space-s);
30160
+ cursor: pointer;
30161
+ display: none;
30162
+ }
30163
+ .overflow-btn[visible] { display: inline-flex; }
30164
+ .overflow-popover {
30165
+ position: fixed;
30166
+ top: anchor(bottom);
30167
+ left: anchor(right);
30168
+ position-anchor: var(--anchor-name);
30169
+ position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
30170
+ margin: 8px;
30171
+ max-height: min(60vh, 400px);
30172
+ max-width: min(90vw, 320px);
30173
+ overflow: auto;
30174
+ overscroll-behavior: contain;
30175
+ z-index: 100;
30176
+ padding: var(--space-s);
30177
+ flex-direction: column;
30178
+ gap: var(--space-s);
30179
+ }
30180
+ .overflow-popover:popover-open { display: flex; }
30181
+ .overflow-popover ::slotted(*) { writing-mode: horizontal-tb; text-orientation: mixed; }
30182
+ `
30183
+ ];
29690
30184
  }
29691
- #syncVCanvasScroll() {
29692
- if (!this.#vcanvas) return;
29693
- this.#vcanvas.logicalScrollLeft = (this._viewRange.min - this.min) * this._ppu;
30185
+ connectedCallback() {
30186
+ super.connectedCallback();
30187
+ this.style.setProperty(`--anchor-name`, this._anchor);
29694
30188
  }
29695
- #invalidateCanvas() {
29696
- this.#vcanvas?.invalidateAll();
30189
+ firstUpdated() {
30190
+ this._slot.addEventListener(`slotchange`, () => this._scheduleMeasure());
30191
+ this._ro = new ResizeObserver(() => this._scheduleMeasure());
30192
+ this._ro.observe(this._inner);
30193
+ this._scheduleMeasure();
30194
+ this._updateGroupLabels();
29697
30195
  }
29698
- /** Called by ResizeObserver when vcanvas/content-area changes size */
29699
- #onResize;
29700
- #drawCallback;
29701
- #onScrollVirtual;
29702
- #recomputeTrackLayout() {
29703
- const layout = [];
29704
- let y = this.#axisHeight;
29705
- for (const track of this._internalTracks) {
29706
- if (track.hidden) continue;
29707
- const baseHeight = this._trackHeightOverrides.get(track.key) ?? track.height ?? this.defaultTrackHeight;
29708
- const height = Math.round(baseHeight * this._vScale);
29709
- layout.push({
29710
- trackKey: track.key,
29711
- y,
29712
- height
29713
- });
29714
- y += height;
30196
+ updated(changed) {
30197
+ if (changed.has(`showGroupLabels`)) this._updateGroupLabels();
30198
+ }
30199
+ _updateGroupLabels() {
30200
+ for (const child of Array.from(this.children)) if (child.tagName === `IXFX-TOOLBAR-GROUP`) {
30201
+ if (this.showGroupLabels) child.setAttribute(`show-label`, ``);
30202
+ else child.removeAttribute(`show-label`);
29715
30203
  }
29716
- this._trackLayout = layout;
29717
30204
  }
29718
- /**
29719
- * Range slider handler.
29720
- * Slider controls zoom (via span) + pan (via position).
29721
- * Derive ppu from the span the slider produces.
29722
- */
29723
- #onHZoomInput;
29724
- /**
29725
- * Vertical range slider handler.
29726
- * Slider controls vertical zoom (via span) + vertical pan (via position).
29727
- * Derive _vScale from the span the slider produces.
29728
- */
29729
- #onVZoomInput;
29730
- #onVAxisPointerDown;
29731
- #onVAxisPointerMove;
29732
- #onVAxisPointerUp;
29733
- /** Sync vertical scroll position to vcanvas logicalScrollTop */
29734
- #syncVerticalScroll() {
29735
- this.#syncVCanvasVertical();
29736
- this.#positionTabs();
30205
+ disconnectedCallback() {
30206
+ super.disconnectedCallback();
30207
+ this._ro?.disconnect();
29737
30208
  }
29738
- /**
29739
- * Position track tabs in the .tab-column via absolute CSS positioning.
29740
- * Applies a vertical translateY to offset for the current vertical scroll.
29741
- */
29742
- #positionTabs() {
29743
- const tabColumn = this.shadowRoot?.querySelector(`.tab-column`);
29744
- if (!tabColumn) return;
29745
- const scrollTop = this.#vcanvas?.logicalScrollTop ?? 0;
29746
- tabColumn.style.transform = `translateY(${-scrollTop}px)`;
29747
- for (const layout of this._trackLayout) {
29748
- const tab = tabColumn.querySelector(`ixfx-timeline-track-tab[track-key="${layout.trackKey}"]`);
29749
- if (!tab) continue;
29750
- tab.style.top = `${layout.y}px`;
29751
- tab.style.height = `${layout.height}px`;
29752
- }
30209
+ /** Coalesce measure passes into one per frame; prevents slotchange feedback loops. */
30210
+ _scheduleMeasure() {
30211
+ if (this._measureQueued) return;
30212
+ this._measureQueued = true;
30213
+ requestAnimationFrame(() => {
30214
+ this._measureQueued = false;
30215
+ this._measure();
30216
+ });
29753
30217
  }
29754
- /** Read the tab width from the CSS custom property */
29755
- get #tabWidth() {
29756
- const raw = getComputedStyle(this).getPropertyValue(`--timeline-tab-width`).trim();
29757
- return Number.parseInt(raw, 10) || 120;
30218
+ _measure() {
30219
+ const children = Array.from(this.children);
30220
+ const isGrow = (el) => el.hasAttribute(`grow`) || el.matches(`[grow]`);
30221
+ const overflowable = children.filter((el) => !isGrow(el));
30222
+ const isHoriz = this.orientation === `horizontal`;
30223
+ if (this.layout !== `one-line`) {
30224
+ let mutated = false;
30225
+ for (const el of children) {
30226
+ if (el.getAttribute(`slot`) === `overflow`) {
30227
+ el.removeAttribute(`slot`);
30228
+ mutated = true;
30229
+ }
30230
+ if (el.hasAttribute(`hidden`)) {
30231
+ el.removeAttribute(`hidden`);
30232
+ mutated = true;
30233
+ }
30234
+ }
30235
+ if (this._overflowCount !== 0) {
30236
+ this._overflowCount = 0;
30237
+ mutated = true;
30238
+ }
30239
+ if (mutated) this.requestUpdate();
30240
+ return;
30241
+ }
30242
+ if (!this._inner) return;
30243
+ const cs = getComputedStyle(this._inner);
30244
+ const gap = (isHoriz ? Number.parseFloat(cs.columnGap) : Number.parseFloat(cs.rowGap)) || 0;
30245
+ const available = isHoriz ? this._inner.clientWidth : this._inner.clientHeight;
30246
+ const btnSize = 36;
30247
+ const inMain = overflowable.filter((el) => el.getAttribute(`slot`) !== `overflow`);
30248
+ const inOverflow = overflowable.filter((el) => el.getAttribute(`slot`) === `overflow`);
30249
+ let cum = 0;
30250
+ inMain.forEach((el, i) => {
30251
+ const s = isHoriz ? el.offsetWidth : el.offsetHeight;
30252
+ if (s > 0) this._sizes.set(el, s);
30253
+ cum += (i ? gap : 0) + (this._sizes.get(el) ?? s);
30254
+ });
30255
+ const btnAllowance = inOverflow.length > 0 ? gap + btnSize : 0;
30256
+ let mutated = false;
30257
+ while (inMain.length > 0 && cum + btnAllowance > available) {
30258
+ const last = inMain[inMain.length - 1];
30259
+ const s = this._sizes.get(last) ?? 0;
30260
+ last.setAttribute(`slot`, `overflow`);
30261
+ inMain.pop();
30262
+ inOverflow.unshift(last);
30263
+ cum -= (inMain.length ? gap : 0) + s;
30264
+ mutated = true;
30265
+ }
30266
+ while (inOverflow.length > 0) {
30267
+ const first = inOverflow[0];
30268
+ const s = this._sizes.get(first);
30269
+ if (s === void 0) break;
30270
+ const addGap = inMain.length ? gap : 0;
30271
+ const nextBtnAllowance = inOverflow.length > 1 ? gap + btnSize : 0;
30272
+ if (cum + addGap + s + nextBtnAllowance > available) break;
30273
+ first.removeAttribute(`slot`);
30274
+ inOverflow.shift();
30275
+ inMain.push(first);
30276
+ cum += addGap + s;
30277
+ mutated = true;
30278
+ }
30279
+ const newCount = inOverflow.length;
30280
+ if (newCount !== this._overflowCount) {
30281
+ this._overflowCount = newCount;
30282
+ mutated = true;
30283
+ }
30284
+ if (mutated) this.requestUpdate();
29758
30285
  }
29759
- /** Live preview during drag — update heights but don't fire public event */
29760
- #onTrackResizeMove;
29761
- /** Final resize on pointerup — apply height and fire public event */
29762
- #onTrackResizeEnd;
29763
- /**
29764
- * Apply track height based on the current `trackHeight` mode.
29765
- * - `fixed`: sets `defaultTrackHeight` (all tracks change uniformly)
29766
- * - `free`: sets per-track override in `_trackHeightOverrides`
29767
- * - `none`: should never be called (resize is disabled)
29768
- */
29769
- #applyTrackResize(trackKey, height) {
29770
- if (this.trackHeight === `fixed`) this.defaultTrackHeight = height;
29771
- else if (this.trackHeight === `free`) {
29772
- const next = new Map(this._trackHeightOverrides);
29773
- next.set(trackKey, height);
29774
- this._trackHeightOverrides = next;
30286
+ _toggleOverflow() {
30287
+ try {
30288
+ this._popover.togglePopover();
30289
+ } catch {
30290
+ this._popover.showPopover();
29775
30291
  }
29776
30292
  }
29777
- #fireSelectionChange() {
29778
- this.dispatchEvent(new CustomEvent(`selection-change`, {
29779
- detail: { selectedIds: [...this._selectedIds] },
29780
- bubbles: true,
29781
- composed: true
29782
- }));
30293
+ render() {
30294
+ const hasOverflow = this._overflowCount > 0;
30295
+ return b`
30296
+ <div class="inner" role="toolbar" aria-orientation=${this.orientation}>
30297
+ <slot></slot>
30298
+ <button class="overflow-btn" ?visible=${hasOverflow} @click=${this._toggleOverflow} aria-label="More" aria-haspopup="true" aria-expanded=${this._popover?.matches(`:popover-open`) ?? false}>⋯</button>
30299
+ </div>
30300
+ <div class="overflow-popover popup-surface" popover="auto" @click=${(e) => e.stopPropagation()}>
30301
+ <slot name="overflow"></slot>
30302
+ </div>
30303
+ `;
29783
30304
  }
29784
30305
  };
29785
- __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "tracks", void 0);
29786
- __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "events", void 0);
29787
- __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "min", void 0);
29788
- __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "max", void 0);
29789
30306
  __decorate([property({
29790
30307
  type: String,
29791
- attribute: `track-height`
29792
- })], IxfxTimelineElement.prototype, "trackHeight", void 0);
30308
+ reflect: true
30309
+ })], ToolbarElement.prototype, "orientation", void 0);
29793
30310
  __decorate([property({
29794
30311
  type: String,
29795
- attribute: `user-scale`
29796
- })], IxfxTimelineElement.prototype, "userScale", void 0);
29797
- __decorate([property({ type: Boolean })], IxfxTimelineElement.prototype, "reorderable", void 0);
30312
+ reflect: true
30313
+ })], ToolbarElement.prototype, "layout", void 0);
29798
30314
  __decorate([property({
29799
- type: Boolean,
29800
- attribute: `meta`
29801
- })], IxfxTimelineElement.prototype, "metaEnabled", void 0);
30315
+ type: String,
30316
+ attribute: `vertical-writing`,
30317
+ reflect: true
30318
+ })], ToolbarElement.prototype, "verticalWriting", void 0);
29802
30319
  __decorate([property({
29803
30320
  type: Boolean,
29804
- attribute: `alt-major-bg`
29805
- })], IxfxTimelineElement.prototype, "altMajorBg", void 0);
29806
- __decorate([property({
29807
- type: Number,
29808
- attribute: `default-track-height`
29809
- })], IxfxTimelineElement.prototype, "defaultTrackHeight", void 0);
29810
- __decorate([property({
29811
- type: String,
29812
- attribute: `grid-mode`
29813
- })], IxfxTimelineElement.prototype, "gridMode", void 0);
30321
+ attribute: `show-group-labels`,
30322
+ reflect: true
30323
+ })], ToolbarElement.prototype, "showGroupLabels", void 0);
29814
30324
  __decorate([property({
29815
- type: Number,
29816
- attribute: `minor-step`
29817
- })], IxfxTimelineElement.prototype, "minorStep", void 0);
29818
- __decorate([property({ type: Object })], IxfxTimelineElement.prototype, "onDragging", void 0);
29819
- __decorate([state()], IxfxTimelineElement.prototype, "_ppu", void 0);
29820
- __decorate([state()], IxfxTimelineElement.prototype, "_viewRange", void 0);
29821
- __decorate([state()], IxfxTimelineElement.prototype, "_vViewRange", void 0);
29822
- __decorate([state()], IxfxTimelineElement.prototype, "_vScale", void 0);
29823
- __decorate([state()], IxfxTimelineElement.prototype, "_selectedIds", void 0);
29824
- __decorate([state()], IxfxTimelineElement.prototype, "_tickledId", void 0);
29825
- __decorate([state()], IxfxTimelineElement.prototype, "_drag", void 0);
29826
- __decorate([state()], IxfxTimelineElement.prototype, "_metaHeight", void 0);
29827
- __decorate([state()], IxfxTimelineElement.prototype, "_trackHeightOverrides", void 0);
29828
- __decorate([state()], IxfxTimelineElement.prototype, "_trackLayout", void 0);
29829
- __decorate([state()], IxfxTimelineElement.prototype, "_internalEvents", void 0);
29830
- __decorate([state()], IxfxTimelineElement.prototype, "_internalTracks", void 0);
29831
- IxfxTimelineElement = __decorate([safeCustomElement(`ixfx-timeline`)], IxfxTimelineElement);
30325
+ type: Boolean,
30326
+ attribute: `invisible-groups`,
30327
+ reflect: true
30328
+ })], ToolbarElement.prototype, "invisibleGroups", void 0);
30329
+ __decorate([state()], ToolbarElement.prototype, "_overflowCount", void 0);
30330
+ __decorate([query(`.inner`)], ToolbarElement.prototype, "_inner", void 0);
30331
+ __decorate([query(`.overflow-popover`)], ToolbarElement.prototype, "_popover", void 0);
30332
+ __decorate([query(`slot`)], ToolbarElement.prototype, "_slot", void 0);
30333
+ ToolbarElement = _ToolbarElement = __decorate([safeCustomElement(`ixfx-toolbar`)], ToolbarElement);
29832
30334
  //#endregion
29833
30335
  //#region src/transitory-label/transitory-label.ts
29834
30336
  let TransitoryLabelElement = class TransitoryLabelElement extends i {
@@ -30689,6 +31191,6 @@ function init() {
30689
31191
  console.log(`Init`);
30690
31192
  }
30691
31193
  //#endregion
30692
- export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, DataGridElement, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, RatingElement, SelectHorizElement, SliderInputElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, ToolbarElement, ToolbarGroupElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
31194
+ export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, DataGridElement, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, RatingElement, SelectHorizElement, SliderInputElement, SlidingNumberElement, SnackbarElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TextShimmerElement, TimelineController, TimelineTrackTabElement, ToolbarElement, ToolbarGroupElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
30693
31195
 
30694
31196
  //# sourceMappingURL=index.js.map