@pictogrammers/components 0.5.14 → 0.5.17

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.
Files changed (153) hide show
  1. package/package.json +1 -1
  2. package/pg/autocompleteItem/__examples__/basic/basic.html +3 -0
  3. package/pg/autocompleteItem/autocompleteItem.css +55 -0
  4. package/pg/autocompleteItem/autocompleteItem.html +1 -0
  5. package/pg/autocompleteItem/autocompleteItem.ts +65 -0
  6. package/pg/button/button.css +5 -0
  7. package/pg/buttonMenu/buttonMenu.ts +1 -1
  8. package/pg/inputCombobox/__examples__/basic/basic.ts +33 -0
  9. package/pg/inputCombobox/inputCombobox.ts +158 -0
  10. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.751480cb81cc +158 -0
  11. package/pg/inputCombobox/inputCombobox.ts.tmp.44252.dcea847c40a8 +156 -0
  12. package/pg/inputNumber/inputNumber.ts +31 -13
  13. package/pg/inputPill/inputPill.html +6 -0
  14. package/pg/inputPill/inputPill.html.tmp.26852.84ac63f4c46f +6 -0
  15. package/pg/inputPill/inputPill.ts +41 -0
  16. package/pg/inputPills/__examples__/basic/basic.html +9 -0
  17. package/pg/inputPills/__examples__/basic/basic.html.tmp.26852.4771e4cad5b7 +9 -0
  18. package/pg/inputPills/__examples__/basic/basic.ts.tmp.26852.d8fe41df18bd +0 -0
  19. package/pg/inputPixelEditor/README.md +104 -69
  20. package/pg/inputPixelEditor/README.md.tmp.42596.658de5f0a6f5 +0 -0
  21. package/pg/inputPixelEditor/__examples__/basic/basic.ts +6 -5
  22. package/pg/inputPixelEditor/inputPixelEditor.ts +95 -23
  23. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.38516.96529dd82670 +1703 -0
  24. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.42596.48ecc3ad9c72 +1724 -0
  25. package/pg/inputPixelEditor/utils/bitmapToMask.ts +113 -79
  26. package/pg/inputPixelEditor/utils/getLassoPixels.ts +51 -0
  27. package/pg/inputRange/inputRange.css +7 -0
  28. package/pg/inputSelect/__examples__/basic/basic.ts +2 -2
  29. package/pg/inputSelect/inputSelect.css +1 -1
  30. package/pg/inputSelect/inputSelect.ts +62 -5
  31. package/pg/inputText/README.md +6 -6
  32. package/pg/inputText/__examples__/basic/basic.ts +1 -1
  33. package/pg/inputText/inputText.css +2 -2
  34. package/pg/inputText copy/README.md +38 -0
  35. package/pg/inputText copy/inputText.css +41 -0
  36. package/pg/inputText copy/inputText.html +1 -0
  37. package/pg/inputText copy/inputText.spec.ts +59 -0
  38. package/pg/inputText copy/inputText.ts +67 -0
  39. package/pg/inputTextarea/README.md +39 -0
  40. package/pg/inputTextarea/__examples__/basic/basic.html +9 -0
  41. package/pg/inputTextarea/__examples__/basic/basic.ts +30 -0
  42. package/pg/inputTextarea/inputTextarea.ts +121 -0
  43. package/pg/inputTextarea copy/README.md +39 -0
  44. package/pg/inputTextarea copy/inputTextarea.css +41 -0
  45. package/pg/inputTextarea copy/inputTextarea.html +1 -0
  46. package/pg/inputTextarea copy/inputTextarea.spec.ts +59 -0
  47. package/pg/inputTextarea copy/inputTextarea.ts +79 -0
  48. package/pg/inputTextareaAutocomplete/README.md +70 -0
  49. package/pg/inputTextareaAutocomplete/__examples__/basic/basic.ts +67 -0
  50. package/pg/inputTextareaAutocomplete/inputTextareaAutocomplete.ts +267 -0
  51. package/pg/node/README.md +35 -0
  52. package/pg/node/__examples__/basic/basic.ts +34 -0
  53. package/pg/node/index.ts +3 -0
  54. package/pg/node/node.css +53 -0
  55. package/pg/node/node.html +5 -0
  56. package/pg/node/node.ts +270 -0
  57. package/pg/nodeEditorLink/nodeEditorLink.css +69 -0
  58. package/pg/nodeEditorLink/nodeEditorLink.css.tmp.1408.09e961fd0dcc +69 -0
  59. package/pg/nodeEditorLink/nodeEditorLink.html +9 -0
  60. package/pg/nodeEditorNumber/nodeEditorNumber.css +59 -0
  61. package/pg/nodeEditorNumber/nodeEditorNumber.ts +57 -0
  62. package/pg/nodeEditorRange/nodeEditorRange.css +23 -0
  63. package/pg/nodeEditorRange/nodeEditorRange.ts +69 -0
  64. package/pg/nodeEditorText/__examples__/basic/basic.html +9 -0
  65. package/pg/nodeEditorText/__examples__/basic/basic.ts +30 -0
  66. package/pg/nodeEditorText/nodeEditorText.css +17 -0
  67. package/pg/nodeEditorText/nodeEditorText.html +4 -0
  68. package/pg/nodeEditorText/nodeEditorText.ts +57 -0
  69. package/pg/nodeEditorText copy/README.md +35 -0
  70. package/pg/nodeEditorText copy/nodeEditorText.css +49 -0
  71. package/pg/nodeEditorText copy/nodeEditorText.html +4 -0
  72. package/pg/nodeEditorText copy/nodeEditorText.ts +50 -0
  73. package/pg/nodeEditorTextArray/nodeEditorTextArray.css +68 -0
  74. package/pg/nodeEditorTextArray/nodeEditorTextArray.html +9 -0
  75. package/pg/nodeEditorTextArray/nodeEditorTextArray.ts +162 -0
  76. package/pg/nodeEntry/nodeEntry.css +61 -0
  77. package/pg/nodeEntry/nodeEntry.ts +164 -0
  78. package/pg/nodeEntry/nodeEntry.ts.tmp.28724.dda67762bca5 +164 -0
  79. package/pg/nodeInputText/nodeInputText.css +75 -0
  80. package/pg/nodeInputText/nodeInputText.html +4 -0
  81. package/pg/nodeInputText/nodeInputText.ts +105 -0
  82. package/pg/nodeOutput/nodeOutput.css +32 -0
  83. package/pg/nodeResize/README.md +3 -0
  84. package/pg/nodeResize/THINKING.md +81 -0
  85. package/pg/nodeResize/THINKING.md.tmp.24812.99a70ba81062 +81 -0
  86. package/pg/nodeResize/basic/basic.ts +17 -0
  87. package/pg/nodeResize/dragUtil.ts +105 -0
  88. package/pg/nodeResize/dragUtil.ts.tmp.34372.787464c73309 +75 -0
  89. package/pg/nodeResize/nodeResize.css +187 -0
  90. package/pg/nodeResize/nodeResize.html +9 -0
  91. package/pg/nodeResize/nodeResize.ts +156 -0
  92. package/pg/nodes/README.md +177 -0
  93. package/pg/nodes/__examples__/basic/basic.html +33 -0
  94. package/pg/nodes/__examples__/basic/basic.ts +716 -0
  95. package/pg/nodes/__examples__/basic/exampleNodes.ts +129 -0
  96. package/pg/nodes/__examples__/basic/exampleScripts.ts +129 -0
  97. package/pg/nodes/__examples__/basic/keystore.ts +38 -0
  98. package/pg/nodes/executeInSandbox.ts +32 -0
  99. package/pg/nodes/index.ts +3 -0
  100. package/pg/nodes/nodes.css +69 -0
  101. package/pg/nodes/nodes.html +6 -0
  102. package/pg/nodes/nodes.ts +1240 -0
  103. package/pg/nodes copy/nodes.css +41 -0
  104. package/pg/nodes copy/nodes.html +1 -0
  105. package/pg/overlayContextMenu/__examples__/filter/filter.ts +87 -0
  106. package/pg/overlayContextMenu/overlayContextMenu.css +14 -0
  107. package/pg/overlayContextMenu/overlayContextMenu.html +4 -3
  108. package/pg/overlayContextMenu/overlayContextMenu.ts +6 -2
  109. package/pg/overlayContextMenu/overlayContextMenu.ts.tmp.37088.530ff1c0a321 +0 -0
  110. package/pg/overlayMenu/overlayMenu.css +3 -1
  111. package/pg/overlayMenu/overlayMenu.ts +11 -2
  112. package/pg/overlayMenu/overlayMenu.ts.tmp.44252.9bb22fd59ede +80 -0
  113. package/pg/overlaySelectMenu/overlaySelectMenu.css +2 -0
  114. package/pg/overlaySubMenu/overlaySubMenu.css +8 -6
  115. package/pg/poco/README.md +22 -0
  116. package/pg/poco/__examples__/basic/basic.html +11 -0
  117. package/pg/poco/__examples__/basic/basic.ts +95 -0
  118. package/pg/poco/__examples__/basic/examples.ts +258 -0
  119. package/pg/poco/__examples__/basic/myFont.ts +1300 -0
  120. package/pg/poco/index.ts +3 -0
  121. package/pg/poco/mockPoco.ts +640 -0
  122. package/pg/poco/poco.css +7 -0
  123. package/pg/poco/poco.html +1 -0
  124. package/pg/poco/poco.ts +75 -0
  125. package/pg/popover/README.md +47 -0
  126. package/pg/popover/__examples__/basic/basic.html +3 -0
  127. package/pg/popover/popover.html +3 -0
  128. package/pg/popover/popover.ts +44 -0
  129. package/pg/popoverAutocomplete/__examples__/basic/basic.html +4 -0
  130. package/pg/popoverAutocomplete/__examples__/basic/basic.ts +46 -0
  131. package/pg/popoverAutocomplete/popoverAutocomplete.css +25 -0
  132. package/pg/popoverAutocomplete/popoverAutocomplete.html +1 -0
  133. package/pg/popoverAutocomplete/popoverAutocomplete.ts +134 -0
  134. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.css +69 -0
  135. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.ts +90 -0
  136. package/pg/table/__examples__/basic/basic.ts +1 -0
  137. package/pg/tableCellFileLocal/tableCellFileLocal.html +3 -0
  138. package/pg/tableCellFileLocal/tableCellFileLocal.html.tmp.20484.68ee2e30710e +3 -0
  139. package/pg/tableCellFileLocal/tableCellFileLocal.ts +44 -0
  140. package/pg/tableCellSelect/tableCellSelect.html +3 -0
  141. package/pg/tableCellSelect/tableCellSelect.html.tmp.41808.99c1a6f14340 +3 -0
  142. package/pg/tableCellSelect/tableCellSelect.ts +51 -0
  143. package/pg/tree/__examples__/basic/basic.ts +12 -5
  144. package/pg/tree/tree.html +1 -1
  145. package/pg/tree/tree.ts +385 -227
  146. package/pg/tree/tree.ts.tmp.38376.07d376a04f41 +343 -0
  147. package/pg/tree/tree.ts.tmp.38376.2a04599ade9f +361 -0
  148. package/pg/tree/tree.ts.tmp.38376.6cb2c663d476 +0 -0
  149. package/pg/tree/tree.ts.tmp.38376.ac5af1aff2b0 +393 -0
  150. package/pg/tree/tree.ts.tmp.38376.ac9acfc4f95f +324 -0
  151. package/pg/treeItem/treeItem.ts +536 -558
  152. package/pg/treeItem/treeItem.ts.tmp.38376.145d3121d648 +530 -0
  153. package/pg/treeItem/treeItem.ts.tmp.38376.b5224d48e5c0 +0 -0
