Skip to content

Commit 05a1e6b

Browse files
committed
Start wiring up number editing.
1 parent 73daee9 commit 05a1e6b

File tree

11 files changed

+223
-3
lines changed

11 files changed

+223
-3
lines changed

src/pg/inputNumber/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# `<pg-input-number>`
2+
3+
The `pg-input-number` component creates an input that accepts number input.
4+
5+
```typescript
6+
import '@pictogrammers/components/pgInputNumber';
7+
import PgInputNumber from '@pictogrammers/components/pgInputText';
8+
```
9+
10+
```html
11+
<pg-input-number value="50"></pg-input-number>
12+
```
13+
14+
## Attributes
15+
16+
| Attributes | Tested | Description |
17+
| ----------- | -------- | ----------- |
18+
| name | | Unique name in `pg-form` |
19+
| value | | Field value |
20+
| placeholder | | Placeholder text |
21+
22+
## Events
23+
24+
| Events | Tested | Description |
25+
| ---------- | -------- | ----------- |
26+
| change | | `{ detail: { value }` |
27+
| input | | `{ detail: { value }` |
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<div class="example">
2+
<pg-input-number part="input" value="42"></pg-input-number>
3+
<div>
4+
<code>onchange: <span part="value1"></span></code>
5+
</div>
6+
<div>
7+
<code>oninput: <span part="value2"></span></code>
8+
</div>
9+
</div>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Component, Part, Prop } from '@pictogrammers/element';
2+
import PgInputNumber from '../../inputNumber';
3+
4+
import template from './basic.html';
5+
6+
@Component({
7+
selector: 'x-pg-input-number-basic',
8+
template
9+
})
10+
export default class XPgInputNumberBasic extends HTMLElement {
11+
12+
@Part() $input: PgInputNumber;
13+
@Part() $value1: HTMLSpanElement;
14+
@Part() $value2: HTMLSpanElement;
15+
16+
connectedCallback() {
17+
this.$input.addEventListener('change', this.#handleChange.bind(this));
18+
this.$input.addEventListener('input', this.#handleInput.bind(this));
19+
}
20+
21+
#handleChange(e: CustomEvent) {
22+
const { value } = e.detail;
23+
this.$value1.textContent = value;
24+
}
25+
26+
#handleInput(e: CustomEvent) {
27+
const { value } = e.detail;
28+
this.$value2.textContent = value;
29+
}
30+
}

