@ixfx/components 0.3.2 → 0.4.1
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 +1086 -603
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +16153 -15296
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +14 -4
- package/dist/ac-text.d.ts.map +1 -1
- package/dist/ac-text.js +11 -6
- package/dist/ac-text.js.map +1 -1
- package/dist/{button-DMt5XWUK.js → button-C3fLMKUv.js} +4 -4
- package/dist/{button-DMt5XWUK.js.map → button-C3fLMKUv.js.map} +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/button.js +1 -1
- package/dist/checkbox.d.ts +2 -2
- package/dist/checkbox.d.ts.map +1 -1
- package/dist/checkbox.js +14 -8
- package/dist/checkbox.js.map +1 -1
- package/dist/{colour-C3MQIjFJ-BLXg8W3U.js → colour-C3MQIjFJ-vRCdr8W-.js} +146 -552
- package/dist/colour-C3MQIjFJ-vRCdr8W-.js.map +1 -0
- package/dist/{colour-picker-K6zu82lm.js → colour-picker-0sgAha1T.js} +14 -9
- package/dist/colour-picker-0sgAha1T.js.map +1 -0
- package/dist/colour-picker.d.ts +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.d.ts.map +1 -1
- package/dist/crumbs.js +11 -6
- package/dist/crumbs.js.map +1 -1
- package/dist/data-display.d.ts +9 -4
- package/dist/data-display.d.ts.map +1 -1
- package/dist/data-display.js +270 -43
- package/dist/data-display.js.map +1 -1
- package/dist/data-provider-DgI909FP.js +23 -0
- package/dist/data-provider-DgI909FP.js.map +1 -0
- package/dist/{decorate-D7rC1gLP.js → decorate-DdjvVHS-.js} +2 -2
- package/dist/{decorate-D7rC1gLP.js.map → decorate-DdjvVHS-.js.map} +1 -1
- package/dist/{defaults-C7elhuyJ.js → defaults-C3b9OWJD.js} +2 -2
- package/dist/{defaults-C7elhuyJ.js.map → defaults-C3b9OWJD.js.map} +1 -1
- package/dist/{dist-TAGYwaju.js → dist-CA13FvMn.js} +7 -66
- package/dist/dist-CA13FvMn.js.map +1 -0
- package/dist/editable-label.d.ts.map +1 -1
- package/dist/editable-label.js +3 -2
- package/dist/editable-label.js.map +1 -1
- package/dist/fallbacks-pNMOMx38.js +168 -0
- package/dist/fallbacks-pNMOMx38.js.map +1 -0
- package/dist/{hex-editor-DlfoA65y.d.ts → hex-editor-CMIxtNgT.d.ts} +1 -1
- package/dist/hex-editor-CMIxtNgT.d.ts.map +1 -0
- package/dist/{hex-editor-CsN_ySkH.js → hex-editor-WZrjRtvL.js} +3 -3
- package/dist/{hex-editor-CsN_ySkH.js.map → hex-editor-WZrjRtvL.js.map} +1 -1
- package/dist/hex.d.ts +1 -1
- package/dist/hex.js +1 -1
- package/dist/{highlight-TPbSHruI.js → highlight-B-eQrhhb.js} +1 -1
- package/dist/{highlight-TPbSHruI.js.map → highlight-B-eQrhhb.js.map} +1 -1
- package/dist/{icon-9NWTXtE1.js → icon-Ndo40kNO.js} +6 -5
- package/dist/icon-Ndo40kNO.js.map +1 -0
- package/dist/{icon-Dm_DHDz6.d.ts → icon-epZd-JIO.d.ts} +2 -2
- package/dist/icon-epZd-JIO.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/icons.js +3 -3
- package/dist/{incr-search-DSKKsk6w.js → incr-search-CeERfijK.js} +2 -2
- package/dist/{incr-search-DSKKsk6w.js.map → incr-search-CeERfijK.js.map} +1 -1
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +2 -2
- package/dist/{index-hXFn14tM.d.ts → index-BMjri2-S.d.ts} +2 -2
- package/dist/{index-hXFn14tM.d.ts.map → index-BMjri2-S.d.ts.map} +1 -1
- package/dist/{index-DSlPeWLK.d.ts → index-CWpNcQKE.d.ts} +5 -5
- package/dist/index-CWpNcQKE.d.ts.map +1 -0
- package/dist/{index-DLkSKL4T.d.ts → index-CowKi2mo.d.ts} +1 -1
- package/dist/index-CowKi2mo.d.ts.map +1 -0
- package/dist/{index-B1hNR7Z9.d.ts → index-D87kRcEs.d.ts} +1 -1
- package/dist/{index-B1hNR7Z9.d.ts.map → index-D87kRcEs.d.ts.map} +1 -1
- package/dist/{index-CnL9krsH.d.ts → index-DgXpCg_G.d.ts} +32 -26
- package/dist/index-DgXpCg_G.d.ts.map +1 -0
- package/dist/{index-iZLld8Ca.d.ts → index-JuEVfmr-.d.ts} +2 -2
- package/dist/index-JuEVfmr-.d.ts.map +1 -0
- package/dist/index.d.ts +432 -121
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2369 -1706
- package/dist/index.js.map +1 -1
- package/dist/interaction-D6efrBLo.js +1 -0
- package/dist/{keyboard-De_vOHLg.js → keyboard-CimiEskD.js} +1 -1
- package/dist/{keyboard-De_vOHLg.js.map → keyboard-CimiEskD.js.map} +1 -1
- package/dist/{labelled-input-base-CqPL5rKm.js → labelled-input-base-9K_w3oLj.js} +2 -2
- package/dist/{labelled-input-base-CqPL5rKm.js.map → labelled-input-base-9K_w3oLj.js.map} +1 -1
- package/dist/{labelled-input-base-BVvNeb5R.d.ts → labelled-input-base-Cz6qE6Dk.d.ts} +1 -1
- package/dist/labelled-input-base-Cz6qE6Dk.d.ts.map +1 -0
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-radial-input.js +7 -6
- package/dist/labelled-radial-input.js.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-range-input.js +2 -2
- package/dist/led.d.ts +1 -1
- package/dist/led.d.ts.map +1 -1
- package/dist/led.js +2 -2
- package/dist/led.js.map +1 -1
- package/dist/{menu-item-CKRfP0pN.js → menu-item-BrIuORYD.js} +20 -10
- package/dist/menu-item-BrIuORYD.js.map +1 -0
- package/dist/{menu-item-ClQF2DKN.d.ts → menu-item-COx-Azgj.d.ts} +1 -1
- package/dist/menu-item-COx-Azgj.d.ts.map +1 -0
- package/dist/{menu-DJJuCm-5.js → menu-vjoiHZ13.js} +30 -17
- package/dist/menu-vjoiHZ13.js.map +1 -0
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +2 -2
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +18 -11
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.d.ts.map +1 -1
- package/dist/narrowed-text.js +7 -5
- package/dist/narrowed-text.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/panel.d.ts.map +1 -1
- package/dist/panel.js +5 -4
- package/dist/panel.js.map +1 -1
- package/dist/plots.d.ts +2 -2
- package/dist/plots.js +2 -2
- package/dist/polar-pad.d.ts +1 -1
- package/dist/polar-pad.d.ts.map +1 -1
- package/dist/polar-pad.js +10 -4
- package/dist/polar-pad.js.map +1 -1
- package/dist/{popup-ImtS9KnS.js → popup-DiWMxsWj.js} +1 -1
- package/dist/{popup-ImtS9KnS.js.map → popup-DiWMxsWj.js.map} +1 -1
- package/dist/prominence-DlFShic3.js +104 -0
- package/dist/prominence-DlFShic3.js.map +1 -0
- package/dist/{radial-input-LUSBEycd.d.ts → radial-input-CpQPs1Mp.d.ts} +1 -1
- package/dist/radial-input-CpQPs1Mp.d.ts.map +1 -0
- package/dist/{radial-input-DZA6WaFu.js → radial-input-DZ7eQCcM.js} +11 -6
- package/dist/radial-input-DZ7eQCcM.js.map +1 -0
- package/dist/radial-input.d.ts +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.d.ts +1 -1
- package/dist/range-input.d.ts.map +1 -1
- package/dist/range-input.js +9 -4
- package/dist/range-input.js.map +1 -1
- package/dist/range.d.ts +1 -1
- package/dist/range.d.ts.map +1 -1
- package/dist/range.js +5 -3
- package/dist/range.js.map +1 -1
- package/dist/{registry-Q2gYQCHM.js → registry-CkW7q09Q.js} +1 -1
- package/dist/{registry-Q2gYQCHM.js.map → registry-CkW7q09Q.js.map} +1 -1
- package/dist/selecthorizontal.d.ts +1 -1
- package/dist/selecthorizontal.d.ts.map +1 -1
- package/dist/selecthorizontal.js +4 -3
- package/dist/selecthorizontal.js.map +1 -1
- package/dist/snap-container.d.ts.map +1 -1
- package/dist/snap-container.js +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/split-layout.d.ts.map +1 -1
- package/dist/split-layout.js +6 -5
- package/dist/split-layout.js.map +1 -1
- package/dist/style.css +14 -4
- package/dist/swipe.d.ts.map +1 -1
- package/dist/swipe.js +9 -4
- package/dist/swipe.js.map +1 -1
- package/dist/{tab-list-BnqISNvO.d.ts → tab-list-DLzb-m-I.d.ts} +2 -2
- package/dist/tab-list-DLzb-m-I.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +10 -4
- package/dist/tabs.js.map +1 -1
- package/dist/{tickled-controller-Cq1Va0rR.d.ts → tickled-controller-BjYCzGrU.d.ts} +2 -2
- package/dist/tickled-controller-BjYCzGrU.d.ts.map +1 -0
- package/dist/{tickled-styles-Bg3QbcrD.js → tickled-styles-fNDdqf6l.js} +1 -17
- package/dist/{tickled-styles-Bg3QbcrD.js.map → tickled-styles-fNDdqf6l.js.map} +1 -1
- package/dist/{timeline-Bh0PhlKW.js → timeline-2OFtN4Ta.js} +2 -2
- package/dist/{timeline-Bh0PhlKW.js.map → timeline-2OFtN4Ta.js.map} +1 -1
- package/dist/timeline.d.ts +1 -1
- package/dist/timeline.js +1 -1
- package/dist/{tooltip-DMxmBNky.js → tooltip-CJt3WLmN.js} +1 -1
- package/dist/{tooltip-DMxmBNky.js.map → tooltip-CJt3WLmN.js.map} +1 -1
- package/dist/{tooltip-CwGfb4lp.d.ts → tooltip-RGVIwHrZ.d.ts} +1 -1
- package/dist/{tooltip-CwGfb4lp.d.ts.map → tooltip-RGVIwHrZ.d.ts.map} +1 -1
- package/dist/{tree-CvvKbO-f.js → tree-CJWpMUvD.js} +113 -103
- package/dist/tree-CJWpMUvD.js.map +1 -0
- package/dist/{tree-component-D8Bg48tt.d.ts → tree-component-BcO26Xvt.d.ts} +65 -3
- package/dist/tree-component-BcO26Xvt.d.ts.map +1 -0
- package/dist/tree.d.ts +15 -15
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/{types-BKaqnpwx.d.ts → types-DSfbtHs3.d.ts} +1 -1
- package/dist/types-DSfbtHs3.d.ts.map +1 -0
- package/dist/{xy-axis-DL0tfJDr.js → xy-axis-CK64haaK.js} +1831 -359
- package/dist/xy-axis-CK64haaK.js.map +1 -0
- package/dist/{xy-axis-D9uwpGTT.d.ts → xy-axis-McdUpcYr.d.ts} +102 -3
- package/dist/xy-axis-McdUpcYr.d.ts.map +1 -0
- package/dist/xy-pad.d.ts +1 -1
- package/dist/xy-pad.d.ts.map +1 -1
- package/dist/xy-pad.js +11 -6
- package/dist/xy-pad.js.map +1 -1
- package/docs-user/README.md +45 -0
- package/docs-user/ac-text.md +67 -0
- package/docs-user/ac-token.md +187 -0
- package/docs-user/button.md +355 -0
- package/docs-user/checkbox.md +62 -0
- package/docs-user/colour-picker.md +237 -0
- package/docs-user/crumbs.md +66 -0
- package/docs-user/data-display.md +98 -0
- package/docs-user/editable-label.md +244 -0
- package/docs-user/grouped-item-lister.md +424 -0
- package/docs-user/icons.md +191 -0
- package/docs-user/incr-search.md +94 -0
- package/docs-user/labelled-radial-input.md +204 -0
- package/docs-user/labelled-range-input.md +194 -0
- package/docs-user/led.md +40 -0
- package/docs-user/menu.md +319 -0
- package/docs-user/miller.md +453 -0
- package/docs-user/narrowed-text.md +72 -0
- package/docs-user/panel.md +250 -0
- package/docs-user/plots.md +361 -0
- package/docs-user/polar-pad.md +228 -0
- package/docs-user/radial-input.md +559 -0
- package/docs-user/range-input.md +264 -0
- package/docs-user/range.md +12 -0
- package/docs-user/selecthorizontal.md +32 -0
- package/docs-user/snap-container.md +132 -0
- package/docs-user/split-layout.md +232 -0
- package/docs-user/swipe.md +44 -0
- package/docs-user/tabs.md +217 -0
- package/docs-user/timeline.md +116 -0
- package/docs-user/transitory-label.md +120 -0
- package/docs-user/tree.md +592 -0
- package/docs-user/user-catalog.md +165 -0
- package/docs-user/user-theming.md +379 -0
- package/docs-user/util.md +122 -0
- package/docs-user/vertical-list.md +351 -0
- package/docs-user/xy-pad.md +94 -0
- package/package.json +19 -18
- package/dist/colour-C3MQIjFJ-BLXg8W3U.js.map +0 -1
- package/dist/colour-picker-K6zu82lm.js.map +0 -1
- package/dist/dist-BX0OVIm7.js +0 -1290
- package/dist/dist-BX0OVIm7.js.map +0 -1
- package/dist/dist-TAGYwaju.js.map +0 -1
- package/dist/hex-editor-DlfoA65y.d.ts.map +0 -1
- package/dist/icon-9NWTXtE1.js.map +0 -1
- package/dist/icon-Dm_DHDz6.d.ts.map +0 -1
- package/dist/index-CnL9krsH.d.ts.map +0 -1
- package/dist/index-DLkSKL4T.d.ts.map +0 -1
- package/dist/index-DSlPeWLK.d.ts.map +0 -1
- package/dist/index-iZLld8Ca.d.ts.map +0 -1
- package/dist/interaction-DG7X1rhI.js +0 -1
- package/dist/labelled-input-base-BVvNeb5R.d.ts.map +0 -1
- package/dist/menu-DJJuCm-5.js.map +0 -1
- package/dist/menu-item-CKRfP0pN.js.map +0 -1
- package/dist/menu-item-ClQF2DKN.d.ts.map +0 -1
- package/dist/prominence--ic9uWBl.js +0 -98
- package/dist/prominence--ic9uWBl.js.map +0 -1
- package/dist/radial-input-DZA6WaFu.js.map +0 -1
- package/dist/radial-input-LUSBEycd.d.ts.map +0 -1
- package/dist/tab-list-BnqISNvO.d.ts.map +0 -1
- package/dist/tickled-controller-Cq1Va0rR.d.ts.map +0 -1
- package/dist/tree-CvvKbO-f.js.map +0 -1
- package/dist/tree-component-D8Bg48tt.d.ts.map +0 -1
- package/dist/types-BKaqnpwx.d.ts.map +0 -1
- package/dist/xy-axis-D9uwpGTT.d.ts.map +0 -1
- package/dist/xy-axis-DL0tfJDr.js.map +0 -1
- /package/bundle/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
- /package/dist/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# `ixfx-vertical-list`
|
|
2
|
+
|
|
3
|
+
A scrollable vertical list of items with selection, keyboard navigation, and incremental search. Items can be plain `<li>` elements declared in HTML or rich custom elements added programmatically.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
1. [Quick start](#quick-start)
|
|
10
|
+
2. [Item types](#item-types)
|
|
11
|
+
3. [Properties](#properties)
|
|
12
|
+
4. [Selection](#selection)
|
|
13
|
+
5. [Events](#events)
|
|
14
|
+
6. [Keyboard navigation](#keyboard-navigation)
|
|
15
|
+
7. [Incremental search](#incremental-search)
|
|
16
|
+
8. [CSS variables](#css-variables)
|
|
17
|
+
9. [CSS parts](#css-parts)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
### Declarative HTML items
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<ixfx-vertical-list id="my-list" selection-mode="single">
|
|
27
|
+
<li>Apple</li>
|
|
28
|
+
<li>Banana</li>
|
|
29
|
+
<li>Cherry</li>
|
|
30
|
+
</ixfx-vertical-list>
|
|
31
|
+
|
|
32
|
+
<script type="module">
|
|
33
|
+
import '@ixfx/components/vertical-list';
|
|
34
|
+
|
|
35
|
+
const list = document.querySelector('#my-list');
|
|
36
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
37
|
+
const [item] = detail.selected;
|
|
38
|
+
console.log('selected:', item?.textContent);
|
|
39
|
+
});
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Programmatic items
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import type { VerticalListElement } from '@ixfx/components';
|
|
47
|
+
|
|
48
|
+
const list = document.querySelector<VerticalListElement>('ixfx-vertical-list')!;
|
|
49
|
+
|
|
50
|
+
list.addItem('Document A');
|
|
51
|
+
list.addItem('Image 01.png');
|
|
52
|
+
|
|
53
|
+
// Or pass an element directly
|
|
54
|
+
const li = document.createElement('li');
|
|
55
|
+
li.textContent = 'Custom item';
|
|
56
|
+
list.addItem(li);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Item types
|
|
62
|
+
|
|
63
|
+
### Plain `<li>` elements
|
|
64
|
+
|
|
65
|
+
The simplest item type. Styled directly via `::slotted(li)` CSS from the component's shadow DOM.
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<ixfx-vertical-list>
|
|
69
|
+
<li>Item one</li>
|
|
70
|
+
<li>Item two</li>
|
|
71
|
+
</ixfx-vertical-list>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Searchable text is the element's `textContent`. Override with `data-search-label` for custom search terms:
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<li data-search-label="document a alpha">Document A</li>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Custom shadow-DOM components
|
|
81
|
+
|
|
82
|
+
Any element with a `data-list-item` attribute is recognised as a list item. This enables rich card-style rows built with Lit or any other framework:
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<ixfx-vertical-list>
|
|
86
|
+
<my-track-card data-list-item track-title="Bohemian Rhapsody" artist="Queen"></my-track-card>
|
|
87
|
+
</ixfx-vertical-list>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Because the component cannot reach inside a custom element's shadow root, you must expose searchable text via a `data-search-label` attribute on the host element. The recommended pattern is to set this in the custom element's `willUpdate` lifecycle:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
override willUpdate(changed: PropertyValues) {
|
|
94
|
+
super.willUpdate(changed);
|
|
95
|
+
if (changed.has('trackTitle') || changed.has('artist')) {
|
|
96
|
+
this.setAttribute('data-search-label', `${this.trackTitle} ${this.artist}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To reflect selection state inside the custom element's shadow DOM, target the `:host([data-selected])` CSS selector:
|
|
102
|
+
|
|
103
|
+
```css
|
|
104
|
+
:host([data-selected]) .title {
|
|
105
|
+
color: var(--item-text-selected, #fff);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Properties
|
|
112
|
+
|
|
113
|
+
| Property / Attribute | Type | Default | Description |
|
|
114
|
+
|---|---|---|---|
|
|
115
|
+
| `selectionMode` / `selection-mode` | `'none' \| 'single' \| 'multiple'` | `'single'` | Which items can be selected simultaneously |
|
|
116
|
+
| `interactionMode` / `interaction-mode` | `ListInteractionMode` | `'standard'` | How gestures map to selection changes (see table below) |
|
|
117
|
+
| `filterPredicate` | `((el: Element) => boolean) \| undefined` | `undefined` | External filter; only items returning `true` are shown |
|
|
118
|
+
|
|
119
|
+
Switching `interactionMode` always clears the current selection.
|
|
120
|
+
|
|
121
|
+
### `interactionMode`
|
|
122
|
+
|
|
123
|
+
| Value | Behaviour |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `'implicit'` | Click always replaces selection. No modifier support. |
|
|
126
|
+
| `'standard'` | Plain click replaces selection; Ctrl/Cmd+click toggles; Shift+click range-selects (multiple mode only); Cmd+A selects all |
|
|
127
|
+
| `'vscode'` | Like `standard` for clicks; Shift+Arrow extends the range from the keyboard anchor |
|
|
128
|
+
| `'checked'` | Checkboxes on every `<li>` row; checkbox click (or Space) toggles; body clicks do nothing. Custom elements show a left-border indicator instead of a checkbox |
|
|
129
|
+
| `'manual'` | No automatic selection; drive state entirely via `select()` / `deselect()` / `clearSelection()` |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Selection
|
|
134
|
+
|
|
135
|
+
### Programmatic API
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Replace selection with a single item
|
|
139
|
+
list.select(element);
|
|
140
|
+
|
|
141
|
+
// Replace selection with multiple items — requires selectionMode="multiple", throws otherwise
|
|
142
|
+
list.selectMany([elementA, elementB, elementC]);
|
|
143
|
+
|
|
144
|
+
// Remove one item from the selection
|
|
145
|
+
list.deselect(element);
|
|
146
|
+
|
|
147
|
+
// Clear entire selection
|
|
148
|
+
list.clearSelection();
|
|
149
|
+
|
|
150
|
+
// Select all visible items (only works when multiple selection is effective)
|
|
151
|
+
list.selectAll();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Adding and removing items
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
// Append a string (wrapped in <li>) or an Element
|
|
158
|
+
list.addItem('New item');
|
|
159
|
+
list.addItem(myElement);
|
|
160
|
+
|
|
161
|
+
// Remove a specific element
|
|
162
|
+
list.removeItem(element);
|
|
163
|
+
|
|
164
|
+
// Remove all items and clear selection
|
|
165
|
+
list.clearItems();
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Reading the selection
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// Most recently selected item (primary selection)
|
|
172
|
+
const item = list.selectedItem;
|
|
173
|
+
if (item) console.log(item.textContent?.trim());
|
|
174
|
+
|
|
175
|
+
// Full selection set
|
|
176
|
+
for (const el of list.selectedItems) {
|
|
177
|
+
console.log(el.textContent?.trim());
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Via event
|
|
181
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
182
|
+
const { selected, previous } = detail;
|
|
183
|
+
for (const el of selected) {
|
|
184
|
+
console.log(el.textContent?.trim());
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Attribute hooks on items
|
|
190
|
+
|
|
191
|
+
The component reflects state onto list items as data attributes. Use these in CSS or to read state from JavaScript:
|
|
192
|
+
|
|
193
|
+
| Attribute | Set when |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `data-tickled` | The keyboard/pointer cursor is on this item |
|
|
196
|
+
| `data-selected` | The item is in the current selection |
|
|
197
|
+
| `data-checked` | Set in `checked` mode; mirrors `data-selected` |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Events
|
|
202
|
+
|
|
203
|
+
All events **bubble** and are **composed** (they cross shadow-DOM boundaries).
|
|
204
|
+
|
|
205
|
+
| Event | Detail type | When fired |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `list-select` | `ListSelectDetail` | Selection changes by any means |
|
|
208
|
+
| `list-tickle` | `ListTickleDetail` | An item enters cursor focus (hover or keyboard navigation) |
|
|
209
|
+
| `list-activate` | `ListActivateDetail` | User explicitly activates an item: Enter key or double-click |
|
|
210
|
+
| `list-item-click` | `ListItemClickDetail` | Raw click or Enter on any item |
|
|
211
|
+
|
|
212
|
+
### Detail types
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
type ListSelectDetail = {
|
|
216
|
+
readonly selected: ReadonlySet<Element>; // Current full selection
|
|
217
|
+
readonly previous: ReadonlySet<Element>; // Selection before this change
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
type ListTickleDetail = { readonly item: Element };
|
|
221
|
+
type ListActivateDetail = { readonly item: Element };
|
|
222
|
+
type ListItemClickDetail = { readonly item: Element };
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Usage example
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
229
|
+
const labels = [...detail.selected]
|
|
230
|
+
.map(el => el.getAttribute('data-search-label') ?? el.textContent?.trim())
|
|
231
|
+
.join(', ');
|
|
232
|
+
console.log('selection:', labels);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
list.addEventListener('list-tickle', ({ detail }) => {
|
|
236
|
+
previewPane.show(detail.item);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
list.addEventListener('list-activate', ({ detail }) => {
|
|
240
|
+
router.navigate(detail.item.dataset.key);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
list.addEventListener('list-item-click', ({ detail }) => {
|
|
244
|
+
analytics.track('list-click', detail.item.dataset.key);
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Keyboard navigation
|
|
251
|
+
|
|
252
|
+
The element must be focused (click it or tab to it) before keyboard navigation works. A visible focus ring appears on focus.
|
|
253
|
+
|
|
254
|
+
| Key | Action |
|
|
255
|
+
|---|---|
|
|
256
|
+
| `Arrow Down` | Move cursor to next visible item |
|
|
257
|
+
| `Arrow Up` | Move cursor to previous visible item |
|
|
258
|
+
| `Enter` | Activate the cursor item — fires `list-item-click` then `list-activate`; selects the item (except in `manual` mode) |
|
|
259
|
+
| `Space` | Toggle selection on the cursor item |
|
|
260
|
+
| `Shift+Arrow Down/Up` | Extend range from anchor (`vscode` mode only) |
|
|
261
|
+
| `Ctrl/Cmd+A` | Select all visible items (when effective multiple selection is on) |
|
|
262
|
+
| `Ctrl/Cmd+F` | Open the incremental search overlay |
|
|
263
|
+
| `Escape` | Clear the current selection (or close the search overlay if open) |
|
|
264
|
+
|
|
265
|
+
### While the search overlay is open
|
|
266
|
+
|
|
267
|
+
| Key | Action |
|
|
268
|
+
|---|---|
|
|
269
|
+
| `Arrow Down / Up` | Move cursor through the filtered list |
|
|
270
|
+
| `Enter` | Activate the cursor item (or first visible item) and close search |
|
|
271
|
+
| `Escape` | Close search overlay |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Incremental search
|
|
276
|
+
|
|
277
|
+
Press **Ctrl+F** (or **Cmd+F**) to open the search overlay. Typing filters items in real time using fuzzy matching. Matched text in plain `<li>` items is highlighted via the [CSS Highlight API](https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API).
|
|
278
|
+
|
|
279
|
+
### Adding the page-level highlight rule
|
|
280
|
+
|
|
281
|
+
The CSS Highlight API requires a `::highlight()` rule in the page stylesheet to make matches visible. Add this to your page:
|
|
282
|
+
|
|
283
|
+
```css
|
|
284
|
+
::highlight(vertical-list-search) {
|
|
285
|
+
background: var(--accent);
|
|
286
|
+
color: var(--accent-text, #fff);
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Without this rule the filtering still works (non-matching items are hidden) but matched text inside `<li>` items will not be highlighted.
|
|
291
|
+
|
|
292
|
+
### Searchable text
|
|
293
|
+
|
|
294
|
+
| Item type | Default search text | Override |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| `<li>` | `textContent` | `data-search-label` attribute |
|
|
297
|
+
| `[data-list-item]` custom element | `data-search-label` attribute | — |
|
|
298
|
+
|
|
299
|
+
Custom elements must always set `data-search-label` since the component cannot read their shadow DOM content.
|
|
300
|
+
|
|
301
|
+
### External `filterPredicate`
|
|
302
|
+
|
|
303
|
+
Supply a custom filter function to hide items independently of the search overlay:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// Show only items tagged as 'document'
|
|
307
|
+
list.filterPredicate = (el) => el.dataset.type === 'document';
|
|
308
|
+
|
|
309
|
+
// Remove the filter
|
|
310
|
+
list.filterPredicate = undefined;
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## CSS variables
|
|
316
|
+
|
|
317
|
+
| Variable | Default | Description |
|
|
318
|
+
|---|---|---|
|
|
319
|
+
| `--list-bg` | `var(--surface-3)` | List background |
|
|
320
|
+
| `--list-text` | `var(--surface-3-text)` | Default text colour |
|
|
321
|
+
| `--list-border` | `var(--border)` | Border colour |
|
|
322
|
+
| `--list-radius` | `var(--radius-s)` | Border radius |
|
|
323
|
+
| `--list-item-height` | `28px` | Minimum row height for `<li>` items |
|
|
324
|
+
| `--list-item-padding` | `4px var(--space-m, 8px)` | Padding for `<li>` items |
|
|
325
|
+
| `--item-bg-tickled` | `rgba(0,0,0,0.06)` | Row background when cursor is on it |
|
|
326
|
+
| `--item-bg-selected` | `rgba(25,118,210,1)` | Selected row background |
|
|
327
|
+
| `--item-text-selected` | `#fff` | Selected row text colour |
|
|
328
|
+
| `--item-bg-selected-tickled` | `rgba(21,101,192,1)` | Selected + cursor row background |
|
|
329
|
+
| `--accent` | — | Accent colour (focus ring, search highlight, checkbox) |
|
|
330
|
+
| `--transition` | `0.1s ease-out` | Transition timing for hover/selection changes |
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## CSS parts
|
|
335
|
+
|
|
336
|
+
| Part | Element |
|
|
337
|
+
|---|---|
|
|
338
|
+
| `list` | The `<ul>` scroll container |
|
|
339
|
+
| `search-overlay` | The floating search input overlay |
|
|
340
|
+
|
|
341
|
+
Use `::part()` to style these from outside the component's shadow DOM:
|
|
342
|
+
|
|
343
|
+
```css
|
|
344
|
+
ixfx-vertical-list::part(list) {
|
|
345
|
+
padding: 4px 0;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
ixfx-vertical-list::part(search-overlay) {
|
|
349
|
+
border-radius: 8px;
|
|
350
|
+
}
|
|
351
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# `ixfx-xy-pad`
|
|
2
|
+
|
|
3
|
+
A 2D touch-friendly XY pad for controlling two parameters simultaneously. Each axis supports independent linear/logarithmic scaling.
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<ixfx-xy-pad></ixfx-xy-pad>
|
|
7
|
+
<ixfx-xy-pad x-min="0" x-max="1" y-min="0" y-max="1" x-label="Volume" y-label="Pan"></ixfx-xy-pad>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
const pad = document.querySelector('ixfx-xy-pad');
|
|
12
|
+
pad.xMin = 0;
|
|
13
|
+
pad.xMax = 100;
|
|
14
|
+
pad.yMin = 0;
|
|
15
|
+
pad.yMax = 100;
|
|
16
|
+
pad.xScale = 'linear';
|
|
17
|
+
pad.yScale = 'log'; // logarithmic scaling for y axis
|
|
18
|
+
|
|
19
|
+
pad.addEventListener('input', e => {
|
|
20
|
+
console.log(`x: ${e.detail.x.toFixed(2)}, y: ${e.detail.y.toFixed(2)}`);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
pad.addEventListener('change', e => {
|
|
24
|
+
console.log('drag ended:', e.detail);
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Properties / attributes
|
|
29
|
+
|
|
30
|
+
| Attribute / Property | Type | Default | Description |
|
|
31
|
+
|-----------------------|------------------------|------------|----------------------------------------------|
|
|
32
|
+
| `xMin` | `number` | `1` | Minimum X value |
|
|
33
|
+
| `xMax` | `number` | `100` | Maximum X value |
|
|
34
|
+
| `x` | `number` | `50` | Current X value |
|
|
35
|
+
| `yMin` | `number` | `1` | Minimum Y value |
|
|
36
|
+
| `yMax` | `number` | `100` | Maximum Y value |
|
|
37
|
+
| `y` | `number` | `50` | Current Y value |
|
|
38
|
+
| `xScale` | `'linear' \| 'log'` | `'linear'` | X axis scaling |
|
|
39
|
+
| `yScale` | `'linear' \| 'log'` | `'linear'` | Y axis scaling |
|
|
40
|
+
| `xSnapStep` | `number \| undefined` | `undefined`| X axis snap granularity (`x-snap-step`) |
|
|
41
|
+
| `ySnapStep` | `number \| undefined` | `undefined`| Y axis snap granularity (`y-snap-step`) |
|
|
42
|
+
| `xLabel` | `string` | `'X'` | X axis label text |
|
|
43
|
+
| `yLabel` | `string` | `'Y'` | Y axis label text |
|
|
44
|
+
| `showCrosshairs` | `boolean` | `false` | Show crosshair lines |
|
|
45
|
+
| `showGrid` | `boolean` | `false` | Show background grid |
|
|
46
|
+
| `hideCursor` | `boolean` | `false` | Hide cursor during drag |
|
|
47
|
+
| `disabled` | `boolean` | `false` | Disable all interaction |
|
|
48
|
+
| `stops` | `number \| undefined` | `undefined`| Quantized stops for both axes |
|
|
49
|
+
| `stopsX` | `number \| undefined` | `undefined`| Quantized stops for X axis only |
|
|
50
|
+
| `stopsY` | `number \| undefined` | `undefined`| Quantized stops for Y axis only |
|
|
51
|
+
|
|
52
|
+
### Events
|
|
53
|
+
|
|
54
|
+
| Event | Detail | Description |
|
|
55
|
+
|----------|---------------------------|----------------------------------------|
|
|
56
|
+
| `input` | `{ x: number, y: number }` | Continuously during drag |
|
|
57
|
+
| `change` | `{ x: number, y: number }` | When drag ends (pointer release) |
|
|
58
|
+
|
|
59
|
+
### Methods
|
|
60
|
+
|
|
61
|
+
| Method | Returns | Description |
|
|
62
|
+
|------------------|------------------------------|--------------------------------------------------|
|
|
63
|
+
| `getRelativeX()` | `number` (0–1) | X position as fraction |
|
|
64
|
+
| `getRelativeY()` | `number` (0–1) | Y position as fraction |
|
|
65
|
+
| `getPolar()` | `{ radius: number, angle: number }` | Polar coordinates (radius 0–1, angle 0–2π radians, 0 = right, clockwise) |
|
|
66
|
+
|
|
67
|
+
### Keyboard navigation
|
|
68
|
+
|
|
69
|
+
Arrow keys move the position. Hold Shift for finer control (step divisor).
|
|
70
|
+
|
|
71
|
+
### CSS custom properties
|
|
72
|
+
|
|
73
|
+
| Property | Default | Description |
|
|
74
|
+
|-----------------------|----------------------|---------------------------------------|
|
|
75
|
+
| `--marker-size` | `10cqb` | Position marker diameter |
|
|
76
|
+
| `--crosshair-color` | `var(--surface-6)` | Crosshair line color |
|
|
77
|
+
| `--crosshair-width` | `2px` | Crosshair line thickness |
|
|
78
|
+
| `--crosshair-x-color` | `var(--crosshair-color)` | Vertical crosshair color |
|
|
79
|
+
| `--crosshair-x-width` | `var(--crosshair-width)` | Vertical crosshair thickness |
|
|
80
|
+
| `--crosshair-y-color` | `var(--crosshair-color)` | Horizontal crosshair color |
|
|
81
|
+
| `--crosshair-y-width` | `var(--crosshair-width)` | Horizontal crosshair thickness |
|
|
82
|
+
| `--grid-color` | `var(--surface-6)` | Grid line color |
|
|
83
|
+
| `--grid-width` | `1px` | Grid line thickness |
|
|
84
|
+
| `--xy-pad-bg` | `var(--surface-3)` | Pad background colour |
|
|
85
|
+
|
|
86
|
+
### CSS properties set on host (for external use)
|
|
87
|
+
|
|
88
|
+
The component sets these custom properties on its host element during drag:
|
|
89
|
+
|
|
90
|
+
| Property | Description |
|
|
91
|
+
|------------|----------------------------------------------|
|
|
92
|
+
| `--x-pct` | X position as 0–100 percentage |
|
|
93
|
+
| `--y-pct` | Y position as 0–100 percentage |
|
|
94
|
+
| `--radius-pct` | Distance from centre as 0–100 percentage |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixfx/components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.1",
|
|
5
5
|
"description": "",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "ISC",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"types": "./dist/incr-search.d.ts",
|
|
20
20
|
"import": "./dist/incr-search.js"
|
|
21
21
|
},
|
|
22
|
-
"
|
|
22
|
+
"./*.js": {
|
|
23
23
|
"types": "./dist/*.d.ts",
|
|
24
24
|
"import": "./dist/*.js"
|
|
25
25
|
}
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"main": "dist/index.js",
|
|
28
28
|
"files": [
|
|
29
29
|
"bundle",
|
|
30
|
-
"dist"
|
|
30
|
+
"dist",
|
|
31
|
+
"docs-user"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
34
|
"typecheck": "tsc --noEmit",
|
|
@@ -48,23 +49,23 @@
|
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@antfu/eslint-config": "^9.0.0",
|
|
50
51
|
"@clinth/vcanvas": "0.0.3",
|
|
51
|
-
"@ixfx/arrays": "0.56.
|
|
52
|
-
"@ixfx/collections": "0.56.
|
|
53
|
-
"@ixfx/core": "0.56.
|
|
54
|
-
"@ixfx/dom": "0.56.
|
|
55
|
-
"@ixfx/flow": "0.56.
|
|
56
|
-
"@ixfx/geometry": "0.56.
|
|
57
|
-
"@ixfx/modulation": "0.56.
|
|
58
|
-
"@ixfx/numbers": "0.56.
|
|
59
|
-
"@ixfx/visual": "0.56.
|
|
60
|
-
"@tsdown/css": "0.22.
|
|
61
|
-
"eslint": "10.4.
|
|
52
|
+
"@ixfx/arrays": "0.56.13",
|
|
53
|
+
"@ixfx/collections": "0.56.13",
|
|
54
|
+
"@ixfx/core": "0.56.13",
|
|
55
|
+
"@ixfx/dom": "0.56.13",
|
|
56
|
+
"@ixfx/flow": "0.56.13",
|
|
57
|
+
"@ixfx/geometry": "0.56.13",
|
|
58
|
+
"@ixfx/modulation": "0.56.13",
|
|
59
|
+
"@ixfx/numbers": "0.56.13",
|
|
60
|
+
"@ixfx/visual": "0.56.13",
|
|
61
|
+
"@tsdown/css": "0.22.1",
|
|
62
|
+
"eslint": "10.4.1",
|
|
62
63
|
"eslint-plugin-format": "2.0.1",
|
|
63
64
|
"globals": "17.6.0",
|
|
64
|
-
"knip": "6.14.
|
|
65
|
-
"tsdown": "0.22.
|
|
65
|
+
"knip": "6.14.2",
|
|
66
|
+
"tsdown": "0.22.1",
|
|
66
67
|
"typescript": "6.0.3",
|
|
67
|
-
"typescript-eslint": "8.
|
|
68
|
-
"vite": "8.0.
|
|
68
|
+
"typescript-eslint": "8.60.0",
|
|
69
|
+
"vite": "8.0.14"
|
|
69
70
|
}
|
|
70
71
|
}
|