@grayscale-dev/dragon 0.1.1 → 0.1.3
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/README.md +18 -4
- package/dist/components/dui-input.d.ts +2 -0
- package/dist/index.js +131 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,8 @@ Covers value/property sync, native `input`/`change` events, form association, fo
|
|
|
24
24
|
import '@grayscale-dev/dragon';
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
|
-
<dui-input id="name"
|
|
27
|
+
<dui-input id="name" label="Name" label-position="above"></dui-input>
|
|
28
|
+
<dui-input id="email" label="Email" label-position="floating"></dui-input>
|
|
28
29
|
|
|
29
30
|
<script type="module">
|
|
30
31
|
const el = document.querySelector('#name');
|
|
@@ -42,7 +43,8 @@ import '@grayscale-dev/dragon';
|
|
|
42
43
|
export function Demo() {
|
|
43
44
|
return (
|
|
44
45
|
<dui-input
|
|
45
|
-
|
|
46
|
+
label="Email"
|
|
47
|
+
label-position="floating"
|
|
46
48
|
onInput={(e) => {
|
|
47
49
|
const el = e.currentTarget as HTMLInputElement & { value: string };
|
|
48
50
|
console.log(el.value);
|
|
@@ -65,7 +67,7 @@ function handleInput(e: Event) {
|
|
|
65
67
|
</script>
|
|
66
68
|
|
|
67
69
|
<template>
|
|
68
|
-
<dui-input
|
|
70
|
+
<dui-input label="Email" label-position="floating" @input="handleInput" />
|
|
69
71
|
</template>
|
|
70
72
|
```
|
|
71
73
|
|
|
@@ -81,15 +83,19 @@ CSS custom properties:
|
|
|
81
83
|
- `--ui-input-color`
|
|
82
84
|
- `--ui-input-placeholder-color`
|
|
83
85
|
- `--ui-input-focus-ring`
|
|
86
|
+
- `--ui-input-label-font-size`
|
|
87
|
+
|
|
88
|
+
Default size values in `<dui-input>` are pixel-based.
|
|
84
89
|
|
|
85
90
|
Example:
|
|
86
91
|
|
|
87
92
|
```css
|
|
88
93
|
dui-input {
|
|
89
|
-
--ui-input-padding:
|
|
94
|
+
--ui-input-padding: 12px 16px;
|
|
90
95
|
--ui-input-border: 1px solid #94a3b8;
|
|
91
96
|
--ui-input-radius: 999px;
|
|
92
97
|
--ui-input-focus-ring: 0 0 0 3px rgba(59, 130, 246, 0.35);
|
|
98
|
+
--ui-input-label-font-size: 14px;
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
dui-input::part(input) {
|
|
@@ -97,6 +103,14 @@ dui-input::part(input) {
|
|
|
97
103
|
}
|
|
98
104
|
```
|
|
99
105
|
|
|
106
|
+
**Labels**
|
|
107
|
+
|
|
108
|
+
`label` and `label-position` control the built-in label:
|
|
109
|
+
|
|
110
|
+
- `label-position="above"` (default): label sits above the field.
|
|
111
|
+
- `label-position="floating"`: label sits like a placeholder and floats to the top-left on focus or when the input has a value.
|
|
112
|
+
- Floating mode hides placeholder text to avoid overlap with the label.
|
|
113
|
+
|
|
100
114
|
**Form Behavior**
|
|
101
115
|
|
|
102
116
|
`<dui-input>` dispatches native `input` and `change` events (bubbling + composed) and exposes a `value` property on the custom element. It also integrates with forms via the Form-Associated Custom Elements API where supported.
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { property as
|
|
3
|
-
import { ifDefined as
|
|
4
|
-
var
|
|
5
|
-
for (var
|
|
6
|
-
(
|
|
7
|
-
return
|
|
1
|
+
import { css as h, LitElement as c, html as d } from "lit";
|
|
2
|
+
import { property as l, query as f, customElement as b } from "lit/decorators.js";
|
|
3
|
+
import { ifDefined as u } from "lit/directives/if-defined.js";
|
|
4
|
+
var g = Object.defineProperty, v = Object.getOwnPropertyDescriptor, a = (t, i, n, r) => {
|
|
5
|
+
for (var o = r > 1 ? void 0 : r ? v(i, n) : i, s = t.length - 1, p; s >= 0; s--)
|
|
6
|
+
(p = t[s]) && (o = (r ? p(i, n, o) : p(o)) || o);
|
|
7
|
+
return r && o && g(i, n, o), o;
|
|
8
8
|
};
|
|
9
|
-
let
|
|
9
|
+
let e = class extends c {
|
|
10
10
|
constructor() {
|
|
11
|
-
super(), this.value = "", this.placeholder = "", this.name = "", this.disabled = !1, this.required = !1, this.type = "text", "attachInternals" in this && (this.internals = this.attachInternals());
|
|
11
|
+
super(), this.value = "", this.placeholder = "", this.name = "", this.disabled = !1, this.required = !1, this.type = "text", this.label = "", this.labelPosition = "above", "attachInternals" in this && (this.internals = this.attachInternals());
|
|
12
12
|
}
|
|
13
13
|
connectedCallback() {
|
|
14
14
|
super.connectedCallback(), this.defaultValue === void 0 && (this.defaultValue = this.getAttribute("value") ?? ""), this.syncFormValue();
|
|
15
15
|
}
|
|
16
|
-
updated(
|
|
17
|
-
(
|
|
16
|
+
updated(t) {
|
|
17
|
+
(t.has("value") || t.has("disabled")) && this.syncFormValue();
|
|
18
18
|
}
|
|
19
|
-
focus(
|
|
20
|
-
this.inputEl?.focus(
|
|
19
|
+
focus(t) {
|
|
20
|
+
this.inputEl?.focus(t);
|
|
21
21
|
}
|
|
22
22
|
blur() {
|
|
23
23
|
this.inputEl?.blur();
|
|
@@ -25,11 +25,11 @@ let t = class extends h {
|
|
|
25
25
|
formResetCallback() {
|
|
26
26
|
this.value = this.defaultValue ?? "";
|
|
27
27
|
}
|
|
28
|
-
formStateRestoreCallback(
|
|
29
|
-
typeof
|
|
28
|
+
formStateRestoreCallback(t) {
|
|
29
|
+
typeof t == "string" && (this.value = t);
|
|
30
30
|
}
|
|
31
|
-
formDisabledCallback(
|
|
32
|
-
this.disabled =
|
|
31
|
+
formDisabledCallback(t) {
|
|
32
|
+
this.disabled = t;
|
|
33
33
|
}
|
|
34
34
|
syncFormValue() {
|
|
35
35
|
if (this.internals) {
|
|
@@ -40,53 +40,93 @@ let t = class extends h {
|
|
|
40
40
|
this.internals.setFormValue(this.value);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
handleInput(
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
this.value =
|
|
43
|
+
handleInput(t) {
|
|
44
|
+
t.stopPropagation();
|
|
45
|
+
const i = t.target;
|
|
46
|
+
this.value = i.value, this.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 }));
|
|
47
47
|
}
|
|
48
|
-
handleChange(
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
this.value =
|
|
48
|
+
handleChange(t) {
|
|
49
|
+
t.stopPropagation();
|
|
50
|
+
const i = t.target;
|
|
51
|
+
this.value = i.value, this.dispatchEvent(new Event("change", { bubbles: !0, composed: !0 }));
|
|
52
52
|
}
|
|
53
|
-
handleKeydown(
|
|
54
|
-
if (
|
|
55
|
-
const
|
|
56
|
-
this.value =
|
|
53
|
+
handleKeydown(t) {
|
|
54
|
+
if (t.key !== "Enter") return;
|
|
55
|
+
const i = t.target;
|
|
56
|
+
this.value = i.value, this.dispatchEvent(new Event("change", { bubbles: !0, composed: !0 }));
|
|
57
57
|
}
|
|
58
58
|
render() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
const t = this.label.length > 0, i = t && this.labelPosition === "floating", n = this.value.length > 0, r = i ? void 0 : this.placeholder || void 0;
|
|
60
|
+
return d`
|
|
61
|
+
<div class="field ${i ? "floating" : ""}" data-has-value=${n}>
|
|
62
|
+
${t ? d`<label for="input">${this.label}</label>` : null}
|
|
63
|
+
<input
|
|
64
|
+
id="input"
|
|
65
|
+
part="input"
|
|
66
|
+
.value=${this.value}
|
|
67
|
+
.type=${this.type}
|
|
68
|
+
.name=${this.name}
|
|
69
|
+
?disabled=${this.disabled}
|
|
70
|
+
?required=${this.required}
|
|
71
|
+
placeholder=${u(r)}
|
|
72
|
+
autocomplete=${u(this.autocomplete)}
|
|
73
|
+
aria-label=${u(this.label || this.placeholder || void 0)}
|
|
74
|
+
@input=${this.handleInput}
|
|
75
|
+
@change=${this.handleChange}
|
|
76
|
+
@keydown=${this.handleKeydown}
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
73
79
|
`;
|
|
74
80
|
}
|
|
75
81
|
};
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
e.formAssociated = !0;
|
|
83
|
+
e.styles = h`
|
|
78
84
|
:host {
|
|
79
85
|
display: inline-block;
|
|
80
86
|
width: 100%;
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
.field {
|
|
90
|
+
position: relative;
|
|
91
|
+
display: block;
|
|
92
|
+
width: 100%;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
label {
|
|
96
|
+
display: block;
|
|
97
|
+
font-size: var(--ui-input-label-font-size, 14px);
|
|
98
|
+
color: var(--ui-input-label-color, #475569);
|
|
99
|
+
margin-bottom: 6px;
|
|
100
|
+
line-height: 1.2;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.field.floating label {
|
|
104
|
+
position: absolute;
|
|
105
|
+
left: var(--ui-input-floating-label-left, 12px);
|
|
106
|
+
top: 50%;
|
|
107
|
+
transform: translateY(-50%);
|
|
108
|
+
margin: 0;
|
|
109
|
+
padding: 0 4px;
|
|
110
|
+
background: var(--ui-input-bg, #ffffff);
|
|
111
|
+
color: var(--ui-input-placeholder-color, #9aa4b2);
|
|
112
|
+
pointer-events: none;
|
|
113
|
+
transition: transform 120ms ease, top 120ms ease, color 120ms ease;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.field.floating[data-has-value='true'] label,
|
|
117
|
+
:host(:focus-within) .field.floating label {
|
|
118
|
+
top: 6px;
|
|
119
|
+
transform: translateY(0) scale(0.85);
|
|
120
|
+
color: var(--ui-input-label-color, #475569);
|
|
121
|
+
}
|
|
122
|
+
|
|
83
123
|
input {
|
|
84
124
|
box-sizing: border-box;
|
|
85
125
|
width: 100%;
|
|
86
|
-
padding: var(--ui-input-padding,
|
|
87
|
-
font-size: var(--ui-input-font-size,
|
|
126
|
+
padding: var(--ui-input-padding, 8px 12px);
|
|
127
|
+
font-size: var(--ui-input-font-size, 16px);
|
|
88
128
|
border: var(--ui-input-border, 1px solid #c6ccd5);
|
|
89
|
-
border-radius: var(--ui-input-radius,
|
|
129
|
+
border-radius: var(--ui-input-radius, 8px);
|
|
90
130
|
background: var(--ui-input-bg, #ffffff);
|
|
91
131
|
color: var(--ui-input-color, #1f2937);
|
|
92
132
|
outline: none;
|
|
@@ -97,6 +137,10 @@ t.styles = d`
|
|
|
97
137
|
color: var(--ui-input-placeholder-color, #9aa4b2);
|
|
98
138
|
}
|
|
99
139
|
|
|
140
|
+
.field.floating input::placeholder {
|
|
141
|
+
color: transparent;
|
|
142
|
+
}
|
|
143
|
+
|
|
100
144
|
input:focus {
|
|
101
145
|
box-shadow: var(--ui-input-focus-ring, 0 0 0 3px rgba(24, 98, 255, 0.25));
|
|
102
146
|
}
|
|
@@ -105,34 +149,47 @@ t.styles = d`
|
|
|
105
149
|
opacity: 0.6;
|
|
106
150
|
cursor: not-allowed;
|
|
107
151
|
}
|
|
152
|
+
|
|
153
|
+
.field.floating input {
|
|
154
|
+
padding-top: var(--ui-input-floating-padding-top, 15px);
|
|
155
|
+
padding-right: var(--ui-input-floating-padding-right, 12px);
|
|
156
|
+
padding-bottom: var(--ui-input-floating-padding-bottom, 7px);
|
|
157
|
+
padding-left: var(--ui-input-floating-padding-left, 12px);
|
|
158
|
+
}
|
|
108
159
|
`;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
],
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
],
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
],
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
],
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
],
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
],
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
],
|
|
130
|
-
|
|
160
|
+
a([
|
|
161
|
+
l({ type: String })
|
|
162
|
+
], e.prototype, "value", 2);
|
|
163
|
+
a([
|
|
164
|
+
l({ type: String })
|
|
165
|
+
], e.prototype, "placeholder", 2);
|
|
166
|
+
a([
|
|
167
|
+
l({ type: String, reflect: !0 })
|
|
168
|
+
], e.prototype, "name", 2);
|
|
169
|
+
a([
|
|
170
|
+
l({ type: Boolean, reflect: !0 })
|
|
171
|
+
], e.prototype, "disabled", 2);
|
|
172
|
+
a([
|
|
173
|
+
l({ type: Boolean, reflect: !0 })
|
|
174
|
+
], e.prototype, "required", 2);
|
|
175
|
+
a([
|
|
176
|
+
l({ type: String, reflect: !0 })
|
|
177
|
+
], e.prototype, "type", 2);
|
|
178
|
+
a([
|
|
179
|
+
l({ type: String, reflect: !0 })
|
|
180
|
+
], e.prototype, "autocomplete", 2);
|
|
181
|
+
a([
|
|
182
|
+
l({ type: String })
|
|
183
|
+
], e.prototype, "label", 2);
|
|
184
|
+
a([
|
|
185
|
+
l({ type: String, attribute: "label-position" })
|
|
186
|
+
], e.prototype, "labelPosition", 2);
|
|
187
|
+
a([
|
|
131
188
|
f("input")
|
|
132
|
-
],
|
|
133
|
-
|
|
189
|
+
], e.prototype, "inputEl", 2);
|
|
190
|
+
e = a([
|
|
134
191
|
b("dui-input")
|
|
135
|
-
],
|
|
192
|
+
], e);
|
|
136
193
|
export {
|
|
137
|
-
|
|
194
|
+
e as DuiInput
|
|
138
195
|
};
|