src/pg/inputNumber/inputNumber.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
:host {
2+
display: block;
3+
font-family: var(--pg-font-family);
4+
}
5+
6+
[part=input] {
7+
border: 1px solid var(--pg-input-text-border-color, #453C4F);
8+
border-radius: 0.125rem;
9+
padding: var(--pg-input-text-padding, calc(0.5rem - 1px) 0.75rem);
10+
font-family: var(--pg-font-family);
11+
font-size: 1rem;
12+
outline: none;
13+
field-sizing: content;
14+
min-width: calc(100% - 0.5rem - 2px);
15+
max-width: calc(var(--pg-input-text-max-width, 100%) - 0.5rem - 2px);
16+
background-color: transparent;
17+
}
18+
19+
[part=input]:read-only {
20+
border-color: transparent;
21+
}
22+
23+
[part=input]:active {
24+
box-shadow: 0 0 0 3px var(--pg-input-text-active-glow, rgb(79, 143, 249, 0.6));
25+
}
26+
[part=input]:focus {
27+
box-shadow: 0 0 0 3px var(--pg-input-text-focus-glow, rgb(79, 143, 249, 0.5));
28+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<input part="input" type="number" />
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { selectComponent, getProps } from '@pictogrammers/element';
2+
3+
import './inputNumber';
4+
import PgInputText from './inputNumber';
5+
6+
const PG_INPUT_TEXT = 'pg-input-text';
7+
8+
describe('pg-input-text', () => {
9+
10+
beforeEach(() => {
11+
var c = document.createElement(PG_INPUT_TEXT);
12+
document.body.appendChild(c);
13+
});
14+
15+
afterEach(() => {
16+
while (document.body.firstChild) {
17+
document.body.removeChild(document.body.firstChild);
18+
}
19+
});
20+
21+
it('should be registered', () => {
22+
expect(customElements.get(PG_INPUT_TEXT)).toBeDefined();
23+
});
24+
25+
it('should only expose known props', () => {
26+
const props = getProps(PG_INPUT_TEXT);
27+
expect(props.length).toBe(3);
28+
expect(props).toContain('name');
29+
expect(props).toContain('value');
30+
expect(props).toContain('placeholder');
31+
});
32+
33+
it('should default value to empty', () => {
34+
const component = selectComponent<PgInputText>(PG_INPUT_TEXT);
35+
const { $input } = component;
36+
expect($input.value).toEqual('');
37+
});
38+
39+
it('should set value to "Hello World!"', () => {
40+
const component = selectComponent<PgInputText>(PG_INPUT_TEXT);
41+
component.value = 'Hello World!';
42+
const { $input } = component;
43+
expect($input.value).toEqual('Hello World!');
44+
});
45+
46+
it('should default placeholder to empty', () => {
47+
const component = selectComponent<PgInputText>(PG_INPUT_TEXT);
48+
const { $input } = component;
49+
expect($input.placeholder).toEqual('');
50+
});
51+
52+
it('should set placeholder to "Hello World!"', () => {
53+
const component = selectComponent<PgInputText>(PG_INPUT_TEXT);
54+
component.placeholder = 'Hello World!';
55+
const { $input } = component;
56+
expect($input.placeholder).toEqual('Hello World!');
57+
});
58+
59+
});

src/pg/inputNumber/inputNumber.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Component, Prop, Part } from '@pictogrammers/element';
2+
3+
import template from './inputNumber.html';
4+
import style from './inputNumber.css';
5+
6+
@Component({
7+
selector: 'pg-input-number',
8+
style,
9+
template,
10+
})
11+
export default class PgInputNumber extends HTMLElement {
12+
@Prop() name: string = '';
13+
@Prop() value: string = '';
14+
@Prop() placeholder: string = '';
15+
@Prop() readOnly: boolean = false;
16+
17+
@Part() $input: HTMLInputElement;
18+
19+
connectedCallback() {
20+
this.$input.addEventListener('input', this.handleInput.bind(this));
21+
this.$input.addEventListener('change', this.handleChange.bind(this));
22+
}
23+
24+
skipValue = false;
25+
26+
render(changes) {
27+
if (changes.value && !this.skipValue) {
28+
this.$input.value = this.value;
29+
}
30+
if (changes.placeholder) {
31+
this.$input.placeholder = this.placeholder;
32+
}
33+
if (changes.readOnly) {
34+
this.$input.readOnly = this.readOnly;
35+
}
36+
this.skipValue = false;
37+
}
38+
39+
handleInput(e) {
40+
e.stopPropagation();
41+
this.skipValue = true;
42+
this.value = e.target.value;
43+
this.dispatchEvent(
44+
new CustomEvent('input', {
45+
detail: {
46+
value: e.target.value,
47+
name: e.name
48+
}
49+
})
50+
);
51+
}
52+
53+
handleChange(e) {
54+
this.dispatchEvent(
55+
new CustomEvent('change', {
56+
detail: {
57+
value: e.target.value,
58+
name: e.name
59+
}
60+
})
61+
);
62+
}
63+
}

src/pg/inputText/inputText.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ export default class PgInputText extends HTMLElement {
6060
})
6161
);
6262
}
63-
}
63+
}

src/pg/jsonNumber/jsonNumber.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div part="key"></div>
22
<div part="seperator">:&nbsp;</div>
33
<div part="container">
4-
<div part="value"></div>
4+
<pg-input-number part="value"></pg-input-number>
55
</div>

src/pg/jsonString/jsonString.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44

55
[part=value] {
66
user-select: text;
7+
--pg-input-text-padding: 0 0.25rem;
8+
display: inline-flex;
9+
vertical-align: middle;
710
}

0 commit comments

Comments
 (0)