@neovici/cosmoz-input 1.6.2 → 2.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/cosmoz-input.js CHANGED
@@ -1,12 +1,12 @@
1
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';
2
+ import { live } from 'lit-html/directives/live.js';
3
+ import { ifDefined } from 'lit-html/directives/if-defined.js';
4
4
 
5
5
  import { component } from 'haunted';
6
6
  import { useInput, useAllowedPattern } from './use-input';
7
7
  import { render, attributes } from './render';
8
8
 
9
- export const Input = host => {
9
+ export const Input = (host) => {
10
10
  const {
11
11
  type = 'text',
12
12
  pattern,
@@ -18,21 +18,36 @@ export const Input = host => {
18
18
  disabled,
19
19
  min,
20
20
  max,
21
- step
21
+ step,
22
+ maxlength,
22
23
  } = host,
23
24
  { onChange, onFocus, onInput } = useInput(host),
24
25
  onBeforeInput = useAllowedPattern(allowedPattern);
25
- return render(html`<input id="input" part="input"
26
- type=${ type } pattern=${ ifDefined(pattern) }
27
- autocomplete=${ ifDefined(autocomplete) } placeholder=${ placeholder || ' ' }
28
- ?readonly=${ readonly } ?aria-disabled=${ disabled } ?disabled=${ disabled }
29
- .value=${ live(value ?? '') }
30
- @beforeinput=${ onBeforeInput } @input=${ onInput }
31
- @change=${ onChange } @focus=${ onFocus } @blur=${ onFocus }
32
- min=${ ifDefined(min) } max=${ ifDefined(max) } step=${ifDefined(step)} >`
33
- , host);
26
+ return render(
27
+ html`<input
28
+ id="input"
29
+ part="input"
30
+ type=${type}
31
+ pattern=${ifDefined(pattern)}
32
+ autocomplete=${ifDefined(autocomplete)}
33
+ placeholder=${placeholder || ' '}
34
+ ?readonly=${readonly}
35
+ ?aria-disabled=${disabled}
36
+ ?disabled=${disabled}
37
+ .value=${live(value ?? '')}
38
+ maxlength=${ifDefined(maxlength)}
39
+ @beforeinput=${onBeforeInput}
40
+ @input=${onInput}
41
+ @change=${onChange}
42
+ @focus=${onFocus}
43
+ @blur=${onFocus}
44
+ min=${ifDefined(min)}
45
+ max=${ifDefined(max)}
46
+ step=${ifDefined(step)}
47
+ />`,
48
+ host
49
+ );
34
50
  },
35
-
36
51
  observedAttributes = [
37
52
  'type',
38
53
  'pattern',
@@ -40,7 +55,7 @@ export const Input = host => {
40
55
  'min',
41
56
  'max',
42
57
  'step',
43
- ...attributes
58
+ ...attributes,
44
59
  ];
45
60
 
46
61
  customElements.define('cosmoz-input', component(Input, { observedAttributes }));
@@ -1,12 +1,12 @@
1
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';
2
+ import { live } from 'lit-html/directives/live.js';
3
+ import { ifDefined } from 'lit-html/directives/if-defined.js';
4
4
 
5
5
  import { component } from 'haunted';
6
6
  import { useInput, useAutosize } from './use-input';
7
7
  import { render, attributes } from './render';
8
8
 
9
- export const Textarea = host => {
9
+ export const Textarea = (host) => {
10
10
  const {
11
11
  autocomplete,
12
12
  value,
@@ -14,24 +14,28 @@ export const Textarea = host => {
14
14
  readonly,
15
15
  disabled,
16
16
  rows,
17
- cols
17
+ cols,
18
+ maxlength,
18
19
  } = host,
19
20
  { onChange, onFocus, onInput } = useInput(host);
20
21
 
21
22
  useAutosize(host);
22
23
 
23
- return render(html`
24
+ return render(
25
+ html`
24
26
  <textarea id="input" part="input" style="resize: none"
25
- autocomplete=${ ifDefined(autocomplete) } placeholder=${ placeholder || ' ' } rows=${ rows ?? 1 } cols=${ ifDefined(cols) }
26
- ?readonly=${ readonly } ?aria-disabled=${ disabled } ?disabled=${ disabled }
27
- .value=${ live(value ?? '') } @input=${ onInput }
28
- @change=${ onChange } @focus=${ onFocus } @blur=${ onFocus }>`
29
- , host);
27
+ autocomplete=${ifDefined(autocomplete)} placeholder=${
28
+ placeholder || ' '
29
+ } rows=${rows ?? 1} cols=${ifDefined(cols)}
30
+ ?readonly=${readonly} ?aria-disabled=${disabled} ?disabled=${disabled}
31
+ .value=${live(value ?? '')} maxlength=${ifDefined(maxlength)} @input=${onInput}
32
+ @change=${onChange} @focus=${onFocus} @blur=${onFocus}>`,
33
+ host
34
+ );
30
35
  },
36
+ observedAttributes = ['rows', ...attributes];
31
37
 
32
- observedAttributes = [
33
- 'rows',
34
- ...attributes
35
- ];
36
-
37
- customElements.define('cosmoz-textarea', component(Textarea, { observedAttributes }));
38
+ customElements.define(
39
+ 'cosmoz-textarea',
40
+ component(Textarea, { observedAttributes })
41
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neovici/cosmoz-input",
3
- "version": "1.6.2",
3
+ "version": "2.0.0",
4
4
  "description": "A input web component",
5
5
  "keywords": [
6
6
  "lit-html",
@@ -23,11 +23,10 @@
23
23
  "scripts": {
24
24
  "lint": "eslint --cache --ext .js .",
25
25
  "lint-tsc": "tsc",
26
- "start": "npm run storybook",
26
+ "start": "wds",
27
27
  "test": "wtr --coverage",
28
28
  "test:watch": "wtr --watch",
29
29
  "prepare": "husky install",
30
- "storybook": "start-storybook --node-resolve --watch --open",
31
30
  "storybook:build": "build-storybook",
32
31
  "storybook:deploy": "storybook-to-ghpages"
33
32
  },
@@ -53,25 +52,32 @@
53
52
  "commitlint": {
54
53
  "extends": [
55
54
  "@commitlint/config-conventional"
56
- ]
55
+ ],
56
+ "rules": {
57
+ "body-max-line-length": [
58
+ 1,
59
+ "always",
60
+ 100
61
+ ]
62
+ }
57
63
  },
58
64
  "dependencies": {
59
- "@neovici/cosmoz-utils": "^3.23.0",
60
- "haunted": "^4.8.0",
61
- "lit-html": "^1.4.0"
65
+ "@neovici/cosmoz-utils": "^4.0.0",
66
+ "haunted": "^5.0.0",
67
+ "lit-html": "^2.0.0"
62
68
  },
63
69
  "devDependencies": {
64
- "@commitlint/cli": "^16.0.0",
65
- "@commitlint/config-conventional": "^16.0.0",
70
+ "@commitlint/cli": "^17.0.0",
71
+ "@commitlint/config-conventional": "^17.0.0",
66
72
  "@neovici/cfg": "^1.13.1",
67
- "@open-wc/demoing-storybook": "^2.1.0",
68
- "@open-wc/testing": "^2.5.0",
73
+ "@open-wc/testing": "^3.0.0",
69
74
  "@semantic-release/changelog": "^6.0.0",
70
75
  "@semantic-release/git": "^10.0.0",
71
76
  "@storybook/storybook-deployer": "^2.8.5",
72
- "husky": "^7.0.0",
77
+ "@web/dev-server-storybook": "^0.5.1",
78
+ "husky": "^8.0.0",
73
79
  "semantic-release": "^19.0.0",
74
- "sinon": "^13.0.0",
80
+ "sinon": "^14.0.0",
75
81
  "typescript": "^4.6.0"
76
82
  }
77
83
  }
package/render.js CHANGED
@@ -25,6 +25,7 @@ export const render = (control, { label, invalid, errorMessage }) => html`
25
25
  'autocomplete',
26
26
  'readonly',
27
27
  'disabled',
28
+ 'maxlength',
28
29
  'invalid',
29
30
  'no-label-float',
30
31
  'always-float-label',
package/styles.js CHANGED
@@ -3,7 +3,7 @@ export const styles = css`
3
3
  :host {
4
4
  --font-family: var(
5
5
  --cosmoz-input-font-family,
6
- var(--paper-font-subhead_-_font-family, "Roboto", "Noto", sans-serif)
6
+ var(--paper-font-subhead_-_font-family, 'Roboto', 'Noto', sans-serif)
7
7
  );
8
8
  --font-size: var(
9
9
  --cosmoz-input-font-size,
@@ -109,7 +109,7 @@ export const styles = css`
109
109
  position: relative;
110
110
  }
111
111
  .line::before {
112
- content: "";
112
+ content: '';
113
113
  position: absolute;
114
114
  display: block;
115
115
  border-bottom: 2px solid transparent;
package/use-input.js CHANGED
@@ -2,11 +2,20 @@ import { useCallback, useEffect, useMemo } from 'haunted';
2
2
  import { useImperativeApi } from '@neovici/cosmoz-utils/lib/hooks/use-imperative-api';
3
3
  import { notifyProperty } from '@neovici/cosmoz-utils/lib/hooks/use-notify-property';
4
4
 
5
- export const useInput = host => {
5
+ export const useInput = (host) => {
6
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'), []),
7
+ onChange = useCallback(
8
+ (e) => host.dispatchEvent(new Event(e.type, { bubbles: e.bubbles })),
9
+ []
10
+ ),
11
+ onInput = useCallback(
12
+ (e) => notifyProperty(host, 'value', e.target.value),
13
+ []
14
+ ),
15
+ onFocus = useCallback(
16
+ (e) => notifyProperty(host, 'focused', e.type === 'focus'),
17
+ []
18
+ ),
10
19
  focus = useCallback(() => root.querySelector('#input')?.focus(), []),
11
20
  validate = useCallback(() => {
12
21
  const valid = root.querySelector('#input')?.checkValidity();
@@ -17,12 +26,13 @@ export const useInput = host => {
17
26
  useImperativeApi({ focus, validate }, [focus, validate]);
18
27
 
19
28
  useEffect(() => {
20
- const onMouseDown = e => {
29
+ const onMouseDown = (e) => {
21
30
  if (e.defaultPrevented || e.target.matches('input, textarea, label')) {
22
31
  return;
23
32
  }
24
33
  e.preventDefault(); // don't blur
25
- if (!host.matches(':focus-within')) { // if input not focused
34
+ if (!host.matches(':focus-within')) {
35
+ // if input not focused
26
36
  focus(); // focus input
27
37
  }
28
38
  };
@@ -34,24 +44,24 @@ export const useInput = host => {
34
44
  return {
35
45
  onChange,
36
46
  onFocus,
37
- onInput
47
+ onInput,
38
48
  };
39
49
  },
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();
50
+ useAllowedPattern = (allowedPattern) =>
51
+ useMemo(() => {
52
+ if (allowedPattern == null) {
53
+ return;
48
54
  }
49
-
50
- };
51
- }, [allowedPattern]),
52
- autosize = input => {
55
+ const regexp = new RegExp(allowedPattern, 'u');
56
+ return (e) => {
57
+ if (!e.defaultPrevent && e.data && !regexp.test(e.data)) {
58
+ e.preventDefault();
59
+ }
60
+ };
61
+ }, [allowedPattern]),
62
+ autosize = (input) => {
53
63
  input.style.height = '';
54
- input.style.height = `${ input.scrollHeight }px`;
64
+ input.style.height = `${input.scrollHeight}px`;
55
65
  },
56
66
  limit = (input, maxRows) => {
57
67
  if (maxRows > 0) {
@@ -64,16 +74,17 @@ export const useInput = host => {
64
74
  input.setAttribute('rows', rows);
65
75
  }
66
76
  },
67
- useAutosize = host => {
77
+ useAutosize = (host) => {
68
78
  const { value, maxRows } = host,
69
79
  input = useMemo(() => () => host.shadowRoot.querySelector('#input'), []);
70
80
  useEffect(() => limit(input(), maxRows), [maxRows, input]);
71
81
  useEffect(() => autosize(input()), [input, value]);
72
82
  useEffect(() => {
73
83
  const el = input(),
74
- observer = new ResizeObserver(() => requestAnimationFrame(() => autosize(el)));
84
+ observer = new ResizeObserver(() =>
85
+ requestAnimationFrame(() => autosize(el))
86
+ );
75
87
  observer.observe(el);
76
88
  return () => observer.unobserve(el);
77
89
  }, [input]);
78
-
79
90
  };
@@ -1,8 +0,0 @@
1
- /* eslint-env node */
2
- module.exports = {
3
- appIndex: 'demo/index.html',
4
- open: true,
5
- preserveSymlinks: true,
6
- dedupe: true,
7
- nodeResolve: { mainFields: ['browser', 'jsnext', 'jsnext:main', 'module', 'main']}
8
- };