@entur/dropdown 7.3.1 → 7.3.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dropdown.cjs.js +1465 -0
- package/dist/dropdown.cjs.js.map +1 -0
- package/dist/dropdown.esm.js +1336 -1746
- package/dist/dropdown.esm.js.map +1 -1
- package/dist/index.d.ts +313 -7
- package/dist/styles.css +82 -90
- package/package.json +39 -21
- package/dist/Dropdown.d.ts +0 -91
- package/dist/MultiSelect.d.ts +0 -108
- package/dist/NativeDropdown.d.ts +0 -56
- package/dist/SearchableDropdown.d.ts +0 -32
- package/dist/components/DropdownList.d.ts +0 -27
- package/dist/components/FieldComponents.d.ts +0 -33
- package/dist/dropdown.cjs.development.js +0 -1882
- package/dist/dropdown.cjs.development.js.map +0 -1
- package/dist/dropdown.cjs.production.min.js +0 -2
- package/dist/dropdown.cjs.production.min.js.map +0 -1
- package/dist/index.js +0 -8
- package/dist/types.d.ts +0 -15
- package/dist/useNormalizedItems.d.ts +0 -2
- package/dist/useResolvedItems.d.ts +0 -6
- package/dist/utils.d.ts +0 -39
package/dist/dropdown.esm.js
CHANGED
|
@@ -1,735 +1,382 @@
|
|
|
1
|
-
import { useDebounce, mergeRefs, useRandomId, warnAboutMissingStyles } from
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
for (var e = 1; e < arguments.length; e++) {
|
|
43
|
-
var t = arguments[e];
|
|
44
|
-
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
45
|
-
}
|
|
46
|
-
return n;
|
|
47
|
-
}, _extends.apply(null, arguments);
|
|
48
|
-
}
|
|
49
|
-
function _objectWithoutPropertiesLoose(r, e) {
|
|
50
|
-
if (null == r) return {};
|
|
51
|
-
var t = {};
|
|
52
|
-
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
53
|
-
if (e.includes(n)) continue;
|
|
54
|
-
t[n] = r[n];
|
|
55
|
-
}
|
|
56
|
-
return t;
|
|
57
|
-
}
|
|
58
|
-
function _regeneratorRuntime() {
|
|
59
|
-
_regeneratorRuntime = function () {
|
|
60
|
-
return e;
|
|
61
|
-
};
|
|
62
|
-
var t,
|
|
63
|
-
e = {},
|
|
64
|
-
r = Object.prototype,
|
|
65
|
-
n = r.hasOwnProperty,
|
|
66
|
-
o = Object.defineProperty || function (t, e, r) {
|
|
67
|
-
t[e] = r.value;
|
|
68
|
-
},
|
|
69
|
-
i = "function" == typeof Symbol ? Symbol : {},
|
|
70
|
-
a = i.iterator || "@@iterator",
|
|
71
|
-
c = i.asyncIterator || "@@asyncIterator",
|
|
72
|
-
u = i.toStringTag || "@@toStringTag";
|
|
73
|
-
function define(t, e, r) {
|
|
74
|
-
return Object.defineProperty(t, e, {
|
|
75
|
-
value: r,
|
|
76
|
-
enumerable: !0,
|
|
77
|
-
configurable: !0,
|
|
78
|
-
writable: !0
|
|
79
|
-
}), t[e];
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
define({}, "");
|
|
83
|
-
} catch (t) {
|
|
84
|
-
define = function (t, e, r) {
|
|
85
|
-
return t[e] = r;
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function wrap(t, e, r, n) {
|
|
89
|
-
var i = e && e.prototype instanceof Generator ? e : Generator,
|
|
90
|
-
a = Object.create(i.prototype),
|
|
91
|
-
c = new Context(n || []);
|
|
92
|
-
return o(a, "_invoke", {
|
|
93
|
-
value: makeInvokeMethod(t, r, c)
|
|
94
|
-
}), a;
|
|
95
|
-
}
|
|
96
|
-
function tryCatch(t, e, r) {
|
|
97
|
-
try {
|
|
98
|
-
return {
|
|
99
|
-
type: "normal",
|
|
100
|
-
arg: t.call(e, r)
|
|
101
|
-
};
|
|
102
|
-
} catch (t) {
|
|
103
|
-
return {
|
|
104
|
-
type: "throw",
|
|
105
|
-
arg: t
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
e.wrap = wrap;
|
|
110
|
-
var h = "suspendedStart",
|
|
111
|
-
l = "suspendedYield",
|
|
112
|
-
f = "executing",
|
|
113
|
-
s = "completed",
|
|
114
|
-
y = {};
|
|
115
|
-
function Generator() {}
|
|
116
|
-
function GeneratorFunction() {}
|
|
117
|
-
function GeneratorFunctionPrototype() {}
|
|
118
|
-
var p = {};
|
|
119
|
-
define(p, a, function () {
|
|
120
|
-
return this;
|
|
121
|
-
});
|
|
122
|
-
var d = Object.getPrototypeOf,
|
|
123
|
-
v = d && d(d(values([])));
|
|
124
|
-
v && v !== r && n.call(v, a) && (p = v);
|
|
125
|
-
var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
|
|
126
|
-
function defineIteratorMethods(t) {
|
|
127
|
-
["next", "throw", "return"].forEach(function (e) {
|
|
128
|
-
define(t, e, function (t) {
|
|
129
|
-
return this._invoke(e, t);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function AsyncIterator(t, e) {
|
|
134
|
-
function invoke(r, o, i, a) {
|
|
135
|
-
var c = tryCatch(t[r], t, o);
|
|
136
|
-
if ("throw" !== c.type) {
|
|
137
|
-
var u = c.arg,
|
|
138
|
-
h = u.value;
|
|
139
|
-
return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
|
|
140
|
-
invoke("next", t, i, a);
|
|
141
|
-
}, function (t) {
|
|
142
|
-
invoke("throw", t, i, a);
|
|
143
|
-
}) : e.resolve(h).then(function (t) {
|
|
144
|
-
u.value = t, i(u);
|
|
145
|
-
}, function (t) {
|
|
146
|
-
return invoke("throw", t, i, a);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
a(c.arg);
|
|
150
|
-
}
|
|
151
|
-
var r;
|
|
152
|
-
o(this, "_invoke", {
|
|
153
|
-
value: function (t, n) {
|
|
154
|
-
function callInvokeWithMethodAndArg() {
|
|
155
|
-
return new e(function (e, r) {
|
|
156
|
-
invoke(t, n, e, r);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
function makeInvokeMethod(e, r, n) {
|
|
164
|
-
var o = h;
|
|
165
|
-
return function (i, a) {
|
|
166
|
-
if (o === f) throw Error("Generator is already running");
|
|
167
|
-
if (o === s) {
|
|
168
|
-
if ("throw" === i) throw a;
|
|
1
|
+
import { useDebounce, mergeRefs, useRandomId, warnAboutMissingStyles } from "@entur/utils";
|
|
2
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { forwardRef, createElement, useState, useRef, useEffect, useCallback } from "react";
|
|
4
|
+
import { useCombobox, useMultipleSelection, useSelect } from "downshift";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import { useFloating, offset, shift, size, flip, autoUpdate } from "@floating-ui/react-dom";
|
|
7
|
+
import { Checkbox, BaseFormControl } from "@entur/form";
|
|
8
|
+
import { space } from "@entur/tokens";
|
|
9
|
+
import { VisuallyHidden } from "@entur/a11y";
|
|
10
|
+
import { IconButton } from "@entur/button";
|
|
11
|
+
import { TagChip } from "@entur/chip";
|
|
12
|
+
import { DownArrowIcon, CloseSmallIcon } from "@entur/icons";
|
|
13
|
+
import { LoadingDots } from "@entur/loader";
|
|
14
|
+
import { Tooltip } from "@entur/tooltip";
|
|
15
|
+
const DropdownList = ({
|
|
16
|
+
ariaLabelChosenSingular = "valgt",
|
|
17
|
+
ariaLabelSelectedItem = ", valgt element, trykk for å fjerne",
|
|
18
|
+
getItemProps,
|
|
19
|
+
getMenuProps,
|
|
20
|
+
isOpen,
|
|
21
|
+
highlightedIndex,
|
|
22
|
+
listItems,
|
|
23
|
+
floatingStyles,
|
|
24
|
+
setListRef,
|
|
25
|
+
loading = false,
|
|
26
|
+
loadingText = "Laster inn …",
|
|
27
|
+
noMatchesText = "Ingen treff for søket",
|
|
28
|
+
selectAllCheckboxState,
|
|
29
|
+
selectAllItem,
|
|
30
|
+
selectedItems,
|
|
31
|
+
readOnly = false,
|
|
32
|
+
...rest
|
|
33
|
+
}) => {
|
|
34
|
+
const isMultiselect = selectAllItem !== void 0;
|
|
35
|
+
const isNoMatches = !loading && (listItems.length === 0 || listItems?.length === 1 && listItems?.[0]?.value === selectAllItem?.value);
|
|
36
|
+
const isItemSelected = (item) => selectedItems.some(
|
|
37
|
+
(selectedItem) => selectedItem?.value === item?.value && selectedItem?.label === item?.label
|
|
38
|
+
);
|
|
39
|
+
const ariaValuesSelectAll = () => {
|
|
40
|
+
switch (selectAllCheckboxState?.()) {
|
|
41
|
+
case "indeterminate": {
|
|
169
42
|
return {
|
|
170
|
-
|
|
171
|
-
|
|
43
|
+
label: `${selectAllItem?.label}, delvis valgt`,
|
|
44
|
+
selected: false
|
|
172
45
|
};
|
|
173
46
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (u === y) continue;
|
|
180
|
-
return u;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
|
|
184
|
-
if (o === h) throw o = s, n.arg;
|
|
185
|
-
n.dispatchException(n.arg);
|
|
186
|
-
} else "return" === n.method && n.abrupt("return", n.arg);
|
|
187
|
-
o = f;
|
|
188
|
-
var p = tryCatch(e, r, n);
|
|
189
|
-
if ("normal" === p.type) {
|
|
190
|
-
if (o = n.done ? s : l, p.arg === y) continue;
|
|
191
|
-
return {
|
|
192
|
-
value: p.arg,
|
|
193
|
-
done: n.done
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
"throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
|
|
47
|
+
case true: {
|
|
48
|
+
return {
|
|
49
|
+
label: `${selectAllItem?.label}, ${ariaLabelChosenSingular}`,
|
|
50
|
+
selected: true
|
|
51
|
+
};
|
|
197
52
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
function maybeInvokeDelegate(e, r) {
|
|
201
|
-
var n = r.method,
|
|
202
|
-
o = e.iterator[n];
|
|
203
|
-
if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
|
|
204
|
-
var i = tryCatch(o, e.iterator, r.arg);
|
|
205
|
-
if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
|
|
206
|
-
var a = i.arg;
|
|
207
|
-
return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
|
|
208
|
-
}
|
|
209
|
-
function pushTryEntry(t) {
|
|
210
|
-
var e = {
|
|
211
|
-
tryLoc: t[0]
|
|
212
|
-
};
|
|
213
|
-
1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
|
|
214
|
-
}
|
|
215
|
-
function resetTryEntry(t) {
|
|
216
|
-
var e = t.completion || {};
|
|
217
|
-
e.type = "normal", delete e.arg, t.completion = e;
|
|
218
|
-
}
|
|
219
|
-
function Context(t) {
|
|
220
|
-
this.tryEntries = [{
|
|
221
|
-
tryLoc: "root"
|
|
222
|
-
}], t.forEach(pushTryEntry, this), this.reset(!0);
|
|
223
|
-
}
|
|
224
|
-
function values(e) {
|
|
225
|
-
if (e || "" === e) {
|
|
226
|
-
var r = e[a];
|
|
227
|
-
if (r) return r.call(e);
|
|
228
|
-
if ("function" == typeof e.next) return e;
|
|
229
|
-
if (!isNaN(e.length)) {
|
|
230
|
-
var o = -1,
|
|
231
|
-
i = function next() {
|
|
232
|
-
for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
|
|
233
|
-
return next.value = t, next.done = !0, next;
|
|
234
|
-
};
|
|
235
|
-
return i.next = i;
|
|
53
|
+
default: {
|
|
54
|
+
return { label: `${selectAllItem?.label}`, selected: false };
|
|
236
55
|
}
|
|
237
56
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
|
|
249
|
-
}, e.mark = function (t) {
|
|
250
|
-
return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
|
|
251
|
-
}, e.awrap = function (t) {
|
|
252
|
-
return {
|
|
253
|
-
__await: t
|
|
254
|
-
};
|
|
255
|
-
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
|
|
256
|
-
return this;
|
|
257
|
-
}), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
|
|
258
|
-
void 0 === i && (i = Promise);
|
|
259
|
-
var a = new AsyncIterator(wrap(t, r, n, o), i);
|
|
260
|
-
return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
|
|
261
|
-
return t.done ? t.value : a.next();
|
|
262
|
-
});
|
|
263
|
-
}, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
|
|
264
|
-
return this;
|
|
265
|
-
}), define(g, "toString", function () {
|
|
266
|
-
return "[object Generator]";
|
|
267
|
-
}), e.keys = function (t) {
|
|
268
|
-
var e = Object(t),
|
|
269
|
-
r = [];
|
|
270
|
-
for (var n in e) r.push(n);
|
|
271
|
-
return r.reverse(), function next() {
|
|
272
|
-
for (; r.length;) {
|
|
273
|
-
var t = r.pop();
|
|
274
|
-
if (t in e) return next.value = t, next.done = !1, next;
|
|
275
|
-
}
|
|
276
|
-
return next.done = !0, next;
|
|
277
|
-
};
|
|
278
|
-
}, e.values = values, Context.prototype = {
|
|
279
|
-
constructor: Context,
|
|
280
|
-
reset: function (e) {
|
|
281
|
-
if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
|
|
282
|
-
},
|
|
283
|
-
stop: function () {
|
|
284
|
-
this.done = !0;
|
|
285
|
-
var t = this.tryEntries[0].completion;
|
|
286
|
-
if ("throw" === t.type) throw t.arg;
|
|
287
|
-
return this.rval;
|
|
288
|
-
},
|
|
289
|
-
dispatchException: function (e) {
|
|
290
|
-
if (this.done) throw e;
|
|
291
|
-
var r = this;
|
|
292
|
-
function handle(n, o) {
|
|
293
|
-
return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
|
|
294
|
-
}
|
|
295
|
-
for (var o = this.tryEntries.length - 1; o >= 0; --o) {
|
|
296
|
-
var i = this.tryEntries[o],
|
|
297
|
-
a = i.completion;
|
|
298
|
-
if ("root" === i.tryLoc) return handle("end");
|
|
299
|
-
if (i.tryLoc <= this.prev) {
|
|
300
|
-
var c = n.call(i, "catchLoc"),
|
|
301
|
-
u = n.call(i, "finallyLoc");
|
|
302
|
-
if (c && u) {
|
|
303
|
-
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
|
|
304
|
-
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
|
|
305
|
-
} else if (c) {
|
|
306
|
-
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
|
|
307
|
-
} else {
|
|
308
|
-
if (!u) throw Error("try statement without catch or finally");
|
|
309
|
-
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
abrupt: function (t, e) {
|
|
315
|
-
for (var r = this.tryEntries.length - 1; r >= 0; --r) {
|
|
316
|
-
var o = this.tryEntries[r];
|
|
317
|
-
if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
|
|
318
|
-
var i = o;
|
|
319
|
-
break;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
|
|
323
|
-
var a = i ? i.completion : {};
|
|
324
|
-
return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
|
|
325
|
-
},
|
|
326
|
-
complete: function (t, e) {
|
|
327
|
-
if ("throw" === t.type) throw t.arg;
|
|
328
|
-
return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
|
|
329
|
-
},
|
|
330
|
-
finish: function (t) {
|
|
331
|
-
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
|
|
332
|
-
var r = this.tryEntries[e];
|
|
333
|
-
if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
|
|
57
|
+
};
|
|
58
|
+
const selectAllListItemContent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Checkbox,
|
|
61
|
+
{
|
|
62
|
+
"aria-hidden": "true",
|
|
63
|
+
checked: selectAllCheckboxState?.(),
|
|
64
|
+
className: "eds-dropdown__list__item__checkbox",
|
|
65
|
+
tabIndex: -1,
|
|
66
|
+
onChange: () => void 0
|
|
334
67
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
var o = n.arg;
|
|
343
|
-
resetTryEntry(r);
|
|
344
|
-
}
|
|
345
|
-
return o;
|
|
346
|
-
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
"span",
|
|
71
|
+
{
|
|
72
|
+
className: "eds-dropdown__list__item__text",
|
|
73
|
+
"aria-label": ariaValuesSelectAll().label,
|
|
74
|
+
children: selectAllItem?.label
|
|
347
75
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
iterator: values(e),
|
|
353
|
-
resultName: r,
|
|
354
|
-
nextLoc: n
|
|
355
|
-
}, "next" === this.method && (this.arg = t), y;
|
|
356
|
-
}
|
|
357
|
-
}, e;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
var _excluded$5 = ["ariaLabelChosenSingular", "ariaLabelSelectedItem", "getItemProps", "getMenuProps", "isOpen", "highlightedIndex", "listItems", "floatingStyles", "setListRef", "loading", "loadingText", "noMatchesText", "selectAllCheckboxState", "selectAllItem", "selectedItems", "readOnly"];
|
|
361
|
-
var DropdownList = function DropdownList(_ref) {
|
|
362
|
-
var _listItems$;
|
|
363
|
-
var _ref$ariaLabelChosenS = _ref.ariaLabelChosenSingular,
|
|
364
|
-
ariaLabelChosenSingular = _ref$ariaLabelChosenS === void 0 ? 'valgt' : _ref$ariaLabelChosenS,
|
|
365
|
-
_ref$ariaLabelSelecte = _ref.ariaLabelSelectedItem,
|
|
366
|
-
ariaLabelSelectedItem = _ref$ariaLabelSelecte === void 0 ? ', valgt element, trykk for å fjerne' : _ref$ariaLabelSelecte,
|
|
367
|
-
getItemProps = _ref.getItemProps,
|
|
368
|
-
getMenuProps = _ref.getMenuProps,
|
|
369
|
-
isOpen = _ref.isOpen,
|
|
370
|
-
highlightedIndex = _ref.highlightedIndex,
|
|
371
|
-
listItems = _ref.listItems,
|
|
372
|
-
floatingStyles = _ref.floatingStyles,
|
|
373
|
-
setListRef = _ref.setListRef,
|
|
374
|
-
_ref$loading = _ref.loading,
|
|
375
|
-
loading = _ref$loading === void 0 ? false : _ref$loading,
|
|
376
|
-
_ref$loadingText = _ref.loadingText,
|
|
377
|
-
loadingText = _ref$loadingText === void 0 ? 'Laster inn …' : _ref$loadingText,
|
|
378
|
-
_ref$noMatchesText = _ref.noMatchesText,
|
|
379
|
-
noMatchesText = _ref$noMatchesText === void 0 ? 'Ingen treff for søket' : _ref$noMatchesText,
|
|
380
|
-
selectAllCheckboxState = _ref.selectAllCheckboxState,
|
|
381
|
-
selectAllItem = _ref.selectAllItem,
|
|
382
|
-
selectedItems = _ref.selectedItems,
|
|
383
|
-
_ref$readOnly = _ref.readOnly,
|
|
384
|
-
readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
|
|
385
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
386
|
-
var isMultiselect = selectAllItem !== undefined;
|
|
387
|
-
var isNoMatches = !loading && (listItems.length === 0 || (listItems == null ? void 0 : listItems.length) === 1 && (listItems == null || (_listItems$ = listItems[0]) == null ? void 0 : _listItems$.value) === (selectAllItem == null ? void 0 : selectAllItem.value));
|
|
388
|
-
var isItemSelected = function isItemSelected(item) {
|
|
389
|
-
return selectedItems.some(function (selectedItem) {
|
|
390
|
-
return (selectedItem == null ? void 0 : selectedItem.value) === (item == null ? void 0 : item.value) && (selectedItem == null ? void 0 : selectedItem.label) === (item == null ? void 0 : item.label);
|
|
391
|
-
});
|
|
76
|
+
)
|
|
77
|
+
] });
|
|
78
|
+
const isReactComponent = (icon) => {
|
|
79
|
+
return typeof icon === "function" || typeof icon === "object" && icon !== null && "$$typeof" in icon && typeof icon.$$typeof === "symbol";
|
|
392
80
|
};
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
81
|
+
const listItemContent = (item) => {
|
|
82
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
83
|
+
isMultiselect && /* @__PURE__ */ jsx(
|
|
84
|
+
Checkbox,
|
|
396
85
|
{
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
86
|
+
"aria-hidden": "true",
|
|
87
|
+
checked: isItemSelected(item),
|
|
88
|
+
className: "eds-dropdown__list__item__checkbox",
|
|
89
|
+
tabIndex: -1,
|
|
90
|
+
onChange: () => void 0
|
|
401
91
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
return React.createElement(React.Fragment, null, React.createElement(Checkbox, {
|
|
420
|
-
"aria-hidden": "true",
|
|
421
|
-
checked: selectAllCheckboxState == null ? void 0 : selectAllCheckboxState(),
|
|
422
|
-
className: "eds-dropdown__list__item__checkbox",
|
|
423
|
-
tabIndex: -1,
|
|
424
|
-
onChange: function onChange() {
|
|
425
|
-
return undefined;
|
|
426
|
-
}
|
|
427
|
-
}), React.createElement("span", {
|
|
428
|
-
className: "eds-dropdown__list__item__text",
|
|
429
|
-
"aria-label": ariaValuesSelectAll().label
|
|
430
|
-
}, selectAllItem == null ? void 0 : selectAllItem.label));
|
|
431
|
-
};
|
|
432
|
-
var isReactComponent = function isReactComponent(icon) {
|
|
433
|
-
return typeof icon === 'function' || typeof icon === 'object' && icon !== null && '$$typeof' in icon && typeof icon.$$typeof === 'symbol';
|
|
434
|
-
};
|
|
435
|
-
var listItemContent = function listItemContent(item) {
|
|
436
|
-
return React.createElement(React.Fragment, null, isMultiselect && React.createElement(Checkbox, {
|
|
437
|
-
"aria-hidden": "true",
|
|
438
|
-
checked: isItemSelected(item),
|
|
439
|
-
className: "eds-dropdown__list__item__checkbox",
|
|
440
|
-
tabIndex: -1,
|
|
441
|
-
onChange: function onChange() {
|
|
442
|
-
return undefined;
|
|
443
|
-
}
|
|
444
|
-
}), React.createElement("span", {
|
|
445
|
-
className: "eds-dropdown__list__item__text"
|
|
446
|
-
}, item.label, React.createElement(VisuallyHidden, null, isItemSelected(item) ? ariaLabelSelectedItem : '')), Array.isArray(item.icons) ? item.icons.filter(isReactComponent).map(function (Icon, index) {
|
|
447
|
-
var _ref2, _Icon$displayName;
|
|
448
|
-
var key = ((_ref2 = (_Icon$displayName = Icon.displayName) != null ? _Icon$displayName : Icon.name) != null ? _ref2 : Icon.name) + "-" + index;
|
|
449
|
-
return React.createElement(Icon, {
|
|
450
|
-
key: key,
|
|
451
|
-
inline: true,
|
|
452
|
-
className: "eds-dropdown__list__item__icon"
|
|
453
|
-
});
|
|
454
|
-
}) : null);
|
|
92
|
+
),
|
|
93
|
+
/* @__PURE__ */ jsxs("span", { className: "eds-dropdown__list__item__text", children: [
|
|
94
|
+
item.label,
|
|
95
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { children: isItemSelected(item) ? ariaLabelSelectedItem : "" })
|
|
96
|
+
] }),
|
|
97
|
+
Array.isArray(item.icons) ? item.icons.filter(isReactComponent).map((Icon, index) => {
|
|
98
|
+
const key = `${Icon.displayName ?? Icon.name ?? Icon.name}-${index}`;
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
Icon,
|
|
101
|
+
{
|
|
102
|
+
inline: true,
|
|
103
|
+
className: "eds-dropdown__list__item__icon"
|
|
104
|
+
},
|
|
105
|
+
key
|
|
106
|
+
);
|
|
107
|
+
}) : null
|
|
108
|
+
] });
|
|
455
109
|
};
|
|
456
110
|
return (
|
|
457
111
|
// use popover from @entur/tooltip when that package upgrades to floating-ui
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
112
|
+
/* @__PURE__ */ jsx(
|
|
113
|
+
"ul",
|
|
114
|
+
{
|
|
115
|
+
...getMenuProps({
|
|
116
|
+
"aria-multiselectable": isMultiselect,
|
|
117
|
+
ref: setListRef,
|
|
118
|
+
className: "eds-dropdown__list",
|
|
119
|
+
style: {
|
|
120
|
+
...floatingStyles,
|
|
121
|
+
display: isOpen && !readOnly ? void 0 : "none",
|
|
122
|
+
...rest.style
|
|
123
|
+
}
|
|
124
|
+
}),
|
|
125
|
+
children: (() => {
|
|
126
|
+
if (!isOpen || readOnly) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
if (loading) {
|
|
130
|
+
return /* @__PURE__ */ jsx(
|
|
131
|
+
"li",
|
|
132
|
+
{
|
|
133
|
+
className: "eds-dropdown__list__item",
|
|
134
|
+
children: loadingText
|
|
135
|
+
},
|
|
136
|
+
"dropdown-list-loading"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (isNoMatches) {
|
|
140
|
+
return /* @__PURE__ */ jsx(
|
|
141
|
+
"li",
|
|
142
|
+
{
|
|
143
|
+
className: "eds-dropdown__list__item",
|
|
144
|
+
children: noMatchesText
|
|
145
|
+
},
|
|
146
|
+
"dropdown-list-no-match"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return listItems.map((item, index) => {
|
|
150
|
+
const key = item.itemKey ?? `${item.label ?? ""}-${item.value ?? ""}-${(item.icons ?? []).map((icon) => icon?.displayName ?? icon?.name ?? "unknown").join("-")}`;
|
|
151
|
+
const itemIsSelectAll = item.value === selectAllItem?.value;
|
|
152
|
+
if (itemIsSelectAll && listItems.length <= 2) return null;
|
|
153
|
+
return /* @__PURE__ */ jsx(
|
|
154
|
+
"li",
|
|
155
|
+
{
|
|
156
|
+
className: classNames("eds-dropdown__list__item", {
|
|
157
|
+
"eds-dropdown__list__item--select-all": itemIsSelectAll,
|
|
158
|
+
"eds-dropdown__list__item--highlighted": highlightedIndex === index,
|
|
159
|
+
"eds-dropdown__list__item--selected": !isMultiselect && isItemSelected(item)
|
|
160
|
+
}),
|
|
161
|
+
...getItemProps({
|
|
162
|
+
// @ts-expect-error Since getItemProps expects the same item type
|
|
163
|
+
// here as items, it throws error when selectAllItem is a string.
|
|
164
|
+
// This does, however, not cause any functional issues.
|
|
165
|
+
item,
|
|
166
|
+
index,
|
|
167
|
+
"aria-selected": itemIsSelectAll ? ariaValuesSelectAll().selected : isItemSelected(item)
|
|
168
|
+
}),
|
|
169
|
+
children: itemIsSelectAll ? selectAllListItemContent() : listItemContent(
|
|
170
|
+
item
|
|
171
|
+
)
|
|
172
|
+
},
|
|
173
|
+
key
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
})()
|
|
480
177
|
}
|
|
481
|
-
|
|
482
|
-
var _item$itemKey, _item$label, _item$value, _item$icons;
|
|
483
|
-
var key = (_item$itemKey = item.itemKey) != null ? _item$itemKey : ((_item$label = item.label) != null ? _item$label : '') + "-" + ((_item$value = item.value) != null ? _item$value : '') + "-" + ((_item$icons = item.icons) != null ? _item$icons : []).map(function (icon) {
|
|
484
|
-
var _ref3, _icon$displayName;
|
|
485
|
-
return (_ref3 = (_icon$displayName = icon == null ? void 0 : icon.displayName) != null ? _icon$displayName : icon == null ? void 0 : icon.name) != null ? _ref3 : 'unknown';
|
|
486
|
-
}).join('-');
|
|
487
|
-
var itemIsSelectAll = item.value === (selectAllItem == null ? void 0 : selectAllItem.value);
|
|
488
|
-
if (itemIsSelectAll && listItems.length <= 2) return null;
|
|
489
|
-
return React.createElement("li", _extends({
|
|
490
|
-
className: classNames('eds-dropdown__list__item', {
|
|
491
|
-
'eds-dropdown__list__item--select-all': itemIsSelectAll,
|
|
492
|
-
'eds-dropdown__list__item--highlighted': highlightedIndex === index,
|
|
493
|
-
'eds-dropdown__list__item--selected': !isMultiselect && isItemSelected(item)
|
|
494
|
-
}),
|
|
495
|
-
key: key
|
|
496
|
-
}, getItemProps({
|
|
497
|
-
// @ts-expect-error Since getItemProps expects the same item type
|
|
498
|
-
// here as items, it throws error when selectAllItem is a string.
|
|
499
|
-
// This does, however, not cause any functional issues.
|
|
500
|
-
item: item,
|
|
501
|
-
index: index,
|
|
502
|
-
'aria-selected': itemIsSelectAll ? ariaValuesSelectAll().selected : isItemSelected(item)
|
|
503
|
-
})), itemIsSelectAll ? selectAllListItemContent() : listItemContent(item));
|
|
504
|
-
});
|
|
505
|
-
}())
|
|
178
|
+
)
|
|
506
179
|
);
|
|
507
180
|
};
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
e.stopPropagation()
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
return e.stopPropagation();
|
|
181
|
+
const SelectedItemTag = ({
|
|
182
|
+
ariaLabelRemoveSelected,
|
|
183
|
+
ariaLabelChosen = "valgt",
|
|
184
|
+
disabled,
|
|
185
|
+
getSelectedItemProps,
|
|
186
|
+
index,
|
|
187
|
+
readOnly,
|
|
188
|
+
removeSelectedItem,
|
|
189
|
+
selectedItem
|
|
190
|
+
}) => {
|
|
191
|
+
const { tabIndex: _, ...selectedItemProps } = getSelectedItemProps?.({
|
|
192
|
+
selectedItem,
|
|
193
|
+
index
|
|
194
|
+
}) ?? {};
|
|
195
|
+
return /* @__PURE__ */ createElement(
|
|
196
|
+
TagChip,
|
|
197
|
+
{
|
|
198
|
+
size: "small",
|
|
199
|
+
className: classNames("eds-dropdown__selected-item-tag", {
|
|
200
|
+
"eds-dropdown__selected-item-tag--readonly": readOnly,
|
|
201
|
+
"eds-dropdown__selected-item-tag--disabled": disabled
|
|
202
|
+
}),
|
|
203
|
+
...selectedItemProps,
|
|
204
|
+
onClose: (e) => {
|
|
205
|
+
e.stopPropagation();
|
|
206
|
+
removeSelectedItem(selectedItem);
|
|
207
|
+
},
|
|
208
|
+
onClick: (e) => e.stopPropagation(),
|
|
209
|
+
closeButtonAriaLabel: `${selectedItem.label} ${ariaLabelChosen}, ${ariaLabelRemoveSelected} `,
|
|
210
|
+
key: selectedItem.value,
|
|
211
|
+
"aria-live": "polite"
|
|
540
212
|
},
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
213
|
+
/* @__PURE__ */ jsx(
|
|
214
|
+
"span",
|
|
215
|
+
{
|
|
216
|
+
"aria-hidden": "true",
|
|
217
|
+
className: "eds-dropdown__selected-item-tag__text",
|
|
218
|
+
children: selectedItem.label
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
);
|
|
548
222
|
};
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
clearable =
|
|
554
|
-
labelClearSelected
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
223
|
+
const DropdownFieldAppendix = forwardRef(
|
|
224
|
+
({
|
|
225
|
+
ariaLabelCloseList,
|
|
226
|
+
ariaLabelOpenList,
|
|
227
|
+
clearable = false,
|
|
228
|
+
labelClearSelected,
|
|
229
|
+
focusable = false,
|
|
230
|
+
disabled,
|
|
231
|
+
isOpen,
|
|
232
|
+
loading = false,
|
|
233
|
+
loadingText,
|
|
234
|
+
onClear,
|
|
235
|
+
itemIsSelected,
|
|
236
|
+
...rest
|
|
237
|
+
}, ref) => {
|
|
238
|
+
function getToggleAriaLabel() {
|
|
239
|
+
if (loading) return loadingText;
|
|
240
|
+
if (isOpen) return ariaLabelCloseList;
|
|
241
|
+
return ariaLabelOpenList;
|
|
242
|
+
}
|
|
243
|
+
return /* @__PURE__ */ jsx(Fragment, { children: !disabled && /* @__PURE__ */ jsxs("div", { className: "eds-dropdown__appendix", children: [
|
|
244
|
+
clearable && itemIsSelected && /* @__PURE__ */ jsx(
|
|
245
|
+
ClearableButton,
|
|
246
|
+
{
|
|
247
|
+
onClear,
|
|
248
|
+
focusable: true,
|
|
249
|
+
labelClearSelectedItems: labelClearSelected
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ jsx(
|
|
253
|
+
IconButton,
|
|
254
|
+
{
|
|
255
|
+
className: classNames("eds-dropdown__appendix__toggle-button", {
|
|
256
|
+
"eds-dropdown__appendix__toggle-button--open": isOpen
|
|
257
|
+
}),
|
|
258
|
+
ref,
|
|
259
|
+
"aria-label": getToggleAriaLabel(),
|
|
260
|
+
...rest,
|
|
261
|
+
type: "button",
|
|
262
|
+
tabIndex: focusable ? 0 : -1,
|
|
263
|
+
children: !loading ? /* @__PURE__ */ jsx(DownArrowIcon, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(LoadingDots, { "aria-hidden": "true" })
|
|
264
|
+
}
|
|
265
|
+
)
|
|
266
|
+
] }) });
|
|
569
267
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
tabIndex: focusable ? 0 : -1,
|
|
606
|
-
// These events bubble up to the Dropdown container and trigger openMenu.
|
|
607
|
-
// To avoid this, stopPropagation and preventDefault are added.
|
|
608
|
-
onClick: function onClick(e) {
|
|
609
|
-
e.stopPropagation();
|
|
610
|
-
onClear();
|
|
611
|
-
},
|
|
612
|
-
onKeyDown: function onKeyDown(e) {
|
|
613
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
614
|
-
e.preventDefault();
|
|
615
|
-
e.stopPropagation();
|
|
616
|
-
onClear();
|
|
268
|
+
);
|
|
269
|
+
const ClearableButton = ({
|
|
270
|
+
onClear,
|
|
271
|
+
labelClearSelectedItems = "Fjern valgte",
|
|
272
|
+
focusable = false
|
|
273
|
+
}) => {
|
|
274
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
275
|
+
/* @__PURE__ */ jsx(
|
|
276
|
+
Tooltip,
|
|
277
|
+
{
|
|
278
|
+
"aria-hidden": "true",
|
|
279
|
+
placement: "top",
|
|
280
|
+
content: labelClearSelectedItems,
|
|
281
|
+
className: "eds-dropdown__appendix__clear-button__tooltip",
|
|
282
|
+
children: /* @__PURE__ */ jsx(
|
|
283
|
+
IconButton,
|
|
284
|
+
{
|
|
285
|
+
className: "eds-dropdown__appendix__clear-button",
|
|
286
|
+
type: "button",
|
|
287
|
+
tabIndex: focusable ? 0 : -1,
|
|
288
|
+
onClick: (e) => {
|
|
289
|
+
e.stopPropagation();
|
|
290
|
+
onClear();
|
|
291
|
+
},
|
|
292
|
+
onKeyDown: (e) => {
|
|
293
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
294
|
+
e.preventDefault();
|
|
295
|
+
e.stopPropagation();
|
|
296
|
+
onClear();
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"aria-label": labelClearSelectedItems,
|
|
300
|
+
children: /* @__PURE__ */ jsx(CloseSmallIcon, { "aria-hidden": "true" })
|
|
301
|
+
}
|
|
302
|
+
)
|
|
617
303
|
}
|
|
618
|
-
|
|
619
|
-
"
|
|
620
|
-
}
|
|
621
|
-
"aria-hidden": "true"
|
|
622
|
-
}))), React.createElement("div", {
|
|
623
|
-
className: "eds-dropdown__appendix__divider"
|
|
624
|
-
}));
|
|
304
|
+
),
|
|
305
|
+
/* @__PURE__ */ jsx("div", { className: "eds-dropdown__appendix__divider" })
|
|
306
|
+
] });
|
|
625
307
|
};
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
308
|
+
const useNormalizedItems = (items) => React.useMemo(
|
|
309
|
+
() => items.map((item) => {
|
|
310
|
+
if (typeof item == "string") {
|
|
311
|
+
return {
|
|
312
|
+
value: item,
|
|
313
|
+
label: item
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (item?.value === void 0) {
|
|
317
|
+
return {
|
|
318
|
+
...item,
|
|
319
|
+
value: item.label
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return { ...item, value: item.value };
|
|
323
|
+
}),
|
|
324
|
+
[items]
|
|
325
|
+
);
|
|
326
|
+
const useResolvedItems = (itemsOrItemsResolver, debounceTimeout = 250) => {
|
|
327
|
+
const itemsIsAFunction = typeof itemsOrItemsResolver === "function";
|
|
328
|
+
const [items, setItems] = React.useState(
|
|
329
|
+
itemsIsAFunction ? [] : itemsOrItemsResolver
|
|
330
|
+
);
|
|
331
|
+
const [loading, setLoading] = React.useState(false);
|
|
332
|
+
const abortControllerRef = React.useRef(
|
|
333
|
+
new AbortController()
|
|
334
|
+
);
|
|
335
|
+
const itemsResolver = React.useMemo(() => {
|
|
336
|
+
if (itemsIsAFunction)
|
|
337
|
+
return itemsOrItemsResolver;
|
|
338
|
+
return () => Promise.resolve(itemsOrItemsResolver);
|
|
339
|
+
}, [itemsOrItemsResolver, itemsIsAFunction]);
|
|
340
|
+
const updateItems = async (inputValue) => {
|
|
341
|
+
if (abortControllerRef?.current) abortControllerRef?.current?.abort();
|
|
342
|
+
const abortController = new AbortController();
|
|
343
|
+
abortControllerRef.current = abortController;
|
|
344
|
+
setLoading(true);
|
|
345
|
+
try {
|
|
346
|
+
const resolvedItems = await itemsResolver(
|
|
347
|
+
inputValue ?? "",
|
|
348
|
+
abortControllerRef
|
|
349
|
+
);
|
|
350
|
+
if (abortControllerRef?.current?.signal?.aborted) {
|
|
351
|
+
console.warn(
|
|
352
|
+
"Avbryt den asynkrone funksjonen din med signalet fra AbortController-en for å for å unngå minnelekkasje.",
|
|
353
|
+
'Funksjonen bør kaste en DOMException med navnet "AbortError" når den avbrytes.',
|
|
354
|
+
"",
|
|
355
|
+
"\n\nSe eksempel her: https://linje.entur.no/komponenter/skjemaelementer/dropdown#s%C3%B8kbar-dropdown-med-valg-fra-nettverkskall-bassert-p%C3%A5-tekstinput",
|
|
356
|
+
"\nLes mer om AbortController her: https://developer.mozilla.org/en-US/docs/Web/API/AbortController"
|
|
357
|
+
);
|
|
358
|
+
return;
|
|
635
359
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
360
|
+
setLoading(false);
|
|
361
|
+
setItems(resolvedItems);
|
|
362
|
+
} catch (error2) {
|
|
363
|
+
if (error2 && typeof error2 === "object" && "name" in error2 && error2.name === "AbortError") {
|
|
364
|
+
return;
|
|
640
365
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
if (debounceTimeout === void 0) {
|
|
652
|
-
debounceTimeout = 250;
|
|
653
|
-
}
|
|
654
|
-
var itemsIsAFunction = typeof itemsOrItemsResolver === 'function';
|
|
655
|
-
var _React$useState = React.useState(itemsIsAFunction ? [] : itemsOrItemsResolver),
|
|
656
|
-
items = _React$useState[0],
|
|
657
|
-
setItems = _React$useState[1];
|
|
658
|
-
var _React$useState2 = React.useState(false),
|
|
659
|
-
loading = _React$useState2[0],
|
|
660
|
-
setLoading = _React$useState2[1];
|
|
661
|
-
var abortControllerRef = React.useRef(new AbortController());
|
|
662
|
-
// We normalize the itemsResolver argument to an async function, so we
|
|
663
|
-
// can use it without thinking about the differences later
|
|
664
|
-
var itemsResolver = React.useMemo(function () {
|
|
665
|
-
if (itemsIsAFunction) return itemsOrItemsResolver;
|
|
666
|
-
return function () {
|
|
667
|
-
return Promise.resolve(itemsOrItemsResolver);
|
|
668
|
-
};
|
|
669
|
-
}, [itemsOrItemsResolver, itemsIsAFunction]);
|
|
670
|
-
// This should be called whenever the input value changes
|
|
671
|
-
var updateItems = /*#__PURE__*/function () {
|
|
672
|
-
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(inputValue) {
|
|
673
|
-
var _abortControllerRef$c;
|
|
674
|
-
var abortController, _abortControllerRef$c2, resolvedItems;
|
|
675
|
-
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
676
|
-
while (1) switch (_context.prev = _context.next) {
|
|
677
|
-
case 0:
|
|
678
|
-
// The abortController handles cleanup of the previous request and unmounting
|
|
679
|
-
if (abortControllerRef != null && abortControllerRef.current) abortControllerRef == null || (_abortControllerRef$c = abortControllerRef.current) == null || _abortControllerRef$c.abort();
|
|
680
|
-
abortController = new AbortController();
|
|
681
|
-
abortControllerRef.current = abortController;
|
|
682
|
-
setLoading(true);
|
|
683
|
-
_context.prev = 4;
|
|
684
|
-
_context.next = 7;
|
|
685
|
-
return itemsResolver(inputValue != null ? inputValue : '', abortControllerRef);
|
|
686
|
-
case 7:
|
|
687
|
-
resolvedItems = _context.sent;
|
|
688
|
-
if (!(abortControllerRef != null && (_abortControllerRef$c2 = abortControllerRef.current) != null && (_abortControllerRef$c2 = _abortControllerRef$c2.signal) != null && _abortControllerRef$c2.aborted)) {
|
|
689
|
-
_context.next = 11;
|
|
690
|
-
break;
|
|
691
|
-
}
|
|
692
|
-
console.warn('Avbryt den asynkrone funksjonen din med signalet fra AbortController-en for å for å unngå minnelekkasje.', 'Funksjonen bør kaste en DOMException med navnet "AbortError" når den avbrytes.', '', '\n\nSe eksempel her: https://linje.entur.no/komponenter/skjemaelementer/dropdown#s%C3%B8kbar-dropdown-med-valg-fra-nettverkskall-bassert-p%C3%A5-tekstinput', '\nLes mer om AbortController her: https://developer.mozilla.org/en-US/docs/Web/API/AbortController');
|
|
693
|
-
return _context.abrupt("return");
|
|
694
|
-
case 11:
|
|
695
|
-
setLoading(false);
|
|
696
|
-
setItems(resolvedItems);
|
|
697
|
-
_context.next = 21;
|
|
698
|
-
break;
|
|
699
|
-
case 15:
|
|
700
|
-
_context.prev = 15;
|
|
701
|
-
_context.t0 = _context["catch"](4);
|
|
702
|
-
if (!(_context.t0 && typeof _context.t0 === 'object' && 'name' in _context.t0 && _context.t0.name === 'AbortError')) {
|
|
703
|
-
_context.next = 19;
|
|
704
|
-
break;
|
|
705
|
-
}
|
|
706
|
-
return _context.abrupt("return");
|
|
707
|
-
case 19:
|
|
708
|
-
console.warn('The following error was received but not handled inside Entur Designsystems useResolvedItems hook:');
|
|
709
|
-
throw _context.t0;
|
|
710
|
-
case 21:
|
|
711
|
-
case "end":
|
|
712
|
-
return _context.stop();
|
|
713
|
-
}
|
|
714
|
-
}, _callee, null, [[4, 15]]);
|
|
715
|
-
}));
|
|
716
|
-
return function updateItems(_x) {
|
|
717
|
-
return _ref.apply(this, arguments);
|
|
718
|
-
};
|
|
719
|
-
}();
|
|
720
|
-
var debouncedFetchItems = useDebounce(updateItems, debounceTimeout);
|
|
721
|
-
var normalizedItems = useNormalizedItems(items);
|
|
722
|
-
React.useEffect(function () {
|
|
723
|
-
// send abort signal to previous request on unmount for cleanup
|
|
724
|
-
return function () {
|
|
725
|
-
var _abortControllerRef$c3;
|
|
726
|
-
return abortControllerRef == null || (_abortControllerRef$c3 = abortControllerRef.current) == null ? void 0 : _abortControllerRef$c3.abort('Component unmounted');
|
|
727
|
-
};
|
|
366
|
+
console.warn(
|
|
367
|
+
"The following error was received but not handled inside Entur Designsystems useResolvedItems hook:"
|
|
368
|
+
);
|
|
369
|
+
throw error2;
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const debouncedFetchItems = useDebounce(updateItems, debounceTimeout);
|
|
373
|
+
const normalizedItems = useNormalizedItems(items);
|
|
374
|
+
React.useEffect(() => {
|
|
375
|
+
return () => abortControllerRef?.current?.abort("Component unmounted");
|
|
728
376
|
}, []);
|
|
729
|
-
React.useEffect(
|
|
730
|
-
// Let's fetch the list initially if it's specified
|
|
377
|
+
React.useEffect(() => {
|
|
731
378
|
if (itemsIsAFunction) {
|
|
732
|
-
debouncedFetchItems(
|
|
379
|
+
debouncedFetchItems("");
|
|
733
380
|
}
|
|
734
381
|
}, [itemsIsAFunction, itemsResolver]);
|
|
735
382
|
return {
|
|
@@ -738,79 +385,56 @@ debounceTimeout) {
|
|
|
738
385
|
fetchItems: debouncedFetchItems
|
|
739
386
|
};
|
|
740
387
|
};
|
|
741
|
-
|
|
742
|
-
/* start general utils */
|
|
743
|
-
var EMPTY_INPUT = '';
|
|
388
|
+
const EMPTY_INPUT = "";
|
|
744
389
|
function lowerCaseFilterTest(item, input) {
|
|
745
390
|
if (!input) {
|
|
746
391
|
return true;
|
|
747
392
|
}
|
|
748
|
-
|
|
749
|
-
|
|
393
|
+
const sanitizeEscapeCharacters = input.replace(
|
|
394
|
+
/[-/\\^$*+?.()|[\]{}]/g,
|
|
395
|
+
"\\$&"
|
|
396
|
+
);
|
|
397
|
+
const inputRegex = new RegExp(sanitizeEscapeCharacters, "i");
|
|
750
398
|
return inputRegex.test(item.label);
|
|
751
399
|
}
|
|
752
|
-
function noFilter(
|
|
753
|
-
//@ts-expect-error only here to comply with dropdown filter API
|
|
754
|
-
item,
|
|
755
|
-
//@ts-expect-error only here to comply with dropdown filter API
|
|
756
|
-
input) {
|
|
400
|
+
function noFilter(item, input) {
|
|
757
401
|
return true;
|
|
758
402
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
});
|
|
795
|
-
var someListItemsAreSelected = listItemsWithoutSelectAll.some(function (listItem) {
|
|
796
|
-
return selectedItems.some(function (selectedItem) {
|
|
797
|
-
return selectedItem.value === listItem.value;
|
|
798
|
-
});
|
|
799
|
-
});
|
|
800
|
-
var addClickedItemToSelectedItems = function addClickedItemToSelectedItems(clickedItem, onChange) {
|
|
801
|
-
return onChange([].concat(selectedItems, [clickedItem]));
|
|
802
|
-
};
|
|
803
|
-
var clickedItemIsInSelectedItems = function clickedItemIsInSelectedItems(clickedItem) {
|
|
804
|
-
return selectedItems.some(function (selectedItem) {
|
|
805
|
-
return selectedItem.value === clickedItem.value;
|
|
806
|
-
});
|
|
807
|
-
};
|
|
808
|
-
var clickedItemIsSelectAll = function clickedItemIsSelectAll(clickedItem) {
|
|
809
|
-
return clickedItem.value === selectAll.value;
|
|
810
|
-
};
|
|
811
|
-
var handleListItemClicked = function handleListItemClicked(_ref2) {
|
|
812
|
-
var clickedItem = _ref2.clickedItem,
|
|
813
|
-
onChange = _ref2.onChange;
|
|
403
|
+
const itemToString = (item) => item ? item.label : "";
|
|
404
|
+
const itemToKey = (item) => item?.label + item?.value;
|
|
405
|
+
const isFunctionWithQueryArgument = (object) => typeof object === "function" && object.length > 0;
|
|
406
|
+
const clamp = (val, min = 1, max = 10) => Math.min(Math.max(val, min), max);
|
|
407
|
+
const useMultiselectUtils = ({
|
|
408
|
+
listItems,
|
|
409
|
+
selectedItems,
|
|
410
|
+
selectAll
|
|
411
|
+
}) => {
|
|
412
|
+
const hasSelectedItems = selectedItems.length > 0;
|
|
413
|
+
const listItemsWithoutSelectAll = listItems.filter(
|
|
414
|
+
(item) => item.value !== selectAll.value
|
|
415
|
+
);
|
|
416
|
+
const unselectedItemsInListItems = listItemsWithoutSelectAll.filter(
|
|
417
|
+
(listItem) => !selectedItems.some(
|
|
418
|
+
(selectedItem) => selectedItem.value === listItem.value
|
|
419
|
+
)
|
|
420
|
+
);
|
|
421
|
+
const allListItemsAreSelected = !listItemsWithoutSelectAll.some(
|
|
422
|
+
(listItem) => !selectedItems.some(
|
|
423
|
+
(selectedItem) => selectedItem.value === listItem.value
|
|
424
|
+
)
|
|
425
|
+
);
|
|
426
|
+
const someListItemsAreSelected = listItemsWithoutSelectAll.some(
|
|
427
|
+
(listItem) => selectedItems.some((selectedItem) => selectedItem.value === listItem.value)
|
|
428
|
+
);
|
|
429
|
+
const addClickedItemToSelectedItems = (clickedItem, onChange) => onChange([...selectedItems, clickedItem]);
|
|
430
|
+
const clickedItemIsInSelectedItems = (clickedItem) => selectedItems.some(
|
|
431
|
+
(selectedItem) => selectedItem.value === clickedItem.value
|
|
432
|
+
);
|
|
433
|
+
const clickedItemIsSelectAll = (clickedItem) => clickedItem.value === selectAll.value;
|
|
434
|
+
const handleListItemClicked = ({
|
|
435
|
+
clickedItem,
|
|
436
|
+
onChange
|
|
437
|
+
}) => {
|
|
814
438
|
if (clickedItemIsSelectAll(clickedItem)) {
|
|
815
439
|
if (allListItemsAreSelected) {
|
|
816
440
|
return unselectAllListItems(onChange);
|
|
@@ -822,1054 +446,1020 @@ var useMultiselectUtils = function useMultiselectUtils(_ref) {
|
|
|
822
446
|
}
|
|
823
447
|
addClickedItemToSelectedItems(clickedItem, onChange);
|
|
824
448
|
};
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
449
|
+
const removeClickedItemFromSelectedItems = (clickedItem, onChange) => onChange(
|
|
450
|
+
selectedItems.filter(
|
|
451
|
+
(selectedItem) => selectedItem.value !== clickedItem.value
|
|
452
|
+
)
|
|
453
|
+
);
|
|
454
|
+
const selectAllCheckboxState = () => {
|
|
831
455
|
if (allListItemsAreSelected) return true;
|
|
832
|
-
if (someListItemsAreSelected) return
|
|
456
|
+
if (someListItemsAreSelected) return "indeterminate";
|
|
833
457
|
return false;
|
|
834
458
|
};
|
|
835
|
-
|
|
836
|
-
onChange([
|
|
459
|
+
const selectAllUnselectedItemsInListItems = (onChange) => {
|
|
460
|
+
onChange([...selectedItems, ...unselectedItemsInListItems]);
|
|
837
461
|
};
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
462
|
+
const unselectAllListItems = (onChange) => {
|
|
463
|
+
const selectedItemsWithoutItemsInListItems = selectedItems.filter(
|
|
464
|
+
(selectedItem) => !listItemsWithoutSelectAll.some(
|
|
465
|
+
(listItem) => listItem.value === selectedItem.value
|
|
466
|
+
)
|
|
467
|
+
);
|
|
844
468
|
onChange(selectedItemsWithoutItemsInListItems);
|
|
845
469
|
};
|
|
846
470
|
return {
|
|
847
|
-
addClickedItemToSelectedItems
|
|
848
|
-
allListItemsAreSelected
|
|
849
|
-
clickedItemIsInSelectedItems
|
|
850
|
-
clickedItemIsSelectAll
|
|
851
|
-
handleListItemClicked
|
|
852
|
-
hasSelectedItems
|
|
853
|
-
listItemsWithoutSelectAll
|
|
854
|
-
removeClickedItemFromSelectedItems
|
|
855
|
-
selectAllCheckboxState
|
|
856
|
-
selectAllUnselectedItemsInListItems
|
|
857
|
-
someListItemsAreSelected
|
|
858
|
-
unselectAllListItems
|
|
471
|
+
addClickedItemToSelectedItems,
|
|
472
|
+
allListItemsAreSelected,
|
|
473
|
+
clickedItemIsInSelectedItems,
|
|
474
|
+
clickedItemIsSelectAll,
|
|
475
|
+
handleListItemClicked,
|
|
476
|
+
hasSelectedItems,
|
|
477
|
+
listItemsWithoutSelectAll,
|
|
478
|
+
removeClickedItemFromSelectedItems,
|
|
479
|
+
selectAllCheckboxState,
|
|
480
|
+
selectAllUnselectedItemsInListItems,
|
|
481
|
+
someListItemsAreSelected,
|
|
482
|
+
unselectAllListItems
|
|
859
483
|
};
|
|
860
484
|
};
|
|
861
|
-
/* end multiselect utils */
|
|
862
|
-
/* start a11y utils */
|
|
863
|
-
// called when the state changes:
|
|
864
|
-
// selectedItem, highlightedIndex, inputValue or isOpen.
|
|
865
485
|
function getA11yStatusMessage(options) {
|
|
866
|
-
|
|
867
|
-
_options$selectAllIte = options.selectAllItemIncluded,
|
|
868
|
-
selectAllItemIncluded = _options$selectAllIte === void 0 ? false : _options$selectAllIte,
|
|
869
|
-
resultCount = options.resultCount;
|
|
486
|
+
const { isOpen, selectAllItemIncluded = false, resultCount } = options;
|
|
870
487
|
if (!isOpen) {
|
|
871
|
-
return
|
|
488
|
+
return "";
|
|
872
489
|
}
|
|
873
|
-
|
|
490
|
+
const resultCountWithoutSelectAll = selectAllItemIncluded ? resultCount - 1 : resultCount;
|
|
874
491
|
if (resultCountWithoutSelectAll === 0) {
|
|
875
|
-
return
|
|
492
|
+
return "Ingen resultater";
|
|
876
493
|
}
|
|
877
|
-
return resultCountWithoutSelectAll
|
|
494
|
+
return `${resultCountWithoutSelectAll} resultat${resultCountWithoutSelectAll === 1 ? "" : "er"} tilgjengelig, naviger med pil opp eller ned, velg elementer med Enter.`;
|
|
878
495
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
setLastHighlightedIndex = _useState2[1];
|
|
935
|
-
var inputRef = useRef(null);
|
|
936
|
-
var _useResolvedItems = useResolvedItems(initialItems, debounceTimeout),
|
|
937
|
-
normalizedItems = _useResolvedItems.items,
|
|
938
|
-
resolvedItemsLoading = _useResolvedItems.loading,
|
|
939
|
-
fetchItems = _useResolvedItems.fetchItems;
|
|
940
|
-
var _useState3 = useState(normalizedItems),
|
|
941
|
-
listItems = _useState3[0],
|
|
942
|
-
setListItems = _useState3[1];
|
|
943
|
-
var filterListItems = function filterListItems(_ref2) {
|
|
944
|
-
var inputValue = _ref2.inputValue;
|
|
945
|
-
return setListItems(normalizedItems.filter(function (item) {
|
|
946
|
-
return itemFilter(item, inputValue);
|
|
947
|
-
}));
|
|
948
|
-
};
|
|
949
|
-
var updateListItems = function updateListItems(_ref3) {
|
|
950
|
-
var inputValue = _ref3.inputValue;
|
|
951
|
-
var shouldRefetchItems = isFunctionWithQueryArgument(initialItems);
|
|
952
|
-
if (shouldRefetchItems) fetchItems(inputValue != null ? inputValue : EMPTY_INPUT);
|
|
953
|
-
filterListItems({
|
|
954
|
-
inputValue: inputValue != null ? inputValue : EMPTY_INPUT
|
|
955
|
-
});
|
|
956
|
-
};
|
|
957
|
-
var resetInputState = function resetInputState(_ref4) {
|
|
958
|
-
var changes = _ref4.changes;
|
|
959
|
-
updateListItems({
|
|
960
|
-
inputValue: EMPTY_INPUT
|
|
961
|
-
});
|
|
962
|
-
return _extends({}, changes, {
|
|
963
|
-
inputValue: EMPTY_INPUT
|
|
964
|
-
});
|
|
965
|
-
};
|
|
966
|
-
var inputHasFocus = typeof document !== 'undefined' ? (inputRef == null ? void 0 : inputRef.current) === ((_document = document) == null ? void 0 : _document.activeElement) : false;
|
|
967
|
-
useEffect(function () {
|
|
968
|
-
filterListItems({
|
|
969
|
-
inputValue: inputValue
|
|
970
|
-
});
|
|
971
|
-
}, [normalizedItems]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
972
|
-
useEffect(function () {
|
|
973
|
-
// sync internal state on initial render
|
|
974
|
-
if (selectedItem !== null && !inputHasFocus) {
|
|
975
|
-
setShowSelectedItem(true);
|
|
976
|
-
updateListItems({
|
|
496
|
+
const SearchableDropdown = React.forwardRef(
|
|
497
|
+
({
|
|
498
|
+
ariaLabelChosenSingular,
|
|
499
|
+
ariaLabelCloseList = "Lukk liste med valg",
|
|
500
|
+
ariaLabelOpenList = "Åpne liste med valg",
|
|
501
|
+
ariaLabelSelectedItem,
|
|
502
|
+
className,
|
|
503
|
+
clearable = true,
|
|
504
|
+
debounceTimeout,
|
|
505
|
+
disabled = false,
|
|
506
|
+
disableLabelAnimation = false,
|
|
507
|
+
feedback,
|
|
508
|
+
items: initialItems,
|
|
509
|
+
itemFilter = isFunctionWithQueryArgument(initialItems) ? noFilter : lowerCaseFilterTest,
|
|
510
|
+
label,
|
|
511
|
+
labelClearSelectedItem = "fjern valgt",
|
|
512
|
+
labelTooltip,
|
|
513
|
+
listStyle,
|
|
514
|
+
loading,
|
|
515
|
+
loadingText = "Laster resultater …",
|
|
516
|
+
noMatchesText = "Ingen tilgjengelige valg …",
|
|
517
|
+
onChange = () => void 0,
|
|
518
|
+
placeholder,
|
|
519
|
+
prepend,
|
|
520
|
+
readOnly = false,
|
|
521
|
+
selectedItem: value,
|
|
522
|
+
selectOnBlur = false,
|
|
523
|
+
selectOnTab = false,
|
|
524
|
+
style,
|
|
525
|
+
variant = "info",
|
|
526
|
+
...rest
|
|
527
|
+
}, ref) => {
|
|
528
|
+
const [showSelectedItem, setShowSelectedItem] = useState(value !== null);
|
|
529
|
+
const [lastHighlightedIndex, setLastHighlightedIndex] = useState(0);
|
|
530
|
+
const inputRef = useRef(null);
|
|
531
|
+
const {
|
|
532
|
+
items: normalizedItems,
|
|
533
|
+
loading: resolvedItemsLoading,
|
|
534
|
+
fetchItems
|
|
535
|
+
} = useResolvedItems(initialItems, debounceTimeout);
|
|
536
|
+
const [listItems, setListItems] = useState(normalizedItems);
|
|
537
|
+
const filterListItems = ({ inputValue: inputValue2 }) => setListItems(
|
|
538
|
+
normalizedItems.filter((item) => itemFilter(item, inputValue2))
|
|
539
|
+
);
|
|
540
|
+
const updateListItems = ({ inputValue: inputValue2 }) => {
|
|
541
|
+
const shouldRefetchItems = isFunctionWithQueryArgument(initialItems);
|
|
542
|
+
if (shouldRefetchItems) fetchItems(inputValue2 ?? EMPTY_INPUT);
|
|
543
|
+
filterListItems({ inputValue: inputValue2 ?? EMPTY_INPUT });
|
|
544
|
+
};
|
|
545
|
+
const resetInputState = ({
|
|
546
|
+
changes
|
|
547
|
+
}) => {
|
|
548
|
+
updateListItems({ inputValue: EMPTY_INPUT });
|
|
549
|
+
return {
|
|
550
|
+
...changes,
|
|
977
551
|
inputValue: EMPTY_INPUT
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
const inputHasFocus = typeof document !== "undefined" ? inputRef?.current === document?.activeElement : false;
|
|
555
|
+
useEffect(() => {
|
|
556
|
+
filterListItems({ inputValue });
|
|
557
|
+
}, [normalizedItems]);
|
|
558
|
+
useEffect(() => {
|
|
559
|
+
if (selectedItem !== null && !inputHasFocus) {
|
|
560
|
+
setShowSelectedItem(true);
|
|
561
|
+
updateListItems({ inputValue: EMPTY_INPUT });
|
|
562
|
+
setInputValue(EMPTY_INPUT);
|
|
563
|
+
}
|
|
564
|
+
}, []);
|
|
565
|
+
const stateReducer = useCallback(
|
|
566
|
+
(state, {
|
|
567
|
+
type,
|
|
568
|
+
changes
|
|
569
|
+
}) => {
|
|
570
|
+
if (changes.highlightedIndex !== void 0 && changes?.highlightedIndex >= 0) {
|
|
571
|
+
setLastHighlightedIndex(changes?.highlightedIndex);
|
|
572
|
+
}
|
|
573
|
+
switch (type) {
|
|
574
|
+
// empty input to show selected item and reset dropdown list on item selection
|
|
575
|
+
case useCombobox.stateChangeTypes.ItemClick:
|
|
576
|
+
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
577
|
+
case useCombobox.stateChangeTypes.InputBlur:
|
|
578
|
+
return resetInputState({ changes });
|
|
579
|
+
case useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem:
|
|
580
|
+
if (changes.selectedItem !== null && !inputHasFocus)
|
|
581
|
+
setShowSelectedItem(true);
|
|
582
|
+
return resetInputState({ changes });
|
|
583
|
+
// remove leading whitespace, select element with spacebar on empty input
|
|
584
|
+
case useCombobox.stateChangeTypes.InputChange: {
|
|
585
|
+
const leadingWhitespaceTest = /^\s+/g;
|
|
586
|
+
const isSpacePressedOnEmptyInput = changes.inputValue === " ";
|
|
587
|
+
if (!isSpacePressedOnEmptyInput) setLastHighlightedIndex(0);
|
|
588
|
+
if (changes.inputValue?.match(leadingWhitespaceTest)) {
|
|
589
|
+
const sanitizedInputValue = changes.inputValue.replace(
|
|
590
|
+
leadingWhitespaceTest,
|
|
591
|
+
EMPTY_INPUT
|
|
592
|
+
);
|
|
593
|
+
if (isSpacePressedOnEmptyInput) {
|
|
594
|
+
if (!state.isOpen)
|
|
595
|
+
return {
|
|
596
|
+
...changes,
|
|
597
|
+
inputValue: sanitizedInputValue,
|
|
598
|
+
isOpen: true
|
|
599
|
+
};
|
|
600
|
+
if (changes.highlightedIndex !== void 0) {
|
|
601
|
+
return {
|
|
602
|
+
...changes,
|
|
603
|
+
inputValue: sanitizedInputValue,
|
|
604
|
+
selectedItem: listItems[changes.highlightedIndex]
|
|
605
|
+
};
|
|
606
|
+
}
|
|
1020
607
|
}
|
|
1021
608
|
}
|
|
609
|
+
return { ...changes, highlightedIndex: 0 };
|
|
1022
610
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
});
|
|
611
|
+
default:
|
|
612
|
+
return changes;
|
|
1026
613
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
614
|
+
},
|
|
615
|
+
[fetchItems, filterListItems, inputHasFocus, resetInputState]
|
|
616
|
+
);
|
|
617
|
+
const {
|
|
618
|
+
isOpen,
|
|
619
|
+
getToggleButtonProps,
|
|
620
|
+
getLabelProps,
|
|
621
|
+
getMenuProps,
|
|
622
|
+
getInputProps,
|
|
623
|
+
highlightedIndex,
|
|
624
|
+
getItemProps,
|
|
625
|
+
selectedItem,
|
|
626
|
+
inputValue,
|
|
627
|
+
setInputValue,
|
|
628
|
+
selectItem,
|
|
629
|
+
reset
|
|
630
|
+
} = useCombobox({
|
|
1032
631
|
defaultHighlightedIndex: lastHighlightedIndex,
|
|
1033
632
|
items: listItems,
|
|
1034
|
-
itemToString
|
|
633
|
+
itemToString,
|
|
1035
634
|
selectedItem: value,
|
|
1036
|
-
stateReducer
|
|
1037
|
-
onInputValueChange
|
|
1038
|
-
updateListItems({
|
|
1039
|
-
inputValue: changes.inputValue
|
|
1040
|
-
});
|
|
635
|
+
stateReducer,
|
|
636
|
+
onInputValueChange(changes) {
|
|
637
|
+
updateListItems({ inputValue: changes.inputValue });
|
|
1041
638
|
},
|
|
1042
|
-
onSelectedItemChange:
|
|
1043
|
-
var newSelectedItem = _ref6.selectedItem;
|
|
639
|
+
onSelectedItemChange({ selectedItem: newSelectedItem }) {
|
|
1044
640
|
onChange(newSelectedItem);
|
|
1045
641
|
},
|
|
1046
642
|
// Accessibility
|
|
1047
|
-
getA11yStatusMessage:
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
}));
|
|
1051
|
-
}
|
|
1052
|
-
}),
|
|
1053
|
-
isOpen = _useCombobox.isOpen,
|
|
1054
|
-
getToggleButtonProps = _useCombobox.getToggleButtonProps,
|
|
1055
|
-
getLabelProps = _useCombobox.getLabelProps,
|
|
1056
|
-
getMenuProps = _useCombobox.getMenuProps,
|
|
1057
|
-
getInputProps = _useCombobox.getInputProps,
|
|
1058
|
-
highlightedIndex = _useCombobox.highlightedIndex,
|
|
1059
|
-
getItemProps = _useCombobox.getItemProps,
|
|
1060
|
-
selectedItem = _useCombobox.selectedItem,
|
|
1061
|
-
inputValue = _useCombobox.inputValue,
|
|
1062
|
-
setInputValue = _useCombobox.setInputValue,
|
|
1063
|
-
selectItem = _useCombobox.selectItem,
|
|
1064
|
-
reset = _useCombobox.reset;
|
|
1065
|
-
// calculations for floating-UI popover position
|
|
1066
|
-
var _useFloating = useFloating({
|
|
643
|
+
getA11yStatusMessage: (options) => getA11yStatusMessage({ ...options, resultCount: listItems.length })
|
|
644
|
+
});
|
|
645
|
+
const { refs, floatingStyles, update } = useFloating({
|
|
1067
646
|
open: isOpen,
|
|
1068
|
-
placement:
|
|
1069
|
-
middleware: [
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
elements
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
// Downshift doesn't work correctly when conditionally rendered since props and refs aren't correctly
|
|
1093
|
-
// spread to the component. We therefor use this useEffect to update position. See https://floating-ui.com/docs/autoupdate#usage
|
|
1094
|
-
useEffect(function () {
|
|
1095
|
-
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1096
|
-
return autoUpdate(refs.reference.current, refs.floating.current, update);
|
|
1097
|
-
}
|
|
1098
|
-
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1099
|
-
var handleOnClear = function handleOnClear() {
|
|
1100
|
-
var _inputRef$current;
|
|
1101
|
-
(_inputRef$current = inputRef.current) == null || _inputRef$current.focus();
|
|
1102
|
-
reset();
|
|
1103
|
-
};
|
|
1104
|
-
return React.createElement(BaseFormControl, _extends({
|
|
1105
|
-
className: classNames('eds-dropdown', 'eds-dropdown--searchable', className, {
|
|
1106
|
-
'eds-dropdown--has-tooltip': labelTooltip !== undefined
|
|
1107
|
-
}),
|
|
1108
|
-
disabled: disabled,
|
|
1109
|
-
disableLabelAnimation: disableLabelAnimation,
|
|
1110
|
-
feedback: feedback,
|
|
1111
|
-
isFilled: selectedItem !== null || inputValue !== EMPTY_INPUT,
|
|
1112
|
-
label: label,
|
|
1113
|
-
labelId: getLabelProps().id,
|
|
1114
|
-
labelProps: getLabelProps(),
|
|
1115
|
-
labelTooltip: labelTooltip,
|
|
1116
|
-
onClick: function onClick(e) {
|
|
1117
|
-
if (e.target === e.currentTarget) {
|
|
1118
|
-
var _getInputProps;
|
|
1119
|
-
(_getInputProps = getInputProps()) == null || _getInputProps.onClick == null || _getInputProps.onClick(e);
|
|
1120
|
-
}
|
|
1121
|
-
},
|
|
1122
|
-
prepend: prepend,
|
|
1123
|
-
readOnly: readOnly,
|
|
1124
|
-
ref: refs.setReference,
|
|
1125
|
-
style: style,
|
|
1126
|
-
tabIndex: disabled || readOnly ? -1 : undefined,
|
|
1127
|
-
variant: variant,
|
|
1128
|
-
after: React.createElement(DropdownList, {
|
|
1129
|
-
ariaLabelChosenSingular: ariaLabelChosenSingular,
|
|
1130
|
-
ariaLabelSelectedItem: ariaLabelSelectedItem,
|
|
1131
|
-
floatingStyles: floatingStyles,
|
|
1132
|
-
getItemProps: getItemProps,
|
|
1133
|
-
getMenuProps: getMenuProps,
|
|
1134
|
-
highlightedIndex: highlightedIndex,
|
|
1135
|
-
isOpen: isOpen,
|
|
1136
|
-
listItems: listItems,
|
|
1137
|
-
style: listStyle,
|
|
1138
|
-
setListRef: refs.setFloating,
|
|
1139
|
-
loading: loading != null ? loading : resolvedItemsLoading,
|
|
1140
|
-
loadingText: loadingText,
|
|
1141
|
-
noMatchesText: noMatchesText,
|
|
1142
|
-
selectedItems: selectedItem !== null ? [selectedItem] : [],
|
|
1143
|
-
readOnly: readOnly
|
|
1144
|
-
})
|
|
1145
|
-
}, rest, {
|
|
1146
|
-
// Append is not supported as of now
|
|
1147
|
-
append: undefined
|
|
1148
|
-
}), React.createElement("span", {
|
|
1149
|
-
className: classNames('eds-dropdown--searchable__selected-item', {
|
|
1150
|
-
'eds-dropdown--searchable__selected-item--hidden': !showSelectedItem
|
|
1151
|
-
}),
|
|
1152
|
-
onClick: function onClick(event) {
|
|
1153
|
-
if (!disabled && !readOnly) {
|
|
1154
|
-
var _inputRef$current2, _getInputProps2;
|
|
1155
|
-
(_inputRef$current2 = inputRef.current) == null || _inputRef$current2.focus();
|
|
1156
|
-
(_getInputProps2 = getInputProps()) == null || _getInputProps2.onClick == null || _getInputProps2.onClick(event);
|
|
1157
|
-
}
|
|
1158
|
-
},
|
|
1159
|
-
tabIndex: readOnly ? 0 : -1
|
|
1160
|
-
}, showSelectedItem ? selectedItem == null ? void 0 : selectedItem.label : ''), React.createElement("input", _extends({
|
|
1161
|
-
className: classNames('eds-dropdown__input eds-form-control', {
|
|
1162
|
-
'eds-dropdown__input--hidden': showSelectedItem
|
|
1163
|
-
})
|
|
1164
|
-
}, getInputProps({
|
|
1165
|
-
onKeyDown: function onKeyDown(e) {
|
|
1166
|
-
if (isOpen && e.key === 'Tab') {
|
|
1167
|
-
var highlitedItem = listItems[highlightedIndex];
|
|
1168
|
-
// we don't want to clear selection with tab
|
|
1169
|
-
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
1170
|
-
selectItem(highlitedItem);
|
|
1171
|
-
}
|
|
647
|
+
placement: "bottom-start",
|
|
648
|
+
middleware: [
|
|
649
|
+
offset(space.extraSmall2),
|
|
650
|
+
shift({ padding: space.extraSmall }),
|
|
651
|
+
size({
|
|
652
|
+
apply({ rects, elements, availableHeight }) {
|
|
653
|
+
Object.assign(elements.floating.style, {
|
|
654
|
+
width: `${rects.reference.width}px`,
|
|
655
|
+
// Floating will flip when smaller than 10*16 px
|
|
656
|
+
// and never exceed 20*16 px.
|
|
657
|
+
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
}),
|
|
661
|
+
flip({ fallbackStrategy: "initialPlacement" })
|
|
662
|
+
]
|
|
663
|
+
});
|
|
664
|
+
useEffect(() => {
|
|
665
|
+
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
666
|
+
return autoUpdate(
|
|
667
|
+
refs.reference.current,
|
|
668
|
+
refs.floating.current,
|
|
669
|
+
update
|
|
670
|
+
);
|
|
1172
671
|
}
|
|
1173
|
-
},
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
672
|
+
}, [isOpen, refs.reference, refs.floating, update]);
|
|
673
|
+
const handleOnClear = () => {
|
|
674
|
+
inputRef.current?.focus();
|
|
675
|
+
reset();
|
|
676
|
+
};
|
|
677
|
+
return /* @__PURE__ */ jsxs(
|
|
678
|
+
BaseFormControl,
|
|
679
|
+
{
|
|
680
|
+
className: classNames(
|
|
681
|
+
"eds-dropdown",
|
|
682
|
+
"eds-dropdown--searchable",
|
|
683
|
+
className,
|
|
684
|
+
{ "eds-dropdown--has-tooltip": labelTooltip !== void 0 }
|
|
685
|
+
),
|
|
686
|
+
disabled,
|
|
687
|
+
disableLabelAnimation,
|
|
688
|
+
feedback,
|
|
689
|
+
isFilled: selectedItem !== null || inputValue !== EMPTY_INPUT,
|
|
690
|
+
label,
|
|
691
|
+
labelId: getLabelProps().id,
|
|
692
|
+
labelProps: getLabelProps(),
|
|
693
|
+
labelTooltip,
|
|
694
|
+
onClick: (e) => {
|
|
695
|
+
if (e.target === e.currentTarget) {
|
|
696
|
+
getInputProps()?.onClick?.(e);
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
prepend,
|
|
700
|
+
readOnly,
|
|
701
|
+
ref: refs.setReference,
|
|
702
|
+
style,
|
|
703
|
+
tabIndex: disabled || readOnly ? -1 : void 0,
|
|
704
|
+
variant,
|
|
705
|
+
after: /* @__PURE__ */ jsx(
|
|
706
|
+
DropdownList,
|
|
707
|
+
{
|
|
708
|
+
ariaLabelChosenSingular,
|
|
709
|
+
ariaLabelSelectedItem,
|
|
710
|
+
floatingStyles,
|
|
711
|
+
getItemProps,
|
|
712
|
+
getMenuProps,
|
|
713
|
+
highlightedIndex,
|
|
714
|
+
isOpen,
|
|
715
|
+
listItems,
|
|
716
|
+
style: listStyle,
|
|
717
|
+
setListRef: refs.setFloating,
|
|
718
|
+
loading: loading ?? resolvedItemsLoading,
|
|
719
|
+
loadingText,
|
|
720
|
+
noMatchesText,
|
|
721
|
+
selectedItems: selectedItem !== null ? [selectedItem] : [],
|
|
722
|
+
readOnly
|
|
723
|
+
}
|
|
724
|
+
),
|
|
725
|
+
...rest,
|
|
726
|
+
append: void 0,
|
|
727
|
+
children: [
|
|
728
|
+
/* @__PURE__ */ jsx(
|
|
729
|
+
"span",
|
|
730
|
+
{
|
|
731
|
+
className: classNames("eds-dropdown--searchable__selected-item", {
|
|
732
|
+
"eds-dropdown--searchable__selected-item--hidden": !showSelectedItem
|
|
733
|
+
}),
|
|
734
|
+
onClick: (event) => {
|
|
735
|
+
if (!disabled && !readOnly) {
|
|
736
|
+
inputRef.current?.focus();
|
|
737
|
+
getInputProps()?.onClick?.(event);
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
tabIndex: readOnly ? 0 : -1,
|
|
741
|
+
children: showSelectedItem ? selectedItem?.label : ""
|
|
742
|
+
}
|
|
743
|
+
),
|
|
744
|
+
/* @__PURE__ */ jsx(
|
|
745
|
+
"input",
|
|
746
|
+
{
|
|
747
|
+
className: classNames("eds-dropdown__input eds-form-control", {
|
|
748
|
+
"eds-dropdown__input--hidden": showSelectedItem
|
|
749
|
+
}),
|
|
750
|
+
...getInputProps({
|
|
751
|
+
onKeyDown(e) {
|
|
752
|
+
if (isOpen && e.key === "Tab") {
|
|
753
|
+
const highlitedItem = listItems[highlightedIndex];
|
|
754
|
+
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
755
|
+
selectItem(highlitedItem);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
onBlur() {
|
|
760
|
+
if (selectedItem !== null) setShowSelectedItem(true);
|
|
761
|
+
},
|
|
762
|
+
onFocus() {
|
|
763
|
+
if (!readOnly) {
|
|
764
|
+
setShowSelectedItem(false);
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
disabled,
|
|
768
|
+
readOnly,
|
|
769
|
+
placeholder: selectedItem?.label ?? placeholder,
|
|
770
|
+
tabIndex: disabled || readOnly ? -1 : void 0,
|
|
771
|
+
ref: mergeRefs(inputRef, ref)
|
|
772
|
+
})
|
|
773
|
+
}
|
|
774
|
+
),
|
|
775
|
+
/* @__PURE__ */ jsx(
|
|
776
|
+
DropdownFieldAppendix,
|
|
777
|
+
{
|
|
778
|
+
...getToggleButtonProps({
|
|
779
|
+
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
780
|
+
}),
|
|
781
|
+
ariaLabelCloseList,
|
|
782
|
+
ariaLabelOpenList,
|
|
783
|
+
clearable,
|
|
784
|
+
disabled: disabled || readOnly,
|
|
785
|
+
onClear: handleOnClear,
|
|
786
|
+
focusable: false,
|
|
787
|
+
labelClearSelected: labelClearSelectedItem,
|
|
788
|
+
isOpen,
|
|
789
|
+
itemIsSelected: selectedItem !== null,
|
|
790
|
+
loadingText,
|
|
791
|
+
loading: loading ?? resolvedItemsLoading
|
|
792
|
+
}
|
|
793
|
+
)
|
|
794
|
+
]
|
|
1180
795
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
} : _ref$onChange,
|
|
1241
|
-
placeholder = _ref.placeholder,
|
|
1242
|
-
_ref$readOnly = _ref.readOnly,
|
|
1243
|
-
readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
|
|
1244
|
-
_ref$selectedItems = _ref.selectedItems,
|
|
1245
|
-
selectedItems = _ref$selectedItems === void 0 ? [] : _ref$selectedItems,
|
|
1246
|
-
_ref$selectOnTab = _ref.selectOnTab,
|
|
1247
|
-
selectOnTab = _ref$selectOnTab === void 0 ? false : _ref$selectOnTab,
|
|
1248
|
-
style = _ref.style,
|
|
1249
|
-
_ref$variant = _ref.variant,
|
|
1250
|
-
variant = _ref$variant === void 0 ? 'information' : _ref$variant,
|
|
1251
|
-
ariaLabelChosenSingular = _ref.ariaLabelChosenSingular,
|
|
1252
|
-
_ref$ariaLabelChosenP = _ref.ariaLabelChosenPlural,
|
|
1253
|
-
ariaLabelChosenPlural = _ref$ariaLabelChosenP === void 0 ? 'valgte' : _ref$ariaLabelChosenP,
|
|
1254
|
-
_ref$ariaLabelCloseLi = _ref.ariaLabelCloseList,
|
|
1255
|
-
ariaLabelCloseList = _ref$ariaLabelCloseLi === void 0 ? 'Lukk liste med valg' : _ref$ariaLabelCloseLi,
|
|
1256
|
-
_ref$ariaLabelJumpToI = _ref.ariaLabelJumpToInput,
|
|
1257
|
-
ariaLabelJumpToInput = _ref$ariaLabelJumpToI === void 0 ? selectedItems.length + " valgte elementer, trykk for \xE5 hoppe til tekstfeltet" : _ref$ariaLabelJumpToI,
|
|
1258
|
-
_ref$ariaLabelOpenLis = _ref.ariaLabelOpenList,
|
|
1259
|
-
ariaLabelOpenList = _ref$ariaLabelOpenLis === void 0 ? 'Åpne liste med valg' : _ref$ariaLabelOpenLis,
|
|
1260
|
-
_ref$ariaLabelRemoveS = _ref.ariaLabelRemoveSelected,
|
|
1261
|
-
ariaLabelRemoveSelected = _ref$ariaLabelRemoveS === void 0 ? 'trykk for å fjerne valg' : _ref$ariaLabelRemoveS,
|
|
1262
|
-
ariaLabelSelectedItem = _ref.ariaLabelSelectedItem,
|
|
1263
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
|
|
1264
|
-
var _React$useState = React.useState(0),
|
|
1265
|
-
lastHighlightedIndex = _React$useState[0],
|
|
1266
|
-
setLastHighlightedIndex = _React$useState[1];
|
|
1267
|
-
var inputRef = useRef(null);
|
|
1268
|
-
useEffect(function () {
|
|
1269
|
-
//@ts-expect-error this is done to aid developers debug wrong prop usage
|
|
1270
|
-
if (rest.selectedItem !== undefined) console.warn("Incorrect 'selectedItem' prop found, did you mean to use 'selectedItems?");
|
|
1271
|
-
//@ts-expect-error selectedItem should not actually exist in rest
|
|
1272
|
-
}, [rest.selectedItem]);
|
|
1273
|
-
var _useResolvedItems = useResolvedItems(initialItems, debounceTimeout),
|
|
1274
|
-
normalizedItems = _useResolvedItems.items,
|
|
1275
|
-
resolvedItemsLoading = _useResolvedItems.loading,
|
|
1276
|
-
fetchItems = _useResolvedItems.fetchItems;
|
|
1277
|
-
var isAllNonAsyncItemsSelected = typeof initialItems !== 'function' && selectedItems.length === normalizedItems.length;
|
|
1278
|
-
// special 'item' used as Select All entry in the dropdown list
|
|
1279
|
-
var selectAll = {
|
|
1280
|
-
value: useRandomId('select-all'),
|
|
1281
|
-
label: labelSelectAll
|
|
1282
|
-
};
|
|
1283
|
-
// special 'item' used as a replacement selected item tag for when
|
|
1284
|
-
// there are more selected element than maxChips
|
|
1285
|
-
var summarySelectedItems = React.useMemo(function () {
|
|
1286
|
-
return {
|
|
1287
|
-
value: EMPTY_INPUT,
|
|
1288
|
-
label: isAllNonAsyncItemsSelected ? labelAllItemsSelected : selectedItems.length + ' ' + ariaLabelChosenPlural
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
);
|
|
799
|
+
const MultiSelect = React.forwardRef(
|
|
800
|
+
({
|
|
801
|
+
className,
|
|
802
|
+
clearable = true,
|
|
803
|
+
clearInputOnSelect = false,
|
|
804
|
+
debounceTimeout,
|
|
805
|
+
disabled = false,
|
|
806
|
+
disableLabelAnimation,
|
|
807
|
+
feedback,
|
|
808
|
+
hideSelectAll = false,
|
|
809
|
+
items: initialItems,
|
|
810
|
+
itemFilter = isFunctionWithQueryArgument(initialItems) ? noFilter : lowerCaseFilterTest,
|
|
811
|
+
label,
|
|
812
|
+
labelAllItemsSelected = "Alle valgt",
|
|
813
|
+
labelClearAllItems = "Fjern valgte",
|
|
814
|
+
labelSelectAll = "Velg alle",
|
|
815
|
+
labelTooltip,
|
|
816
|
+
listStyle,
|
|
817
|
+
loading,
|
|
818
|
+
loadingText = "Laster resultater …",
|
|
819
|
+
maxChips = 10,
|
|
820
|
+
noMatchesText,
|
|
821
|
+
onChange = () => void 0,
|
|
822
|
+
placeholder,
|
|
823
|
+
readOnly = false,
|
|
824
|
+
selectedItems = [],
|
|
825
|
+
selectOnBlur = false,
|
|
826
|
+
selectOnTab = false,
|
|
827
|
+
style,
|
|
828
|
+
variant = "information",
|
|
829
|
+
ariaLabelChosenSingular,
|
|
830
|
+
ariaLabelChosenPlural = "valgte",
|
|
831
|
+
ariaLabelCloseList = "Lukk liste med valg",
|
|
832
|
+
ariaLabelJumpToInput = `${selectedItems.length} valgte elementer, trykk for å hoppe til tekstfeltet`,
|
|
833
|
+
ariaLabelOpenList = "Åpne liste med valg",
|
|
834
|
+
ariaLabelRemoveSelected = "trykk for å fjerne valg",
|
|
835
|
+
ariaLabelSelectedItem,
|
|
836
|
+
...rest
|
|
837
|
+
}, ref) => {
|
|
838
|
+
const [lastHighlightedIndex, setLastHighlightedIndex] = React.useState(0);
|
|
839
|
+
const inputRef = useRef(null);
|
|
840
|
+
useEffect(() => {
|
|
841
|
+
if (rest.selectedItem !== void 0)
|
|
842
|
+
console.warn(
|
|
843
|
+
"Incorrect 'selectedItem' prop found, did you mean to use 'selectedItems?"
|
|
844
|
+
);
|
|
845
|
+
}, [rest.selectedItem]);
|
|
846
|
+
const {
|
|
847
|
+
items: normalizedItems,
|
|
848
|
+
loading: resolvedItemsLoading,
|
|
849
|
+
fetchItems
|
|
850
|
+
} = useResolvedItems(initialItems, debounceTimeout);
|
|
851
|
+
const isAllNonAsyncItemsSelected = typeof initialItems !== "function" && selectedItems.length === normalizedItems.length;
|
|
852
|
+
const selectAll = {
|
|
853
|
+
value: useRandomId("select-all"),
|
|
854
|
+
label: labelSelectAll
|
|
1289
855
|
};
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
})
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
856
|
+
const summarySelectedItems = React.useMemo(
|
|
857
|
+
() => ({
|
|
858
|
+
value: EMPTY_INPUT,
|
|
859
|
+
label: isAllNonAsyncItemsSelected ? labelAllItemsSelected : selectedItems.length + " " + ariaLabelChosenPlural
|
|
860
|
+
}),
|
|
861
|
+
[
|
|
862
|
+
isAllNonAsyncItemsSelected,
|
|
863
|
+
selectedItems,
|
|
864
|
+
labelAllItemsSelected,
|
|
865
|
+
ariaLabelChosenPlural
|
|
866
|
+
]
|
|
867
|
+
);
|
|
868
|
+
const [listItems, setListItems] = useState([
|
|
869
|
+
...!hideSelectAll ? [selectAll] : [],
|
|
870
|
+
...normalizedItems
|
|
871
|
+
]);
|
|
872
|
+
const filterListItems = ({ inputValue: inputValue2 }) => setListItems([
|
|
873
|
+
...!hideSelectAll ? [selectAll] : [],
|
|
874
|
+
...normalizedItems.filter((item) => itemFilter(item, inputValue2))
|
|
875
|
+
]);
|
|
876
|
+
const updateListItems = ({ inputValue: inputValue2 }) => {
|
|
877
|
+
const shouldRefetchItems = isFunctionWithQueryArgument(initialItems);
|
|
878
|
+
if (shouldRefetchItems) fetchItems(inputValue2 ?? EMPTY_INPUT);
|
|
879
|
+
filterListItems({ inputValue: inputValue2 ?? EMPTY_INPUT });
|
|
880
|
+
};
|
|
881
|
+
React.useEffect(() => {
|
|
882
|
+
filterListItems({ inputValue });
|
|
883
|
+
}, [normalizedItems]);
|
|
884
|
+
const {
|
|
885
|
+
hasSelectedItems,
|
|
886
|
+
handleListItemClicked,
|
|
887
|
+
selectAllCheckboxState,
|
|
888
|
+
clickedItemIsInSelectedItems,
|
|
889
|
+
clickedItemIsSelectAll
|
|
890
|
+
} = useMultiselectUtils({
|
|
891
|
+
listItems,
|
|
892
|
+
selectAll,
|
|
893
|
+
selectedItems
|
|
1311
894
|
});
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
selectAllCheckboxState = _useMultiselectUtils.selectAllCheckboxState,
|
|
1321
|
-
clickedItemIsInSelectedItems = _useMultiselectUtils.clickedItemIsInSelectedItems,
|
|
1322
|
-
clickedItemIsSelectAll = _useMultiselectUtils.clickedItemIsSelectAll;
|
|
1323
|
-
var _useMultipleSelection = useMultipleSelection({
|
|
1324
|
-
selectedItems: selectedItems,
|
|
895
|
+
const {
|
|
896
|
+
getSelectedItemProps,
|
|
897
|
+
getDropdownProps,
|
|
898
|
+
reset,
|
|
899
|
+
removeSelectedItem,
|
|
900
|
+
setSelectedItems
|
|
901
|
+
} = useMultipleSelection({
|
|
902
|
+
selectedItems,
|
|
1325
903
|
// @ts-expect-error prop missing from library types
|
|
1326
|
-
itemToString
|
|
1327
|
-
itemToKey
|
|
1328
|
-
onSelectedItemsChange:
|
|
1329
|
-
var newSelectedItems = _ref4.selectedItems;
|
|
904
|
+
itemToString,
|
|
905
|
+
itemToKey,
|
|
906
|
+
onSelectedItemsChange({ selectedItems: newSelectedItems }) {
|
|
1330
907
|
onChange(newSelectedItems);
|
|
1331
908
|
}
|
|
1332
|
-
})
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
type = _ref5.type;
|
|
1341
|
-
if (changes.highlightedIndex !== undefined && (changes == null ? void 0 : changes.highlightedIndex) >= 0) {
|
|
1342
|
-
setLastHighlightedIndex(changes == null ? void 0 : changes.highlightedIndex);
|
|
1343
|
-
}
|
|
1344
|
-
switch (type) {
|
|
1345
|
-
// reset input value when leaving input field
|
|
1346
|
-
case useCombobox.stateChangeTypes.InputBlur:
|
|
1347
|
-
return _extends({}, changes, {
|
|
1348
|
-
inputValue: EMPTY_INPUT
|
|
1349
|
-
});
|
|
1350
|
-
// keep menu open and edit input value on item selection
|
|
1351
|
-
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
1352
|
-
case useCombobox.stateChangeTypes.ItemClick:
|
|
1353
|
-
{
|
|
1354
|
-
var _inputRef$current$val, _inputRef$current;
|
|
1355
|
-
return _extends({}, changes, {
|
|
1356
|
-
isOpen: true,
|
|
1357
|
-
inputValue: clearInputOnSelect ? EMPTY_INPUT : (_inputRef$current$val = inputRef == null || (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.value) != null ? _inputRef$current$val : EMPTY_INPUT
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
// edit input value when selected items is updated outside component
|
|
1361
|
-
case useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem:
|
|
1362
|
-
{
|
|
1363
|
-
var _inputRef$current$val2, _inputRef$current2;
|
|
1364
|
-
return _extends({}, changes, {
|
|
1365
|
-
inputValue: (_inputRef$current$val2 = inputRef == null || (_inputRef$current2 = inputRef.current) == null ? void 0 : _inputRef$current2.value) != null ? _inputRef$current$val2 : EMPTY_INPUT
|
|
1366
|
-
});
|
|
909
|
+
});
|
|
910
|
+
const stateReducer = React.useCallback(
|
|
911
|
+
(state, {
|
|
912
|
+
changes,
|
|
913
|
+
type
|
|
914
|
+
}) => {
|
|
915
|
+
if (changes.highlightedIndex !== void 0 && changes?.highlightedIndex >= 0) {
|
|
916
|
+
setLastHighlightedIndex(changes?.highlightedIndex);
|
|
1367
917
|
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
918
|
+
switch (type) {
|
|
919
|
+
// reset input value when leaving input field
|
|
920
|
+
case useCombobox.stateChangeTypes.InputBlur:
|
|
921
|
+
return {
|
|
922
|
+
...changes,
|
|
923
|
+
inputValue: EMPTY_INPUT
|
|
924
|
+
};
|
|
925
|
+
// keep menu open and edit input value on item selection
|
|
926
|
+
case useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
927
|
+
case useCombobox.stateChangeTypes.ItemClick: {
|
|
928
|
+
return {
|
|
929
|
+
...changes,
|
|
930
|
+
isOpen: true,
|
|
931
|
+
inputValue: clearInputOnSelect ? EMPTY_INPUT : inputRef?.current?.value ?? EMPTY_INPUT
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
// edit input value when selected items is updated outside component
|
|
935
|
+
case useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem: {
|
|
936
|
+
return {
|
|
937
|
+
...changes,
|
|
938
|
+
inputValue: inputRef?.current?.value ?? EMPTY_INPUT
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
// remove leading whitespace, select item with spacebar if input is empty and filter list items
|
|
942
|
+
case useCombobox.stateChangeTypes.InputChange: {
|
|
943
|
+
const leadingWhitespaceTest = /^\s+/g;
|
|
944
|
+
const isSpacePressedOnEmptyInput = changes.inputValue === " ";
|
|
945
|
+
if (changes.inputValue?.match(leadingWhitespaceTest)) {
|
|
946
|
+
const sanitizedInputValue = changes.inputValue.replace(
|
|
947
|
+
leadingWhitespaceTest,
|
|
948
|
+
EMPTY_INPUT
|
|
949
|
+
);
|
|
950
|
+
if (isSpacePressedOnEmptyInput) {
|
|
951
|
+
if (!state.isOpen)
|
|
952
|
+
return {
|
|
953
|
+
...changes,
|
|
954
|
+
inputValue: sanitizedInputValue,
|
|
955
|
+
isOpen: true
|
|
956
|
+
};
|
|
957
|
+
if (changes.highlightedIndex !== void 0) {
|
|
958
|
+
return {
|
|
959
|
+
...changes,
|
|
960
|
+
inputValue: sanitizedInputValue,
|
|
961
|
+
selectedItem: listItems[changes.highlightedIndex]
|
|
962
|
+
};
|
|
963
|
+
}
|
|
1386
964
|
}
|
|
1387
965
|
}
|
|
966
|
+
return changes;
|
|
1388
967
|
}
|
|
1389
|
-
|
|
968
|
+
default:
|
|
969
|
+
return changes;
|
|
1390
970
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
971
|
+
},
|
|
972
|
+
[hideSelectAll, normalizedItems, filterListItems, initialItems]
|
|
973
|
+
);
|
|
974
|
+
const {
|
|
975
|
+
getInputProps,
|
|
976
|
+
getItemProps,
|
|
977
|
+
getLabelProps,
|
|
978
|
+
getMenuProps,
|
|
979
|
+
getToggleButtonProps,
|
|
980
|
+
highlightedIndex,
|
|
981
|
+
setHighlightedIndex,
|
|
982
|
+
inputValue,
|
|
983
|
+
isOpen,
|
|
984
|
+
setInputValue
|
|
985
|
+
} = useCombobox({
|
|
1396
986
|
defaultHighlightedIndex: lastHighlightedIndex,
|
|
1397
987
|
// after selection, highlight previously selected item.
|
|
1398
988
|
items: listItems,
|
|
1399
|
-
itemToString
|
|
989
|
+
itemToString,
|
|
1400
990
|
selectedItem: null,
|
|
1401
|
-
stateReducer
|
|
1402
|
-
onInputValueChange
|
|
1403
|
-
updateListItems({
|
|
1404
|
-
inputValue: changes.inputValue
|
|
1405
|
-
});
|
|
1406
|
-
// set highlighted item to first item after search
|
|
991
|
+
stateReducer,
|
|
992
|
+
onInputValueChange(changes) {
|
|
993
|
+
updateListItems({ inputValue: changes.inputValue });
|
|
1407
994
|
setHighlightedIndex(hideSelectAll ? 0 : 1);
|
|
1408
995
|
setLastHighlightedIndex(hideSelectAll ? 0 : 1);
|
|
1409
996
|
},
|
|
1410
|
-
onSelectedItemChange:
|
|
1411
|
-
var clickedItem = _ref6.selectedItem;
|
|
1412
|
-
// clickedItem means item chosen either via mouse or keyboard
|
|
997
|
+
onSelectedItemChange({ selectedItem: clickedItem }) {
|
|
1413
998
|
if (!clickedItem) return;
|
|
1414
999
|
handleListItemClicked({
|
|
1415
|
-
clickedItem
|
|
1000
|
+
clickedItem,
|
|
1416
1001
|
onChange: setSelectedItems
|
|
1417
1002
|
});
|
|
1418
1003
|
},
|
|
1419
1004
|
// Accessibility
|
|
1420
|
-
getA11yStatusMessage:
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
getItemProps = _useCombobox.getItemProps,
|
|
1429
|
-
getLabelProps = _useCombobox.getLabelProps,
|
|
1430
|
-
getMenuProps = _useCombobox.getMenuProps,
|
|
1431
|
-
getToggleButtonProps = _useCombobox.getToggleButtonProps,
|
|
1432
|
-
highlightedIndex = _useCombobox.highlightedIndex,
|
|
1433
|
-
setHighlightedIndex = _useCombobox.setHighlightedIndex,
|
|
1434
|
-
inputValue = _useCombobox.inputValue,
|
|
1435
|
-
isOpen = _useCombobox.isOpen,
|
|
1436
|
-
setInputValue = _useCombobox.setInputValue;
|
|
1437
|
-
// calculations for floating-UI popover position
|
|
1438
|
-
var _useFloating = useFloating({
|
|
1005
|
+
getA11yStatusMessage: (options) => getA11yStatusMessage({
|
|
1006
|
+
...options,
|
|
1007
|
+
selectAllItemIncluded: !hideSelectAll,
|
|
1008
|
+
resultCount: listItems.length
|
|
1009
|
+
}),
|
|
1010
|
+
...rest
|
|
1011
|
+
});
|
|
1012
|
+
const { refs, floatingStyles, update } = useFloating({
|
|
1439
1013
|
open: isOpen,
|
|
1440
|
-
placement:
|
|
1441
|
-
middleware: [
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
elements
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
fallbackStrategy: 'initialPlacement'
|
|
1457
|
-
})]
|
|
1458
|
-
}),
|
|
1459
|
-
refs = _useFloating.refs,
|
|
1460
|
-
floatingStyles = _useFloating.floatingStyles,
|
|
1461
|
-
update = _useFloating.update;
|
|
1462
|
-
// Update floating-ui position on scroll etc. Floating-ui's autoupdate is usually used inside
|
|
1463
|
-
// the useFloating hook but this requires the floating element to be conditionally rendered.
|
|
1464
|
-
// Downshift doesn't work correctly when conditionally rendered since props and refs aren't correctly
|
|
1465
|
-
// spread to the component. We therefor use this useEffect to update position. See https://floating-ui.com/docs/autoupdate#usage
|
|
1466
|
-
useEffect(function () {
|
|
1467
|
-
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1468
|
-
return autoUpdate(refs.reference.current, refs.floating.current, update);
|
|
1469
|
-
}
|
|
1470
|
-
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1471
|
-
var handleOnClear = function handleOnClear() {
|
|
1472
|
-
var _inputRef$current3;
|
|
1473
|
-
(_inputRef$current3 = inputRef.current) == null || _inputRef$current3.focus();
|
|
1474
|
-
reset();
|
|
1475
|
-
};
|
|
1476
|
-
return React.createElement(BaseFormControl, _extends({
|
|
1477
|
-
className: classNames('eds-dropdown', 'eds-dropdown--multiselect', className, {
|
|
1478
|
-
'eds-dropdown--has-tooltip': labelTooltip !== undefined
|
|
1479
|
-
}),
|
|
1480
|
-
disabled: disabled,
|
|
1481
|
-
disableLabelAnimation: disableLabelAnimation,
|
|
1482
|
-
feedback: feedback,
|
|
1483
|
-
isFilled: hasSelectedItems || inputValue !== EMPTY_INPUT,
|
|
1484
|
-
label: label,
|
|
1485
|
-
labelId: getLabelProps().id,
|
|
1486
|
-
labelProps: getLabelProps(),
|
|
1487
|
-
labelTooltip: labelTooltip,
|
|
1488
|
-
onBlur: function onBlur() {
|
|
1489
|
-
return setInputValue('');
|
|
1490
|
-
},
|
|
1491
|
-
onClick: function onClick(e) {
|
|
1492
|
-
if (e.target === e.currentTarget) {
|
|
1493
|
-
var _getInputProps;
|
|
1494
|
-
(_getInputProps = getInputProps()) == null || _getInputProps.onClick == null || _getInputProps.onClick(e);
|
|
1495
|
-
}
|
|
1496
|
-
},
|
|
1497
|
-
readOnly: readOnly,
|
|
1498
|
-
ref: refs.setReference,
|
|
1499
|
-
style: style,
|
|
1500
|
-
variant: variant,
|
|
1501
|
-
after: React.createElement(DropdownList, {
|
|
1502
|
-
ariaLabelChosenSingular: ariaLabelChosenSingular,
|
|
1503
|
-
ariaLabelSelectedItem: ariaLabelSelectedItem,
|
|
1504
|
-
floatingStyles: floatingStyles,
|
|
1505
|
-
getItemProps: getItemProps,
|
|
1506
|
-
getMenuProps: getMenuProps,
|
|
1507
|
-
highlightedIndex: highlightedIndex,
|
|
1508
|
-
isOpen: isOpen,
|
|
1509
|
-
listItems: listItems,
|
|
1510
|
-
style: listStyle,
|
|
1511
|
-
setListRef: refs.setFloating,
|
|
1512
|
-
loading: loading != null ? loading : resolvedItemsLoading,
|
|
1513
|
-
loadingText: loadingText,
|
|
1514
|
-
noMatchesText: noMatchesText,
|
|
1515
|
-
selectAllCheckboxState: selectAllCheckboxState,
|
|
1516
|
-
selectAllItem: selectAll,
|
|
1517
|
-
selectedItems: selectedItems,
|
|
1518
|
-
readOnly: readOnly
|
|
1519
|
-
})
|
|
1520
|
-
}, rest), React.createElement("div", {
|
|
1521
|
-
className: classNames('eds-dropdown--multiselect__selected-items-and-input', {
|
|
1522
|
-
'eds-dropdown--multiselect__selected-items-and-input--filled': hasSelectedItems
|
|
1523
|
-
})
|
|
1524
|
-
}, selectedItems.length > 1 ? React.createElement(VisuallyHidden, {
|
|
1525
|
-
onClick: (_inputRef$current4 = inputRef.current) == null ? void 0 : _inputRef$current4.focus
|
|
1526
|
-
}, ariaLabelJumpToInput) : null, selectedItems.length <= maxChips ? selectedItems.map(function (selectedItem, index) {
|
|
1527
|
-
return React.createElement(SelectedItemTag, {
|
|
1528
|
-
ariaLabelChosen: ariaLabelChosenSingular,
|
|
1529
|
-
ariaLabelRemoveSelected: ariaLabelRemoveSelected,
|
|
1530
|
-
disabled: disabled,
|
|
1531
|
-
getSelectedItemProps: getSelectedItemProps,
|
|
1532
|
-
index: index,
|
|
1533
|
-
key: (selectedItem == null ? void 0 : selectedItem.label) + (typeof (selectedItem == null ? void 0 : selectedItem.value) === 'string' ? selectedItem.value : ''),
|
|
1534
|
-
readOnly: readOnly,
|
|
1535
|
-
removeSelectedItem: function removeSelectedItem() {
|
|
1536
|
-
var _inputRef$current5;
|
|
1537
|
-
_removeSelectedItem(selectedItem);
|
|
1538
|
-
inputRef == null || (_inputRef$current5 = inputRef.current) == null || _inputRef$current5.focus();
|
|
1539
|
-
},
|
|
1540
|
-
selectedItem: selectedItem
|
|
1014
|
+
placement: "bottom-start",
|
|
1015
|
+
middleware: [
|
|
1016
|
+
offset(space.extraSmall2),
|
|
1017
|
+
shift({ padding: space.extraSmall }),
|
|
1018
|
+
size({
|
|
1019
|
+
apply({ rects, elements, availableHeight }) {
|
|
1020
|
+
Object.assign(elements.floating.style, {
|
|
1021
|
+
width: `${rects.reference.width}px`,
|
|
1022
|
+
// Floating will flip when smaller than 10*16 px
|
|
1023
|
+
// and never exceed 20*16 px.
|
|
1024
|
+
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
}),
|
|
1028
|
+
flip({ fallbackStrategy: "initialPlacement" })
|
|
1029
|
+
]
|
|
1541
1030
|
});
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
}), React.createElement("input", _extends({}, getInputProps(_extends({
|
|
1550
|
-
onKeyDown: function onKeyDown(e) {
|
|
1551
|
-
if (selectOnTab && isOpen && e.key === 'Tab') {
|
|
1552
|
-
var highlitedItem = listItems[highlightedIndex];
|
|
1553
|
-
if (!highlitedItem) return;
|
|
1554
|
-
// Skip tab selection for select all or if item already is selected
|
|
1555
|
-
var shouldSkipTabSelection = clickedItemIsSelectAll(highlitedItem) || !clickedItemIsSelectAll(highlitedItem) && clickedItemIsInSelectedItems(highlitedItem);
|
|
1556
|
-
if (shouldSkipTabSelection) return;
|
|
1557
|
-
handleListItemClicked({
|
|
1558
|
-
clickedItem: highlitedItem,
|
|
1559
|
-
onChange: setSelectedItems
|
|
1560
|
-
});
|
|
1031
|
+
useEffect(() => {
|
|
1032
|
+
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1033
|
+
return autoUpdate(
|
|
1034
|
+
refs.reference.current,
|
|
1035
|
+
refs.floating.current,
|
|
1036
|
+
update
|
|
1037
|
+
);
|
|
1561
1038
|
}
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1039
|
+
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1040
|
+
const handleOnClear = () => {
|
|
1041
|
+
inputRef.current?.focus();
|
|
1042
|
+
reset();
|
|
1043
|
+
};
|
|
1044
|
+
return /* @__PURE__ */ jsxs(
|
|
1045
|
+
BaseFormControl,
|
|
1046
|
+
{
|
|
1047
|
+
className: classNames(
|
|
1048
|
+
"eds-dropdown",
|
|
1049
|
+
"eds-dropdown--multiselect",
|
|
1050
|
+
className,
|
|
1051
|
+
{ "eds-dropdown--has-tooltip": labelTooltip !== void 0 }
|
|
1052
|
+
),
|
|
1053
|
+
disabled,
|
|
1054
|
+
disableLabelAnimation,
|
|
1055
|
+
feedback,
|
|
1056
|
+
isFilled: hasSelectedItems || inputValue !== EMPTY_INPUT,
|
|
1057
|
+
label,
|
|
1058
|
+
labelId: getLabelProps().id,
|
|
1059
|
+
labelProps: getLabelProps(),
|
|
1060
|
+
labelTooltip,
|
|
1061
|
+
onBlur: () => setInputValue(""),
|
|
1062
|
+
onClick: (e) => {
|
|
1063
|
+
if (e.target === e.currentTarget) {
|
|
1064
|
+
getInputProps()?.onClick?.(e);
|
|
1065
|
+
}
|
|
1066
|
+
},
|
|
1067
|
+
readOnly,
|
|
1068
|
+
ref: refs.setReference,
|
|
1069
|
+
style,
|
|
1070
|
+
variant,
|
|
1071
|
+
after: /* @__PURE__ */ jsx(
|
|
1072
|
+
DropdownList,
|
|
1073
|
+
{
|
|
1074
|
+
ariaLabelChosenSingular,
|
|
1075
|
+
ariaLabelSelectedItem,
|
|
1076
|
+
floatingStyles,
|
|
1077
|
+
getItemProps,
|
|
1078
|
+
getMenuProps,
|
|
1079
|
+
highlightedIndex,
|
|
1080
|
+
isOpen,
|
|
1081
|
+
listItems,
|
|
1082
|
+
style: listStyle,
|
|
1083
|
+
setListRef: refs.setFloating,
|
|
1084
|
+
loading: loading ?? resolvedItemsLoading,
|
|
1085
|
+
loadingText,
|
|
1086
|
+
noMatchesText,
|
|
1087
|
+
selectAllCheckboxState,
|
|
1088
|
+
selectAllItem: selectAll,
|
|
1089
|
+
selectedItems,
|
|
1090
|
+
readOnly
|
|
1091
|
+
}
|
|
1092
|
+
),
|
|
1093
|
+
...rest,
|
|
1094
|
+
children: [
|
|
1095
|
+
/* @__PURE__ */ jsxs(
|
|
1096
|
+
"div",
|
|
1097
|
+
{
|
|
1098
|
+
className: classNames(
|
|
1099
|
+
"eds-dropdown--multiselect__selected-items-and-input",
|
|
1100
|
+
{
|
|
1101
|
+
"eds-dropdown--multiselect__selected-items-and-input--filled": hasSelectedItems
|
|
1102
|
+
}
|
|
1103
|
+
),
|
|
1104
|
+
children: [
|
|
1105
|
+
selectedItems.length > 1 ? /* @__PURE__ */ jsx(VisuallyHidden, { onClick: inputRef.current?.focus, children: ariaLabelJumpToInput }) : null,
|
|
1106
|
+
selectedItems.length <= maxChips ? selectedItems.map((selectedItem, index) => /* @__PURE__ */ jsx(
|
|
1107
|
+
SelectedItemTag,
|
|
1108
|
+
{
|
|
1109
|
+
ariaLabelChosen: ariaLabelChosenSingular,
|
|
1110
|
+
ariaLabelRemoveSelected,
|
|
1111
|
+
disabled,
|
|
1112
|
+
getSelectedItemProps,
|
|
1113
|
+
index,
|
|
1114
|
+
readOnly,
|
|
1115
|
+
removeSelectedItem: () => {
|
|
1116
|
+
removeSelectedItem(selectedItem);
|
|
1117
|
+
inputRef?.current?.focus();
|
|
1118
|
+
},
|
|
1119
|
+
selectedItem
|
|
1120
|
+
},
|
|
1121
|
+
selectedItem?.label + (typeof selectedItem?.value === "string" ? selectedItem.value : "")
|
|
1122
|
+
)) : /* @__PURE__ */ jsx(
|
|
1123
|
+
SelectedItemTag,
|
|
1124
|
+
{
|
|
1125
|
+
ariaLabelRemoveSelected: labelClearAllItems,
|
|
1126
|
+
ariaLabelChosen: "",
|
|
1127
|
+
disabled,
|
|
1128
|
+
readOnly,
|
|
1129
|
+
removeSelectedItem: handleOnClear,
|
|
1130
|
+
selectedItem: summarySelectedItems
|
|
1131
|
+
}
|
|
1132
|
+
),
|
|
1133
|
+
/* @__PURE__ */ jsx(
|
|
1134
|
+
"input",
|
|
1135
|
+
{
|
|
1136
|
+
...getInputProps({
|
|
1137
|
+
onKeyDown: (e) => {
|
|
1138
|
+
if (selectOnTab && isOpen && e.key === "Tab") {
|
|
1139
|
+
const highlitedItem = listItems[highlightedIndex];
|
|
1140
|
+
if (!highlitedItem) return;
|
|
1141
|
+
const shouldSkipTabSelection = clickedItemIsSelectAll(highlitedItem) || !clickedItemIsSelectAll(highlitedItem) && clickedItemIsInSelectedItems(highlitedItem);
|
|
1142
|
+
if (shouldSkipTabSelection) return;
|
|
1143
|
+
handleListItemClicked({
|
|
1144
|
+
clickedItem: highlitedItem,
|
|
1145
|
+
onChange: setSelectedItems
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
...getDropdownProps({
|
|
1150
|
+
preventKeyAction: isOpen,
|
|
1151
|
+
value: inputValue ?? EMPTY_INPUT,
|
|
1152
|
+
ref: mergeRefs(inputRef, ref)
|
|
1153
|
+
}),
|
|
1154
|
+
className: "eds-dropdown__input eds-form-control",
|
|
1155
|
+
disabled: readOnly || disabled,
|
|
1156
|
+
placeholder,
|
|
1157
|
+
tabIndex: disabled || readOnly ? -1 : void 0
|
|
1158
|
+
})
|
|
1159
|
+
}
|
|
1160
|
+
)
|
|
1161
|
+
]
|
|
1162
|
+
}
|
|
1163
|
+
),
|
|
1164
|
+
/* @__PURE__ */ jsx(
|
|
1165
|
+
DropdownFieldAppendix,
|
|
1166
|
+
{
|
|
1167
|
+
...getToggleButtonProps({
|
|
1168
|
+
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
1169
|
+
}),
|
|
1170
|
+
ariaLabelCloseList,
|
|
1171
|
+
ariaLabelOpenList,
|
|
1172
|
+
clearable,
|
|
1173
|
+
disabled: disabled || readOnly,
|
|
1174
|
+
onClear: handleOnClear,
|
|
1175
|
+
focusable: false,
|
|
1176
|
+
labelClearSelected: labelClearAllItems,
|
|
1177
|
+
isOpen,
|
|
1178
|
+
itemIsSelected: selectedItems.length > 0,
|
|
1179
|
+
loadingText,
|
|
1180
|
+
loading: loading ?? resolvedItemsLoading
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
]
|
|
1184
|
+
}
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
);
|
|
1188
|
+
const Dropdown = React.forwardRef(
|
|
1189
|
+
({
|
|
1190
|
+
ariaLabelChosenSingular,
|
|
1191
|
+
ariaLabelCloseList = "Lukk liste med valg",
|
|
1192
|
+
ariaLabelOpenList = "Åpne liste med valg",
|
|
1193
|
+
ariaLabelSelectedItem,
|
|
1194
|
+
className,
|
|
1195
|
+
clearable = false,
|
|
1196
|
+
disabled = false,
|
|
1197
|
+
disableLabelAnimation,
|
|
1198
|
+
feedback,
|
|
1199
|
+
items: initialItems,
|
|
1200
|
+
label,
|
|
1201
|
+
labelClearSelectedItem = "fjern valgt",
|
|
1202
|
+
labelTooltip,
|
|
1203
|
+
listStyle,
|
|
1204
|
+
loading,
|
|
1205
|
+
loadingText = "Laster resultater …",
|
|
1206
|
+
noMatchesText = "Ingen tilgjengelige valg …",
|
|
1207
|
+
onChange,
|
|
1208
|
+
placeholder,
|
|
1209
|
+
prepend,
|
|
1210
|
+
readOnly = false,
|
|
1211
|
+
selectedItem,
|
|
1212
|
+
selectOnBlur = false,
|
|
1213
|
+
selectOnTab = false,
|
|
1214
|
+
style,
|
|
1215
|
+
variant = "information",
|
|
1216
|
+
...rest
|
|
1217
|
+
}, ref) => {
|
|
1218
|
+
const { items: normalizedItems, loading: resolvedItemsLoading } = useResolvedItems(initialItems);
|
|
1219
|
+
const isFilled = selectedItem !== null || placeholder !== void 0;
|
|
1220
|
+
const {
|
|
1221
|
+
isOpen,
|
|
1222
|
+
getItemProps,
|
|
1223
|
+
getLabelProps,
|
|
1224
|
+
getMenuProps,
|
|
1225
|
+
getToggleButtonProps,
|
|
1226
|
+
highlightedIndex,
|
|
1227
|
+
selectItem,
|
|
1228
|
+
reset
|
|
1229
|
+
} = useSelect({
|
|
1635
1230
|
items: normalizedItems,
|
|
1636
|
-
defaultHighlightedIndex: selectedItem ?
|
|
1637
|
-
selectedItem
|
|
1638
|
-
stateReducer
|
|
1639
|
-
|
|
1640
|
-
type = _ref2.type;
|
|
1641
|
-
var toggleButtonIsFocused = typeof document !== 'undefined' && document.activeElement === refs.reference.current;
|
|
1231
|
+
defaultHighlightedIndex: selectedItem ? void 0 : 0,
|
|
1232
|
+
selectedItem,
|
|
1233
|
+
stateReducer(_, { changes, type }) {
|
|
1234
|
+
const toggleButtonIsFocused = typeof document !== "undefined" && document.activeElement === refs.reference.current;
|
|
1642
1235
|
switch (type) {
|
|
1643
1236
|
case useSelect.stateChangeTypes.ToggleButtonKeyDownArrowDown:
|
|
1644
1237
|
case useSelect.stateChangeTypes.ToggleButtonKeyDownArrowUp:
|
|
1645
|
-
if (!toggleButtonIsFocused) return
|
|
1646
|
-
isOpen: false
|
|
1647
|
-
});
|
|
1238
|
+
if (!toggleButtonIsFocused) return { ...changes, isOpen: false };
|
|
1648
1239
|
}
|
|
1649
1240
|
return changes;
|
|
1650
1241
|
},
|
|
1651
|
-
onStateChange:
|
|
1652
|
-
var type = _ref3.type,
|
|
1653
|
-
newSelectedItem = _ref3.selectedItem;
|
|
1242
|
+
onStateChange({ type, selectedItem: newSelectedItem }) {
|
|
1654
1243
|
switch (type) {
|
|
1655
1244
|
case useSelect.stateChangeTypes.ToggleButtonBlur:
|
|
1656
1245
|
if (!selectOnBlur) return;
|
|
1657
1246
|
}
|
|
1658
|
-
if (newSelectedItem ===
|
|
1659
|
-
onChange
|
|
1247
|
+
if (newSelectedItem === void 0) return;
|
|
1248
|
+
onChange?.(newSelectedItem ?? null);
|
|
1660
1249
|
},
|
|
1661
|
-
itemToString
|
|
1662
|
-
})
|
|
1663
|
-
|
|
1664
|
-
getItemProps = _useSelect.getItemProps,
|
|
1665
|
-
getLabelProps = _useSelect.getLabelProps,
|
|
1666
|
-
getMenuProps = _useSelect.getMenuProps,
|
|
1667
|
-
getToggleButtonProps = _useSelect.getToggleButtonProps,
|
|
1668
|
-
highlightedIndex = _useSelect.highlightedIndex,
|
|
1669
|
-
selectItem = _useSelect.selectItem,
|
|
1670
|
-
reset = _useSelect.reset;
|
|
1671
|
-
// calculations for floating-UI popover position
|
|
1672
|
-
var _useFloating = useFloating({
|
|
1250
|
+
itemToString
|
|
1251
|
+
});
|
|
1252
|
+
const { refs, floatingStyles, update } = useFloating({
|
|
1673
1253
|
open: isOpen,
|
|
1674
|
-
placement:
|
|
1675
|
-
middleware: [
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
elements
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
// Downshift doesn't work correctly when conditionally rendered since props and refs aren't correctly
|
|
1699
|
-
// spread to the component. We therefor use this useEffect to update position. See https://floating-ui.com/docs/autoupdate#usage
|
|
1700
|
-
useEffect(function () {
|
|
1701
|
-
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1702
|
-
return autoUpdate(refs.reference.current, refs.floating.current, update);
|
|
1703
|
-
}
|
|
1704
|
-
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1705
|
-
var handleOnClear = function handleOnClear() {
|
|
1706
|
-
var _refs$reference$curre;
|
|
1707
|
-
reset();
|
|
1708
|
-
(_refs$reference$curre = refs.reference.current) == null || _refs$reference$curre.focus();
|
|
1709
|
-
};
|
|
1710
|
-
return React.createElement(BaseFormControl, _extends({
|
|
1711
|
-
className: classNames('eds-dropdown', className, {
|
|
1712
|
-
'eds-dropdown--has-tooltip': labelTooltip !== undefined
|
|
1713
|
-
}),
|
|
1714
|
-
disableLabelAnimation: disableLabelAnimation,
|
|
1715
|
-
feedback: feedback,
|
|
1716
|
-
isFilled: isFilled,
|
|
1717
|
-
labelProps: getLabelProps(),
|
|
1718
|
-
labelTooltip: labelTooltip,
|
|
1719
|
-
prepend: prepend,
|
|
1720
|
-
style: style,
|
|
1721
|
-
variant: variant
|
|
1722
|
-
}, getToggleButtonProps({
|
|
1723
|
-
ref: mergeRefs(ref, refs.setReference),
|
|
1724
|
-
'aria-disabled': disabled,
|
|
1725
|
-
'aria-label': disabled ? 'Disabled dropdown' : '',
|
|
1726
|
-
disabled: disabled,
|
|
1727
|
-
readOnly: readOnly,
|
|
1728
|
-
label: label,
|
|
1729
|
-
labelId: (_getLabelProps = getLabelProps()) == null ? void 0 : _getLabelProps.id,
|
|
1730
|
-
children: undefined,
|
|
1731
|
-
tabIndex: disabled || readOnly ? -1 : 0,
|
|
1732
|
-
onKeyDown: function onKeyDown(e) {
|
|
1733
|
-
if (isOpen && e.key === 'Tab') {
|
|
1734
|
-
var highlitedItem = normalizedItems[highlightedIndex];
|
|
1735
|
-
// we don't want to clear selection with tab
|
|
1736
|
-
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
1737
|
-
selectItem(highlitedItem);
|
|
1738
|
-
}
|
|
1254
|
+
placement: "bottom-start",
|
|
1255
|
+
middleware: [
|
|
1256
|
+
offset(space.extraSmall2),
|
|
1257
|
+
shift({ padding: space.extraSmall }),
|
|
1258
|
+
size({
|
|
1259
|
+
apply({ rects, elements, availableHeight }) {
|
|
1260
|
+
Object.assign(elements.floating.style, {
|
|
1261
|
+
width: `${rects.reference.width}px`,
|
|
1262
|
+
// Floating will flip when smaller than 10*16 px
|
|
1263
|
+
// and never exceed 20*16 px.
|
|
1264
|
+
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
}),
|
|
1268
|
+
flip({ fallbackStrategy: "initialPlacement" })
|
|
1269
|
+
]
|
|
1270
|
+
});
|
|
1271
|
+
useEffect(() => {
|
|
1272
|
+
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1273
|
+
return autoUpdate(
|
|
1274
|
+
refs.reference.current,
|
|
1275
|
+
refs.floating.current,
|
|
1276
|
+
update
|
|
1277
|
+
);
|
|
1739
1278
|
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1279
|
+
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1280
|
+
const handleOnClear = () => {
|
|
1281
|
+
reset();
|
|
1282
|
+
refs.reference.current?.focus();
|
|
1283
|
+
};
|
|
1284
|
+
return /* @__PURE__ */ jsxs(
|
|
1285
|
+
BaseFormControl,
|
|
1286
|
+
{
|
|
1287
|
+
className: classNames("eds-dropdown", className, {
|
|
1288
|
+
"eds-dropdown--has-tooltip": labelTooltip !== void 0
|
|
1289
|
+
}),
|
|
1290
|
+
disableLabelAnimation,
|
|
1291
|
+
feedback,
|
|
1292
|
+
isFilled,
|
|
1293
|
+
labelProps: getLabelProps(),
|
|
1294
|
+
labelTooltip,
|
|
1295
|
+
prepend,
|
|
1296
|
+
style,
|
|
1297
|
+
variant,
|
|
1298
|
+
...getToggleButtonProps({
|
|
1299
|
+
ref: mergeRefs(ref, refs.setReference),
|
|
1300
|
+
"aria-disabled": disabled,
|
|
1301
|
+
"aria-label": disabled ? "Disabled dropdown" : "",
|
|
1302
|
+
disabled,
|
|
1303
|
+
readOnly,
|
|
1304
|
+
label,
|
|
1305
|
+
labelId: getLabelProps()?.id,
|
|
1306
|
+
children: void 0,
|
|
1307
|
+
tabIndex: disabled || readOnly ? -1 : 0,
|
|
1308
|
+
onKeyDown(e) {
|
|
1309
|
+
if (isOpen && e.key === "Tab") {
|
|
1310
|
+
const highlitedItem = normalizedItems[highlightedIndex];
|
|
1311
|
+
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
1312
|
+
selectItem(highlitedItem);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}),
|
|
1317
|
+
after: /* @__PURE__ */ jsx(
|
|
1318
|
+
DropdownList,
|
|
1319
|
+
{
|
|
1320
|
+
ariaLabelChosenSingular,
|
|
1321
|
+
ariaLabelSelectedItem,
|
|
1322
|
+
floatingStyles,
|
|
1323
|
+
getItemProps,
|
|
1324
|
+
getMenuProps,
|
|
1325
|
+
highlightedIndex,
|
|
1326
|
+
isOpen,
|
|
1327
|
+
listItems: normalizedItems,
|
|
1328
|
+
noMatchesText,
|
|
1329
|
+
style: listStyle,
|
|
1330
|
+
setListRef: refs.setFloating,
|
|
1331
|
+
loading: loading ?? resolvedItemsLoading,
|
|
1332
|
+
loadingText,
|
|
1333
|
+
selectedItems: selectedItem !== null ? [selectedItem] : [],
|
|
1334
|
+
readOnly
|
|
1335
|
+
}
|
|
1336
|
+
),
|
|
1337
|
+
...rest,
|
|
1338
|
+
append: void 0,
|
|
1339
|
+
children: [
|
|
1340
|
+
/* @__PURE__ */ jsx("div", { className: "eds-dropdown__selected-item", children: selectedItem?.label ?? /* @__PURE__ */ jsx(
|
|
1341
|
+
"div",
|
|
1342
|
+
{
|
|
1343
|
+
className: classNames(
|
|
1344
|
+
"eds-dropdown__selected-item__placeholder",
|
|
1345
|
+
{
|
|
1346
|
+
"eds-dropdown__selected-item__placeholder--readonly": readOnly
|
|
1347
|
+
}
|
|
1348
|
+
),
|
|
1349
|
+
children: placeholder
|
|
1350
|
+
}
|
|
1351
|
+
) }),
|
|
1352
|
+
/* @__PURE__ */ jsx(
|
|
1353
|
+
DropdownFieldAppendix,
|
|
1354
|
+
{
|
|
1355
|
+
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true",
|
|
1356
|
+
"aria-expanded": isOpen,
|
|
1357
|
+
clearable,
|
|
1358
|
+
onClear: handleOnClear,
|
|
1359
|
+
disabled: disabled || readOnly,
|
|
1360
|
+
focusable: false,
|
|
1361
|
+
labelClearSelected: labelClearSelectedItem,
|
|
1362
|
+
isOpen,
|
|
1363
|
+
itemIsSelected: selectedItem !== null,
|
|
1364
|
+
ariaLabelCloseList,
|
|
1365
|
+
ariaLabelOpenList,
|
|
1366
|
+
loading: false,
|
|
1367
|
+
loadingText: void 0
|
|
1368
|
+
}
|
|
1369
|
+
)
|
|
1370
|
+
]
|
|
1371
|
+
}
|
|
1372
|
+
);
|
|
1373
|
+
}
|
|
1374
|
+
);
|
|
1375
|
+
const error = "error";
|
|
1376
|
+
const NativeDropdown = forwardRef(
|
|
1377
|
+
({
|
|
1378
|
+
className,
|
|
1379
|
+
disabled = false,
|
|
1380
|
+
disableLabelAnimation,
|
|
1381
|
+
feedback,
|
|
1382
|
+
items,
|
|
1383
|
+
label,
|
|
1384
|
+
loadingText,
|
|
1385
|
+
onChange,
|
|
1386
|
+
prepend,
|
|
1387
|
+
readOnly = false,
|
|
1388
|
+
selectedItem,
|
|
1389
|
+
style,
|
|
1390
|
+
value,
|
|
1391
|
+
variant,
|
|
1392
|
+
...rest
|
|
1393
|
+
}, ref) => {
|
|
1394
|
+
const { items: normalizedItems, loading } = useResolvedItems(items);
|
|
1395
|
+
const nativeDropdownId = useRandomId("eds-dropdown-native");
|
|
1396
|
+
return /* @__PURE__ */ jsx(
|
|
1397
|
+
BaseFormControl,
|
|
1398
|
+
{
|
|
1399
|
+
disabled,
|
|
1400
|
+
readOnly,
|
|
1401
|
+
prepend,
|
|
1402
|
+
append: /* @__PURE__ */ jsx(
|
|
1403
|
+
FieldAppend,
|
|
1404
|
+
{
|
|
1405
|
+
hidden: disabled || readOnly,
|
|
1406
|
+
loading,
|
|
1407
|
+
loadingText
|
|
1408
|
+
}
|
|
1409
|
+
),
|
|
1410
|
+
className,
|
|
1411
|
+
style,
|
|
1412
|
+
label,
|
|
1413
|
+
labelId: nativeDropdownId,
|
|
1414
|
+
variant,
|
|
1415
|
+
feedback,
|
|
1416
|
+
disableLabelAnimation,
|
|
1417
|
+
isFilled: true,
|
|
1418
|
+
children: /* @__PURE__ */ jsx(
|
|
1419
|
+
"select",
|
|
1420
|
+
{
|
|
1421
|
+
"aria-invalid": variant === "negative" || variant === error,
|
|
1422
|
+
"aria-labelledby": nativeDropdownId,
|
|
1423
|
+
"aria-busy": loading,
|
|
1424
|
+
className: "eds-form-control eds-dropdown--native",
|
|
1425
|
+
disabled: disabled || readOnly,
|
|
1426
|
+
onChange: (event) => {
|
|
1427
|
+
onChange?.({
|
|
1428
|
+
value: event.target.value,
|
|
1429
|
+
selectedItem: normalizedItems.find(
|
|
1430
|
+
(item) => item.value === event.target.value
|
|
1431
|
+
) ?? null,
|
|
1432
|
+
target: event.target
|
|
1433
|
+
});
|
|
1434
|
+
},
|
|
1435
|
+
value: value ?? selectedItem?.value ?? void 0,
|
|
1436
|
+
ref,
|
|
1437
|
+
...rest,
|
|
1438
|
+
children: normalizedItems.map((item) => /* @__PURE__ */ jsx("option", { value: item.value, children: item.label }, item.value))
|
|
1439
|
+
}
|
|
1440
|
+
)
|
|
1441
|
+
}
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
);
|
|
1445
|
+
const FieldAppend = ({
|
|
1446
|
+
loading,
|
|
1447
|
+
loadingText,
|
|
1448
|
+
hidden
|
|
1449
|
+
}) => {
|
|
1857
1450
|
if (loading) {
|
|
1858
|
-
return
|
|
1859
|
-
className: "eds-dropdown-native__loading-dots"
|
|
1860
|
-
}, React.createElement(LoadingDots, {
|
|
1861
|
-
"aria-label": loadingText
|
|
1862
|
-
}));
|
|
1451
|
+
return /* @__PURE__ */ jsx("div", { className: "eds-dropdown-native__loading-dots", children: /* @__PURE__ */ jsx(LoadingDots, { "aria-label": loadingText }) });
|
|
1863
1452
|
}
|
|
1864
1453
|
if (hidden) {
|
|
1865
|
-
return
|
|
1454
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
1866
1455
|
}
|
|
1867
|
-
return
|
|
1868
|
-
|
|
1869
|
-
|
|
1456
|
+
return /* @__PURE__ */ jsx(DownArrowIcon, { inline: true });
|
|
1457
|
+
};
|
|
1458
|
+
warnAboutMissingStyles("dropdown", "form", "a11y", "chip");
|
|
1459
|
+
export {
|
|
1460
|
+
Dropdown,
|
|
1461
|
+
MultiSelect,
|
|
1462
|
+
NativeDropdown,
|
|
1463
|
+
SearchableDropdown
|
|
1870
1464
|
};
|
|
1871
|
-
|
|
1872
|
-
warnAboutMissingStyles('dropdown', 'form', 'a11y', 'chip');
|
|
1873
|
-
|
|
1874
|
-
export { Dropdown, MultiSelect, NativeDropdown, SearchableDropdown };
|
|
1875
1465
|
//# sourceMappingURL=dropdown.esm.js.map
|