kanto-ds 1.5.2 → 1.6.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/README.md +10 -10
- package/dist/chunks/floating-B33g-M_1.js +63 -0
- package/dist/chunks/floating-B33g-M_1.js.map +1 -0
- package/dist/chunks/{index-STEEvEP7.js → index-TWJzttLX.js} +38 -15
- package/dist/chunks/index-TWJzttLX.js.map +1 -0
- package/dist/chunks/kt-calendar-CtwOby1R.js +780 -0
- package/dist/chunks/kt-calendar-CtwOby1R.js.map +1 -0
- package/dist/chunks/{kt-element-Djx2JcGl.js → kt-element-T0VbIBNp.js} +2 -2
- package/dist/chunks/{kt-element-Djx2JcGl.js.map → kt-element-T0VbIBNp.js.map} +1 -1
- package/dist/chunks/{listbox-llcUu_V-.js → listbox-LsUEyGhQ.js} +2 -2
- package/dist/chunks/{listbox-llcUu_V-.js.map → listbox-LsUEyGhQ.js.map} +1 -1
- package/dist/chunks/segmented-field-BBXR4XFL.js +384 -0
- package/dist/chunks/segmented-field-BBXR4XFL.js.map +1 -0
- package/dist/chunks/typed-date-CPAUNHzr.js +103 -0
- package/dist/chunks/typed-date-CPAUNHzr.js.map +1 -0
- package/dist/components/core/kt-avatar/kt-avatar.js +2 -2
- package/dist/components/core/kt-badge/kt-badge.js +2 -2
- package/dist/components/core/kt-button/kt-button.js +1 -1
- package/dist/components/core/kt-card/kt-card.js +1 -1
- package/dist/components/core/kt-code/kt-code.js +13 -13
- package/dist/components/core/kt-code/kt-code.js.map +1 -1
- package/dist/components/core/kt-icon/kt-icon.js +1 -1
- package/dist/components/core/kt-kbd/kt-kbd.js +5 -5
- package/dist/components/core/kt-kbd/kt-kbd.js.map +1 -1
- package/dist/components/core/kt-split-button/kt-split-button.js +3 -3
- package/dist/components/data/kt-chart/kt-chart.js +3 -3
- package/dist/components/data/kt-chart/kt-chart.js.map +1 -1
- package/dist/components/data/kt-meter/kt-meter.js +1 -1
- package/dist/components/data/kt-pagination/kt-pagination.js +2 -2
- package/dist/components/data/kt-stat/kt-stat.js +1 -1
- package/dist/components/data/kt-table/kt-table.js +85 -85
- package/dist/components/data/kt-table/kt-table.js.map +1 -1
- package/dist/components/data/kt-timeline/kt-timeline.js +1 -1
- package/dist/components/feedback/kt-alert/kt-alert.js +15 -15
- package/dist/components/feedback/kt-alert/kt-alert.js.map +1 -1
- package/dist/components/feedback/kt-empty-state/kt-empty-state.js +1 -1
- package/dist/components/feedback/kt-progress-bar/kt-progress-bar.js +1 -1
- package/dist/components/feedback/kt-skeleton/kt-skeleton.js +13 -13
- package/dist/components/feedback/kt-skeleton/kt-skeleton.js.map +1 -1
- package/dist/components/feedback/kt-toast/kt-toast.js +3 -3
- package/dist/components/feedback/kt-toast/kt-toast.js.map +1 -1
- package/dist/components/feedback/kt-toast-container/kt-toast-container.js +1 -1
- package/dist/components/feedback/kt-tooltip/kt-tooltip.js +1 -1
- package/dist/components/forms/kt-calendar/kt-calendar.d.ts +35 -9
- package/dist/components/forms/kt-calendar/kt-calendar.js +3 -3
- package/dist/components/forms/kt-checkbox/kt-checkbox.js +2 -2
- package/dist/components/forms/kt-date-input/kt-date-input.d.ts +65 -0
- package/dist/components/forms/kt-date-input/kt-date-input.js +241 -0
- package/dist/components/forms/kt-date-input/kt-date-input.js.map +1 -0
- package/dist/components/forms/kt-date-picker/kt-date-picker.d.ts +47 -3
- package/dist/components/forms/kt-date-picker/kt-date-picker.js +430 -199
- package/dist/components/forms/kt-date-picker/kt-date-picker.js.map +1 -1
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js +3 -3
- package/dist/components/forms/kt-drag-drop/kt-drag-drop.js.map +1 -1
- package/dist/components/forms/kt-form/kt-form.js +2 -2
- package/dist/components/forms/kt-input/kt-input.js +10 -10
- package/dist/components/forms/kt-input/kt-input.js.map +1 -1
- package/dist/components/forms/kt-input-menu/kt-input-menu.js +4 -4
- package/dist/components/forms/kt-label-input/kt-label-input.js +1 -1
- package/dist/components/forms/kt-multi-select/kt-multi-select.d.ts +113 -0
- package/dist/components/forms/kt-multi-select/kt-multi-select.js +532 -0
- package/dist/components/forms/kt-multi-select/kt-multi-select.js.map +1 -0
- package/dist/components/forms/kt-radio-group/kt-radio-group.js +56 -51
- package/dist/components/forms/kt-radio-group/kt-radio-group.js.map +1 -1
- package/dist/components/forms/kt-select/kt-select.js +4 -4
- package/dist/components/forms/kt-textarea/kt-textarea.js +2 -2
- package/dist/components/forms/kt-time-input/kt-time-input.d.ts +48 -0
- package/dist/components/forms/kt-time-input/kt-time-input.js +114 -0
- package/dist/components/forms/kt-time-input/kt-time-input.js.map +1 -0
- package/dist/components/forms/kt-toggle/kt-toggle.js +1 -1
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js +6 -6
- package/dist/components/navigation/kt-breadcrumb/kt-breadcrumb.js.map +1 -1
- package/dist/components/navigation/kt-header/kt-header.js +2 -2
- package/dist/components/navigation/kt-page-header/kt-page-header.js +1 -1
- package/dist/components/navigation/kt-segmented-control/kt-segmented-control.js +2 -2
- package/dist/components/navigation/kt-sub-menu-navigation/kt-sub-menu-navigation.js +2 -2
- package/dist/components/navigation/kt-tabs/kt-tabs.js +2 -2
- package/dist/components/navigation/kt-tabs/kt-tabs.js.map +1 -1
- package/dist/components/navigation/kt-toggle-button/kt-toggle-button.js +1 -1
- package/dist/components/navigation/kt-toggle-button-group/kt-toggle-button-group.js +2 -2
- package/dist/components/overlays/kt-collapsible/kt-collapsible.js +3 -3
- package/dist/components/overlays/kt-collapsible/kt-collapsible.js.map +1 -1
- package/dist/components/overlays/kt-confirm-dialog/kt-confirm-dialog.js +2 -2
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js +24 -24
- package/dist/components/overlays/kt-dropdown/kt-dropdown.js.map +1 -1
- package/dist/components/overlays/kt-modal/kt-modal.js +2 -2
- package/dist/components/overlays/kt-side-panel/kt-side-panel.js +2 -2
- package/dist/custom-elements.json +2230 -842
- package/dist/index.d.ts +9 -1
- package/dist/index.js +316 -109
- package/dist/index.js.map +1 -1
- package/dist/internal/floating.d.ts +3 -0
- package/dist/internal/segmented-field.d.ts +114 -0
- package/dist/internal/segments.d.ts +30 -0
- package/dist/internal/strings.d.ts +30 -0
- package/dist/internal/typed-date.d.ts +33 -0
- package/dist/react/index.d.ts +23 -0
- package/dist/react/index.js +193 -169
- package/dist/react/index.js.map +1 -1
- package/dist/react/jsx.d.ts +20 -1
- package/dist/strings/index.js +1 -1
- package/dist/theme/accent.d.ts +51 -0
- package/dist/theme/appearance.d.ts +37 -0
- package/dist/tokens/README.md +100 -1
- package/dist/tokens/accents.css +80 -0
- package/dist/tokens/appearance.css +65 -0
- package/dist/tokens/base.css +3 -0
- package/dist/tokens/colors.css +78 -25
- package/dist/tokens/index.css +2 -0
- package/dist/tokens/responsive.css +160 -75
- package/dist/tokens/spacing.css +47 -28
- package/dist/tokens/theme-light.css +124 -38
- package/dist/tokens/typography.css +20 -13
- package/dist/vscode.css-custom-data.json +36 -1
- package/dist/vscode.html-custom-data.json +67 -2
- package/dist/vue/index.d.ts +6 -0
- package/dist/vue/index.js +11 -8
- package/dist/vue/index.js.map +1 -1
- package/dist/web-types.json +190 -3
- package/package.json +13 -1
- package/dist/chunks/floating-B7_Dahpn.js +0 -54
- package/dist/chunks/floating-B7_Dahpn.js.map +0 -1
- package/dist/chunks/index-STEEvEP7.js.map +0 -1
- package/dist/chunks/kt-calendar-B_hFdD9V.js +0 -640
- package/dist/chunks/kt-calendar-B_hFdD9V.js.map +0 -1
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import { css as O, nothing as l, html as c } from "lit";
|
|
2
|
+
import { query as R, state as d, property as a } from "lit/decorators.js";
|
|
3
|
+
import { classMap as u } from "lit/directives/class-map.js";
|
|
4
|
+
import { live as E } from "lit/directives/live.js";
|
|
5
|
+
import { K as $, d as P } from "../../../chunks/kt-element-T0VbIBNp.js";
|
|
6
|
+
import { u as C, t as I, e as D } from "../../../chunks/events-r51msXNf.js";
|
|
7
|
+
import { a as L, s as z, b as B } from "../../../chunks/form-control-B74_EHtG.js";
|
|
8
|
+
import { a as T, b as F, f as y, l as V, n as _, o as w } from "../../../chunks/listbox-LsUEyGhQ.js";
|
|
9
|
+
import { F as A, f as W } from "../../../chunks/floating-B33g-M_1.js";
|
|
10
|
+
import { s as p } from "../../../chunks/index-TWJzttLX.js";
|
|
11
|
+
import "../../core/kt-icon/kt-icon.js";
|
|
12
|
+
var K = Object.defineProperty, r = (m, t, i, e) => {
|
|
13
|
+
for (var o = void 0, n = m.length - 1, v; n >= 0; n--)
|
|
14
|
+
(v = m[n]) && (o = v(t, i, o) || o);
|
|
15
|
+
return o && K(t, i, o), o;
|
|
16
|
+
};
|
|
17
|
+
const S = 48, M = 40;
|
|
18
|
+
class s extends $ {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments), this.internals = null, this.defaultValue = [], this.listId = C("kt-multi-select-list"), this.countId = C("kt-multi-select-count"), this.open = !1, this.placement = "bottom", this.floating = new A(this, {
|
|
21
|
+
panel: () => this.shadowRoot?.querySelector(".popup"),
|
|
22
|
+
anchor: () => this.shadowRoot?.querySelector(".control"),
|
|
23
|
+
matchWidth: !0,
|
|
24
|
+
onPlace: (t) => {
|
|
25
|
+
this.placement = t;
|
|
26
|
+
}
|
|
27
|
+
}), this.query = "", this.activeIndex = -1, this.overflowCount = 0, this.options = [], this.value = [], this.placeholder = "", this.name = "", this.disabled = !1, this.formDisabled = !1, this.required = !1, this.error = "", this.label = "", this.emptyText = void 0, this.onDocumentPointerDown = (t) => {
|
|
28
|
+
t.composedPath().includes(this) || this.close();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
static {
|
|
32
|
+
this.formAssociated = !0;
|
|
33
|
+
}
|
|
34
|
+
static {
|
|
35
|
+
this.styles = [
|
|
36
|
+
$.styles,
|
|
37
|
+
W,
|
|
38
|
+
T,
|
|
39
|
+
O`
|
|
40
|
+
:host {
|
|
41
|
+
position: relative;
|
|
42
|
+
display: block;
|
|
43
|
+
--field-height: var(--button-height);
|
|
44
|
+
--chip-height: calc(var(--field-height) - 16px);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.control {
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: var(--gap-element);
|
|
51
|
+
width: 100%;
|
|
52
|
+
height: var(--field-height);
|
|
53
|
+
padding: 0 var(--button-padding-x);
|
|
54
|
+
color: var(--text-body);
|
|
55
|
+
font: var(--font-input);
|
|
56
|
+
background-color: var(--color-dark-20);
|
|
57
|
+
/* The same resting hairline and rings as kt-input-menu. */
|
|
58
|
+
border: var(--border-width) solid var(--border-field);
|
|
59
|
+
border-radius: var(--radius-input);
|
|
60
|
+
outline: var(--outline-width) solid transparent;
|
|
61
|
+
cursor: text;
|
|
62
|
+
transition:
|
|
63
|
+
background-color var(--duration-instant),
|
|
64
|
+
outline-color var(--duration-instant);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.control:hover {
|
|
68
|
+
outline: var(--outline-width) solid var(--color-text-700);
|
|
69
|
+
}
|
|
70
|
+
.control:focus-within {
|
|
71
|
+
background-color: var(--color-dark-12);
|
|
72
|
+
outline: var(--outline-width) solid var(--color-primary-base);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.error .control,
|
|
76
|
+
.error .control:hover,
|
|
77
|
+
.error .control:focus-within {
|
|
78
|
+
outline: var(--outline-width) solid var(--color-danger-base);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host(:disabled) {
|
|
82
|
+
pointer-events: none;
|
|
83
|
+
opacity: 0.6;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* One line, whatever is chosen: the chips that do not fit are hidden
|
|
87
|
+
and counted in the "+N" beside them. */
|
|
88
|
+
.chips {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex: 0 1 auto;
|
|
91
|
+
align-items: center;
|
|
92
|
+
gap: var(--gap-element);
|
|
93
|
+
min-width: 0;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Chips sit inset in the field, the same distance from its top, bottom
|
|
98
|
+
and left edge — a fill inside a fill, in the family of a chosen
|
|
99
|
+
segment or option, never an outlined pill. */
|
|
100
|
+
.has-chips {
|
|
101
|
+
padding-left: calc((var(--field-height) - var(--chip-height)) / 2);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.chip,
|
|
105
|
+
.more {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
flex: none;
|
|
108
|
+
align-items: center;
|
|
109
|
+
gap: 2px;
|
|
110
|
+
height: var(--chip-height);
|
|
111
|
+
padding: 0 8px;
|
|
112
|
+
color: var(--text-body);
|
|
113
|
+
font: var(--font-normal-small);
|
|
114
|
+
white-space: nowrap;
|
|
115
|
+
background: var(--color-dark-23);
|
|
116
|
+
border-radius: calc(var(--radius-input) - 2px);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.chip.removable {
|
|
120
|
+
padding-right: 4px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* The chips that do not fit are hidden by fitChips; their own display
|
|
124
|
+
would otherwise win over the attribute and leave them drawn. */
|
|
125
|
+
.chip[hidden] {
|
|
126
|
+
display: none;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* A count, not a choice: same shape, quieter. */
|
|
130
|
+
.more {
|
|
131
|
+
color: var(--text-muted);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.remove {
|
|
135
|
+
display: inline-flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
width: 16px;
|
|
139
|
+
height: 16px;
|
|
140
|
+
padding: 0;
|
|
141
|
+
color: var(--text-muted);
|
|
142
|
+
background: transparent;
|
|
143
|
+
border: none;
|
|
144
|
+
border-radius: calc(4px * var(--radius-scale, 1));
|
|
145
|
+
cursor: pointer;
|
|
146
|
+
transition:
|
|
147
|
+
background-color var(--duration-instant),
|
|
148
|
+
color var(--duration-instant);
|
|
149
|
+
}
|
|
150
|
+
.remove:hover {
|
|
151
|
+
color: var(--text-body);
|
|
152
|
+
background: var(--color-dark-24);
|
|
153
|
+
}
|
|
154
|
+
.remove:focus-visible {
|
|
155
|
+
outline: var(--outline-width) solid var(--color-primary-base);
|
|
156
|
+
outline-offset: 1px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
input {
|
|
160
|
+
flex: 1;
|
|
161
|
+
min-width: ${S}px;
|
|
162
|
+
color: var(--text-body);
|
|
163
|
+
font: var(--font-input);
|
|
164
|
+
background: transparent;
|
|
165
|
+
border: none;
|
|
166
|
+
outline: none;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
input::placeholder {
|
|
170
|
+
color: var(--text-muted);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.toggle {
|
|
174
|
+
display: inline-flex;
|
|
175
|
+
flex: none;
|
|
176
|
+
align-items: center;
|
|
177
|
+
padding: 0;
|
|
178
|
+
color: inherit;
|
|
179
|
+
background: transparent;
|
|
180
|
+
border: none;
|
|
181
|
+
cursor: pointer;
|
|
182
|
+
transition: transform var(--duration-fast) ease-in-out;
|
|
183
|
+
}
|
|
184
|
+
.open .toggle {
|
|
185
|
+
transform: scaleY(-1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.option {
|
|
189
|
+
display: flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
gap: var(--gap-element);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* The tick's room is kept on every row, so labels line up whether or
|
|
195
|
+
not their option is chosen. */
|
|
196
|
+
.tick {
|
|
197
|
+
display: inline-flex;
|
|
198
|
+
width: 16px;
|
|
199
|
+
color: var(--color-primary-text);
|
|
200
|
+
}
|
|
201
|
+
`
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
/** Whether the control is off, by its own `disabled` or by its form. */
|
|
205
|
+
get inactive() {
|
|
206
|
+
return this.disabled || this.formDisabled;
|
|
207
|
+
}
|
|
208
|
+
connectedCallback() {
|
|
209
|
+
super.connectedCallback(), this.internals ??= L(this), this.defaultValue = this.value, I(this.open, document, "pointerdown", this.onDocumentPointerDown), document.fonts?.ready.then(() => this.fitChips());
|
|
210
|
+
}
|
|
211
|
+
disconnectedCallback() {
|
|
212
|
+
super.disconnectedCallback(), document.removeEventListener("pointerdown", this.onDocumentPointerDown), this.resizeObserver?.disconnect(), this.resizeObserver = void 0;
|
|
213
|
+
}
|
|
214
|
+
willUpdate(t) {
|
|
215
|
+
if (t.has("value") || t.has("name") || t.has("required") || t.has("error") || this.stringsChanged(t)) {
|
|
216
|
+
let i = null;
|
|
217
|
+
if (this.value.length > 0) {
|
|
218
|
+
i = new FormData();
|
|
219
|
+
for (const o of this.value) i.append(this.name, String(o));
|
|
220
|
+
}
|
|
221
|
+
z(this.internals, i);
|
|
222
|
+
const e = this.required && this.value.length === 0;
|
|
223
|
+
B(
|
|
224
|
+
this.internals,
|
|
225
|
+
{ valueMissing: e, customError: !!this.error },
|
|
226
|
+
this.error || (e ? p().selectOption : "")
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Untyped: `open` is private, so not among the keys PropertyValues<this> knows.
|
|
231
|
+
updated(t) {
|
|
232
|
+
t.has("open") && I(this.open, document, "pointerdown", this.onDocumentPointerDown), this.floating.sync(this.open), this.observeWidth(), this.fitChips();
|
|
233
|
+
}
|
|
234
|
+
formResetCallback() {
|
|
235
|
+
this.value = this.defaultValue, this.close();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Called by the platform when the control's disabled state changes — its
|
|
239
|
+
* own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.
|
|
240
|
+
*/
|
|
241
|
+
formDisabledCallback(t) {
|
|
242
|
+
this.formDisabled = t;
|
|
243
|
+
}
|
|
244
|
+
/** Called by the platform when the browser restores a session. */
|
|
245
|
+
formStateRestoreCallback(t) {
|
|
246
|
+
const i = t instanceof FormData ? t.getAll(this.name).map(String) : t ? [t] : [];
|
|
247
|
+
this.value = i.map(
|
|
248
|
+
(e) => this.options.find((o) => String(o.id) === e)?.id ?? e
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
focus(t) {
|
|
252
|
+
this.input?.focus(t);
|
|
253
|
+
}
|
|
254
|
+
/** The chosen options, in the order chosen. */
|
|
255
|
+
get selectedOptions() {
|
|
256
|
+
return this.value.map(
|
|
257
|
+
(t) => this.options.find((i) => i.id === t) ?? { id: t, label: String(t) }
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
/** Options after the current query, which is what the keyboard walks. */
|
|
261
|
+
get visibleOptions() {
|
|
262
|
+
return F(this.options, this.query);
|
|
263
|
+
}
|
|
264
|
+
isChosen(t) {
|
|
265
|
+
return this.value.includes(t.id);
|
|
266
|
+
}
|
|
267
|
+
openList() {
|
|
268
|
+
this.inactive || this.open || (this.open = !0, this.activeIndex = y(this.visibleOptions));
|
|
269
|
+
}
|
|
270
|
+
close() {
|
|
271
|
+
this.open = !1, this.query = "", this.activeIndex = -1;
|
|
272
|
+
}
|
|
273
|
+
onInput(t) {
|
|
274
|
+
this.query = t.target.value, this.open = !0, this.activeIndex = y(this.visibleOptions), D(this, "kt-filter", { query: this.query });
|
|
275
|
+
}
|
|
276
|
+
/** Adds an option, or takes it out if it is already chosen. The list stays open. */
|
|
277
|
+
toggle(t) {
|
|
278
|
+
t.disabled || this.inactive || this.commit(
|
|
279
|
+
this.isChosen(t) ? this.value.filter((i) => i !== t.id) : [...this.value, t.id]
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
removeValue(t) {
|
|
283
|
+
this.inactive || this.commit(this.value.filter((i) => i !== t));
|
|
284
|
+
}
|
|
285
|
+
commit(t) {
|
|
286
|
+
this.value = t, D(this, "kt-change", { value: t, options: this.selectedOptions });
|
|
287
|
+
}
|
|
288
|
+
onKeyDown(t) {
|
|
289
|
+
const i = this.visibleOptions;
|
|
290
|
+
switch (t.key) {
|
|
291
|
+
case "ArrowDown":
|
|
292
|
+
case "ArrowUp":
|
|
293
|
+
if (t.preventDefault(), !this.open) return this.openList();
|
|
294
|
+
this.activeIndex = _(
|
|
295
|
+
i,
|
|
296
|
+
this.activeIndex,
|
|
297
|
+
t.key === "ArrowDown" ? 1 : -1
|
|
298
|
+
);
|
|
299
|
+
return;
|
|
300
|
+
case "Home":
|
|
301
|
+
if (!this.open) return;
|
|
302
|
+
t.preventDefault(), this.activeIndex = y(i);
|
|
303
|
+
return;
|
|
304
|
+
case "End":
|
|
305
|
+
if (!this.open) return;
|
|
306
|
+
t.preventDefault(), this.activeIndex = V(i);
|
|
307
|
+
return;
|
|
308
|
+
case "Enter": {
|
|
309
|
+
if (!this.open) return;
|
|
310
|
+
t.preventDefault();
|
|
311
|
+
const e = i[this.activeIndex];
|
|
312
|
+
e && this.toggle(e);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
case "Backspace": {
|
|
316
|
+
const e = this.value[this.value.length - 1];
|
|
317
|
+
if (this.input?.value || e === void 0) return;
|
|
318
|
+
this.removeValue(e);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
case "Escape":
|
|
322
|
+
if (!this.open) return;
|
|
323
|
+
t.stopPropagation(), this.close();
|
|
324
|
+
return;
|
|
325
|
+
case "Tab":
|
|
326
|
+
this.close();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/** Measures again when the field's width changes, since that is what fits. */
|
|
330
|
+
observeWidth() {
|
|
331
|
+
if (this.resizeObserver || typeof ResizeObserver > "u") return;
|
|
332
|
+
const t = this.shadowRoot?.querySelector(".control");
|
|
333
|
+
t && (this.resizeObserver = new ResizeObserver(() => this.fitChips()), this.resizeObserver.observe(t));
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Hides the chips that do not fit on the field's one line, and counts them
|
|
337
|
+
* in "+N".
|
|
338
|
+
*
|
|
339
|
+
* The room comes from what never moves: the field's inner width, less the
|
|
340
|
+
* input's minimum, the toggle and the gaps between them. It used to be read
|
|
341
|
+
* from the chip row itself, whose width depends on the chips shown and on
|
|
342
|
+
* the "+N" — so in Firefox each pass undid the last, and the loop between
|
|
343
|
+
* this and the render it triggered froze the page.
|
|
344
|
+
*/
|
|
345
|
+
fitChips() {
|
|
346
|
+
const t = this.shadowRoot?.querySelector(".control"), i = this.shadowRoot?.querySelector(".chips");
|
|
347
|
+
if (!t || !i) return;
|
|
348
|
+
const e = [...i.querySelectorAll(".chip")];
|
|
349
|
+
for (const h of e) h.hidden = !1;
|
|
350
|
+
const o = getComputedStyle(t), n = parseFloat(o.columnGap) || 0, v = t.querySelector(".toggle")?.getBoundingClientRect().width ?? 0, g = t.clientWidth - parseFloat(o.paddingLeft) - parseFloat(o.paddingRight) - S - v - 2 * n;
|
|
351
|
+
if (t.clientWidth === 0 || g <= 0) return;
|
|
352
|
+
const q = i.getBoundingClientRect().left, x = (h) => e.filter((b) => b.getBoundingClientRect().right - q <= h).length;
|
|
353
|
+
let f = x(g);
|
|
354
|
+
if (f < e.length) {
|
|
355
|
+
const h = this.shadowRoot?.querySelector(".more")?.getBoundingClientRect().width;
|
|
356
|
+
f = x(g - (h || M) - n);
|
|
357
|
+
}
|
|
358
|
+
e.forEach((h, b) => {
|
|
359
|
+
h.hidden = b >= f;
|
|
360
|
+
});
|
|
361
|
+
const k = e.length - f;
|
|
362
|
+
k !== this.overflowCount && (this.overflowCount = k);
|
|
363
|
+
}
|
|
364
|
+
optionId(t) {
|
|
365
|
+
return `${this.listId}-option-${t}`;
|
|
366
|
+
}
|
|
367
|
+
render() {
|
|
368
|
+
const t = this.visibleOptions, i = this.selectedOptions;
|
|
369
|
+
return c`<div
|
|
370
|
+
class=${u({ open: this.open, error: !!this.error })}
|
|
371
|
+
@keydown=${this.onKeyDown}
|
|
372
|
+
>
|
|
373
|
+
<span id=${this.countId} class="visually-hidden">
|
|
374
|
+
${i.length > 0 ? p().selectedCount(i.length) : ""}
|
|
375
|
+
</span>
|
|
376
|
+
|
|
377
|
+
<div
|
|
378
|
+
part="control"
|
|
379
|
+
class=${u({ control: !0, "has-chips": i.length > 0 })}
|
|
380
|
+
@click=${this.openList}
|
|
381
|
+
>
|
|
382
|
+
<div part="chips" class="chips">
|
|
383
|
+
${i.map(
|
|
384
|
+
(e) => c`<span class=${u({ chip: !0, removable: !this.inactive })}>
|
|
385
|
+
${w(e)}
|
|
386
|
+
${this.inactive ? l : c`<button
|
|
387
|
+
type="button"
|
|
388
|
+
class="remove"
|
|
389
|
+
tabindex="-1"
|
|
390
|
+
aria-label=${p().remove(w(e))}
|
|
391
|
+
@click=${(o) => {
|
|
392
|
+
o.stopPropagation(), this.removeValue(e.id);
|
|
393
|
+
}}
|
|
394
|
+
>
|
|
395
|
+
<kt-icon name="x" size="12"></kt-icon>
|
|
396
|
+
</button>`}
|
|
397
|
+
</span>`
|
|
398
|
+
)}
|
|
399
|
+
</div>
|
|
400
|
+
${this.overflowCount > 0 ? c`<span class="more"
|
|
401
|
+
>${// With not one chip left to count on from, "+3" says less
|
|
402
|
+
// than how many are chosen. The wider label only ever hides
|
|
403
|
+
// more chips, never fewer, so the fit cannot swing on it.
|
|
404
|
+
this.overflowCount === i.length ? p().selectedCount(i.length) : `+${this.overflowCount}`}</span
|
|
405
|
+
>` : l}
|
|
406
|
+
|
|
407
|
+
<input
|
|
408
|
+
part="input"
|
|
409
|
+
role="combobox"
|
|
410
|
+
aria-expanded=${this.open ? "true" : "false"}
|
|
411
|
+
aria-controls=${this.listId}
|
|
412
|
+
aria-autocomplete="list"
|
|
413
|
+
aria-activedescendant=${this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : l}
|
|
414
|
+
aria-label=${this.label || l}
|
|
415
|
+
aria-describedby=${this.countId}
|
|
416
|
+
aria-invalid=${this.error ? "true" : l}
|
|
417
|
+
placeholder=${i.length === 0 && this.placeholder ? this.placeholder : l}
|
|
418
|
+
.value=${E(this.query)}
|
|
419
|
+
?disabled=${this.inactive}
|
|
420
|
+
@focus=${this.openList}
|
|
421
|
+
@input=${this.onInput}
|
|
422
|
+
/>
|
|
423
|
+
|
|
424
|
+
<button
|
|
425
|
+
type="button"
|
|
426
|
+
class="toggle"
|
|
427
|
+
aria-label=${this.open ? p().closeList : p().openList}
|
|
428
|
+
tabindex="-1"
|
|
429
|
+
@click=${(e) => {
|
|
430
|
+
e.stopPropagation(), this.open ? this.close() : this.openList();
|
|
431
|
+
}}
|
|
432
|
+
>
|
|
433
|
+
<kt-icon name="chevron-down" size="18"></kt-icon>
|
|
434
|
+
</button>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<ul
|
|
438
|
+
part="popup"
|
|
439
|
+
id=${this.listId}
|
|
440
|
+
popover="manual"
|
|
441
|
+
class=${u({
|
|
442
|
+
popup: !0,
|
|
443
|
+
floating: !0,
|
|
444
|
+
open: this.open,
|
|
445
|
+
top: this.placement === "top"
|
|
446
|
+
})}
|
|
447
|
+
role="listbox"
|
|
448
|
+
aria-multiselectable="true"
|
|
449
|
+
aria-label=${this.label || this.placeholder}
|
|
450
|
+
@pointerdown=${(e) => {
|
|
451
|
+
e.preventDefault();
|
|
452
|
+
}}
|
|
453
|
+
>
|
|
454
|
+
${t.length === 0 ? c`<li class="empty">${this.emptyText ?? p().noOptions}</li>` : t.map((e, o) => {
|
|
455
|
+
const n = this.isChosen(e);
|
|
456
|
+
return c`<li
|
|
457
|
+
part="option"
|
|
458
|
+
id=${this.optionId(o)}
|
|
459
|
+
class=${u({
|
|
460
|
+
option: !0,
|
|
461
|
+
selected: n,
|
|
462
|
+
active: o === this.activeIndex,
|
|
463
|
+
disabled: !!e.disabled
|
|
464
|
+
})}
|
|
465
|
+
role="option"
|
|
466
|
+
aria-selected=${n ? "true" : "false"}
|
|
467
|
+
aria-disabled=${e.disabled ? "true" : l}
|
|
468
|
+
@click=${() => this.toggle(e)}
|
|
469
|
+
>
|
|
470
|
+
<span class="tick" aria-hidden="true">
|
|
471
|
+
${n ? c`<kt-icon name="check" size="16"></kt-icon>` : l}
|
|
472
|
+
</span>
|
|
473
|
+
${w(e)}
|
|
474
|
+
</li>`;
|
|
475
|
+
})}
|
|
476
|
+
</ul>
|
|
477
|
+
</div>`;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
r([
|
|
481
|
+
R("input")
|
|
482
|
+
], s.prototype, "input");
|
|
483
|
+
r([
|
|
484
|
+
d()
|
|
485
|
+
], s.prototype, "open");
|
|
486
|
+
r([
|
|
487
|
+
d()
|
|
488
|
+
], s.prototype, "placement");
|
|
489
|
+
r([
|
|
490
|
+
d()
|
|
491
|
+
], s.prototype, "query");
|
|
492
|
+
r([
|
|
493
|
+
d()
|
|
494
|
+
], s.prototype, "activeIndex");
|
|
495
|
+
r([
|
|
496
|
+
d()
|
|
497
|
+
], s.prototype, "overflowCount");
|
|
498
|
+
r([
|
|
499
|
+
a({ attribute: !1 })
|
|
500
|
+
], s.prototype, "options");
|
|
501
|
+
r([
|
|
502
|
+
a({ attribute: !1 })
|
|
503
|
+
], s.prototype, "value");
|
|
504
|
+
r([
|
|
505
|
+
a({ type: String })
|
|
506
|
+
], s.prototype, "placeholder");
|
|
507
|
+
r([
|
|
508
|
+
a({ type: String })
|
|
509
|
+
], s.prototype, "name");
|
|
510
|
+
r([
|
|
511
|
+
a({ type: Boolean, reflect: !0 })
|
|
512
|
+
], s.prototype, "disabled");
|
|
513
|
+
r([
|
|
514
|
+
d()
|
|
515
|
+
], s.prototype, "formDisabled");
|
|
516
|
+
r([
|
|
517
|
+
a({ type: Boolean, reflect: !0 })
|
|
518
|
+
], s.prototype, "required");
|
|
519
|
+
r([
|
|
520
|
+
a({ type: String, reflect: !0 })
|
|
521
|
+
], s.prototype, "error");
|
|
522
|
+
r([
|
|
523
|
+
a({ type: String })
|
|
524
|
+
], s.prototype, "label");
|
|
525
|
+
r([
|
|
526
|
+
a({ type: String, attribute: "empty-text" })
|
|
527
|
+
], s.prototype, "emptyText");
|
|
528
|
+
P("kt-multi-select", s);
|
|
529
|
+
export {
|
|
530
|
+
s as KtMultiSelect
|
|
531
|
+
};
|
|
532
|
+
//# sourceMappingURL=kt-multi-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kt-multi-select.js","sources":["../../../../src/components/forms/kt-multi-select/kt-multi-select.ts"],"sourcesContent":["import { css, html, nothing, type PropertyValues, type TemplateResult } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { live } from 'lit/directives/live.js';\nimport { KtElement, defineElement } from '#internal/kt-element';\nimport { emit, toggleListener, uniqueId } from '#internal/events';\nimport {\n attachFormInternals,\n setFormValue,\n setValidity,\n type UsableInternals,\n} from '#internal/form-control';\nimport {\n filterOptions,\n firstEnabledIndex,\n lastEnabledIndex,\n listboxStyles,\n nextEnabledIndex,\n optionLabel,\n type KtOption,\n} from '#internal/listbox';\nimport { FloatingController, floatingStyles } from '#internal/floating';\nimport type { Side } from '#internal/position';\nimport { strings } from '#internal/strings';\nimport '../../core/kt-icon/kt-icon.js';\n\nexport type KtMultiSelectValue = readonly (string | number)[];\n\n/** Kept clear for the text you type — a few letters of a search — whatever the chips take. */\nconst INPUT_MIN_WIDTH = 48;\n\n/** The \"+N\" before it is drawn and can be measured. */\nconst MORE_WIDTH_GUESS = 40;\n\n/**\n * Several choices from a list: type to narrow it, pick as many as you need.\n *\n * Each choice shows in the field as a removable chip. The field keeps to one\n * line — the chips that do not fit collapse into a \"+3\" — so it sits in a row\n * of filters without changing its height; the open list shows everything,\n * chosen or not.\n *\n * @element kt-multi-select\n *\n * @csspart control - The field.\n * @csspart chips - The row of chips.\n * @csspart input - The native `<input>`.\n * @csspart popup - The option list.\n * @csspart option - An option row.\n *\n * @fires kt-change - The choice changed. `detail: { value, options }`.\n * @fires kt-filter - The query changed. `detail: { query }`.\n *\n * @example\n * ```js\n * select.options = [{ id: 'ne', label: 'North East' }, { id: 'sw', label: 'South West' }];\n * select.value = ['ne'];\n * select.addEventListener('kt-change', (e) => filter(e.detail.value));\n * ```\n */\nexport class KtMultiSelect extends KtElement {\n static readonly formAssociated = true;\n\n static override styles = [\n KtElement.styles,\n floatingStyles,\n listboxStyles,\n css`\n :host {\n position: relative;\n display: block;\n --field-height: var(--button-height);\n --chip-height: calc(var(--field-height) - 16px);\n }\n\n .control {\n display: flex;\n align-items: center;\n gap: var(--gap-element);\n width: 100%;\n height: var(--field-height);\n padding: 0 var(--button-padding-x);\n color: var(--text-body);\n font: var(--font-input);\n background-color: var(--color-dark-20);\n /* The same resting hairline and rings as kt-input-menu. */\n border: var(--border-width) solid var(--border-field);\n border-radius: var(--radius-input);\n outline: var(--outline-width) solid transparent;\n cursor: text;\n transition:\n background-color var(--duration-instant),\n outline-color var(--duration-instant);\n }\n\n .control:hover {\n outline: var(--outline-width) solid var(--color-text-700);\n }\n .control:focus-within {\n background-color: var(--color-dark-12);\n outline: var(--outline-width) solid var(--color-primary-base);\n }\n\n .error .control,\n .error .control:hover,\n .error .control:focus-within {\n outline: var(--outline-width) solid var(--color-danger-base);\n }\n\n :host(:disabled) {\n pointer-events: none;\n opacity: 0.6;\n }\n\n /* One line, whatever is chosen: the chips that do not fit are hidden\n and counted in the \"+N\" beside them. */\n .chips {\n display: flex;\n flex: 0 1 auto;\n align-items: center;\n gap: var(--gap-element);\n min-width: 0;\n overflow: hidden;\n }\n\n /* Chips sit inset in the field, the same distance from its top, bottom\n and left edge — a fill inside a fill, in the family of a chosen\n segment or option, never an outlined pill. */\n .has-chips {\n padding-left: calc((var(--field-height) - var(--chip-height)) / 2);\n }\n\n .chip,\n .more {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: 2px;\n height: var(--chip-height);\n padding: 0 8px;\n color: var(--text-body);\n font: var(--font-normal-small);\n white-space: nowrap;\n background: var(--color-dark-23);\n border-radius: calc(var(--radius-input) - 2px);\n }\n\n .chip.removable {\n padding-right: 4px;\n }\n\n /* The chips that do not fit are hidden by fitChips; their own display\n would otherwise win over the attribute and leave them drawn. */\n .chip[hidden] {\n display: none;\n }\n\n /* A count, not a choice: same shape, quieter. */\n .more {\n color: var(--text-muted);\n }\n\n .remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n color: var(--text-muted);\n background: transparent;\n border: none;\n border-radius: calc(4px * var(--radius-scale, 1));\n cursor: pointer;\n transition:\n background-color var(--duration-instant),\n color var(--duration-instant);\n }\n .remove:hover {\n color: var(--text-body);\n background: var(--color-dark-24);\n }\n .remove:focus-visible {\n outline: var(--outline-width) solid var(--color-primary-base);\n outline-offset: 1px;\n }\n\n input {\n flex: 1;\n min-width: ${INPUT_MIN_WIDTH}px;\n color: var(--text-body);\n font: var(--font-input);\n background: transparent;\n border: none;\n outline: none;\n }\n\n input::placeholder {\n color: var(--text-muted);\n }\n\n .toggle {\n display: inline-flex;\n flex: none;\n align-items: center;\n padding: 0;\n color: inherit;\n background: transparent;\n border: none;\n cursor: pointer;\n transition: transform var(--duration-fast) ease-in-out;\n }\n .open .toggle {\n transform: scaleY(-1);\n }\n\n .option {\n display: flex;\n align-items: center;\n gap: var(--gap-element);\n }\n\n /* The tick's room is kept on every row, so labels line up whether or\n not their option is chosen. */\n .tick {\n display: inline-flex;\n width: 16px;\n color: var(--color-primary-text);\n }\n `,\n ];\n\n @query('input')\n private input!: HTMLInputElement;\n\n private internals: UsableInternals | null = null;\n private defaultValue: KtMultiSelectValue = [];\n private readonly listId = uniqueId('kt-multi-select-list');\n private readonly countId = uniqueId('kt-multi-select-count');\n private resizeObserver: ResizeObserver | undefined;\n\n @state()\n private open = false;\n\n /** The side the list opened on, for the direction of its entrance. */\n @state()\n private placement: Side = 'bottom';\n\n private floating = new FloatingController(this, {\n panel: () => this.shadowRoot?.querySelector<HTMLElement>('.popup'),\n anchor: () => this.shadowRoot?.querySelector('.control'),\n matchWidth: true,\n onPlace: (side) => {\n this.placement = side;\n },\n });\n\n @state()\n private query = '';\n\n @state()\n private activeIndex = -1;\n\n /** Chips hidden for want of room, counted in \"+N\". */\n @state()\n private overflowCount = 0;\n\n @property({ attribute: false })\n options: readonly KtOption[] = [];\n\n /** The ids of the chosen options, in the order they were chosen. */\n @property({ attribute: false })\n value: KtMultiSelectValue = [];\n\n @property({ type: String })\n placeholder = '';\n\n @property({ type: String })\n name = '';\n\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Disabled by an enclosing `<fieldset>`, which leaves `disabled` alone. */\n @state()\n private formDisabled = false;\n\n /** Whether the control is off, by its own `disabled` or by its form. */\n private get inactive(): boolean {\n return this.disabled || this.formDisabled;\n }\n\n /** At least one value must be chosen. */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n @property({ type: String, reflect: true })\n error = '';\n\n /** Accessible name, when no `<kt-label-input>` wraps the field. */\n @property({ type: String })\n label = '';\n\n /** Shown in the list when no option matches. */\n @property({ type: String, attribute: 'empty-text' })\n emptyText: string | undefined = undefined;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.internals ??= attachFormInternals(this);\n this.defaultValue = this.value;\n // Back on the document if it was reconnected while open.\n toggleListener(this.open, document, 'pointerdown', this.onDocumentPointerDown);\n // A web font changes every chip's width once it arrives.\n void document.fonts?.ready.then(() => this.fitChips());\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('pointerdown', this.onDocumentPointerDown);\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n }\n\n override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('value') ||\n changed.has('name') ||\n changed.has('required') ||\n changed.has('error') ||\n this.stringsChanged(changed)\n ) {\n // One entry per value, under the one name, as <select multiple> does;\n // nothing at all when nothing is chosen.\n let data: FormData | null = null;\n if (this.value.length > 0) {\n data = new FormData();\n for (const id of this.value) data.append(this.name, String(id));\n }\n setFormValue(this.internals, data);\n\n const missing = this.required && this.value.length === 0;\n setValidity(\n this.internals,\n { valueMissing: missing, customError: Boolean(this.error) },\n this.error || (missing ? strings().selectOption : ''),\n );\n }\n }\n\n // Untyped: `open` is private, so not among the keys PropertyValues<this> knows.\n override updated(changed: PropertyValues): void {\n // Only an open list closes on an outside click, so only an open one listens.\n if (changed.has('open')) {\n toggleListener(this.open, document, 'pointerdown', this.onDocumentPointerDown);\n }\n this.floating.sync(this.open);\n this.observeWidth();\n this.fitChips();\n }\n\n formResetCallback(): void {\n this.value = this.defaultValue;\n this.close();\n }\n\n /**\n * Called by the platform when the control's disabled state changes — its\n * own `disabled`, or an ancestor `<fieldset disabled>` it cannot see.\n */\n formDisabledCallback(disabled: boolean): void {\n this.formDisabled = disabled;\n }\n\n /** Called by the platform when the browser restores a session. */\n formStateRestoreCallback(state: string | FormData | null): void {\n const saved =\n state instanceof FormData ? state.getAll(this.name).map(String) : state ? [state] : [];\n // Back to the options' own ids, which may be numbers.\n this.value = saved.map(\n (text) => this.options.find((option) => String(option.id) === text)?.id ?? text,\n );\n }\n\n override focus(options?: FocusOptions): void {\n this.input?.focus(options);\n }\n\n /** The chosen options, in the order chosen. */\n get selectedOptions(): readonly KtOption[] {\n return this.value.map(\n (id) => this.options.find((option) => option.id === id) ?? { id, label: String(id) },\n );\n }\n\n /** Options after the current query, which is what the keyboard walks. */\n private get visibleOptions(): readonly KtOption[] {\n return filterOptions(this.options, this.query);\n }\n\n private isChosen(option: KtOption): boolean {\n return this.value.includes(option.id);\n }\n\n private onDocumentPointerDown = (event: Event): void => {\n if (event.composedPath().includes(this)) return;\n this.close();\n };\n\n private openList(): void {\n if (this.inactive || this.open) return;\n this.open = true;\n this.activeIndex = firstEnabledIndex(this.visibleOptions);\n }\n\n private close(): void {\n this.open = false;\n this.query = '';\n this.activeIndex = -1;\n }\n\n private onInput(event: Event): void {\n this.query = (event.target as HTMLInputElement).value;\n this.open = true;\n this.activeIndex = firstEnabledIndex(this.visibleOptions);\n emit(this, 'kt-filter', { query: this.query });\n }\n\n /** Adds an option, or takes it out if it is already chosen. The list stays open. */\n private toggle(option: KtOption): void {\n if (option.disabled || this.inactive) return;\n this.commit(\n this.isChosen(option)\n ? this.value.filter((id) => id !== option.id)\n : [...this.value, option.id],\n );\n }\n\n private removeValue(id: string | number): void {\n if (this.inactive) return;\n this.commit(this.value.filter((chosen) => chosen !== id));\n }\n\n private commit(value: KtMultiSelectValue): void {\n this.value = value;\n emit(this, 'kt-change', { value, options: this.selectedOptions });\n }\n\n private onKeyDown(event: KeyboardEvent): void {\n const options = this.visibleOptions;\n\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp':\n event.preventDefault();\n if (!this.open) return this.openList();\n this.activeIndex = nextEnabledIndex(\n options,\n this.activeIndex,\n event.key === 'ArrowDown' ? 1 : -1,\n );\n return;\n case 'Home':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = firstEnabledIndex(options);\n return;\n case 'End':\n if (!this.open) return;\n event.preventDefault();\n this.activeIndex = lastEnabledIndex(options);\n return;\n case 'Enter': {\n if (!this.open) return;\n event.preventDefault();\n const option = options[this.activeIndex];\n if (option) this.toggle(option);\n return;\n }\n case 'Backspace': {\n // Only once the text is gone: until then Backspace edits the query.\n const last = this.value[this.value.length - 1];\n if (this.input?.value || last === undefined) return;\n this.removeValue(last);\n return;\n }\n case 'Escape':\n if (!this.open) return;\n event.stopPropagation();\n this.close();\n return;\n case 'Tab':\n this.close();\n }\n }\n\n /** Measures again when the field's width changes, since that is what fits. */\n private observeWidth(): void {\n if (this.resizeObserver || typeof ResizeObserver === 'undefined') return;\n const control = this.shadowRoot?.querySelector('.control');\n if (!control) return;\n this.resizeObserver = new ResizeObserver(() => this.fitChips());\n this.resizeObserver.observe(control);\n }\n\n /**\n * Hides the chips that do not fit on the field's one line, and counts them\n * in \"+N\".\n *\n * The room comes from what never moves: the field's inner width, less the\n * input's minimum, the toggle and the gaps between them. It used to be read\n * from the chip row itself, whose width depends on the chips shown and on\n * the \"+N\" — so in Firefox each pass undid the last, and the loop between\n * this and the render it triggered froze the page.\n */\n private fitChips(): void {\n const control = this.shadowRoot?.querySelector<HTMLElement>('.control');\n const row = this.shadowRoot?.querySelector<HTMLElement>('.chips');\n if (!control || !row) return;\n const chips = [...row.querySelectorAll<HTMLElement>('.chip')];\n for (const chip of chips) chip.hidden = false;\n\n const style = getComputedStyle(control);\n const gap = parseFloat(style.columnGap) || 0;\n const toggle = control.querySelector('.toggle')?.getBoundingClientRect().width ?? 0;\n const inner =\n control.clientWidth - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);\n // Between the chips and the input, and between the input and the toggle.\n const room = inner - INPUT_MIN_WIDTH - toggle - 2 * gap;\n // No layout — a test DOM, or a field not on screen — so nothing to fit.\n if (control.clientWidth === 0 || room <= 0) return;\n\n const left = row.getBoundingClientRect().left;\n const fitting = (limit: number) =>\n chips.filter((chip) => chip.getBoundingClientRect().right - left <= limit).length;\n\n let shown = fitting(room);\n if (shown < chips.length) {\n // Room for the \"+N\" and its gap: as wide as it is, or a guess before it exists.\n const more = this.shadowRoot?.querySelector('.more')?.getBoundingClientRect().width;\n shown = fitting(room - (more || MORE_WIDTH_GUESS) - gap);\n }\n\n chips.forEach((chip, index) => {\n chip.hidden = index >= shown;\n });\n const hidden = chips.length - shown;\n if (hidden !== this.overflowCount) this.overflowCount = hidden;\n }\n\n private optionId(index: number): string {\n return `${this.listId}-option-${index}`;\n }\n\n override render(): TemplateResult {\n const options = this.visibleOptions;\n const chosen = this.selectedOptions;\n\n return html`<div\n class=${classMap({ open: this.open, error: Boolean(this.error) })}\n @keydown=${this.onKeyDown}\n >\n <span id=${this.countId} class=\"visually-hidden\">\n ${chosen.length > 0 ? strings().selectedCount(chosen.length) : ''}\n </span>\n\n <div\n part=\"control\"\n class=${classMap({ control: true, 'has-chips': chosen.length > 0 })}\n @click=${this.openList}\n >\n <div part=\"chips\" class=\"chips\">\n ${chosen.map(\n (option) =>\n html`<span class=${classMap({ chip: true, removable: !this.inactive })}>\n ${optionLabel(option)}\n ${\n this.inactive\n ? nothing\n : html`<button\n type=\"button\"\n class=\"remove\"\n tabindex=\"-1\"\n aria-label=${strings().remove(optionLabel(option))}\n @click=${(event: Event) => {\n // Removing a chip is not a request to open the list.\n event.stopPropagation();\n this.removeValue(option.id);\n }}\n >\n <kt-icon name=\"x\" size=\"12\"></kt-icon>\n </button>`\n }\n </span>`,\n )}\n </div>\n ${\n this.overflowCount > 0\n ? html`<span class=\"more\"\n >${\n // With not one chip left to count on from, \"+3\" says less\n // than how many are chosen. The wider label only ever hides\n // more chips, never fewer, so the fit cannot swing on it.\n this.overflowCount === chosen.length\n ? strings().selectedCount(chosen.length)\n : `+${this.overflowCount}`\n }</span\n >`\n : nothing\n }\n\n <input\n part=\"input\"\n role=\"combobox\"\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-controls=${this.listId}\n aria-autocomplete=\"list\"\n aria-activedescendant=${\n this.open && this.activeIndex >= 0 ? this.optionId(this.activeIndex) : nothing\n }\n aria-label=${this.label || nothing}\n aria-describedby=${this.countId}\n aria-invalid=${this.error ? 'true' : nothing}\n placeholder=${chosen.length === 0 && this.placeholder ? this.placeholder : nothing}\n .value=${live(this.query)}\n ?disabled=${this.inactive}\n @focus=${this.openList}\n @input=${this.onInput}\n />\n\n <button\n type=\"button\"\n class=\"toggle\"\n aria-label=${this.open ? strings().closeList : strings().openList}\n tabindex=\"-1\"\n @click=${(event: Event) => {\n event.stopPropagation();\n if (this.open) this.close();\n else this.openList();\n }}\n >\n <kt-icon name=\"chevron-down\" size=\"18\"></kt-icon>\n </button>\n </div>\n\n <ul\n part=\"popup\"\n id=${this.listId}\n popover=\"manual\"\n class=${classMap({\n popup: true,\n floating: true,\n open: this.open,\n top: this.placement === 'top',\n })}\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-label=${this.label || this.placeholder}\n @pointerdown=${(event: Event) => {\n // Keeps the focus in the field while options are ticked.\n event.preventDefault();\n }}\n >\n ${\n options.length === 0\n ? html`<li class=\"empty\">${this.emptyText ?? strings().noOptions}</li>`\n : options.map((option, index) => {\n const isChosen = this.isChosen(option);\n return html`<li\n part=\"option\"\n id=${this.optionId(index)}\n class=${classMap({\n option: true,\n selected: isChosen,\n active: index === this.activeIndex,\n disabled: Boolean(option.disabled),\n })}\n role=\"option\"\n aria-selected=${isChosen ? 'true' : 'false'}\n aria-disabled=${option.disabled ? 'true' : nothing}\n @click=${() => this.toggle(option)}\n >\n <span class=\"tick\" aria-hidden=\"true\">\n ${isChosen ? html`<kt-icon name=\"check\" size=\"16\"></kt-icon>` : nothing}\n </span>\n ${optionLabel(option)}\n </li>`;\n })\n }\n </ul>\n </div>`;\n }\n}\n\ndefineElement('kt-multi-select', KtMultiSelect);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kt-multi-select': KtMultiSelect;\n }\n}\n"],"names":["INPUT_MIN_WIDTH","MORE_WIDTH_GUESS","KtMultiSelect","KtElement","uniqueId","FloatingController","side","event","floatingStyles","listboxStyles","css","attachFormInternals","toggleListener","changed","data","id","setFormValue","missing","setValidity","strings","disabled","state","saved","text","option","options","filterOptions","firstEnabledIndex","emit","chosen","value","nextEnabledIndex","lastEnabledIndex","last","control","row","chips","chip","style","gap","toggle","room","left","fitting","limit","shown","more","index","hidden","html","classMap","optionLabel","nothing","live","isChosen","__decorateClass","query","property","defineElement"],"mappings":"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"}
|