@ixfx/components 0.11.6 → 0.11.7

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 (35) hide show
  1. package/bundle/index.d.ts +61 -1
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +638 -2
  4. package/bundle/index.js.map +1 -1
  5. package/dist/checkbox.d.ts +3 -0
  6. package/dist/checkbox.d.ts.map +1 -1
  7. package/dist/checkbox.js +24 -1
  8. package/dist/checkbox.js.map +1 -1
  9. package/dist/checked-select-CglRukbP.d.ts +59 -0
  10. package/dist/checked-select-CglRukbP.d.ts.map +1 -0
  11. package/dist/checked-select-Dejl13qd.js +604 -0
  12. package/dist/checked-select-Dejl13qd.js.map +1 -0
  13. package/dist/checked-select.d.ts +2 -0
  14. package/dist/checked-select.js +3 -0
  15. package/dist/{detail-list-CmdCxddo.d.ts → detail-list-CgkOHYOa.d.ts} +3 -1
  16. package/dist/{detail-list-CmdCxddo.d.ts.map → detail-list-CgkOHYOa.d.ts.map} +1 -1
  17. package/dist/detail-list.d.ts +1 -1
  18. package/dist/detail-list.js +22 -0
  19. package/dist/detail-list.js.map +1 -1
  20. package/dist/{hex-editor-BiRfwTz1.js → hex-editor-DiYpgIKs.js} +2 -2
  21. package/dist/{hex-editor-BiRfwTz1.js.map → hex-editor-DiYpgIKs.js.map} +1 -1
  22. package/dist/hex.js +1 -1
  23. package/dist/index.d.ts +3 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/plots.js +1 -1
  28. package/dist/{xy-axis-COKw338Q.js → xy-axis-CyMd_Bn1.js} +2 -2
  29. package/dist/{xy-axis-COKw338Q.js.map → xy-axis-CyMd_Bn1.js.map} +1 -1
  30. package/docs-user/README.md +1 -0
  31. package/docs-user/checked-select.md +63 -0
  32. package/docs-user/index.json +6 -1
  33. package/docs-user/llms.txt +1 -0
  34. package/llms.txt +1 -0
  35. package/package.json +5 -1
