@pictogrammers/components 0.5.15 → 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 (149) 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/inputPill/inputPill.html +6 -0
  13. package/pg/inputPill/inputPill.html.tmp.26852.84ac63f4c46f +6 -0
  14. package/pg/inputPill/inputPill.ts +41 -0
  15. package/pg/inputPills/__examples__/basic/basic.html +9 -0
  16. package/pg/inputPills/__examples__/basic/basic.html.tmp.26852.4771e4cad5b7 +9 -0
  17. package/pg/inputPills/__examples__/basic/basic.ts.tmp.26852.d8fe41df18bd +0 -0
  18. package/pg/inputPixelEditor/README.md +104 -69
  19. package/pg/inputPixelEditor/README.md.tmp.42596.658de5f0a6f5 +0 -0
  20. package/pg/inputPixelEditor/__examples__/basic/basic.ts +6 -5
  21. package/pg/inputPixelEditor/inputPixelEditor.ts +95 -23
  22. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.38516.96529dd82670 +1703 -0
  23. package/pg/inputPixelEditor/inputPixelEditor.ts.tmp.42596.48ecc3ad9c72 +1724 -0
  24. package/pg/inputPixelEditor/utils/bitmapToMask.ts +113 -79
  25. package/pg/inputPixelEditor/utils/getLassoPixels.ts +51 -0
  26. package/pg/inputSelect/inputSelect.ts +5 -1
  27. package/pg/inputText/README.md +6 -6
  28. package/pg/inputText/__examples__/basic/basic.ts +1 -1
  29. package/pg/inputText/inputText.css +2 -2
  30. package/pg/inputText copy/README.md +38 -0
  31. package/pg/inputText copy/inputText.css +41 -0
  32. package/pg/inputText copy/inputText.html +1 -0
  33. package/pg/inputText copy/inputText.spec.ts +59 -0
  34. package/pg/inputText copy/inputText.ts +67 -0
  35. package/pg/inputTextarea/README.md +39 -0
  36. package/pg/inputTextarea/__examples__/basic/basic.html +9 -0
  37. package/pg/inputTextarea/__examples__/basic/basic.ts +30 -0
  38. package/pg/inputTextarea/inputTextarea.ts +121 -0
  39. package/pg/inputTextarea copy/README.md +39 -0
  40. package/pg/inputTextarea copy/inputTextarea.css +41 -0
  41. package/pg/inputTextarea copy/inputTextarea.html +1 -0
  42. package/pg/inputTextarea copy/inputTextarea.spec.ts +59 -0
  43. package/pg/inputTextarea copy/inputTextarea.ts +79 -0
  44. package/pg/inputTextareaAutocomplete/README.md +70 -0
  45. package/pg/inputTextareaAutocomplete/__examples__/basic/basic.ts +67 -0
  46. package/pg/inputTextareaAutocomplete/inputTextareaAutocomplete.ts +267 -0
  47. package/pg/node/README.md +35 -0
  48. package/pg/node/__examples__/basic/basic.ts +34 -0
  49. package/pg/node/index.ts +3 -0
  50. package/pg/node/node.css +53 -0
  51. package/pg/node/node.html +5 -0
  52. package/pg/node/node.ts +270 -0
  53. package/pg/nodeEditorLink/nodeEditorLink.css +69 -0
  54. package/pg/nodeEditorLink/nodeEditorLink.css.tmp.1408.09e961fd0dcc +69 -0
  55. package/pg/nodeEditorLink/nodeEditorLink.html +9 -0
  56. package/pg/nodeEditorNumber/nodeEditorNumber.css +59 -0
  57. package/pg/nodeEditorNumber/nodeEditorNumber.ts +57 -0
  58. package/pg/nodeEditorRange/nodeEditorRange.css +23 -0
  59. package/pg/nodeEditorRange/nodeEditorRange.ts +69 -0
  60. package/pg/nodeEditorText/__examples__/basic/basic.html +9 -0
  61. package/pg/nodeEditorText/__examples__/basic/basic.ts +30 -0
  62. package/pg/nodeEditorText/nodeEditorText.css +17 -0
  63. package/pg/nodeEditorText/nodeEditorText.html +4 -0
  64. package/pg/nodeEditorText/nodeEditorText.ts +57 -0
  65. package/pg/nodeEditorText copy/README.md +35 -0
  66. package/pg/nodeEditorText copy/nodeEditorText.css +49 -0
  67. package/pg/nodeEditorText copy/nodeEditorText.html +4 -0
  68. package/pg/nodeEditorText copy/nodeEditorText.ts +50 -0
  69. package/pg/nodeEditorTextArray/nodeEditorTextArray.css +68 -0
  70. package/pg/nodeEditorTextArray/nodeEditorTextArray.html +9 -0
  71. package/pg/nodeEditorTextArray/nodeEditorTextArray.ts +162 -0
  72. package/pg/nodeEntry/nodeEntry.css +61 -0
  73. package/pg/nodeEntry/nodeEntry.ts +164 -0
  74. package/pg/nodeEntry/nodeEntry.ts.tmp.28724.dda67762bca5 +164 -0
  75. package/pg/nodeInputText/nodeInputText.css +75 -0
  76. package/pg/nodeInputText/nodeInputText.html +4 -0
  77. package/pg/nodeInputText/nodeInputText.ts +105 -0
  78. package/pg/nodeOutput/nodeOutput.css +32 -0
  79. package/pg/nodeResize/README.md +3 -0
  80. package/pg/nodeResize/THINKING.md +81 -0
  81. package/pg/nodeResize/THINKING.md.tmp.24812.99a70ba81062 +81 -0
  82. package/pg/nodeResize/basic/basic.ts +17 -0
  83. package/pg/nodeResize/dragUtil.ts +105 -0
  84. package/pg/nodeResize/dragUtil.ts.tmp.34372.787464c73309 +75 -0
  85. package/pg/nodeResize/nodeResize.css +187 -0
  86. package/pg/nodeResize/nodeResize.html +9 -0
  87. package/pg/nodeResize/nodeResize.ts +156 -0
  88. package/pg/nodes/README.md +177 -0
  89. package/pg/nodes/__examples__/basic/basic.html +33 -0
  90. package/pg/nodes/__examples__/basic/basic.ts +716 -0
  91. package/pg/nodes/__examples__/basic/exampleNodes.ts +129 -0
  92. package/pg/nodes/__examples__/basic/exampleScripts.ts +129 -0
  93. package/pg/nodes/__examples__/basic/keystore.ts +38 -0
  94. package/pg/nodes/executeInSandbox.ts +32 -0
  95. package/pg/nodes/index.ts +3 -0
  96. package/pg/nodes/nodes.css +69 -0
  97. package/pg/nodes/nodes.html +6 -0
  98. package/pg/nodes/nodes.ts +1240 -0
  99. package/pg/nodes copy/nodes.css +41 -0
  100. package/pg/nodes copy/nodes.html +1 -0
  101. package/pg/overlayContextMenu/__examples__/filter/filter.ts +87 -0
  102. package/pg/overlayContextMenu/overlayContextMenu.css +14 -0
  103. package/pg/overlayContextMenu/overlayContextMenu.html +4 -3
  104. package/pg/overlayContextMenu/overlayContextMenu.ts +6 -2
  105. package/pg/overlayContextMenu/overlayContextMenu.ts.tmp.37088.530ff1c0a321 +0 -0
  106. package/pg/overlayMenu/overlayMenu.css +3 -1
  107. package/pg/overlayMenu/overlayMenu.ts +11 -2
  108. package/pg/overlayMenu/overlayMenu.ts.tmp.44252.9bb22fd59ede +80 -0
  109. package/pg/overlaySelectMenu/overlaySelectMenu.css +2 -0
  110. package/pg/overlaySubMenu/overlaySubMenu.css +8 -6
  111. package/pg/poco/README.md +22 -0
  112. package/pg/poco/__examples__/basic/basic.html +11 -0
  113. package/pg/poco/__examples__/basic/basic.ts +95 -0
  114. package/pg/poco/__examples__/basic/examples.ts +258 -0
  115. package/pg/poco/__examples__/basic/myFont.ts +1300 -0
  116. package/pg/poco/index.ts +3 -0
  117. package/pg/poco/mockPoco.ts +640 -0
  118. package/pg/poco/poco.css +7 -0
  119. package/pg/poco/poco.html +1 -0
  120. package/pg/poco/poco.ts +75 -0
  121. package/pg/popover/README.md +47 -0
  122. package/pg/popover/__examples__/basic/basic.html +3 -0
  123. package/pg/popover/popover.html +3 -0
  124. package/pg/popover/popover.ts +44 -0
  125. package/pg/popoverAutocomplete/__examples__/basic/basic.html +4 -0
  126. package/pg/popoverAutocomplete/__examples__/basic/basic.ts +46 -0
  127. package/pg/popoverAutocomplete/popoverAutocomplete.css +25 -0
  128. package/pg/popoverAutocomplete/popoverAutocomplete.html +1 -0
  129. package/pg/popoverAutocomplete/popoverAutocomplete.ts +134 -0
  130. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.css +69 -0
  131. package/pg/popoverAutocompleteItem/popoverAutocompleteItem.ts +90 -0
  132. package/pg/table/__examples__/basic/basic.ts +1 -0
  133. package/pg/tableCellFileLocal/tableCellFileLocal.html +3 -0
  134. package/pg/tableCellFileLocal/tableCellFileLocal.html.tmp.20484.68ee2e30710e +3 -0
  135. package/pg/tableCellFileLocal/tableCellFileLocal.ts +44 -0
  136. package/pg/tableCellSelect/tableCellSelect.html +3 -0
  137. package/pg/tableCellSelect/tableCellSelect.html.tmp.41808.99c1a6f14340 +3 -0
  138. package/pg/tableCellSelect/tableCellSelect.ts +51 -0
  139. package/pg/tree/__examples__/basic/basic.ts +12 -5
  140. package/pg/tree/tree.html +1 -1
  141. package/pg/tree/tree.ts +385 -227
  142. package/pg/tree/tree.ts.tmp.38376.07d376a04f41 +343 -0
  143. package/pg/tree/tree.ts.tmp.38376.2a04599ade9f +361 -0
  144. package/pg/tree/tree.ts.tmp.38376.6cb2c663d476 +0 -0
  145. package/pg/tree/tree.ts.tmp.38376.ac5af1aff2b0 +393 -0
  146. package/pg/tree/tree.ts.tmp.38376.ac9acfc4f95f +324 -0
  147. package/pg/treeItem/treeItem.ts +536 -558
  148. package/pg/treeItem/treeItem.ts.tmp.38376.145d3121d648 +530 -0
  149. package/pg/treeItem/treeItem.ts.tmp.38376.b5224d48e5c0 +0 -0
