@neovici/cosmoz-input 1.7.0 → 3.0.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/package.json +31 -20
- package/cosmoz-input.js +0 -47
- package/cosmoz-textarea.js +0 -38
- package/es-dev-server.config.js +0 -8
- package/render.js +0 -32
- package/styles.js +0 -160
- package/use-input.js +0 -79
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-input",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A input web component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit-html",
|
|
@@ -16,18 +16,20 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"author": "",
|
|
19
|
-
"main": "
|
|
19
|
+
"main": "dist/index.js",
|
|
20
20
|
"directories": {
|
|
21
21
|
"test": "test"
|
|
22
22
|
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist/"
|
|
25
|
+
],
|
|
23
26
|
"scripts": {
|
|
24
|
-
"lint": "eslint --cache
|
|
25
|
-
"
|
|
26
|
-
"start": "
|
|
27
|
+
"lint": "tsc && eslint --cache .",
|
|
28
|
+
"build": "tsc -p tsconfig.build.json",
|
|
29
|
+
"start": "wds",
|
|
27
30
|
"test": "wtr --coverage",
|
|
28
31
|
"test:watch": "wtr --watch",
|
|
29
32
|
"prepare": "husky install",
|
|
30
|
-
"storybook": "start-storybook --node-resolve --watch --open",
|
|
31
33
|
"storybook:build": "build-storybook",
|
|
32
34
|
"storybook:deploy": "storybook-to-ghpages"
|
|
33
35
|
},
|
|
@@ -46,32 +48,41 @@
|
|
|
46
48
|
"publishConfig": {
|
|
47
49
|
"access": "public"
|
|
48
50
|
},
|
|
49
|
-
"files": [
|
|
50
|
-
"*.js",
|
|
51
|
-
"lib/**/*.js"
|
|
52
|
-
],
|
|
53
51
|
"commitlint": {
|
|
54
52
|
"extends": [
|
|
55
53
|
"@commitlint/config-conventional"
|
|
56
|
-
]
|
|
54
|
+
],
|
|
55
|
+
"rules": {
|
|
56
|
+
"body-max-line-length": [
|
|
57
|
+
1,
|
|
58
|
+
"always",
|
|
59
|
+
100
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"exports": {
|
|
64
|
+
".": "./dist/index.js",
|
|
65
|
+
"./use-input": "./dist/use-input.js",
|
|
66
|
+
"./input": "./dist/cosmoz-input.js",
|
|
67
|
+
"./textarea": "./dist/cosmoz-textarea.js"
|
|
57
68
|
},
|
|
58
69
|
"dependencies": {
|
|
59
|
-
"@neovici/cosmoz-utils": "^
|
|
60
|
-
"haunted": "^
|
|
61
|
-
"lit-html": "^
|
|
70
|
+
"@neovici/cosmoz-utils": "^5.1.0",
|
|
71
|
+
"haunted": "^5.0.0",
|
|
72
|
+
"lit-html": "^2.0.0"
|
|
62
73
|
},
|
|
63
74
|
"devDependencies": {
|
|
64
|
-
"@commitlint/cli": "^
|
|
65
|
-
"@commitlint/config-conventional": "^
|
|
75
|
+
"@commitlint/cli": "^17.0.0",
|
|
76
|
+
"@commitlint/config-conventional": "^17.0.0",
|
|
66
77
|
"@neovici/cfg": "^1.13.1",
|
|
67
|
-
"@open-wc/
|
|
68
|
-
"@open-wc/testing": "^2.5.0",
|
|
78
|
+
"@open-wc/testing": "^3.0.0",
|
|
69
79
|
"@semantic-release/changelog": "^6.0.0",
|
|
70
80
|
"@semantic-release/git": "^10.0.0",
|
|
71
81
|
"@storybook/storybook-deployer": "^2.8.5",
|
|
72
|
-
"
|
|
82
|
+
"@web/dev-server-storybook": "^0.5.1",
|
|
83
|
+
"husky": "^8.0.0",
|
|
73
84
|
"semantic-release": "^19.0.0",
|
|
74
|
-
"sinon": "^
|
|
85
|
+
"sinon": "^14.0.0",
|
|
75
86
|
"typescript": "^4.6.0"
|
|
76
87
|
}
|
|
77
88
|
}
|
package/cosmoz-input.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { html } from 'lit-html'; // eslint-disable-line object-curly-newline
|
|
2
|
-
import { live } from 'lit-html/directives/live';
|
|
3
|
-
import { ifDefined } from 'lit-html/directives/if-defined';
|
|
4
|
-
|
|
5
|
-
import { component } from 'haunted';
|
|
6
|
-
import { useInput, useAllowedPattern } from './use-input';
|
|
7
|
-
import { render, attributes } from './render';
|
|
8
|
-
|
|
9
|
-
export const Input = host => {
|
|
10
|
-
const {
|
|
11
|
-
type = 'text',
|
|
12
|
-
pattern,
|
|
13
|
-
allowedPattern,
|
|
14
|
-
autocomplete,
|
|
15
|
-
value,
|
|
16
|
-
placeholder,
|
|
17
|
-
readonly,
|
|
18
|
-
disabled,
|
|
19
|
-
min,
|
|
20
|
-
max,
|
|
21
|
-
step,
|
|
22
|
-
maxlength
|
|
23
|
-
} = host,
|
|
24
|
-
{ onChange, onFocus, onInput } = useInput(host),
|
|
25
|
-
onBeforeInput = useAllowedPattern(allowedPattern);
|
|
26
|
-
return render(html`<input id="input" part="input"
|
|
27
|
-
type=${ type } pattern=${ ifDefined(pattern) }
|
|
28
|
-
autocomplete=${ ifDefined(autocomplete) } placeholder=${ placeholder || ' ' }
|
|
29
|
-
?readonly=${ readonly } ?aria-disabled=${ disabled } ?disabled=${ disabled }
|
|
30
|
-
.value=${ live(value ?? '') } maxlength=${ifDefined(maxlength)}
|
|
31
|
-
@beforeinput=${ onBeforeInput } @input=${ onInput }
|
|
32
|
-
@change=${ onChange } @focus=${ onFocus } @blur=${ onFocus }
|
|
33
|
-
min=${ ifDefined(min) } max=${ ifDefined(max) } step=${ifDefined(step)} >`
|
|
34
|
-
, host);
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
observedAttributes = [
|
|
38
|
-
'type',
|
|
39
|
-
'pattern',
|
|
40
|
-
'allowed-pattern',
|
|
41
|
-
'min',
|
|
42
|
-
'max',
|
|
43
|
-
'step',
|
|
44
|
-
...attributes
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
customElements.define('cosmoz-input', component(Input, { observedAttributes }));
|
package/cosmoz-textarea.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { html } from 'lit-html'; // eslint-disable-line object-curly-newline
|
|
2
|
-
import { live } from 'lit-html/directives/live';
|
|
3
|
-
import { ifDefined } from 'lit-html/directives/if-defined';
|
|
4
|
-
|
|
5
|
-
import { component } from 'haunted';
|
|
6
|
-
import { useInput, useAutosize } from './use-input';
|
|
7
|
-
import { render, attributes } from './render';
|
|
8
|
-
|
|
9
|
-
export const Textarea = host => {
|
|
10
|
-
const {
|
|
11
|
-
autocomplete,
|
|
12
|
-
value,
|
|
13
|
-
placeholder,
|
|
14
|
-
readonly,
|
|
15
|
-
disabled,
|
|
16
|
-
rows,
|
|
17
|
-
cols,
|
|
18
|
-
maxlength
|
|
19
|
-
} = host,
|
|
20
|
-
{ onChange, onFocus, onInput } = useInput(host);
|
|
21
|
-
|
|
22
|
-
useAutosize(host);
|
|
23
|
-
|
|
24
|
-
return render(html`
|
|
25
|
-
<textarea id="input" part="input" style="resize: none"
|
|
26
|
-
autocomplete=${ ifDefined(autocomplete) } placeholder=${ placeholder || ' ' } rows=${ rows ?? 1 } cols=${ ifDefined(cols) }
|
|
27
|
-
?readonly=${ readonly } ?aria-disabled=${ disabled } ?disabled=${ disabled }
|
|
28
|
-
.value=${ live(value ?? '') } maxlength=${ifDefined(maxlength)} @input=${ onInput }
|
|
29
|
-
@change=${ onChange } @focus=${ onFocus } @blur=${ onFocus }>`
|
|
30
|
-
, host);
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
observedAttributes = [
|
|
34
|
-
'rows',
|
|
35
|
-
...attributes
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
customElements.define('cosmoz-textarea', component(Textarea, { observedAttributes }));
|
package/es-dev-server.config.js
DELETED
package/render.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { html, nothing } from 'lit-html';
|
|
2
|
-
import { styles } from './styles';
|
|
3
|
-
|
|
4
|
-
export const render = (control, { label, invalid, errorMessage }) => html`
|
|
5
|
-
<style>
|
|
6
|
-
${styles}
|
|
7
|
-
</style>
|
|
8
|
-
<div class="float" part="float"> </div>
|
|
9
|
-
<div class="wrap" part="wrap">
|
|
10
|
-
<slot name="prefix"></slot>
|
|
11
|
-
<div class="control" part="control">
|
|
12
|
-
${control}
|
|
13
|
-
${label
|
|
14
|
-
? html`<label for="input" part="label">${label}</label>`
|
|
15
|
-
: nothing}
|
|
16
|
-
</div>
|
|
17
|
-
<slot name="suffix"></slot>
|
|
18
|
-
</div>
|
|
19
|
-
<div class="line" part="line"></div>
|
|
20
|
-
${invalid && errorMessage
|
|
21
|
-
? html`<div class="error" part="error">${errorMessage}</div>`
|
|
22
|
-
: nothing}
|
|
23
|
-
`,
|
|
24
|
-
attributes = [
|
|
25
|
-
'autocomplete',
|
|
26
|
-
'readonly',
|
|
27
|
-
'disabled',
|
|
28
|
-
'maxlength',
|
|
29
|
-
'invalid',
|
|
30
|
-
'no-label-float',
|
|
31
|
-
'always-float-label',
|
|
32
|
-
];
|
package/styles.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { tagged as css } from '@neovici/cosmoz-utils';
|
|
2
|
-
export const styles = css`
|
|
3
|
-
:host {
|
|
4
|
-
--font-family: var(
|
|
5
|
-
--cosmoz-input-font-family,
|
|
6
|
-
var(--paper-font-subhead_-_font-family, "Roboto", "Noto", sans-serif)
|
|
7
|
-
);
|
|
8
|
-
--font-size: var(
|
|
9
|
-
--cosmoz-input-font-size,
|
|
10
|
-
var(--paper-font-subhead_-_font-size, 16px)
|
|
11
|
-
);
|
|
12
|
-
--line-height: var(
|
|
13
|
-
--cosmoz-input-line-height,
|
|
14
|
-
var(--paper-font-subhead_-_line-height, 24px)
|
|
15
|
-
);
|
|
16
|
-
--label-scale: var(--cosmoz-input-label-scale, 0.75);
|
|
17
|
-
--disabled-opacity: var(
|
|
18
|
-
--cosmoz-input-disabled-opacity,
|
|
19
|
-
var(--paper-input-container-disabled_-_opacity, 0.33)
|
|
20
|
-
);
|
|
21
|
-
--disabled-line-opacity: var(
|
|
22
|
-
--cosmoz-input-disabled-line-opacity,
|
|
23
|
-
var(--paper-input-container-underline-disabled_-_opacity, 1)
|
|
24
|
-
);
|
|
25
|
-
--invalid-color: var(
|
|
26
|
-
--cosmoz-input-invalid-color,
|
|
27
|
-
var(--paper-input-container-invalid-color, var(--error-color, #fc5c5b))
|
|
28
|
-
);
|
|
29
|
-
--bg: var(--cosmoz-input-background);
|
|
30
|
-
--focused-bg: var(--cosmoz-input-focused-background, var(--bg));
|
|
31
|
-
--color: var(--cosmoz-input-color, var(--secondary-text-color, #737373));
|
|
32
|
-
--focused-color: var(
|
|
33
|
-
--cosmoz-input-focused-color,
|
|
34
|
-
var(--primary-color, #3f51b5)
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
display: block;
|
|
38
|
-
padding: var(--cosmoz-input-padding, 8px 0);
|
|
39
|
-
padding-top: var(--paper-input-container_-_padding-top, 8px);
|
|
40
|
-
padding-bottom: var(--paper-input-container_-_padding-bottom, 8px);
|
|
41
|
-
position: relative;
|
|
42
|
-
|
|
43
|
-
font-family: var(--font-family);
|
|
44
|
-
font-size: var(--font-size);
|
|
45
|
-
line-height: var(--line-height);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
:host([disabled]) {
|
|
49
|
-
opacity: var(--disabled-opacity);
|
|
50
|
-
pointer-events: none;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.float {
|
|
54
|
-
line-height: calc(var(--line-height) * var(--label-scale));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.wrap {
|
|
58
|
-
display: flex;
|
|
59
|
-
align-items: center;
|
|
60
|
-
position: relative;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.control {
|
|
64
|
-
flex: 1;
|
|
65
|
-
position: relative;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
#input {
|
|
69
|
-
padding: 0;
|
|
70
|
-
margin: 0;
|
|
71
|
-
outline: none;
|
|
72
|
-
border: none;
|
|
73
|
-
width: 100%;
|
|
74
|
-
max-width: 100%;
|
|
75
|
-
display: block;
|
|
76
|
-
background: var(--bg);
|
|
77
|
-
line-height: inherit;
|
|
78
|
-
font-size: inherit;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
:host(:focus-within) #input {
|
|
82
|
-
background: var(--focused-bg);
|
|
83
|
-
}
|
|
84
|
-
label {
|
|
85
|
-
position: absolute;
|
|
86
|
-
top: 0;
|
|
87
|
-
left: 0;
|
|
88
|
-
width: 100%;
|
|
89
|
-
transition: transform 0.25s, width 0.25s;
|
|
90
|
-
transform-origin: left top;
|
|
91
|
-
color: var(--color);
|
|
92
|
-
white-space: nowrap;
|
|
93
|
-
overflow: hidden;
|
|
94
|
-
text-overflow: ellipsis;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
:host([always-float-label]) label,
|
|
98
|
-
#input:not(:placeholder-shown) + label {
|
|
99
|
-
transform: translateY(calc(var(--label-scale) * -100%))
|
|
100
|
-
scale(var(--label-scale));
|
|
101
|
-
}
|
|
102
|
-
#input:not(:placeholder-shown):focus + label {
|
|
103
|
-
color: var(--focused-color);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.line {
|
|
107
|
-
padding-top: 1px;
|
|
108
|
-
border-bottom: 1px solid var(--color);
|
|
109
|
-
position: relative;
|
|
110
|
-
}
|
|
111
|
-
.line::before {
|
|
112
|
-
content: "";
|
|
113
|
-
position: absolute;
|
|
114
|
-
display: block;
|
|
115
|
-
border-bottom: 2px solid transparent;
|
|
116
|
-
border-bottom-color: inherit;
|
|
117
|
-
left: 0;
|
|
118
|
-
right: 0;
|
|
119
|
-
top: 0;
|
|
120
|
-
transform: scale3d(0, 1, 1);
|
|
121
|
-
transform-origin: center center;
|
|
122
|
-
z-index: 1;
|
|
123
|
-
}
|
|
124
|
-
:host(:focus-within) .line::before {
|
|
125
|
-
transform: none;
|
|
126
|
-
transition: 0.25s transform ease;
|
|
127
|
-
}
|
|
128
|
-
:host(:focus-within) .line {
|
|
129
|
-
border-bottom-color: var(--focused-color);
|
|
130
|
-
}
|
|
131
|
-
:host([disabled]) .line {
|
|
132
|
-
border-bottom-style: dashed;
|
|
133
|
-
opacity: var(--disabled-line-opacity);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
:host([no-label-float]) .float,
|
|
137
|
-
:host([no-label-float]) #input:not(:placeholder-shown) + label {
|
|
138
|
-
display: none;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.error {
|
|
142
|
-
font-size: 12px;
|
|
143
|
-
line-height: 20px;
|
|
144
|
-
overflow: hidden;
|
|
145
|
-
text-overflow: clip;
|
|
146
|
-
position: absolute;
|
|
147
|
-
max-width: 100%;
|
|
148
|
-
}
|
|
149
|
-
:host([invalid]) label,
|
|
150
|
-
.error {
|
|
151
|
-
color: var(--invalid-color);
|
|
152
|
-
}
|
|
153
|
-
:host([invalid]) .line {
|
|
154
|
-
border-bottom-color: var(--invalid-color);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
#input::-webkit-inner-spin-button {
|
|
158
|
-
z-index: 1;
|
|
159
|
-
}
|
|
160
|
-
`;
|
package/use-input.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo } from 'haunted';
|
|
2
|
-
import { useImperativeApi } from '@neovici/cosmoz-utils/lib/hooks/use-imperative-api';
|
|
3
|
-
import { notifyProperty } from '@neovici/cosmoz-utils/lib/hooks/use-notify-property';
|
|
4
|
-
|
|
5
|
-
export const useInput = host => {
|
|
6
|
-
const root = host.shadowRoot,
|
|
7
|
-
onChange = useCallback(e => host.dispatchEvent(new Event(e.type, { bubbles: e.bubbles })), []),
|
|
8
|
-
onInput = useCallback(e => notifyProperty(host, 'value', e.target.value), []),
|
|
9
|
-
onFocus = useCallback(e => notifyProperty(host, 'focused', e.type === 'focus'), []),
|
|
10
|
-
focus = useCallback(() => root.querySelector('#input')?.focus(), []),
|
|
11
|
-
validate = useCallback(() => {
|
|
12
|
-
const valid = root.querySelector('#input')?.checkValidity();
|
|
13
|
-
host.toggleAttribute('invalid', !valid);
|
|
14
|
-
return valid;
|
|
15
|
-
}, []);
|
|
16
|
-
|
|
17
|
-
useImperativeApi({ focus, validate }, [focus, validate]);
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
const onMouseDown = e => {
|
|
21
|
-
if (e.defaultPrevented || e.target.matches('input, textarea, label')) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
e.preventDefault(); // don't blur
|
|
25
|
-
if (!host.matches(':focus-within')) { // if input not focused
|
|
26
|
-
focus(); // focus input
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
root.addEventListener('mousedown', onMouseDown);
|
|
31
|
-
return () => root.removeEventListener('mousedown', onMouseDown);
|
|
32
|
-
}, [focus]);
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
onChange,
|
|
36
|
-
onFocus,
|
|
37
|
-
onInput
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
useAllowedPattern = allowedPattern => useMemo(() => {
|
|
41
|
-
if (allowedPattern == null) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const regexp = new RegExp(allowedPattern, 'u');
|
|
45
|
-
return e => {
|
|
46
|
-
if (!e.defaultPrevent && e.data && !regexp.test(e.data)) {
|
|
47
|
-
e.preventDefault();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
}, [allowedPattern]),
|
|
52
|
-
autosize = input => {
|
|
53
|
-
input.style.height = '';
|
|
54
|
-
input.style.height = `${ input.scrollHeight }px`;
|
|
55
|
-
},
|
|
56
|
-
limit = (input, maxRows) => {
|
|
57
|
-
if (maxRows > 0) {
|
|
58
|
-
const rows = input.getAttribute('rows'),
|
|
59
|
-
height = input.style.height;
|
|
60
|
-
input.style.height = '';
|
|
61
|
-
input.setAttribute('rows', maxRows);
|
|
62
|
-
input.style.maxHeight = input.getBoundingClientRect().height + 'px';
|
|
63
|
-
input.style.height = height;
|
|
64
|
-
input.setAttribute('rows', rows);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
useAutosize = host => {
|
|
68
|
-
const { value, maxRows } = host,
|
|
69
|
-
input = useMemo(() => () => host.shadowRoot.querySelector('#input'), []);
|
|
70
|
-
useEffect(() => limit(input(), maxRows), [maxRows, input]);
|
|
71
|
-
useEffect(() => autosize(input()), [input, value]);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
const el = input(),
|
|
74
|
-
observer = new ResizeObserver(() => requestAnimationFrame(() => autosize(el)));
|
|
75
|
-
observer.observe(el);
|
|
76
|
-
return () => observer.unobserve(el);
|
|
77
|
-
}, [input]);
|
|
78
|
-
|
|
79
|
-
};
|