@sondor-technology/sondor-components 1.0.4 → 1.0.6
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/alert/alert.constants.d.ts +3 -0
- package/dist/components/alert/alert.constants.d.ts.map +1 -0
- package/dist/components/alert/alert.constants.js +2 -0
- package/dist/components/alert/alert.constants.js.map +1 -0
- package/dist/components/alert/alert.d.ts +4 -3
- package/dist/components/alert/alert.d.ts.map +1 -1
- package/dist/components/alert/alert.js +21 -11
- package/dist/components/alert/alert.js.map +1 -0
- package/dist/components/badge/badge.constants.d.ts +3 -0
- package/dist/components/badge/badge.constants.d.ts.map +1 -0
- package/dist/components/badge/badge.constants.js +2 -0
- package/dist/components/badge/badge.constants.js.map +1 -0
- package/dist/components/badge/badge.d.ts +1 -1
- package/dist/components/badge/badge.d.ts.map +1 -1
- package/dist/components/badge/badge.js +3 -2
- package/dist/components/badge/badge.js.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/breadcrumb/breadcrumb.js +2 -1
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -0
- package/dist/components/button/button.constants.d.ts +7 -0
- package/dist/components/button/button.constants.d.ts.map +1 -0
- package/dist/components/button/button.constants.js +4 -0
- package/dist/components/button/button.constants.js.map +1 -0
- package/dist/components/button/button.d.ts +8 -4
- package/dist/components/button/button.d.ts.map +1 -1
- package/dist/components/button/button.js +181 -137
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/button-group/button-group.d.ts +6 -0
- package/dist/components/button-group/button-group.d.ts.map +1 -1
- package/dist/components/button-group/button-group.js +17 -21
- package/dist/components/button-group/button-group.js.map +1 -0
- package/dist/components/checkbox/checkbox.constants.d.ts +3 -0
- package/dist/components/checkbox/checkbox.constants.d.ts.map +1 -0
- package/dist/components/checkbox/checkbox.constants.js +2 -0
- package/dist/components/checkbox/checkbox.constants.js.map +1 -0
- package/dist/components/checkbox/checkbox.d.ts +5 -1
- package/dist/components/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox/checkbox.js +21 -5
- package/dist/components/checkbox/checkbox.js.map +1 -0
- package/dist/components/code-block/code-block.d.ts +12 -7
- package/dist/components/code-block/code-block.d.ts.map +1 -1
- package/dist/components/code-block/code-block.js +130 -66
- package/dist/components/code-block/code-block.js.map +1 -0
- package/dist/components/content-card/content-card.d.ts.map +1 -1
- package/dist/components/content-card/content-card.js +10 -15
- package/dist/components/content-card/content-card.js.map +1 -0
- package/dist/components/divider/divider.constants.d.ts +5 -0
- package/dist/components/divider/divider.constants.d.ts.map +1 -0
- package/dist/components/divider/divider.constants.js +3 -0
- package/dist/components/divider/divider.constants.js.map +1 -0
- package/dist/components/divider/divider.d.ts +4 -2
- package/dist/components/divider/divider.d.ts.map +1 -1
- package/dist/components/divider/divider.js +18 -9
- package/dist/components/divider/divider.js.map +1 -0
- package/dist/components/drawer/drawer.d.ts +7 -4
- package/dist/components/drawer/drawer.d.ts.map +1 -1
- package/dist/components/drawer/drawer.js +73 -30
- package/dist/components/drawer/drawer.js.map +1 -0
- package/dist/components/field/field.d.ts +2 -2
- package/dist/components/field/field.d.ts.map +1 -1
- package/dist/components/field/field.js +8 -9
- package/dist/components/field/field.js.map +1 -0
- package/dist/components/footer/footer.d.ts +8 -1
- package/dist/components/footer/footer.d.ts.map +1 -1
- package/dist/components/footer/footer.js +42 -12
- package/dist/components/footer/footer.js.map +1 -0
- package/dist/components/form/form-step.js +1 -0
- package/dist/components/form/form-step.js.map +1 -0
- package/dist/components/form/form.d.ts +3 -0
- package/dist/components/form/form.d.ts.map +1 -1
- package/dist/components/form/form.js +107 -67
- package/dist/components/form/form.js.map +1 -0
- package/dist/components/grid/grid-row.d.ts +3 -3
- package/dist/components/grid/grid-row.d.ts.map +1 -1
- package/dist/components/grid/grid-row.js +36 -22
- package/dist/components/grid/grid-row.js.map +1 -0
- package/dist/components/grid/grid.d.ts +2 -2
- package/dist/components/grid/grid.d.ts.map +1 -1
- package/dist/components/grid/grid.js +5 -2
- package/dist/components/grid/grid.js.map +1 -0
- package/dist/components/icon/icon-paths.js +1 -0
- package/dist/components/icon/icon-paths.js.map +1 -0
- package/dist/components/icon/icon.js +1 -0
- package/dist/components/icon/icon.js.map +1 -0
- package/dist/components/input/input.d.ts +14 -0
- package/dist/components/input/input.d.ts.map +1 -1
- package/dist/components/input/input.js +30 -37
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/link/link.d.ts +6 -6
- package/dist/components/link/link.d.ts.map +1 -1
- package/dist/components/link/link.js +42 -19
- package/dist/components/link/link.js.map +1 -0
- package/dist/components/metadata/metadata.d.ts +3 -3
- package/dist/components/metadata/metadata.d.ts.map +1 -1
- package/dist/components/metadata/metadata.js +23 -20
- package/dist/components/metadata/metadata.js.map +1 -0
- package/dist/components/modal/modal.d.ts +4 -16
- package/dist/components/modal/modal.d.ts.map +1 -1
- package/dist/components/modal/modal.js +99 -62
- package/dist/components/modal/modal.js.map +1 -0
- package/dist/components/page-layout/page-layout.d.ts +4 -3
- package/dist/components/page-layout/page-layout.d.ts.map +1 -1
- package/dist/components/page-layout/page-layout.js +96 -69
- package/dist/components/page-layout/page-layout.js.map +1 -0
- package/dist/components/radio/radio.d.ts +8 -0
- package/dist/components/radio/radio.d.ts.map +1 -1
- package/dist/components/radio/radio.js +8 -12
- package/dist/components/radio/radio.js.map +1 -0
- package/dist/components/radio-group/radio-group.d.ts +6 -1
- package/dist/components/radio-group/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group/radio-group.js +44 -18
- package/dist/components/radio-group/radio-group.js.map +1 -0
- package/dist/components/router/router.d.ts +5 -7
- package/dist/components/router/router.d.ts.map +1 -1
- package/dist/components/router/router.js +54 -38
- package/dist/components/router/router.js.map +1 -0
- package/dist/components/select/select.d.ts +41 -7
- package/dist/components/select/select.d.ts.map +1 -1
- package/dist/components/select/select.js +467 -150
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +3 -2
- package/dist/components/skeleton/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton/skeleton.js +10 -13
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/switch/switch.d.ts +12 -0
- package/dist/components/switch/switch.d.ts.map +1 -1
- package/dist/components/switch/switch.js +28 -22
- package/dist/components/switch/switch.js.map +1 -0
- package/dist/components/table/data-table.d.ts +3 -25
- package/dist/components/table/data-table.d.ts.map +1 -1
- package/dist/components/table/data-table.js +211 -146
- package/dist/components/table/data-table.js.map +1 -0
- package/dist/components/table/table.d.ts +3 -3
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/table/table.js +39 -20
- package/dist/components/table/table.js.map +1 -0
- package/dist/components/tabs/tab-panel.d.ts +8 -1
- package/dist/components/tabs/tab-panel.d.ts.map +1 -1
- package/dist/components/tabs/tab-panel.js +21 -11
- package/dist/components/tabs/tab-panel.js.map +1 -0
- package/dist/components/tabs/tab.d.ts +10 -1
- package/dist/components/tabs/tab.d.ts.map +1 -1
- package/dist/components/tabs/tab.js +46 -28
- package/dist/components/tabs/tab.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +9 -0
- package/dist/components/tabs/tabs.d.ts.map +1 -1
- package/dist/components/tabs/tabs.js +76 -13
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/textarea/textarea.d.ts +13 -0
- package/dist/components/textarea/textarea.d.ts.map +1 -1
- package/dist/components/textarea/textarea.js +59 -13
- package/dist/components/textarea/textarea.js.map +1 -0
- package/dist/components/theme-toggle/theme-toggle.constants.d.ts +3 -0
- package/dist/components/theme-toggle/theme-toggle.constants.d.ts.map +1 -0
- package/dist/components/theme-toggle/theme-toggle.constants.js +2 -0
- package/dist/components/theme-toggle/theme-toggle.constants.js.map +1 -0
- package/dist/components/theme-toggle/theme-toggle.d.ts +3 -2
- package/dist/components/theme-toggle/theme-toggle.d.ts.map +1 -1
- package/dist/components/theme-toggle/theme-toggle.js +46 -19
- package/dist/components/theme-toggle/theme-toggle.js.map +1 -0
- package/dist/components/vertical-nav/vertical-nav-group.d.ts +5 -2
- package/dist/components/vertical-nav/vertical-nav-group.d.ts.map +1 -1
- package/dist/components/vertical-nav/vertical-nav-group.js +50 -14
- package/dist/components/vertical-nav/vertical-nav-group.js.map +1 -0
- package/dist/components/vertical-nav/vertical-nav-item.d.ts +3 -2
- package/dist/components/vertical-nav/vertical-nav-item.d.ts.map +1 -1
- package/dist/components/vertical-nav/vertical-nav-item.js +30 -8
- package/dist/components/vertical-nav/vertical-nav-item.js.map +1 -0
- package/dist/styles/index.css +50 -17
- package/dist/styles/reset.js +1 -0
- package/dist/styles/reset.js.map +1 -0
- package/package.json +2 -1
- package/src/components/alert/alert.constants.ts +2 -0
- package/src/components/alert/alert.ts +24 -15
- package/src/components/badge/badge.constants.ts +2 -0
- package/src/components/badge/badge.ts +3 -4
- package/src/components/breadcrumb/breadcrumb.ts +2 -2
- package/src/components/button/button.constants.ts +8 -0
- package/src/components/button/button.ts +184 -144
- package/src/components/button-group/button-group.ts +23 -21
- package/src/components/checkbox/checkbox.constants.ts +2 -0
- package/src/components/checkbox/checkbox.ts +33 -18
- package/src/components/code-block/code-block.ts +157 -84
- package/src/components/content-card/content-card.ts +10 -16
- package/src/components/divider/divider.constants.ts +5 -0
- package/src/components/divider/divider.ts +22 -11
- package/src/components/drawer/drawer.ts +79 -34
- package/src/components/field/field.ts +9 -11
- package/src/components/footer/footer.ts +43 -12
- package/src/components/form/form.ts +120 -83
- package/src/components/grid/grid-row.ts +45 -32
- package/src/components/grid/grid.ts +7 -4
- package/src/components/input/input.ts +37 -41
- package/src/components/link/link.ts +45 -21
- package/src/components/metadata/metadata.ts +26 -24
- package/src/components/modal/modal.ts +108 -74
- package/src/components/page-layout/page-layout.ts +98 -73
- package/src/components/radio/radio.ts +8 -13
- package/src/components/radio-group/radio-group.ts +45 -21
- package/src/components/router/router.ts +73 -50
- package/src/components/select/select.ts +502 -131
- package/src/components/skeleton/skeleton.ts +14 -14
- package/src/components/switch/switch.ts +31 -25
- package/src/components/table/data-table.ts +248 -177
- package/src/components/table/table.ts +52 -29
- package/src/components/tabs/tab-panel.ts +30 -13
- package/src/components/tabs/tab.ts +64 -33
- package/src/components/tabs/tabs.ts +82 -14
- package/src/components/textarea/textarea.ts +63 -15
- package/src/components/theme-toggle/theme-toggle.constants.ts +2 -0
- package/src/components/theme-toggle/theme-toggle.ts +47 -22
- package/src/components/vertical-nav/vertical-nav-group.ts +57 -18
- package/src/components/vertical-nav/vertical-nav-item.ts +35 -12
- package/src/styles/globals.css +27 -4
- package/src/styles/theme.css +39 -31
- package/tsconfig.json +2 -1
- package/dist/components/card/card.d.ts +0 -11
- package/dist/components/card/card.d.ts.map +0 -1
- package/dist/components/card/card.js +0 -54
- package/src/components/card/card.ts +0 -53
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {LitElement, html, css, PropertyValues} from "lit";
|
|
2
|
+
import {customElement, property} from "lit/decorators.js";
|
|
3
|
+
import {resetStyles} from "../../styles/reset.js";
|
|
4
4
|
|
|
5
|
-
@customElement(
|
|
5
|
+
@customElement("st-grid-row")
|
|
6
6
|
export class StGridRow extends LitElement {
|
|
7
|
-
@property({
|
|
8
|
-
@property({
|
|
9
|
-
@property({
|
|
10
|
-
@property({
|
|
11
|
-
@property({
|
|
7
|
+
@property({type: Number}) xs = 1;
|
|
8
|
+
@property({type: Number}) sm?: number;
|
|
9
|
+
@property({type: Number}) md?: number;
|
|
10
|
+
@property({type: Number}) lg?: number;
|
|
11
|
+
@property({type: Number}) xl?: number;
|
|
12
12
|
|
|
13
13
|
static styles = [
|
|
14
14
|
resetStyles,
|
|
@@ -22,46 +22,59 @@ export class StGridRow extends LitElement {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/* Mobile First (xs) */
|
|
25
|
-
:host {
|
|
25
|
+
:host {
|
|
26
|
+
--_cols: var(--grid-xs, 1);
|
|
27
|
+
}
|
|
26
28
|
|
|
27
29
|
/* Small (sm: >= 640px) */
|
|
28
30
|
@media (min-width: 640px) {
|
|
29
|
-
:host {
|
|
31
|
+
:host {
|
|
32
|
+
--_cols: var(--grid-sm, var(--grid-xs, 1));
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
|
-
|
|
35
|
+
|
|
32
36
|
/* Medium (md: >= 768px) */
|
|
33
37
|
@media (min-width: 768px) {
|
|
34
|
-
:host {
|
|
38
|
+
:host {
|
|
39
|
+
--_cols: var(--grid-md, var(--grid-sm, var(--grid-xs, 1)));
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
|
-
|
|
42
|
+
|
|
37
43
|
/* Large (lg: >= 1024px) */
|
|
38
44
|
@media (min-width: 1024px) {
|
|
39
|
-
:host {
|
|
45
|
+
:host {
|
|
46
|
+
--_cols: var(--grid-lg, var(--grid-md, var(--grid-sm, var(--grid-xs, 1))));
|
|
47
|
+
}
|
|
40
48
|
}
|
|
41
|
-
|
|
49
|
+
|
|
42
50
|
/* Extra Large (xl: >= 1280px) */
|
|
43
51
|
@media (min-width: 1280px) {
|
|
44
|
-
:host {
|
|
52
|
+
:host {
|
|
53
|
+
--_cols: var(
|
|
54
|
+
--grid-xl,
|
|
55
|
+
var(--grid-lg, var(--grid-md, var(--grid-sm, var(--grid-xs, 1))))
|
|
56
|
+
);
|
|
57
|
+
}
|
|
45
58
|
}
|
|
46
|
-
|
|
59
|
+
`,
|
|
47
60
|
];
|
|
48
61
|
|
|
49
|
-
updated(changedProperties:
|
|
62
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
50
63
|
super.updated(changedProperties);
|
|
51
|
-
|
|
52
|
-
this.style.setProperty('--grid-xs', this.xs.toString());
|
|
53
|
-
|
|
54
|
-
if (this.sm !== undefined) this.style.setProperty('--grid-sm', this.sm.toString());
|
|
55
|
-
else this.style.removeProperty('--grid-sm');
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
this.style.setProperty("--grid-xs", this.xs.toString());
|
|
66
|
+
|
|
67
|
+
if (this.sm !== undefined) this.style.setProperty("--grid-sm", this.sm.toString());
|
|
68
|
+
else this.style.removeProperty("--grid-sm");
|
|
59
69
|
|
|
60
|
-
if (this.
|
|
61
|
-
else this.style.removeProperty(
|
|
70
|
+
if (this.md !== undefined) this.style.setProperty("--grid-md", this.md.toString());
|
|
71
|
+
else this.style.removeProperty("--grid-md");
|
|
62
72
|
|
|
63
|
-
if (this.
|
|
64
|
-
else this.style.removeProperty(
|
|
73
|
+
if (this.lg !== undefined) this.style.setProperty("--grid-lg", this.lg.toString());
|
|
74
|
+
else this.style.removeProperty("--grid-lg");
|
|
75
|
+
|
|
76
|
+
if (this.xl !== undefined) this.style.setProperty("--grid-xl", this.xl.toString());
|
|
77
|
+
else this.style.removeProperty("--grid-xl");
|
|
65
78
|
}
|
|
66
79
|
|
|
67
80
|
render() {
|
|
@@ -71,6 +84,6 @@ export class StGridRow extends LitElement {
|
|
|
71
84
|
|
|
72
85
|
declare global {
|
|
73
86
|
interface HTMLElementTagNameMap {
|
|
74
|
-
|
|
87
|
+
"st-grid-row": StGridRow;
|
|
75
88
|
}
|
|
76
|
-
}
|
|
89
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement, html, css } from 'lit';
|
|
1
|
+
import { LitElement, html, css, PropertyValues } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { resetStyles } from '../../styles/reset.js';
|
|
4
4
|
|
|
@@ -19,10 +19,13 @@ export class StGrid extends LitElement {
|
|
|
19
19
|
`
|
|
20
20
|
];
|
|
21
21
|
|
|
22
|
-
updated(changedProperties:
|
|
22
|
+
updated(changedProperties: PropertyValues<this>) {
|
|
23
23
|
super.updated(changedProperties);
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
|
|
25
|
+
// Performance optimization: Only touch the DOM if the gap property actually changed
|
|
26
|
+
if (changedProperties.has('gap')) {
|
|
27
|
+
this.style.setProperty('--grid-gap', this.gap);
|
|
28
|
+
}
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
render() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {LitElement, html, css, PropertyValues} from "lit";
|
|
2
2
|
import {customElement, property, query} from "lit/decorators.js";
|
|
3
|
-
import {ifDefined} from "lit/directives/if-defined.js";
|
|
3
|
+
import {ifDefined} from "lit/directives/if-defined.js";
|
|
4
4
|
import {resetStyles} from "../../styles/reset.js";
|
|
5
5
|
|
|
6
6
|
export type InputType = "text" | "password" | "email" | "number" | "search" | "url";
|
|
@@ -8,6 +8,7 @@ export type InputType = "text" | "password" | "email" | "number" | "search" | "u
|
|
|
8
8
|
@customElement("st-input")
|
|
9
9
|
export class StInput extends LitElement {
|
|
10
10
|
static formAssociated = true;
|
|
11
|
+
static shadowRootOptions = {...LitElement.shadowRootOptions, delegatesFocus: true};
|
|
11
12
|
private _internals: ElementInternals;
|
|
12
13
|
|
|
13
14
|
@query("input") private _inputEl!: HTMLInputElement;
|
|
@@ -17,8 +18,8 @@ export class StInput extends LitElement {
|
|
|
17
18
|
@property({type: String}) placeholder = "";
|
|
18
19
|
@property({type: String}) type: InputType = "text";
|
|
19
20
|
@property({attribute: "help-text"}) helpText = "";
|
|
21
|
+
@property({ type: String }) autocomplete?: string;
|
|
20
22
|
|
|
21
|
-
// Validation Properties
|
|
22
23
|
@property({type: Boolean, reflect: true}) required = false;
|
|
23
24
|
@property({type: Number}) minlength?: number;
|
|
24
25
|
@property({type: Number}) maxlength?: number;
|
|
@@ -32,12 +33,10 @@ export class StInput extends LitElement {
|
|
|
32
33
|
super();
|
|
33
34
|
this._internals = this.attachInternals();
|
|
34
35
|
|
|
35
|
-
// 1. Trigger error state if the user clicks away and the field is invalid
|
|
36
36
|
this.addEventListener("focusout", () => {
|
|
37
37
|
this.invalid = !this._inputEl.validity.valid;
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
// 2. Trigger error state if the st-form tries to submit and fails
|
|
41
40
|
this.addEventListener("invalid", () => {
|
|
42
41
|
this.invalid = true;
|
|
43
42
|
});
|
|
@@ -61,41 +60,34 @@ export class StInput extends LitElement {
|
|
|
61
60
|
font-weight: var(--st-font-weight-medium);
|
|
62
61
|
color: var(--st-color-text);
|
|
63
62
|
margin-bottom: 0.5em;
|
|
63
|
+
cursor: pointer;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
/* 1. The Wrapper acts as the visual input field */
|
|
67
66
|
.input-wrapper {
|
|
68
67
|
display: flex;
|
|
69
68
|
align-items: center;
|
|
70
69
|
gap: var(--st-spacing-sm);
|
|
71
70
|
width: 100%;
|
|
72
|
-
|
|
73
71
|
background-color: var(--st-color-bg);
|
|
74
72
|
border: 1px solid var(--st-color-border);
|
|
75
73
|
border-radius: 4px;
|
|
76
|
-
|
|
77
|
-
/* Horizontal padding on the wrapper, vertical on the input */
|
|
78
74
|
padding: 0 var(--st-spacing-md);
|
|
79
75
|
transition:
|
|
80
76
|
border-color 0.2s ease,
|
|
81
77
|
box-shadow 0.2s ease;
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
/* 2. Apply focus ring to the wrapper when the internal input is focused */
|
|
85
80
|
.input-wrapper:focus-within {
|
|
86
81
|
border-color: var(--st-color-primary);
|
|
87
82
|
box-shadow: 0 0 0 1px var(--st-color-primary);
|
|
88
83
|
}
|
|
89
84
|
|
|
90
|
-
/* 3. The actual input becomes transparent and fills the wrapper */
|
|
91
85
|
input {
|
|
92
86
|
flex: 1;
|
|
93
87
|
width: 100%;
|
|
94
88
|
border: none;
|
|
95
89
|
background: transparent;
|
|
96
90
|
outline: none;
|
|
97
|
-
|
|
98
|
-
/* Vertical padding stretches the wrapper */
|
|
99
91
|
padding: var(--st-spacing-sm) 0;
|
|
100
92
|
font-size: var(--st-font-size-base);
|
|
101
93
|
color: var(--st-color-text);
|
|
@@ -105,77 +97,63 @@ export class StInput extends LitElement {
|
|
|
105
97
|
color: var(--st-color-text-muted);
|
|
106
98
|
}
|
|
107
99
|
|
|
108
|
-
/* Slotted Icons */
|
|
109
100
|
::slotted(svg) {
|
|
110
101
|
width: 1.25em;
|
|
111
102
|
height: 1.25em;
|
|
112
|
-
/* Default icons to the muted text color */
|
|
113
103
|
color: var(--st-color-text-muted);
|
|
114
104
|
fill: currentColor;
|
|
115
105
|
flex-shrink: 0;
|
|
116
106
|
}
|
|
117
107
|
|
|
118
|
-
/* Interactive Slotted Elements (like clear buttons) */
|
|
119
108
|
::slotted(st-button) {
|
|
120
|
-
/* Pull the button back slightly so it aligns nicely with the input padding */
|
|
121
109
|
margin-right: calc(var(--st-spacing-sm) * -1);
|
|
122
110
|
}
|
|
123
111
|
|
|
124
|
-
|
|
112
|
+
.help-text {
|
|
113
|
+
font-size: var(--st-font-size-xs);
|
|
114
|
+
color: var(--st-color-text-muted);
|
|
115
|
+
margin: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
125
118
|
:host([invalid]) .input-wrapper {
|
|
126
119
|
border-color: var(--st-color-error);
|
|
127
120
|
}
|
|
121
|
+
|
|
128
122
|
:host([invalid]) .input-wrapper:focus-within {
|
|
129
123
|
box-shadow: 0 0 0 1px var(--st-color-error);
|
|
130
124
|
}
|
|
125
|
+
|
|
131
126
|
:host([invalid]) .help-text {
|
|
132
127
|
color: var(--st-color-error);
|
|
133
128
|
}
|
|
134
129
|
|
|
135
|
-
/* Disabled & Readonly States */
|
|
136
130
|
:host([disabled]) .input-wrapper {
|
|
137
131
|
opacity: 0.5;
|
|
138
132
|
cursor: not-allowed;
|
|
139
133
|
background-color: var(--st-color-surface);
|
|
140
134
|
}
|
|
135
|
+
|
|
141
136
|
:host([disabled]) input {
|
|
142
137
|
cursor: not-allowed;
|
|
143
138
|
}
|
|
139
|
+
|
|
144
140
|
:host([readonly]) .input-wrapper {
|
|
145
141
|
background-color: var(--st-color-surface);
|
|
146
142
|
}
|
|
147
|
-
|
|
148
|
-
.help-text {
|
|
149
|
-
font-size: var(--st-font-size-xs);
|
|
150
|
-
color: var(--st-color-text-muted);
|
|
151
|
-
margin: 0;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
:host([invalid]) .input-wrapper {
|
|
155
|
-
border-color: var(--st-color-error);
|
|
156
|
-
}
|
|
157
|
-
:host([invalid]) .help-text {
|
|
158
|
-
color: var(--st-color-error);
|
|
159
|
-
}
|
|
160
143
|
`,
|
|
161
144
|
];
|
|
162
145
|
|
|
163
146
|
override updated(changedProperties: PropertyValues<this>) {
|
|
164
147
|
super.updated(changedProperties);
|
|
165
148
|
|
|
166
|
-
// Sync the value to the form engine
|
|
167
149
|
if (changedProperties.has("value")) {
|
|
168
150
|
this._internals.setFormValue(this.value);
|
|
169
151
|
}
|
|
170
|
-
|
|
171
|
-
// Sync validity whenever properties change (like value or required status)
|
|
172
152
|
this._syncValidity();
|
|
173
153
|
}
|
|
174
154
|
|
|
175
155
|
private _syncValidity() {
|
|
176
156
|
if (!this._inputEl) return;
|
|
177
|
-
|
|
178
|
-
// setValidity arguments: (ValidityState object, Custom Error Message, Anchor Element for Tooltip)
|
|
179
157
|
this._internals.setValidity(
|
|
180
158
|
this._inputEl.validity,
|
|
181
159
|
this._inputEl.validationMessage,
|
|
@@ -186,11 +164,9 @@ export class StInput extends LitElement {
|
|
|
186
164
|
formResetCallback() {
|
|
187
165
|
this.value = "";
|
|
188
166
|
this._internals.setFormValue("");
|
|
189
|
-
// Need to wait for the render cycle to finish before checking validity on reset
|
|
190
167
|
this.updateComplete.then(() => this._syncValidity());
|
|
191
168
|
}
|
|
192
169
|
|
|
193
|
-
// Expose standard native methods so external scripts can call them on the component
|
|
194
170
|
checkValidity() {
|
|
195
171
|
return this._internals.checkValidity();
|
|
196
172
|
}
|
|
@@ -200,7 +176,7 @@ export class StInput extends LitElement {
|
|
|
200
176
|
}
|
|
201
177
|
|
|
202
178
|
private _handleInput(e: Event) {
|
|
203
|
-
const target = e.target as
|
|
179
|
+
const target = e.target as HTMLInputElement;
|
|
204
180
|
this.value = target.value;
|
|
205
181
|
|
|
206
182
|
if (this.invalid && target.validity.valid) {
|
|
@@ -214,7 +190,14 @@ export class StInput extends LitElement {
|
|
|
214
190
|
this.dispatchEvent(new Event("change", {bubbles: true, composed: true}));
|
|
215
191
|
}
|
|
216
192
|
|
|
217
|
-
|
|
193
|
+
render() {
|
|
194
|
+
const helpTextId = this.helpText ? "help-text" : undefined;
|
|
195
|
+
|
|
196
|
+
// Security: Prevent OS/Extensions from logging sensitive data via spellcheck
|
|
197
|
+
const isSensitive = this.type === "password" || this.type === "email";
|
|
198
|
+
const safeSpellcheck = isSensitive ? "false" : undefined;
|
|
199
|
+
const safeAutocapitalize = isSensitive ? "none" : undefined;
|
|
200
|
+
|
|
218
201
|
return html`
|
|
219
202
|
<div class="form-control">
|
|
220
203
|
${this.label ? html`<label for="input">${this.label}</label>` : ""}
|
|
@@ -234,6 +217,11 @@ export class StInput extends LitElement {
|
|
|
234
217
|
minlength=${ifDefined(this.minlength)}
|
|
235
218
|
maxlength=${ifDefined(this.maxlength)}
|
|
236
219
|
pattern=${ifDefined(this.pattern)}
|
|
220
|
+
autocomplete=${ifDefined(this.autocomplete as any)}
|
|
221
|
+
spellcheck=${ifDefined(safeSpellcheck)}
|
|
222
|
+
autocapitalize=${ifDefined(safeAutocapitalize)}
|
|
223
|
+
aria-invalid=${this.invalid ? "true" : "false"}
|
|
224
|
+
aria-describedby=${ifDefined(helpTextId)}
|
|
237
225
|
@input=${this._handleInput}
|
|
238
226
|
@change=${this._handleChange}
|
|
239
227
|
/>
|
|
@@ -241,8 +229,16 @@ export class StInput extends LitElement {
|
|
|
241
229
|
<slot name="suffix"></slot>
|
|
242
230
|
</div>
|
|
243
231
|
|
|
244
|
-
${this.helpText
|
|
232
|
+
${this.helpText
|
|
233
|
+
? html`<div id="help-text" class="help-text">${this.helpText}</div>`
|
|
234
|
+
: ""}
|
|
245
235
|
</div>
|
|
246
236
|
`;
|
|
247
237
|
}
|
|
248
238
|
}
|
|
239
|
+
|
|
240
|
+
declare global {
|
|
241
|
+
interface HTMLElementTagNameMap {
|
|
242
|
+
"st-input": StInput;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {LitElement, html, css} from "lit";
|
|
2
|
+
import {customElement, property} from "lit/decorators.js";
|
|
3
|
+
import {ifDefined} from "lit/directives/if-defined.js";
|
|
4
|
+
import {resetStyles} from "../../styles/reset.js";
|
|
4
5
|
|
|
5
|
-
@customElement(
|
|
6
|
+
@customElement("st-link")
|
|
6
7
|
export class StLink extends LitElement {
|
|
7
|
-
@property({
|
|
8
|
-
@property({
|
|
9
|
-
@property({
|
|
10
|
-
@property({
|
|
11
|
-
@property({
|
|
8
|
+
@property({type: String}) href = "#";
|
|
9
|
+
@property({type: String}) target: "_blank" | "_self" = "_self";
|
|
10
|
+
@property({type: String, reflect: true}) size: "sm" | "md" | "lg" = "md";
|
|
11
|
+
@property({type: String, reflect: true}) variant: "inline" | "standalone" = "inline";
|
|
12
|
+
@property({type: String, reflect: true}) color: "default" | "primary" | "muted" = "primary";
|
|
12
13
|
|
|
13
14
|
static styles = [
|
|
14
15
|
resetStyles,
|
|
15
16
|
css`
|
|
16
17
|
:host {
|
|
17
18
|
display: inline-flex;
|
|
18
|
-
align-items:
|
|
19
|
+
align-items: baseline; /* Ensures it sits perfectly inside a line of text */
|
|
20
|
+
vertical-align: baseline;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
a {
|
|
@@ -24,7 +26,17 @@ export class StLink extends LitElement {
|
|
|
24
26
|
gap: 0.25em;
|
|
25
27
|
text-decoration: none;
|
|
26
28
|
font-weight: 500;
|
|
27
|
-
transition:
|
|
29
|
+
transition:
|
|
30
|
+
color 0.2s ease,
|
|
31
|
+
opacity 0.2s ease,
|
|
32
|
+
text-decoration-thickness 0.2s ease;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Accessibility: Clear focus indicators for keyboard navigation */
|
|
36
|
+
a:focus-visible {
|
|
37
|
+
outline: 2px solid var(--st-color-primary);
|
|
38
|
+
outline-offset: 2px;
|
|
39
|
+
border-radius: 2px;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
/* ==========================================================
|
|
@@ -54,24 +66,28 @@ export class StLink extends LitElement {
|
|
|
54
66
|
/* ==========================================================
|
|
55
67
|
Sizes
|
|
56
68
|
========================================================== */
|
|
57
|
-
:host([size="sm"]) a {
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
:host([size="sm"]) a {
|
|
70
|
+
font-size: 0.875rem;
|
|
71
|
+
}
|
|
72
|
+
:host([size="md"]) a {
|
|
73
|
+
font-size: 1rem;
|
|
74
|
+
}
|
|
75
|
+
:host([size="lg"]) a {
|
|
76
|
+
font-size: 1.125rem;
|
|
77
|
+
}
|
|
60
78
|
|
|
61
79
|
/* ==========================================================
|
|
62
80
|
Variants
|
|
63
81
|
========================================================== */
|
|
64
|
-
/* inline links live inside paragraphs and underline on hover */
|
|
65
82
|
:host([variant="inline"]) a {
|
|
66
83
|
text-decoration: underline;
|
|
67
84
|
text-underline-offset: 4px;
|
|
68
|
-
font-weight: inherit;
|
|
85
|
+
font-weight: inherit;
|
|
69
86
|
}
|
|
70
87
|
:host([variant="inline"]) a:hover {
|
|
71
88
|
text-decoration-thickness: 2px;
|
|
72
89
|
}
|
|
73
90
|
|
|
74
|
-
/* standalone links (e.g., footers, sidebars) have no underline by default */
|
|
75
91
|
:host([variant="standalone"]) a {
|
|
76
92
|
text-decoration: none;
|
|
77
93
|
}
|
|
@@ -79,12 +95,20 @@ export class StLink extends LitElement {
|
|
|
79
95
|
text-decoration: underline;
|
|
80
96
|
text-underline-offset: 4px;
|
|
81
97
|
}
|
|
82
|
-
|
|
98
|
+
`,
|
|
83
99
|
];
|
|
84
100
|
|
|
85
101
|
render() {
|
|
102
|
+
// SECURITY: Prevent XSS via javascript: URI injection
|
|
103
|
+
const sanitizedHref = this.href?.trim().toLowerCase().startsWith("javascript:")
|
|
104
|
+
? "#blocked"
|
|
105
|
+
: this.href;
|
|
106
|
+
|
|
107
|
+
// SECURITY: Prevent Reverse Tabnabbing for external links
|
|
108
|
+
const secureRel = this.target === "_blank" ? "noopener noreferrer" : undefined;
|
|
109
|
+
|
|
86
110
|
return html`
|
|
87
|
-
<a href="${
|
|
111
|
+
<a href="${sanitizedHref}" target="${this.target}" rel="${ifDefined(secureRel)}">
|
|
88
112
|
<slot></slot>
|
|
89
113
|
</a>
|
|
90
114
|
`;
|
|
@@ -93,6 +117,6 @@ export class StLink extends LitElement {
|
|
|
93
117
|
|
|
94
118
|
declare global {
|
|
95
119
|
interface HTMLElementTagNameMap {
|
|
96
|
-
|
|
120
|
+
"st-link": StLink;
|
|
97
121
|
}
|
|
98
|
-
}
|
|
122
|
+
}
|
|
@@ -1,58 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {LitElement, nothing, PropertyValues} from "lit";
|
|
2
|
+
import {customElement, property} from "lit/decorators.js";
|
|
3
3
|
|
|
4
|
-
@customElement(
|
|
4
|
+
@customElement("st-metadata")
|
|
5
5
|
export class StMetadata extends LitElement {
|
|
6
|
-
@property({
|
|
7
|
-
@property({
|
|
8
|
-
@property({
|
|
6
|
+
@property({type: String}) pageTitle = "";
|
|
7
|
+
@property({type: String}) description = "";
|
|
8
|
+
@property({type: String}) image = "";
|
|
9
9
|
|
|
10
|
-
protected createRenderRoot() {
|
|
10
|
+
protected createRenderRoot() {
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
// 🚀 Added strict PropertyValues typing and super call
|
|
15
|
+
override updated(changedProperties: PropertyValues<this>) {
|
|
16
|
+
super.updated(changedProperties);
|
|
13
17
|
this._updateMetadata();
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
private _updateMetadata() {
|
|
17
|
-
|
|
18
|
-
const siteName = (import.meta as any).env?.VITE_SITE_NAME || '';
|
|
21
|
+
const siteName = (import.meta as any).env?.VITE_SITE_NAME || "";
|
|
19
22
|
|
|
20
23
|
if (this.pageTitle) {
|
|
21
|
-
// If site name is configured, append it; otherwise use the title standalone
|
|
22
24
|
document.title = siteName ? `${this.pageTitle} - ${siteName}` : this.pageTitle;
|
|
23
|
-
this._setMeta(
|
|
25
|
+
this._setMeta("property", "og:title", this.pageTitle);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
if (this.description) {
|
|
27
|
-
this._setMeta(
|
|
28
|
-
this._setMeta(
|
|
29
|
+
this._setMeta("name", "description", this.description);
|
|
30
|
+
this._setMeta("property", "og:description", this.description);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
if (this.image) {
|
|
32
|
-
this._setMeta(
|
|
34
|
+
this._setMeta("property", "og:image", this.image);
|
|
33
35
|
}
|
|
34
|
-
|
|
36
|
+
|
|
35
37
|
this._setCanonical(window.location.href);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
private _setMeta(attrName:
|
|
40
|
+
private _setMeta(attrName: "name" | "property", attrValue: string, content: string) {
|
|
39
41
|
let meta = document.head.querySelector(`meta[${attrName}="${attrValue}"]`);
|
|
40
42
|
if (!meta) {
|
|
41
|
-
meta = document.createElement(
|
|
43
|
+
meta = document.createElement("meta");
|
|
42
44
|
meta.setAttribute(attrName, attrValue);
|
|
43
45
|
document.head.appendChild(meta);
|
|
44
46
|
}
|
|
45
|
-
meta.setAttribute(
|
|
47
|
+
meta.setAttribute("content", content);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
private _setCanonical(url: string) {
|
|
49
51
|
let link = document.head.querySelector('link[rel="canonical"]');
|
|
50
52
|
if (!link) {
|
|
51
|
-
link = document.createElement(
|
|
52
|
-
link.setAttribute(
|
|
53
|
+
link = document.createElement("link");
|
|
54
|
+
link.setAttribute("rel", "canonical");
|
|
53
55
|
document.head.appendChild(link);
|
|
54
56
|
}
|
|
55
|
-
link.setAttribute(
|
|
57
|
+
link.setAttribute("href", url);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
render() {
|
|
@@ -62,6 +64,6 @@ export class StMetadata extends LitElement {
|
|
|
62
64
|
|
|
63
65
|
declare global {
|
|
64
66
|
interface HTMLElementTagNameMap {
|
|
65
|
-
|
|
67
|
+
"st-metadata": StMetadata;
|
|
66
68
|
}
|
|
67
|
-
}
|
|
69
|
+
}
|