@@ -0,0 +1,162 @@
1
+ import { Component, Prop, Part, forEach } from '@pictogrammers/element';
2
+
3
+ import PgNodeInputText from '../nodeInputText/nodeInputText';
4
+
5
+ import template from './nodeEditorTextArray.html';
6
+ import style from './nodeEditorTextArray.css';
7
+
8
+ function uuid() {
9
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
10
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
11
+ return v.toString(16);
12
+ });
13
+ }
14
+
15
+ @Component({
16
+ selector: 'pg-node-editor-text-array',
17
+ style,
18
+ template,
19
+ })
20
+ export default class PgNodeEditorTextArray extends HTMLElement {
21
+
22
+ static type = 'TextArray';
23
+
24
+ @Prop() label: string = '';
25
+ @Prop() value: string[] = [];
26
+ @Prop() name: string = '';
27
+
28
+ @Part() $label: HTMLSpanElement;
29
+ @Part() $inputs: HTMLDivElement;
30
+ @Part() $add: HTMLButtonElement;
31
+
32
+ @Prop() #inputs: any[] = [];
33
+
34
+ #focusNext = false;
35
+
36
+ connectedCallback() {
37
+ // Map this.value to list
38
+ this.value.forEach((value) => {
39
+ this.#inputs.push({
40
+ value: value,
41
+ key: uuid(),
42
+ });
43
+ });
44
+ forEach({
45
+ container: this.$inputs,
46
+ items: this.#inputs,
47
+ type: () => PgNodeInputText,
48
+ create: ($item: PgNodeInputText, item: any) => {
49
+ $item.value = item.value;
50
+ $item.removable = true;
51
+ $item.addEventListener('change', (e: any) => {
52
+ e.stopPropagation();
53
+ const { index, value } = e.detail;
54
+ this.#inputs[index].value = value;
55
+ this.dispatchEvent(new CustomEvent('change', {
56
+ detail: {
57
+ value: this.#inputs.map(x => x.value),
58
+ },
59
+ }));
60
+ });
61
+ $item.addEventListener('input', (e: any) => {
62
+ e.stopPropagation();
63
+ const { index, value } = e.detail;
64
+ this.#inputs[index].value = value;
65
+ this.dispatchEvent(new CustomEvent('input', {
66
+ detail: {
67
+ value: this.#inputs.map(x => x.value),
68
+ },
69
+ }));
70
+ });
71
+ $item.addEventListener('inputprevious', (e: any) => {
72
+ const { index, selectionIndex } = e.detail;
73
+ const $items = Array.from(this.$inputs.children);
74
+ if ($items.length > 1) {
75
+ if (index === 0) {
76
+ ($items[$items.length - 1] as any).selectionStart = selectionIndex;
77
+ ($items[$items.length - 1] as any).selectionEnd = selectionIndex;
78
+ ($items[$items.length - 1] as any).focus();
79
+ } else {
80
+ ($items[index - 1] as any).selectionStart = selectionIndex;
81
+ ($items[index - 1] as any).selectionEnd = selectionIndex;
82
+ ($items[index - 1] as any).focus();
83
+ }
84
+ }
85
+ });
86
+ $item.addEventListener('inputnext', (e: any) => {
87
+ const { index, selectionIndex } = e.detail;
88
+ const $items = Array.from(this.$inputs.children);
89
+ if ($items.length > 1) {
90
+ if (index === $items.length - 1) {
91
+ ($items[0] as any).selectionStart = selectionIndex;
92
+ ($items[0] as any).selectionEnd = selectionIndex;
93
+ ($items[0] as any).focus();
94
+ } else {
95
+ ($items[index + 1] as any).selectionStart = selectionIndex;
96
+ ($items[index + 1] as any).selectionEnd = selectionIndex;
97
+ ($items[index + 1] as any).focus();
98
+ }
99
+ }
100
+ });
101
+ $item.addEventListener('enter', (e: any) => {
102
+ const { index } = e.detail;
103
+ const emptyItem = this.#inputs.findIndex(x => x.value === '');
104
+ if (emptyItem !== -1) {
105
+ (this.$inputs.children[emptyItem] as any).focus();
106
+ return;
107
+ }
108
+ this.#focusNext = true;
109
+ this.#inputs.splice(index + 1, 0, {
110
+ key: uuid(),
111
+ value: '',
112
+ });
113
+ });
114
+ $item.addEventListener('remove', (e: any) => {
115
+ const { index } = e.detail;
116
+ if (this.#inputs.length > 1) {
117
+ this.#inputs.splice(index, 1);
118
+ // Emit updated array
119
+ this.dispatchEvent(new CustomEvent('change', {
120
+ detail: {
121
+ value: this.#inputs.map(x => x.value),
122
+ },
123
+ }));
124
+ }
125
+ });
126
+ },
127
+ connect: ($item) => {
128
+ if (this.#focusNext) {
129
+ $item.focus();
130
+ this.#focusNext = false;
131
+ }
132
+ },
133
+ });
134
+
135
+ this.$add.addEventListener('click', () => {
136
+ this.#focusNext = true;
137
+ this.#inputs.push({
138
+ key: uuid(),
139
+ value: '',
140
+ });
141
+ // Emit updated array
142
+ this.dispatchEvent(new CustomEvent('change', {
143
+ detail: { value: [...this.value, ''] },
144
+ }));
145
+ });
146
+ }
147
+
148
+ render(changes: any) {
149
+ if (changes.label) {
150
+ this.$label.textContent = this.label;
151
+ }
152
+ }
153
+
154
+ get height() {
155
+ return this.#inputs.length + 1;
156
+ }
157
+
158
+ focus() {
159
+ const first = this.$inputs.firstElementChild as PgNodeInputText;
160
+ first?.focus();
161
+ }
162
+ }
@@ -0,0 +1,61 @@
1
+ :host {
2
+ display: contents;
3
+ }
4
+
5
+ [part=header] {
6
+ font-size: 0.75rem;
7
+ line-height: 1.375rem;
8
+ padding-inline: 0.5rem;
9
+ padding-block: 0 0.125rem;
10
+ background-color: #181818;
11
+ color: rgba(255, 255, 255, 0.9);
12
+ }
13
+
14
+ [part=node] {
15
+ display: flex;
16
+ flex-direction: column;
17
+ position: absolute;
18
+ box-sizing: border-box;
19
+ border: 2px solid rgba(67, 227, 64, 0.5);
20
+ border-radius: 0.25rem;
21
+ background: #1D1D1D;
22
+ color: #FFF;
23
+ width: var(--pg-node-width, 12rem);
24
+ min-height: var(--pg-node-height, 3rem);
25
+ padding-block-end: 0.25rem;
26
+ }
27
+
28
+ [part=node]:hover {
29
+ border-color: rgba(67, 227, 64, 0.75);
30
+ }
31
+
32
+ textarea {
33
+ background-color: #2B2B2B;
34
+ border: 0;
35
+ color: #FFF;
36
+ font-family: var(--pg-input-text-font-family, var(--pg-font-family, system-ui));
37
+ margin-inline: 0.25rem;
38
+ resize: none;
39
+ flex: 1;
40
+ }
41
+
42
+ textarea:focus {
43
+ box-shadow: 0 0 0 2px var(--pg-input-text-focus-glow, rgb(79, 143, 249, 0.75));
44
+ outline: 0;
45
+ }
46
+
47
+ [part=node].selected {
48
+ outline: 2px solid #248BE5;
49
+ outline-offset: 2px;
50
+ }
51
+
52
+ [part=node].debug {
53
+ border-color: #4ade80;
54
+ box-shadow: 0 0 0.5rem rgba(74, 222, 128, 0.75);
55
+ outline: 1px solid #1a1d2e;
56
+ outline-offset: 0;
57
+ }
58
+
59
+ [part=node].debug [part=header] {
60
+ color: #4ade80;
61
+ }
@@ -0,0 +1,164 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './nodeEntry.html';
4
+ import style from './nodeEntry.css';
5
+ import PgNodeResize from '../nodeResize/nodeResize';
6
+
7
+ const ANCHOR_NAME = '--node-entry-resize-anchor';
8
+
9
+ @Component({
10
+ selector: 'pg-node-entry',
11
+ style,
12
+ template,
13
+ })
14
+ export default class PgNodeEntry extends HTMLElement {
15
+ @Prop() x: number = 0;
16
+ @Prop() y: number = 0;
17
+ @Prop() width: number = 12;
18
+ @Prop() height: number = 5;
19
+ @Prop() itemId: number = 0;
20
+ @Prop() fields: any = [];
21
+ @Prop() debug: boolean = false;
22
+
23
+ @Part() $node: HTMLDivElement;
24
+ @Part() $header: HTMLDivElement;
25
+ @Part() $input: HTMLTextAreaElement;
26
+
27
+ connectedCallback() {
28
+ this.height = this.getMinHeight();
29
+ this.$node.addEventListener('pointerover', this.#handlePointerOver.bind(this));
30
+ this.$input.addEventListener('input', () => {
31
+ this.dispatchEvent(new CustomEvent('input', {
32
+ detail: {
33
+ id: 0,
34
+ type: 'arg',
35
+ key: 'description',
36
+ value: this.$input.value,
37
+ }
38
+ }));
39
+ });
40
+ this.$input.addEventListener('change', () => {
41
+ this.dispatchEvent(new CustomEvent('change', {
42
+ detail: {
43
+ id: 0,
44
+ type: 'arg',
45
+ key: 'description',
46
+ value: this.$input.value,
47
+ }
48
+ }));
49
+ });
50
+ }
51
+
52
+ render(changes: any) {
53
+ if (changes.fields) {
54
+ const field = this.fields.find((f: any) => f.key === 'description');
55
+ if (field) {
56
+ this.$input.value = field.value ?? '';
57
+ }
58
+ }
59
+ if (changes.x) {
60
+ this.$node.style.setProperty('left', `${this.x}rem`);
61
+ }
62
+ if (changes.y) {
63
+ this.$node.style.setProperty('top', `${this.y}rem`);
64
+ }
65
+ if (changes.width) {
66
+ this.$node.style.setProperty('--pg-node-width', `${this.width}rem`);
67
+ }
68
+ if (changes.height) {
69
+ this.$node.style.setProperty('--pg-node-height', `${this.height}rem`);
70
+ }
71
+ if (changes.debug) {
72
+ this.$node.classList.toggle('debug', this.debug);
73
+ }
74
+ if (this.#resizeElement) {
75
+ if (changes.x) this.#resizeElement.x = this.x;
76
+ if (changes.y) this.#resizeElement.y = this.y;
77
+ if (changes.width) this.#resizeElement.width = this.width;
78
+ if (changes.height) this.#resizeElement.height = this.height;
79
+ }
80
+ }
81
+
82
+ #handleSelect(_e: any) {
83
+ this.dispatchEvent(new CustomEvent('select', {
84
+ detail: {
85
+ nodeId: this.itemId,
86
+ }
87
+ }));
88
+ }
89
+
90
+ #resizeElement: PgNodeResize | null = null;
91
+ #handlePointerOver(_e: any) {
92
+ if (this.#resizeElement) {
93
+ this.#resizeElement.style.visibility = 'visible';
94
+ return;
95
+ }
96
+ // @ts-ignore
97
+ this.$node.style.anchorName = ANCHOR_NAME;
98
+ const ele = document.createElement('pg-node-resize') as PgNodeResize;
99
+ ele.addEventListener('pointerout', this.#handlePointerOut.bind(this));
100
+ ele.style.setProperty('position-anchor', ANCHOR_NAME);
101
+ ele.x = this.x;
102
+ ele.y = this.y;
103
+ ele.width = this.width;
104
+ ele.height = this.height;
105
+ ele.minHeight = this.getMinHeight();
106
+ ele.minWidth = this.getMinWidth();
107
+ ele.addEventListener('change', (e: any) => {
108
+ const { x, y, width, height } = e.detail;
109
+ this.x = x;
110
+ this.y = y;
111
+ this.width = width;
112
+ this.height = height;
113
+ ele.x = x;
114
+ ele.y = y;
115
+ ele.width = width;
116
+ ele.height = height;
117
+ this.dispatchEvent(new CustomEvent('change', { detail: { x, y, width, height } }));
118
+ });
119
+ ele.addEventListener('dragstart', () => {
120
+ this.dispatchEvent(new CustomEvent('nodedragstart', { detail: { nodeId: this.itemId } }));
121
+ });
122
+ ele.addEventListener('dragmove', (e: any) => {
123
+ this.dispatchEvent(new CustomEvent('nodedragmove', { detail: e.detail }));
124
+ });
125
+ ele.addEventListener('dragend', (e: any) => {
126
+ const { dx, dy, complete } = e.detail;
127
+ this.dispatchEvent(new CustomEvent('nodedragend', { detail: { nodeId: this.itemId } }));
128
+ // Only commit when the node actually landed on a new grid position.
129
+ if (!complete || (dx === 0 && dy === 0)) return;
130
+ this.x += dx;
131
+ this.y += dy;
132
+ this.dispatchEvent(new CustomEvent('change', {
133
+ detail: { type: 'transform', x: this.x, y: this.y, width: this.width, height: this.height, final: true },
134
+ }));
135
+ });
136
+ ele.addEventListener('select', this.#handleSelect.bind(this));
137
+ this.shadowRoot?.appendChild(ele);
138
+ this.#resizeElement = ele;
139
+ this.$node.classList.toggle('resize', true);
140
+ }
141
+
142
+ #handlePointerOut(_e: any) {
143
+ this.$node.classList.toggle('resize', false);
144
+ if (this.#resizeElement) {
145
+ this.#resizeElement.style.visibility = 'hidden';
146
+ }
147
+ }
148
+
149
+ select() {
150
+ this.$node.classList.toggle('selected', true);
151
+ }
152
+
153
+ deselect() {
154
+ this.$node.classList.toggle('selected', false);
155
+ }
156
+
157
+ getMinHeight() {
158
+ return 5;
159
+ }
160
+
161
+ getMinWidth() {
162
+ return 6;
163
+ }
164
+ }
@@ -0,0 +1,164 @@
1
+ import { Component, Prop, Part } from '@pictogrammers/element';
2
+
3
+ import template from './nodeEntry.html';
4
+ import style from './nodeEntry.css';
5
+ import PgNodeResize from '../nodeResize/nodeResize';
6
+
7
+ const ANCHOR_NAME = '--node-entry-resize-anchor';
8
+
9
+ @Component({
10
+ selector: 'pg-node-entry',
11
+ style,
12
+ template,
13
+ })
14
+ export default class PgNodeEntry extends HTMLElement {
15
+ @Prop() x: number = 0;
16
+ @Prop() y: number = 0;
17
+ @Prop() width: number = 12;
18
+ @Prop() height: number = 5;
19
+ @Prop() itemId: number = 0;
20
+ @Prop() fields: any = [];
21
+ @Prop() debug: boolean = false;
22
+
23
+ @Part() $node: HTMLDivElement;
24
+ @Part() $header: HTMLDivElement;
25
+ @Part() $input: HTMLTextAreaElement;
26
+
27
+ connectedCallback() {
28
+ this.height = this.getMinHeight();
29
+ this.$node.addEventListener('pointerover', this.#handlePointerOver.bind(this));
30
+ this.$input.addEventListener('input', () => {
31
+ this.dispatchEvent(new CustomEvent('input', {
32
+ detail: {
33
+ id: 0,
34
+ type: 'arg',
35
+ key: 'description',
36
+ value: this.$input.value,
37
+ }
38
+ }));
39
+ });
40
+ this.$input.addEventListener('change', () => {
41
+ this.dispatchEvent(new CustomEvent('change', {
42
+ detail: {
43
+ id: 0,
44
+ type: 'arg',
45
+ key: 'description',
46
+ value: this.$input.value,
47
+ }
48
+ }));
49
+ });
50
+ }
51
+
52
+ render(changes: any) {
53
+ if (changes.fields) {
54
+ const field = this.fields.find((f: any) => f.key === 'description');
55
+ if (field) {
56
+ this.$input.value = field.value ?? '';
57
+ }
58
+ }
59
+ if (changes.x) {
60
+ this.$node.style.setProperty('left', `${this.x}rem`);
61
+ }
62
+ if (changes.y) {
63
+ this.$node.style.setProperty('top', `${this.y}rem`);
64
+ }
65
+ if (changes.width) {
66
+ this.$node.style.setProperty('--pg-node-width', `${this.width}rem`);
67
+ }
68
+ if (changes.height) {
69
+ this.$node.style.setProperty('--pg-node-height', `${this.height}rem`);
70
+ }
71
+ if (changes.debug) {
72
+ this.$node.classList.toggle('debug', this.debug);
73
+ }
74
+ if (this.#resizeElement) {
75
+ if (changes.x) this.#resizeElement.x = this.x;
76
+ if (changes.y) this.#resizeElement.y = this.y;
77
+ if (changes.width) this.#resizeElement.width = this.width;
78
+ if (changes.height) this.#resizeElement.height = this.height;
79
+ }
80
+ }
81
+
82
+ #handleSelect(_e: any) {
83
+ this.dispatchEvent(new CustomEvent('select', {
84
+ detail: {
85
+ nodeId: this.itemId,
86
+ }
87
+ }));
88
+ }
89
+
90
+ #resizeElement: PgNodeResize | null = null;
91
+ #handlePointerOver(_e: any) {
92
+ if (this.#resizeElement) {
93
+ this.#resizeElement.style.visibility = 'visible';
94
+ return;
95
+ }
96
+ // @ts-ignore
97
+ this.$node.style.anchorName = ANCHOR_NAME;
98
+ const ele = document.createElement('pg-node-resize') as PgNodeResize;
99
+ ele.addEventListener('pointerout', this.#handlePointerOut.bind(this));
100
+ ele.style.setProperty('position-anchor', ANCHOR_NAME);
101
+ ele.x = this.x;
102
+ ele.y = this.y;
103
+ ele.width = this.width;
104
+ ele.height = this.height;
105
+ ele.minHeight = this.getMinHeight();
106
+ ele.minWidth = this.getMinWidth();
107
+ ele.addEventListener('change', (e: any) => {
108
+ const { x, y, width, height } = e.detail;
109
+ this.x = x;
110
+ this.y = y;
111
+ this.width = width;
112
+ this.height = height;
113
+ ele.x = x;
114
+ ele.y = y;
115
+ ele.width = width;
116
+ ele.height = height;
117
+ this.dispatchEvent(new CustomEvent('change', { detail: { x, y, width, height } }));
118
+ });
119
+ ele.addEventListener('dragstart', () => {
120
+ this.dispatchEvent(new CustomEvent('nodedragstart', { detail: { nodeId: this.itemId } }));
121
+ });
122
+ ele.addEventListener('dragmove', (e: any) => {
123
+ this.dispatchEvent(new CustomEvent('nodedragmove', { detail: e.detail }));
124
+ });
125
+ ele.addEventListener('dragend', (e: any) => {
126
+ const { dx, dy, complete } = e.detail;
127
+ this.dispatchEvent(new CustomEvent('nodedragend', { detail: { nodeId: this.itemId } }));
128
+ // Only commit when the node actually landed on a new grid position.
129
+ if (!complete || (dx === 0 && dy === 0)) return;
130
+ this.x += dx;
131
+ this.y += dy;
132
+ this.dispatchEvent(new CustomEvent('change', {
133
+ detail: { type: 'transform', x: this.x, y: this.y, width: this.width, height: this.height, final: true },
134
+ }));
135
+ });
136
+ ele.addEventListener('select', this.#handleSelect.bind(this));
137
+ this.shadowRoot?.appendChild(ele);
138
+ this.#resizeElement = ele;
139
+ this.$node.classList.toggle('resize', true);
140
+ }
141
+
142
+ #handlePointerOut(_e: any) {
143
+ this.$node.classList.toggle('resize', false);
144
+ if (this.#resizeElement) {
145
+ this.#resizeElement.style.visibility = 'hidden';
146
+ }
147
+ }
148
+
149
+ select() {
150
+ this.$node.classList.toggle('selected', true);
151
+ }
152
+
153
+ deselect() {
154
+ this.$node.classList.toggle('selected', false);
155
+ }
156
+
157
+ getMinHeight() {
158
+ return 5;
159
+ }
160
+
161
+ getMinWidth() {
162
+ return 6;
163
+ }
164
+ }
@@ -0,0 +1,75 @@
1
+ :host {
2
+ display: flex;
3
+ }
4
+
5
+ [part=input] {
6
+ border: 0;
7
+ border-top-left-radius: var(--pg-node-input-text-border-top-left-radius, 0.125rem);
8
+ border-top-right-radius: var(--pg-node-input-text-border-top-right-radius, 0.125rem);
9
+ border-bottom-left-radius: var(--pg-node-input-text-border-bottom-left-radius, 0.125rem);
10
+ border-bottom-right-radius: var(--pg-node-input-text-border-bottom-right-radius, 0.125rem);
11
+ padding-inline-start: 0.25rem;
12
+ padding-inline-end: 0.25rem;
13
+ padding-block-start: 0;
14
+ padding-block-end: 0;
15
+ font-family: var(--pg-input-text-font-family, var(--pg-font-family));
16
+ font-size: 0.75rem;
17
+ line-height: 1rem;
18
+ outline: none;
19
+ field-sizing: content;
20
+ min-width: calc(
21
+ 100%
22
+ - var(--pg-input-text-padding-inline-start, var(--pg-input-text-padding-inline, 0.25rem))
23
+ - var(--pg-input-text-padding-inline-end, var(--pg-input-text-padding-inline, 0.25rem))
24
+ );
25
+ background-color: #2B2B2B;
26
+ color: #FFF;
27
+ outline: 1px solid #444;
28
+ }
29
+
30
+ [part=input]:read-only {
31
+ border-color: transparent;
32
+ }
33
+
34
+ [part=input]:active {
35
+ outline-color: rgb(79, 143, 249, 0.75);
36
+ }
37
+
38
+ [part=input]:focus {
39
+ outline-color: rgb(79, 143, 249, 0.75);
40
+ z-index: 1;
41
+ }
42
+
43
+ [part=input]:hover + button:not(.hide),
44
+ [part=input]:focus + button:not(.hide) {
45
+ display: flex;
46
+ }
47
+
48
+ .hide {
49
+ display: none;
50
+ }
51
+
52
+ [part=input]:has(+ button:not(.hide):active) {
53
+ outline-color: #cd2626;
54
+ border-radius: 0.125rem;
55
+ z-index: 1;
56
+ }
57
+
58
+ [part=input] + [part=remove]:not(.hide):active {
59
+ color: #cd2626;
60
+ }
61
+
62
+ [part=remove] {
63
+ display: none;
64
+ background: transparent;
65
+ border: 0;
66
+ color: rgba(255, 255, 255, 0.5);
67
+ margin-left: -1rem;
68
+ padding: 0;
69
+ align-items: center;
70
+ z-index: 2;
71
+ }
72
+ [part=remove]:hover {
73
+ color: rgba(255, 255, 255, 0.8);
74
+ display: flex;
75
+ }
@@ -0,0 +1,4 @@
1
+ <input type="text" part="input" autocomplete="off">
2
+ <button part="remove" class="hide">
3
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14"><path fill="currentColor" d="M9.535 3.05a1 1 0 0 1 1.414 1.415L8.414 6.999l2.536 2.536a1 1 0 0 1-1.415 1.414L7 8.414 4.465 10.95A1.001 1.001 0 0 1 3.05 9.535L5.585 7 3.05 4.464A1 1 0 0 1 4.465 3.05L7 5.585z"/></svg>
4
+ </button>