@neovici/cosmoz-input 3.2.0 → 3.4.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/dist/cosmoz-input.js +30 -24
- package/dist/cosmoz-textarea.js +3 -2
- package/dist/render.d.ts +1 -1
- package/dist/styles.js +26 -0
- package/dist/use-allowed-pattern.d.ts +1 -0
- package/dist/use-allowed-pattern.js +12 -0
- package/dist/use-auto-height.d.ts +2 -0
- package/dist/use-auto-height.js +25 -0
- package/dist/use-input.d.ts +1 -1
- package/dist/use-input.js +1 -32
- package/package.json +1 -1
package/dist/cosmoz-input.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { html } from 'lit-html';
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
2
|
import { live } from 'lit-html/directives/live.js';
|
|
3
3
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
4
4
|
import { component } from 'haunted';
|
|
5
|
-
import { useInput
|
|
5
|
+
import { useInput } from './use-input';
|
|
6
|
+
import { useAllowedPattern } from './use-allowed-pattern';
|
|
6
7
|
import { render, attributes } from './render';
|
|
7
8
|
const observedAttributes = [
|
|
8
9
|
'type',
|
|
@@ -11,30 +12,35 @@ const observedAttributes = [
|
|
|
11
12
|
'min',
|
|
12
13
|
'max',
|
|
13
14
|
'step',
|
|
15
|
+
'autosize',
|
|
14
16
|
...attributes,
|
|
15
17
|
];
|
|
16
18
|
export const Input = (host) => {
|
|
17
|
-
const { type = 'text', pattern, allowedPattern, autocomplete, value, placeholder, readonly, disabled, min, max, step, maxlength, } = host, { onChange, onFocus, onInput } = useInput(host)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
const { type = 'text', pattern, allowedPattern, autocomplete, value, placeholder, readonly, disabled, min, max, step, maxlength, } = host, { onChange, onFocus, onInput } = useInput(host);
|
|
20
|
+
const onBeforeInput = useAllowedPattern(allowedPattern);
|
|
21
|
+
return render(html `
|
|
22
|
+
<input
|
|
23
|
+
style="--chars: ${value?.toString()?.length ?? 0}ch"
|
|
24
|
+
id="input"
|
|
25
|
+
part="input"
|
|
26
|
+
type=${type}
|
|
27
|
+
pattern=${ifDefined(pattern)}
|
|
28
|
+
autocomplete=${ifDefined(autocomplete)}
|
|
29
|
+
placeholder=${placeholder || ' '}
|
|
30
|
+
?readonly=${readonly}
|
|
31
|
+
?aria-disabled=${disabled}
|
|
32
|
+
?disabled=${disabled}
|
|
33
|
+
.value=${live(value ?? '')}
|
|
34
|
+
maxlength=${ifDefined(maxlength)}
|
|
35
|
+
@beforeinput=${onBeforeInput}
|
|
36
|
+
@input=${onInput}
|
|
37
|
+
@change=${onChange}
|
|
38
|
+
@focus=${onFocus}
|
|
39
|
+
@blur=${onFocus}
|
|
40
|
+
min=${ifDefined(min)}
|
|
41
|
+
max=${ifDefined(max)}
|
|
42
|
+
step=${ifDefined(step)}
|
|
43
|
+
/>
|
|
44
|
+
`, host);
|
|
39
45
|
};
|
|
40
46
|
customElements.define('cosmoz-input', component(Input, { observedAttributes }));
|
package/dist/cosmoz-textarea.js
CHANGED
|
@@ -2,12 +2,13 @@ import { html } from 'lit-html'; // eslint-disable-line object-curly-newline
|
|
|
2
2
|
import { live } from 'lit-html/directives/live.js';
|
|
3
3
|
import { ifDefined } from 'lit-html/directives/if-defined.js';
|
|
4
4
|
import { component } from 'haunted';
|
|
5
|
-
import { useInput
|
|
5
|
+
import { useInput } from './use-input';
|
|
6
|
+
import { useAutoHeight } from './use-auto-height';
|
|
6
7
|
import { render, attributes } from './render';
|
|
7
8
|
const observedAttributes = ['rows', ...attributes];
|
|
8
9
|
export const Textarea = (host) => {
|
|
9
10
|
const { autocomplete, value, placeholder, readonly, disabled, rows, cols, maxlength, } = host, { onChange, onFocus, onInput } = useInput(host);
|
|
10
|
-
|
|
11
|
+
useAutoHeight(host);
|
|
11
12
|
return render(html `
|
|
12
13
|
<textarea id="input" part="input" style="resize: none"
|
|
13
14
|
autocomplete=${ifDefined(autocomplete)}
|
package/dist/render.d.ts
CHANGED
package/dist/styles.js
CHANGED
|
@@ -157,4 +157,30 @@ export const styles = css `
|
|
|
157
157
|
#input::-webkit-inner-spin-button {
|
|
158
158
|
z-index: 1;
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
:host([no-spinner]) #input::-webkit-inner-spin-button {
|
|
162
|
+
display: none;
|
|
163
|
+
}
|
|
164
|
+
:host([no-spinner]) #input {
|
|
165
|
+
-moz-appearence: textfield;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
:host([autosize]) {
|
|
169
|
+
width: max-content;
|
|
170
|
+
}
|
|
171
|
+
:host([autosize]) #input {
|
|
172
|
+
min-width: 2ch;
|
|
173
|
+
width: var(--chars);
|
|
174
|
+
}
|
|
175
|
+
:host([autosize][type='number']) #input {
|
|
176
|
+
--width: calc(var(--chars) + 0.25em);
|
|
177
|
+
}
|
|
178
|
+
:host([autosize][type='number']:not([no-spinner])) #input {
|
|
179
|
+
width: calc(var(--width) + 15px);
|
|
180
|
+
min-width: calc(2ch + 0.25em + 15px);
|
|
181
|
+
}
|
|
182
|
+
:host([autosize][type='number'][no-spinner]) #input {
|
|
183
|
+
width: var(--width);
|
|
184
|
+
min-width: calc(2ch + 0.25em);
|
|
185
|
+
}
|
|
160
186
|
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useAllowedPattern: (allowedPattern: string | RegExp) => (<T extends InputEvent>(e: T) => void) | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useMemo } from 'haunted';
|
|
2
|
+
export const useAllowedPattern = (allowedPattern) => useMemo(() => {
|
|
3
|
+
if (allowedPattern == null) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
const regexp = new RegExp(allowedPattern, 'u');
|
|
7
|
+
return (e) => {
|
|
8
|
+
if (!e.defaultPrevented && e.data && !regexp.test(e.data)) {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}, [allowedPattern]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useEffect, useMemo } from 'haunted';
|
|
2
|
+
const autoheight = (input) => {
|
|
3
|
+
input.style.height = '';
|
|
4
|
+
input.style.height = `${input.scrollHeight}px`;
|
|
5
|
+
};
|
|
6
|
+
const limit = (input, maxRows = 0) => {
|
|
7
|
+
if (maxRows > 0) {
|
|
8
|
+
const rows = input.getAttribute('rows') ?? '', height = input.style.height;
|
|
9
|
+
input.style.height = '';
|
|
10
|
+
input.setAttribute('rows', maxRows);
|
|
11
|
+
input.style.maxHeight = input.getBoundingClientRect().height + 'px';
|
|
12
|
+
input.style.height = height;
|
|
13
|
+
input.setAttribute('rows', rows);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
export const useAutoHeight = (host) => {
|
|
17
|
+
const { value, maxRows } = host, input = useMemo(() => () => host.shadowRoot.querySelector('#input'), []);
|
|
18
|
+
useEffect(() => limit(input(), maxRows), [maxRows, input]);
|
|
19
|
+
useEffect(() => autoheight(input()), [input, value]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const el = input(), observer = new ResizeObserver(() => requestAnimationFrame(() => autoheight(el)));
|
|
22
|
+
observer.observe(el);
|
|
23
|
+
return () => observer.unobserve(el);
|
|
24
|
+
}, [input]);
|
|
25
|
+
};
|
package/dist/use-input.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export declare const useInput: <T extends BaseInput>(host: T) => {
|
|
|
8
8
|
onChange: (e: Event) => boolean;
|
|
9
9
|
onFocus: (e: FocusEvent) => void;
|
|
10
10
|
onInput: (e: InputEvent) => void;
|
|
11
|
-
}
|
|
11
|
+
};
|
package/dist/use-input.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useEffect
|
|
1
|
+
import { useCallback, useEffect } from 'haunted';
|
|
2
2
|
import { useImperativeApi } from '@neovici/cosmoz-utils/hooks/use-imperative-api';
|
|
3
3
|
import { notifyProperty } from '@neovici/cosmoz-utils/hooks/use-notify-property';
|
|
4
4
|
// TODO: use useRef instead of callback with querySelector
|
|
@@ -30,35 +30,4 @@ export const useInput = (host) => {
|
|
|
30
30
|
onFocus,
|
|
31
31
|
onInput,
|
|
32
32
|
};
|
|
33
|
-
}, useAllowedPattern = (allowedPattern) => useMemo(() => {
|
|
34
|
-
if (allowedPattern == null) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const regexp = new RegExp(allowedPattern, 'u');
|
|
38
|
-
return (e) => {
|
|
39
|
-
if (!e.defaultPrevented && e.data && !regexp.test(e.data)) {
|
|
40
|
-
e.preventDefault();
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
}, [allowedPattern]), autosize = (input) => {
|
|
44
|
-
input.style.height = '';
|
|
45
|
-
input.style.height = `${input.scrollHeight}px`;
|
|
46
|
-
}, limit = (input, maxRows = 0) => {
|
|
47
|
-
if (maxRows > 0) {
|
|
48
|
-
const rows = input.getAttribute('rows') ?? '', height = input.style.height;
|
|
49
|
-
input.style.height = '';
|
|
50
|
-
input.setAttribute('rows', maxRows);
|
|
51
|
-
input.style.maxHeight = input.getBoundingClientRect().height + 'px';
|
|
52
|
-
input.style.height = height;
|
|
53
|
-
input.setAttribute('rows', rows);
|
|
54
|
-
}
|
|
55
|
-
}, useAutosize = (host) => {
|
|
56
|
-
const { value, maxRows } = host, input = useMemo(() => () => host.shadowRoot.querySelector('#input'), []);
|
|
57
|
-
useEffect(() => limit(input(), maxRows), [maxRows, input]);
|
|
58
|
-
useEffect(() => autosize(input()), [input, value]);
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
const el = input(), observer = new ResizeObserver(() => requestAnimationFrame(() => autosize(el)));
|
|
61
|
-
observer.observe(el);
|
|
62
|
-
return () => observer.unobserve(el);
|
|
63
|
-
}, [input]);
|
|
64
33
|
};
|