@politiet/sheriff-web-components 2.13.1 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +3949 -1463
- package/dist/controllers/index.d.ts +3 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +3 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/sds-drag-drop-controller.d.ts +25 -0
- package/dist/controllers/sds-drag-drop-controller.d.ts.map +1 -0
- package/dist/controllers/sds-drag-drop-controller.js +52 -0
- package/dist/controllers/sds-drag-drop-controller.js.map +1 -0
- package/dist/controllers/sds-file-preview-controller.d.ts +38 -0
- package/dist/controllers/sds-file-preview-controller.d.ts.map +1 -0
- package/dist/controllers/sds-file-preview-controller.js +90 -0
- package/dist/controllers/sds-file-preview-controller.js.map +1 -0
- package/dist/frameworks/preact.d.ts +14 -1
- package/dist/frameworks/preact.d.ts.map +1 -1
- package/dist/frameworks/react.d.ts +30 -1
- package/dist/frameworks/react.d.ts.map +1 -1
- package/dist/frameworks/solidjs.d.ts +4 -0
- package/dist/frameworks/solidjs.d.ts.map +1 -1
- package/dist/frameworks/svelte.d.ts +4 -0
- package/dist/frameworks/svelte.d.ts.map +1 -1
- package/dist/frameworks/vue.d.ts +24 -1
- package/dist/frameworks/vue.d.ts.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/react-wrappers/SDSDialogWrapper.d.ts +1 -0
- package/dist/react-wrappers/SDSDialogWrapper.d.ts.map +1 -1
- package/dist/react-wrappers/SDSDialogWrapper.js +1 -0
- package/dist/react-wrappers/SDSDialogWrapper.js.map +1 -1
- package/dist/react-wrappers/SDSFileUploadFileListWrapper.d.ts +3 -0
- package/dist/react-wrappers/SDSFileUploadFileListWrapper.d.ts.map +1 -0
- package/dist/react-wrappers/SDSFileUploadFileListWrapper.js +10 -0
- package/dist/react-wrappers/SDSFileUploadFileListWrapper.js.map +1 -0
- package/dist/react-wrappers/SDSFileUploadItemWrapper.d.ts +6 -0
- package/dist/react-wrappers/SDSFileUploadItemWrapper.d.ts.map +1 -0
- package/dist/react-wrappers/SDSFileUploadItemWrapper.js +12 -0
- package/dist/react-wrappers/SDSFileUploadItemWrapper.js.map +1 -0
- package/dist/react-wrappers/SDSFileUploadWrapper.d.ts +12 -0
- package/dist/react-wrappers/SDSFileUploadWrapper.d.ts.map +1 -0
- package/dist/react-wrappers/SDSFileUploadWrapper.js +18 -0
- package/dist/react-wrappers/SDSFileUploadWrapper.js.map +1 -0
- package/dist/react-wrappers/SDSSearchWrapper.d.ts +15 -0
- package/dist/react-wrappers/SDSSearchWrapper.d.ts.map +1 -0
- package/dist/react-wrappers/SDSSearchWrapper.js +19 -0
- package/dist/react-wrappers/SDSSearchWrapper.js.map +1 -0
- package/dist/react-wrappers/index.d.ts +4 -0
- package/dist/react-wrappers/index.d.ts.map +1 -1
- package/dist/react-wrappers/index.js +4 -0
- package/dist/react-wrappers/index.js.map +1 -1
- package/dist/sds-button/sds-button.component.d.ts +0 -1
- package/dist/sds-button/sds-button.component.d.ts.map +1 -1
- package/dist/sds-button/sds-button.component.js +10 -16
- package/dist/sds-button/sds-button.component.js.map +1 -1
- package/dist/sds-dialog/sds-dialog.component.d.ts.map +1 -1
- package/dist/sds-dialog/sds-dialog.component.js +11 -1
- package/dist/sds-dialog/sds-dialog.component.js.map +1 -1
- package/dist/sds-file-upload/sds-file-upload.d.ts +102 -0
- package/dist/sds-file-upload/sds-file-upload.d.ts.map +1 -0
- package/dist/sds-file-upload/sds-file-upload.js +384 -0
- package/dist/sds-file-upload/sds-file-upload.js.map +1 -0
- package/dist/sds-file-upload/sds-file-upload.styles.d.ts +2 -0
- package/dist/sds-file-upload/sds-file-upload.styles.d.ts.map +1 -0
- package/dist/sds-file-upload/sds-file-upload.styles.js +234 -0
- package/dist/sds-file-upload/sds-file-upload.styles.js.map +1 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.d.ts +14 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.d.ts.map +1 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.js +26 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.js.map +1 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.styles.d.ts +2 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.styles.d.ts.map +1 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.styles.js +19 -0
- package/dist/sds-file-upload-file-list/sds-file-upload-file-list.styles.js.map +1 -0
- package/dist/sds-file-upload-item/assets/u-progress.js +2 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.d.ts +62 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.d.ts.map +1 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.js +205 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.js.map +1 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.styles.d.ts +2 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.styles.d.ts.map +1 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.styles.js +227 -0
- package/dist/sds-file-upload-item/sds-file-upload-item.styles.js.map +1 -0
- package/dist/sds-search/sds-search.component.d.ts +128 -0
- package/dist/sds-search/sds-search.component.d.ts.map +1 -0
- package/dist/sds-search/sds-search.component.js +345 -0
- package/dist/sds-search/sds-search.component.js.map +1 -0
- package/dist/sds-search/sds-search.d.ts +13 -0
- package/dist/sds-search/sds-search.d.ts.map +1 -0
- package/dist/sds-search/sds-search.js +18 -0
- package/dist/sds-search/sds-search.js.map +1 -0
- package/dist/sds-search/sds-search.styles.d.ts +2 -0
- package/dist/sds-search/sds-search.styles.d.ts.map +1 -0
- package/dist/sds-search/sds-search.styles.js +74 -0
- package/dist/sds-search/sds-search.styles.js.map +1 -0
- package/dist/sds-textfield/sds-textfield.component.d.ts +4 -1
- package/dist/sds-textfield/sds-textfield.component.d.ts.map +1 -1
- package/dist/sds-textfield/sds-textfield.component.js +20 -5
- package/dist/sds-textfield/sds-textfield.component.js.map +1 -1
- package/dist/sds-textfield/sds-textfield.styles.d.ts.map +1 -1
- package/dist/sds-textfield/sds-textfield.styles.js +11 -0
- package/dist/sds-textfield/sds-textfield.styles.js.map +1 -1
- package/dist/sheriff-web-components.js +1015 -294
- package/dist/skill/SKILL.md +44 -36
- package/dist/skill/references/components.md +88 -3
- package/dist/skill/references/react-wrappers.md +25 -18
- package/dist/utils/file-validation.d.ts +31 -0
- package/dist/utils/file-validation.d.ts.map +1 -0
- package/dist/utils/file-validation.js +57 -0
- package/dist/utils/file-validation.js.map +1 -0
- package/dist/utils/format-bytes.d.ts +6 -0
- package/dist/utils/format-bytes.d.ts.map +1 -0
- package/dist/utils/format-bytes.js +13 -0
- package/dist/utils/format-bytes.js.map +1 -0
- package/dist/utils/video-thumbnail.d.ts +8 -0
- package/dist/utils/video-thumbnail.d.ts.map +1 -0
- package/dist/utils/video-thumbnail.js +77 -0
- package/dist/utils/video-thumbnail.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +24 -4
- package/web-types.json +3431 -1120
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html } from 'lit';
|
|
8
|
+
import { property, query } from 'lit/decorators.js';
|
|
9
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
10
|
+
import { SDSElement } from '../utils/sds-element';
|
|
11
|
+
import { SDSEventDispatcherMixin, SDSFormControlMixin } from '../mixins';
|
|
12
|
+
import { styles } from './sds-search.styles';
|
|
13
|
+
import '../sds-textfield/sds-textfield';
|
|
14
|
+
import '../sds-button/sds-button';
|
|
15
|
+
import '../sds-icon/sds-icon';
|
|
16
|
+
/**
|
|
17
|
+
* A search field composed of an `sds-textfield` and `sds-button`.
|
|
18
|
+
*
|
|
19
|
+
* The field uses `type="search"`, so its input exposes the `searchbox` role and
|
|
20
|
+
* assistive technology announces it as a search field.
|
|
21
|
+
*
|
|
22
|
+
* The element is form-associated. Its `name` and value are submitted with the
|
|
23
|
+
* surrounding `<form>`, and the form's reset restores the initial value.
|
|
24
|
+
* `required`, `minlength`, `maxlength` and `pattern` are forwarded to the inner input, and its
|
|
25
|
+
* validity is mirrored on the host, so the field takes part in form validation like a native input.
|
|
26
|
+
*
|
|
27
|
+
* Emits a cancelable `search` event (detail: `{ value }`) when the button is
|
|
28
|
+
* pressed or the user presses Enter while the field is focused. Like a form's `submit`
|
|
29
|
+
* event, it is only emitted once the field passes validation (unless the form has
|
|
30
|
+
* `novalidate`). Unless the event is cancelled, the surrounding form (if any) is then submitted.
|
|
31
|
+
*
|
|
32
|
+
* A custom action control can be supplied through the `button` slot.
|
|
33
|
+
* A slotted control owns its own behaviour (click, `disabled`, form submission);
|
|
34
|
+
* Enter in the field still emits `search` and submits the form.
|
|
35
|
+
*
|
|
36
|
+
* @fires search - `CustomEvent<SDSSearchDetail>` on submit. Cancel it to prevent form submission.
|
|
37
|
+
* @fires input - When the value of the field changes.
|
|
38
|
+
* @fires change - When the value of the field has changed and the field loses focus.
|
|
39
|
+
* @fires select - When text in the field is selected.
|
|
40
|
+
* @fires keydown - `KeyboardEvent` on key presses in the field. Cancelling Enter prevents `search`.
|
|
41
|
+
* @fires focus - `FocusEvent` when focus moves into the component. Moving between the field and the button does not fire.
|
|
42
|
+
* @fires blur - `FocusEvent` when focus leaves the component. Moving between the field and the button does not fire.
|
|
43
|
+
* @fires invalid - When `checkValidity()`, `reportValidity()` or form submission finds the field invalid.
|
|
44
|
+
* @slot label - Rich content for the field's label. Takes precedence over the `label` property.
|
|
45
|
+
* @slot button - Optional replacement for the default icon button.
|
|
46
|
+
*/
|
|
47
|
+
export class SDSSearchComponent extends SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement)) {
|
|
48
|
+
constructor() {
|
|
49
|
+
super();
|
|
50
|
+
this.value = '';
|
|
51
|
+
/** Hides the label visually while keeping it as the field's accessible name. */
|
|
52
|
+
this.hideLabel = false;
|
|
53
|
+
this.size = 'md';
|
|
54
|
+
this.buttonLabel = 'Søk';
|
|
55
|
+
this.buttonVariant = 'primary';
|
|
56
|
+
this.required = false;
|
|
57
|
+
this._defaultValue = '';
|
|
58
|
+
this._customValidityMessage = '';
|
|
59
|
+
// The browser does not dispatch focusin/focusout on the host
|
|
60
|
+
// when focus moves within the shadow tree.
|
|
61
|
+
// `relatedTarget` is set to the host when it moves to/from slotted content.
|
|
62
|
+
this._handleFocusIn = (event) => {
|
|
63
|
+
if (!this._isOwnNode(event.relatedTarget)) {
|
|
64
|
+
this.dispatchEvent(new FocusEvent('focus', { composed: true, relatedTarget: event.relatedTarget }));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
this._handleFocusOut = (event) => {
|
|
68
|
+
if (!this._isOwnNode(event.relatedTarget)) {
|
|
69
|
+
this.dispatchEvent(new FocusEvent('blur', { composed: true, relatedTarget: event.relatedTarget }));
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/** Stops `focus`/`blur` from the inner controls, both synthetic and native. The host emits its own. */
|
|
73
|
+
this._stopChildEvent = (event) => {
|
|
74
|
+
event.stopImmediatePropagation();
|
|
75
|
+
};
|
|
76
|
+
this._reemitChildEvent = (event) => {
|
|
77
|
+
event.stopImmediatePropagation();
|
|
78
|
+
this.dispatchSheriffEvent(event.type);
|
|
79
|
+
};
|
|
80
|
+
this._handleInput = (event) => {
|
|
81
|
+
event.stopImmediatePropagation();
|
|
82
|
+
// Synced before re-emitting so `event.target.value` is current in listeners, like native `input`.
|
|
83
|
+
const target = event.target;
|
|
84
|
+
if (!!target && 'value' in target && typeof target.value === 'string') {
|
|
85
|
+
this.value = target.value;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.value = '';
|
|
89
|
+
}
|
|
90
|
+
this.updateValidity();
|
|
91
|
+
this.dispatchSheriffEvent('input');
|
|
92
|
+
};
|
|
93
|
+
this._handleButtonClick = () => {
|
|
94
|
+
this._submit();
|
|
95
|
+
};
|
|
96
|
+
this._handleKeydown = (event) => {
|
|
97
|
+
event.stopImmediatePropagation();
|
|
98
|
+
// Cancelling the re-emitted event also cancels the textfield's, so neither submits.
|
|
99
|
+
if (!this.dispatchKeyboardEvent('keydown', event)) {
|
|
100
|
+
event.preventDefault();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Enter that confirms an IME composition is not a submit, matching native implicit submission.
|
|
104
|
+
if (event.key !== 'Enter' || event.isComposing) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Suppress the textfield's own Enter handling so `search` fires once.
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
this._submit();
|
|
110
|
+
};
|
|
111
|
+
this.addEventListener('focusin', this._handleFocusIn);
|
|
112
|
+
this.addEventListener('focusout', this._handleFocusOut);
|
|
113
|
+
}
|
|
114
|
+
connectedCallback() {
|
|
115
|
+
super.connectedCallback();
|
|
116
|
+
this._defaultValue = this.value;
|
|
117
|
+
this.internals.setFormValue(this.value);
|
|
118
|
+
// Re-align when the field reflows (e.g. help text wraps on narrow widths).
|
|
119
|
+
const resizeObserver = new ResizeObserver(() => this._alignButtonToInput());
|
|
120
|
+
this._resizeObserver = resizeObserver;
|
|
121
|
+
void this.updateComplete.then(() => {
|
|
122
|
+
if (this._resizeObserver === resizeObserver && this._field) {
|
|
123
|
+
resizeObserver.observe(this._field);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
disconnectedCallback() {
|
|
128
|
+
super.disconnectedCallback();
|
|
129
|
+
this._resizeObserver?.disconnect();
|
|
130
|
+
this._resizeObserver = undefined;
|
|
131
|
+
}
|
|
132
|
+
updated(changedProperties) {
|
|
133
|
+
super.updated(changedProperties);
|
|
134
|
+
if (changedProperties.has('value')) {
|
|
135
|
+
this.internals.setFormValue(this.value);
|
|
136
|
+
}
|
|
137
|
+
// The inner input applies new constraints and values when the textfield renders.
|
|
138
|
+
void this._field?.updateComplete.then(() => this.updateValidity());
|
|
139
|
+
const onlyValueChanged = changedProperties.size === 1 && changedProperties.has('value');
|
|
140
|
+
if (onlyValueChanged) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this._alignButtonToInput();
|
|
144
|
+
}
|
|
145
|
+
/** Mirrors the inner input's validity on the host, which is the element the form validates. */
|
|
146
|
+
updateValidity() {
|
|
147
|
+
const field = this._field;
|
|
148
|
+
const control = field?.control;
|
|
149
|
+
if (!field || !control) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
field.setCustomValidity(this._customValidityMessage);
|
|
153
|
+
this.internals.setValidity(control.validity, control.validationMessage, control);
|
|
154
|
+
}
|
|
155
|
+
get validity() {
|
|
156
|
+
return this.internals.validity;
|
|
157
|
+
}
|
|
158
|
+
get validationMessage() {
|
|
159
|
+
return this.internals.validationMessage;
|
|
160
|
+
}
|
|
161
|
+
get willValidate() {
|
|
162
|
+
return this.internals.willValidate;
|
|
163
|
+
}
|
|
164
|
+
checkValidity() {
|
|
165
|
+
return this.internals.checkValidity();
|
|
166
|
+
}
|
|
167
|
+
reportValidity() {
|
|
168
|
+
return this.internals.reportValidity();
|
|
169
|
+
}
|
|
170
|
+
setCustomValidity(message) {
|
|
171
|
+
this._customValidityMessage = message;
|
|
172
|
+
this.updateValidity();
|
|
173
|
+
}
|
|
174
|
+
select() {
|
|
175
|
+
this._field?.select();
|
|
176
|
+
}
|
|
177
|
+
get selectionStart() {
|
|
178
|
+
return this._field?.selectionStart ?? null;
|
|
179
|
+
}
|
|
180
|
+
set selectionStart(value) {
|
|
181
|
+
if (this._field) {
|
|
182
|
+
this._field.selectionStart = value;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
get selectionEnd() {
|
|
186
|
+
return this._field?.selectionEnd ?? null;
|
|
187
|
+
}
|
|
188
|
+
set selectionEnd(value) {
|
|
189
|
+
if (this._field) {
|
|
190
|
+
this._field.selectionEnd = value;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
setSelectionRange(start, end, direction) {
|
|
194
|
+
this._field?.setSelectionRange(start, end, direction);
|
|
195
|
+
}
|
|
196
|
+
formResetCallback() {
|
|
197
|
+
this.value = this._defaultValue;
|
|
198
|
+
}
|
|
199
|
+
formStateRestoreCallback(state) {
|
|
200
|
+
if (typeof state === 'string') {
|
|
201
|
+
this.value = state;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Keeps the button aligned with the input row regardless of a stacked label,
|
|
206
|
+
* help text (including when it wraps) or an error message below the input, by
|
|
207
|
+
* shifting the button down by the input's offset within the field.
|
|
208
|
+
*/
|
|
209
|
+
async _alignButtonToInput() {
|
|
210
|
+
const field = this._field;
|
|
211
|
+
const buttonCol = this._buttonCol;
|
|
212
|
+
if (!field || !buttonCol) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
await field.updateComplete;
|
|
216
|
+
const input = field.control;
|
|
217
|
+
if (!input) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const offset = input.getBoundingClientRect().top - field.getBoundingClientRect().top;
|
|
221
|
+
buttonCol.style.marginBlockStart = offset > 0 ? `${offset}px` : '';
|
|
222
|
+
}
|
|
223
|
+
/** Emits `search` and, unless it is cancelled, submits the surrounding form. */
|
|
224
|
+
_submit() {
|
|
225
|
+
if (this.disabled) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// Like a form's `submit` event, `search` only fires for a valid field. `novalidate` opts out, as for the form.
|
|
229
|
+
if (!this.form?.noValidate && !this.reportValidity()) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const shouldContinue = this.dispatchSheriffEvent('search', { value: this.value });
|
|
233
|
+
if (shouldContinue) {
|
|
234
|
+
this.form?.requestSubmit();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** Whether `node` is the host, its light DOM content or part of its shadow tree. */
|
|
238
|
+
_isOwnNode(node) {
|
|
239
|
+
return node instanceof Node && (node === this || this.contains(node) || Boolean(this.shadowRoot?.contains(node)));
|
|
240
|
+
}
|
|
241
|
+
_renderField() {
|
|
242
|
+
return html `
|
|
243
|
+
<sds-textfield
|
|
244
|
+
class="sds-search__field"
|
|
245
|
+
type="search"
|
|
246
|
+
size="${this.size ?? 'md'}"
|
|
247
|
+
.value="${this.value}"
|
|
248
|
+
?hide-label="${this.hideLabel}"
|
|
249
|
+
placeholder="${ifDefined(this.placeholder)}"
|
|
250
|
+
help-text="${ifDefined(this.helpText)}"
|
|
251
|
+
error-message="${ifDefined(this.errorMessage)}"
|
|
252
|
+
?disabled="${this.disabled}"
|
|
253
|
+
?readonly="${this.readOnly}"
|
|
254
|
+
autocomplete="${ifDefined(this.autocomplete)}"
|
|
255
|
+
?required="${this.required}"
|
|
256
|
+
minlength="${ifDefined(this.minlength)}"
|
|
257
|
+
maxlength="${ifDefined(this.maxlength)}"
|
|
258
|
+
pattern="${ifDefined(this.pattern)}"
|
|
259
|
+
@input="${this._handleInput}"
|
|
260
|
+
@change="${this._reemitChildEvent}"
|
|
261
|
+
@select="${this._reemitChildEvent}"
|
|
262
|
+
@keydown="${this._handleKeydown}"
|
|
263
|
+
@focus="${this._stopChildEvent}"
|
|
264
|
+
@blur="${this._stopChildEvent}"
|
|
265
|
+
>
|
|
266
|
+
<slot name="label" slot="label">${this.label}</slot>
|
|
267
|
+
</sds-textfield>
|
|
268
|
+
`;
|
|
269
|
+
}
|
|
270
|
+
_renderButtonColumn() {
|
|
271
|
+
return html `
|
|
272
|
+
<div class="sds-search__button-col">
|
|
273
|
+
<slot name="button">
|
|
274
|
+
<sds-button
|
|
275
|
+
class="sds-search__button"
|
|
276
|
+
icon
|
|
277
|
+
type="button"
|
|
278
|
+
size="${this.size ?? 'md'}"
|
|
279
|
+
variant="${this.buttonVariant}"
|
|
280
|
+
label="${this.buttonLabel}"
|
|
281
|
+
?disabled="${this.disabled}"
|
|
282
|
+
@click="${this._handleButtonClick}"
|
|
283
|
+
@focus="${this._stopChildEvent}"
|
|
284
|
+
@blur="${this._stopChildEvent}"
|
|
285
|
+
>
|
|
286
|
+
<sds-icon name="search-material-outlined" size="${this.size}"></sds-icon>
|
|
287
|
+
</sds-button>
|
|
288
|
+
</slot>
|
|
289
|
+
</div>
|
|
290
|
+
`;
|
|
291
|
+
}
|
|
292
|
+
render() {
|
|
293
|
+
return html `<div class="sds-search">${this._renderField()} ${this._renderButtonColumn()}</div>`;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
SDSSearchComponent.styles = [styles];
|
|
297
|
+
__decorate([
|
|
298
|
+
property({ type: String })
|
|
299
|
+
], SDSSearchComponent.prototype, "value", void 0);
|
|
300
|
+
__decorate([
|
|
301
|
+
property({ type: String, reflect: true })
|
|
302
|
+
], SDSSearchComponent.prototype, "label", void 0);
|
|
303
|
+
__decorate([
|
|
304
|
+
property({ type: Boolean, attribute: 'hide-label', reflect: true })
|
|
305
|
+
], SDSSearchComponent.prototype, "hideLabel", void 0);
|
|
306
|
+
__decorate([
|
|
307
|
+
property({ type: String, reflect: true })
|
|
308
|
+
], SDSSearchComponent.prototype, "placeholder", void 0);
|
|
309
|
+
__decorate([
|
|
310
|
+
property({ type: String, attribute: 'help-text', reflect: true })
|
|
311
|
+
], SDSSearchComponent.prototype, "helpText", void 0);
|
|
312
|
+
__decorate([
|
|
313
|
+
property({ type: String, attribute: 'error-message', reflect: true })
|
|
314
|
+
], SDSSearchComponent.prototype, "errorMessage", void 0);
|
|
315
|
+
__decorate([
|
|
316
|
+
property({ type: String, reflect: true })
|
|
317
|
+
], SDSSearchComponent.prototype, "size", void 0);
|
|
318
|
+
__decorate([
|
|
319
|
+
property({ type: String, attribute: 'button-label', reflect: true })
|
|
320
|
+
], SDSSearchComponent.prototype, "buttonLabel", void 0);
|
|
321
|
+
__decorate([
|
|
322
|
+
property({ type: String, attribute: 'button-variant', reflect: true })
|
|
323
|
+
], SDSSearchComponent.prototype, "buttonVariant", void 0);
|
|
324
|
+
__decorate([
|
|
325
|
+
property({ type: String, reflect: true })
|
|
326
|
+
], SDSSearchComponent.prototype, "autocomplete", void 0);
|
|
327
|
+
__decorate([
|
|
328
|
+
property({ type: Boolean, reflect: true })
|
|
329
|
+
], SDSSearchComponent.prototype, "required", void 0);
|
|
330
|
+
__decorate([
|
|
331
|
+
property({ type: Number, reflect: true })
|
|
332
|
+
], SDSSearchComponent.prototype, "minlength", void 0);
|
|
333
|
+
__decorate([
|
|
334
|
+
property({ type: Number, reflect: true })
|
|
335
|
+
], SDSSearchComponent.prototype, "maxlength", void 0);
|
|
336
|
+
__decorate([
|
|
337
|
+
property({ type: String, reflect: true })
|
|
338
|
+
], SDSSearchComponent.prototype, "pattern", void 0);
|
|
339
|
+
__decorate([
|
|
340
|
+
query('.sds-search__field')
|
|
341
|
+
], SDSSearchComponent.prototype, "_field", void 0);
|
|
342
|
+
__decorate([
|
|
343
|
+
query('.sds-search__button-col')
|
|
344
|
+
], SDSSearchComponent.prototype, "_buttonCol", void 0);
|
|
345
|
+
//# sourceMappingURL=sds-search.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sds-search.component.js","sourceRoot":"","sources":["../../src/sds-search/sds-search.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, PropertyValues } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { SDSElement } from '../utils/sds-element';\nimport { SDSEventDispatcherMixin, SDSFormControlMixin } from '../mixins';\nimport type { SDSFormControlAttributes } from '../mixins/sds-form-control-mixin';\nimport { styles } from './sds-search.styles';\nimport { SDS_SIZES, SDS_VARIANTS } from '../types';\n\nimport '../sds-textfield/sds-textfield';\nimport type { SDSTextField, SDSTextFieldProps } from '../sds-textfield/sds-textfield';\nimport '../sds-button/sds-button';\nimport '../sds-icon/sds-icon';\n\ntype SearchSize = Extract<SDS_SIZES, 'lg' | 'md' | 'sm'>;\ntype ButtonVariant = SDS_VARIANTS;\n\n/** Detail payload dispatched with the `search` event. */\nexport interface SDSSearchDetail {\n\tvalue: string;\n}\n\nexport interface SDSSearchProps extends SDSFormControlAttributes {\n\tvalue?: string;\n\tlabel?: string;\n\t'hide-label'?: boolean;\n\tplaceholder?: string;\n\t'help-text'?: string;\n\t'error-message'?: string;\n\tsize?: SearchSize;\n\t'button-label'?: string;\n\t'button-variant'?: ButtonVariant;\n\tautocomplete?: SDSTextFieldProps['autocomplete'];\n\trequired?: boolean;\n\tminlength?: number;\n\tmaxlength?: number;\n\tpattern?: string;\n}\n\n/**\n * A search field composed of an `sds-textfield` and `sds-button`.\n *\n * The field uses `type=\"search\"`, so its input exposes the `searchbox` role and\n * assistive technology announces it as a search field.\n *\n * The element is form-associated. Its `name` and value are submitted with the\n * surrounding `<form>`, and the form's reset restores the initial value.\n * `required`, `minlength`, `maxlength` and `pattern` are forwarded to the inner input, and its\n * validity is mirrored on the host, so the field takes part in form validation like a native input.\n *\n * Emits a cancelable `search` event (detail: `{ value }`) when the button is\n * pressed or the user presses Enter while the field is focused. Like a form's `submit`\n * event, it is only emitted once the field passes validation (unless the form has\n * `novalidate`). Unless the event is cancelled, the surrounding form (if any) is then submitted.\n *\n * A custom action control can be supplied through the `button` slot.\n * A slotted control owns its own behaviour (click, `disabled`, form submission);\n * Enter in the field still emits `search` and submits the form.\n *\n * @fires search - `CustomEvent<SDSSearchDetail>` on submit. Cancel it to prevent form submission.\n * @fires input - When the value of the field changes.\n * @fires change - When the value of the field has changed and the field loses focus.\n * @fires select - When text in the field is selected.\n * @fires keydown - `KeyboardEvent` on key presses in the field. Cancelling Enter prevents `search`.\n * @fires focus - `FocusEvent` when focus moves into the component. Moving between the field and the button does not fire.\n * @fires blur - `FocusEvent` when focus leaves the component. Moving between the field and the button does not fire.\n * @fires invalid - When `checkValidity()`, `reportValidity()` or form submission finds the field invalid.\n * @slot label - Rich content for the field's label. Takes precedence over the `label` property.\n * @slot button - Optional replacement for the default icon button.\n */\nexport class SDSSearchComponent extends SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement)) {\n\tstatic override styles = [styles];\n\n\t@property({ type: String }) value: string = '';\n\t@property({ type: String, reflect: true }) label?: string;\n\t/** Hides the label visually while keeping it as the field's accessible name. */\n\t@property({ type: Boolean, attribute: 'hide-label', reflect: true })\n\thideLabel: boolean = false;\n\t@property({ type: String, reflect: true }) placeholder?: string;\n\t@property({ type: String, attribute: 'help-text', reflect: true })\n\thelpText?: string;\n\t@property({ type: String, attribute: 'error-message', reflect: true })\n\terrorMessage?: string;\n\t@property({ type: String, reflect: true }) size: SearchSize = 'md';\n\t@property({ type: String, attribute: 'button-label', reflect: true })\n\tbuttonLabel: string = 'Søk';\n\t@property({ type: String, attribute: 'button-variant', reflect: true })\n\tbuttonVariant: ButtonVariant = 'primary';\n\t@property({ type: String, reflect: true }) autocomplete?: SDSSearchProps['autocomplete'];\n\t@property({ type: Boolean, reflect: true }) required: boolean = false;\n\t@property({ type: Number, reflect: true }) minlength?: number;\n\t@property({ type: Number, reflect: true }) maxlength?: number;\n\t@property({ type: String, reflect: true }) pattern?: string;\n\n\t@query('.sds-search__field') private _field?: SDSTextField;\n\t@query('.sds-search__button-col') private _buttonCol?: HTMLElement;\n\n\tprivate _resizeObserver?: ResizeObserver;\n\tprivate _defaultValue = '';\n\tprivate _customValidityMessage = '';\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.addEventListener('focusin', this._handleFocusIn);\n\t\tthis.addEventListener('focusout', this._handleFocusOut);\n\t}\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tthis._defaultValue = this.value;\n\t\tthis.internals.setFormValue(this.value);\n\t\t// Re-align when the field reflows (e.g. help text wraps on narrow widths).\n\t\tconst resizeObserver = new ResizeObserver(() => this._alignButtonToInput());\n\t\tthis._resizeObserver = resizeObserver;\n\t\tvoid this.updateComplete.then(() => {\n\t\t\tif (this._resizeObserver === resizeObserver && this._field) {\n\t\t\t\tresizeObserver.observe(this._field);\n\t\t\t}\n\t\t});\n\t}\n\n\toverride disconnectedCallback(): void {\n\t\tsuper.disconnectedCallback();\n\t\tthis._resizeObserver?.disconnect();\n\t\tthis._resizeObserver = undefined;\n\t}\n\n\toverride updated(changedProperties: PropertyValues): void {\n\t\tsuper.updated(changedProperties);\n\t\tif (changedProperties.has('value')) {\n\t\t\tthis.internals.setFormValue(this.value);\n\t\t}\n\t\t// The inner input applies new constraints and values when the textfield renders.\n\t\tvoid this._field?.updateComplete.then(() => this.updateValidity());\n\t\tconst onlyValueChanged = changedProperties.size === 1 && changedProperties.has('value');\n\t\tif (onlyValueChanged) {\n\t\t\treturn;\n\t\t}\n\t\tthis._alignButtonToInput();\n\t}\n\n\t/** Mirrors the inner input's validity on the host, which is the element the form validates. */\n\toverride updateValidity(): void {\n\t\tconst field = this._field;\n\t\tconst control = field?.control;\n\t\tif (!field || !control) {\n\t\t\treturn;\n\t\t}\n\t\tfield.setCustomValidity(this._customValidityMessage);\n\t\tthis.internals.setValidity(control.validity, control.validationMessage, control);\n\t}\n\n\tget validity(): ValidityState {\n\t\treturn this.internals.validity;\n\t}\n\n\tget validationMessage(): string {\n\t\treturn this.internals.validationMessage;\n\t}\n\n\tget willValidate(): boolean {\n\t\treturn this.internals.willValidate;\n\t}\n\n\tcheckValidity(): boolean {\n\t\treturn this.internals.checkValidity();\n\t}\n\n\treportValidity(): boolean {\n\t\treturn this.internals.reportValidity();\n\t}\n\n\tsetCustomValidity(message: string): void {\n\t\tthis._customValidityMessage = message;\n\t\tthis.updateValidity();\n\t}\n\n\tselect(): void {\n\t\tthis._field?.select();\n\t}\n\n\tget selectionStart(): number | null {\n\t\treturn this._field?.selectionStart ?? null;\n\t}\n\n\tset selectionStart(value: number | null) {\n\t\tif (this._field) {\n\t\t\tthis._field.selectionStart = value;\n\t\t}\n\t}\n\n\tget selectionEnd(): number | null {\n\t\treturn this._field?.selectionEnd ?? null;\n\t}\n\n\tset selectionEnd(value: number | null) {\n\t\tif (this._field) {\n\t\t\tthis._field.selectionEnd = value;\n\t\t}\n\t}\n\n\tsetSelectionRange(start: number, end: number, direction?: 'forward' | 'backward' | 'none'): void {\n\t\tthis._field?.setSelectionRange(start, end, direction);\n\t}\n\n\tformResetCallback(): void {\n\t\tthis.value = this._defaultValue;\n\t}\n\n\tformStateRestoreCallback(state: string | File | FormData | null): void {\n\t\tif (typeof state === 'string') {\n\t\t\tthis.value = state;\n\t\t}\n\t}\n\n\t/**\n\t * Keeps the button aligned with the input row regardless of a stacked label,\n\t * help text (including when it wraps) or an error message below the input, by\n\t * shifting the button down by the input's offset within the field.\n\t */\n\tprivate async _alignButtonToInput(): Promise<void> {\n\t\tconst field = this._field;\n\t\tconst buttonCol = this._buttonCol;\n\t\tif (!field || !buttonCol) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait field.updateComplete;\n\n\t\tconst input = field.control;\n\t\tif (!input) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst offset = input.getBoundingClientRect().top - field.getBoundingClientRect().top;\n\t\tbuttonCol.style.marginBlockStart = offset > 0 ? `${offset}px` : '';\n\t}\n\n\t/** Emits `search` and, unless it is cancelled, submits the surrounding form. */\n\tprivate _submit(): void {\n\t\tif (this.disabled) {\n\t\t\treturn;\n\t\t}\n\t\t// Like a form's `submit` event, `search` only fires for a valid field. `novalidate` opts out, as for the form.\n\t\tif (!this.form?.noValidate && !this.reportValidity()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst shouldContinue = this.dispatchSheriffEvent<SDSSearchDetail>('search', { value: this.value });\n\t\tif (shouldContinue) {\n\t\t\tthis.form?.requestSubmit();\n\t\t}\n\t}\n\n\t/** Whether `node` is the host, its light DOM content or part of its shadow tree. */\n\tprivate _isOwnNode(node: EventTarget | null): boolean {\n\t\treturn node instanceof Node && (node === this || this.contains(node) || Boolean(this.shadowRoot?.contains(node)));\n\t}\n\n\t// The browser does not dispatch focusin/focusout on the host\n\t// when focus moves within the shadow tree.\n\t// `relatedTarget` is set to the host when it moves to/from slotted content.\n\tprivate readonly _handleFocusIn = (event: FocusEvent) => {\n\t\tif (!this._isOwnNode(event.relatedTarget)) {\n\t\t\tthis.dispatchEvent(new FocusEvent('focus', { composed: true, relatedTarget: event.relatedTarget }));\n\t\t}\n\t};\n\n\tprivate readonly _handleFocusOut = (event: FocusEvent) => {\n\t\tif (!this._isOwnNode(event.relatedTarget)) {\n\t\t\tthis.dispatchEvent(new FocusEvent('blur', { composed: true, relatedTarget: event.relatedTarget }));\n\t\t}\n\t};\n\n\t/** Stops `focus`/`blur` from the inner controls, both synthetic and native. The host emits its own. */\n\tprivate readonly _stopChildEvent = (event: Event) => {\n\t\tevent.stopImmediatePropagation();\n\t};\n\n\tprivate readonly _reemitChildEvent = (event: Event) => {\n\t\tevent.stopImmediatePropagation();\n\t\tthis.dispatchSheriffEvent(event.type);\n\t};\n\n\tprivate readonly _handleInput = (event: Event) => {\n\t\tevent.stopImmediatePropagation();\n\t\t// Synced before re-emitting so `event.target.value` is current in listeners, like native `input`.\n\t\tconst target = event.target;\n\t\tif (!!target && 'value' in target && typeof target.value === 'string') {\n\t\t\tthis.value = target.value;\n\t\t} else {\n\t\t\tthis.value = '';\n\t\t}\n\t\tthis.updateValidity();\n\t\tthis.dispatchSheriffEvent('input');\n\t};\n\n\tprivate readonly _handleButtonClick = () => {\n\t\tthis._submit();\n\t};\n\n\tprivate readonly _handleKeydown = (event: KeyboardEvent) => {\n\t\tevent.stopImmediatePropagation();\n\t\t// Cancelling the re-emitted event also cancels the textfield's, so neither submits.\n\t\tif (!this.dispatchKeyboardEvent('keydown', event)) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\t\t// Enter that confirms an IME composition is not a submit, matching native implicit submission.\n\t\tif (event.key !== 'Enter' || event.isComposing) {\n\t\t\treturn;\n\t\t}\n\t\t// Suppress the textfield's own Enter handling so `search` fires once.\n\t\tevent.preventDefault();\n\t\tthis._submit();\n\t};\n\n\tprivate _renderField() {\n\t\treturn html`\n\t\t\t<sds-textfield\n\t\t\t\tclass=\"sds-search__field\"\n\t\t\t\ttype=\"search\"\n\t\t\t\tsize=\"${this.size ?? 'md'}\"\n\t\t\t\t.value=\"${this.value}\"\n\t\t\t\t?hide-label=\"${this.hideLabel}\"\n\t\t\t\tplaceholder=\"${ifDefined(this.placeholder)}\"\n\t\t\t\thelp-text=\"${ifDefined(this.helpText)}\"\n\t\t\t\terror-message=\"${ifDefined(this.errorMessage)}\"\n\t\t\t\t?disabled=\"${this.disabled}\"\n\t\t\t\t?readonly=\"${this.readOnly}\"\n\t\t\t\tautocomplete=\"${ifDefined(this.autocomplete)}\"\n\t\t\t\t?required=\"${this.required}\"\n\t\t\t\tminlength=\"${ifDefined(this.minlength)}\"\n\t\t\t\tmaxlength=\"${ifDefined(this.maxlength)}\"\n\t\t\t\tpattern=\"${ifDefined(this.pattern)}\"\n\t\t\t\t@input=\"${this._handleInput}\"\n\t\t\t\t@change=\"${this._reemitChildEvent}\"\n\t\t\t\t@select=\"${this._reemitChildEvent}\"\n\t\t\t\t@keydown=\"${this._handleKeydown}\"\n\t\t\t\t@focus=\"${this._stopChildEvent}\"\n\t\t\t\t@blur=\"${this._stopChildEvent}\"\n\t\t\t>\n\t\t\t\t<slot name=\"label\" slot=\"label\">${this.label}</slot>\n\t\t\t</sds-textfield>\n\t\t`;\n\t}\n\n\tprivate _renderButtonColumn() {\n\t\treturn html`\n\t\t\t<div class=\"sds-search__button-col\">\n\t\t\t\t<slot name=\"button\">\n\t\t\t\t\t<sds-button\n\t\t\t\t\t\tclass=\"sds-search__button\"\n\t\t\t\t\t\ticon\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"${this.size ?? 'md'}\"\n\t\t\t\t\t\tvariant=\"${this.buttonVariant}\"\n\t\t\t\t\t\tlabel=\"${this.buttonLabel}\"\n\t\t\t\t\t\t?disabled=\"${this.disabled}\"\n\t\t\t\t\t\t@click=\"${this._handleButtonClick}\"\n\t\t\t\t\t\t@focus=\"${this._stopChildEvent}\"\n\t\t\t\t\t\t@blur=\"${this._stopChildEvent}\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<sds-icon name=\"search-material-outlined\" size=\"${this.size}\"></sds-icon>\n\t\t\t\t\t</sds-button>\n\t\t\t\t</slot>\n\t\t\t</div>\n\t\t`;\n\t}\n\n\toverride render() {\n\t\treturn html`<div class=\"sds-search\">${this._renderField()} ${this._renderButtonColumn()}</div>`;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SDSSearchComponent } from './sds-search.component';
|
|
2
|
+
import '../sds-textfield/sds-textfield';
|
|
3
|
+
import '../sds-button/sds-button';
|
|
4
|
+
import '../sds-icon/sds-icon';
|
|
5
|
+
export type { SDSSearchProps, SDSSearchDetail } from './sds-search.component';
|
|
6
|
+
export declare class SDSSearch extends SDSSearchComponent {
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
'sds-search': SDSSearch;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=sds-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sds-search.d.ts","sourceRoot":"","sources":["../../src/sds-search/sds-search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,gCAAgC,CAAC;AACxC,OAAO,0BAA0B,CAAC;AAClC,OAAO,sBAAsB,CAAC;AAE9B,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9E,qBACa,SAAU,SAAQ,kBAAkB;CAAG;AAEpD,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,YAAY,EAAE,SAAS,CAAC;KACxB;CACD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { guardedCustomElement } from '../utils/guarded-custom-element';
|
|
8
|
+
import { SDSSearchComponent } from './sds-search.component';
|
|
9
|
+
import '../sds-textfield/sds-textfield';
|
|
10
|
+
import '../sds-button/sds-button';
|
|
11
|
+
import '../sds-icon/sds-icon';
|
|
12
|
+
let SDSSearch = class SDSSearch extends SDSSearchComponent {
|
|
13
|
+
};
|
|
14
|
+
SDSSearch = __decorate([
|
|
15
|
+
guardedCustomElement('sds-search')
|
|
16
|
+
], SDSSearch);
|
|
17
|
+
export { SDSSearch };
|
|
18
|
+
//# sourceMappingURL=sds-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sds-search.js","sourceRoot":"","sources":["../../src/sds-search/sds-search.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,gCAAgC,CAAC;AACxC,OAAO,0BAA0B,CAAC;AAClC,OAAO,sBAAsB,CAAC;AAKvB,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,kBAAkB;CAAG,CAAA;AAAvC,SAAS;IADrB,oBAAoB,CAAC,YAAY,CAAC;GACtB,SAAS,CAA8B","sourcesContent":["import { guardedCustomElement } from '../utils/guarded-custom-element';\nimport { SDSSearchComponent } from './sds-search.component';\n\nimport '../sds-textfield/sds-textfield';\nimport '../sds-button/sds-button';\nimport '../sds-icon/sds-icon';\n\nexport type { SDSSearchProps, SDSSearchDetail } from './sds-search.component';\n\n@guardedCustomElement('sds-search')\nexport class SDSSearch extends SDSSearchComponent {}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sds-search': SDSSearch;\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sds-search.styles.d.ts","sourceRoot":"","sources":["../../src/sds-search/sds-search.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAuElB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
/*
|
|
4
|
+
* The search controls radius and border of inner button and textfield.
|
|
5
|
+
*/
|
|
6
|
+
:host {
|
|
7
|
+
--_sds-search-radius: var(--sds-search-radius, var(--sds-radius-sm));
|
|
8
|
+
--_sds-search-border-width: var(--sds-search-border-width, var(--sds-border-sm));
|
|
9
|
+
|
|
10
|
+
display: block;
|
|
11
|
+
text-align: start;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.sds-search {
|
|
15
|
+
display: flex;
|
|
16
|
+
/* Align to the top; the button is nudged down to the input row in JS so a
|
|
17
|
+
stacked label, help text, or an error message never drags it out of line. */
|
|
18
|
+
align-items: flex-start;
|
|
19
|
+
inline-size: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* The field keeps its rounded corners on the inline-start side and squares the
|
|
24
|
+
* edge that meets the button; the button mirrors it.
|
|
25
|
+
*/
|
|
26
|
+
.sds-search__field {
|
|
27
|
+
flex: 1 1 auto;
|
|
28
|
+
/* Allow the field to shrink below its intrinsic min-width inside flex. */
|
|
29
|
+
min-inline-size: 0;
|
|
30
|
+
/* Let the surrounding container govern the width instead of the
|
|
31
|
+
textfield's default 60ch cap. */
|
|
32
|
+
--sds-textfield-input-max-width: none;
|
|
33
|
+
--sds-textfield-border-width: var(--_sds-search-border-width);
|
|
34
|
+
--sds-textfield-border-radius: var(--_sds-search-radius) 0 0 var(--_sds-search-radius);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.sds-search__button,
|
|
38
|
+
::slotted([slot='button']) {
|
|
39
|
+
--sds-button-border-width: var(--_sds-search-border-width);
|
|
40
|
+
--sds-button-radius: 0 var(--_sds-search-radius) var(--_sds-search-radius) 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.sds-search__button-col {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
/* Keep the button at its intrinsic size instead of stretching it. */
|
|
47
|
+
align-items: flex-start;
|
|
48
|
+
flex: 0 0 auto;
|
|
49
|
+
/* Overlap the borders so the field and button share a single border. */
|
|
50
|
+
margin-inline-start: calc(-1 * var(--_sds-search-border-width));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Raise whichever control is focused so its focus outline is painted on
|
|
54
|
+
top of the neighbouring control and never clipped by it. */
|
|
55
|
+
.sds-search__field:focus-within,
|
|
56
|
+
.sds-search__button-col:focus-within {
|
|
57
|
+
position: relative;
|
|
58
|
+
z-index: 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* border-radius is physical, so mirror the rounded corners for RTL. Logical
|
|
63
|
+
* layout (DOM order, logical margins) already flips on its own.
|
|
64
|
+
*/
|
|
65
|
+
:host(:dir(rtl)) .sds-search__field {
|
|
66
|
+
--sds-textfield-border-radius: 0 var(--_sds-search-radius) var(--_sds-search-radius) 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:host(:dir(rtl)) .sds-search__button,
|
|
70
|
+
:host(:dir(rtl)) ::slotted([slot='button']) {
|
|
71
|
+
--sds-button-radius: var(--_sds-search-radius) 0 0 var(--_sds-search-radius);
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
//# sourceMappingURL=sds-search.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sds-search.styles.js","sourceRoot":"","sources":["../../src/sds-search/sds-search.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuExB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const styles = css`\n\t/*\n\t * The search controls radius and border of inner button and textfield.\n\t */\n\t:host {\n\t\t--_sds-search-radius: var(--sds-search-radius, var(--sds-radius-sm));\n\t\t--_sds-search-border-width: var(--sds-search-border-width, var(--sds-border-sm));\n\n\t\tdisplay: block;\n\t\ttext-align: start;\n\t}\n\n\t.sds-search {\n\t\tdisplay: flex;\n\t\t/* Align to the top; the button is nudged down to the input row in JS so a\n\t\t stacked label, help text, or an error message never drags it out of line. */\n\t\talign-items: flex-start;\n\t\tinline-size: 100%;\n\t}\n\n\t/*\n\t * The field keeps its rounded corners on the inline-start side and squares the\n\t * edge that meets the button; the button mirrors it.\n\t */\n\t.sds-search__field {\n\t\tflex: 1 1 auto;\n\t\t/* Allow the field to shrink below its intrinsic min-width inside flex. */\n\t\tmin-inline-size: 0;\n\t\t/* Let the surrounding container govern the width instead of the\n\t\t textfield's default 60ch cap. */\n\t\t--sds-textfield-input-max-width: none;\n\t\t--sds-textfield-border-width: var(--_sds-search-border-width);\n\t\t--sds-textfield-border-radius: var(--_sds-search-radius) 0 0 var(--_sds-search-radius);\n\t}\n\n\t.sds-search__button,\n\t::slotted([slot='button']) {\n\t\t--sds-button-border-width: var(--_sds-search-border-width);\n\t\t--sds-button-radius: 0 var(--_sds-search-radius) var(--_sds-search-radius) 0;\n\t}\n\n\t.sds-search__button-col {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\t/* Keep the button at its intrinsic size instead of stretching it. */\n\t\talign-items: flex-start;\n\t\tflex: 0 0 auto;\n\t\t/* Overlap the borders so the field and button share a single border. */\n\t\tmargin-inline-start: calc(-1 * var(--_sds-search-border-width));\n\t}\n\n\t/* Raise whichever control is focused so its focus outline is painted on\n\t top of the neighbouring control and never clipped by it. */\n\t.sds-search__field:focus-within,\n\t.sds-search__button-col:focus-within {\n\t\tposition: relative;\n\t\tz-index: 1;\n\t}\n\n\t/*\n\t * border-radius is physical, so mirror the rounded corners for RTL. Logical\n\t * layout (DOM order, logical margins) already flips on its own.\n\t */\n\t:host(:dir(rtl)) .sds-search__field {\n\t\t--sds-textfield-border-radius: 0 var(--_sds-search-radius) var(--_sds-search-radius) 0;\n\t}\n\n\t:host(:dir(rtl)) .sds-search__button,\n\t:host(:dir(rtl)) ::slotted([slot='button']) {\n\t\t--sds-button-radius: var(--_sds-search-radius) 0 0 var(--_sds-search-radius);\n\t}\n`;\n"]}
|
|
@@ -8,6 +8,7 @@ export interface SDSTextFieldProps extends SDSFormControlAttributes {
|
|
|
8
8
|
autocomplete?: AutocompleteTypes;
|
|
9
9
|
'error-message'?: string;
|
|
10
10
|
'help-text'?: string;
|
|
11
|
+
'hide-label'?: boolean;
|
|
11
12
|
label?: string;
|
|
12
13
|
maxlength?: number;
|
|
13
14
|
minlength?: number;
|
|
@@ -26,6 +27,8 @@ export declare class SDSTextFieldComponent extends SDSTextFieldComponent_base {
|
|
|
26
27
|
type: SDSTextFieldProps['type'];
|
|
27
28
|
value?: SDSTextFieldProps['value'];
|
|
28
29
|
label?: SDSTextFieldProps['label'];
|
|
30
|
+
/** Hides the label visually while keeping it as the input's accessible name. */
|
|
31
|
+
hideLabel: SDSTextFieldProps['hide-label'];
|
|
29
32
|
placeholder?: SDSTextFieldProps['placeholder'];
|
|
30
33
|
helpText?: SDSTextFieldProps['help-text'];
|
|
31
34
|
errorMessage?: SDSTextFieldProps['error-message'];
|
|
@@ -38,7 +41,7 @@ export declare class SDSTextFieldComponent extends SDSTextFieldComponent_base {
|
|
|
38
41
|
max?: SDSTextFieldProps['max'];
|
|
39
42
|
size: SDSTextFieldProps['size'];
|
|
40
43
|
private hasIcon;
|
|
41
|
-
/** Tracks whether the `label` slot
|
|
44
|
+
/** Tracks whether the `label` slot renders any content, including content forwarded through another slot. */
|
|
42
45
|
private _hasSlottedLabel;
|
|
43
46
|
control: HTMLInputElement;
|
|
44
47
|
private _defaultValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sds-textfield.component.d.ts","sourceRoot":"","sources":["../../src/sds-textfield/sds-textfield.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"sds-textfield.component.d.ts","sourceRoot":"","sources":["../../src/sds-textfield/sds-textfield.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,25 +9,31 @@ import { SDSElement } from '../utils/sds-element';
|
|
|
9
9
|
import { property, query, state } from 'lit/decorators.js';
|
|
10
10
|
import { classMap } from 'lit/directives/class-map.js';
|
|
11
11
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
12
|
+
import { live } from 'lit/directives/live.js';
|
|
12
13
|
import { SDSEventDispatcherMixin, SDSDelegateInteractionMixin, SDSFormControlMixin } from '../mixins';
|
|
13
14
|
import { styles } from './sds-textfield.styles';
|
|
14
15
|
export class SDSTextFieldComponent extends SDSDelegateInteractionMixin(SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement))) {
|
|
15
16
|
constructor() {
|
|
16
17
|
super(...arguments);
|
|
17
18
|
this.type = 'text';
|
|
19
|
+
/** Hides the label visually while keeping it as the input's accessible name. */
|
|
20
|
+
this.hideLabel = false;
|
|
18
21
|
this.required = false;
|
|
19
22
|
this.size = 'md';
|
|
20
23
|
// State
|
|
21
24
|
this.hasIcon = false;
|
|
22
|
-
/** Tracks whether the `label` slot
|
|
25
|
+
/** Tracks whether the `label` slot renders any content, including content forwarded through another slot. */
|
|
23
26
|
this._hasSlottedLabel = false;
|
|
24
27
|
this._defaultValue = null;
|
|
25
28
|
this.handleSlotChange = (e) => {
|
|
26
29
|
const slot = e.target;
|
|
27
30
|
this.hasIcon = slot.assignedNodes({ flatten: true }).length > 0;
|
|
28
31
|
};
|
|
32
|
+
// Flattened, so a slot forwarded from a wrapping component (like sds-search) counts by what it renders,
|
|
33
|
+
// not as content in itself. `currentTarget`, because slotchange from a forwarded slot bubbles to this one.
|
|
29
34
|
this._handleLabelSlotChange = (e) => {
|
|
30
|
-
|
|
35
|
+
const slot = e.currentTarget;
|
|
36
|
+
this._hasSlottedLabel = slot.assignedNodes({ flatten: true }).some((node) => node.nodeType === Node.ELEMENT_NODE || Boolean(node.textContent?.trim()));
|
|
31
37
|
};
|
|
32
38
|
this._handleInputChange = (event) => {
|
|
33
39
|
event.stopImmediatePropagation();
|
|
@@ -87,7 +93,9 @@ export class SDSTextFieldComponent extends SDSDelegateInteractionMixin(SDSEventD
|
|
|
87
93
|
super.updated(changedProperties);
|
|
88
94
|
if (changedProperties.has('value')) {
|
|
89
95
|
this.internals.setFormValue(this.value ?? '');
|
|
90
|
-
|
|
96
|
+
// Writing the value the user just typed back to the input counts as a script change and
|
|
97
|
+
// clears its user-edit flag, which turns off the minlength/maxlength checks.
|
|
98
|
+
if (this.control && this.control.value !== (this.value ?? '')) {
|
|
91
99
|
this.control.value = this.value ?? '';
|
|
92
100
|
}
|
|
93
101
|
}
|
|
@@ -153,9 +161,13 @@ export class SDSTextFieldComponent extends SDSDelegateInteractionMixin(SDSEventD
|
|
|
153
161
|
};
|
|
154
162
|
const describedBy = [this.errorMessage ? 'error-message' : null, this.helpText ? 'help-text' : null].filter(Boolean).join(' ') || undefined;
|
|
155
163
|
const showLabel = this._hasSlottedLabel || Boolean(this.label);
|
|
164
|
+
const labelClasses = {
|
|
165
|
+
'sds-textfield__label': true,
|
|
166
|
+
'sds-textfield__label--hidden': Boolean(this.hideLabel),
|
|
167
|
+
};
|
|
156
168
|
return html `
|
|
157
169
|
<div class="${classMap(textfieldClasses)}">
|
|
158
|
-
<label for="sds-textfield" class="
|
|
170
|
+
<label for="sds-textfield" class="${classMap(labelClasses)}" ?hidden="${!showLabel}">
|
|
159
171
|
${this.readOnly ? html `<sds-icon name="lock-material-filled" size="m"></sds-icon>` : nothing}
|
|
160
172
|
<slot name="label" @slotchange="${this._handleLabelSlotChange}">${this.label}</slot>
|
|
161
173
|
</label>
|
|
@@ -169,7 +181,7 @@ export class SDSTextFieldComponent extends SDSDelegateInteractionMixin(SDSEventD
|
|
|
169
181
|
?disabled="${this.disabled}"
|
|
170
182
|
?readonly="${this.readOnly}"
|
|
171
183
|
placeholder="${ifDefined(this.placeholder)}"
|
|
172
|
-
.value="${this.value ?? ''}"
|
|
184
|
+
.value="${live(this.value ?? '')}"
|
|
173
185
|
name="${ifDefined(this.name)}"
|
|
174
186
|
autocomplete="${ifDefined(this.autocomplete)}"
|
|
175
187
|
?required="${this.required}"
|
|
@@ -205,6 +217,9 @@ __decorate([
|
|
|
205
217
|
__decorate([
|
|
206
218
|
property({ type: String, reflect: true })
|
|
207
219
|
], SDSTextFieldComponent.prototype, "label", void 0);
|
|
220
|
+
__decorate([
|
|
221
|
+
property({ type: Boolean, attribute: 'hide-label', reflect: true })
|
|
222
|
+
], SDSTextFieldComponent.prototype, "hideLabel", void 0);
|
|
208
223
|
__decorate([
|
|
209
224
|
property({ type: String, reflect: true })
|
|
210
225
|
], SDSTextFieldComponent.prototype, "placeholder", void 0);
|