@sebgroup/green-core 1.81.0 → 1.83.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/components/checkbox/checkbox-group/checkbox-group.component.js +1 -1
- package/components/datepicker/datepicker.component.js +12 -5
- package/components/datepicker/datepicker.styles.js +2 -2
- package/components/dialog/dialog.component.d.ts +1 -1
- package/components/dialog/dialog.component.js +32 -7
- package/components/dropdown/dropdown.component.js +9 -6
- package/components/form/form-control.js +4 -3
- package/components/form/index.d.ts +1 -1
- package/components/form/index.js +1 -1
- package/components/form-summary/summary.component.d.ts +41 -0
- package/components/form-summary/summary.component.js +197 -0
- package/components/{form/summary → form-summary}/summary.js +1 -1
- package/components/form-summary/summary.styles.d.ts +2 -0
- package/components/form-summary/summary.styles.js +33 -0
- package/components/input/input.component.js +4 -4
- package/components/popover/popover.component.js +1 -1
- package/components/pure.d.ts +1 -1
- package/components/pure.js +1 -1
- package/components/radio/radio-group/radio-group.component.js +1 -1
- package/components/textarea/textarea.component.js +6 -4
- package/generated/locales/da.d.ts +1 -1
- package/generated/locales/da.js +1 -1
- package/generated/locales/de.d.ts +1 -1
- package/generated/locales/de.js +1 -1
- package/generated/locales/fi.d.ts +1 -1
- package/generated/locales/fi.js +1 -1
- package/generated/locales/fr.d.ts +1 -1
- package/generated/locales/fr.js +1 -1
- package/generated/locales/it.d.ts +1 -1
- package/generated/locales/it.js +1 -1
- package/generated/locales/nl.d.ts +1 -1
- package/generated/locales/nl.js +1 -1
- package/generated/locales/no.d.ts +1 -1
- package/generated/locales/no.js +1 -1
- package/generated/locales/sv.d.ts +1 -1
- package/generated/locales/sv.js +1 -1
- package/generated/react/form-control-footer/index.d.ts +2 -2
- package/generated/react/form-summary/index.d.ts +369 -0
- package/generated/react/form-summary/index.js +13 -0
- package/generated/react/index.d.ts +9 -8
- package/generated/react/index.js +9 -8
- package/package.json +3 -3
- package/primitives/form-control-footer/form-control-footer.component.d.ts +3 -1
- package/primitives/form-control-footer/form-control-footer.component.js +19 -4
- package/primitives/form-control-footer/form-control-footer.styles.js +8 -0
- package/tokens/variables.css.js +1 -1
- package/tokens/variables.shadows.css.js +2 -0
- package/tokens.style.js +3 -0
- package/utils/helpers/custom-element-scoping.js +1 -1
- package/components/form/summary/summary.component.d.ts +0 -9
- package/components/form/summary/summary.component.js +0 -88
- /package/components/{form/summary → form-summary}/index.d.ts +0 -0
- /package/components/{form/summary → form-summary}/index.js +0 -0
- /package/components/{form/summary → form-summary}/summary.d.ts +0 -0
|
@@ -153,7 +153,7 @@ renderFieldControlFooter_fn = function() {
|
|
|
153
153
|
return html`<gds-form-control-footer
|
|
154
154
|
id="footer"
|
|
155
155
|
class="size-${this.size}"
|
|
156
|
-
.
|
|
156
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
157
157
|
>
|
|
158
158
|
</gds-form-control-footer>`;
|
|
159
159
|
};
|
|
@@ -239,10 +239,14 @@ let Datepicker = class extends GdsFormControlElement {
|
|
|
239
239
|
return "gds-datepicker";
|
|
240
240
|
}
|
|
241
241
|
get value() {
|
|
242
|
-
|
|
242
|
+
const dateValue = super.value;
|
|
243
|
+
if (dateValue instanceof Date) {
|
|
244
|
+
return new Date(dateValue);
|
|
245
|
+
}
|
|
246
|
+
return void 0;
|
|
243
247
|
}
|
|
244
248
|
set value(value) {
|
|
245
|
-
|
|
249
|
+
super.value = value;
|
|
246
250
|
}
|
|
247
251
|
get dateformat() {
|
|
248
252
|
return this._dateFormatLayout.layout.map((f) => f.token).join(this._dateFormatLayout.delimiter);
|
|
@@ -369,13 +373,16 @@ let Datepicker = class extends GdsFormControlElement {
|
|
|
369
373
|
|
|
370
374
|
${when(
|
|
371
375
|
__privateMethod(this, _shouldShowFooter, shouldShowFooter_fn).call(this),
|
|
372
|
-
() => html`<gds-form-control-footer
|
|
376
|
+
() => html`<gds-form-control-footer
|
|
377
|
+
class="size-${this.size}"
|
|
378
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
379
|
+
>
|
|
373
380
|
${``}
|
|
374
381
|
<slot id="message" name="message" slot="message">
|
|
375
382
|
<gds-icon-triangle-exclamation
|
|
376
383
|
solid
|
|
377
384
|
></gds-icon-triangle-exclamation>
|
|
378
|
-
${this.errorMessage
|
|
385
|
+
${this.errorMessage}
|
|
379
386
|
</slot>
|
|
380
387
|
</gds-form-control-footer>`
|
|
381
388
|
)}
|
|
@@ -553,7 +560,7 @@ let Datepicker = class extends GdsFormControlElement {
|
|
|
553
560
|
_valueOnOpen = new WeakMap();
|
|
554
561
|
_shouldShowFooter = new WeakSet();
|
|
555
562
|
shouldShowFooter_fn = function() {
|
|
556
|
-
return !this.plain
|
|
563
|
+
return !this.plain;
|
|
557
564
|
};
|
|
558
565
|
_renderBackToValidRangeButton = new WeakSet();
|
|
559
566
|
renderBackToValidRangeButton_fn = async function() {
|
|
@@ -38,8 +38,8 @@ const styles = css`
|
|
|
38
38
|
text-align: center;
|
|
39
39
|
|
|
40
40
|
&:focus {
|
|
41
|
-
background-color: var(--gds-color-l2-background-tertiary);
|
|
42
|
-
color: var(--gds-color-l2-content-tertiary);
|
|
41
|
+
background-color: var(--gds-sys-color-l2-background-tertiary);
|
|
42
|
+
color: var(--gds-sys-color-l2-content-tertiary);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -4,7 +4,7 @@ declare const GdsDialog_base: (new (...args: any[]) => import("../../utils/mixin
|
|
|
4
4
|
* @element gds-dialog
|
|
5
5
|
* @status beta
|
|
6
6
|
*
|
|
7
|
-
* @event gds-ui-state - Fired when the dialog is opened or closed
|
|
7
|
+
* @event gds-ui-state - Fired when the dialog is opened or closed. Can be cancelled to prevent the dialog from closing.
|
|
8
8
|
* @event gds-close - Fired when the dialog is closed
|
|
9
9
|
* @event gds-show - Fired when the dialog is opened
|
|
10
10
|
*
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
__privateMethod,
|
|
6
6
|
__privateSet
|
|
7
7
|
} from "../../chunks/chunk.QTSIPXV3.js";
|
|
8
|
-
var _returnValue, _handleNativeClose, _dispatchCloseEvent, _dispatchShowEvent, _dispatchUiStateEvent, _handleTriggerSlotChange, handleTriggerSlotChange_fn, _handleTriggerClick;
|
|
8
|
+
var _returnValue, _handleNativeClose, _dispatchCloseEvent, _dispatchShowEvent, _dispatchUiStateEvent, _handleTriggerSlotChange, handleTriggerSlotChange_fn, _handleTriggerClick, _handleClickOutside;
|
|
9
9
|
import { localized, msg } from "@lit/localize";
|
|
10
10
|
import { property, query } from "lit/decorators.js";
|
|
11
11
|
import { when } from "lit/directives/when.js";
|
|
@@ -42,9 +42,14 @@ let GdsDialog = class extends withSizeXProps(withSizeYProps(GdsElement)) {
|
|
|
42
42
|
__privateAdd(this, _handleNativeClose, (e) => {
|
|
43
43
|
const dialog = e.target;
|
|
44
44
|
const returnValue = dialog.returnValue;
|
|
45
|
+
if (returnValue !== "prop-change") {
|
|
46
|
+
if (!__privateGet(this, _dispatchCloseEvent).call(this, returnValue)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.close(returnValue || "native-close");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
45
52
|
this.close(returnValue || "native-close");
|
|
46
|
-
if (returnValue !== "prop-change")
|
|
47
|
-
__privateGet(this, _dispatchCloseEvent).call(this, returnValue);
|
|
48
53
|
});
|
|
49
54
|
__privateAdd(this, _dispatchCloseEvent, (reason) => {
|
|
50
55
|
this.dispatchEvent(
|
|
@@ -54,7 +59,7 @@ let GdsDialog = class extends withSizeXProps(withSizeYProps(GdsElement)) {
|
|
|
54
59
|
composed: false
|
|
55
60
|
})
|
|
56
61
|
);
|
|
57
|
-
__privateGet(this, _dispatchUiStateEvent).call(this, reason);
|
|
62
|
+
return __privateGet(this, _dispatchUiStateEvent).call(this, reason);
|
|
58
63
|
});
|
|
59
64
|
__privateAdd(this, _dispatchShowEvent, (reason) => {
|
|
60
65
|
this.dispatchEvent(
|
|
@@ -64,20 +69,34 @@ let GdsDialog = class extends withSizeXProps(withSizeYProps(GdsElement)) {
|
|
|
64
69
|
composed: false
|
|
65
70
|
})
|
|
66
71
|
);
|
|
67
|
-
__privateGet(this, _dispatchUiStateEvent).call(this, reason);
|
|
72
|
+
return __privateGet(this, _dispatchUiStateEvent).call(this, reason);
|
|
68
73
|
});
|
|
69
74
|
__privateAdd(this, _dispatchUiStateEvent, (reason) => {
|
|
70
|
-
this.dispatchEvent(
|
|
75
|
+
return this.dispatchEvent(
|
|
71
76
|
new CustomEvent("gds-ui-state", {
|
|
72
77
|
detail: { reason, open: this.open },
|
|
73
78
|
bubbles: false,
|
|
74
|
-
composed: false
|
|
79
|
+
composed: false,
|
|
80
|
+
cancelable: true
|
|
75
81
|
})
|
|
76
82
|
);
|
|
77
83
|
});
|
|
78
84
|
__privateAdd(this, _handleTriggerClick, (e) => {
|
|
79
85
|
this.show("slotted-trigger");
|
|
80
86
|
});
|
|
87
|
+
__privateAdd(this, _handleClickOutside, (evt) => {
|
|
88
|
+
const e = evt;
|
|
89
|
+
const dialog = this._elDialog;
|
|
90
|
+
const isNotEnterKey = e.clientX > 0 || e.clientY > 0;
|
|
91
|
+
if (isNotEnterKey && dialog && this.open) {
|
|
92
|
+
const rect = dialog.getBoundingClientRect();
|
|
93
|
+
const isInDialog = rect.top <= e.clientY && e.clientY <= rect.top + rect.height && rect.left <= e.clientX && e.clientX <= rect.left + rect.width;
|
|
94
|
+
const closeReason = "click-outside";
|
|
95
|
+
if (!isInDialog && __privateGet(this, _dispatchCloseEvent).call(this, closeReason)) {
|
|
96
|
+
this.close(closeReason);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
81
100
|
}
|
|
82
101
|
/**
|
|
83
102
|
* Opens the dialog.
|
|
@@ -166,6 +185,10 @@ let GdsDialog = class extends withSizeXProps(withSizeYProps(GdsElement)) {
|
|
|
166
185
|
this.updateComplete.then(() => {
|
|
167
186
|
this._elDialog?.showModal();
|
|
168
187
|
lockBodyScrolling(this);
|
|
188
|
+
document.removeEventListener("click", __privateGet(this, _handleClickOutside));
|
|
189
|
+
requestAnimationFrame(
|
|
190
|
+
() => document.addEventListener("click", __privateGet(this, _handleClickOutside))
|
|
191
|
+
);
|
|
169
192
|
if (isIOS) {
|
|
170
193
|
this._elDialog?.focus();
|
|
171
194
|
}
|
|
@@ -174,6 +197,7 @@ let GdsDialog = class extends withSizeXProps(withSizeYProps(GdsElement)) {
|
|
|
174
197
|
__privateSet(this, _returnValue, __privateGet(this, _returnValue) || "prop-change");
|
|
175
198
|
this._elDialog?.close(__privateGet(this, _returnValue));
|
|
176
199
|
unlockBodyScrolling(this);
|
|
200
|
+
document.removeEventListener("click", __privateGet(this, _handleClickOutside));
|
|
177
201
|
this.requestUpdate("open");
|
|
178
202
|
}
|
|
179
203
|
}
|
|
@@ -192,6 +216,7 @@ handleTriggerSlotChange_fn = function() {
|
|
|
192
216
|
}
|
|
193
217
|
};
|
|
194
218
|
_handleTriggerClick = new WeakMap();
|
|
219
|
+
_handleClickOutside = new WeakMap();
|
|
195
220
|
GdsDialog.styles = [styles];
|
|
196
221
|
GdsDialog.styleExpressionBaseSelector = "dialog";
|
|
197
222
|
__decorateClass([
|
|
@@ -268,13 +268,13 @@ let GdsDropdown = class extends GdsFormControlElement {
|
|
|
268
268
|
let displayValue;
|
|
269
269
|
if (Array.isArray(this.value)) {
|
|
270
270
|
this.value.length > 2 ? displayValue = msg(str`${this.value.length} selected`) : displayValue = this.value.reduce(
|
|
271
|
-
(acc, cur) => acc + this.options.find((v) => v.value === cur)?.
|
|
271
|
+
(acc, cur) => acc + this.options.find((v) => v.value === cur)?.innerText + ", ",
|
|
272
272
|
""
|
|
273
273
|
).slice(0, -2);
|
|
274
274
|
} else {
|
|
275
|
-
displayValue = this.options.find((v) => v.selected)?.
|
|
275
|
+
displayValue = this.options.find((v) => v.selected)?.innerText;
|
|
276
276
|
}
|
|
277
|
-
return displayValue || this.placeholder?.
|
|
277
|
+
return displayValue || this.placeholder?.innerText || "";
|
|
278
278
|
}
|
|
279
279
|
/**
|
|
280
280
|
* Moves focus to this element.
|
|
@@ -373,13 +373,16 @@ let GdsDropdown = class extends GdsFormControlElement {
|
|
|
373
373
|
${when(
|
|
374
374
|
__privateMethod(this, _shouldShowFooter, shouldShowFooter_fn).call(this),
|
|
375
375
|
() => html`
|
|
376
|
-
<gds-form-control-footer
|
|
376
|
+
<gds-form-control-footer
|
|
377
|
+
class="size-${this.size}"
|
|
378
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
379
|
+
>
|
|
377
380
|
${``}
|
|
378
381
|
<slot id="message" name="message" slot="message">
|
|
379
382
|
<gds-icon-triangle-exclamation
|
|
380
383
|
solid
|
|
381
384
|
></gds-icon-triangle-exclamation>
|
|
382
|
-
${this.
|
|
385
|
+
${this.validationMessage || this.errorMessage}
|
|
383
386
|
</slot>
|
|
384
387
|
</gds-form-control-footer>
|
|
385
388
|
`
|
|
@@ -439,7 +442,7 @@ let GdsDropdown = class extends GdsFormControlElement {
|
|
|
439
442
|
_optionElements = new WeakMap();
|
|
440
443
|
_shouldShowFooter = new WeakSet();
|
|
441
444
|
shouldShowFooter_fn = function() {
|
|
442
|
-
return !this.plain
|
|
445
|
+
return !this.plain;
|
|
443
446
|
};
|
|
444
447
|
_renderCombobox = new WeakMap();
|
|
445
448
|
_renderTriggerButton = new WeakMap();
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
__privateSet
|
|
6
6
|
} from "../../chunks/chunk.QTSIPXV3.js";
|
|
7
7
|
var _internals;
|
|
8
|
-
import { msg } from "@lit/localize";
|
|
9
8
|
import { property } from "lit/decorators.js";
|
|
10
9
|
import { GdsElement } from "../../gds-element.js";
|
|
11
10
|
import { watch } from "../../utils/decorators/index.js";
|
|
@@ -59,7 +58,7 @@ class GdsFormControlElement extends GdsElement {
|
|
|
59
58
|
customError: value,
|
|
60
59
|
valid: !value
|
|
61
60
|
},
|
|
62
|
-
this.validationMessage ||
|
|
61
|
+
this.errorMessage || this.validationMessage || " ",
|
|
63
62
|
// @ts-expect-error - setValidity actually takes an element as the third argument, but the type definition is wrong.
|
|
64
63
|
this._getValidityAnchor() || void 0
|
|
65
64
|
);
|
|
@@ -74,6 +73,7 @@ class GdsFormControlElement extends GdsElement {
|
|
|
74
73
|
}
|
|
75
74
|
set value(value) {
|
|
76
75
|
this._internalValue = value;
|
|
76
|
+
__privateGet(this, _internals).setFormValue(value);
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
79
|
* The form element that the form control is associated with.
|
|
@@ -99,6 +99,7 @@ class GdsFormControlElement extends GdsElement {
|
|
|
99
99
|
{ ...this.validity, valid: true },
|
|
100
100
|
""
|
|
101
101
|
];
|
|
102
|
+
this.errorMessage = validity[1] || this.errorMessage;
|
|
102
103
|
__privateGet(this, _internals).setValidity(
|
|
103
104
|
validity[0],
|
|
104
105
|
validity[1],
|
|
@@ -124,7 +125,6 @@ class GdsFormControlElement extends GdsElement {
|
|
|
124
125
|
return __privateGet(this, _internals).reportValidity();
|
|
125
126
|
}
|
|
126
127
|
__handleValueChange() {
|
|
127
|
-
__privateGet(this, _internals).setFormValue(this.value);
|
|
128
128
|
this.checkValidity();
|
|
129
129
|
}
|
|
130
130
|
formResetCallback() {
|
|
@@ -143,6 +143,7 @@ class GdsFormControlElement extends GdsElement {
|
|
|
143
143
|
if (!this.validity.valid)
|
|
144
144
|
e.preventDefault();
|
|
145
145
|
}
|
|
146
|
+
// TODO: This needs to be handled on a component by component basis, since it's not always the validity anchor that should be the focus reciever.
|
|
146
147
|
focus(options) {
|
|
147
148
|
this._getValidityAnchor().focus(options);
|
|
148
149
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '
|
|
1
|
+
export * from '../form-summary';
|
package/components/form/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "
|
|
1
|
+
export * from "../form-summary/index.js";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GdsElement } from '../../gds-element';
|
|
2
|
+
/**
|
|
3
|
+
* @element gds-form-summary
|
|
4
|
+
*
|
|
5
|
+
* When a user attempts to submit a form with errors, this component displays a summary of those errors.
|
|
6
|
+
* Including an error summary greatly assists users in promptly identifying and addressing multiple errors
|
|
7
|
+
* in a consolidated manner. It provides a clear indication of what went wrong and what needs to be corrected.
|
|
8
|
+
*/
|
|
9
|
+
export declare class GdsFormSummary extends GdsElement {
|
|
10
|
+
#private;
|
|
11
|
+
static styles: (import("lit").CSSResult | import("lit").CSSResult[])[];
|
|
12
|
+
/**
|
|
13
|
+
* Whether to hide the error messages under the labels.
|
|
14
|
+
*/
|
|
15
|
+
hideErrors: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether to refresh the summary automatically as controls in the form change validation state.
|
|
18
|
+
*
|
|
19
|
+
* Avoid this setting if the summary is located above the form controls, as it may cause the form
|
|
20
|
+
* to jump around as the summary is updated.
|
|
21
|
+
*/
|
|
22
|
+
reactive: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The current number of errors displayed in the summary.
|
|
25
|
+
*
|
|
26
|
+
* This is a convenience property that can be used to display the number of errors in the summary.
|
|
27
|
+
*/
|
|
28
|
+
get errorCount(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Focuses the first focusable element in the summary.
|
|
31
|
+
*/
|
|
32
|
+
focus(options?: FocusOptions): void;
|
|
33
|
+
private _elRoot;
|
|
34
|
+
connectedCallback(): void;
|
|
35
|
+
disconnectedCallback(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Refresh the component to reflext the current state of the form.
|
|
38
|
+
*/
|
|
39
|
+
refresh(): void;
|
|
40
|
+
render(): any;
|
|
41
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__decorateClass,
|
|
3
|
+
__privateAdd,
|
|
4
|
+
__privateGet,
|
|
5
|
+
__privateMethod,
|
|
6
|
+
__privateSet
|
|
7
|
+
} from "../../chunks/chunk.QTSIPXV3.js";
|
|
8
|
+
var _form, _formObserver, _getFormControls, getFormControls_fn, _getErrorControls, getErrorControls_fn, _renderArrowIcon, renderArrowIcon_fn;
|
|
9
|
+
import { msg, str } from "@lit/localize";
|
|
10
|
+
import { nothing } from "lit";
|
|
11
|
+
import { property, queryAsync } from "lit/decorators.js";
|
|
12
|
+
import { until } from "lit/directives/until.js";
|
|
13
|
+
import { when } from "lit/directives/when.js";
|
|
14
|
+
import { GdsElement } from "../../gds-element.js";
|
|
15
|
+
import { gdsCustomElement, html } from "../../scoping.js";
|
|
16
|
+
import { tokens } from "../../tokens.style.js";
|
|
17
|
+
import { GdsButton } from "../button/button.component.js";
|
|
18
|
+
import { GdsCard } from "../card/card.component.js";
|
|
19
|
+
import { GdsDiv } from "../div/div.component.js";
|
|
20
|
+
import { GdsFlex } from "../flex/flex.component.js";
|
|
21
|
+
import { IconArrowUp } from "../icon/icons/arrow-up.component.js";
|
|
22
|
+
import styles from "./summary.styles.js";
|
|
23
|
+
let GdsFormSummary = class extends GdsElement {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
__privateAdd(this, _getFormControls);
|
|
27
|
+
__privateAdd(this, _getErrorControls);
|
|
28
|
+
__privateAdd(this, _renderArrowIcon);
|
|
29
|
+
this.hideErrors = false;
|
|
30
|
+
this.reactive = false;
|
|
31
|
+
__privateAdd(this, _form, void 0);
|
|
32
|
+
__privateAdd(this, _formObserver, void 0);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The current number of errors displayed in the summary.
|
|
36
|
+
*
|
|
37
|
+
* This is a convenience property that can be used to display the number of errors in the summary.
|
|
38
|
+
*/
|
|
39
|
+
get errorCount() {
|
|
40
|
+
return __privateMethod(this, _getErrorControls, getErrorControls_fn).call(this).length;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Focuses the first focusable element in the summary.
|
|
44
|
+
*/
|
|
45
|
+
focus(options) {
|
|
46
|
+
this._elRoot.then((el) => {
|
|
47
|
+
const firstFocusable = el.querySelector(
|
|
48
|
+
'[gds-element="gds-button"]'
|
|
49
|
+
);
|
|
50
|
+
if (firstFocusable) {
|
|
51
|
+
firstFocusable.focus(options);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
connectedCallback() {
|
|
56
|
+
super.connectedCallback();
|
|
57
|
+
__privateSet(this, _form, this.closest("form") || void 0);
|
|
58
|
+
if (__privateGet(this, _form) && this.reactive) {
|
|
59
|
+
__privateSet(this, _formObserver, new MutationObserver(() => {
|
|
60
|
+
this.refresh();
|
|
61
|
+
}));
|
|
62
|
+
__privateGet(this, _formObserver).observe(__privateGet(this, _form), {
|
|
63
|
+
attributes: true,
|
|
64
|
+
subtree: true
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
disconnectedCallback() {
|
|
69
|
+
super.disconnectedCallback();
|
|
70
|
+
__privateGet(this, _formObserver)?.disconnect();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Refresh the component to reflext the current state of the form.
|
|
74
|
+
*/
|
|
75
|
+
refresh() {
|
|
76
|
+
this.requestUpdate();
|
|
77
|
+
}
|
|
78
|
+
render() {
|
|
79
|
+
const formControls = __privateMethod(this, _getFormControls, getFormControls_fn).call(this);
|
|
80
|
+
const errorControls = __privateMethod(this, _getErrorControls, getErrorControls_fn).call(this);
|
|
81
|
+
return when(
|
|
82
|
+
errorControls.length > 0,
|
|
83
|
+
() => html`<gds-card
|
|
84
|
+
id="root"
|
|
85
|
+
role="navigation"
|
|
86
|
+
border-color="negative"
|
|
87
|
+
border-radius="xs"
|
|
88
|
+
border-width="0"
|
|
89
|
+
padding="l"
|
|
90
|
+
background="negative"
|
|
91
|
+
color="negative"
|
|
92
|
+
overflow="hidden"
|
|
93
|
+
aria-describedby="description"
|
|
94
|
+
aria-label=${msg(`Form error summary`)}
|
|
95
|
+
>
|
|
96
|
+
<gds-flex gap="0" flex-direction="column">
|
|
97
|
+
<gds-text
|
|
98
|
+
font-size="heading-xs"
|
|
99
|
+
font-weight="book"
|
|
100
|
+
id="description"
|
|
101
|
+
>
|
|
102
|
+
${msg(
|
|
103
|
+
str`There are ${errorControls.length} errors to correct before you can continue:`
|
|
104
|
+
)}
|
|
105
|
+
</gds-text>
|
|
106
|
+
<ul>
|
|
107
|
+
${formControls.map(
|
|
108
|
+
(el, idx) => html`<li ?inert=${!(el.ariaInvalid === "true" || el.invalid)}>
|
|
109
|
+
<gds-card
|
|
110
|
+
display="flex"
|
|
111
|
+
padding="s"
|
|
112
|
+
flex-direction="row"
|
|
113
|
+
align-items="center"
|
|
114
|
+
justify-content="space-between"
|
|
115
|
+
gap="xs"
|
|
116
|
+
level="3"
|
|
117
|
+
color="negative"
|
|
118
|
+
background="transparent; hover: negative/.2"
|
|
119
|
+
style="cursor: pointer"
|
|
120
|
+
border-width="0"
|
|
121
|
+
border-radius="xs"
|
|
122
|
+
margin="0 -xs"
|
|
123
|
+
@click=${(e) => {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
el.focus();
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<div id=${`error-label-${idx}`}>
|
|
129
|
+
<gds-div font-weight="book"
|
|
130
|
+
>${el.dataset.label || el.label || el.ariaLabel}</gds-div
|
|
131
|
+
>
|
|
132
|
+
${when(
|
|
133
|
+
!this.hideErrors,
|
|
134
|
+
() => html`<gds-div font-size="body-s">
|
|
135
|
+
${el.dataset.errormessage || el.errorMessage || el.ariaErrorMessage}
|
|
136
|
+
</gds-div>`
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
<gds-button
|
|
140
|
+
size="small"
|
|
141
|
+
variant="negative"
|
|
142
|
+
label=${`Move focus to ${el.label} field`}
|
|
143
|
+
>
|
|
144
|
+
${until(__privateMethod(this, _renderArrowIcon, renderArrowIcon_fn).call(this, el), nothing)}
|
|
145
|
+
</gds-button>
|
|
146
|
+
</gds-card>
|
|
147
|
+
</li>`
|
|
148
|
+
)}
|
|
149
|
+
</ul>
|
|
150
|
+
</gds-flex>
|
|
151
|
+
</gds-card>`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
_form = new WeakMap();
|
|
156
|
+
_formObserver = new WeakMap();
|
|
157
|
+
_getFormControls = new WeakSet();
|
|
158
|
+
getFormControls_fn = function() {
|
|
159
|
+
return Array.from(__privateGet(this, _form)?.elements || []).filter(
|
|
160
|
+
// Individual checkboxes can be used as form controls, but they don't support error messages,
|
|
161
|
+
// so we filter them out here. Checkboxes needs to be wrapped in a group to work with form summary.
|
|
162
|
+
(el) => el.gdsElementName !== "gds-checkbox"
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
_getErrorControls = new WeakSet();
|
|
166
|
+
getErrorControls_fn = function() {
|
|
167
|
+
return __privateMethod(this, _getFormControls, getFormControls_fn).call(this).filter(
|
|
168
|
+
(el) => el.ariaInvalid === "true" || el.invalid
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
_renderArrowIcon = new WeakSet();
|
|
172
|
+
renderArrowIcon_fn = async function(el) {
|
|
173
|
+
const selfTop = (await this._elRoot).getBoundingClientRect().top;
|
|
174
|
+
const elTop = el.getBoundingClientRect().top;
|
|
175
|
+
const isAbove = elTop < selfTop;
|
|
176
|
+
return isAbove ? html`<gds-icon-arrow-up></gds-icon-arrow-up>` : html`<gds-icon-arrow-up
|
|
177
|
+
style="transform: rotate(180deg)"
|
|
178
|
+
></gds-icon-arrow-up>`;
|
|
179
|
+
};
|
|
180
|
+
GdsFormSummary.styles = [tokens, styles];
|
|
181
|
+
__decorateClass([
|
|
182
|
+
property({ type: Boolean })
|
|
183
|
+
], GdsFormSummary.prototype, "hideErrors", 2);
|
|
184
|
+
__decorateClass([
|
|
185
|
+
property({ type: Boolean })
|
|
186
|
+
], GdsFormSummary.prototype, "reactive", 2);
|
|
187
|
+
__decorateClass([
|
|
188
|
+
queryAsync("#root")
|
|
189
|
+
], GdsFormSummary.prototype, "_elRoot", 2);
|
|
190
|
+
GdsFormSummary = __decorateClass([
|
|
191
|
+
gdsCustomElement("gds-form-summary", {
|
|
192
|
+
dependsOn: [GdsCard, GdsFlex, GdsDiv, GdsButton, IconArrowUp]
|
|
193
|
+
})
|
|
194
|
+
], GdsFormSummary);
|
|
195
|
+
export {
|
|
196
|
+
GdsFormSummary
|
|
197
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "../../chunks/chunk.QTSIPXV3.js";
|
|
2
|
+
import { css } from "lit";
|
|
3
|
+
var summary_styles_default = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: contents;
|
|
6
|
+
}
|
|
7
|
+
ul {
|
|
8
|
+
list-style-type: none;
|
|
9
|
+
margin: 1rem 0 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
li {
|
|
13
|
+
margin: 0;
|
|
14
|
+
transition:
|
|
15
|
+
max-height 0.3s ease-in-out,
|
|
16
|
+
opacity 0.3s ease-in-out,
|
|
17
|
+
margin 0.3s ease-in-out;
|
|
18
|
+
}
|
|
19
|
+
li[inert] {
|
|
20
|
+
max-height: 0;
|
|
21
|
+
opacity: 0;
|
|
22
|
+
}
|
|
23
|
+
li:not([inert]) {
|
|
24
|
+
max-height: 4rem;
|
|
25
|
+
opacity: 1;
|
|
26
|
+
}
|
|
27
|
+
a {
|
|
28
|
+
color: inherit;
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
export {
|
|
32
|
+
summary_styles_default as default
|
|
33
|
+
};
|
|
@@ -121,10 +121,10 @@ let Input = class extends GdsFormControlElement {
|
|
|
121
121
|
</gds-field-base>
|
|
122
122
|
${when(
|
|
123
123
|
__privateMethod(this, _shouldShowFooter, shouldShowFooter_fn).call(this),
|
|
124
|
-
() => html
|
|
124
|
+
() => html` <gds-form-control-footer
|
|
125
125
|
class="size-${this.size}"
|
|
126
|
-
.charCounter=${__privateGet(this, _shouldShowRemainingChars, shouldShowRemainingChars_get)
|
|
127
|
-
.
|
|
126
|
+
.charCounter=${__privateGet(this, _shouldShowRemainingChars, shouldShowRemainingChars_get) ? this.maxlength - (this.value?.length || 0) : void 0}
|
|
127
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
128
128
|
></gds-form-control-footer>`
|
|
129
129
|
)}
|
|
130
130
|
`;
|
|
@@ -135,7 +135,7 @@ let Input = class extends GdsFormControlElement {
|
|
|
135
135
|
};
|
|
136
136
|
_shouldShowFooter = new WeakSet();
|
|
137
137
|
shouldShowFooter_fn = function() {
|
|
138
|
-
return !this.plain
|
|
138
|
+
return !this.plain;
|
|
139
139
|
};
|
|
140
140
|
_handleOnInput = new WeakMap();
|
|
141
141
|
_handleOnChange = new WeakMap();
|
|
@@ -145,7 +145,7 @@ let GdsPopover = class extends GdsElement {
|
|
|
145
145
|
});
|
|
146
146
|
this.addEventListener("focusin", (e) => {
|
|
147
147
|
const t = e.target;
|
|
148
|
-
if (t.tagName === "INPUT" || t.tagName === "TEXTAREA") {
|
|
148
|
+
if (t === this || t.tagName === "INPUT" || t.tagName === "TEXTAREA") {
|
|
149
149
|
this._isVirtKbVisible = true;
|
|
150
150
|
} else {
|
|
151
151
|
this._isVirtKbVisible = false;
|
package/components/pure.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export * from './icon/icon.component';
|
|
|
31
31
|
export * from './segmented-control/segmented-control.component';
|
|
32
32
|
export * from './theme/theme.component';
|
|
33
33
|
export * from './filter-chips/filter-chips.component';
|
|
34
|
-
export * from './form
|
|
34
|
+
export * from './form-summary/summary.component';
|
|
35
35
|
export * from './input/input.component';
|
|
36
36
|
export * from './select/select.component';
|
|
37
37
|
export * from './spinner/spinner.component';
|
package/components/pure.js
CHANGED
|
@@ -31,7 +31,7 @@ export * from "./icon/icon.component.js";
|
|
|
31
31
|
export * from "./segmented-control/segmented-control.component.js";
|
|
32
32
|
export * from "./theme/theme.component.js";
|
|
33
33
|
export * from "./filter-chips/filter-chips.component.js";
|
|
34
|
-
export * from "./form
|
|
34
|
+
export * from "./form-summary/summary.component.js";
|
|
35
35
|
export * from "./input/input.component.js";
|
|
36
36
|
export * from "./select/select.component.js";
|
|
37
37
|
export * from "./spinner/spinner.component.js";
|
|
@@ -245,7 +245,7 @@ renderFieldControlFooter_fn = function() {
|
|
|
245
245
|
return html` <gds-form-control-footer
|
|
246
246
|
id="footer"
|
|
247
247
|
class="size-${this.size}"
|
|
248
|
-
.
|
|
248
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
249
249
|
>
|
|
250
250
|
</gds-form-control-footer>`;
|
|
251
251
|
};
|
|
@@ -188,9 +188,10 @@ let Textarea = class extends GdsFormControlElement {
|
|
|
188
188
|
${when(
|
|
189
189
|
__privateMethod(this, _shouldShowFooter, shouldShowFooter_fn).call(this),
|
|
190
190
|
() => html`<gds-form-control-footer
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
.
|
|
191
|
+
id="footer"
|
|
192
|
+
class="size-${this.size}"
|
|
193
|
+
.charCounter=${__privateGet(this, _shouldShowRemainingChars, shouldShowRemainingChars_get) ? this.maxlength - (this.value?.length || 0) : void 0}
|
|
194
|
+
.errorMessage=${this.invalid ? this.errorMessage : void 0}
|
|
194
195
|
></gds-form-control-footer>`
|
|
195
196
|
)}
|
|
196
197
|
`;
|
|
@@ -239,7 +240,7 @@ let Textarea = class extends GdsFormControlElement {
|
|
|
239
240
|
};
|
|
240
241
|
_shouldShowFooter = new WeakSet();
|
|
241
242
|
shouldShowFooter_fn = function() {
|
|
242
|
-
return !this.plain
|
|
243
|
+
return !this.plain;
|
|
243
244
|
};
|
|
244
245
|
_handleOnInput = new WeakMap();
|
|
245
246
|
_handleOnChange = new WeakMap();
|
|
@@ -276,6 +277,7 @@ renderNativeTextarea_fn = function() {
|
|
|
276
277
|
class="native-control resize-${this.resizable}"
|
|
277
278
|
aria-label=${this.plain && this.label || nothing}
|
|
278
279
|
aria-describedby="supporting-text extended-supporting-text sub-label message"
|
|
280
|
+
aria-errormessage="footer"
|
|
279
281
|
placeholder=" "
|
|
280
282
|
autocapitalize=${ifDefined(this.autocapitalize)}
|
|
281
283
|
autocomplete=${ifDefined(this.autocomplete)}
|