@ixfx/components 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.d.ts +126 -3
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +560 -24
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +1 -1
- package/dist/{colour-picker-BacNRabo.js → colour-picker-C3Ag4uh-.js} +2 -2
- package/dist/{colour-picker-BacNRabo.js.map → colour-picker-C3Ag4uh-.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/{defaults-C3b9OWJD.js → defaults-DcE8RQJc.js} +19 -1
- package/dist/defaults-DcE8RQJc.js.map +1 -0
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +127 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +540 -27
- package/dist/index.js.map +1 -1
- package/dist/labelled-radial-input.d.ts +1 -1
- package/dist/polar-pad.d.ts +1 -1
- package/dist/{radial-input-DXMN55Nz.d.ts → radial-input-BhZeyyP-.d.ts} +2 -2
- package/dist/{radial-input-DXMN55Nz.d.ts.map → radial-input-BhZeyyP-.d.ts.map} +1 -1
- package/dist/radial-input.d.ts +1 -1
- package/dist/range-input.d.ts +1 -1
- package/dist/range.d.ts +1 -1
- package/dist/{slider-input-XppH3vcy.d.ts → slider-input-TidGhvXt.d.ts} +2 -2
- package/dist/{slider-input-XppH3vcy.d.ts.map → slider-input-TidGhvXt.d.ts.map} +1 -1
- package/dist/slider-input.d.ts +1 -1
- package/dist/style.css +1 -1
- package/dist/swipe.d.ts +1 -1
- package/dist/tab-list-BohmbvqF.d.ts.map +1 -1
- package/dist/{tab-list-DzknpdSo.js → tab-list-DhkVhRQc.js} +7 -2
- package/dist/{tab-list-DzknpdSo.js.map → tab-list-DhkVhRQc.js.map} +1 -1
- package/dist/tabs.js +1 -1
- package/dist/wheel-nudge-BlSCe_hD.js.map +1 -1
- package/dist/{wheel-nudge-DGrNzWuE.d.ts → wheel-nudge-DgMTRYlh.d.ts} +3 -3
- package/dist/wheel-nudge-DgMTRYlh.d.ts.map +1 -0
- package/dist/xy-pad.d.ts +1 -1
- package/docs-user/README.md +2 -0
- package/docs-user/button.md +48 -0
- package/docs-user/narrowed-text.md +33 -1
- package/docs-user/notifier.md +131 -0
- package/docs-user/plots.md +61 -1
- package/docs-user/slider-input.md +673 -0
- package/docs-user/tabs.md +12 -14
- package/docs-user/user-catalog.md +69 -4
- package/docs-user/vertical-list.md +75 -7
- package/package.json +3 -1
- package/dist/defaults-C3b9OWJD.js.map +0 -1
- package/dist/wheel-nudge-DGrNzWuE.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -6,14 +6,14 @@ import { a as svgToDataUri, i as registerIcon, n as hasIcon, r as iconBus, t as
|
|
|
6
6
|
import { t as IxfxIconElement } from "./icon-B22XVlCt.js";
|
|
7
7
|
import { AcTextElement } from "./ac-text.js";
|
|
8
8
|
import { a as createFuzzySearch, i as createAcCompletionProvider, n as IncrSearchTreeController, r as createIncrSearch, t as createElementIncrSearch } from "./incr-search-2pz21xtR.js";
|
|
9
|
-
import { i as ICON_CLOSE, n as ICON_CHECK, r as ICON_CHEVRON_DOWN, t as ICON_CARET_RIGHT } from "./defaults-
|
|
9
|
+
import { i as ICON_CLOSE, n as ICON_CHECK, r as ICON_CHEVRON_DOWN, t as ICON_CARET_RIGHT } from "./defaults-DcE8RQJc.js";
|
|
10
10
|
import "./icons.js";
|
|
11
11
|
import { t as prominenceStyles } from "./prominence-DlFShic3.js";
|
|
12
12
|
import { n as buttonStyles, t as ButtonElement } from "./button-DxYee1ZH.js";
|
|
13
13
|
import { t as popupSurfaceStyles } from "./popup-DiWMxsWj.js";
|
|
14
14
|
import "./menu-item-NUKwJ4s5.js";
|
|
15
15
|
import { Checkbox } from "./checkbox.js";
|
|
16
|
-
import { n as ColourPicker, t as ColourPickerPopup } from "./colour-picker-
|
|
16
|
+
import { n as ColourPicker, t as ColourPickerPopup } from "./colour-picker-C3Ag4uh-.js";
|
|
17
17
|
import { LabelledRangeInput } from "./labelled-range-input.js";
|
|
18
18
|
import { t as collectDataResult } from "./data-provider-35TyWclX.js";
|
|
19
19
|
import { i as TreeDataModel, n as TreeListElement, r as TreeBaseElement, t as TreeController } from "./tree-BnvzhsAw.js";
|
|
@@ -40,10 +40,10 @@ import { t as SliderInputElement } from "./slider-input-DFpG23bS.js";
|
|
|
40
40
|
import { SnapContainer } from "./snap-container.js";
|
|
41
41
|
import { SplitLayoutElement } from "./split-layout.js";
|
|
42
42
|
import { SwipeElement } from "./swipe.js";
|
|
43
|
-
import { t as TabListElement } from "./tab-list-
|
|
43
|
+
import { t as TabListElement } from "./tab-list-DhkVhRQc.js";
|
|
44
44
|
import { a as resolveCssVars, i as attachTimelineInteractions, n as TimelineTrackTabElement, o as resolveGrid, r as timelineStyles, s as TimelineController, t as IxfxTimelineElement } from "./timeline-B2fgDL4U.js";
|
|
45
45
|
import { XyPad } from "./xy-pad.js";
|
|
46
|
-
import { LitElement, css, html, nothing } from "lit";
|
|
46
|
+
import { LitElement, css, html, nothing, render } from "lit";
|
|
47
47
|
import { eventOptions, property, query, queryAssignedElements, state } from "lit/decorators.js";
|
|
48
48
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
49
49
|
import { Trees } from "@ixfx/collections";
|
|
@@ -1001,9 +1001,11 @@ let RadioGroup = class RadioGroup extends LitElement {
|
|
|
1001
1001
|
min-width: min-content;
|
|
1002
1002
|
box-sizing: border-box;
|
|
1003
1003
|
/* Default to looking like a cohesive control group */
|
|
1004
|
-
background: var(--surface-
|
|
1004
|
+
background: var(--surface-4, transparent);
|
|
1005
|
+
background: oklch(from var(--surface-4) l calc(c*0.2) h / 0.4);
|
|
1006
|
+
|
|
1005
1007
|
border: var(--border, none);
|
|
1006
|
-
border-radius: var(--radius-
|
|
1008
|
+
border-radius: var(--radius-xl, 8px);
|
|
1007
1009
|
}
|
|
1008
1010
|
|
|
1009
1011
|
* {
|
|
@@ -1033,6 +1035,7 @@ let RadioGroup = class RadioGroup extends LitElement {
|
|
|
1033
1035
|
gap: var(--item-spacing, 0);
|
|
1034
1036
|
overflow: hidden;
|
|
1035
1037
|
border-radius: inherit;
|
|
1038
|
+
justify-content: center;
|
|
1036
1039
|
}
|
|
1037
1040
|
|
|
1038
1041
|
.radio-group.horizontal {
|
|
@@ -1074,13 +1077,13 @@ let RadioGroup = class RadioGroup extends LitElement {
|
|
|
1074
1077
|
|
|
1075
1078
|
.radio-item:hover:not([disabled]) {
|
|
1076
1079
|
opacity: 0.9;
|
|
1077
|
-
background: var(--surface-4
|
|
1080
|
+
background: color-mix(in oklch, var(--surface-4) 80%, transparent);
|
|
1078
1081
|
}
|
|
1079
1082
|
|
|
1080
1083
|
.radio-item.selected {
|
|
1081
1084
|
font-weight: bold;
|
|
1082
1085
|
color: var(--color-fg-accent, var(--surface-2-text));
|
|
1083
|
-
background: var(--surface-
|
|
1086
|
+
background: var(--surface-5, rgba(255,255,255,0.1));
|
|
1084
1087
|
}
|
|
1085
1088
|
|
|
1086
1089
|
.radio-item[disabled] {
|
|
@@ -3356,7 +3359,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
3356
3359
|
this._selectedItems = remapped;
|
|
3357
3360
|
}
|
|
3358
3361
|
this._syncItemStates();
|
|
3359
|
-
}
|
|
3362
|
+
} else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) this._syncCheckboxes();
|
|
3360
3363
|
}
|
|
3361
3364
|
/** The most recently selected item, or `undefined` if nothing is selected. */
|
|
3362
3365
|
get selectedItem() {
|
|
@@ -3552,6 +3555,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
3552
3555
|
}
|
|
3553
3556
|
_syncCheckboxes() {
|
|
3554
3557
|
const inCheckedMode = this.interactionMode === `checked`;
|
|
3558
|
+
const wantsCustom = typeof this.checkboxRenderer === `function`;
|
|
3555
3559
|
if (inCheckedMode) for (const inner of Array.from(this.children)) {
|
|
3556
3560
|
if (!inner.hasAttribute(`data-list-item`)) continue;
|
|
3557
3561
|
if (inner.parentElement !== this) continue;
|
|
@@ -3576,24 +3580,70 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
3576
3580
|
this.#customWrappers.clear();
|
|
3577
3581
|
}
|
|
3578
3582
|
for (const el of this.querySelectorAll(`li`)) {
|
|
3579
|
-
|
|
3580
|
-
if (inCheckedMode) {
|
|
3581
|
-
if (
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
cb.checked
|
|
3594
|
-
|
|
3583
|
+
const existing = el.querySelector(`.ixfx-list-checkbox`);
|
|
3584
|
+
if (!inCheckedMode) {
|
|
3585
|
+
if (existing) existing.remove();
|
|
3586
|
+
continue;
|
|
3587
|
+
}
|
|
3588
|
+
const existingIsCustom = existing?.classList.contains(`ixfx-list-checkbox-custom`) ?? false;
|
|
3589
|
+
if (existing && existingIsCustom !== wantsCustom) existing.remove();
|
|
3590
|
+
let cb = el.querySelector(`.ixfx-list-checkbox`);
|
|
3591
|
+
if (!cb) {
|
|
3592
|
+
cb = wantsCustom ? this._createCustomCheckbox(el) : this._createNativeCheckboxCell(el);
|
|
3593
|
+
el.prepend(cb);
|
|
3594
|
+
}
|
|
3595
|
+
const checked = this._selectedItems.has(el);
|
|
3596
|
+
if (wantsCustom) {
|
|
3597
|
+
cb.setAttribute(`aria-checked`, String(checked));
|
|
3598
|
+
cb.toggleAttribute(`data-checked`, checked);
|
|
3599
|
+
if (this.checkboxRenderer) render(this.checkboxRenderer(checked), cb);
|
|
3600
|
+
} else {
|
|
3601
|
+
const input = cb.querySelector(`input.ixfx-list-checkbox`);
|
|
3602
|
+
if (input) input.checked = checked;
|
|
3603
|
+
}
|
|
3595
3604
|
}
|
|
3596
3605
|
}
|
|
3606
|
+
/**
|
|
3607
|
+
* Native checkbox cell: a span that stretches to the row's full cross-axis
|
|
3608
|
+
* (so the entire column height is a click target) with a real `<input>`
|
|
3609
|
+
* centred inside. The span owns the click; the input is purely visual and
|
|
3610
|
+
* has `pointer-events:none` so a single click produces one toggle.
|
|
3611
|
+
*/
|
|
3612
|
+
_createNativeCheckboxCell(el) {
|
|
3613
|
+
const cell = document.createElement(`span`);
|
|
3614
|
+
cell.className = `ixfx-list-checkbox ixfx-list-checkbox-native`;
|
|
3615
|
+
cell.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:18px;margin:0 6px 0 0;cursor:pointer;pointer-events:auto`;
|
|
3616
|
+
cell.tabIndex = -1;
|
|
3617
|
+
cell.setAttribute(`role`, `checkbox`);
|
|
3618
|
+
cell.setAttribute(`part`, `checkbox`);
|
|
3619
|
+
cell.addEventListener(`click`, (e) => {
|
|
3620
|
+
e.stopPropagation();
|
|
3621
|
+
this._toggleItem(el);
|
|
3622
|
+
});
|
|
3623
|
+
const input = document.createElement(`input`);
|
|
3624
|
+
input.type = `checkbox`;
|
|
3625
|
+
input.className = `ixfx-list-checkbox`;
|
|
3626
|
+
input.style.cssText = `pointer-events:none;cursor:pointer;margin:0`;
|
|
3627
|
+
cell.appendChild(input);
|
|
3628
|
+
return cell;
|
|
3629
|
+
}
|
|
3630
|
+
/**
|
|
3631
|
+
* Custom checkbox cell: same shape as the native cell (a stretching span)
|
|
3632
|
+
* so behaviour is identical. The renderer's content goes inside.
|
|
3633
|
+
*/
|
|
3634
|
+
_createCustomCheckbox(el) {
|
|
3635
|
+
const span = document.createElement(`span`);
|
|
3636
|
+
span.className = `ixfx-list-checkbox ixfx-list-checkbox-custom`;
|
|
3637
|
+
span.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:24px;margin:0 6px 0 0;cursor:pointer;pointer-events:auto`;
|
|
3638
|
+
span.tabIndex = -1;
|
|
3639
|
+
span.setAttribute(`role`, `checkbox`);
|
|
3640
|
+
span.setAttribute(`part`, `checkbox`);
|
|
3641
|
+
span.addEventListener(`click`, (e) => {
|
|
3642
|
+
e.stopPropagation();
|
|
3643
|
+
this._toggleItem(el);
|
|
3644
|
+
});
|
|
3645
|
+
return span;
|
|
3646
|
+
}
|
|
3597
3647
|
_findListItem(path) {
|
|
3598
3648
|
for (const target of path) {
|
|
3599
3649
|
if (!(target instanceof Element)) continue;
|
|
@@ -3655,8 +3705,14 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
3655
3705
|
padding: 0;
|
|
3656
3706
|
width: 100%;
|
|
3657
3707
|
height: 100%;
|
|
3708
|
+
overflow-x: hidden;
|
|
3658
3709
|
overflow-y: auto;
|
|
3659
3710
|
box-sizing: border-box;
|
|
3711
|
+
/* Scrollbar theming: end users override these CSS variables to control
|
|
3712
|
+
the native scrollbar (scrollbar-width, scrollbar-gutter, scrollbar-color). */
|
|
3713
|
+
scrollbar-width: var(--list-scrollbar-width, auto);
|
|
3714
|
+
scrollbar-gutter: var(--list-scrollbar-gutter, auto);
|
|
3715
|
+
scrollbar-color: var(--list-scrollbar-color, auto);
|
|
3660
3716
|
}
|
|
3661
3717
|
|
|
3662
3718
|
::slotted([hidden]) {
|
|
@@ -3686,6 +3742,25 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
3686
3742
|
outline: 1px solid transparent;
|
|
3687
3743
|
}
|
|
3688
3744
|
|
|
3745
|
+
/* In checked mode, only the checkbox column is clickable; the row body
|
|
3746
|
+
gets a default cursor so it doesn't suggest otherwise. */
|
|
3747
|
+
:host([interaction-mode="checked"]) ::slotted(li),
|
|
3748
|
+
:host([interaction-mode="checked"]) ::slotted([data-list-item]) {
|
|
3749
|
+
cursor: default;
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
/* Wrapper inserted around custom [data-list-item] elements in checked mode.
|
|
3753
|
+
Provides the flex layout so the injected checkbox can stretch to the
|
|
3754
|
+
row's full height via align-self:stretch. */
|
|
3755
|
+
.ixfx-custom-row {
|
|
3756
|
+
display: flex;
|
|
3757
|
+
align-items: center;
|
|
3758
|
+
min-height: var(--list-item-height, 28px);
|
|
3759
|
+
box-sizing: border-box;
|
|
3760
|
+
cursor: default;
|
|
3761
|
+
user-select: none;
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3689
3764
|
::slotted([data-tickled]) {
|
|
3690
3765
|
background: var(--item-bg-tickled);
|
|
3691
3766
|
outline: var(--item-border-tickled);
|
|
@@ -3793,6 +3868,7 @@ __decorate([property({
|
|
|
3793
3868
|
attribute: `interaction-mode`
|
|
3794
3869
|
})], VerticalListElement.prototype, "interactionMode", void 0);
|
|
3795
3870
|
__decorate([property({ attribute: false })], VerticalListElement.prototype, "filterPredicate", void 0);
|
|
3871
|
+
__decorate([property({ attribute: false })], VerticalListElement.prototype, "checkboxRenderer", void 0);
|
|
3796
3872
|
__decorate([state()], VerticalListElement.prototype, "_selectedItems", void 0);
|
|
3797
3873
|
__decorate([state()], VerticalListElement.prototype, "_searchVisible", void 0);
|
|
3798
3874
|
__decorate([state()], VerticalListElement.prototype, "_searchQuery", void 0);
|
|
@@ -3928,6 +4004,441 @@ function createVerticalListAdapter(renderItem, options) {
|
|
|
3928
4004
|
return adapter;
|
|
3929
4005
|
}
|
|
3930
4006
|
//#endregion
|
|
4007
|
+
//#region src/notifier/notification-pill.ts
|
|
4008
|
+
let NotificationPillElement = class NotificationPillElement extends LitElement {
|
|
4009
|
+
constructor(..._args) {
|
|
4010
|
+
super(..._args);
|
|
4011
|
+
this.notificationType = `info`;
|
|
4012
|
+
this.message = ``;
|
|
4013
|
+
this.dismissing = false;
|
|
4014
|
+
this.notificationId = ``;
|
|
4015
|
+
}
|
|
4016
|
+
#handleClick() {
|
|
4017
|
+
this.#emitTap();
|
|
4018
|
+
}
|
|
4019
|
+
#handleKeyDown(e) {
|
|
4020
|
+
if (e.key === `Enter` || e.key === ` `) {
|
|
4021
|
+
e.preventDefault();
|
|
4022
|
+
this.#emitTap();
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
#emitTap() {
|
|
4026
|
+
this.dispatchEvent(new CustomEvent(`pill-tap`, {
|
|
4027
|
+
detail: { id: this.notificationId },
|
|
4028
|
+
bubbles: true,
|
|
4029
|
+
composed: true
|
|
4030
|
+
}));
|
|
4031
|
+
}
|
|
4032
|
+
#renderIcon() {
|
|
4033
|
+
if (!this.icon) return nothing;
|
|
4034
|
+
if (this.icon.startsWith(`<svg`)) return html`<span class="pill-icon">${unsafeHTML(this.icon)}</span>`;
|
|
4035
|
+
if (!getIcon(this.icon)) return nothing;
|
|
4036
|
+
return html`<ixfx-icon class="pill-icon" name="${this.icon}"></ixfx-icon>`;
|
|
4037
|
+
}
|
|
4038
|
+
render() {
|
|
4039
|
+
return html`
|
|
4040
|
+
<button
|
|
4041
|
+
type="button"
|
|
4042
|
+
class="pill"
|
|
4043
|
+
notification-type="${this.notificationType}"
|
|
4044
|
+
@click=${this.#handleClick}
|
|
4045
|
+
@keydown=${this.#handleKeyDown}
|
|
4046
|
+
aria-label="${this.message}"
|
|
4047
|
+
>
|
|
4048
|
+
${this.#renderIcon()}
|
|
4049
|
+
<span class="pill-message">${this.message}</span>
|
|
4050
|
+
</button>
|
|
4051
|
+
`;
|
|
4052
|
+
}
|
|
4053
|
+
static {
|
|
4054
|
+
this.styles = [themeFallbacks, css`
|
|
4055
|
+
:host {
|
|
4056
|
+
display: block;
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
.pill {
|
|
4060
|
+
appearance: none;
|
|
4061
|
+
cursor: pointer;
|
|
4062
|
+
font-family: var(--font-family, inherit);
|
|
4063
|
+
font-size: var(--text-m, 12px);
|
|
4064
|
+
padding: var(--space-s, 4px) var(--space-m, 8px);
|
|
4065
|
+
border-radius: var(--radius-l, 6px);
|
|
4066
|
+
border: 1px solid var(--surface-6, #666);
|
|
4067
|
+
display: inline-flex;
|
|
4068
|
+
align-items: center;
|
|
4069
|
+
gap: var(--space-s, 4px);
|
|
4070
|
+
max-width: 300px;
|
|
4071
|
+
box-shadow: var(--shadow-m);
|
|
4072
|
+
transition: opacity 0.2s ease-out, transform 0.2s ease-out;
|
|
4073
|
+
pointer-events: auto;
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
:host([dismissing]) .pill {
|
|
4077
|
+
opacity: 0;
|
|
4078
|
+
transform: translateX(20px);
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
.pill[notification-type="info"] {
|
|
4082
|
+
background: var(--surface-5, #555);
|
|
4083
|
+
color: var(--surface-5-text, #fff);
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
.pill[notification-type="warning"] {
|
|
4087
|
+
background: color-mix(in oklch, oklch(65% 0.18 70) 30%, var(--surface-5));
|
|
4088
|
+
border-color: oklch(65% 0.18 70);
|
|
4089
|
+
color: var(--surface-5-text, #fff);
|
|
4090
|
+
}
|
|
4091
|
+
|
|
4092
|
+
.pill[notification-type="error"] {
|
|
4093
|
+
background: var(--error, #c00);
|
|
4094
|
+
border-color: var(--error, #c00);
|
|
4095
|
+
color: var(--error-text, #fff);
|
|
4096
|
+
}
|
|
4097
|
+
|
|
4098
|
+
.pill-icon {
|
|
4099
|
+
display: inline-flex;
|
|
4100
|
+
align-items: center;
|
|
4101
|
+
flex-shrink: 0;
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
.pill-icon ixfx-icon {
|
|
4105
|
+
font-size: var(--text-m, 12px);
|
|
4106
|
+
}
|
|
4107
|
+
|
|
4108
|
+
.pill-message {
|
|
4109
|
+
white-space: nowrap;
|
|
4110
|
+
overflow: hidden;
|
|
4111
|
+
text-overflow: ellipsis;
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
.pill:focus-visible {
|
|
4115
|
+
outline: 2px solid var(--accent, #4a9);
|
|
4116
|
+
outline-offset: 2px;
|
|
4117
|
+
}
|
|
4118
|
+
|
|
4119
|
+
@media (prefers-reduced-motion: reduce) {
|
|
4120
|
+
.pill {
|
|
4121
|
+
transition: opacity 0.1s ease-out;
|
|
4122
|
+
transform: none !important;
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
`];
|
|
4126
|
+
}
|
|
4127
|
+
};
|
|
4128
|
+
__decorate([property({
|
|
4129
|
+
type: String,
|
|
4130
|
+
attribute: `notification-type`
|
|
4131
|
+
})], NotificationPillElement.prototype, "notificationType", void 0);
|
|
4132
|
+
__decorate([property({ type: String })], NotificationPillElement.prototype, "message", void 0);
|
|
4133
|
+
__decorate([property({ type: String })], NotificationPillElement.prototype, "icon", void 0);
|
|
4134
|
+
__decorate([property({
|
|
4135
|
+
type: Boolean,
|
|
4136
|
+
reflect: true
|
|
4137
|
+
})], NotificationPillElement.prototype, "dismissing", void 0);
|
|
4138
|
+
__decorate([property({
|
|
4139
|
+
type: String,
|
|
4140
|
+
attribute: `notification-id`
|
|
4141
|
+
})], NotificationPillElement.prototype, "notificationId", void 0);
|
|
4142
|
+
NotificationPillElement = __decorate([safeCustomElement(`ixfx-notification-pill`)], NotificationPillElement);
|
|
4143
|
+
//#endregion
|
|
4144
|
+
//#region src/notifier/pill-renderer.ts
|
|
4145
|
+
const ROW_SPACING = 8;
|
|
4146
|
+
const DEFAULT_ROW_HEIGHT = 40;
|
|
4147
|
+
const STACK_OFFSET_STEP = 4;
|
|
4148
|
+
const STACK_OPACITY_BASE = .7;
|
|
4149
|
+
const STACK_OPACITY_DECAY = .15;
|
|
4150
|
+
const STACK_OPACITY_MIN = .2;
|
|
4151
|
+
function edgesOf(position) {
|
|
4152
|
+
return {
|
|
4153
|
+
vertical: position.startsWith(`top`) ? `top` : `bottom`,
|
|
4154
|
+
horizontal: position.endsWith(`-left`) ? `left` : position.endsWith(`-right`) ? `right` : `middle`
|
|
4155
|
+
};
|
|
4156
|
+
}
|
|
4157
|
+
function anchorStyles(position, safeArea) {
|
|
4158
|
+
const { vertical, horizontal } = edgesOf(position);
|
|
4159
|
+
const vMargin = `calc(var(--space-l, 12px) + ${(vertical === `top` ? safeArea.top : safeArea.bottom) ?? 0}px)`;
|
|
4160
|
+
let css = `position: fixed; `;
|
|
4161
|
+
css += vertical === `top` ? `top: ${vMargin}; bottom: auto; ` : `bottom: ${vMargin}; top: auto; `;
|
|
4162
|
+
if (horizontal === `left`) {
|
|
4163
|
+
const hMargin = `calc(var(--space-l, 12px) + ${safeArea.left ?? 0}px)`;
|
|
4164
|
+
css += `left: ${hMargin}; right: auto;`;
|
|
4165
|
+
} else if (horizontal === `right`) {
|
|
4166
|
+
const hMargin = `calc(var(--space-l, 12px) + ${safeArea.right ?? 0}px)`;
|
|
4167
|
+
css += `right: ${hMargin}; left: auto;`;
|
|
4168
|
+
} else css += `left: 50%; right: auto;`;
|
|
4169
|
+
return css;
|
|
4170
|
+
}
|
|
4171
|
+
/** Entry-animation starting transform: pills slide in from the edge they're anchored to. */
|
|
4172
|
+
function entryTransform(edges) {
|
|
4173
|
+
const dy = edges.vertical === `top` ? -20 : 20;
|
|
4174
|
+
if (edges.horizontal === `middle`) return `translateX(-50%) translate(0, ${dy}px)`;
|
|
4175
|
+
return `translate(${edges.horizontal === `left` ? -20 : 20}px, ${dy}px)`;
|
|
4176
|
+
}
|
|
4177
|
+
function restingTransform(edges, dx, dy) {
|
|
4178
|
+
if (edges.horizontal === `middle`) return `translateX(-50%) translate(${dx}px, ${dy}px)`;
|
|
4179
|
+
return `translate(${dx}px, ${dy}px)`;
|
|
4180
|
+
}
|
|
4181
|
+
function createPillRenderer(options = {}) {
|
|
4182
|
+
const position = options.position ?? `top-right`;
|
|
4183
|
+
const queueDisplay = options.queueDisplay ?? `list`;
|
|
4184
|
+
const safeArea = options.safeArea ?? {};
|
|
4185
|
+
const edges = edgesOf(position);
|
|
4186
|
+
let container = null;
|
|
4187
|
+
let hooks = null;
|
|
4188
|
+
const pills = /* @__PURE__ */ new Map();
|
|
4189
|
+
let rowHeight = DEFAULT_ROW_HEIGHT;
|
|
4190
|
+
let measured = false;
|
|
4191
|
+
function ensureContainer() {
|
|
4192
|
+
if (container) return container;
|
|
4193
|
+
container = document.createElement(`div`);
|
|
4194
|
+
container.className = `ixfx-notification-container`;
|
|
4195
|
+
container.setAttribute(`role`, `region`);
|
|
4196
|
+
container.setAttribute(`aria-label`, `Notifications`);
|
|
4197
|
+
document.body.appendChild(container);
|
|
4198
|
+
return container;
|
|
4199
|
+
}
|
|
4200
|
+
function updateAttributes(el, notification) {
|
|
4201
|
+
el.setAttribute(`notification-type`, notification.type);
|
|
4202
|
+
el.setAttribute(`message`, notification.message);
|
|
4203
|
+
if (notification.icon) el.setAttribute(`icon`, notification.icon);
|
|
4204
|
+
else el.removeAttribute(`icon`);
|
|
4205
|
+
}
|
|
4206
|
+
function createPillElement(notification) {
|
|
4207
|
+
const el = document.createElement(`ixfx-notification-pill`);
|
|
4208
|
+
el.setAttribute(`notification-id`, notification.id);
|
|
4209
|
+
el.style.cssText = anchorStyles(position, safeArea);
|
|
4210
|
+
updateAttributes(el, notification);
|
|
4211
|
+
el.style.opacity = `0`;
|
|
4212
|
+
el.style.transform = entryTransform(edges);
|
|
4213
|
+
el.addEventListener(`pill-tap`, (e) => {
|
|
4214
|
+
const customEvent = e;
|
|
4215
|
+
hooks?.onTap(customEvent.detail.id);
|
|
4216
|
+
});
|
|
4217
|
+
return el;
|
|
4218
|
+
}
|
|
4219
|
+
function measureRowHeight(el) {
|
|
4220
|
+
if (measured) return;
|
|
4221
|
+
requestAnimationFrame(() => {
|
|
4222
|
+
const height = el.getBoundingClientRect().height;
|
|
4223
|
+
if (height > 0) {
|
|
4224
|
+
rowHeight = height;
|
|
4225
|
+
measured = true;
|
|
4226
|
+
}
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
/** Positions every currently-visible pill for its rank in `order` (index 0 = front/oldest). */
|
|
4230
|
+
function applyLayout(order) {
|
|
4231
|
+
const total = order.length;
|
|
4232
|
+
order.forEach((notification, index) => {
|
|
4233
|
+
const entry = pills.get(notification.id);
|
|
4234
|
+
if (!entry) return;
|
|
4235
|
+
const el = entry.element;
|
|
4236
|
+
let dx = 0;
|
|
4237
|
+
let dy = 0;
|
|
4238
|
+
let opacity = 1;
|
|
4239
|
+
let pointerEvents = `auto`;
|
|
4240
|
+
let filter = `none`;
|
|
4241
|
+
if (queueDisplay === `list`) {
|
|
4242
|
+
const step = index * (rowHeight + ROW_SPACING);
|
|
4243
|
+
dy = edges.vertical === `top` ? step : -step;
|
|
4244
|
+
} else {
|
|
4245
|
+
const step = index * STACK_OFFSET_STEP;
|
|
4246
|
+
dy = edges.vertical === `top` ? step : -step;
|
|
4247
|
+
dx = edges.horizontal === `left` ? step : edges.horizontal === `right` ? -step : 0;
|
|
4248
|
+
if (index > 0) {
|
|
4249
|
+
const hintIndex = index - 1;
|
|
4250
|
+
opacity = Math.max(STACK_OPACITY_MIN, STACK_OPACITY_BASE - hintIndex * STACK_OPACITY_DECAY);
|
|
4251
|
+
pointerEvents = `none`;
|
|
4252
|
+
filter = `saturate(0.6)`;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
el.style.transition = `opacity 0.2s ease-out, transform 0.2s ease-out`;
|
|
4256
|
+
el.style.opacity = `${opacity}`;
|
|
4257
|
+
el.style.zIndex = `${total - index}`;
|
|
4258
|
+
el.style.pointerEvents = pointerEvents;
|
|
4259
|
+
el.style.filter = filter;
|
|
4260
|
+
el.style.transform = restingTransform(edges, dx, dy);
|
|
4261
|
+
});
|
|
4262
|
+
}
|
|
4263
|
+
function dismiss(id) {
|
|
4264
|
+
const entry = pills.get(id);
|
|
4265
|
+
if (!entry) return;
|
|
4266
|
+
const el = entry.element;
|
|
4267
|
+
el.setAttribute(`dismissing`, `true`);
|
|
4268
|
+
const cleanup = () => {
|
|
4269
|
+
el.removeEventListener(`transitionend`, cleanup);
|
|
4270
|
+
el.remove();
|
|
4271
|
+
pills.delete(id);
|
|
4272
|
+
if (container && pills.size === 0) {
|
|
4273
|
+
container.remove();
|
|
4274
|
+
container = null;
|
|
4275
|
+
measured = false;
|
|
4276
|
+
rowHeight = DEFAULT_ROW_HEIGHT;
|
|
4277
|
+
}
|
|
4278
|
+
};
|
|
4279
|
+
el.addEventListener(`transitionend`, cleanup);
|
|
4280
|
+
setTimeout(cleanup, 300);
|
|
4281
|
+
}
|
|
4282
|
+
function setNotifications(notifications, _queueSize) {
|
|
4283
|
+
const cont = ensureContainer();
|
|
4284
|
+
const idsToKeep = new Set(notifications.map((n) => n.id));
|
|
4285
|
+
for (const notification of notifications) {
|
|
4286
|
+
const existing = pills.get(notification.id);
|
|
4287
|
+
if (existing) {
|
|
4288
|
+
existing.notification = notification;
|
|
4289
|
+
updateAttributes(existing.element, notification);
|
|
4290
|
+
continue;
|
|
4291
|
+
}
|
|
4292
|
+
const el = createPillElement(notification);
|
|
4293
|
+
pills.set(notification.id, {
|
|
4294
|
+
element: el,
|
|
4295
|
+
notification
|
|
4296
|
+
});
|
|
4297
|
+
cont.appendChild(el);
|
|
4298
|
+
measureRowHeight(el);
|
|
4299
|
+
}
|
|
4300
|
+
for (const [id] of pills) if (!idsToKeep.has(id)) dismiss(id);
|
|
4301
|
+
requestAnimationFrame(() => applyLayout(notifications));
|
|
4302
|
+
}
|
|
4303
|
+
return {
|
|
4304
|
+
attach(newHooks) {
|
|
4305
|
+
hooks = newHooks;
|
|
4306
|
+
},
|
|
4307
|
+
detach() {
|
|
4308
|
+
for (const [id] of pills) dismiss(id);
|
|
4309
|
+
if (container) {
|
|
4310
|
+
container.remove();
|
|
4311
|
+
container = null;
|
|
4312
|
+
}
|
|
4313
|
+
},
|
|
4314
|
+
setNotifications
|
|
4315
|
+
};
|
|
4316
|
+
}
|
|
4317
|
+
//#endregion
|
|
4318
|
+
//#region src/notifier/manager.ts
|
|
4319
|
+
const options = {
|
|
4320
|
+
renderer: void 0,
|
|
4321
|
+
timeout: 4e3,
|
|
4322
|
+
timeoutError: 8e3,
|
|
4323
|
+
queue: true,
|
|
4324
|
+
queueSize: 3,
|
|
4325
|
+
tapBehaviour: `dismiss`,
|
|
4326
|
+
tapHandlerDefault: void 0
|
|
4327
|
+
};
|
|
4328
|
+
/** Rank-ordered, index 0 = oldest/first (next to be evicted or timed out). Length never exceeds queueSize (or 1 when queuing is disabled). */
|
|
4329
|
+
const visible = [];
|
|
4330
|
+
let renderer = null;
|
|
4331
|
+
let defaultRenderer = null;
|
|
4332
|
+
function getDefaultRenderer() {
|
|
4333
|
+
defaultRenderer ??= createPillRenderer({ position: `top-right` });
|
|
4334
|
+
return defaultRenderer;
|
|
4335
|
+
}
|
|
4336
|
+
function getRenderer() {
|
|
4337
|
+
return renderer ?? getDefaultRenderer();
|
|
4338
|
+
}
|
|
4339
|
+
function syncRenderer() {
|
|
4340
|
+
getRenderer().setNotifications([...visible], options.queueSize);
|
|
4341
|
+
}
|
|
4342
|
+
function clearTimer(managed) {
|
|
4343
|
+
if (managed.timer !== null) {
|
|
4344
|
+
clearTimeout(managed.timer);
|
|
4345
|
+
managed.timer = null;
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
/**
|
|
4349
|
+
* A message shown alone takes the full timeout. A message that joined a
|
|
4350
|
+
* non-empty queue at arrival time is permanently "wasQueued" and gets
|
|
4351
|
+
* 1/queueSize of the timeout once it reaches the front. The timer for a
|
|
4352
|
+
* given message is only ever started once - when it first becomes front.
|
|
4353
|
+
*/
|
|
4354
|
+
function startTimer(managed) {
|
|
4355
|
+
const base = managed.type === `error` ? options.timeoutError : options.timeout;
|
|
4356
|
+
const duration = managed.wasQueued ? base / options.queueSize : base;
|
|
4357
|
+
managed.timer = window.setTimeout(() => dismiss(managed.id), duration);
|
|
4358
|
+
}
|
|
4359
|
+
function ensureFrontTimer() {
|
|
4360
|
+
const front = visible[0];
|
|
4361
|
+
if (front && front.timer === null) startTimer(front);
|
|
4362
|
+
}
|
|
4363
|
+
const NotificationManager = {
|
|
4364
|
+
configure(opts) {
|
|
4365
|
+
if (opts.renderer !== void 0) {
|
|
4366
|
+
renderer?.detach?.();
|
|
4367
|
+
renderer = opts.renderer;
|
|
4368
|
+
renderer.attach({ onTap(id) {
|
|
4369
|
+
const notification = visible.find((n) => n.id === id);
|
|
4370
|
+
if (!notification) return;
|
|
4371
|
+
if (notification.onTap) notification.onTap(id);
|
|
4372
|
+
else options.tapHandlerDefault?.(notification);
|
|
4373
|
+
if (options.tapBehaviour === `dismiss`) dismiss(id);
|
|
4374
|
+
} });
|
|
4375
|
+
syncRenderer();
|
|
4376
|
+
}
|
|
4377
|
+
if (opts.timeout !== void 0) options.timeout = opts.timeout;
|
|
4378
|
+
if (opts.timeoutError !== void 0) options.timeoutError = opts.timeoutError;
|
|
4379
|
+
if (opts.queue !== void 0) options.queue = opts.queue;
|
|
4380
|
+
if (opts.queueSize !== void 0) {
|
|
4381
|
+
options.queueSize = Math.max(1, opts.queueSize);
|
|
4382
|
+
while (visible.length > options.queueSize) clearTimer(visible.shift());
|
|
4383
|
+
ensureFrontTimer();
|
|
4384
|
+
syncRenderer();
|
|
4385
|
+
}
|
|
4386
|
+
if (opts.tapBehaviour !== void 0) options.tapBehaviour = opts.tapBehaviour;
|
|
4387
|
+
if (opts.tapHandlerDefault !== void 0) options.tapHandlerDefault = opts.tapHandlerDefault;
|
|
4388
|
+
},
|
|
4389
|
+
notify(content) {
|
|
4390
|
+
const id = crypto.randomUUID();
|
|
4391
|
+
const now = Date.now();
|
|
4392
|
+
const icon = content.icon ?? (content.type === `error` ? `error` : void 0);
|
|
4393
|
+
const managed = {
|
|
4394
|
+
...content,
|
|
4395
|
+
icon,
|
|
4396
|
+
id,
|
|
4397
|
+
createdAt: now,
|
|
4398
|
+
updatedAt: now,
|
|
4399
|
+
timer: null,
|
|
4400
|
+
wasQueued: false
|
|
4401
|
+
};
|
|
4402
|
+
if (options.queue) {
|
|
4403
|
+
if (visible.length >= options.queueSize) clearTimer(visible.shift());
|
|
4404
|
+
managed.wasQueued = visible.length > 0;
|
|
4405
|
+
visible.push(managed);
|
|
4406
|
+
} else {
|
|
4407
|
+
while (visible.length > 0) clearTimer(visible.pop());
|
|
4408
|
+
visible.push(managed);
|
|
4409
|
+
}
|
|
4410
|
+
ensureFrontTimer();
|
|
4411
|
+
syncRenderer();
|
|
4412
|
+
return id;
|
|
4413
|
+
},
|
|
4414
|
+
update(id, content) {
|
|
4415
|
+
const managed = visible.find((n) => n.id === id);
|
|
4416
|
+
if (!managed) return;
|
|
4417
|
+
Object.assign(managed, content);
|
|
4418
|
+
managed.updatedAt = Date.now();
|
|
4419
|
+
if (visible[0] === managed) {
|
|
4420
|
+
clearTimer(managed);
|
|
4421
|
+
startTimer(managed);
|
|
4422
|
+
}
|
|
4423
|
+
syncRenderer();
|
|
4424
|
+
},
|
|
4425
|
+
dismiss(id) {
|
|
4426
|
+
dismiss(id);
|
|
4427
|
+
},
|
|
4428
|
+
dismissAll() {
|
|
4429
|
+
for (const m of visible) clearTimer(m);
|
|
4430
|
+
visible.length = 0;
|
|
4431
|
+
syncRenderer();
|
|
4432
|
+
}
|
|
4433
|
+
};
|
|
4434
|
+
function dismiss(id) {
|
|
4435
|
+
const idx = visible.findIndex((m) => m.id === id);
|
|
4436
|
+
if (idx === -1) return;
|
|
4437
|
+
clearTimer(visible.splice(idx, 1)[0]);
|
|
4438
|
+
ensureFrontTimer();
|
|
4439
|
+
syncRenderer();
|
|
4440
|
+
}
|
|
4441
|
+
//#endregion
|
|
3931
4442
|
//#region src/panel/panel-group.ts
|
|
3932
4443
|
let PanelGroupElement = class PanelGroupElement extends LitElement {
|
|
3933
4444
|
constructor(..._args) {
|
|
@@ -4616,7 +5127,7 @@ let TabListItemElement = class TabListItemElement extends LitElement {
|
|
|
4616
5127
|
prominenceStyles,
|
|
4617
5128
|
css`
|
|
4618
5129
|
:host {
|
|
4619
|
-
--selected-colour: var(--
|
|
5130
|
+
--selected-colour: var(--surface-2-text);
|
|
4620
5131
|
--selected-border-width: 1px;
|
|
4621
5132
|
--padding: var(--space-m);
|
|
4622
5133
|
display: inline-flex;
|
|
@@ -4642,6 +5153,8 @@ let TabListItemElement = class TabListItemElement extends LitElement {
|
|
|
4642
5153
|
border-bottom-color: var(--indicator-color-bottom, transparent);
|
|
4643
5154
|
border-left-color: var(--indicator-color-left, transparent);
|
|
4644
5155
|
border-right-color: var(--indicator-color-right, transparent);
|
|
5156
|
+
background: var(--surface-5);
|
|
5157
|
+
font-weight: bold;
|
|
4645
5158
|
}
|
|
4646
5159
|
|
|
4647
5160
|
.label {
|
|
@@ -5104,6 +5617,6 @@ function init() {
|
|
|
5104
5617
|
console.log(`Init`);
|
|
5105
5618
|
}
|
|
5106
5619
|
//#endregion
|
|
5107
|
-
export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, 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, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SliderInputElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
|
|
5620
|
+
export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, 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, SelectHorizontalElement, SliderInputElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, 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 };
|
|
5108
5621
|
|
|
5109
5622
|
//# sourceMappingURL=index.js.map
|