@excom/super-input 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/chunked-rush-logs/super-input.apply-exports.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/super-input.build_docs.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/super-input.build_package-metas.chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/all.log +1 -0
- package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/state.json +3 -0
- package/.rush/temp/operation/build_docs/all.log +1 -0
- package/.rush/temp/operation/build_docs/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_docs/state.json +3 -0
- package/.rush/temp/operation/build_package-metas/all.log +1 -0
- package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_package-metas/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +9 -0
- package/config/rig.json +5 -0
- package/index.css +5 -0
- package/index.ts +17 -0
- package/package.json +44 -0
- package/rush-logs/super-input.apply-exports.cache.log +1 -0
- package/rush-logs/super-input.apply-exports.log +1 -0
- package/rush-logs/super-input.build_docs.cache.log +1 -0
- package/rush-logs/super-input.build_docs.log +1 -0
- package/rush-logs/super-input.build_package-metas.cache.log +1 -0
- package/rush-logs/super-input.build_package-metas.log +1 -0
- package/src/super-input.css +372 -0
- package/super-input.ts +165 -0
- package/support/custom-elements.json +327 -0
- package/support/demos/comprehensive.html +13 -0
- package/support/demos/invalid-message.html +7 -0
- package/support/demos/reflect-value.html +15 -0
- package/support/demos/slider.html +4 -0
- package/support/demos/with-format.html +4 -0
- package/support/dist-docs/super-input.md +208 -0
- package/support/docs/README.md +71 -0
- package/support/package-meta.json +275 -0
- package/support/tests/comprehensive.view.test.ts +22 -0
- package/support/tests/invalid-message.view.test.ts +21 -0
- package/support/tests/reflect-value.view.test.ts +24 -0
- package/support/tests/slider.view.test.ts +24 -0
- package/support/tests/super-input.test.ts +245 -0
- package/support/tests/with-format.view.test.ts +20 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"../../packages/super-input": "../../packages/super-input:fueVqvrObk+Av74S5aPlYPlhcaLS7CnIrVGb9WU6O8s=:",
|
|
3
|
+
"input-format@0.3.14": "input-format@0.3.14:wcZZfzrfa6WangE6QCn6dztFBYbHJDpmvmqRVDmgNCY=:",
|
|
4
|
+
"js-tokens@4.0.0": "js-tokens@4.0.0:bylIGj6At7FynPHmuZRgqLdhMSiaXEF+4m8SwJ0gY5k=:",
|
|
5
|
+
"loose-envify@1.4.0": "loose-envify@1.4.0:jl4j5x+ArQHmZCLrhcyKySMYfzxa2ijSEIuGDd0Pnn4=:",
|
|
6
|
+
"object-assign@4.1.1": "object-assign@4.1.1:gEYm2YMdR9pgGzUfDEsvSm8ByOtns3HUdx2PKjOtz8o=:",
|
|
7
|
+
"prop-types@15.8.1": "prop-types@15.8.1:F1eP/KKS5NQ0iflvTEPenWZltp31hhxQ7mL9wYzJELU=:",
|
|
8
|
+
"react-is@16.13.1": "react-is@16.13.1:qb0MRFVn3OE37GB60Jr8crveic53PdhMhnO/V/iWDPw=:"
|
|
9
|
+
}
|
package/config/rig.json
ADDED
package/index.css
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SuperInput } from "./super-input";
|
|
2
|
+
|
|
3
|
+
SuperInput.define();
|
|
4
|
+
|
|
5
|
+
export { SuperInput };
|
|
6
|
+
|
|
7
|
+
type T_HTMLSuperInputElement = typeof SuperInput.CustomElement;
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLSuperInputElement extends T_HTMLSuperInputElement {}
|
|
10
|
+
interface Window {
|
|
11
|
+
HTMLSuperInputElement: HTMLSuperInputElement;
|
|
12
|
+
}
|
|
13
|
+
interface HTMLElementTagNameMap {
|
|
14
|
+
"super-input": HTMLSuperInputElement;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export type { HTMLSuperInputElement };
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@excom/super-input",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "<super-input> custom element",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.13.0"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"input-format": "^0.3.10",
|
|
12
|
+
"@excom/neutron": "^0.1.0",
|
|
13
|
+
"@excom/valence": "^0.1.0"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@excom/heft-rig": "^0.1.0"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"url": "excom-dev/nucleus",
|
|
21
|
+
"directory": "packages/super-input"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/excom-dev/nucleus/tree/main/packages/super-input/support/docs/README.md",
|
|
24
|
+
"bugs": "https://github.com/excom-dev/nucleus/issues",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"super-input",
|
|
27
|
+
"neutron",
|
|
28
|
+
"custom-elements"
|
|
29
|
+
],
|
|
30
|
+
"excom": {
|
|
31
|
+
"packageType": "kit-element"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "node node_modules/@excom/heft-rig/scripts/vite-build.mjs",
|
|
35
|
+
"build:watch": "node node_modules/@excom/heft-rig/scripts/vite-build-watch.mjs",
|
|
36
|
+
"format": "node node_modules/@excom/heft-rig/scripts/format.mjs",
|
|
37
|
+
"test": "node node_modules/@excom/heft-rig/scripts/vitest.mjs",
|
|
38
|
+
"coverage": "node node_modules/@excom/heft-rig/scripts/coverage.mjs",
|
|
39
|
+
"dev": "node node_modules/@excom/heft-rig/scripts/vite-dev.mjs",
|
|
40
|
+
"preview": "node node_modules/@excom/heft-rig/scripts/vite-preview.mjs",
|
|
41
|
+
"build:package-metas": "node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs",
|
|
42
|
+
"build:docs": "node node_modules/@excom/heft-rig/scripts/build-docs.mjs"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Caching has been disabled for this project's "apply-exports" command.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:docs" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:package-metas" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
@import "@excom/valence/src/util.default.css";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Styles for `<super-input>`.
|
|
5
|
+
* @element super-input
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* Aliases */
|
|
9
|
+
@custom-selector :--super-input super-input, .tag-super-input;
|
|
10
|
+
@custom-selector :--super-input--has-reflect-value
|
|
11
|
+
[reflect-value],
|
|
12
|
+
[data-reflect-value];
|
|
13
|
+
@custom-selector :--super-input--has-current-value
|
|
14
|
+
[current-value],
|
|
15
|
+
[data-current-value];
|
|
16
|
+
|
|
17
|
+
@define-mixin slider-track {
|
|
18
|
+
height: var(--super-input-track-height);
|
|
19
|
+
line-height: normal;
|
|
20
|
+
background: linear-gradient(
|
|
21
|
+
to right,
|
|
22
|
+
var(--super-input-accent) 0%,
|
|
23
|
+
var(--super-input-accent) var(--super-input-progress, 50%),
|
|
24
|
+
transparent var(--super-input-progress, 50%),
|
|
25
|
+
transparent 100%
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@define-mixin slider-thumb {
|
|
30
|
+
margin: calc(
|
|
31
|
+
calc(var(--super-input-thumb-size) * -0.5) +
|
|
32
|
+
var(--super-input-track-height)
|
|
33
|
+
)
|
|
34
|
+
0 0 0;
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
cursor: grab;
|
|
37
|
+
width: var(--super-input-thumb-size);
|
|
38
|
+
height: var(--super-input-thumb-size);
|
|
39
|
+
background: var(--super-input-thumb-color);
|
|
40
|
+
border-radius: var(--super-input-thumb-radius, 100%);
|
|
41
|
+
border: var(
|
|
42
|
+
--super-input-thumb-border,
|
|
43
|
+
var(--super-input-border-width) solid var(--super-input-primary)
|
|
44
|
+
);
|
|
45
|
+
-webkit-appearance: none;
|
|
46
|
+
appearance: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@define-mixin module-super-input {
|
|
50
|
+
:root {
|
|
51
|
+
/**
|
|
52
|
+
* Foreground / label color.
|
|
53
|
+
* @cssproperty
|
|
54
|
+
* @syntax <color>
|
|
55
|
+
*/
|
|
56
|
+
--super-input-color: var(--v-color, inherit);
|
|
57
|
+
/**
|
|
58
|
+
* Surface background behind the control (and raised-label mask).
|
|
59
|
+
* @cssproperty
|
|
60
|
+
* @syntax <color>
|
|
61
|
+
*/
|
|
62
|
+
--super-input-bg: var(--v-form-element-background-color, transparent);
|
|
63
|
+
/**
|
|
64
|
+
* Default border color for raised inputs.
|
|
65
|
+
* @cssproperty
|
|
66
|
+
* @syntax <color>
|
|
67
|
+
*/
|
|
68
|
+
--super-input-border-color: var(
|
|
69
|
+
--v-form-element-border-color,
|
|
70
|
+
currentColor
|
|
71
|
+
);
|
|
72
|
+
/**
|
|
73
|
+
* Focus ring / focus border color.
|
|
74
|
+
* @cssproperty
|
|
75
|
+
* @syntax <color>
|
|
76
|
+
*/
|
|
77
|
+
--super-input-focus-color: var(
|
|
78
|
+
--v-form-element-focus-color,
|
|
79
|
+
var(--super-input-border-color)
|
|
80
|
+
);
|
|
81
|
+
/**
|
|
82
|
+
* Corner radius for raised inputs.
|
|
83
|
+
* @cssproperty
|
|
84
|
+
* @syntax <length>
|
|
85
|
+
*/
|
|
86
|
+
--super-input-border-radius: var(--v-border-radius, 4px);
|
|
87
|
+
/**
|
|
88
|
+
* Border width for raised inputs.
|
|
89
|
+
* @cssproperty
|
|
90
|
+
* @syntax <length>
|
|
91
|
+
*/
|
|
92
|
+
--super-input-border-width: var(--v-border-width, 1px);
|
|
93
|
+
/**
|
|
94
|
+
* Duration for border / label transitions.
|
|
95
|
+
* @cssproperty
|
|
96
|
+
* @syntax <time>
|
|
97
|
+
*/
|
|
98
|
+
--super-input-transition-duration: var(--v-transition-duration-fast, 0.15s);
|
|
99
|
+
/**
|
|
100
|
+
* Easing for border / label transitions.
|
|
101
|
+
* @cssproperty
|
|
102
|
+
* @syntax *
|
|
103
|
+
*/
|
|
104
|
+
--super-input-transition-ease: var(--v-transition-ease-out, ease-out);
|
|
105
|
+
/**
|
|
106
|
+
* Accent color (range fill, thumb border, focus chrome).
|
|
107
|
+
* @cssproperty
|
|
108
|
+
* @syntax <color>
|
|
109
|
+
*/
|
|
110
|
+
--super-input-primary: var(--v-primary, blue);
|
|
111
|
+
/**
|
|
112
|
+
* Gap between a floating label and the control.
|
|
113
|
+
* @cssproperty
|
|
114
|
+
* @syntax <length>
|
|
115
|
+
*/
|
|
116
|
+
--super-input-label-margin-bottom: calc(21px * 0.375);
|
|
117
|
+
/**
|
|
118
|
+
* Base font size for the control and value readout.
|
|
119
|
+
* @cssproperty
|
|
120
|
+
* @syntax <length>
|
|
121
|
+
*/
|
|
122
|
+
--super-input-font-size: 16px;
|
|
123
|
+
/**
|
|
124
|
+
* Computed label line box height (used when a `<label>` is present).
|
|
125
|
+
* @cssproperty
|
|
126
|
+
* @syntax <length>
|
|
127
|
+
*/
|
|
128
|
+
--super-input-label-height: calc(
|
|
129
|
+
var(--v-line-height, 1.5) * var(--super-input-font-size)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
:--super-input {
|
|
134
|
+
&:has(input[type="range"]) {
|
|
135
|
+
/**
|
|
136
|
+
* Host height for range layout (thumb + value readout).
|
|
137
|
+
* @cssproperty
|
|
138
|
+
* @syntax <length>
|
|
139
|
+
*/
|
|
140
|
+
--super-input-height: calc(var(--super-input-thumb-size) + 36px);
|
|
141
|
+
/**
|
|
142
|
+
* Host width for range layout.
|
|
143
|
+
* @cssproperty
|
|
144
|
+
* @syntax <length> | <percentage>
|
|
145
|
+
*/
|
|
146
|
+
--super-input-width: 100%;
|
|
147
|
+
/**
|
|
148
|
+
* Range minimum. Prefer setting on the host (or via CSS): CSS cannot
|
|
149
|
+
* read the child input's `min` attribute from the parent.
|
|
150
|
+
* @cssproperty
|
|
151
|
+
* @syntax <number>
|
|
152
|
+
*/
|
|
153
|
+
--super-input-min: 0;
|
|
154
|
+
/**
|
|
155
|
+
* Range maximum. Prefer setting on the host (or via CSS).
|
|
156
|
+
* @cssproperty
|
|
157
|
+
* @syntax <number>
|
|
158
|
+
*/
|
|
159
|
+
--super-input-max: 100;
|
|
160
|
+
/**
|
|
161
|
+
* Current range value used for fill / readout positioning. With
|
|
162
|
+
* `reflect-value`, may be driven from `attr(current-value)` where
|
|
163
|
+
* typed `attr()` is supported.
|
|
164
|
+
* @cssproperty
|
|
165
|
+
* @syntax <number>
|
|
166
|
+
*/
|
|
167
|
+
--super-input-value: 50;
|
|
168
|
+
/* START this will not work in safari or firefox yet */
|
|
169
|
+
--super-input-value: attr(current-value type(<number>));
|
|
170
|
+
/* END */
|
|
171
|
+
/** @internal */
|
|
172
|
+
--super-input-zero: calc(
|
|
173
|
+
var(--super-input-value) - var(--super-input-min, 0)
|
|
174
|
+
);
|
|
175
|
+
/** @internal */
|
|
176
|
+
--super-input-range: calc(
|
|
177
|
+
var(--super-input-max, 100) - var(--super-input-min, 0)
|
|
178
|
+
);
|
|
179
|
+
/** @internal */
|
|
180
|
+
--super-input-number-raw: calc(
|
|
181
|
+
calc(var(--super-input-zero) / var(--super-input-range)) *
|
|
182
|
+
calc(var(--super-input-width) - var(--super-input-thumb-size))
|
|
183
|
+
);
|
|
184
|
+
/** @internal Fill / readout progress position along the track. */
|
|
185
|
+
--super-input-progress: calc(
|
|
186
|
+
var(--super-input-number-raw) + calc(var(--super-input-thumb-size) / 2)
|
|
187
|
+
);
|
|
188
|
+
/**
|
|
189
|
+
* Diameter of the range thumb.
|
|
190
|
+
* @cssproperty
|
|
191
|
+
* @syntax <length>
|
|
192
|
+
*/
|
|
193
|
+
--super-input-thumb-size: 44px;
|
|
194
|
+
/**
|
|
195
|
+
* Range thumb fill color.
|
|
196
|
+
* @cssproperty
|
|
197
|
+
* @syntax <color>
|
|
198
|
+
*/
|
|
199
|
+
--super-input-thumb-color: var(
|
|
200
|
+
--v-range-thumb-color,
|
|
201
|
+
var(--super-input-bg)
|
|
202
|
+
);
|
|
203
|
+
/**
|
|
204
|
+
* Active track / accent color for the range fill.
|
|
205
|
+
* @cssproperty
|
|
206
|
+
* @syntax <color>
|
|
207
|
+
*/
|
|
208
|
+
--super-input-accent: var(--super-input-primary, blue);
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Height of the range track.
|
|
212
|
+
* @cssproperty
|
|
213
|
+
* @syntax <length>
|
|
214
|
+
*/
|
|
215
|
+
--super-input-track-height: 2px;
|
|
216
|
+
|
|
217
|
+
/** @internal */
|
|
218
|
+
--super-input-value-content: attr(current-value);
|
|
219
|
+
/** @internal */
|
|
220
|
+
--super-input-value-bottom: var(--super-input-thumb-size);
|
|
221
|
+
/** @internal */
|
|
222
|
+
--super-input-value-transform: translate(-50%, 0);
|
|
223
|
+
|
|
224
|
+
display: block;
|
|
225
|
+
position: relative;
|
|
226
|
+
box-sizing: border-box;
|
|
227
|
+
font-size: var(--super-input-font-size);
|
|
228
|
+
/**
|
|
229
|
+
* Font weight for the range value readout.
|
|
230
|
+
* @cssproperty --super-input-font-weight
|
|
231
|
+
* @syntax <number> | <integer>
|
|
232
|
+
* @default 700
|
|
233
|
+
*/
|
|
234
|
+
font-weight: var(--super-input-font-weight, 700);
|
|
235
|
+
height: var(--super-input-height, 100%);
|
|
236
|
+
width: var(--super-input-width, 100%);
|
|
237
|
+
&:has(label) {
|
|
238
|
+
padding-top: calc(
|
|
239
|
+
var(--super-input-label-height) + var(--super-input-height, 100%)
|
|
240
|
+
);
|
|
241
|
+
label {
|
|
242
|
+
position: absolute;
|
|
243
|
+
margin: 0;
|
|
244
|
+
top: 0;
|
|
245
|
+
left: 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
input,
|
|
250
|
+
&::before {
|
|
251
|
+
position: absolute;
|
|
252
|
+
bottom: calc(var(--super-input-thumb-size) / 2);
|
|
253
|
+
}
|
|
254
|
+
&::before {
|
|
255
|
+
position: absolute;
|
|
256
|
+
display: block;
|
|
257
|
+
box-sizing: border-box;
|
|
258
|
+
text-align: center;
|
|
259
|
+
padding-bottom: var(--super-input-label-margin-bottom);
|
|
260
|
+
bottom: var(--super-input-value-bottom);
|
|
261
|
+
left: var(--super-input-progress);
|
|
262
|
+
content: var(--super-input-value-content);
|
|
263
|
+
transform: var(--super-input-value-transform);
|
|
264
|
+
}
|
|
265
|
+
input {
|
|
266
|
+
box-sizing: border-box;
|
|
267
|
+
margin: 0;
|
|
268
|
+
width: 100%;
|
|
269
|
+
background: var(--super-input-bg);
|
|
270
|
+
height: var(--super-input-track-height);
|
|
271
|
+
outline: none;
|
|
272
|
+
z-index: 2;
|
|
273
|
+
-webkit-appearance: none;
|
|
274
|
+
-moz-appearance: none;
|
|
275
|
+
appearance: none;
|
|
276
|
+
/* Don't combine webkit + moz selectors; identical blocks still break WebKit. */
|
|
277
|
+
&::-webkit-slider-runnable-track {
|
|
278
|
+
@mixin slider-track;
|
|
279
|
+
}
|
|
280
|
+
&::-moz-range-track {
|
|
281
|
+
@mixin slider-track;
|
|
282
|
+
}
|
|
283
|
+
&::-webkit-slider-thumb {
|
|
284
|
+
@mixin slider-thumb;
|
|
285
|
+
}
|
|
286
|
+
&::-moz-range-thumb {
|
|
287
|
+
@mixin slider-thumb;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Raised / floating-label text field appearance. Apply as
|
|
294
|
+
* `class="raised"` on `<super-input>` wrapping a text-like `<input>`.
|
|
295
|
+
* @cssclass
|
|
296
|
+
*/
|
|
297
|
+
&.raised {
|
|
298
|
+
display: block;
|
|
299
|
+
position: relative;
|
|
300
|
+
margin-top: 8px;
|
|
301
|
+
|
|
302
|
+
input {
|
|
303
|
+
@mixin util-nested-card;
|
|
304
|
+
font-size: 1rem;
|
|
305
|
+
padding: 0 10px 0 10px;
|
|
306
|
+
outline: none;
|
|
307
|
+
border-radius: var(--super-input-border-radius);
|
|
308
|
+
color: var(--super-input-color);
|
|
309
|
+
border: var(--super-input-border-width) solid
|
|
310
|
+
var(--super-input-border-color);
|
|
311
|
+
transition: border-color var(--super-input-transition-duration)
|
|
312
|
+
var(--super-input-transition-ease);
|
|
313
|
+
&:focus {
|
|
314
|
+
border-color: var(--super-input-focus-color) !important;
|
|
315
|
+
}
|
|
316
|
+
&::placeholder {
|
|
317
|
+
transition: color var(--super-input-transition-duration)
|
|
318
|
+
var(--super-input-transition-ease);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
label {
|
|
322
|
+
position: absolute;
|
|
323
|
+
margin: 0;
|
|
324
|
+
font-size: 0.9rem;
|
|
325
|
+
line-height: var(--v-line-height, 16px);
|
|
326
|
+
top: -14px;
|
|
327
|
+
left: 10px;
|
|
328
|
+
background: transparent;
|
|
329
|
+
color: var(--super-input-color);
|
|
330
|
+
padding: 0 3px;
|
|
331
|
+
pointer-events: none;
|
|
332
|
+
z-index: 1;
|
|
333
|
+
transition:
|
|
334
|
+
top var(--super-input-transition-duration)
|
|
335
|
+
var(--super-input-transition-ease),
|
|
336
|
+
font-size var(--super-input-transition-duration)
|
|
337
|
+
var(--super-input-transition-ease);
|
|
338
|
+
&::after {
|
|
339
|
+
/* a line to hide input border behind label */
|
|
340
|
+
content: "";
|
|
341
|
+
position: absolute;
|
|
342
|
+
top: 12px;
|
|
343
|
+
left: 0;
|
|
344
|
+
width: 100%;
|
|
345
|
+
height: 4px;
|
|
346
|
+
z-index: -1;
|
|
347
|
+
background-color: var(--super-input-bg);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* `[reflect-value]`: raised label even with no placeholder */
|
|
352
|
+
&:--super-input--has-reflect-value:not(:--super-input--has-current-value):not(
|
|
353
|
+
:has(input:focus)
|
|
354
|
+
),
|
|
355
|
+
/* Else fall back to `:placeholder-shown` */
|
|
356
|
+
&:not(:--super-input--has-reflect-value):has(input:placeholder-shown):not(
|
|
357
|
+
:has(input:focus)
|
|
358
|
+
) {
|
|
359
|
+
label {
|
|
360
|
+
font-size: 1rem;
|
|
361
|
+
top: 16px;
|
|
362
|
+
&::after {
|
|
363
|
+
content: none;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
input::placeholder {
|
|
367
|
+
color: transparent;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
package/super-input.ts
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { Neutron } from "@excom/neutron";
|
|
2
|
+
// TODO swap this library for something lighter.
|
|
3
|
+
import {
|
|
4
|
+
format as formatInput,
|
|
5
|
+
parse as parseInput,
|
|
6
|
+
parseDigit,
|
|
7
|
+
templateFormatter,
|
|
8
|
+
templateParser,
|
|
9
|
+
} from "input-format";
|
|
10
|
+
|
|
11
|
+
const formatValue = (
|
|
12
|
+
value: string,
|
|
13
|
+
selection: number,
|
|
14
|
+
textFormat: string,
|
|
15
|
+
parseFormat?: string
|
|
16
|
+
) => {
|
|
17
|
+
const parser = templateParser(parseFormat ?? textFormat, parseDigit);
|
|
18
|
+
const formatter = templateFormatter(textFormat);
|
|
19
|
+
return formatInput(parseInput(value, -1, parser).value, selection, formatter)
|
|
20
|
+
.text;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Wrapper around a native `<input>` that adds live text formatting, auto-labeling, and
|
|
25
|
+
* a reflected value attribute. Does not replace the input — enhances it. Pair it with
|
|
26
|
+
* `<super-form>` for form-level submission handling.
|
|
27
|
+
*
|
|
28
|
+
* @descendant input - Required native `<input>` to enhance.
|
|
29
|
+
* @descendant ?label - Optional native `<label>`. When `auto-label` is set,
|
|
30
|
+
* its `for` attribute is linked to the input's `id`.
|
|
31
|
+
*
|
|
32
|
+
* @example Basic
|
|
33
|
+
* <super-input auto-label>
|
|
34
|
+
* <label>Name</label>
|
|
35
|
+
* <input />
|
|
36
|
+
* </super-input>
|
|
37
|
+
*
|
|
38
|
+
* @example With text formatting
|
|
39
|
+
* <super-input text-format="(xxx) xxx-xxxx" auto-label>
|
|
40
|
+
* <label>Phone</label>
|
|
41
|
+
* <input pattern="^\(\d{3}\)\s\d{3}-\d{4}" />
|
|
42
|
+
* </super-input>
|
|
43
|
+
*/
|
|
44
|
+
export const SuperInput = Neutron({
|
|
45
|
+
tag: "super-input",
|
|
46
|
+
props: {
|
|
47
|
+
/**
|
|
48
|
+
* @option
|
|
49
|
+
* Pattern defining visible formatting. Use `x` for any digit and any
|
|
50
|
+
* other character as a literal. Examples: `(xxx) xxx-xxxx`, `xx/xx/xxxx`,
|
|
51
|
+
* `xxx-xx-xxxx`. When set, the input value is live-formatted on every
|
|
52
|
+
* keystroke.
|
|
53
|
+
*/
|
|
54
|
+
textFormat: String,
|
|
55
|
+
/**
|
|
56
|
+
* @option
|
|
57
|
+
* If set, this message is installed via `setCustomValidity()` when the
|
|
58
|
+
* native `invalid` event fires, and cleared on the next `keydown`. Makes
|
|
59
|
+
* built-in HTML validation surface a custom message.
|
|
60
|
+
*/
|
|
61
|
+
invalidMessage: String,
|
|
62
|
+
/**
|
|
63
|
+
* @option
|
|
64
|
+
* When set, the current input value is mirrored to the `current-value`
|
|
65
|
+
* attribute so CSS and selectors can respond to it. Off by default because
|
|
66
|
+
* reflecting every keystroke is not free.
|
|
67
|
+
*/
|
|
68
|
+
reflectValue: Boolean,
|
|
69
|
+
/**
|
|
70
|
+
* @state
|
|
71
|
+
* Mirrors the wrapped `<input>`'s value when `reflect-value` is set.
|
|
72
|
+
* Read-only from the app's point of view — writing it does not change
|
|
73
|
+
* the input.
|
|
74
|
+
*/
|
|
75
|
+
currentValue: String,
|
|
76
|
+
/**
|
|
77
|
+
* @option
|
|
78
|
+
* When set, generates or uses an existing `id` on the `<input>` and associates the `<label>`.
|
|
79
|
+
*/
|
|
80
|
+
autoLabel: Boolean,
|
|
81
|
+
_inputElement: HTMLInputElement,
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
.defineMethods({
|
|
85
|
+
doFormat: ({ textFormat, _inputElement }, parseFormat?: string) => {
|
|
86
|
+
if ((!!textFormat || parseFormat) && _inputElement?.value) {
|
|
87
|
+
return {
|
|
88
|
+
_inputElement: {
|
|
89
|
+
value: formatValue(
|
|
90
|
+
_inputElement!.value,
|
|
91
|
+
_inputElement!.selectionEnd ?? 0,
|
|
92
|
+
textFormat ?? "",
|
|
93
|
+
parseFormat
|
|
94
|
+
),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
setCurrentValue: ({ reflectValue, _inputElement }) => ({
|
|
100
|
+
currentValue: reflectValue ? _inputElement?.value || null : null,
|
|
101
|
+
}),
|
|
102
|
+
handleInput: ({ reflectValue }) => [
|
|
103
|
+
{
|
|
104
|
+
doFormat: [],
|
|
105
|
+
},
|
|
106
|
+
reflectValue && {
|
|
107
|
+
setCurrentValue: [],
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
handleInvalid: ({ invalidMessage }) =>
|
|
111
|
+
invalidMessage && {
|
|
112
|
+
_inputElement: {
|
|
113
|
+
setCustomValidity: [invalidMessage],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
handleValid: () => ({
|
|
117
|
+
_inputElement: {
|
|
118
|
+
setCustomValidity: [""],
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
121
|
+
})
|
|
122
|
+
.onConnected((el) => ({
|
|
123
|
+
_inputElement: el.querySelector("input"),
|
|
124
|
+
}))
|
|
125
|
+
// formatting
|
|
126
|
+
.onPropChanged(
|
|
127
|
+
["_inputElement", "reflectValue", "textFormat"],
|
|
128
|
+
({ _inputElement, reflectValue, textFormat, handleInput }, previous) => [
|
|
129
|
+
// Rare: reformat the input programmatically
|
|
130
|
+
{ doFormat: [previous?.textFormat ?? undefined] },
|
|
131
|
+
{ setCurrentValue: [] },
|
|
132
|
+
_inputElement && {
|
|
133
|
+
_inputElement: {
|
|
134
|
+
// Same handler so these tasks stay in order
|
|
135
|
+
toggleListeners: [
|
|
136
|
+
["input", handleInput, reflectValue || !!textFormat],
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
)
|
|
142
|
+
.onPropChanged(
|
|
143
|
+
["_inputElement", "invalidMessage"],
|
|
144
|
+
({ _inputElement, invalidMessage, handleInvalid, handleValid }) =>
|
|
145
|
+
!!_inputElement && {
|
|
146
|
+
_inputElement: {
|
|
147
|
+
toggleListeners: [
|
|
148
|
+
["invalid", handleInvalid, !!invalidMessage],
|
|
149
|
+
["keydown", handleValid, !!invalidMessage],
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
.onPropChanged(["_inputElement", "autoLabel"], (ce) => {
|
|
155
|
+
const { _inputElement, autoLabel } = ce;
|
|
156
|
+
const labelElement = ce.querySelector("label");
|
|
157
|
+
if (_inputElement && autoLabel && labelElement) {
|
|
158
|
+
const labelValue =
|
|
159
|
+
_inputElement.id ||
|
|
160
|
+
labelElement.htmlFor ||
|
|
161
|
+
"super-input-" + Math.random().toString(36).substring(2, 10);
|
|
162
|
+
_inputElement.id = labelValue;
|
|
163
|
+
labelElement.htmlFor = labelValue;
|
|
164
|
+
}
|
|
165
|
+
});
|