@skf-design-system/ui-components 0.0.1-beta.4 → 1.0.0-beta.4
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/components/checkbox/checkbox.component.js +1 -1
- package/dist/components/input/input.component.js +24 -26
- package/dist/components/select/select.component.d.ts +138 -0
- package/dist/components/select/select.component.js +311 -0
- package/dist/components/select/select.controllers.d.ts +59 -0
- package/dist/components/select/select.controllers.js +169 -0
- package/dist/components/select/select.d.ts +8 -0
- package/dist/components/select/select.js +6 -0
- package/dist/components/select/select.styles.d.ts +1 -0
- package/dist/components/select/select.styles.js +116 -0
- package/dist/components/select-option/select-option.component.d.ts +77 -0
- package/dist/components/select-option/select-option.component.js +117 -0
- package/dist/components/select-option/select-option.controllers.d.ts +9 -0
- package/dist/components/select-option/select-option.d.ts +8 -0
- package/dist/components/select-option/select-option.js +6 -0
- package/dist/components/select-option/select-option.styles.d.ts +1 -0
- package/dist/components/select-option/select-option.styles.js +53 -0
- package/dist/components/select-option-group/select-option-group.component.d.ts +16 -0
- package/dist/components/select-option-group/select-option-group.component.js +31 -0
- package/dist/components/select-option-group/select-option-group.d.ts +8 -0
- package/dist/components/select-option-group/select-option-group.js +6 -0
- package/dist/components/select-option-group/select-option-group.style.d.ts +1 -0
- package/dist/components/select-option-group/select-option-group.style.js +18 -0
- package/dist/components/tag/tag.component.d.ts +18 -2
- package/dist/components/tag/tag.component.js +69 -32
- package/dist/components/tag/tag.styles.js +0 -4
- package/dist/custom-elements.json +1279 -624
- package/dist/index.d.ts +3 -0
- package/dist/index.js +39 -30
- package/dist/internal/components/formBase.d.ts +18 -1
- package/dist/internal/components/formBase.js +25 -13
- package/dist/internal/components/skf-element.d.ts +4 -4
- package/dist/internal/components/skf-element.js +15 -19
- package/dist/internal/helpers/array.d.ts +4 -0
- package/dist/internal/helpers/findMatchingTags.d.ts +2 -0
- package/dist/internal/helpers/findMatchingTags.js +12 -0
- package/dist/internal/helpers/hintSeverity.d.ts +2 -0
- package/dist/internal/helpers/hintSeverity.js +6 -0
- package/dist/internal/helpers/raiseError.d.ts +28 -0
- package/dist/internal/helpers/raiseError.js +29 -0
- package/dist/internal/storybook/shadowRootTraverser.d.ts +2 -0
- package/dist/react/index.d.ts +6 -3
- package/dist/react/index.js +6 -3
- package/dist/react/skf-select/index.d.ts +21 -0
- package/dist/react/skf-select/index.js +21 -0
- package/dist/react/skf-select-option/index.d.ts +9 -0
- package/dist/react/skf-select-option/index.js +17 -0
- package/dist/react/skf-select-option-group/index.d.ts +3 -0
- package/dist/react/skf-select-option-group/index.js +13 -0
- package/dist/styles/form-field.styles.js +6 -6
- package/dist/types/jsx/custom-element-jsx.d.ts +326 -176
- package/dist/types/vue/index.d.ts +268 -135
- package/dist/vscode.html-custom-data.json +344 -147
- package/dist/web-types.json +755 -383
- package/package.json +34 -30
@@ -23,7 +23,7 @@ const h = class h extends p {
|
|
23
23
|
super.connectedCallback(), this._validateInput();
|
24
24
|
}
|
25
25
|
willUpdate(t) {
|
26
|
-
t.has("_invalid") && (this._invalid ? (this.setAttribute("invalid", ""), this.showValid
|
26
|
+
t.has("_invalid") && (this._invalid ? (this.setAttribute("invalid", ""), this.showValid && this.removeAttribute("valid"), this.checkValidity()) : (this.removeAttribute("invalid"), !this.pristine && this.showValid && this.setAttribute("valid", "true")));
|
27
27
|
}
|
28
28
|
firstUpdated() {
|
29
29
|
var t;
|
@@ -1,23 +1,24 @@
|
|
1
1
|
import "../icon/icon.js";
|
2
|
-
import { FormBase as
|
2
|
+
import { FormBase as v } from "../../internal/components/formBase.js";
|
3
3
|
import "../../internal/components/hint/hint.js";
|
4
|
-
import {
|
5
|
-
import y from "../../
|
4
|
+
import { hintSeverity as c } from "../../internal/helpers/hintSeverity.js";
|
5
|
+
import { Asterisk as y } from "../../internal/templates/asterisk.js";
|
6
|
+
import f from "../../styles/component.styles.js";
|
6
7
|
import { html as h, nothing as d } from "lit";
|
7
|
-
import { property as s, state as b, query as
|
8
|
+
import { property as s, state as b, query as _ } from "lit/decorators.js";
|
8
9
|
import { ifDefined as a } from "lit/directives/if-defined.js";
|
9
10
|
import { live as $ } from "lit/directives/live.js";
|
10
|
-
import { InputNumberController as
|
11
|
-
import
|
12
|
-
var
|
13
|
-
for (var o = n > 1 ? void 0 : n ?
|
14
|
-
(
|
15
|
-
return n && o &&
|
11
|
+
import { InputNumberController as g, InputPasswordController as w } from "./input.controllers.js";
|
12
|
+
import E from "./input.styles.js";
|
13
|
+
var A = Object.defineProperty, C = Object.getOwnPropertyDescriptor, i = (m, e, r, n) => {
|
14
|
+
for (var o = n > 1 ? void 0 : n ? C(e, r) : e, l = m.length - 1, u; l >= 0; l--)
|
15
|
+
(u = m[l]) && (o = (n ? u(e, r, o) : u(o)) || o);
|
16
|
+
return n && o && A(e, r, o), o;
|
16
17
|
};
|
17
|
-
const
|
18
|
+
const p = class p extends v {
|
18
19
|
constructor() {
|
19
20
|
super(), this.buttonAriaLabelClear = "Clear input", this.buttonAriaLabelHide = "Hide password", this.buttonAriaLabelShow = "Show password", this.debug = !1, this.hideLabel = !1, this.inputmode = "text", this.size = "md", this.type = "text", this.validateOn = "change", this.value = "", this.invalid = !1, this._buttonDown = !1, this._handleInput = () => {
|
20
|
-
this.value = this.$input.value || "", this.validateOn === "input" && (this.
|
21
|
+
this.value = this.$input.value || "", this.validateOn === "input" && (this._pristine = !1, this.validateInput());
|
21
22
|
}, this._resetValue = (e) => {
|
22
23
|
var r;
|
23
24
|
e.stopPropagation(), this.value = ((r = this.getAttribute("value")) == null ? void 0 : r.trim()) ?? "", this._internals.setFormValue(this.value), this.$input.focus();
|
@@ -66,7 +67,7 @@ const m = class m extends c {
|
|
66
67
|
</button>
|
67
68
|
`, this._onBlur = () => {
|
68
69
|
this._buttonDown && this.$input.focus();
|
69
|
-
}, this._numberController = new
|
70
|
+
}, this._numberController = new g(this), this._passwordController = new w(this);
|
70
71
|
}
|
71
72
|
set customInvalid(e) {
|
72
73
|
this.customError = String(e);
|
@@ -76,9 +77,9 @@ const m = class m extends c {
|
|
76
77
|
}
|
77
78
|
firstUpdated() {
|
78
79
|
this.$input.addEventListener("change", () => {
|
79
|
-
this.validateOn === "change" && (this.validateOn = "input", this.
|
80
|
+
this.validateOn === "change" && (this.validateOn = "input", this._pristine = !1), this._internals.setFormValue(this.$input.value || ""), this.emitEvent("change"), this.validateInput();
|
80
81
|
}), this.addEventListener("invalid", (e) => {
|
81
|
-
this.
|
82
|
+
this._pristine = !1, this.invalid = !0, this.customErrorDisplay && e.preventDefault();
|
82
83
|
}), this.addEventListener("reset", this._resetValue), this.validateInput();
|
83
84
|
}
|
84
85
|
willUpdate(e) {
|
@@ -88,13 +89,13 @@ const m = class m extends c {
|
|
88
89
|
const r = this._internals.validationMessage;
|
89
90
|
this.hint = r !== "" ? this._internals.validationMessage : "", this.checkValidity();
|
90
91
|
} else
|
91
|
-
this.removeAttribute("invalid"), !this.
|
92
|
+
this.removeAttribute("invalid"), !this._pristine && this.showValid && this.setAttribute("valid", "true"), this.hint = this.getAttribute("hint") ?? "";
|
92
93
|
}
|
93
94
|
attributeChangedCallback(e, r, n) {
|
94
95
|
if (super.attributeChangedCallback(e, r, n), e === "value" && this._internals.setFormValue(n), e === "custom-invalid")
|
95
96
|
if (typeof n == "string") {
|
96
97
|
const l = String(n).trim();
|
97
|
-
this.
|
98
|
+
this._pristine = !1, this._internals.setValidity({ customError: !0 }, l), this.invalid = !0, this.hint = l, this.checkValidity();
|
98
99
|
} else
|
99
100
|
this._internals.setValidity({}), this.validateInput();
|
100
101
|
}
|
@@ -105,7 +106,7 @@ const m = class m extends c {
|
|
105
106
|
if (this.invalid = !1, r.valid)
|
106
107
|
this._internals.setValidity({ customError: this._internals.validity.customError });
|
107
108
|
else {
|
108
|
-
this.invalid = !this.
|
109
|
+
this.invalid = !this._pristine && !r.valid;
|
109
110
|
let n;
|
110
111
|
for (n in r) {
|
111
112
|
const o = `data-${n.toString()}`;
|
@@ -129,7 +130,7 @@ const m = class m extends c {
|
|
129
130
|
<label>
|
130
131
|
<div class=${this.hideLabel ? "visually-hidden" : ""} id="label">
|
131
132
|
<slot>${this.label}</slot>
|
132
|
-
${this.required ?
|
133
|
+
${this.required ? y(this.requiredLabel) : null}
|
133
134
|
</div>
|
134
135
|
<div id="input">
|
135
136
|
${this.type === "search" ? h`<skf-icon name="search" size="sm"></skf-icon>` : d}
|
@@ -175,7 +176,7 @@ const m = class m extends c {
|
|
175
176
|
<skf-hint
|
176
177
|
aria-live=${this.invalid ? "assertive" : "polite"}
|
177
178
|
id="hint"
|
178
|
-
severity=${a(
|
179
|
+
severity=${a(c(this.severity, this.invalid))}
|
179
180
|
>${this.hint}
|
180
181
|
</skf-hint>
|
181
182
|
`}
|
@@ -183,8 +184,8 @@ const m = class m extends c {
|
|
183
184
|
`;
|
184
185
|
}
|
185
186
|
};
|
186
|
-
|
187
|
-
let t =
|
187
|
+
p.styles = [f, E];
|
188
|
+
let t = p;
|
188
189
|
i([
|
189
190
|
s({ attribute: "button-aria-label-clear" })
|
190
191
|
], t.prototype, "buttonAriaLabelClear", 2);
|
@@ -270,11 +271,8 @@ i([
|
|
270
271
|
b()
|
271
272
|
], t.prototype, "_buttonDown", 2);
|
272
273
|
i([
|
273
|
-
|
274
|
+
_("input")
|
274
275
|
], t.prototype, "$input", 2);
|
275
|
-
function C(u, e) {
|
276
|
-
return e ? "error" : u;
|
277
|
-
}
|
278
276
|
export {
|
279
277
|
t as SkfInput
|
280
278
|
};
|
@@ -0,0 +1,138 @@
|
|
1
|
+
import { FormBase } from '@internal/components/formBase.js';
|
2
|
+
import type { FormFieldBaseProps } from '@internal/types/formField.js';
|
3
|
+
import { type CSSResultGroup } from 'lit';
|
4
|
+
import '../../internal/components/hint/hint';
|
5
|
+
import type { SelectOptionEvent, SkfSelectOption } from '../select-option/select-option.component.js';
|
6
|
+
import '../tag/tag';
|
7
|
+
import { DeveloperFeedbackController, GlobalClickController, KeyboardNavigationController, ResizeController, ScrollController } from './select.controllers.js';
|
8
|
+
/**
|
9
|
+
* TODO: abstract the popover logic to a separate component/helper/partial, and use it in both select and in input[datalist], combobox etc
|
10
|
+
*
|
11
|
+
* TODO: Fix the popover positioning, it should be relative to the button, not the window (low priority since we have solution and is it possible at all on something in #toplayer)
|
12
|
+
*/
|
13
|
+
/**
|
14
|
+
* The `<skf-select>` is a component that displays a list of actions or options. A click in the options list toggle the selected state of the option. Use it together with the ´skf-select-option` tag.
|
15
|
+
*
|
16
|
+
* @documentation See [InVision DSM](https://skf.invisionapp.com/dsm/ab-skf/4-web-applications/nav/5fa7caf78c01200018354495/asset/6229d63d9fe16020a60657e5) for design principles
|
17
|
+
*
|
18
|
+
* @attribute {Boolean} [disabled] - If true, the select is disabled `default: false`
|
19
|
+
*
|
20
|
+
* @slot - The select's placeholder content
|
21
|
+
* @slot icon - The select's slot for custom meta information
|
22
|
+
*
|
23
|
+
* @event change - Fired when the selected option(s) changes
|
24
|
+
* @event invalid - Fired when the select is invalid
|
25
|
+
* @event reset - Fired when the form is reset
|
26
|
+
* @event skf-select:dropdown - {detail: {expanded: boolean}} Fired when the select dropdown is toggled
|
27
|
+
* @event skf-select-option:select - {detail: {value: string | null, option: SkfSelectOption}} Fired when the select dropdown is toggled
|
28
|
+
*
|
29
|
+
* @tagname skf-select
|
30
|
+
*/
|
31
|
+
export declare class SkfSelect extends FormBase {
|
32
|
+
static styles: CSSResultGroup;
|
33
|
+
/** @internal */
|
34
|
+
selectDelay: number;
|
35
|
+
/** @internal */
|
36
|
+
_optionsList: SkfSelectOption[];
|
37
|
+
/** Sets the first visible text on the component */
|
38
|
+
buttonLabel: string;
|
39
|
+
/** If defined, forces component to invalid state until removed */
|
40
|
+
customInvalid?: string;
|
41
|
+
/** If true, hides the label visually */
|
42
|
+
hideLabel?: boolean;
|
43
|
+
/** If true and mulltiple is true, no tags are displayed under the select */
|
44
|
+
hideTags?: boolean;
|
45
|
+
/** If defined, sets the hint text under the select component in the form */
|
46
|
+
hint?: string;
|
47
|
+
/** A readonly property that returns the selected value(s) in a array */
|
48
|
+
get getSelectedValues(): string[];
|
49
|
+
/** A readonly property that returns the selected slot(s) text content in a array */
|
50
|
+
get getSelectedOptionsText(): (string | null)[];
|
51
|
+
/** Sets the visible label of the select in the form */
|
52
|
+
label: string;
|
53
|
+
/** If defined, limits the number of selectable options */
|
54
|
+
max?: number;
|
55
|
+
/** If defined, sets the minimum number of required options */
|
56
|
+
min?: number;
|
57
|
+
/** If provided, allows for multiple options to be selected */
|
58
|
+
multiple?: boolean;
|
59
|
+
/** If provided, set name of the component */
|
60
|
+
name?: string;
|
61
|
+
/** If defined, renders an alternative A11y text for the asterisk */
|
62
|
+
requiredLabel?: string;
|
63
|
+
/** If defined, displays provided severity state */
|
64
|
+
severity?: FormFieldBaseProps['severity'];
|
65
|
+
/** If provided, displays valid state after interaction */
|
66
|
+
showValid?: boolean;
|
67
|
+
/** Size of the Select */
|
68
|
+
size: 'sm' | 'md';
|
69
|
+
/** Read only, returns the selected value. (if multiple: in a comma separated string) */
|
70
|
+
get value(): string;
|
71
|
+
/** @internal */
|
72
|
+
/** Stores the selected SkfSelectOption tag(s) in a array. Is the source of truth for the internal state. */
|
73
|
+
private _selectedOptions;
|
74
|
+
/** @internal */
|
75
|
+
/** The selected options in an array. Treat it as a read only property. See selectedValues, slectedSlots for computed value arrays. */
|
76
|
+
set selectedOptions(option: SkfSelectOption[]);
|
77
|
+
/** @internal */
|
78
|
+
get selectedOptions(): SkfSelectOption[];
|
79
|
+
/** @internal */
|
80
|
+
_expanded: boolean;
|
81
|
+
/** @internal */
|
82
|
+
/** True if the internal state is invalid */
|
83
|
+
private _invalid;
|
84
|
+
/** @internal */
|
85
|
+
private $selectBtn?;
|
86
|
+
/** @internal */
|
87
|
+
private $selectedValue?;
|
88
|
+
/** @internal */
|
89
|
+
private $dropdown?;
|
90
|
+
/** @internal */
|
91
|
+
protected scrollController: ScrollController;
|
92
|
+
/** @internal */
|
93
|
+
protected resizeController: ResizeController;
|
94
|
+
/** @internal */
|
95
|
+
protected globalClickController: GlobalClickController;
|
96
|
+
/** @internal */
|
97
|
+
protected keyboardNavController: KeyboardNavigationController;
|
98
|
+
/** @internal */
|
99
|
+
protected developerFeedbackController: DeveloperFeedbackController;
|
100
|
+
constructor();
|
101
|
+
willUpdate(changedProperties: Map<string | number | symbol, unknown>): void;
|
102
|
+
firstUpdated(): void;
|
103
|
+
updated(changedProperties: Map<string, unknown>): void;
|
104
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
105
|
+
disconnectedCallback(): void;
|
106
|
+
/** @internal */
|
107
|
+
_handleOptionSelected: EventListener;
|
108
|
+
/** @internal */
|
109
|
+
_updateState(event: CustomEvent<SelectOptionEvent>): void;
|
110
|
+
/** @internal */
|
111
|
+
_handleReset: () => void;
|
112
|
+
/** @internal */
|
113
|
+
onUpdateComplete(): Promise<string>;
|
114
|
+
/** @internal */
|
115
|
+
/** Filter out elements other than skf-select-option and store in this._optionsList */
|
116
|
+
_collectSlotOptionTags(): void;
|
117
|
+
/** @internal */
|
118
|
+
_updateWidth: () => void;
|
119
|
+
/** @internal */
|
120
|
+
/** this runs only from the 'updated' lifecycle, by setting source-of-truth _expanded=false */
|
121
|
+
private _managePopover;
|
122
|
+
/** @internal */
|
123
|
+
_handleDropdownToggle: (e: Event) => void;
|
124
|
+
/** @internal
|
125
|
+
* Sets the value of the select component based on the selected options.
|
126
|
+
* Also closes the dropdown if not multiple.
|
127
|
+
*/
|
128
|
+
_setValue: () => Promise<unknown>;
|
129
|
+
/** @internal */
|
130
|
+
_resetSelectedOptions: (target?: SkfSelectOption) => void;
|
131
|
+
/** @internal */
|
132
|
+
_handleSlotChange: () => void;
|
133
|
+
/** @internal */
|
134
|
+
_computeVisibleValue: () => string;
|
135
|
+
/** @internal */
|
136
|
+
private _validateInput;
|
137
|
+
render(): import("lit").TemplateResult<1>;
|
138
|
+
}
|
@@ -0,0 +1,311 @@
|
|
1
|
+
import { computePosition as f, flip as _, shift as v, offset as g } from "@floating-ui/dom";
|
2
|
+
import { FormBase as b } from "../../internal/components/formBase.js";
|
3
|
+
import { findMatchingTags as y } from "../../internal/helpers/findMatchingTags.js";
|
4
|
+
import { hintSeverity as O } from "../../internal/helpers/hintSeverity.js";
|
5
|
+
import { raiseError as S } from "../../internal/helpers/raiseError.js";
|
6
|
+
import { Asterisk as w } from "../../internal/templates/asterisk.js";
|
7
|
+
import x from "../../styles/component.styles.js";
|
8
|
+
import { html as h, nothing as $ } from "lit";
|
9
|
+
import { property as r, state as d, query as p } from "lit/decorators.js";
|
10
|
+
import { classMap as V } from "lit/directives/class-map.js";
|
11
|
+
import { ifDefined as m } from "lit/directives/if-defined.js";
|
12
|
+
import "../../internal/components/hint/hint.js";
|
13
|
+
import "../tag/tag.js";
|
14
|
+
import { ScrollController as C, ResizeController as A, GlobalClickController as E, KeyboardNavigationController as k, DeveloperFeedbackController as L } from "./select.controllers.js";
|
15
|
+
import { styles as P } from "./select.styles.js";
|
16
|
+
var D = Object.defineProperty, M = Object.getOwnPropertyDescriptor, l = (u, t, e, s) => {
|
17
|
+
for (var o = s > 1 ? void 0 : s ? M(t, e) : t, a = u.length - 1, n; a >= 0; a--)
|
18
|
+
(n = u[a]) && (o = (s ? n(t, e, o) : n(o)) || o);
|
19
|
+
return s && o && D(t, e, o), o;
|
20
|
+
};
|
21
|
+
const c = class c extends b {
|
22
|
+
constructor() {
|
23
|
+
super(), this.selectDelay = 50, this._optionsList = [], this.buttonLabel = "Select an option", this.label = "Default label", this.size = "md", this._expanded = !1, this._invalid = !1, this.scrollController = new C(this), this.resizeController = new A(this), this.globalClickController = new E(this), this.keyboardNavController = new k(this), this.developerFeedbackController = new L(this), this._handleOptionSelected = (t) => {
|
24
|
+
this._pristine = !1;
|
25
|
+
const e = this._selectedOptions.length > 0;
|
26
|
+
this.setFormValue(e ? this.getSelectedValues.join(",") : null), this._updateState(t);
|
27
|
+
}, this._handleReset = () => {
|
28
|
+
this.emitEvent("reset"), this._resetSelectedOptions();
|
29
|
+
}, this._updateWidth = () => {
|
30
|
+
setTimeout(() => {
|
31
|
+
var t;
|
32
|
+
(t = this.$dropdown) == null || t.style.setProperty("--select-width", `${String(this.offsetWidth)}px`);
|
33
|
+
}, 50);
|
34
|
+
}, this._managePopover = () => ({ close: () => {
|
35
|
+
var s;
|
36
|
+
(s = this.$dropdown) == null || s.hidePopover();
|
37
|
+
}, open: () => {
|
38
|
+
const s = this.$selectBtn, o = this.$dropdown;
|
39
|
+
!s || !o || (o.showPopover(), f(s, o, {
|
40
|
+
placement: "bottom",
|
41
|
+
middleware: [_(), v({ padding: 5 }), g(2)]
|
42
|
+
}).then(({ x: a, y: n }) => {
|
43
|
+
Object.assign(o.style, {
|
44
|
+
left: `${String(a)}px`,
|
45
|
+
top: `${String(Math.round(n - window.scrollY))}px`
|
46
|
+
});
|
47
|
+
}).catch((a) => {
|
48
|
+
console.error(a);
|
49
|
+
}));
|
50
|
+
} }), this._handleDropdownToggle = (t) => {
|
51
|
+
t.stopPropagation(), this._expanded = !this._expanded;
|
52
|
+
}, this._setValue = async () => new Promise((t) => {
|
53
|
+
switch (!0) {
|
54
|
+
case this._selectedOptions.length === 0:
|
55
|
+
this.setFormValue(null), this.requestUpdate();
|
56
|
+
break;
|
57
|
+
case this._selectedOptions.length === 1:
|
58
|
+
this.setFormValue(this.getSelectedValues[0]);
|
59
|
+
break;
|
60
|
+
case this._selectedOptions.length > 1:
|
61
|
+
this.setFormValue(this.getSelectedValues.join(","));
|
62
|
+
break;
|
63
|
+
default:
|
64
|
+
throw new Error("Something went wrong");
|
65
|
+
}
|
66
|
+
this.emitEvent("change"), this._validateInput(), this.$selectedValue && (this.$selectedValue.animate([{ opacity: 0.5 }, { opacity: 1 }], this.selectDelay).onfinish = () => {
|
67
|
+
this.multiple || (this._expanded = !1), t("done");
|
68
|
+
});
|
69
|
+
}), this._resetSelectedOptions = (t) => {
|
70
|
+
const e = !t;
|
71
|
+
this._optionsList.forEach((s) => {
|
72
|
+
(e || s !== t) && s.removeAttribute("selected");
|
73
|
+
});
|
74
|
+
}, this._handleSlotChange = () => {
|
75
|
+
this._collectSlotOptionTags(), this._validateInput();
|
76
|
+
}, this._computeVisibleValue = () => {
|
77
|
+
var t, e;
|
78
|
+
return (t = this.$selectedValue) == null || t.classList.add("contains-meta-info"), this._selectedOptions.length > 1 ? `(${String(this._selectedOptions.length)} items selected)` : this.value ? ((e = this.$selectedValue) == null || e.classList.remove("contains-meta-info"), this.value) : this.buttonLabel;
|
79
|
+
}, this._selectedOptions = [];
|
80
|
+
}
|
81
|
+
get getSelectedValues() {
|
82
|
+
return this._selectedOptions.map((t) => t.value.trim());
|
83
|
+
}
|
84
|
+
get getSelectedOptionsText() {
|
85
|
+
return this._selectedOptions.map((t) => t.textContent);
|
86
|
+
}
|
87
|
+
get value() {
|
88
|
+
return this._selectedOptions.length ? this._selectedOptions.length === 1 ? this._selectedOptions[0].value.trim() : this._selectedOptions.map((t) => t.value.trim()).join(",") : "";
|
89
|
+
}
|
90
|
+
set selectedOptions(t) {
|
91
|
+
if (!t.length) {
|
92
|
+
this._selectedOptions = [];
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
this._selectedOptions = t;
|
96
|
+
}
|
97
|
+
/** @internal */
|
98
|
+
get selectedOptions() {
|
99
|
+
return this._selectedOptions;
|
100
|
+
}
|
101
|
+
willUpdate(t) {
|
102
|
+
if (t.has("_expanded")) {
|
103
|
+
const e = !!t.get("_expanded") && !this._expanded;
|
104
|
+
this._pristine && e && (this._pristine = !1);
|
105
|
+
}
|
106
|
+
if (t.has("_invalid"))
|
107
|
+
if (this._invalid) {
|
108
|
+
this.setAttribute("invalid", ""), this.showValid && this.removeAttribute("valid");
|
109
|
+
const e = this._internals.validationMessage;
|
110
|
+
this.hint = e !== "" ? this._internals.validationMessage : "", this.checkValidity(), this.emitEvent("invalid");
|
111
|
+
} else
|
112
|
+
this.removeAttribute("invalid"), !this._pristine && this.showValid && this.setAttribute("valid", "true"), this.hint = this.getAttribute("hint") ?? "";
|
113
|
+
}
|
114
|
+
firstUpdated() {
|
115
|
+
var t;
|
116
|
+
this.addEventListener("skf-select-option:select", this._handleOptionSelected), (t = this._internals.form) == null || t.addEventListener("reset", this._handleReset), this.onUpdateComplete(), this._collectSlotOptionTags(), this._validateInput();
|
117
|
+
}
|
118
|
+
updated(t) {
|
119
|
+
var e, s;
|
120
|
+
if (t.has("_expanded")) {
|
121
|
+
const o = !!t.get("_expanded") === this._expanded;
|
122
|
+
if (this.emit("skf-select:dropdown", { detail: { expanded: this._expanded } }), o) return;
|
123
|
+
this._expanded ? ((e = this.$selectBtn) == null || e.setAttribute("aria-expanded", "true"), this._managePopover().open()) : ((s = this.$selectBtn) == null || s.setAttribute("aria-expanded", "false"), this._managePopover().close());
|
124
|
+
}
|
125
|
+
}
|
126
|
+
attributeChangedCallback(t, e, s) {
|
127
|
+
if (super.attributeChangedCallback(t, e, s), t === "custom-invalid")
|
128
|
+
if (typeof s == "string") {
|
129
|
+
const a = String(s).trim() || "Custom error";
|
130
|
+
this._pristine = !1, this._invalid = !0, this.setValidity({ customError: !0 }, a), this.checkValidity();
|
131
|
+
} else
|
132
|
+
this.setValidity({}), this._validateInput();
|
133
|
+
}
|
134
|
+
disconnectedCallback() {
|
135
|
+
var t;
|
136
|
+
super.disconnectedCallback(), (t = this._internals.form) == null || t.removeEventListener("reset", this._handleReset);
|
137
|
+
}
|
138
|
+
/** @internal */
|
139
|
+
_updateState(t) {
|
140
|
+
if (this.multiple)
|
141
|
+
this._selectedOptions = [], this._optionsList.forEach((e) => {
|
142
|
+
e.selected && (this.selectedOptions = [...this.selectedOptions, e]);
|
143
|
+
});
|
144
|
+
else {
|
145
|
+
const e = this._selectedOptions.length > 0, s = t.detail.value !== null;
|
146
|
+
e && (this._selectedOptions[0].setSelectedDiscrete = !1, this._selectedOptions = []), s && (this.selectedOptions = [t.target]);
|
147
|
+
}
|
148
|
+
this._setValue();
|
149
|
+
}
|
150
|
+
/** @internal */
|
151
|
+
async onUpdateComplete() {
|
152
|
+
return await this.updateComplete, this._updateWidth(), "done";
|
153
|
+
}
|
154
|
+
/** @internal */
|
155
|
+
/** Filter out elements other than skf-select-option and store in this._optionsList */
|
156
|
+
_collectSlotOptionTags() {
|
157
|
+
this._optionsList = y(this, "skf-select-option"), this._selectedOptions = this._optionsList.filter((t) => t.selected), S({
|
158
|
+
assert: this._optionsList.length > 0,
|
159
|
+
reason: "no-children",
|
160
|
+
replaceStrings: [this.localName, "skf-select-option"]
|
161
|
+
});
|
162
|
+
}
|
163
|
+
/** @internal */
|
164
|
+
_validateInput() {
|
165
|
+
this._invalid = !1;
|
166
|
+
const t = this.required && !this.getSelectedValues.length || this.min === 1, e = !!(this.min && this.getSelectedValues.length < this.min), s = !!(this.max && this.getSelectedValues.length > this.max);
|
167
|
+
if (this._internals.validity.customError) {
|
168
|
+
this._invalid = !0;
|
169
|
+
return;
|
170
|
+
} else if (t) {
|
171
|
+
const a = this.hasAttribute("data-valuemissing") ? this.getAttribute("data-valuemissing") : "Please select an option";
|
172
|
+
this.setValidity({ valueMissing: !0 }, String(a)), this._pristine || (this._invalid = !0);
|
173
|
+
} else if (e) {
|
174
|
+
const a = this.hasAttribute("data-rangeunderflow") ? this.getAttribute("data-rangeunderflow") : `Please select minimum ${String(this.min)} options`;
|
175
|
+
this.setValidity({ rangeUnderflow: !0 }, String(a)), this._pristine || (this._invalid = !0);
|
176
|
+
} else if (s) {
|
177
|
+
const a = this.hasAttribute("data-rangeoverflow") ? this.getAttribute("data-rangeoverflow") : `Please select maximum ${String(this.max)} options`;
|
178
|
+
this.setValidity({ rangeOverflow: !0 }, String(a)), this._pristine || (this._invalid = !0);
|
179
|
+
} else
|
180
|
+
this.setValidity({}), !this._pristine && this.showValid && this.setAttribute("valid", "true");
|
181
|
+
}
|
182
|
+
render() {
|
183
|
+
return h`
|
184
|
+
<div id="select">
|
185
|
+
<label>
|
186
|
+
<div class=${this.hideLabel ? "visually-hidden" : ""} id="label">
|
187
|
+
${this.label}
|
188
|
+
${this.required ? w(this.requiredLabel) : null}
|
189
|
+
</div>
|
190
|
+
<button
|
191
|
+
?disabled=${this.disabled}
|
192
|
+
@click=${this._handleDropdownToggle}
|
193
|
+
aria-controls="select-dropdown"
|
194
|
+
aria-expanded="false"
|
195
|
+
aria-haspopup="listbox"
|
196
|
+
id="select-button"
|
197
|
+
role="combobox"
|
198
|
+
>
|
199
|
+
<span
|
200
|
+
id="selected-value"
|
201
|
+
class=${V({ "selected-value": !0, "contains-meta-info": !this.value })}>
|
202
|
+
${this._computeVisibleValue()}
|
203
|
+
</span>
|
204
|
+
<skf-icon class="arrow" name="chevronDown"></skf-icon>
|
205
|
+
</button>
|
206
|
+
</label>
|
207
|
+
<div aria-multiselectable=${m(this.multiple && !0)} id="select-dropdown" popover role="listbox">
|
208
|
+
<slot @slotchange=${this._handleSlotChange}></slot>
|
209
|
+
</div>
|
210
|
+
${!this.hideTags && this.multiple ? h`
|
211
|
+
<div id="tags">
|
212
|
+
${this.selectedOptions.map(
|
213
|
+
(t) => h`
|
214
|
+
<skf-tag
|
215
|
+
removable
|
216
|
+
.onRemove=${(e) => (e.stopPropagation(), e.preventDefault(), t.removeAttribute("selected"), !1)}
|
217
|
+
>
|
218
|
+
${t.textContent}
|
219
|
+
</skf-tag>
|
220
|
+
`
|
221
|
+
)}
|
222
|
+
</div>
|
223
|
+
` : $}
|
224
|
+
${this.hint && h`
|
225
|
+
<skf-hint
|
226
|
+
aria-live=${this._invalid ? "assertive" : "polite"}
|
227
|
+
id="hint"
|
228
|
+
severity=${m(O(this.severity, this._invalid))}
|
229
|
+
>
|
230
|
+
${this.hint}
|
231
|
+
</skf-hint>
|
232
|
+
`}
|
233
|
+
</div>
|
234
|
+
</div>
|
235
|
+
`;
|
236
|
+
}
|
237
|
+
};
|
238
|
+
c.styles = [x, P];
|
239
|
+
let i = c;
|
240
|
+
l([
|
241
|
+
r({ type: String, reflect: !0, attribute: "button-label" })
|
242
|
+
], i.prototype, "buttonLabel", 2);
|
243
|
+
l([
|
244
|
+
r({ attribute: "custom-invalid" })
|
245
|
+
], i.prototype, "customInvalid", 2);
|
246
|
+
l([
|
247
|
+
r({ type: Boolean, attribute: "hide-label" })
|
248
|
+
], i.prototype, "hideLabel", 2);
|
249
|
+
l([
|
250
|
+
r({ type: Boolean, reflect: !0, attribute: "hide-tags" })
|
251
|
+
], i.prototype, "hideTags", 2);
|
252
|
+
l([
|
253
|
+
r()
|
254
|
+
], i.prototype, "hint", 2);
|
255
|
+
l([
|
256
|
+
r({ type: Array, attribute: !1 })
|
257
|
+
], i.prototype, "getSelectedValues", 1);
|
258
|
+
l([
|
259
|
+
r({ type: Array, attribute: !1 })
|
260
|
+
], i.prototype, "getSelectedOptionsText", 1);
|
261
|
+
l([
|
262
|
+
r({ reflect: !0 })
|
263
|
+
], i.prototype, "label", 2);
|
264
|
+
l([
|
265
|
+
r({ type: Number })
|
266
|
+
], i.prototype, "max", 2);
|
267
|
+
l([
|
268
|
+
r({ type: Number })
|
269
|
+
], i.prototype, "min", 2);
|
270
|
+
l([
|
271
|
+
r({ type: Boolean, reflect: !0 })
|
272
|
+
], i.prototype, "multiple", 2);
|
273
|
+
l([
|
274
|
+
r()
|
275
|
+
], i.prototype, "name", 2);
|
276
|
+
l([
|
277
|
+
r({ attribute: "required-label" })
|
278
|
+
], i.prototype, "requiredLabel", 2);
|
279
|
+
l([
|
280
|
+
r()
|
281
|
+
], i.prototype, "severity", 2);
|
282
|
+
l([
|
283
|
+
r({ type: Boolean, attribute: "show-valid" })
|
284
|
+
], i.prototype, "showValid", 2);
|
285
|
+
l([
|
286
|
+
r({ reflect: !0 })
|
287
|
+
], i.prototype, "size", 2);
|
288
|
+
l([
|
289
|
+
d()
|
290
|
+
], i.prototype, "value", 1);
|
291
|
+
l([
|
292
|
+
d()
|
293
|
+
], i.prototype, "selectedOptions", 1);
|
294
|
+
l([
|
295
|
+
d()
|
296
|
+
], i.prototype, "_expanded", 2);
|
297
|
+
l([
|
298
|
+
d()
|
299
|
+
], i.prototype, "_invalid", 2);
|
300
|
+
l([
|
301
|
+
p("#select-button")
|
302
|
+
], i.prototype, "$selectBtn", 2);
|
303
|
+
l([
|
304
|
+
p("#selected-value")
|
305
|
+
], i.prototype, "$selectedValue", 2);
|
306
|
+
l([
|
307
|
+
p("#select-dropdown")
|
308
|
+
], i.prototype, "$dropdown", 2);
|
309
|
+
export {
|
310
|
+
i as SkfSelect
|
311
|
+
};
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import type { SkfSelectOption } from '@components/select-option/select-option.component.js';
|
2
|
+
import type { ReactiveController } from 'lit';
|
3
|
+
import type { SkfSelect } from './select.component.js';
|
4
|
+
type ControllerHost = SkfSelect;
|
5
|
+
export declare class ScrollController implements ReactiveController {
|
6
|
+
_scrollHandler?: () => void;
|
7
|
+
host?: ControllerHost;
|
8
|
+
localExpanded: boolean;
|
9
|
+
constructor(host: ControllerHost);
|
10
|
+
hostDisconnected(): void;
|
11
|
+
hostUpdated(): void;
|
12
|
+
enableScrollDetection(): void;
|
13
|
+
disableScrollDetection(): void;
|
14
|
+
/** @internal */
|
15
|
+
_onScrollOutOfView(): void;
|
16
|
+
/** @internal */
|
17
|
+
_onScrollIntoView(): void;
|
18
|
+
}
|
19
|
+
export declare class ResizeController implements ReactiveController {
|
20
|
+
host: ControllerHost;
|
21
|
+
_resizeObserver?: ResizeObserver;
|
22
|
+
constructor(host: ControllerHost);
|
23
|
+
hostConnected(): void;
|
24
|
+
hostDisconnected(): void;
|
25
|
+
enableResizeObserver(): void;
|
26
|
+
disableResizeObserver(): void;
|
27
|
+
/** @internal */
|
28
|
+
_onResize: () => void;
|
29
|
+
}
|
30
|
+
export declare class GlobalClickController implements ReactiveController {
|
31
|
+
host: ControllerHost;
|
32
|
+
constructor(host: ControllerHost);
|
33
|
+
hostDisconnected(): void;
|
34
|
+
hostUpdated(): void;
|
35
|
+
_globalClickHandler: (event: MouseEvent) => void;
|
36
|
+
enableGlobalClickDetection(): void;
|
37
|
+
disableGlobalClickDetection(): void;
|
38
|
+
}
|
39
|
+
export declare class KeyboardNavigationController implements ReactiveController {
|
40
|
+
host: ControllerHost;
|
41
|
+
_listenerActivated: boolean;
|
42
|
+
constructor(host: ControllerHost);
|
43
|
+
hostDisconnected(): void;
|
44
|
+
hostUpdated(): void;
|
45
|
+
setupKeyboardListener(): void;
|
46
|
+
removeKeyboardListener(): void;
|
47
|
+
_handleKeyDown: (event: KeyboardEvent) => void;
|
48
|
+
_focusFirstOption(): void;
|
49
|
+
_focusSiblingOption(dir: 'next' | 'prev'): void;
|
50
|
+
_selectFocusedOption(target: SkfSelectOption): void;
|
51
|
+
get _selectableOptions(): SkfSelectOption[];
|
52
|
+
}
|
53
|
+
export declare class DeveloperFeedbackController implements ReactiveController {
|
54
|
+
host: ControllerHost;
|
55
|
+
constructor(host: ControllerHost);
|
56
|
+
hostConnected(): void;
|
57
|
+
_badAttributeCombinationWarning(): void;
|
58
|
+
}
|
59
|
+
export {};
|