@sondor-technology/sondor-components 1.0.0-1165-initial-setup.11 → 1.0.1-develop.10
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/divider/divider.js +1 -1
- package/dist/components/field/field.js +1 -1
- package/dist/components/form/form.d.ts.map +1 -1
- package/dist/components/form/form.js +33 -27
- 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/link/link.js +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/select/select.js +1 -1
- 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/divider/divider.ts +1 -1
- package/src/components/field/field.ts +1 -1
- package/src/components/form/form.ts +39 -30
- package/src/components/icon/icon-paths.ts +16 -0
- package/src/components/icon/icon.ts +3 -1
- package/src/components/link/link.ts +1 -1
- package/src/components/modal/modal.ts +103 -15
- package/src/components/router/router.ts +99 -12
- package/src/components/select/select.ts +1 -1
- 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
|
@@ -2,7 +2,13 @@ import { LitElement } from 'lit';
|
|
|
2
2
|
export declare class StNavItem extends LitElement {
|
|
3
3
|
href: string;
|
|
4
4
|
active: boolean;
|
|
5
|
+
depth: number;
|
|
5
6
|
static styles: import("lit").CSSResult[];
|
|
6
7
|
render(): import("lit-html").TemplateResult<1>;
|
|
7
8
|
}
|
|
9
|
+
declare global {
|
|
10
|
+
interface HTMLElementTagNameMap {
|
|
11
|
+
'st-vertical-nav-item': StNavItem;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
8
14
|
//# sourceMappingURL=vertical-nav-item.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertical-nav-item.d.ts","sourceRoot":"","sources":["../../../src/components/vertical-nav/vertical-nav-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,qBACa,SAAU,SAAQ,UAAU;IACX,IAAI,SAAO;IACK,MAAM,UAAS;
|
|
1
|
+
{"version":3,"file":"vertical-nav-item.d.ts","sourceRoot":"","sources":["../../../src/components/vertical-nav/vertical-nav-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C,qBACa,SAAU,SAAQ,UAAU;IACX,IAAI,SAAO;IACK,MAAM,UAAS;IAC/B,KAAK,SAAK;IAEtC,MAAM,CAAC,MAAM,4BA8CX;IAEF,MAAM,yCAOL;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,SAAS,CAAC;KACnC;CACF"}
|
|
@@ -12,10 +12,12 @@ let StNavItem = class StNavItem extends LitElement {
|
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.href = '#';
|
|
14
14
|
this.active = false;
|
|
15
|
+
this.depth = 0;
|
|
15
16
|
}
|
|
16
17
|
render() {
|
|
17
18
|
return html `
|
|
18
|
-
<a href=${this.href} part="link">
|
|
19
|
+
<a href=${this.href} part="link" style="--nav-depth: ${this.depth}">
|
|
20
|
+
<slot name="icon"></slot>
|
|
19
21
|
<slot></slot>
|
|
20
22
|
</a>
|
|
21
23
|
`;
|
|
@@ -26,30 +28,45 @@ StNavItem.styles = [
|
|
|
26
28
|
css `
|
|
27
29
|
:host {
|
|
28
30
|
display: block;
|
|
31
|
+
overflow: hidden;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
a {
|
|
32
35
|
display: flex;
|
|
33
36
|
align-items: center;
|
|
34
|
-
|
|
37
|
+
gap: var(--st-spacing-sm, 8px);
|
|
38
|
+
width: 100%;
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
padding: 8px var(--st-spacing-xl);
|
|
41
|
+
padding-left: calc(var(--st-spacing-xl, 24px) + (var(--nav-depth, 0) * 16px));
|
|
35
42
|
color: var(--st-color-text-muted);
|
|
36
43
|
font-size: var(--st-font-size-sm);
|
|
37
44
|
text-decoration: none;
|
|
38
|
-
border-left:
|
|
45
|
+
border-left: 3px solid transparent;
|
|
39
46
|
transition: all 0.15s ease;
|
|
47
|
+
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
text-overflow: ellipsis;
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
a:hover {
|
|
43
54
|
color: var(--st-color-text);
|
|
44
|
-
background-color: var(--st-color-surface);
|
|
55
|
+
background-color: var(--st-color-surface-hover, rgba(0,0,0,0.03));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
::slotted([slot="icon"]) {
|
|
59
|
+
width: 1rem;
|
|
60
|
+
height: 1rem;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
color: inherit;
|
|
45
63
|
}
|
|
46
64
|
|
|
47
|
-
/* Active state: Purple text with a left border indicator */
|
|
48
65
|
:host([active]) a {
|
|
49
66
|
color: var(--st-color-primary);
|
|
50
67
|
border-left-color: var(--st-color-primary);
|
|
51
|
-
font-weight: var(--st-font-weight-
|
|
52
|
-
background-color:
|
|
68
|
+
font-weight: var(--st-font-weight-bold);
|
|
69
|
+
background-color: var(--st-color-primary-light, rgba(98, 0, 238, 0.05));
|
|
53
70
|
}
|
|
54
71
|
`
|
|
55
72
|
];
|
|
@@ -59,6 +76,9 @@ __decorate([
|
|
|
59
76
|
__decorate([
|
|
60
77
|
property({ type: Boolean, reflect: true })
|
|
61
78
|
], StNavItem.prototype, "active", void 0);
|
|
79
|
+
__decorate([
|
|
80
|
+
property({ type: Number })
|
|
81
|
+
], StNavItem.prototype, "depth", void 0);
|
|
62
82
|
StNavItem = __decorate([
|
|
63
83
|
customElement('st-vertical-nav-item')
|
|
64
84
|
], StNavItem);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sondor-technology/sondor-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-develop.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -101,6 +101,10 @@
|
|
|
101
101
|
"types": "./dist/components/icon/icon.d.ts",
|
|
102
102
|
"default": "./dist/components/icon/icon.js"
|
|
103
103
|
},
|
|
104
|
+
"./icon-paths": {
|
|
105
|
+
"types": "./dist/components/icon/icon-paths.d.ts",
|
|
106
|
+
"default": "./dist/components/icon/icon-paths.js"
|
|
107
|
+
},
|
|
104
108
|
"./footer": {
|
|
105
109
|
"types": "./dist/components/footer/footer.d.ts",
|
|
106
110
|
"default": "./dist/components/footer/footer.js"
|
|
@@ -11,7 +11,6 @@ export class StCheckbox extends LitElement {
|
|
|
11
11
|
|
|
12
12
|
@property({type: String, reflect: true}) size: "sm" | "md" | "lg" = "md";
|
|
13
13
|
@property({type: String, reflect: true}) name = "";
|
|
14
|
-
// Checkboxes default to 'on' natively if no value is provided
|
|
15
14
|
@property({type: String}) value = "on";
|
|
16
15
|
|
|
17
16
|
@property({type: Boolean, reflect: true}) checked = false;
|
|
@@ -20,21 +19,20 @@ export class StCheckbox extends LitElement {
|
|
|
20
19
|
@property({type: Boolean, reflect: true}) disabled = false;
|
|
21
20
|
@property({type: Boolean, reflect: true}) invalid = false;
|
|
22
21
|
@property({type: Boolean, reflect: true}) required = false;
|
|
22
|
+
@property({type: String}) errorMessage = "";
|
|
23
23
|
|
|
24
24
|
@property({attribute: "aria-label"}) ariaLabel = "";
|
|
25
25
|
|
|
26
|
-
constructor() {
|
|
26
|
+
constructor() {
|
|
27
27
|
super();
|
|
28
28
|
this._internals = this.attachInternals();
|
|
29
29
|
|
|
30
|
-
// 1. Trigger error state if the user clicks away and the field is invalid
|
|
31
30
|
this.addEventListener('focusout', () => {
|
|
32
|
-
this.invalid = !this.
|
|
31
|
+
this.invalid = !this.checkValidity();
|
|
33
32
|
});
|
|
34
33
|
|
|
35
|
-
// 2. Trigger error state if the st-form tries to submit and fails
|
|
36
34
|
this.addEventListener('invalid', () => {
|
|
37
|
-
this.invalid =
|
|
35
|
+
this.invalid = !this.checkValidity();
|
|
38
36
|
});
|
|
39
37
|
}
|
|
40
38
|
|
|
@@ -67,7 +65,6 @@ constructor() {
|
|
|
67
65
|
font-size: var(--st-font-size-base);
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
/* Visually hide the native input but keep it in the DOM for focus/screen readers */
|
|
71
68
|
input {
|
|
72
69
|
position: absolute;
|
|
73
70
|
width: var(--checkbox-size);
|
|
@@ -80,7 +77,6 @@ constructor() {
|
|
|
80
77
|
border-width: 0;
|
|
81
78
|
}
|
|
82
79
|
|
|
83
|
-
/* Custom Checkbox Box */
|
|
84
80
|
.control {
|
|
85
81
|
display: flex;
|
|
86
82
|
align-items: center;
|
|
@@ -92,30 +88,25 @@ constructor() {
|
|
|
92
88
|
background-color: var(--st-color-bg);
|
|
93
89
|
transition: all 0.2s ease;
|
|
94
90
|
flex-shrink: 0;
|
|
95
|
-
/* Aligns the box nicely with standard text line-height */
|
|
96
91
|
margin-top: 0.125rem;
|
|
97
92
|
}
|
|
98
93
|
|
|
99
|
-
/* Hover State */
|
|
100
94
|
label:hover .control {
|
|
101
95
|
border-color: var(--st-color-primary-hover);
|
|
102
96
|
}
|
|
103
97
|
|
|
104
|
-
/* Focus State */
|
|
105
98
|
input:focus-visible + .control {
|
|
106
99
|
box-shadow:
|
|
107
100
|
0 0 0 2px var(--st-color-bg),
|
|
108
101
|
0 0 0 4px var(--st-color-primary);
|
|
109
102
|
}
|
|
110
103
|
|
|
111
|
-
/* Checked & Indeterminate States */
|
|
112
104
|
:host([checked]) .control,
|
|
113
105
|
:host([indeterminate]) .control {
|
|
114
106
|
border-color: var(--st-color-primary);
|
|
115
107
|
background-color: var(--st-color-primary);
|
|
116
108
|
}
|
|
117
109
|
|
|
118
|
-
/* SVG Icons */
|
|
119
110
|
svg {
|
|
120
111
|
width: var(--checkbox-icon-size);
|
|
121
112
|
height: var(--checkbox-icon-size);
|
|
@@ -131,14 +122,12 @@ constructor() {
|
|
|
131
122
|
opacity 0.2s ease;
|
|
132
123
|
}
|
|
133
124
|
|
|
134
|
-
/* Reveal Icons */
|
|
135
125
|
:host([checked]) svg.icon-check,
|
|
136
126
|
:host([indeterminate]) svg.icon-minus {
|
|
137
127
|
opacity: 1;
|
|
138
128
|
transform: scale(1);
|
|
139
129
|
}
|
|
140
130
|
|
|
141
|
-
/* Disabled State */
|
|
142
131
|
:host([disabled]) {
|
|
143
132
|
pointer-events: none;
|
|
144
133
|
}
|
|
@@ -147,7 +136,6 @@ constructor() {
|
|
|
147
136
|
cursor: not-allowed;
|
|
148
137
|
}
|
|
149
138
|
|
|
150
|
-
/* Invalid State */
|
|
151
139
|
:host([invalid]) .control {
|
|
152
140
|
border-color: var(--st-color-error);
|
|
153
141
|
}
|
|
@@ -162,8 +150,7 @@ constructor() {
|
|
|
162
150
|
override updated(changedProperties: PropertyValues<this>) {
|
|
163
151
|
super.updated(changedProperties);
|
|
164
152
|
|
|
165
|
-
if (changedProperties.has("checked") || changedProperties.has("value")) {
|
|
166
|
-
// Form API: If checked, submit the value. If unchecked, submit null to remove it from FormData.
|
|
153
|
+
if (changedProperties.has("checked") || changedProperties.has("value") || changedProperties.has("errorMessage")) {
|
|
167
154
|
this._internals.setFormValue(this.checked ? this.value : null);
|
|
168
155
|
this._syncValidity();
|
|
169
156
|
}
|
|
@@ -175,16 +162,54 @@ constructor() {
|
|
|
175
162
|
|
|
176
163
|
private _syncValidity() {
|
|
177
164
|
if (!this._inputEl) return;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this._inputEl.validationMessage
|
|
181
|
-
this.
|
|
182
|
-
|
|
165
|
+
|
|
166
|
+
if (this.required && !this.checked) {
|
|
167
|
+
const message = this.errorMessage || this._inputEl.validationMessage || "Please check this box if you want to proceed.";
|
|
168
|
+
this._internals.setValidity(
|
|
169
|
+
{valueMissing: true},
|
|
170
|
+
message,
|
|
171
|
+
this._inputEl,
|
|
172
|
+
);
|
|
173
|
+
} else {
|
|
174
|
+
this._internals.setValidity(
|
|
175
|
+
this._inputEl.validity,
|
|
176
|
+
this._inputEl.validationMessage,
|
|
177
|
+
this._inputEl,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public checkValidity(): boolean {
|
|
183
|
+
if (!this._inputEl) return true;
|
|
184
|
+
|
|
185
|
+
if (this.required && !this.checked) {
|
|
186
|
+
const message = this.errorMessage || this._inputEl.validationMessage || "Please check this box if you want to proceed.";
|
|
187
|
+
this._internals.setValidity(
|
|
188
|
+
{valueMissing: true},
|
|
189
|
+
message,
|
|
190
|
+
this._inputEl,
|
|
191
|
+
);
|
|
192
|
+
this.invalid = true;
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const isValid = this._inputEl.checkValidity();
|
|
197
|
+
this._syncValidity();
|
|
198
|
+
this.invalid = !isValid;
|
|
199
|
+
return isValid;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public reportValidity(): boolean {
|
|
203
|
+
this._syncValidity();
|
|
204
|
+
const isValid = this._internals.reportValidity();
|
|
205
|
+
this.invalid = !isValid;
|
|
206
|
+
return isValid;
|
|
183
207
|
}
|
|
184
208
|
|
|
185
209
|
formResetCallback() {
|
|
186
210
|
this.checked = false;
|
|
187
211
|
this.indeterminate = false;
|
|
212
|
+
this.invalid = false;
|
|
188
213
|
this._internals.setFormValue(null);
|
|
189
214
|
this.updateComplete.then(() => this._syncValidity());
|
|
190
215
|
}
|
|
@@ -194,12 +219,16 @@ constructor() {
|
|
|
194
219
|
|
|
195
220
|
if (this.disabled) return;
|
|
196
221
|
|
|
197
|
-
// Standard native behavior: clicking an indeterminate checkbox unsets the indeterminate state
|
|
198
222
|
if (this.indeterminate) {
|
|
199
223
|
this.indeterminate = false;
|
|
200
224
|
}
|
|
201
225
|
|
|
202
226
|
this.checked = this._inputEl.checked;
|
|
227
|
+
|
|
228
|
+
if (this.checkValidity()) {
|
|
229
|
+
this.invalid = false;
|
|
230
|
+
}
|
|
231
|
+
|
|
203
232
|
this.dispatchEvent(new Event("change", {bubbles: true, composed: true}));
|
|
204
233
|
}
|
|
205
234
|
|
|
@@ -218,7 +247,6 @@ constructor() {
|
|
|
218
247
|
@change=${this._handleChange}
|
|
219
248
|
/>
|
|
220
249
|
<div class="control">
|
|
221
|
-
<!-- Render both SVGs and use CSS to conditionally reveal them based on host attributes -->
|
|
222
250
|
${this.indeterminate
|
|
223
251
|
? html`<svg class="icon-minus" viewBox="0 0 24 24"><path d="M5 12h14"></path></svg>`
|
|
224
252
|
: html`<svg class="icon-check" viewBox="0 0 24 24">
|
|
@@ -235,4 +263,4 @@ declare global {
|
|
|
235
263
|
interface HTMLElementTagNameMap {
|
|
236
264
|
"st-checkbox": StCheckbox;
|
|
237
265
|
}
|
|
238
|
-
}
|
|
266
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
-
import { resetStyles } from '../../styles/reset';
|
|
3
|
+
import { resetStyles } from '../../styles/reset.js';
|
|
4
4
|
|
|
5
5
|
@customElement('st-divider')
|
|
6
6
|
export class StDivider extends LitElement {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { customElement, } from 'lit/decorators.js';
|
|
3
|
-
import { resetStyles } from '../../styles/reset';
|
|
3
|
+
import { resetStyles } from '../../styles/reset.js';
|
|
4
4
|
|
|
5
5
|
@customElement('st-field')
|
|
6
6
|
export class StField extends LitElement {
|
|
@@ -31,9 +31,6 @@ export class StForm extends LitElement {
|
|
|
31
31
|
gap: var(--st-spacing-md);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
/* ==========================================================
|
|
35
|
-
Layouts
|
|
36
|
-
========================================================== */
|
|
37
34
|
:host([layout="vertical"]) form {
|
|
38
35
|
flex-direction: column;
|
|
39
36
|
}
|
|
@@ -55,9 +52,6 @@ export class StForm extends LitElement {
|
|
|
55
52
|
flex-direction: column;
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
/* ==========================================================
|
|
59
|
-
Progress Navigation
|
|
60
|
-
========================================================== */
|
|
61
55
|
.progress-nav {
|
|
62
56
|
display: flex;
|
|
63
57
|
align-items: center;
|
|
@@ -121,9 +115,6 @@ export class StForm extends LitElement {
|
|
|
121
115
|
background-color: var(--st-color-success);
|
|
122
116
|
}
|
|
123
117
|
|
|
124
|
-
/* ==========================================================
|
|
125
|
-
Actions & States
|
|
126
|
-
========================================================== */
|
|
127
118
|
.form-actions {
|
|
128
119
|
display: flex;
|
|
129
120
|
gap: var(--st-spacing-md);
|
|
@@ -175,25 +166,23 @@ export class StForm extends LitElement {
|
|
|
175
166
|
this.requestUpdate();
|
|
176
167
|
}
|
|
177
168
|
|
|
178
|
-
private _validateCurrentContext(): boolean {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
169
|
+
private async _validateCurrentContext(): Promise<boolean> {
|
|
170
|
+
const scope: ParentNode = this._stepElements.length > 0
|
|
171
|
+
? this._stepElements[this._currentStepIndex]
|
|
172
|
+
: this;
|
|
182
173
|
|
|
183
|
-
const currentStep = this._stepElements[this._currentStepIndex];
|
|
184
174
|
let isValid = true;
|
|
185
175
|
|
|
186
|
-
//
|
|
176
|
+
// 1. Validate standard DOM input components
|
|
187
177
|
const inputs = Array.from(
|
|
188
|
-
|
|
189
|
-
HTMLElement & {checkValidity?: () => boolean; reportValidity?: () =>
|
|
178
|
+
scope.querySelectorAll<
|
|
179
|
+
HTMLElement & {checkValidity?: () => boolean; reportValidity?: () => boolean}
|
|
190
180
|
>("*"),
|
|
191
181
|
);
|
|
192
|
-
|
|
182
|
+
|
|
193
183
|
for (const input of inputs) {
|
|
194
184
|
if (typeof input.checkValidity === "function") {
|
|
195
185
|
if (!input.checkValidity()) {
|
|
196
|
-
// Focus and report on the first invalid element encountered
|
|
197
186
|
if (isValid && typeof input.reportValidity === "function") {
|
|
198
187
|
input.reportValidity();
|
|
199
188
|
}
|
|
@@ -202,11 +191,37 @@ export class StForm extends LitElement {
|
|
|
202
191
|
}
|
|
203
192
|
}
|
|
204
193
|
|
|
194
|
+
if (this._stepElements.length === 0 && this._formEl) {
|
|
195
|
+
if (!this._formEl.checkValidity()) {
|
|
196
|
+
isValid = false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 2. Execute step-level async/sync validation hook if defined
|
|
201
|
+
if (isValid && this._stepElements.length > 0) {
|
|
202
|
+
const currentStep = this._stepElements[this._currentStepIndex] as StFormStep & {
|
|
203
|
+
validate?: () => Promise<boolean> | boolean;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
if (typeof currentStep.validate === "function") {
|
|
207
|
+
try {
|
|
208
|
+
this.loading = true;
|
|
209
|
+
const stepPassed = await currentStep.validate();
|
|
210
|
+
if (!stepPassed) {
|
|
211
|
+
isValid = false;
|
|
212
|
+
}
|
|
213
|
+
} catch (err) {
|
|
214
|
+
isValid = false;
|
|
215
|
+
} finally {
|
|
216
|
+
this.loading = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
205
221
|
return isValid;
|
|
206
222
|
}
|
|
207
223
|
|
|
208
224
|
private _triggerSubmission() {
|
|
209
|
-
// HTML5 method that triggers form validation and fires the native submit event
|
|
210
225
|
this._formEl.requestSubmit();
|
|
211
226
|
}
|
|
212
227
|
|
|
@@ -220,13 +235,11 @@ export class StForm extends LitElement {
|
|
|
220
235
|
private _extractFormData(): FormData {
|
|
221
236
|
const formData = new FormData();
|
|
222
237
|
|
|
223
|
-
// Query all light-DOM children that have a 'name' attribute
|
|
224
238
|
const fields = this.querySelectorAll<
|
|
225
239
|
HTMLElement & {name: string; value: any; checked?: boolean; files?: FileList}
|
|
226
240
|
>("[name]");
|
|
227
241
|
|
|
228
242
|
fields.forEach((field) => {
|
|
229
|
-
// Standard HTML form behavior: ignore disabled fields
|
|
230
243
|
if (field.hasAttribute("disabled")) return;
|
|
231
244
|
|
|
232
245
|
const isToggle =
|
|
@@ -236,7 +249,6 @@ export class StForm extends LitElement {
|
|
|
236
249
|
field.getAttribute("type") === "checkbox";
|
|
237
250
|
|
|
238
251
|
if (isToggle) {
|
|
239
|
-
// Only append radios/checkboxes if they are actively checked
|
|
240
252
|
if (field.checked) {
|
|
241
253
|
formData.append(field.name, field.value || "on");
|
|
242
254
|
}
|
|
@@ -245,10 +257,8 @@ export class StForm extends LitElement {
|
|
|
245
257
|
field.getAttribute("type") === "file" &&
|
|
246
258
|
field.files
|
|
247
259
|
) {
|
|
248
|
-
// Handle native file uploads
|
|
249
260
|
Array.from(field.files).forEach((file) => formData.append(field.name, file));
|
|
250
261
|
} else if (field.value !== undefined) {
|
|
251
|
-
// Handle st-input, st-select, st-textarea, and standard inputs
|
|
252
262
|
formData.append(field.name, field.value);
|
|
253
263
|
}
|
|
254
264
|
});
|
|
@@ -256,11 +266,12 @@ export class StForm extends LitElement {
|
|
|
256
266
|
return formData;
|
|
257
267
|
}
|
|
258
268
|
|
|
259
|
-
private _handleSubmit(e: Event) {
|
|
269
|
+
private async _handleSubmit(e: Event) {
|
|
260
270
|
e.preventDefault();
|
|
261
271
|
e.stopPropagation();
|
|
262
272
|
|
|
263
|
-
|
|
273
|
+
const isValid = await this._validateCurrentContext();
|
|
274
|
+
if (!isValid) return;
|
|
264
275
|
|
|
265
276
|
const hasSteps = this._stepElements.length > 0;
|
|
266
277
|
const isLastStep = hasSteps ? this._currentStepIndex === this._stepElements.length - 1 : true;
|
|
@@ -271,7 +282,6 @@ export class StForm extends LitElement {
|
|
|
271
282
|
return;
|
|
272
283
|
}
|
|
273
284
|
|
|
274
|
-
// Use our custom extractor to pierce the Shadow DOM boundary
|
|
275
285
|
const formData = this._extractFormData();
|
|
276
286
|
|
|
277
287
|
this.dispatchEvent(
|
|
@@ -353,7 +363,6 @@ export class StForm extends LitElement {
|
|
|
353
363
|
`
|
|
354
364
|
: ""}
|
|
355
365
|
|
|
356
|
-
<!-- Type is "button", but click triggers requestSubmit() on the internal form -->
|
|
357
366
|
<st-button
|
|
358
367
|
color="primary"
|
|
359
368
|
type="button"
|
|
@@ -373,4 +382,4 @@ declare global {
|
|
|
373
382
|
interface HTMLElementTagNameMap {
|
|
374
383
|
"st-form": StForm;
|
|
375
384
|
}
|
|
376
|
-
}
|
|
385
|
+
}
|
|
@@ -119,6 +119,22 @@ export const iconPaths = {
|
|
|
119
119
|
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>`,
|
|
120
120
|
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>`,
|
|
121
121
|
},
|
|
122
|
+
calender: {
|
|
123
|
+
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>`,
|
|
124
|
+
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>`,
|
|
125
|
+
},
|
|
126
|
+
user: {
|
|
127
|
+
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>`,
|
|
128
|
+
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>`,
|
|
129
|
+
},
|
|
130
|
+
home: {
|
|
131
|
+
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>`,
|
|
132
|
+
solid: svg`<path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path>`,
|
|
133
|
+
},
|
|
134
|
+
"circle-cross": {
|
|
135
|
+
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>`,
|
|
136
|
+
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>`,
|
|
137
|
+
},
|
|
122
138
|
};
|
|
123
139
|
|
|
124
140
|
export type IconName = keyof typeof iconPaths;
|
|
@@ -3,10 +3,12 @@ import { customElement, property } from 'lit/decorators.js';
|
|
|
3
3
|
import { iconPaths, IconName } from './icon-paths.js';
|
|
4
4
|
import { resetStyles } from '../../styles/reset.js';
|
|
5
5
|
|
|
6
|
+
export type IconVariant = 'outline' | 'solid';
|
|
7
|
+
|
|
6
8
|
@customElement('st-icon')
|
|
7
9
|
export class StIcon extends LitElement {
|
|
8
10
|
@property({ type: String }) name: IconName | string = '';
|
|
9
|
-
@property({ type: String }) variant:
|
|
11
|
+
@property({ type: String }) variant: IconVariant = 'outline';
|
|
10
12
|
|
|
11
13
|
// Semantic Colors
|
|
12
14
|
@property({ type: String, reflect: true }) color: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' = 'default';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
-
import { resetStyles } from '../../styles/reset';
|
|
3
|
+
import { resetStyles } from '../../styles/reset.js';
|
|
4
4
|
|
|
5
5
|
@customElement('st-link')
|
|
6
6
|
export class StLink extends LitElement {
|