@sondor-technology/sondor-components 1.0.2 → 1.0.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.d.ts +3 -0
- package/dist/components/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox/checkbox.js +38 -20
- package/dist/components/form/form-step.d.ts +1 -0
- package/dist/components/form/form-step.d.ts.map +1 -1
- package/dist/components/form/form-step.js +3 -0
- package/dist/components/form/form.d.ts +7 -2
- package/dist/components/form/form.d.ts.map +1 -1
- package/dist/components/form/form.js +157 -59
- package/dist/components/icon/icon-paths.d.ts +16 -0
- package/dist/components/icon/icon-paths.d.ts.map +1 -1
- package/dist/components/icon/icon-paths.js +16 -0
- package/dist/components/icon/icon.d.ts +2 -1
- package/dist/components/icon/icon.d.ts.map +1 -1
- package/dist/components/modal/modal.d.ts +11 -0
- package/dist/components/modal/modal.d.ts.map +1 -1
- package/dist/components/modal/modal.js +103 -15
- package/dist/components/router/router.d.ts +27 -3
- package/dist/components/router/router.d.ts.map +1 -1
- package/dist/components/router/router.js +72 -12
- package/dist/components/skeleton/skeleton.d.ts +2 -3
- package/dist/components/skeleton/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton/skeleton.js +89 -18
- package/dist/components/vertical-nav/vertical-nav-group.d.ts +6 -0
- package/dist/components/vertical-nav/vertical-nav-group.d.ts.map +1 -1
- package/dist/components/vertical-nav/vertical-nav-group.js +37 -21
- package/dist/components/vertical-nav/vertical-nav-item.d.ts +6 -0
- package/dist/components/vertical-nav/vertical-nav-item.d.ts.map +1 -1
- package/dist/components/vertical-nav/vertical-nav-item.js +27 -7
- package/package.json +5 -1
- package/src/components/checkbox/checkbox.ts +54 -26
- package/src/components/form/form-step.ts +5 -1
- package/src/components/form/form.ts +182 -66
- package/src/components/icon/icon-paths.ts +16 -0
- package/src/components/icon/icon.ts +3 -1
- package/src/components/modal/modal.ts +103 -15
- package/src/components/router/router.ts +99 -12
- package/src/components/skeleton/skeleton.ts +87 -20
- package/src/components/vertical-nav/vertical-nav-group.ts +40 -21
- package/src/components/vertical-nav/vertical-nav-item.ts +30 -7
|
@@ -11,11 +11,14 @@ export declare class StCheckbox extends LitElement {
|
|
|
11
11
|
disabled: boolean;
|
|
12
12
|
invalid: boolean;
|
|
13
13
|
required: boolean;
|
|
14
|
+
errorMessage: string;
|
|
14
15
|
ariaLabel: string;
|
|
15
16
|
constructor();
|
|
16
17
|
static styles: import("lit").CSSResult[];
|
|
17
18
|
updated(changedProperties: PropertyValues<this>): void;
|
|
18
19
|
private _syncValidity;
|
|
20
|
+
checkValidity(): boolean;
|
|
21
|
+
reportValidity(): boolean;
|
|
19
22
|
formResetCallback(): void;
|
|
20
23
|
private _handleChange;
|
|
21
24
|
render(): import("lit-html").TemplateResult<1>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/checkbox/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,cAAc,EAAC,MAAM,KAAK,CAAC;AAI1D,qBACa,UAAW,SAAQ,UAAU;IACxC,MAAM,CAAC,cAAc,UAAQ;IAC7B,OAAO,CAAC,UAAU,CAAmB;IAErB,OAAO,CAAC,QAAQ,CAAoB;IAEX,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAChC,IAAI,SAAM;
|
|
1
|
+
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/checkbox/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,cAAc,EAAC,MAAM,KAAK,CAAC;AAI1D,qBACa,UAAW,SAAQ,UAAU;IACxC,MAAM,CAAC,cAAc,UAAQ;IAC7B,OAAO,CAAC,UAAU,CAAmB;IAErB,OAAO,CAAC,QAAQ,CAAoB;IAEX,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAChC,IAAI,SAAM;IACzB,KAAK,SAAQ;IAEG,OAAO,UAAS;IAChB,aAAa,UAAS;IAEtB,QAAQ,UAAS;IACjB,OAAO,UAAS;IAChB,QAAQ,UAAS;IACjC,YAAY,SAAM;IAEP,SAAS,SAAM;IAEpD,cAWC;IAED,MAAM,CAAC,MAAM,4BA6GX;IAEO,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,QAWvD;IAED,OAAO,CAAC,aAAa;IAmBd,aAAa,IAAI,OAAO,CAkB9B;IAEM,cAAc,IAAI,OAAO,CAK/B;IAED,iBAAiB,SAMhB;IAED,OAAO,CAAC,aAAa;IAkBrB,MAAM,yCAwBL;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,aAAa,EAAE,UAAU,CAAC;KAC3B;CACF"}
|
|
@@ -12,28 +12,25 @@ let StCheckbox = class StCheckbox extends LitElement {
|
|
|
12
12
|
super();
|
|
13
13
|
this.size = "md";
|
|
14
14
|
this.name = "";
|
|
15
|
-
// Checkboxes default to 'on' natively if no value is provided
|
|
16
15
|
this.value = "on";
|
|
17
16
|
this.checked = false;
|
|
18
17
|
this.indeterminate = false;
|
|
19
18
|
this.disabled = false;
|
|
20
19
|
this.invalid = false;
|
|
21
20
|
this.required = false;
|
|
21
|
+
this.errorMessage = "";
|
|
22
22
|
this.ariaLabel = "";
|
|
23
23
|
this._internals = this.attachInternals();
|
|
24
|
-
// 1. Trigger error state if the user clicks away and the field is invalid
|
|
25
24
|
this.addEventListener('focusout', () => {
|
|
26
|
-
this.invalid = !this.
|
|
25
|
+
this.invalid = !this.checkValidity();
|
|
27
26
|
});
|
|
28
|
-
// 2. Trigger error state if the st-form tries to submit and fails
|
|
29
27
|
this.addEventListener('invalid', () => {
|
|
30
|
-
this.invalid =
|
|
28
|
+
this.invalid = !this.checkValidity();
|
|
31
29
|
});
|
|
32
30
|
}
|
|
33
31
|
updated(changedProperties) {
|
|
34
32
|
super.updated(changedProperties);
|
|
35
|
-
if (changedProperties.has("checked") || changedProperties.has("value")) {
|
|
36
|
-
// Form API: If checked, submit the value. If unchecked, submit null to remove it from FormData.
|
|
33
|
+
if (changedProperties.has("checked") || changedProperties.has("value") || changedProperties.has("errorMessage")) {
|
|
37
34
|
this._internals.setFormValue(this.checked ? this.value : null);
|
|
38
35
|
this._syncValidity();
|
|
39
36
|
}
|
|
@@ -44,11 +41,38 @@ let StCheckbox = class StCheckbox extends LitElement {
|
|
|
44
41
|
_syncValidity() {
|
|
45
42
|
if (!this._inputEl)
|
|
46
43
|
return;
|
|
47
|
-
|
|
44
|
+
if (this.required && !this.checked) {
|
|
45
|
+
const message = this.errorMessage || this._inputEl.validationMessage || "Please check this box if you want to proceed.";
|
|
46
|
+
this._internals.setValidity({ valueMissing: true }, message, this._inputEl);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this._internals.setValidity(this._inputEl.validity, this._inputEl.validationMessage, this._inputEl);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
checkValidity() {
|
|
53
|
+
if (!this._inputEl)
|
|
54
|
+
return true;
|
|
55
|
+
if (this.required && !this.checked) {
|
|
56
|
+
const message = this.errorMessage || this._inputEl.validationMessage || "Please check this box if you want to proceed.";
|
|
57
|
+
this._internals.setValidity({ valueMissing: true }, message, this._inputEl);
|
|
58
|
+
this.invalid = true;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const isValid = this._inputEl.checkValidity();
|
|
62
|
+
this._syncValidity();
|
|
63
|
+
this.invalid = !isValid;
|
|
64
|
+
return isValid;
|
|
65
|
+
}
|
|
66
|
+
reportValidity() {
|
|
67
|
+
this._syncValidity();
|
|
68
|
+
const isValid = this._internals.reportValidity();
|
|
69
|
+
this.invalid = !isValid;
|
|
70
|
+
return isValid;
|
|
48
71
|
}
|
|
49
72
|
formResetCallback() {
|
|
50
73
|
this.checked = false;
|
|
51
74
|
this.indeterminate = false;
|
|
75
|
+
this.invalid = false;
|
|
52
76
|
this._internals.setFormValue(null);
|
|
53
77
|
this.updateComplete.then(() => this._syncValidity());
|
|
54
78
|
}
|
|
@@ -56,11 +80,13 @@ let StCheckbox = class StCheckbox extends LitElement {
|
|
|
56
80
|
e.stopPropagation();
|
|
57
81
|
if (this.disabled)
|
|
58
82
|
return;
|
|
59
|
-
// Standard native behavior: clicking an indeterminate checkbox unsets the indeterminate state
|
|
60
83
|
if (this.indeterminate) {
|
|
61
84
|
this.indeterminate = false;
|
|
62
85
|
}
|
|
63
86
|
this.checked = this._inputEl.checked;
|
|
87
|
+
if (this.checkValidity()) {
|
|
88
|
+
this.invalid = false;
|
|
89
|
+
}
|
|
64
90
|
this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
|
65
91
|
}
|
|
66
92
|
render() {
|
|
@@ -78,7 +104,6 @@ let StCheckbox = class StCheckbox extends LitElement {
|
|
|
78
104
|
@change=${this._handleChange}
|
|
79
105
|
/>
|
|
80
106
|
<div class="control">
|
|
81
|
-
<!-- Render both SVGs and use CSS to conditionally reveal them based on host attributes -->
|
|
82
107
|
${this.indeterminate
|
|
83
108
|
? html `<svg class="icon-minus" viewBox="0 0 24 24"><path d="M5 12h14"></path></svg>`
|
|
84
109
|
: html `<svg class="icon-check" viewBox="0 0 24 24">
|
|
@@ -120,7 +145,6 @@ StCheckbox.styles = [
|
|
|
120
145
|
font-size: var(--st-font-size-base);
|
|
121
146
|
}
|
|
122
147
|
|
|
123
|
-
/* Visually hide the native input but keep it in the DOM for focus/screen readers */
|
|
124
148
|
input {
|
|
125
149
|
position: absolute;
|
|
126
150
|
width: var(--checkbox-size);
|
|
@@ -133,7 +157,6 @@ StCheckbox.styles = [
|
|
|
133
157
|
border-width: 0;
|
|
134
158
|
}
|
|
135
159
|
|
|
136
|
-
/* Custom Checkbox Box */
|
|
137
160
|
.control {
|
|
138
161
|
display: flex;
|
|
139
162
|
align-items: center;
|
|
@@ -145,30 +168,25 @@ StCheckbox.styles = [
|
|
|
145
168
|
background-color: var(--st-color-bg);
|
|
146
169
|
transition: all 0.2s ease;
|
|
147
170
|
flex-shrink: 0;
|
|
148
|
-
/* Aligns the box nicely with standard text line-height */
|
|
149
171
|
margin-top: 0.125rem;
|
|
150
172
|
}
|
|
151
173
|
|
|
152
|
-
/* Hover State */
|
|
153
174
|
label:hover .control {
|
|
154
175
|
border-color: var(--st-color-primary-hover);
|
|
155
176
|
}
|
|
156
177
|
|
|
157
|
-
/* Focus State */
|
|
158
178
|
input:focus-visible + .control {
|
|
159
179
|
box-shadow:
|
|
160
180
|
0 0 0 2px var(--st-color-bg),
|
|
161
181
|
0 0 0 4px var(--st-color-primary);
|
|
162
182
|
}
|
|
163
183
|
|
|
164
|
-
/* Checked & Indeterminate States */
|
|
165
184
|
:host([checked]) .control,
|
|
166
185
|
:host([indeterminate]) .control {
|
|
167
186
|
border-color: var(--st-color-primary);
|
|
168
187
|
background-color: var(--st-color-primary);
|
|
169
188
|
}
|
|
170
189
|
|
|
171
|
-
/* SVG Icons */
|
|
172
190
|
svg {
|
|
173
191
|
width: var(--checkbox-icon-size);
|
|
174
192
|
height: var(--checkbox-icon-size);
|
|
@@ -184,14 +202,12 @@ StCheckbox.styles = [
|
|
|
184
202
|
opacity 0.2s ease;
|
|
185
203
|
}
|
|
186
204
|
|
|
187
|
-
/* Reveal Icons */
|
|
188
205
|
:host([checked]) svg.icon-check,
|
|
189
206
|
:host([indeterminate]) svg.icon-minus {
|
|
190
207
|
opacity: 1;
|
|
191
208
|
transform: scale(1);
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
/* Disabled State */
|
|
195
211
|
:host([disabled]) {
|
|
196
212
|
pointer-events: none;
|
|
197
213
|
}
|
|
@@ -200,7 +216,6 @@ StCheckbox.styles = [
|
|
|
200
216
|
cursor: not-allowed;
|
|
201
217
|
}
|
|
202
218
|
|
|
203
|
-
/* Invalid State */
|
|
204
219
|
:host([invalid]) .control {
|
|
205
220
|
border-color: var(--st-color-error);
|
|
206
221
|
}
|
|
@@ -238,6 +253,9 @@ __decorate([
|
|
|
238
253
|
__decorate([
|
|
239
254
|
property({ type: Boolean, reflect: true })
|
|
240
255
|
], StCheckbox.prototype, "required", void 0);
|
|
256
|
+
__decorate([
|
|
257
|
+
property({ type: String })
|
|
258
|
+
], StCheckbox.prototype, "errorMessage", void 0);
|
|
241
259
|
__decorate([
|
|
242
260
|
property({ attribute: "aria-label" })
|
|
243
261
|
], StCheckbox.prototype, "ariaLabel", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-step.d.ts","sourceRoot":"","sources":["../../../src/components/form/form-step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAY,MAAM,KAAK,CAAC;AAI1C,qBACa,UAAW,SAAQ,UAAU;IACd,KAAK,SAAM;IACK,MAAM,UAAS;
|
|
1
|
+
{"version":3,"file":"form-step.d.ts","sourceRoot":"","sources":["../../../src/components/form/form-step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAY,MAAM,KAAK,CAAC;AAI1C,qBACa,UAAW,SAAQ,UAAU;IACd,KAAK,SAAM;IACK,MAAM,UAAS;IAIzD,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAE5C,MAAM,CAAC,MAAM,4BAWX;IAEF,MAAM,yCAEL;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,UAAU,CAAC;KAC5B;CACF"}
|
|
@@ -35,6 +35,9 @@ __decorate([
|
|
|
35
35
|
__decorate([
|
|
36
36
|
property({ type: Boolean, reflect: true })
|
|
37
37
|
], StFormStep.prototype, "active", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
property({ attribute: false })
|
|
40
|
+
], StFormStep.prototype, "validate", void 0);
|
|
38
41
|
StFormStep = __decorate([
|
|
39
42
|
customElement("st-form-step")
|
|
40
43
|
], StFormStep);
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { LitElement } from "lit";
|
|
1
|
+
import { LitElement, PropertyValues } from "lit";
|
|
2
2
|
export type FormLayout = "vertical" | "horizontal" | "inline";
|
|
3
3
|
export declare class StForm extends LitElement {
|
|
4
4
|
layout: FormLayout;
|
|
5
5
|
loading: boolean;
|
|
6
6
|
error: string;
|
|
7
7
|
private _currentStepIndex;
|
|
8
|
-
private _stepElements;
|
|
9
8
|
private _formEl;
|
|
9
|
+
private _modalFooterEl;
|
|
10
|
+
private get _steps();
|
|
10
11
|
static styles: import("lit").CSSResult[];
|
|
12
|
+
connectedCallback(): void;
|
|
13
|
+
disconnectedCallback(): void;
|
|
14
|
+
updated(changedProperties: PropertyValues<this>): void;
|
|
15
|
+
private _updateModalFooter;
|
|
11
16
|
private _handleSlotChange;
|
|
12
17
|
private _updateStepVisibility;
|
|
13
18
|
private _validateCurrentContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/components/form/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/components/form/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAa,cAAc,EAAC,MAAM,KAAK,CAAC;AAK1D,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,QAAQ,CAAC;AAE9D,qBACa,MAAO,SAAQ,UAAU;IACK,MAAM,EAAE,UAAU,CAAc;IAC/B,OAAO,UAAS;IAChC,KAAK,SAAM;IAE5B,OAAO,CAAC,iBAAiB,CAAK;IAExB,OAAO,CAAC,OAAO,CAAmB;IAEjD,OAAO,CAAC,cAAc,CAA4B;IAElD,OAAO,KAAK,MAAM,GAEjB;IAED,MAAM,CAAC,MAAM,4BAqIX;IAEO,iBAAiB,SAMzB;IAEQ,oBAAoB,SAM5B;IAEQ,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,QAGvD;IAED,OAAO,CAAC,kBAAkB;IAmD1B,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,qBAAqB;YAQf,uBAAuB;IAiFrC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,gBAAgB;YAkCV,aAAa;IA6B3B,MAAM,yCAsFL;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { LitElement, html, css } from "lit";
|
|
8
|
-
import { customElement, property, state,
|
|
8
|
+
import { customElement, property, state, query } from "lit/decorators.js";
|
|
9
9
|
import { resetStyles } from "../../styles/reset.js";
|
|
10
10
|
let StForm = class StForm extends LitElement {
|
|
11
11
|
constructor() {
|
|
@@ -14,41 +14,151 @@ let StForm = class StForm extends LitElement {
|
|
|
14
14
|
this.loading = false;
|
|
15
15
|
this.error = "";
|
|
16
16
|
this._currentStepIndex = 0;
|
|
17
|
+
this._modalFooterEl = null;
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
get _steps() {
|
|
20
|
+
return Array.from(this.querySelectorAll("st-form-step"));
|
|
21
|
+
}
|
|
22
|
+
connectedCallback() {
|
|
23
|
+
super.connectedCallback();
|
|
24
|
+
this.updateComplete.then(() => {
|
|
20
25
|
this._updateStepVisibility();
|
|
26
|
+
this._updateModalFooter();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
disconnectedCallback() {
|
|
30
|
+
super.disconnectedCallback();
|
|
31
|
+
if (this._modalFooterEl) {
|
|
32
|
+
this._modalFooterEl.remove();
|
|
33
|
+
this._modalFooterEl = null;
|
|
21
34
|
}
|
|
22
35
|
}
|
|
36
|
+
updated(changedProperties) {
|
|
37
|
+
super.updated(changedProperties);
|
|
38
|
+
this._updateModalFooter();
|
|
39
|
+
}
|
|
40
|
+
_updateModalFooter() {
|
|
41
|
+
const modal = this.closest("st-modal");
|
|
42
|
+
if (modal) {
|
|
43
|
+
if (!this._modalFooterEl) {
|
|
44
|
+
this._modalFooterEl = document.createElement("div");
|
|
45
|
+
this._modalFooterEl.setAttribute("slot", "footer");
|
|
46
|
+
this._modalFooterEl.style.display = "flex";
|
|
47
|
+
this._modalFooterEl.style.gap = "var(--st-spacing-md)";
|
|
48
|
+
this._modalFooterEl.style.width = "100%";
|
|
49
|
+
this._modalFooterEl.style.justifyContent = "flex-end";
|
|
50
|
+
this._modalFooterEl.style.alignItems = "center";
|
|
51
|
+
modal.appendChild(this._modalFooterEl);
|
|
52
|
+
}
|
|
53
|
+
const steps = this._steps;
|
|
54
|
+
const hasSteps = steps.length > 0;
|
|
55
|
+
const isLastStep = hasSteps ? this._currentStepIndex === steps.length - 1 : true;
|
|
56
|
+
// Imperative DOM management prevents event listener loss and re-rendering conflicts
|
|
57
|
+
this._modalFooterEl.innerHTML = "";
|
|
58
|
+
if (hasSteps && this._currentStepIndex > 0) {
|
|
59
|
+
const backBtn = document.createElement("st-button");
|
|
60
|
+
backBtn.setAttribute("variant", "secondary");
|
|
61
|
+
backBtn.setAttribute("type", "button");
|
|
62
|
+
if (this.loading)
|
|
63
|
+
backBtn.setAttribute("disabled", "");
|
|
64
|
+
backBtn.textContent = "Back";
|
|
65
|
+
backBtn.addEventListener("click", (e) => {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
this._prevStep();
|
|
68
|
+
});
|
|
69
|
+
this._modalFooterEl.appendChild(backBtn);
|
|
70
|
+
}
|
|
71
|
+
const submitBtn = document.createElement("st-button");
|
|
72
|
+
submitBtn.setAttribute("color", "primary");
|
|
73
|
+
submitBtn.setAttribute("type", "button");
|
|
74
|
+
if (this.loading)
|
|
75
|
+
submitBtn.setAttribute("disabled", "");
|
|
76
|
+
submitBtn.textContent = this.loading ? "Submitting..." : (isLastStep ? "Submit" : "Continue");
|
|
77
|
+
submitBtn.addEventListener("click", (e) => {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
this._triggerSubmission();
|
|
80
|
+
});
|
|
81
|
+
this._modalFooterEl.appendChild(submitBtn);
|
|
82
|
+
}
|
|
83
|
+
else if (this._modalFooterEl) {
|
|
84
|
+
this._modalFooterEl.remove();
|
|
85
|
+
this._modalFooterEl = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
_handleSlotChange() {
|
|
89
|
+
this._updateStepVisibility();
|
|
90
|
+
this._updateModalFooter();
|
|
91
|
+
}
|
|
23
92
|
_updateStepVisibility() {
|
|
24
|
-
|
|
93
|
+
const steps = this._steps;
|
|
94
|
+
steps.forEach((step, index) => {
|
|
25
95
|
step.active = index === this._currentStepIndex;
|
|
26
96
|
});
|
|
27
97
|
this.requestUpdate();
|
|
28
98
|
}
|
|
29
|
-
_validateCurrentContext() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
99
|
+
async _validateCurrentContext() {
|
|
100
|
+
const steps = this._steps;
|
|
101
|
+
const scope = steps.length > 0
|
|
102
|
+
? steps[this._currentStepIndex]
|
|
103
|
+
: this;
|
|
34
104
|
let isValid = true;
|
|
35
|
-
|
|
36
|
-
const inputs = Array.from(currentStep.querySelectorAll("*"));
|
|
105
|
+
const inputs = Array.from(scope.querySelectorAll("st-input, st-select, st-textarea, st-checkbox, st-radio, input, select, textarea"));
|
|
37
106
|
for (const input of inputs) {
|
|
107
|
+
if (input.hasAttribute("disabled") || input.disabled)
|
|
108
|
+
continue;
|
|
109
|
+
let fieldValid = true;
|
|
38
110
|
if (typeof input.checkValidity === "function") {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
111
|
+
fieldValid = input.checkValidity();
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const isRequired = input.hasAttribute("required") || input.required;
|
|
115
|
+
if (isRequired) {
|
|
116
|
+
const isToggle = input.tagName === "ST-CHECKBOX" || input.tagName === "ST-RADIO";
|
|
117
|
+
const val = isToggle ? input.checked : input.value;
|
|
118
|
+
if (val === undefined || val === null || val === "" || val === false) {
|
|
119
|
+
fieldValid = false;
|
|
43
120
|
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!fieldValid) {
|
|
124
|
+
if (typeof input.reportValidity === "function") {
|
|
125
|
+
input.reportValidity();
|
|
126
|
+
}
|
|
127
|
+
else if ("invalid" in input) {
|
|
128
|
+
input.invalid = true;
|
|
129
|
+
}
|
|
130
|
+
if (isValid && typeof input.focus === "function") {
|
|
131
|
+
input.focus();
|
|
132
|
+
}
|
|
133
|
+
isValid = false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (steps.length === 0 && this._formEl) {
|
|
137
|
+
if (!this._formEl.checkValidity()) {
|
|
138
|
+
isValid = false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (isValid && steps.length > 0) {
|
|
142
|
+
const currentStep = steps[this._currentStepIndex];
|
|
143
|
+
if (typeof currentStep.validate === "function") {
|
|
144
|
+
try {
|
|
145
|
+
this.loading = true;
|
|
146
|
+
const stepPassed = await currentStep.validate();
|
|
147
|
+
if (!stepPassed) {
|
|
148
|
+
isValid = false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
44
152
|
isValid = false;
|
|
45
153
|
}
|
|
154
|
+
finally {
|
|
155
|
+
this.loading = false;
|
|
156
|
+
}
|
|
46
157
|
}
|
|
47
158
|
}
|
|
48
159
|
return isValid;
|
|
49
160
|
}
|
|
50
161
|
_triggerSubmission() {
|
|
51
|
-
// HTML5 method that triggers form validation and fires the native submit event
|
|
52
162
|
this._formEl.requestSubmit();
|
|
53
163
|
}
|
|
54
164
|
_prevStep() {
|
|
@@ -59,10 +169,8 @@ let StForm = class StForm extends LitElement {
|
|
|
59
169
|
}
|
|
60
170
|
_extractFormData() {
|
|
61
171
|
const formData = new FormData();
|
|
62
|
-
// Query all light-DOM children that have a 'name' attribute
|
|
63
172
|
const fields = this.querySelectorAll("[name]");
|
|
64
173
|
fields.forEach((field) => {
|
|
65
|
-
// Standard HTML form behavior: ignore disabled fields
|
|
66
174
|
if (field.hasAttribute("disabled"))
|
|
67
175
|
return;
|
|
68
176
|
const isToggle = field.tagName === "ST-RADIO" ||
|
|
@@ -70,7 +178,6 @@ let StForm = class StForm extends LitElement {
|
|
|
70
178
|
field.getAttribute("type") === "radio" ||
|
|
71
179
|
field.getAttribute("type") === "checkbox";
|
|
72
180
|
if (isToggle) {
|
|
73
|
-
// Only append radios/checkboxes if they are actively checked
|
|
74
181
|
if (field.checked) {
|
|
75
182
|
formData.append(field.name, field.value || "on");
|
|
76
183
|
}
|
|
@@ -78,29 +185,28 @@ let StForm = class StForm extends LitElement {
|
|
|
78
185
|
else if (field.tagName === "INPUT" &&
|
|
79
186
|
field.getAttribute("type") === "file" &&
|
|
80
187
|
field.files) {
|
|
81
|
-
// Handle native file uploads
|
|
82
188
|
Array.from(field.files).forEach((file) => formData.append(field.name, file));
|
|
83
189
|
}
|
|
84
190
|
else if (field.value !== undefined) {
|
|
85
|
-
// Handle st-input, st-select, st-textarea, and standard inputs
|
|
86
191
|
formData.append(field.name, field.value);
|
|
87
192
|
}
|
|
88
193
|
});
|
|
89
194
|
return formData;
|
|
90
195
|
}
|
|
91
|
-
_handleSubmit(e) {
|
|
196
|
+
async _handleSubmit(e) {
|
|
92
197
|
e.preventDefault();
|
|
93
198
|
e.stopPropagation();
|
|
94
|
-
|
|
199
|
+
const isValid = await this._validateCurrentContext();
|
|
200
|
+
if (!isValid)
|
|
95
201
|
return;
|
|
96
|
-
const
|
|
97
|
-
const
|
|
202
|
+
const steps = this._steps;
|
|
203
|
+
const hasSteps = steps.length > 0;
|
|
204
|
+
const isLastStep = hasSteps ? this._currentStepIndex === steps.length - 1 : true;
|
|
98
205
|
if (hasSteps && !isLastStep) {
|
|
99
206
|
this._currentStepIndex++;
|
|
100
207
|
this._updateStepVisibility();
|
|
101
208
|
return;
|
|
102
209
|
}
|
|
103
|
-
// Use our custom extractor to pierce the Shadow DOM boundary
|
|
104
210
|
const formData = this._extractFormData();
|
|
105
211
|
this.dispatchEvent(new CustomEvent("submit", {
|
|
106
212
|
bubbles: true,
|
|
@@ -110,8 +216,9 @@ let StForm = class StForm extends LitElement {
|
|
|
110
216
|
}));
|
|
111
217
|
}
|
|
112
218
|
render() {
|
|
113
|
-
const
|
|
114
|
-
const
|
|
219
|
+
const steps = this._steps;
|
|
220
|
+
const hasSteps = steps.length > 0;
|
|
221
|
+
const isInModal = !!this.closest("st-modal");
|
|
115
222
|
return html `
|
|
116
223
|
<div class="${hasSteps ? "has-steps" : ""}" aria-busy=${this.loading}>
|
|
117
224
|
${this.loading
|
|
@@ -124,7 +231,7 @@ let StForm = class StForm extends LitElement {
|
|
|
124
231
|
${hasSteps
|
|
125
232
|
? html `
|
|
126
233
|
<div class="progress-nav" role="tablist">
|
|
127
|
-
${
|
|
234
|
+
${steps.map((step, index) => {
|
|
128
235
|
const isActive = index === this._currentStepIndex;
|
|
129
236
|
const isCompleted = index < this._currentStepIndex;
|
|
130
237
|
return html `
|
|
@@ -142,7 +249,7 @@ let StForm = class StForm extends LitElement {
|
|
|
142
249
|
</div>
|
|
143
250
|
<span>${step.title || `Step ${index + 1}`}</span>
|
|
144
251
|
</div>
|
|
145
|
-
${index <
|
|
252
|
+
${index < steps.length - 1
|
|
146
253
|
? html ` <div class="step-connector ${isCompleted ? "completed" : ""}"></div> `
|
|
147
254
|
: ""}
|
|
148
255
|
`;
|
|
@@ -162,30 +269,33 @@ let StForm = class StForm extends LitElement {
|
|
|
162
269
|
<form @submit=${this._handleSubmit}>
|
|
163
270
|
<slot @slotchange=${this._handleSlotChange}></slot>
|
|
164
271
|
|
|
165
|
-
|
|
166
|
-
${hasSteps && this._currentStepIndex > 0
|
|
272
|
+
${!isInModal
|
|
167
273
|
? html `
|
|
274
|
+
<div class="form-actions">
|
|
275
|
+
${hasSteps && this._currentStepIndex > 0
|
|
276
|
+
? html `
|
|
277
|
+
<st-button
|
|
278
|
+
variant="secondary"
|
|
279
|
+
type="button"
|
|
280
|
+
@click=${this._prevStep}
|
|
281
|
+
?disabled=${this.loading}
|
|
282
|
+
>
|
|
283
|
+
Back
|
|
284
|
+
</st-button>
|
|
285
|
+
`
|
|
286
|
+
: ""}
|
|
287
|
+
|
|
168
288
|
<st-button
|
|
169
|
-
|
|
289
|
+
color="primary"
|
|
170
290
|
type="button"
|
|
171
|
-
@click=${this.
|
|
291
|
+
@click=${this._triggerSubmission}
|
|
172
292
|
?disabled=${this.loading}
|
|
173
293
|
>
|
|
174
|
-
|
|
294
|
+
${this.loading ? "Submitting..." : hasSteps && this._currentStepIndex === steps.length - 1 ? "Submit" : hasSteps ? "Continue" : "Submit"}
|
|
175
295
|
</st-button>
|
|
176
|
-
|
|
296
|
+
</div>
|
|
297
|
+
`
|
|
177
298
|
: ""}
|
|
178
|
-
|
|
179
|
-
<!-- Type is "button", but click triggers requestSubmit() on the internal form -->
|
|
180
|
-
<st-button
|
|
181
|
-
color="primary"
|
|
182
|
-
type="button"
|
|
183
|
-
@click=${this._triggerSubmission}
|
|
184
|
-
?disabled=${this.loading}
|
|
185
|
-
>
|
|
186
|
-
${this.loading ? "Submitting..." : isLastStep ? "Submit" : "Continue"}
|
|
187
|
-
</st-button>
|
|
188
|
-
</div>
|
|
189
299
|
</form>
|
|
190
300
|
</div>
|
|
191
301
|
`;
|
|
@@ -204,9 +314,6 @@ StForm.styles = [
|
|
|
204
314
|
gap: var(--st-spacing-md);
|
|
205
315
|
}
|
|
206
316
|
|
|
207
|
-
/* ==========================================================
|
|
208
|
-
Layouts
|
|
209
|
-
========================================================== */
|
|
210
317
|
:host([layout="vertical"]) form {
|
|
211
318
|
flex-direction: column;
|
|
212
319
|
}
|
|
@@ -228,9 +335,6 @@ StForm.styles = [
|
|
|
228
335
|
flex-direction: column;
|
|
229
336
|
}
|
|
230
337
|
|
|
231
|
-
/* ==========================================================
|
|
232
|
-
Progress Navigation
|
|
233
|
-
========================================================== */
|
|
234
338
|
.progress-nav {
|
|
235
339
|
display: flex;
|
|
236
340
|
align-items: center;
|
|
@@ -294,9 +398,6 @@ StForm.styles = [
|
|
|
294
398
|
background-color: var(--st-color-success);
|
|
295
399
|
}
|
|
296
400
|
|
|
297
|
-
/* ==========================================================
|
|
298
|
-
Actions & States
|
|
299
|
-
========================================================== */
|
|
300
401
|
.form-actions {
|
|
301
402
|
display: flex;
|
|
302
403
|
gap: var(--st-spacing-md);
|
|
@@ -346,9 +447,6 @@ __decorate([
|
|
|
346
447
|
__decorate([
|
|
347
448
|
state()
|
|
348
449
|
], StForm.prototype, "_currentStepIndex", void 0);
|
|
349
|
-
__decorate([
|
|
350
|
-
queryAssignedElements({ selector: "st-form-step" })
|
|
351
|
-
], StForm.prototype, "_stepElements", void 0);
|
|
352
450
|
__decorate([
|
|
353
451
|
query("form")
|
|
354
452
|
], StForm.prototype, "_formEl", void 0);
|
|
@@ -111,6 +111,22 @@ export declare const iconPaths: {
|
|
|
111
111
|
outline: import("lit-html").TemplateResult<2>;
|
|
112
112
|
solid: import("lit-html").TemplateResult<2>;
|
|
113
113
|
};
|
|
114
|
+
calender: {
|
|
115
|
+
outline: import("lit-html").TemplateResult<2>;
|
|
116
|
+
solid: import("lit-html").TemplateResult<2>;
|
|
117
|
+
};
|
|
118
|
+
user: {
|
|
119
|
+
outline: import("lit-html").TemplateResult<2>;
|
|
120
|
+
solid: import("lit-html").TemplateResult<2>;
|
|
121
|
+
};
|
|
122
|
+
home: {
|
|
123
|
+
outline: import("lit-html").TemplateResult<2>;
|
|
124
|
+
solid: import("lit-html").TemplateResult<2>;
|
|
125
|
+
};
|
|
126
|
+
"circle-cross": {
|
|
127
|
+
outline: import("lit-html").TemplateResult<2>;
|
|
128
|
+
solid: import("lit-html").TemplateResult<2>;
|
|
129
|
+
};
|
|
114
130
|
};
|
|
115
131
|
export type IconName = keyof typeof iconPaths;
|
|
116
132
|
//# sourceMappingURL=icon-paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-paths.d.ts","sourceRoot":"","sources":["../../../src/components/icon/icon-paths.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;IACpB,cAAc;QACZ,OAAO;QACP,KAAK;;IAEP,gBAAgB;QACd,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,gBAAgB;QACd,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,SAAS;QACP,OAAO;QACP,KAAK;;IAEP,iBAAiB;QACf,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,GAAG;QACD,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,SAAS;QACP,OAAO;QACP,KAAK;;IAEP,cAAc;QACZ,OAAO;QACP,KAAK;;IAEP,eAAe;QACb,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,MAAM;QACJ,OAAO;QACP,KAAK;;IAEP,eAAe;QACb,OAAO;QAIP,KAAK;;IAKP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,KAAK;QACH,OAAO;QACP,KAAK;;IAEP,WAAW;QACT,OAAO;QACP,KAAK;;IAEP,MAAM;QACJ,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,sBAAsB;QACpB,OAAO;QACP,KAAK;;IAEP,wBAAwB;QACtB,OAAO;QACP,KAAK;;IAEP,kBAAkB;QAChB,OAAO;QACP,KAAK;;IAEP,qBAAqB;QACnB,OAAO;QACP,KAAK;;CAER,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"icon-paths.d.ts","sourceRoot":"","sources":["../../../src/components/icon/icon-paths.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;IACpB,cAAc;QACZ,OAAO;QACP,KAAK;;IAEP,gBAAgB;QACd,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,gBAAgB;QACd,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,SAAS;QACP,OAAO;QACP,KAAK;;IAEP,iBAAiB;QACf,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,GAAG;QACD,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,SAAS;QACP,OAAO;QACP,KAAK;;IAEP,cAAc;QACZ,OAAO;QACP,KAAK;;IAEP,eAAe;QACb,OAAO;QACP,KAAK;;IAEP,OAAO;QACL,OAAO;QACP,KAAK;;IAEP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,MAAM;QACJ,OAAO;QACP,KAAK;;IAEP,eAAe;QACb,OAAO;QAIP,KAAK;;IAKP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,KAAK;QACH,OAAO;QACP,KAAK;;IAEP,WAAW;QACT,OAAO;QACP,KAAK;;IAEP,MAAM;QACJ,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,sBAAsB;QACpB,OAAO;QACP,KAAK;;IAEP,wBAAwB;QACtB,OAAO;QACP,KAAK;;IAEP,kBAAkB;QAChB,OAAO;QACP,KAAK;;IAEP,qBAAqB;QACnB,OAAO;QACP,KAAK;;IAEP,QAAQ;QACN,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,IAAI;QACF,OAAO;QACP,KAAK;;IAEP,cAAc;QACZ,OAAO;QACP,KAAK;;CAER,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,CAAC"}
|
|
@@ -118,4 +118,20 @@ export const iconPaths = {
|
|
|
118
118
|
outline: svg `<rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"></rect><line x1="3" y1="8" x2="21" y2="8" stroke="currentColor" stroke-width="2"></line><line x1="7" y1="8" x2="7" y2="21" stroke="currentColor" stroke-width="2"></line><line x1="17" y1="8" x2="17" y2="21" stroke="currentColor" stroke-width="2"></line><line x1="10" y1="14" x2="14" y2="14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></line>`,
|
|
119
119
|
solid: svg `<path fill="currentColor" d="M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5zm2 3h14V5H5v3zM7 9H3v12h4V9zm14 0h-4v12h4V9z"></path>`,
|
|
120
120
|
},
|
|
121
|
+
calender: {
|
|
122
|
+
outline: svg `<rect x="3" y="4" width="18" height="18" rx="2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></rect><line x1="16" y1="2" x2="16" y2="6" stroke="currentColor" stroke-width="2" stroke-linecap="round"></line><line x1="8" y1="2" x2="8" y2="6" stroke="currentColor" stroke-width="2" stroke-linecap="round"></line><line x1="3" y1="10" x2="21" y2="10" stroke="currentColor" stroke-width="2"></line>`,
|
|
123
|
+
solid: svg `<path fill="currentColor" d="M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 16H5V9h14v11z"></path>`,
|
|
124
|
+
},
|
|
125
|
+
user: {
|
|
126
|
+
outline: svg `<circle cx="12" cy="8" r="4" fill="none" stroke="currentColor" stroke-width="2"></circle><path d="M4 20c0-4 4-6 8-6s8 2 8 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path>`,
|
|
127
|
+
solid: svg `<path fill="currentColor" d="M12 12a5 5 0 1 0-5-5 5 5 0 0 0 5 5zm0 2c-3.33 0-10 1.67-10 5v3h20v-3c0-3.33-6.67-5-10-5z"></path>`,
|
|
128
|
+
},
|
|
129
|
+
home: {
|
|
130
|
+
outline: svg `<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></polyline>`,
|
|
131
|
+
solid: svg `<path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path>`,
|
|
132
|
+
},
|
|
133
|
+
"circle-cross": {
|
|
134
|
+
outline: svg `<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle><line x1="15" y1="9" x2="9" y2="15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></line><line x1="9" y1="9" x2="15" y2="15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></line>`,
|
|
135
|
+
solid: svg `<path fill="currentColor" fill-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm3.36 6.64a1 1 0 0 1 0 1.41L13.41 12l1.95 1.95a1 1 0 0 1-1.41 1.41L12 13.41l-1.95 1.95a1 1 0 0 1-1.41-1.41L10.59 12 8.64 10.05a1 1 0 0 1 1.41-1.41L12 10.59l1.95-1.95a1 1 0 0 1 1.41 0z" clip-rule="evenodd"></path>`,
|
|
136
|
+
},
|
|
121
137
|
};
|