@@ -0,0 +1,604 @@
1
+ import { t as TickledController } from "./tickled-controller-Dh1Uh_vG.js";
2
+ import { n as tickledStyles, t as tickledItemStyles } from "./tickled-styles-BrAHEj1q.js";
3
+ import { t as themeFallbacks } from "./fallbacks-DQ_5OsmR.js";
4
+ import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
5
+ import { t as handleStyles } from "./handle-DAXs7kbJ.js";
6
+ import "./interaction-BskmlA9t.js";
7
+ import "./checkbox.js";
8
+ import { LitElement, css, html, nothing } from "lit";
9
+ import { property, state } from "lit/decorators.js";
10
+ import { repeat } from "lit/directives/repeat.js";
11
+ //#region src/checked-select/logic.ts
12
+ function byLabel(a, b) {
13
+ return a.label.localeCompare(b.label, void 0, { sensitivity: `base` });
14
+ }
15
+ /** Checked/indeterminate items first, then the rest; each group sorted by label. */
16
+ function sortForOpen(items) {
17
+ const on = items.filter((i) => i.checked !== `false`).toSorted(byLabel);
18
+ const off = items.filter((i) => i.checked === `false`).toSorted(byLabel);
19
+ return [...on, ...off];
20
+ }
21
+ /** User toggle: indeterminate and unchecked become checked, checked becomes unchecked. */
22
+ function toggleState(state) {
23
+ return state === `true` ? `false` : `true`;
24
+ }
25
+ /** Items shown in the resting state, alphabetically. */
26
+ function visibleAtRest(items) {
27
+ return items.filter((i) => i.checked !== `false`).toSorted(byLabel);
28
+ }
29
+ const VARIES_LABEL = `(varies)`;
30
+ /** Resting text entries: checked labels, then a single `(varies)` if any are indeterminate. */
31
+ function restTextParts(items) {
32
+ const on = items.filter((i) => i.checked === `true`).toSorted(byLabel).map((i) => i.label);
33
+ const varies = items.some((i) => i.checked === `indeterminate`) ? [VARIES_LABEL] : [];
34
+ return [...on, ...varies];
35
+ }
36
+ /** Plain-text resting summary, comma separated. */
37
+ function restText(items) {
38
+ return restTextParts(items).join(`, `);
39
+ }
40
+ /** Returns a new list with the item matching `value` toggled. */
41
+ function applyToggle(items, value) {
42
+ return items.map((i) => i.value === value ? {
43
+ ...i,
44
+ checked: toggleState(i.checked)
45
+ } : i);
46
+ }
47
+ /**
48
+ * Index of the next label after `current` beginning with `char` (case-insensitive),
49
+ * wrapping around. Returns -1 if nothing matches.
50
+ */
51
+ function nextMatchIndex(labels, current, char) {
52
+ const c = char.toLocaleLowerCase();
53
+ const count = labels.length;
54
+ for (let step = 1; step <= count; step++) {
55
+ const index = (current + step + count) % count;
56
+ if (labels[index].toLocaleLowerCase().startsWith(c)) return index;
57
+ }
58
+ return -1;
59
+ }
60
+ /** Items in `draft` whose state differs from `original`. */
61
+ function diffItems(original, draft) {
62
+ const before = new Map(original.map((i) => [i.value, i.checked]));
63
+ return draft.filter((i) => before.get(i.value) !== i.checked);
64
+ }
65
+ function clampSize(size, min, max) {
66
+ return {
67
+ width: Math.min(Math.max(size.width, min.width), Math.max(max.width, min.width)),
68
+ height: Math.min(Math.max(size.height, min.height), Math.max(max.height, min.height))
69
+ };
70
+ }
71
+ //#endregion
72
+ //#region src/checked-select/checked-select.ts
73
+ let instanceCounter = 0;
74
+ let CheckedSelect = class CheckedSelect extends LitElement {
75
+ constructor(..._args) {
76
+ super(..._args);
77
+ this.items = [];
78
+ this.multiline = false;
79
+ this.itemsInert = false;
80
+ this.itemDisplay = `checkbox`;
81
+ this.orientation = `horizontal`;
82
+ this.placeholder = ``;
83
+ this.disabled = false;
84
+ this._open = false;
85
+ this._draft = [];
86
+ this._order = [];
87
+ this.#anchorName = `--checked-select-anchor-${instanceCounter++}`;
88
+ this.#tickled = new TickledController(this, { getItems: () => this._order.map((_, i) => ({ id: i })) });
89
+ this.#onRestCheckboxChange = (e, value) => {
90
+ e.stopPropagation();
91
+ if (this._open) return;
92
+ const next = applyToggle(this.items, value);
93
+ this.#emitChange(next, diffItems(this.items, next));
94
+ this.#focusRestCheckbox(value);
95
+ };
96
+ this.#onDocumentPointerDown = (e) => {
97
+ const path = e.composedPath();
98
+ const popup = this.#popup;
99
+ const trigger = this.#trigger;
100
+ if (popup && path.includes(popup) || trigger && path.includes(trigger)) return;
101
+ this.cancel();
102
+ };
103
+ this.#onTriggerClick = (e) => {
104
+ if (e.target.closest?.(`ixfx-checkbox`)) return;
105
+ const scroller = e.composedPath()[0];
106
+ if (scroller.classList?.contains(`rest-items`) && e instanceof MouseEvent && (e.offsetX > scroller.clientWidth || e.offsetY > scroller.clientHeight)) return;
107
+ if (this._open) this.commit();
108
+ else this.open();
109
+ };
110
+ this.#onTriggerKeyDown = (e) => {
111
+ if (this._open || e.target !== e.currentTarget) return;
112
+ if (e.key === `Enter` || e.key === ` ` || e.key === `ArrowDown`) {
113
+ e.preventDefault();
114
+ this.open();
115
+ }
116
+ };
117
+ this.#onListKeyDown = (e) => {
118
+ const rows = this.#rows();
119
+ switch (e.key) {
120
+ case `ArrowDown`:
121
+ e.preventDefault();
122
+ this.#tickled.handleKeyboardNavigation(`next`);
123
+ this.#scrollToCursor();
124
+ return;
125
+ case `ArrowUp`:
126
+ e.preventDefault();
127
+ this.#tickled.handleKeyboardNavigation(`previous`);
128
+ this.#scrollToCursor();
129
+ return;
130
+ case `Home`:
131
+ e.preventDefault();
132
+ this.#tickled.handleKeyboardNavigation(`first`);
133
+ this.#scrollToCursor();
134
+ return;
135
+ case `End`:
136
+ e.preventDefault();
137
+ this.#tickled.handleKeyboardNavigation(`last`);
138
+ this.#scrollToCursor();
139
+ return;
140
+ case ` `: {
141
+ e.preventDefault();
142
+ const row = rows[this.#tickled.tickledId ?? -1];
143
+ if (row) this.#toggleRow(row.value);
144
+ return;
145
+ }
146
+ case `Enter`:
147
+ e.preventDefault();
148
+ this.commit();
149
+ return;
150
+ case `Escape`:
151
+ e.preventDefault();
152
+ this.cancel();
153
+ return;
154
+ case `Tab`:
155
+ this.cancel();
156
+ return;
157
+ }
158
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
159
+ const next = nextMatchIndex(rows.map((r) => r.label), this.#tickled.tickledId ?? -1, e.key);
160
+ if (next >= 0) {
161
+ this.#tickled.handleKeyboardNavigation(next);
162
+ this.#scrollToCursor();
163
+ }
164
+ }
165
+ };
166
+ this.#onResizeDown = (e) => {
167
+ const frame = this.shadowRoot?.querySelector(`.frame`);
168
+ const zone = e.currentTarget;
169
+ if (!frame) return;
170
+ e.preventDefault();
171
+ const start = frame.getBoundingClientRect();
172
+ const originX = e.clientX;
173
+ const originY = e.clientY;
174
+ const style = getComputedStyle(this);
175
+ const min = {
176
+ width: Number.parseFloat(style.getPropertyValue(`--checked-select-min-width`)) || 128,
177
+ height: Number.parseFloat(style.getPropertyValue(`--checked-select-min-height`)) || 80
178
+ };
179
+ const max = {
180
+ width: window.innerWidth - start.left - 8,
181
+ height: window.innerHeight - start.top - 8
182
+ };
183
+ zone.setPointerCapture?.(e.pointerId);
184
+ zone.setAttribute(`data-active`, ``);
185
+ const onMove = (m) => {
186
+ this._size = clampSize({
187
+ width: start.width + m.clientX - originX,
188
+ height: start.height + m.clientY - originY
189
+ }, min, max);
190
+ };
191
+ const onEnd = () => {
192
+ zone.removeAttribute(`data-active`);
193
+ zone.removeEventListener(`pointermove`, onMove);
194
+ zone.removeEventListener(`pointerup`, onEnd);
195
+ zone.removeEventListener(`pointercancel`, onEnd);
196
+ this.#listbox?.focus();
197
+ };
198
+ zone.addEventListener(`pointermove`, onMove);
199
+ zone.addEventListener(`pointerup`, onEnd);
200
+ zone.addEventListener(`pointercancel`, onEnd);
201
+ };
202
+ }
203
+ static {
204
+ this.styles = [
205
+ themeFallbacks,
206
+ handleStyles,
207
+ tickledStyles,
208
+ tickledItemStyles,
209
+ css`
210
+ :host {
211
+ --checked-select-gap: var(--space-m);
212
+ --checked-select-padding: var(--space-s) var(--space-m);
213
+ --checked-select-caret-width: 2rem;
214
+ --checked-select-rest-max-height: 8rem;
215
+ --checked-select-max-height: 16rem;
216
+ --checked-select-min-width: 8rem;
217
+ --checked-select-min-height: 5rem;
218
+
219
+ display: block;
220
+ position: relative;
221
+ }
222
+
223
+ :host([disabled]) {
224
+ opacity: var(--prominence-disabled-opacity, 0.4);
225
+ pointer-events: none;
226
+ }
227
+
228
+ .rest {
229
+ position: relative;
230
+ box-sizing: border-box;
231
+ cursor: pointer;
232
+ background: var(--surface-4);
233
+ color: var(--surface-4-text);
234
+ border: var(--border);
235
+ border-radius: var(--radius-m);
236
+ user-select: none;
237
+ }
238
+
239
+ .rest-items {
240
+ display: flex;
241
+ flex-wrap: nowrap;
242
+ align-items: center;
243
+ gap: var(--checked-select-gap);
244
+ padding: var(--checked-select-padding);
245
+ /* Room to scroll the last item clear of the caret */
246
+ padding-inline-end: var(--checked-select-caret-width);
247
+ min-height: 1.5em;
248
+ box-sizing: border-box;
249
+ overflow-x: auto;
250
+ overflow-y: hidden;
251
+ scrollbar-width: thin;
252
+ }
253
+ :host([multiline]) .rest-items {
254
+ flex-wrap: wrap;
255
+ overflow-x: hidden;
256
+ overflow-y: auto;
257
+ max-height: var(--checked-select-rest-max-height);
258
+ /* Wrapping never runs under the caret, so keep its column clear (and the scrollbar beside it) */
259
+ padding-inline-end: var(--space-m);
260
+ margin-inline-end: var(--checked-select-caret-width);
261
+ }
262
+
263
+ /* Vertical: one item per row, scrolling vertically beside the caret. Must follow the multiline rule. */
264
+ :host([orientation="vertical"]) .rest-items {
265
+ flex-direction: column;
266
+ flex-wrap: nowrap;
267
+ align-items: flex-start;
268
+ overflow-x: hidden;
269
+ overflow-y: auto;
270
+ max-height: var(--checked-select-rest-max-height);
271
+ padding-inline-end: var(--space-m);
272
+ margin-inline-end: var(--checked-select-caret-width);
273
+ }
274
+
275
+ /* Always-visible caret; items scroll underneath it */
276
+ .caret {
277
+ position: absolute;
278
+ inset-block: 0;
279
+ inset-inline-end: 0;
280
+ width: var(--checked-select-caret-width);
281
+ display: grid;
282
+ place-items: center;
283
+ background: inherit;
284
+ border-radius: inherit;
285
+ pointer-events: auto;
286
+ }
287
+ .caret svg {
288
+ width: 1.1em;
289
+ height: 1.1em;
290
+ fill: none;
291
+ stroke: currentColor;
292
+ stroke-width: 2;
293
+ stroke-linecap: round;
294
+ stroke-linejoin: round;
295
+ transition: rotate var(--transition, 0.1s ease-out);
296
+ }
297
+ .rest[aria-expanded="true"] .caret svg {
298
+ rotate: 180deg;
299
+ }
300
+ /* While the popup is open its draft is authoritative */
301
+ .rest[aria-expanded="true"] ixfx-checkbox {
302
+ pointer-events: none;
303
+ }
304
+ .rest:hover {
305
+ background: var(--surface-5);
306
+ }
307
+ .rest:focus-visible {
308
+ outline: 2px solid var(--accent);
309
+ outline-offset: 2px;
310
+ }
311
+ .rest ixfx-checkbox {
312
+ flex-shrink: 0;
313
+ }
314
+ .rest-text {
315
+ white-space: nowrap;
316
+ }
317
+ :host([multiline]) .rest-text {
318
+ white-space: normal;
319
+ }
320
+ .placeholder {
321
+ opacity: 0.6;
322
+ }
323
+
324
+ .popup {
325
+ /* Reset popover UA styles */
326
+ inset: unset;
327
+ margin: 0;
328
+ padding: 0;
329
+ border: none;
330
+ background: transparent;
331
+ overflow: visible;
332
+
333
+ /* CSS anchor positioning — position-anchor set inline */
334
+ position: fixed;
335
+ left: anchor(left);
336
+ top: anchor(bottom);
337
+ /* anchor-size() only works on the anchored element itself, so the width lives here */
338
+ width: anchor-size(width);
339
+ min-width: var(--checked-select-min-width);
340
+ position-try-fallbacks: flip-block;
341
+ margin-block: 4px;
342
+ z-index: 100;
343
+ }
344
+
345
+ .frame {
346
+ position: relative;
347
+ box-sizing: border-box;
348
+ display: flex;
349
+ flex-direction: column;
350
+ width: 100%;
351
+ max-height: var(--checked-select-max-height);
352
+ background: var(--surface-3);
353
+ color: var(--surface-3-text);
354
+ border: var(--border);
355
+ border-radius: var(--radius-m);
356
+ }
357
+
358
+ .listbox {
359
+ flex: 1;
360
+ min-height: 0;
361
+ overflow-y: auto;
362
+ padding: var(--space-s);
363
+ outline: none;
364
+ }
365
+ .listbox:focus-visible {
366
+ outline: 2px solid var(--accent);
367
+ outline-offset: -2px;
368
+ }
369
+
370
+ .item {
371
+ display: flex;
372
+ width: 100%;
373
+ box-sizing: border-box;
374
+ }
375
+
376
+ /* Key-repeat outpaces the fade, smearing the cursor across rows. Snap while
377
+ the keyboard drives the cursor; hover (mouse mode) keeps the transition. */
378
+ .listbox[data-input-mode="keyboard"] .item {
379
+ transition: none;
380
+ }
381
+
382
+ .resize-zone {
383
+ position: absolute;
384
+ inset-block-end: 0;
385
+ inset-inline-end: 0;
386
+ width: 16px;
387
+ height: 16px;
388
+ display: grid;
389
+ place-items: center;
390
+ cursor: nwse-resize;
391
+ touch-action: none;
392
+ }
393
+ .resize-zone .ixfx-handle {
394
+ --ixfx-handle-spot-size: 10px;
395
+ }
396
+ `
397
+ ];
398
+ }
399
+ #anchorName;
400
+ #tickled;
401
+ get isOpen() {
402
+ return this._open;
403
+ }
404
+ get #trigger() {
405
+ return this.shadowRoot?.querySelector(`.rest`) ?? null;
406
+ }
407
+ get #popup() {
408
+ return this.shadowRoot?.querySelector(`.popup`) ?? null;
409
+ }
410
+ get #listbox() {
411
+ return this.shadowRoot?.querySelector(`.listbox`) ?? null;
412
+ }
413
+ /** Draft items in their frozen open-time order. */
414
+ #rows() {
415
+ const byValue = new Map(this._draft.map((i) => [i.value, i]));
416
+ return this._order.flatMap((v) => byValue.get(v) ?? []);
417
+ }
418
+ disconnectedCallback() {
419
+ super.disconnectedCallback();
420
+ document.removeEventListener(`pointerdown`, this.#onDocumentPointerDown, true);
421
+ }
422
+ willUpdate(changed) {
423
+ super.willUpdate(changed);
424
+ if (changed.has(`disabled`) && this.disabled && this._open) this.cancel();
425
+ }
426
+ async open() {
427
+ if (this._open || this.disabled) return;
428
+ this._draft = this.items;
429
+ this._order = sortForOpen(this.items).map((i) => i.value);
430
+ this._size = void 0;
431
+ this._open = true;
432
+ if (this._order.length > 0) this.#tickled.handleKeyboardNavigation(`first`);
433
+ document.addEventListener(`pointerdown`, this.#onDocumentPointerDown, true);
434
+ await this.updateComplete;
435
+ this.#popup?.showPopover?.();
436
+ this.#listbox?.focus();
437
+ }
438
+ commit() {
439
+ if (!this._open) return;
440
+ const changed = diffItems(this.items, this._draft);
441
+ const next = this._draft;
442
+ this.#close();
443
+ if (changed.length === 0) return;
444
+ this.#emitChange(next, changed);
445
+ }
446
+ #emitChange(next, changed) {
447
+ this.items = next;
448
+ this.dispatchEvent(new CustomEvent(`change`, {
449
+ detail: {
450
+ items: next,
451
+ changed
452
+ },
453
+ bubbles: true,
454
+ composed: true
455
+ }));
456
+ }
457
+ /** A resting checkbox was used directly: toggle and commit immediately. */
458
+ #onRestCheckboxChange;
459
+ async #focusRestCheckbox(value) {
460
+ await this.updateComplete;
461
+ (this.shadowRoot?.querySelector(`.rest ixfx-checkbox[data-value="${CSS.escape(value)}"]`) ?? this.#trigger)?.focus();
462
+ }
463
+ cancel() {
464
+ if (!this._open) return;
465
+ this.#close();
466
+ }
467
+ #close() {
468
+ document.removeEventListener(`pointerdown`, this.#onDocumentPointerDown, true);
469
+ this.#popup?.hidePopover?.();
470
+ this._open = false;
471
+ this._draft = [];
472
+ this.#tickled.clearTickled();
473
+ this.#trigger?.focus();
474
+ }
475
+ #onDocumentPointerDown;
476
+ #onTriggerClick;
477
+ #onTriggerKeyDown;
478
+ #toggleRow(value) {
479
+ this._draft = applyToggle(this._draft, value);
480
+ }
481
+ #onRowClick(value, index) {
482
+ this.#tickled.setTickled(index);
483
+ this.#toggleRow(value);
484
+ }
485
+ #onListKeyDown;
486
+ async #scrollToCursor() {
487
+ await this.updateComplete;
488
+ const index = this.#tickled.tickledId;
489
+ this.shadowRoot?.querySelector(`[data-index="${index}"]`)?.scrollIntoView?.({ block: `nearest` });
490
+ }
491
+ #onResizeDown;
492
+ #renderRest() {
493
+ const shown = visibleAtRest(this.items);
494
+ if (shown.length === 0) return html`<span class="placeholder">${this.placeholder}</span>`;
495
+ if (this.itemDisplay === `text`) {
496
+ if (this.orientation === `vertical`) return restTextParts(this.items).map((part) => html`<span class="rest-text">${part}</span>`);
497
+ return html`<span class="rest-text">${restText(this.items)}</span>`;
498
+ }
499
+ return repeat(shown, (i) => i.value, (i) => html`
500
+ <ixfx-checkbox
501
+ ?readonly=${this.itemsInert}
502
+ data-value=${i.value}
503
+ label=${i.label}
504
+ .checked=${i.checked === `true`}
505
+ .indeterminate=${i.checked === `indeterminate`}
506
+ @change=${(e) => this.#onRestCheckboxChange(e, i.value)}
507
+ ></ixfx-checkbox>`);
508
+ }
509
+ #renderRow(row, index) {
510
+ return html`
511
+ <div
512
+ class="item ${this.#tickled.isTickled(index) ? `tickled` : ``}"
513
+ role="option"
514
+ id="opt-${index}"
515
+ data-index=${index}
516
+ aria-checked=${row.checked === `indeterminate` ? `mixed` : row.checked}
517
+ @pointerenter=${() => this.#tickled.handlePointerEnter(index)}
518
+ @click=${() => this.#onRowClick(row.value, index)}
519
+ >
520
+ <ixfx-checkbox
521
+ readonly
522
+ label=${row.label}
523
+ .checked=${row.checked === `true`}
524
+ .indeterminate=${row.checked === `indeterminate`}
525
+ ></ixfx-checkbox>
526
+ </div>`;
527
+ }
528
+ render() {
529
+ const rows = this._open ? this.#rows() : [];
530
+ const cursor = this.#tickled.tickledId;
531
+ const popupSize = this._size ? `width: ${this._size.width}px;` : ``;
532
+ const frameStyle = this._size ? `height: ${this._size.height}px; max-height: none;` : ``;
533
+ const summary = visibleAtRest(this.items).map((i) => i.label).join(`, `);
534
+ return html`
535
+ <div
536
+ class="rest"
537
+ role="combobox"
538
+ tabindex=${this.disabled ? `-1` : `0`}
539
+ aria-haspopup="listbox"
540
+ aria-expanded=${this._open ? `true` : `false`}
541
+ aria-disabled=${this.disabled ? `true` : nothing}
542
+ title=${summary || nothing}
543
+ style="anchor-name: ${this.#anchorName}"
544
+ @click=${this.#onTriggerClick}
545
+ @keydown=${this.#onTriggerKeyDown}
546
+ >
547
+ <div class="rest-items">${this.#renderRest()}</div>
548
+ <div class="caret" aria-hidden="true">
549
+ <svg viewBox="0 0 24 24"><path d="m6 9 6 6 6-6" /></svg>
550
+ </div>
551
+ </div>
552
+ <div class="popup" popover="manual" style="position-anchor: ${this.#anchorName}; ${popupSize}">
553
+ <div class="frame" style=${frameStyle}>
554
+ <div
555
+ class="listbox"
556
+ role="listbox"
557
+ aria-multiselectable="true"
558
+ tabindex="-1"
559
+ aria-activedescendant=${cursor === void 0 ? nothing : `opt-${cursor}`}
560
+ data-input-mode=${this.#tickled.inputMode}
561
+ @pointerleave=${(e) => this.#tickled.handlePointerLeave(e)}
562
+ @keydown=${this.#onListKeyDown}
563
+ >${rows.map((r, i) => this.#renderRow(r, i))}</div>
564
+ <div class="resize-zone" @pointerdown=${this.#onResizeDown}>
565
+ <span class="ixfx-handle" data-handle="dotted" data-shape="spot" part="handle"></span>
566
+ </div>
567
+ </div>
568
+ </div>
569
+ `;
570
+ }
571
+ };
572
+ __decorate([property({ type: Array })], CheckedSelect.prototype, "items", void 0);
573
+ __decorate([property({
574
+ type: Boolean,
575
+ reflect: true
576
+ })], CheckedSelect.prototype, "multiline", void 0);
577
+ __decorate([property({
578
+ type: Boolean,
579
+ attribute: `items-inert`,
580
+ reflect: true
581
+ })], CheckedSelect.prototype, "itemsInert", void 0);
582
+ __decorate([property({
583
+ type: String,
584
+ attribute: `item-display`,
585
+ reflect: true
586
+ })], CheckedSelect.prototype, "itemDisplay", void 0);
587
+ __decorate([property({
588
+ type: String,
589
+ reflect: true
590
+ })], CheckedSelect.prototype, "orientation", void 0);
591
+ __decorate([property({ type: String })], CheckedSelect.prototype, "placeholder", void 0);
592
+ __decorate([property({
593
+ type: Boolean,
594
+ reflect: true
595
+ })], CheckedSelect.prototype, "disabled", void 0);
596
+ __decorate([state()], CheckedSelect.prototype, "_open", void 0);
597
+ __decorate([state()], CheckedSelect.prototype, "_draft", void 0);
598
+ __decorate([state()], CheckedSelect.prototype, "_order", void 0);
599
+ __decorate([state()], CheckedSelect.prototype, "_size", void 0);
600
+ CheckedSelect = __decorate([safeCustomElement(`ixfx-checked-select`)], CheckedSelect);
601
+ //#endregion
602
+ export { CheckedSelect as t };
603
+
604
+ //# sourceMappingURL=checked-select-Dejl13qd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checked-select-Dejl13qd.js","names":["#emitChange","#focusRestCheckbox","#popup","#trigger","#rows","#tickled","#scrollToCursor","#toggleRow","#listbox","#anchorName","#onDocumentPointerDown","#close","#onRestCheckboxChange","#onRowClick","#onTriggerClick","#onTriggerKeyDown","#renderRest","#onListKeyDown","#renderRow","#onResizeDown","customElement"],"sources":["../src/checked-select/logic.ts","../src/checked-select/checked-select.ts"],"sourcesContent":["import type { CheckedSelectItem, CheckState, Size } from './types.js';\n\nfunction byLabel(a: CheckedSelectItem, b: CheckedSelectItem): number {\n return a.label.localeCompare(b.label, undefined, { sensitivity: `base` });\n}\n\n/** Checked/indeterminate items first, then the rest; each group sorted by label. */\nexport function sortForOpen(items: readonly CheckedSelectItem[]): CheckedSelectItem[] {\n const on = items.filter(i => i.checked !== `false`).toSorted(byLabel);\n const off = items.filter(i => i.checked === `false`).toSorted(byLabel);\n return [...on, ...off];\n}\n\n/** User toggle: indeterminate and unchecked become checked, checked becomes unchecked. */\nexport function toggleState(state: CheckState): CheckState {\n return state === `true` ? `false` : `true`;\n}\n\n/** Items shown in the resting state, alphabetically. */\nexport function visibleAtRest(items: readonly CheckedSelectItem[]): CheckedSelectItem[] {\n return items.filter(i => i.checked !== `false`).toSorted(byLabel);\n}\n\nexport const VARIES_LABEL = `(varies)`;\n\n/** Resting text entries: checked labels, then a single `(varies)` if any are indeterminate. */\nexport function restTextParts(items: readonly CheckedSelectItem[]): string[] {\n const on = items.filter(i => i.checked === `true`).toSorted(byLabel).map(i => i.label);\n const varies = items.some(i => i.checked === `indeterminate`) ? [VARIES_LABEL] : [];\n return [...on, ...varies];\n}\n\n/** Plain-text resting summary, comma separated. */\nexport function restText(items: readonly CheckedSelectItem[]): string {\n return restTextParts(items).join(`, `);\n}\n\n/** Returns a new list with the item matching `value` toggled. */\nexport function applyToggle(items: readonly CheckedSelectItem[], value: string): CheckedSelectItem[] {\n return items.map(i => i.value === value ? { ...i, checked: toggleState(i.checked) } : i);\n}\n\n/**\n * Index of the next label after `current` beginning with `char` (case-insensitive),\n * wrapping around. Returns -1 if nothing matches.\n */\nexport function nextMatchIndex(labels: readonly string[], current: number, char: string): number {\n const c = char.toLocaleLowerCase();\n const count = labels.length;\n for (let step = 1; step <= count; step++) {\n const index = (current + step + count) % count;\n if (labels[index].toLocaleLowerCase().startsWith(c))\n return index;\n }\n return -1;\n}\n\n/** Items in `draft` whose state differs from `original`. */\nexport function diffItems(original: readonly CheckedSelectItem[], draft: readonly CheckedSelectItem[]): CheckedSelectItem[] {\n const before = new Map(original.map(i => [i.value, i.checked]));\n return draft.filter(i => before.get(i.value) !== i.checked);\n}\n\nexport function clampSize(size: Size, min: Size, max: Size): Size {\n return {\n width: Math.min(Math.max(size.width, min.width), Math.max(max.width, min.width)),\n height: Math.min(Math.max(size.height, min.height), Math.max(max.height, min.height)),\n };\n}\n","/* eslint-disable ts/no-unsafe-declaration-merging */\n/**\n * <ixfx-checked-select> — a SELECT-like multi-choice control with tri-state items.\n *\n * At rest it shows the checked and indeterminate items as a flow of display-only\n * `ixfx-checkbox`. Opening it shows a scrollable, resizable popup of every item\n * (checked first, sorted once at open time). Edits are made to a draft:\n * Enter (or clicking the resting area again) commits, Escape or clicking outside\n * cancels.\n *\n * Properties\n * items – CheckedSelectItem[] ({ value, label, checked: 'true'|'false'|'indeterminate' })\n * multiline – let the resting flow wrap (default: false)\n * items-inert – resting checkboxes are display-only; clicking them opens the popup\n * orientation – 'horizontal' (default) flows items in a row; 'vertical' stacks one per row\n * (vertical ignores multiline; text mode then lists one entry per line, no commas)\n * item-display – 'checkbox' (default) or 'text' (comma-separated labels, then '(varies)' if any are indeterminate)\n * placeholder – shown when nothing is checked\n * disabled – prevents opening\n *\n * Events\n * change – CustomEvent { detail: { items, changed } }, bubbles + composed.\n * Fired once per commit, and only if something changed.\n *\n * CSS Variables\n * --checked-select-gap – gap between resting checkboxes\n * --checked-select-padding – padding of the resting area\n * --checked-select-caret-width – width of the always-visible caret (default: 2rem)\n * --checked-select-rest-max-height – resting height before it scrolls when multiline (default: 8rem)\n * --checked-select-max-height – popup height before it scrolls (default: 16rem)\n * --checked-select-min-width – minimum popup width when resized (default: 8rem)\n * --checked-select-min-height – minimum popup height when resized (default: 5rem)\n */\nimport type { PropertyValues } from 'lit';\nimport type { CheckedSelectItem, ItemDisplay, ItemOrientation, Size } from './types.js';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { TickledController, tickledItemStyles, tickledStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { handleStyles } from '../styles/handle.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport { applyToggle, clampSize, diffItems, nextMatchIndex, restText, restTextParts, sortForOpen, visibleAtRest } from './logic.js';\nimport '../checkbox/checkbox.js';\n\nexport type { CheckedSelectItem, CheckState, ItemDisplay, ItemOrientation } from './types.js';\n\nlet instanceCounter = 0;\n\n@customElement(`ixfx-checked-select`)\nexport class CheckedSelect extends LitElement {\n static override styles = [themeFallbacks, handleStyles, tickledStyles, tickledItemStyles, css`\n :host {\n --checked-select-gap: var(--space-m);\n --checked-select-padding: var(--space-s) var(--space-m);\n --checked-select-caret-width: 2rem;\n --checked-select-rest-max-height: 8rem;\n --checked-select-max-height: 16rem;\n --checked-select-min-width: 8rem;\n --checked-select-min-height: 5rem;\n\n display: block;\n position: relative;\n }\n\n :host([disabled]) {\n opacity: var(--prominence-disabled-opacity, 0.4);\n pointer-events: none;\n }\n\n .rest {\n position: relative;\n box-sizing: border-box;\n cursor: pointer;\n background: var(--surface-4);\n color: var(--surface-4-text);\n border: var(--border);\n border-radius: var(--radius-m);\n user-select: none;\n }\n\n .rest-items {\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: var(--checked-select-gap);\n padding: var(--checked-select-padding);\n /* Room to scroll the last item clear of the caret */\n padding-inline-end: var(--checked-select-caret-width);\n min-height: 1.5em;\n box-sizing: border-box;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n }\n :host([multiline]) .rest-items {\n flex-wrap: wrap;\n overflow-x: hidden;\n overflow-y: auto;\n max-height: var(--checked-select-rest-max-height);\n /* Wrapping never runs under the caret, so keep its column clear (and the scrollbar beside it) */\n padding-inline-end: var(--space-m);\n margin-inline-end: var(--checked-select-caret-width);\n }\n\n /* Vertical: one item per row, scrolling vertically beside the caret. Must follow the multiline rule. */\n :host([orientation=\"vertical\"]) .rest-items {\n flex-direction: column;\n flex-wrap: nowrap;\n align-items: flex-start;\n overflow-x: hidden;\n overflow-y: auto;\n max-height: var(--checked-select-rest-max-height);\n padding-inline-end: var(--space-m);\n margin-inline-end: var(--checked-select-caret-width);\n }\n\n /* Always-visible caret; items scroll underneath it */\n .caret {\n position: absolute;\n inset-block: 0;\n inset-inline-end: 0;\n width: var(--checked-select-caret-width);\n display: grid;\n place-items: center;\n background: inherit;\n border-radius: inherit;\n pointer-events: auto;\n }\n .caret svg {\n width: 1.1em;\n height: 1.1em;\n fill: none;\n stroke: currentColor;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n transition: rotate var(--transition, 0.1s ease-out);\n }\n .rest[aria-expanded=\"true\"] .caret svg {\n rotate: 180deg;\n }\n /* While the popup is open its draft is authoritative */\n .rest[aria-expanded=\"true\"] ixfx-checkbox {\n pointer-events: none;\n }\n .rest:hover {\n background: var(--surface-5);\n }\n .rest:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 2px;\n }\n .rest ixfx-checkbox {\n flex-shrink: 0;\n }\n .rest-text {\n white-space: nowrap;\n }\n :host([multiline]) .rest-text {\n white-space: normal;\n }\n .placeholder {\n opacity: 0.6;\n }\n\n .popup {\n /* Reset popover UA styles */\n inset: unset;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n overflow: visible;\n\n /* CSS anchor positioning — position-anchor set inline */\n position: fixed;\n left: anchor(left);\n top: anchor(bottom);\n /* anchor-size() only works on the anchored element itself, so the width lives here */\n width: anchor-size(width);\n min-width: var(--checked-select-min-width);\n position-try-fallbacks: flip-block;\n margin-block: 4px;\n z-index: 100;\n }\n\n .frame {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: 100%;\n max-height: var(--checked-select-max-height);\n background: var(--surface-3);\n color: var(--surface-3-text);\n border: var(--border);\n border-radius: var(--radius-m);\n }\n\n .listbox {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-s);\n outline: none;\n }\n .listbox:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: -2px;\n }\n\n .item {\n display: flex;\n width: 100%;\n box-sizing: border-box;\n }\n\n /* Key-repeat outpaces the fade, smearing the cursor across rows. Snap while\n the keyboard drives the cursor; hover (mouse mode) keeps the transition. */\n .listbox[data-input-mode=\"keyboard\"] .item {\n transition: none;\n }\n\n .resize-zone {\n position: absolute;\n inset-block-end: 0;\n inset-inline-end: 0;\n width: 16px;\n height: 16px;\n display: grid;\n place-items: center;\n cursor: nwse-resize;\n touch-action: none;\n }\n .resize-zone .ixfx-handle {\n --ixfx-handle-spot-size: 10px;\n }\n `];\n\n @property({ type: Array }) items: readonly CheckedSelectItem[] = [];\n @property({ type: Boolean, reflect: true }) multiline = false;\n /** At-rest checkboxes are display-only; clicking them just opens the popup. (Not `inert`: that native attribute would block the whole element.) */\n @property({ type: Boolean, attribute: `items-inert`, reflect: true }) itemsInert = false;\n /** How at-rest items are shown: as `checkbox`es, or as comma-separated `text`. */\n @property({ type: String, attribute: `item-display`, reflect: true }) itemDisplay: ItemDisplay = `checkbox`;\n /** Direction the resting items flow: `horizontal` (default) or `vertical` (one per row). */\n @property({ type: String, reflect: true }) orientation: ItemOrientation = `horizontal`;\n @property({ type: String }) placeholder = ``;\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n @state() private _open = false;\n @state() private _draft: readonly CheckedSelectItem[] = [];\n @state() private _order: readonly string[] = [];\n @state() private _size: Size | undefined;\n\n readonly #anchorName = `--checked-select-anchor-${instanceCounter++}`;\n\n #tickled = new TickledController<number>(this, {\n getItems: () => this._order.map((_, i) => ({ id: i })),\n });\n\n get isOpen(): boolean {\n return this._open;\n }\n\n get #trigger(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>(`.rest`) ?? null;\n }\n\n get #popup(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>(`.popup`) ?? null;\n }\n\n get #listbox(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>(`.listbox`) ?? null;\n }\n\n /** Draft items in their frozen open-time order. */\n #rows(): CheckedSelectItem[] {\n const byValue = new Map(this._draft.map(i => [i.value, i]));\n return this._order.flatMap(v => byValue.get(v) ?? []);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener(`pointerdown`, this.#onDocumentPointerDown, true);\n }\n\n override willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n if (changed.has(`disabled`) && this.disabled && this._open) {\n this.cancel();\n }\n }\n\n async open(): Promise<void> {\n if (this._open || this.disabled)\n return;\n this._draft = this.items;\n this._order = sortForOpen(this.items).map(i => i.value);\n this._size = undefined;\n this._open = true;\n if (this._order.length > 0)\n this.#tickled.handleKeyboardNavigation(`first`);\n document.addEventListener(`pointerdown`, this.#onDocumentPointerDown, true);\n await this.updateComplete;\n this.#popup?.showPopover?.();\n this.#listbox?.focus();\n }\n\n commit(): void {\n if (!this._open)\n return;\n const changed = diffItems(this.items, this._draft);\n const next = this._draft;\n this.#close();\n if (changed.length === 0)\n return;\n this.#emitChange(next, changed);\n }\n\n #emitChange(next: readonly CheckedSelectItem[], changed: readonly CheckedSelectItem[]): void {\n this.items = next;\n this.dispatchEvent(new CustomEvent<CheckedSelectChangeDetail>(`change`, {\n detail: { items: next, changed },\n bubbles: true,\n composed: true,\n }));\n }\n\n /** A resting checkbox was used directly: toggle and commit immediately. */\n #onRestCheckboxChange = (e: Event, value: string): void => {\n // The checkbox's own `change` bubbles out of this shadow root; ours replaces it\n e.stopPropagation();\n if (this._open)\n return;\n const next = applyToggle(this.items, value);\n this.#emitChange(next, diffItems(this.items, next));\n void this.#focusRestCheckbox(value);\n };\n\n async #focusRestCheckbox(value: string): Promise<void> {\n await this.updateComplete;\n const box = this.shadowRoot?.querySelector<HTMLElement>(`.rest ixfx-checkbox[data-value=\"${CSS.escape(value)}\"]`);\n // Unchecking removes the checkbox from the resting view; keep focus on the control\n (box ?? this.#trigger)?.focus();\n }\n\n cancel(): void {\n if (!this._open)\n return;\n this.#close();\n }\n\n #close(): void {\n document.removeEventListener(`pointerdown`, this.#onDocumentPointerDown, true);\n this.#popup?.hidePopover?.();\n this._open = false;\n this._draft = [];\n this.#tickled.clearTickled();\n this.#trigger?.focus();\n }\n\n #onDocumentPointerDown = (e: PointerEvent): void => {\n const path = e.composedPath();\n const popup = this.#popup;\n const trigger = this.#trigger;\n if ((popup && path.includes(popup)) || (trigger && path.includes(trigger)))\n return;\n this.cancel();\n };\n\n #onTriggerClick = (e: Event): void => {\n // Clicks on a resting checkbox toggle it; only empty space (or the caret) opens/commits\n if ((e.target as Element).closest?.(`ixfx-checkbox`))\n return;\n // Grabbing the scrollbar of the resting items isn't a click on the control\n const scroller = e.composedPath()[0] as HTMLElement;\n if (scroller.classList?.contains(`rest-items`) && e instanceof MouseEvent\n && (e.offsetX > scroller.clientWidth || e.offsetY > scroller.clientHeight)) {\n return;\n }\n if (this._open)\n this.commit();\n else void this.open();\n };\n\n #onTriggerKeyDown = (e: KeyboardEvent): void => {\n // Keys on a focused resting checkbox belong to that checkbox\n if (this._open || e.target !== e.currentTarget)\n return;\n if (e.key === `Enter` || e.key === ` ` || e.key === `ArrowDown`) {\n e.preventDefault();\n void this.open();\n }\n };\n\n #toggleRow(value: string): void {\n this._draft = applyToggle(this._draft, value);\n }\n\n #onRowClick(value: string, index: number): void {\n this.#tickled.setTickled(index);\n this.#toggleRow(value);\n }\n\n #onListKeyDown = (e: KeyboardEvent): void => {\n const rows = this.#rows();\n switch (e.key) {\n case `ArrowDown`:\n e.preventDefault();\n this.#tickled.handleKeyboardNavigation(`next`);\n void this.#scrollToCursor();\n return;\n case `ArrowUp`:\n e.preventDefault();\n this.#tickled.handleKeyboardNavigation(`previous`);\n void this.#scrollToCursor();\n return;\n case `Home`:\n e.preventDefault();\n this.#tickled.handleKeyboardNavigation(`first`);\n void this.#scrollToCursor();\n return;\n case `End`:\n e.preventDefault();\n this.#tickled.handleKeyboardNavigation(`last`);\n void this.#scrollToCursor();\n return;\n case ` `: {\n e.preventDefault();\n const row = rows[this.#tickled.tickledId ?? -1];\n if (row)\n this.#toggleRow(row.value);\n return;\n }\n case `Enter`:\n e.preventDefault();\n this.commit();\n return;\n case `Escape`:\n e.preventDefault();\n this.cancel();\n return;\n case `Tab`:\n this.cancel();\n return;\n }\n if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n const next = nextMatchIndex(rows.map(r => r.label), this.#tickled.tickledId ?? -1, e.key);\n if (next >= 0) {\n this.#tickled.handleKeyboardNavigation(next);\n void this.#scrollToCursor();\n }\n }\n };\n\n async #scrollToCursor(): Promise<void> {\n await this.updateComplete;\n const index = this.#tickled.tickledId;\n this.shadowRoot?.querySelector(`[data-index=\"${index}\"]`)?.scrollIntoView?.({ block: `nearest` });\n }\n\n #onResizeDown = (e: PointerEvent): void => {\n const frame = this.shadowRoot?.querySelector<HTMLElement>(`.frame`);\n const zone = e.currentTarget as HTMLElement;\n if (!frame)\n return;\n e.preventDefault();\n const start = frame.getBoundingClientRect();\n const originX = e.clientX;\n const originY = e.clientY;\n const style = getComputedStyle(this);\n const min: Size = {\n width: Number.parseFloat(style.getPropertyValue(`--checked-select-min-width`)) || 128,\n height: Number.parseFloat(style.getPropertyValue(`--checked-select-min-height`)) || 80,\n };\n const max: Size = {\n width: window.innerWidth - start.left - 8,\n height: window.innerHeight - start.top - 8,\n };\n zone.setPointerCapture?.(e.pointerId);\n zone.setAttribute(`data-active`, ``);\n const onMove = (m: PointerEvent): void => {\n this._size = clampSize({\n width: start.width + m.clientX - originX,\n height: start.height + m.clientY - originY,\n }, min, max);\n };\n const onEnd = (): void => {\n zone.removeAttribute(`data-active`);\n zone.removeEventListener(`pointermove`, onMove);\n zone.removeEventListener(`pointerup`, onEnd);\n zone.removeEventListener(`pointercancel`, onEnd);\n this.#listbox?.focus();\n };\n zone.addEventListener(`pointermove`, onMove);\n zone.addEventListener(`pointerup`, onEnd);\n zone.addEventListener(`pointercancel`, onEnd);\n };\n\n #renderRest() {\n const shown = visibleAtRest(this.items);\n if (shown.length === 0) {\n return html`<span class=\"placeholder\">${this.placeholder}</span>`;\n }\n if (this.itemDisplay === `text`) {\n if (this.orientation === `vertical`) {\n return restTextParts(this.items).map(part => html`<span class=\"rest-text\">${part}</span>`);\n }\n return html`<span class=\"rest-text\">${restText(this.items)}</span>`;\n }\n return repeat(shown, i => i.value, i => html`\n <ixfx-checkbox\n ?readonly=${this.itemsInert}\n data-value=${i.value}\n label=${i.label}\n .checked=${i.checked === `true`}\n .indeterminate=${i.checked === `indeterminate`}\n @change=${(e: Event) => this.#onRestCheckboxChange(e, i.value)}\n ></ixfx-checkbox>`);\n }\n\n #renderRow(row: CheckedSelectItem, index: number) {\n return html`\n <div\n class=\"item ${this.#tickled.isTickled(index) ? `tickled` : ``}\"\n role=\"option\"\n id=\"opt-${index}\"\n data-index=${index}\n aria-checked=${row.checked === `indeterminate` ? `mixed` : row.checked}\n @pointerenter=${() => this.#tickled.handlePointerEnter(index)}\n @click=${() => this.#onRowClick(row.value, index)}\n >\n <ixfx-checkbox\n readonly\n label=${row.label}\n .checked=${row.checked === `true`}\n .indeterminate=${row.checked === `indeterminate`}\n ></ixfx-checkbox>\n </div>`;\n }\n\n protected override render() {\n const rows = this._open ? this.#rows() : [];\n const cursor = this.#tickled.tickledId;\n const popupSize = this._size ? `width: ${this._size.width}px;` : ``;\n const frameStyle = this._size ? `height: ${this._size.height}px; max-height: none;` : ``;\n const summary = visibleAtRest(this.items).map(i => i.label).join(`, `);\n return html`\n <div\n class=\"rest\"\n role=\"combobox\"\n tabindex=${this.disabled ? `-1` : `0`}\n aria-haspopup=\"listbox\"\n aria-expanded=${this._open ? `true` : `false`}\n aria-disabled=${this.disabled ? `true` : nothing}\n title=${summary || nothing}\n style=\"anchor-name: ${this.#anchorName}\"\n @click=${this.#onTriggerClick}\n @keydown=${this.#onTriggerKeyDown}\n >\n <div class=\"rest-items\">${this.#renderRest()}</div>\n <div class=\"caret\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\" /></svg>\n </div>\n </div>\n <div class=\"popup\" popover=\"manual\" style=\"position-anchor: ${this.#anchorName}; ${popupSize}\">\n <div class=\"frame\" style=${frameStyle}>\n <div\n class=\"listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n tabindex=\"-1\"\n aria-activedescendant=${cursor === undefined ? nothing : `opt-${cursor}`}\n data-input-mode=${this.#tickled.inputMode}\n @pointerleave=${(e: PointerEvent) => this.#tickled.handlePointerLeave(e)}\n @keydown=${this.#onListKeyDown}\n >${rows.map((r, i) => this.#renderRow(r, i))}</div>\n <div class=\"resize-zone\" @pointerdown=${this.#onResizeDown}>\n <span class=\"ixfx-handle\" data-handle=\"dotted\" data-shape=\"spot\" part=\"handle\"></span>\n </div>\n </div>\n </div>\n `;\n }\n}\n\nexport type CheckedSelectChangeDetail = {\n /** Every item, with its committed state. */\n readonly items: readonly CheckedSelectItem[];\n /** Only the items whose state changed. */\n readonly changed: readonly CheckedSelectItem[];\n};\n\nexport type CheckedSelectChangeEvent = CustomEvent<CheckedSelectChangeDetail>;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-checked-select': CheckedSelect;\n }\n}\n\nexport interface CheckedSelectEventMap {\n change: CheckedSelectChangeEvent;\n}\n\nexport interface CheckedSelect {\n addEventListener: (<K extends keyof CheckedSelectEventMap>(\n type: K,\n listener: (this: CheckedSelect, event: CheckedSelectEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { a as CheckState, c as ItemOrientation, i as CheckedSelectEventMap, n as CheckedSelectChangeDetail, o as CheckedSelectItem, r as CheckedSelectChangeEvent, s as ItemDisplay, t as CheckedSelect } from "./checked-select-CglRukbP.js";
2
+ export { type CheckState, CheckedSelect, CheckedSelectChangeDetail, CheckedSelectChangeEvent, CheckedSelectEventMap, type CheckedSelectItem, type ItemDisplay, type ItemOrientation };
@@ -0,0 +1,3 @@
1
+ import "./checkbox.js";
2
+ import { t as CheckedSelect } from "./checked-select-Dejl13qd.js";
3
+ export { CheckedSelect };