@@ -0,0 +1,67 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './inputText.html';
4
+ import style from './inputText.css';
5
+
6
+ @Component({
7
+ selector: 'pg-input-text',
8
+ style,
9
+ template
10
+ })
11
+ export default class PgInputText 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
+ focus() {
25
+ this.$input.focus();
26
+ }
27
+
28
+ skipValue = false;
29
+
30
+ render(changes) {
31
+ if (changes.value && !this.skipValue) {
32
+ this.$input.value = this.value;
33
+ }
34
+ if (changes.placeholder) {
35
+ this.$input.placeholder = this.placeholder;
36
+ }
37
+ if (changes.readOnly) {
38
+ this.$input.readOnly = this.readOnly;
39
+ }
40
+ this.skipValue = false;
41
+ }
42
+
43
+ handleInput(e) {
44
+ e.stopPropagation();
45
+ this.skipValue = true;
46
+ this.value = e.target.value;
47
+ this.dispatchEvent(
48
+ new CustomEvent('input', {
49
+ detail: {
50
+ value: e.target.value,
51
+ name: e.name
52
+ }
53
+ })
54
+ );
55
+ }
56
+
57
+ handleChange(e) {
58
+ this.dispatchEvent(
59
+ new CustomEvent('change', {
60
+ detail: {
61
+ value: e.target.value,
62
+ name: e.name
63
+ }
64
+ })
65
+ );
66
+ }
67
+ }
@@ -0,0 +1,39 @@
1
+ # `<pg-input-textarea>`
2
+
3
+ The `pg-input-textarea` component creates an input that accepts multiline text. Additionally it can resize.
4
+
5
+ ```typescript
6
+ import '@pictogrammers/components/pgInputTextarea';
7
+ import { PgInputTextarea } from '@pictogrammers/components/pgInputTextarea';
8
+ ```
9
+
10
+ ```html
11
+ <pg-input-textarea value="50"></pg-input-textarea>
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 }` |
28
+ | caret | | `{ detail: { column, row }}` |
29
+
30
+ ## CSS Variables
31
+
32
+ | CSS Variables | Default | Description |
33
+ | ------------------- | --------- | ----------- |
34
+ | `--pg-input-textarea-padding-inline` | `0.5rem` | Padding inline. |
35
+ | `--pg-input-textarea-padding-inline-start` | `0.5rem` | Padding inline start. |
36
+ | `--pg-input-textarea-padding-inline-end` | `0.5rem` | Padding inline end. |
37
+ | `--pg-input-textarea-padding-block` | `0.25rem` | Padding block. |
38
+ | `--pg-input-textarea-padding-block-start` | `0.25rem` | Padding block start. |
39
+ | `--pg-input-textarea-padding-block-end` | `0.25rem` | Padding block end. |
@@ -0,0 +1,9 @@
1
+ <div class="example">
2
+ <pg-input-textarea part="input" value="Hello World!"></pg-input-textarea>
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>
@@ -0,0 +1,30 @@
1
+ import { Component, Part } from '@pictogrammers/element';
2
+ import PgInputTextarea from '../../inputTextarea';
3
+
4
+ import template from './basic.html';
5
+
6
+ @Component({
7
+ selector: 'x-pg-input-textarea-basic',
8
+ template,
9
+ })
10
+ export default class XPgInputTextareaBasic extends HTMLElement {
11
+
12
+ @Part() $input: PgInputTextarea;
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
+ }
@@ -0,0 +1,121 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './inputTextarea.html';
4
+ import style from './inputTextarea.css';
5
+
6
+ function getCursorRowCol(
7
+ textArea: HTMLTextAreaElement
8
+ ): { row: number; col: number } {
9
+ // Get the character index of the cursor
10
+ const cursorIndex = textArea.selectionStart;
11
+
12
+ // Get the text content up to the cursor position
13
+ const textUpToCursor = textArea.value.substring(0, cursorIndex);
14
+
15
+ // Split the text by newline characters to get all lines
16
+ const lines = textUpToCursor.split('\n');
17
+
18
+ // The row (line number) is the number of lines (array length).
19
+ // Rows are typically 1-indexed, so we can return the length directly.
20
+ const row = lines.length - 1;
21
+
22
+ // The column is the length of the last line in the `lines` array.
23
+ const col = lines[lines.length - 1].length; // +1 to make it 1-indexed
24
+
25
+ return { row, col };
26
+ }
27
+
28
+ @Component({
29
+ selector: 'pg-input-textarea',
30
+ style,
31
+ template
32
+ })
33
+ export default class PgInputTextarea extends HTMLElement {
34
+ @Prop() name: string = '';
35
+ @Prop() value: string = '';
36
+ @Prop() placeholder: string = '';
37
+ @Prop() readOnly: boolean = false;
38
+
39
+ @Part() $input: HTMLInputElement;
40
+
41
+ connectedCallback() {
42
+ this.$input.addEventListener('input', this.handleInput.bind(this));
43
+ this.$input.addEventListener('change', this.handleChange.bind(this));
44
+ this.$input.addEventListener('focus', this.handleFocus.bind(this));
45
+ this.$input.addEventListener('focus', this.handleBlur.bind(this));
46
+
47
+ this.$input.addEventListener('input', this.handleCursorMove.bind(this));
48
+ this.$input.addEventListener('click', this.handleCursorMove.bind(this));
49
+ this.$input.addEventListener('keyup', this.handleCursorMove.bind(this));
50
+ }
51
+
52
+ focus() {
53
+ this.$input.focus();
54
+ }
55
+
56
+ skipValue = false;
57
+
58
+ render(changes) {
59
+ if (changes.value && !this.skipValue) {
60
+ this.$input.value = this.value;
61
+ }
62
+ if (changes.placeholder) {
63
+ this.$input.placeholder = this.placeholder;
64
+ }
65
+ if (changes.readOnly) {
66
+ this.$input.readOnly = this.readOnly;
67
+ }
68
+ this.skipValue = false;
69
+ }
70
+
71
+ handleInput(e) {
72
+ e.stopPropagation();
73
+ this.skipValue = true;
74
+ this.value = e.target.value;
75
+ this.dispatchEvent(
76
+ new CustomEvent('input', {
77
+ detail: {
78
+ value: e.target.value,
79
+ name: e.name
80
+ }
81
+ })
82
+ );
83
+ }
84
+
85
+ handleChange(e) {
86
+ this.dispatchEvent(
87
+ new CustomEvent('change', {
88
+ detail: {
89
+ value: e.target.value,
90
+ name: e.name
91
+ }
92
+ })
93
+ );
94
+ }
95
+
96
+ #currentColumn = -1;
97
+ #currentRow = -1;
98
+ handleCursorMove(event: Event) {
99
+ const textArea = event.target as HTMLTextAreaElement;
100
+ const { row, col: column } = getCursorRowCol(textArea);
101
+ if (this.#currentColumn !== column && this.#currentRow !== row) {
102
+ this.dispatchEvent(new CustomEvent('caret', {
103
+ detail: {
104
+ column,
105
+ row
106
+ }
107
+ }));
108
+ }
109
+ console.log(`Cursor position: Row ${row}, Column ${column}`);
110
+ }
111
+
112
+ handleFocus(e: any) {
113
+ e.preventDefault();
114
+ this.dispatchEvent(new CustomEvent('focus'));
115
+ }
116
+
117
+ handleBlur(e: any) {
118
+ e.preventDefault();
119
+ this.dispatchEvent(new CustomEvent('blur'));
120
+ }
121
+ }
@@ -0,0 +1,39 @@
1
+ # `<pg-input-textarea>`
2
+
3
+ The `pg-input-textarea` component creates an input that accepts multiline text. Additionally it can resize.
4
+
5
+ ```typescript
6
+ import '@pictogrammers/components/pgInputTextarea';
7
+ import { PgInputTextarea } from '@pictogrammers/components/pgInputTextarea';
8
+ ```
9
+
10
+ ```html
11
+ <pg-input-textarea value="50"></pg-input-textarea>
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 }` |
28
+ | caret | | `{ detail: { column, row }}` |
29
+
30
+ ## CSS Variables
31
+
32
+ | CSS Variables | Default | Description |
33
+ | ------------------- | --------- | ----------- |
34
+ | `--pg-input-textarea-padding-inline` | `0.5rem` | Padding inline. |
35
+ | `--pg-input-textarea-padding-inline-start` | `0.5rem` | Padding inline start. |
36
+ | `--pg-input-textarea-padding-inline-end` | `0.5rem` | Padding inline end. |
37
+ | `--pg-input-textarea-padding-block` | `0.25rem` | Padding block. |
38
+ | `--pg-input-textarea-padding-block-start` | `0.25rem` | Padding block start. |
39
+ | `--pg-input-textarea-padding-block-end` | `0.25rem` | Padding block end. |
@@ -0,0 +1,41 @@
1
+ :host {
2
+ display: block;
3
+ font-family: var(--pg-font-family, system-ui);
4
+ }
5
+
6
+ [part=input] {
7
+ border: 1px solid var(--pg-input-text-border-color, #453C4F);
8
+ border-radius: 0.125rem;
9
+ padding-inline-start: var(--pg-input-text-padding-inline-start, var(--pg-input-text-padding-inline, 0.5rem));
10
+ padding-inline-end: var(--pg-input-text-padding-inline-end, var(--pg-input-text-padding-inline, 0.5rem));
11
+ padding-block-start: var(--pg-input-text-padding-block-start, var(--pg-input-text-padding-block, 0.25rem));
12
+ padding-block-end: var(--pg-input-text-padding-block-start, var(--pg-input-text-padding-block, 0.25rem));
13
+ font-family: var(--pg-input-text-font-family, var(--pg-font-family));
14
+ font-size: 1rem;
15
+ outline: none;
16
+ field-sizing: content;
17
+ min-width: calc(
18
+ 100%
19
+ - var(--pg-input-text-padding-inline-start, var(--pg-input-text-padding-inline, 0.5rem))
20
+ - var(--pg-input-text-padding-inline-end, var(--pg-input-text-padding-inline, 0.5rem))
21
+ - 2px
22
+ );
23
+ max-width: calc(
24
+ var(--pg-input-text-max-width, 100%)
25
+ - var(--pg-input-text-padding-inline-start, var(--pg-input-text-padding-inline, 0.5rem))
26
+ - var(--pg-input-text-padding-inline-end, var(--pg-input-text-padding-inline, 0.5rem))
27
+ - 2px
28
+ );
29
+ background-color: transparent;
30
+ }
31
+
32
+ [part=input]:read-only {
33
+ border-color: transparent;
34
+ }
35
+
36
+ [part=input]:active {
37
+ box-shadow: 0 0 0 3px var(--pg-input-text-active-glow, rgb(79, 143, 249, 0.6));
38
+ }
39
+ [part=input]:focus {
40
+ box-shadow: 0 0 0 3px var(--pg-input-text-focus-glow, rgb(79, 143, 249, 0.5));
41
+ }
@@ -0,0 +1 @@
1
+ <textarea part="input"></textarea>
@@ -0,0 +1,59 @@
1
+ import { selectComponent, getProps } from '@pictogrammers/element';
2
+
3
+ import './inputTextarea';
4
+ import PgInputText from './inputTextarea';
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
+ });
@@ -0,0 +1,79 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './inputTextarea.html';
4
+ import style from './inputTextarea.css';
5
+
6
+ @Component({
7
+ selector: 'pg-input-textarea',
8
+ style,
9
+ template
10
+ })
11
+ export default class PgInputTextarea 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
+ this.$input.addEventListener('focus', this.handleFocus.bind(this));
23
+ this.$input.addEventListener('focus', this.handleBlur.bind(this));
24
+ }
25
+
26
+ focus() {
27
+ this.$input.focus();
28
+ }
29
+
30
+ skipValue = false;
31
+
32
+ render(changes) {
33
+ if (changes.value && !this.skipValue) {
34
+ this.$input.value = this.value;
35
+ }
36
+ if (changes.placeholder) {
37
+ this.$input.placeholder = this.placeholder;
38
+ }
39
+ if (changes.readOnly) {
40
+ this.$input.readOnly = this.readOnly;
41
+ }
42
+ this.skipValue = false;
43
+ }
44
+
45
+ handleInput(e) {
46
+ e.stopPropagation();
47
+ this.skipValue = true;
48
+ this.value = e.target.value;
49
+ this.dispatchEvent(
50
+ new CustomEvent('input', {
51
+ detail: {
52
+ value: e.target.value,
53
+ name: e.name
54
+ }
55
+ })
56
+ );
57
+ }
58
+
59
+ handleChange(e) {
60
+ this.dispatchEvent(
61
+ new CustomEvent('change', {
62
+ detail: {
63
+ value: e.target.value,
64
+ name: e.name
65
+ }
66
+ })
67
+ );
68
+ }
69
+
70
+ handleFocus(e: any) {
71
+ e.preventDefault();
72
+ this.dispatchEvent(new CustomEvent('focus'));
73
+ }
74
+
75
+ handleBlur(e: any) {
76
+ e.preventDefault();
77
+ this.dispatchEvent(new CustomEvent('blur'));
78
+ }
79
+ }
@@ -0,0 +1,70 @@
1
+ # `<pg-input-textarea-autocomplete>`
2
+
3
+ The `pg-input-textarea-autocomplete` component supports everything `pg-input-textarea` and adds tracking for the caret position implementing a list of options.
4
+
5
+ ```typescript
6
+ import '@pictogrammers/components/pgInputTextareaAutocomplete';
7
+ import { PgInputTextarea } from '@pictogrammers/components/pgInputTextareaAutocomplete';
8
+ ```
9
+
10
+ ```html
11
+ <pg-input-textarea-autocomplete value="50"></pg-input-textarea-autocomplete>
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
+ | tokens | | Tokens array |
22
+
23
+ ## Tokens
24
+
25
+ Tokens will match if the cursor is before, after, or in side of a token regex. The most common is `@` for usernames or `#` for tags.
26
+
27
+ ```typescript
28
+ this.$input.tokens = [
29
+ /@([a-zA-Z]+\w+)?/, // @username
30
+ /#([a-zA-Z]+\w+)?/ // #TagName
31
+ ];
32
+ ```
33
+
34
+ ## Methods
35
+
36
+ ### `setOptions`
37
+
38
+ ```typescript
39
+ this.$input.addEventListener('caret', (e: any) => {
40
+ const { matchIndex, setOptions } = e.detail;
41
+ switch(matchIndex) {
42
+ case 1: // @username
43
+ setOptions([{
44
+ label: 'Dipper',
45
+ value: 'Dipper',
46
+ }]);
47
+ break;
48
+ case 2: // #TagName
49
+ setOptions([{
50
+ label: 'Movie',
51
+ value: 'Movie',
52
+ }]);
53
+ break;
54
+ default:
55
+ setOptions([]);
56
+ }
57
+ });
58
+ ```
59
+
60
+ ## Events
61
+
62
+ | Events | Tested | Description |
63
+ | ---------- | -------- | ----------- |
64
+ | change | | `{ detail: { value }` |
65
+ | input | | `{ detail: { value }` |
66
+ | caret | | `{ detail: { column, row }}` |
67
+
68
+ ## CSS Variables
69
+
70
+ See: `pg-textarea`.
@@ -0,0 +1,67 @@
1
+ import { Component, Part } from '@pictogrammers/element';
2
+ import PgInputTextareaAutocomplete from '../../inputTextareaAutocomplete';
3
+
4
+ import template from './basic.html';
5
+
6
+ const USERS = ['Dipper', 'Mable', 'Grunkle Stan', 'Wendy', 'Soos', 'Gideon', 'Ford', 'McGucket'];
7
+ const TAGS = ['Mystery', 'Cipher', 'Paranormal', 'Gravity', 'Falls', 'Conspiracy', 'Gnomes'];
8
+
9
+ @Component({
10
+ selector: 'x-pg-input-textarea-autocomplete-basic',
11
+ template,
12
+ })
13
+ export default class XPgInputTextareaBasic extends HTMLElement {
14
+
15
+ @Part() $input: PgInputTextareaAutocomplete;
16
+ @Part() $value1: HTMLSpanElement;
17
+ @Part() $value2: HTMLSpanElement;
18
+ @Part() $value3: HTMLSpanElement;
19
+
20
+ connectedCallback() {
21
+ this.$input.addEventListener('change', this.#handleChange.bind(this));
22
+ this.$input.addEventListener('input', this.#handleInput.bind(this));
23
+ this.$input.addEventListener('caret', this.#handleCaret.bind(this));
24
+
25
+ this.$input.tokens = [
26
+ /@([a-zA-Z]+\w*)?/, // @username
27
+ /#([a-zA-Z]+\w*)?/ // #TagName
28
+ ];
29
+ this.$input.addEventListener('caret', (e: any) => {
30
+ const { matchIndex, matchText, setOptions } = e.detail;
31
+ const query = matchText.slice(1).toLowerCase();
32
+ switch (matchIndex) {
33
+ case 1: // @username
34
+ setOptions(
35
+ USERS
36
+ .filter(u => u.toLowerCase().startsWith(query))
37
+ .map(u => ({ label: u, value: u }))
38
+ );
39
+ break;
40
+ case 2: // #TagName
41
+ setOptions(
42
+ TAGS
43
+ .filter(t => t.toLowerCase().startsWith(query))
44
+ .map(t => ({ label: t, value: t }))
45
+ );
46
+ break;
47
+ default:
48
+ setOptions([]);
49
+ }
50
+ });
51
+ }
52
+
53
+ #handleChange(e: CustomEvent) {
54
+ const { value } = e.detail;
55
+ this.$value1.textContent = value;
56
+ }
57
+
58
+ #handleInput(e: CustomEvent) {
59
+ const { value } = e.detail;
60
+ this.$value2.textContent = value;
61
+ }
62
+
63
+ #handleCaret(e: CustomEvent) {
64
+ const { column, row } = e.detail;
65
+ this.$value3.textContent = `${column}, ${row}`;
66
+ }
67
+ }