@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neovici/cosmoz-input",
3
- "version": "1.7.0",
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": "cosmoz-input.js",
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 --ext .js .",
25
- "lint-tsc": "tsc",
26
- "start": "npm run storybook",
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": "^3.23.0",
60
- "haunted": "^4.8.0",
61
- "lit-html": "^1.4.0"
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": "^16.0.0",
65
- "@commitlint/config-conventional": "^16.0.0",
75
+ "@commitlint/cli": "^17.0.0",
76
+ "@commitlint/config-conventional": "^17.0.0",
66
77
  "@neovici/cfg": "^1.13.1",
67
- "@open-wc/demoing-storybook": "^2.1.0",
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
- "husky": "^7.0.0",
82
+ "@web/dev-server-storybook": "^0.5.1",
83
+ "husky": "^8.0.0",
73
84
  "semantic-release": "^19.0.0",
74
- "sinon": "^13.0.0",
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 }));
@@ -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 }));
@@ -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
- };
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">&nbsp;</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
- };