@pictogrammers/components 0.4.9 → 0.5.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.
Files changed (182) hide show
  1. package/package.json +1 -1
  2. package/pg/annoy/annoy.css +1 -1
  3. package/pg/button/button.css +5 -4
  4. package/pg/buttonLink/buttonLink.css +1 -1
  5. package/pg/buttonMenu/__examples__/basic/basic.ts +2 -2
  6. package/pg/buttonMenu/buttonMenu.ts +4 -1
  7. package/pg/cardUser/cardUser.css +1 -1
  8. package/pg/database/__examples__/basic/basic.ts +0 -1
  9. package/pg/grid/__examples__/basic/basic.ts +1 -4
  10. package/pg/grid/grid.css +1 -1
  11. package/pg/header/header.css +1 -1
  12. package/pg/icon/__examples__/basic/basic.ts +1 -1
  13. package/pg/inputCheck/__examples__/basic/basic.ts +1 -1
  14. package/pg/inputCheck/inputCheck.css +5 -0
  15. package/pg/inputCheck/inputCheck.ts +4 -0
  16. package/pg/inputCheckList/__examples__/basic/basic.ts +1 -1
  17. package/pg/inputFileLocal/inputFileLocal.css +1 -1
  18. package/pg/inputNumber/README.md +27 -0
  19. package/pg/inputNumber/__examples__/basic/basic.html +9 -0
  20. package/pg/inputNumber/__examples__/basic/basic.ts +30 -0
  21. package/pg/inputNumber/inputNumber.css +34 -0
  22. package/pg/inputNumber/inputNumber.html +1 -0
  23. package/pg/inputNumber/inputNumber.spec.ts +59 -0
  24. package/pg/inputNumber/inputNumber.ts +63 -0
  25. package/pg/inputPixelEditor/README.md +211 -29
  26. package/pg/inputPixelEditor/__examples__/basic/basic.css +8 -0
  27. package/pg/inputPixelEditor/__examples__/basic/basic.html +29 -7
  28. package/pg/inputPixelEditor/__examples__/basic/basic.ts +274 -13
  29. package/pg/inputPixelEditor/__examples__/basic/constants.ts +62 -0
  30. package/pg/inputPixelEditor/inputPixelEditor.css +37 -2
  31. package/pg/inputPixelEditor/inputPixelEditor.html +22 -0
  32. package/pg/inputPixelEditor/inputPixelEditor.ts +819 -80
  33. package/pg/inputPixelEditor/utils/bitmapToMask.ts +22 -8
  34. package/pg/inputPixelEditor/utils/blobToImage.ts +11 -0
  35. package/pg/inputPixelEditor/utils/canvasToPngBuffer.ts +12 -0
  36. package/pg/inputPixelEditor/utils/constants.ts +55 -1
  37. package/pg/inputPixelEditor/utils/crc32.ts +116 -0
  38. package/pg/inputPixelEditor/utils/diffMap.ts +32 -0
  39. package/pg/inputPixelEditor/utils/generateGradient.ts +112 -0
  40. package/pg/inputPixelEditor/utils/getFloodFill.ts +83 -0
  41. package/pg/inputPixelEditor/utils/getGridColorIndexes.ts +13 -0
  42. package/pg/inputPixelEditor/utils/getOutline.ts +92 -0
  43. package/pg/inputPixelEditor/utils/inputMode.ts +7 -1
  44. package/pg/inputPixelEditor/utils/pixelSizes.ts +47 -0
  45. package/pg/inputPixelEditor/utils/pngMetadata.ts +487 -0
  46. package/pg/inputSelect/inputSelect.css +4 -4
  47. package/pg/inputText/inputText.css +14 -7
  48. package/pg/inputText/inputText.ts +5 -1
  49. package/pg/json/README.md +59 -0
  50. package/pg/json/__examples__/basic/basic.html +4 -0
  51. package/pg/json/__examples__/basic/basic.ts +31 -0
  52. package/pg/json/json.css +9 -0
  53. package/pg/json/json.html +1 -0
  54. package/pg/json/json.ts +124 -0
  55. package/pg/jsonArray/README.md +3 -0
  56. package/pg/jsonArray/jsonArray.css +15 -0
  57. package/pg/jsonArray/jsonArray.html +7 -0
  58. package/pg/jsonArray/jsonArray.ts +55 -0
  59. package/pg/jsonBoolean/README.md +3 -0
  60. package/pg/jsonBoolean/jsonBoolean.css +27 -0
  61. package/pg/jsonBoolean/jsonBoolean.html +5 -0
  62. package/pg/jsonBoolean/jsonBoolean.ts +69 -0
  63. package/pg/jsonNumber/README.md +3 -0
  64. package/pg/jsonNumber/jsonNumber.css +21 -0
  65. package/pg/jsonNumber/jsonNumber.html +5 -0
  66. package/pg/jsonNumber/jsonNumber.ts +42 -0
  67. package/pg/jsonObject/README.md +3 -0
  68. package/pg/jsonObject/jsonObject.css +11 -0
  69. package/pg/jsonObject/jsonObject.html +5 -0
  70. package/pg/jsonObject/jsonObject.ts +55 -0
  71. package/pg/jsonString/README.md +3 -0
  72. package/pg/jsonString/jsonString.css +21 -0
  73. package/pg/jsonString/jsonString.html +5 -0
  74. package/pg/jsonString/jsonString.ts +42 -0
  75. package/pg/menu/menu.ts +6 -5
  76. package/pg/menuItem/README.md +13 -2
  77. package/pg/menuItem/menuItem.css +17 -22
  78. package/pg/menuItem/menuItem.ts +8 -3
  79. package/pg/menuItemIcon/__examples__/basic/basic.html +1 -1
  80. package/pg/menuItemIcon/__examples__/basic/basic.ts +7 -0
  81. package/pg/menuItemIcon/menuItemIcon.css +18 -15
  82. package/pg/menuItemIcon/menuItemIcon.ts +8 -4
  83. package/pg/modification/__examples__/basic/basic.ts +1 -1
  84. package/pg/overlayMenu/overlayMenu.ts +6 -2
  85. package/pg/overlaySelectMenu/overlaySelectMenu.ts +6 -0
  86. package/pg/overlaySubMenu/overlaySubMenu.ts +6 -2
  87. package/pg/scroll/__examples__/basic/basic.ts +1 -1
  88. package/pg/search/search.css +1 -1
  89. package/pg/table/README.md +108 -0
  90. package/pg/table/__examples__/basic/basic.css +0 -0
  91. package/pg/table/__examples__/basic/basic.html +10 -0
  92. package/pg/table/__examples__/basic/basic.ts +111 -0
  93. package/pg/table/table.css +20 -0
  94. package/pg/table/table.html +6 -0
  95. package/pg/table/table.ts +86 -0
  96. package/pg/tableCellButtonIcon/README.md +3 -0
  97. package/pg/tableCellButtonIcon/tableCellButtonIcon.css +16 -0
  98. package/pg/tableCellButtonIcon/tableCellButtonIcon.html +5 -0
  99. package/pg/tableCellButtonIcon/tableCellButtonIcon.ts +34 -0
  100. package/pg/tableCellCheck/README.md +3 -0
  101. package/pg/tableCellCheck/tableCellCheck.css +15 -0
  102. package/pg/tableCellCheck/tableCellCheck.html +3 -0
  103. package/pg/tableCellCheck/tableCellCheck.ts +43 -0
  104. package/pg/tableCellNumber/README.md +3 -0
  105. package/pg/tableCellNumber/tableCellNumber.css +11 -0
  106. package/pg/tableCellNumber/tableCellNumber.html +3 -0
  107. package/pg/tableCellNumber/tableCellNumber.ts +40 -0
  108. package/pg/tableCellText/README.md +3 -0
  109. package/pg/tableCellText/tableCellText.css +11 -0
  110. package/pg/tableCellText/tableCellText.html +3 -0
  111. package/pg/tableCellText/tableCellText.ts +62 -0
  112. package/pg/tableColumn/README.md +3 -0
  113. package/pg/tableColumn/tableColumn.css +12 -0
  114. package/pg/tableColumn/tableColumn.html +1 -0
  115. package/pg/tableColumn/tableColumn.ts +29 -0
  116. package/pg/tableRow/README.md +3 -0
  117. package/pg/tableRow/tableRow.css +11 -0
  118. package/pg/tableRow/tableRow.html +1 -0
  119. package/pg/tableRow/tableRow.ts +77 -0
  120. package/pg/tabs/tabs.css +1 -1
  121. package/pg/tree/README.md +0 -3
  122. package/pg/tree/__examples__/basic/basic.ts +0 -1
  123. package/pg/treeItem/treeItem.css +3 -3
  124. package/favicon.svg +0 -20
  125. package/index.html +0 -321
  126. package/main.js +0 -2
  127. package/main.js.LICENSE.txt +0 -10
  128. package/pgAnnoy.js +0 -1
  129. package/pgApp.js +0 -1
  130. package/pgAvatar.js +0 -1
  131. package/pgButton.js +0 -1
  132. package/pgButtonGroup.js +0 -1
  133. package/pgButtonLink.js +0 -1
  134. package/pgButtonMenu.js +0 -1
  135. package/pgButtonToggle.js +0 -1
  136. package/pgCard.js +0 -1
  137. package/pgCardUser.js +0 -1
  138. package/pgColor.js +0 -1
  139. package/pgDatabase.js +0 -1
  140. package/pgDropdown.js +0 -1
  141. package/pgGrid.js +0 -1
  142. package/pgHeader.js +0 -1
  143. package/pgIcon.js +0 -1
  144. package/pgInputCheck.js +0 -1
  145. package/pgInputCheckList.js +0 -1
  146. package/pgInputFileLocal.js +0 -1
  147. package/pgInputHexRgb.js +0 -1
  148. package/pgInputPixelEditor.js +0 -1
  149. package/pgInputRange.js +0 -1
  150. package/pgInputSelect.js +0 -1
  151. package/pgInputText.js +0 -1
  152. package/pgInputTextIcon.js +0 -1
  153. package/pgInputUserSelect.js +0 -1
  154. package/pgListTag.js +0 -1
  155. package/pgMarkdown.js +0 -2
  156. package/pgMarkdown.js.LICENSE.txt +0 -10
  157. package/pgMenu.js +0 -1
  158. package/pgMenuDivider.js +0 -1
  159. package/pgMenuIcon.js +0 -1
  160. package/pgMenuItem.js +0 -1
  161. package/pgMenuItemIcon.js +0 -1
  162. package/pgModal.js +0 -1
  163. package/pgModalAlert.js +0 -1
  164. package/pgModification.js +0 -1
  165. package/pgNav.js +0 -1
  166. package/pgOverlay.js +0 -1
  167. package/pgOverlayContextMenu.js +0 -1
  168. package/pgOverlayMenu.js +0 -1
  169. package/pgOverlaySelectMenu.js +0 -1
  170. package/pgOverlaySubMenu.js +0 -1
  171. package/pgPicker.js +0 -1
  172. package/pgPreview.js +0 -1
  173. package/pgScroll.js +0 -1
  174. package/pgSearch.js +0 -1
  175. package/pgTab.js +0 -1
  176. package/pgTabs.js +0 -1
  177. package/pgToast.js +0 -1
  178. package/pgToasts.js +0 -1
  179. package/pgTooltip.js +0 -1
  180. package/pgTree.js +0 -1
  181. package/pgTreeButtonIcon.js +0 -1
  182. package/pgTreeItem.js +0 -1
@@ -1,10 +1,17 @@
1
1
  import { Component, Part } from '@pictogrammers/element';
2
2
  import PgInputPixelEditor from '../../inputPixelEditor';
3
+ import PgTable, { createTableItem } from '../../../table/table';
4
+ import PgTableCellButtonIcon from '../../../tableCellButtonIcon/tableCellButtonIcon';
3
5
  import { maskToBitmap } from '../../utils/maskToBitmap';
6
+ import { fileOk, patterns } from './constants';
4
7
 
5
8
  import template from './basic.html';
6
9
  import style from './basic.css';
7
10
 
11
+ const IconPicker = 'M19.35,11.72L17.22,13.85L15.81,12.43L8.1,20.14L3.5,22L2,20.5L3.86,15.9L11.57,8.19L10.15,6.78L12.28,4.65L19.35,11.72M16.76,3C17.93,1.83 19.83,1.83 21,3C22.17,4.17 22.17,6.07 21,7.24L19.08,9.16L14.84,4.92L16.76,3M5.56,17.03L4.5,19.5L6.97,18.44L14.4,11L13,9.6L5.56,17.03Z';
12
+ const IconTrash = 'M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z';
13
+ const IconLayerEdit = 'M4.63 10.27L3 9L12 2L19.94 8.17L12.5 15.61L12 16L4.63 10.27M10 18.94V18.11L10.59 17.53L10.63 17.5L4.62 12.81L3 14.07L10 19.5V18.94M21.7 12.58L20.42 11.3C20.21 11.09 19.86 11.09 19.65 11.3L18.65 12.3L20.7 14.35L21.7 13.35C21.91 13.14 21.91 12.79 21.7 12.58M12 21H14.06L20.11 14.93L18.06 12.88L12 18.94V21Z';
14
+
8
15
  @Component({
9
16
  selector: 'x-pg-input-pixel-editor-basic',
10
17
  style,
@@ -24,13 +31,26 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
24
31
  @Part() $reset: HTMLButtonElement;
25
32
  @Part() $clear: HTMLButtonElement;
26
33
  @Part() $invert: HTMLButtonElement;
34
+ @Part() $outline: HTMLButtonElement;
35
+ @Part() $glow: HTMLButtonElement;
36
+ @Part() $modeStamp1: HTMLButtonElement;
37
+ @Part() $modeStamp2: HTMLButtonElement;
38
+ @Part() $modeStamp3: HTMLButtonElement;
39
+ @Part() $modeStamp4: HTMLButtonElement;
27
40
  @Part() $modePixel: HTMLButtonElement;
28
41
  @Part() $modeLine: HTMLButtonElement;
29
42
  @Part() $modeRectangle: HTMLButtonElement;
30
43
  @Part() $modeRectangleOutline: HTMLButtonElement;
31
44
  @Part() $modeEllipse: HTMLButtonElement;
32
45
  @Part() $modeEllipseOutline: HTMLButtonElement;
46
+ @Part() $cursor: HTMLButtonElement;
47
+ @Part() $selectRectangle: HTMLButtonElement;
48
+ @Part() $selectEllipse: HTMLButtonElement;
49
+ @Part() $selectLasso: HTMLButtonElement;
50
+ @Part() $selectMagic: HTMLButtonElement;
33
51
 
52
+ @Part() $undo: HTMLButtonElement;
53
+ @Part() $redo: HTMLButtonElement;
34
54
  @Part() $save: HTMLButtonElement;
35
55
  @Part() $open: HTMLButtonElement;
36
56
  @Part() $output: HTMLPreElement;
@@ -38,9 +58,12 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
38
58
  @Part() $saveSvg: HTMLInputElement;
39
59
  @Part() $savePng: HTMLInputElement;
40
60
 
41
- // MAKE A LIST COMPONENT!!!! [text | delete]
42
- @Part() $colors: HTMLPreElement;
43
- @Part() $layers: HTMLPreElement;
61
+ @Part() $addLayer: HTMLButtonElement;
62
+ @Part() $addLayerReference: HTMLButtonElement;
63
+ @Part() $addColor: HTMLButtonElement;
64
+
65
+ @Part() $colors: PgTable;
66
+ @Part() $layers: PgTable;
44
67
 
45
68
  connectedCallback() {
46
69
  this.$width.value = '10';
@@ -53,6 +76,19 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
53
76
  this.$transparent.addEventListener('input', this.handleTransparentChange.bind(this));
54
77
  this.$input.addEventListener('input', this.handleInput.bind(this));
55
78
  this.$input.addEventListener('debug', this.handleDebug.bind(this));
79
+ this.$input.addEventListener('selectlayer', this.handleSelectLayer.bind(this));
80
+ this.$input.addEventListener('reference', this.handleReference.bind(this));
81
+ [
82
+ this.$modeStamp1,
83
+ this.$modeStamp2,
84
+ this.$modeStamp3,
85
+ this.$modeStamp4,
86
+ ].forEach(($modeStamp) => {
87
+ $modeStamp.addEventListener('click', (e: any) => {
88
+ const stamp = e.target.dataset.stamp;
89
+ this.$input.inputModeStamp(patterns[stamp]);
90
+ });
91
+ });
56
92
  this.$modePixel.addEventListener('click', () => {
57
93
  this.$input.inputModePixel();
58
94
  });
@@ -71,6 +107,21 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
71
107
  this.$modeEllipseOutline.addEventListener('click', () => {
72
108
  this.$input.inputModeEllipseOutline();
73
109
  });
110
+ this.$cursor.addEventListener('click', () => {
111
+ this.$input.inputModeCursor();
112
+ })
113
+ this.$selectRectangle.addEventListener('click', () => {
114
+ this.$input.inputModeSelectRectangle();
115
+ });
116
+ this.$selectEllipse.addEventListener('click', () => {
117
+ this.$input.inputModeSelectEllipse();
118
+ });
119
+ this.$selectLasso.addEventListener('click', () => {
120
+ this.$input.inputModeSelectLasso();
121
+ });
122
+ this.$selectMagic.addEventListener('click', () => {
123
+ this.$input.inputModeSelectMagicWand();
124
+ });
74
125
  this.$reset.addEventListener('click', () => {
75
126
  this.$input.reset();
76
127
  });
@@ -80,13 +131,19 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
80
131
  this.$invert.addEventListener('click', () => {
81
132
  this.$input.invert();
82
133
  });
134
+ this.$outline.addEventListener('click', () => {
135
+ this.$input.outline();
136
+ });
137
+ this.$glow.addEventListener('click', () => {
138
+ this.$input.glow();
139
+ });
83
140
  this.$save.addEventListener('click', async () => {
84
- const json = await this.$input.save();
141
+ const json = await this.$input.getJson();
85
142
  this.$output.textContent = JSON.stringify(json, null, 4);
86
143
  });
87
144
  this.$open.addEventListener('click', () => {
88
145
  const json = JSON.parse(this.$output.textContent || '');
89
- this.$input.open(json as any);
146
+ this.$input.setJson(json as any);
90
147
  });
91
148
  this.$file.addEventListener('change', this.handleFile.bind(this));
92
149
  this.$saveSvg.addEventListener('click', async () => {
@@ -96,7 +153,7 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
96
153
  suggestedName: 'Canvas',
97
154
  types: [{
98
155
  description: 'SVG Document',
99
- accept: {'image/svg+xml': ['.svg']},
156
+ accept: { 'image/svg+xml': ['.svg'] },
100
157
  }],
101
158
  });
102
159
  const writable = await handle.createWritable();
@@ -114,18 +171,197 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
114
171
  const handle = await window.showSaveFilePicker({
115
172
  suggestedName: 'CanvasName',
116
173
  types: [{
117
- description: 'SVG Document',
118
- accept: {'image/svg+xml': ['.svg']},
174
+ description: 'PNG Image',
175
+ accept: { 'image/png': ['.png'] },
119
176
  }],
120
177
  });
121
178
  const writable = await handle.createWritable();
122
- await writable.write('something');
123
- await writable.write
179
+ const image = await this.$input.getExportPng();
180
+ await writable.write(image);
124
181
  await writable.close();
125
182
  } catch (e: any) {
126
183
  // no save
127
184
  }
128
185
  });
186
+ // Layers
187
+ this.$layers.columns = [{
188
+ label: 'Name',
189
+ key: 'name',
190
+ }, {
191
+ label: 'Type',
192
+ key: 'type',
193
+ }, {
194
+ label: 'Selected',
195
+ key: 'selected',
196
+ hideLabel: true,
197
+ }, {
198
+ label: 'Select',
199
+ key: 'select',
200
+ hideLabel: true,
201
+ }];
202
+ this.$layers.data = [
203
+ createTableItem({
204
+ name: 'Layer 1',
205
+ type: 'pixel',
206
+ selected: true,
207
+ select: {
208
+ type: PgTableCellButtonIcon,
209
+ icon: IconLayerEdit,
210
+ value: this.$layers.data.length,
211
+ }
212
+ })
213
+ ];
214
+ this.$layers.addEventListener('action', (e: any) => {
215
+ const { getColumn, getRows, key, index } = e.detail;
216
+ switch (key) {
217
+ case 'select':
218
+ const selectedLayers: number[] = [];
219
+ getRows().forEach(({ getColumn, index: index2 }) => {
220
+ if (getColumn('selected').value) {
221
+ selectedLayers.push(index2);
222
+ }
223
+ });
224
+ if (
225
+ selectedLayers.length === 1
226
+ && selectedLayers[0] === index
227
+ ) {
228
+ // ignore
229
+ } else {
230
+ const currentValue = getColumn('selected').value;
231
+ getColumn('selected').value = !currentValue;
232
+ if (currentValue) {
233
+ selectedLayers.splice(selectedLayers.findIndex(x => x === index), 1);
234
+ } else {
235
+ selectedLayers.push(index);
236
+ }
237
+ }
238
+ console.log('selected', selectedLayers);
239
+ this.$input.selectLayers(selectedLayers);
240
+ break;
241
+ }
242
+ });
243
+ this.$addLayer.addEventListener('click', () => {
244
+ this.$layers.data.push(
245
+ createTableItem({
246
+ name: 'Layer 2',
247
+ type: 'pixel',
248
+ selected: false,
249
+ select: {
250
+ type: PgTableCellButtonIcon,
251
+ icon: IconLayerEdit,
252
+ value: 1,
253
+ }
254
+ })
255
+ );
256
+ this.$input.addLayer();
257
+ });
258
+ this.$addLayerReference.addEventListener('click', () => {
259
+ this.$layers.data.push(
260
+ createTableItem({
261
+ name: 'Layer 2',
262
+ type: 'reference',
263
+ selected: false,
264
+ select: {
265
+ type: PgTableCellButtonIcon,
266
+ icon: IconLayerEdit,
267
+ value: 1,
268
+ }
269
+ })
270
+ );
271
+ this.$input.addLayer();
272
+ });
273
+ // Colors
274
+ this.$colors.columns = [{
275
+ label: 'Red',
276
+ key: 'r',
277
+ editable: true,
278
+ }, {
279
+ label: 'Green',
280
+ key: 'g',
281
+ editable: true,
282
+ }, {
283
+ label: 'Blue',
284
+ key: 'b',
285
+ editable: true,
286
+ }, {
287
+ label: 'Alpha',
288
+ key: 'a',
289
+ editable: true,
290
+ }, {
291
+ label: 'Selected',
292
+ key: 'selected',
293
+ hideLabel: true,
294
+ }, {
295
+ label: 'Select',
296
+ key: 'select',
297
+ hideLabel: true,
298
+ }, {
299
+ label: 'Delete',
300
+ key: 'delete',
301
+ hideLabel: true,
302
+ }];
303
+ this.$colors.data.push(...this.$input.getColors().map(([r, g, b, a], i) => {
304
+ return createTableItem({
305
+ r,
306
+ g,
307
+ b,
308
+ a,
309
+ selected: i === 1,
310
+ select: {
311
+ type: PgTableCellButtonIcon,
312
+ icon: IconPicker,
313
+ value: i,
314
+ },
315
+ delete: {
316
+ type: PgTableCellButtonIcon,
317
+ icon: IconTrash,
318
+ value: i,
319
+ }
320
+ });
321
+ }));
322
+ this.$colors.addEventListener('action', (e: any) => {
323
+ const { getColumn, getRows, key, value, index } = e.detail;
324
+ const [r, g, b, a] = this.$input.getColor(index);
325
+ switch (key) {
326
+ case 'select':
327
+ getRows().forEach(({ getColumn }) => {
328
+ getColumn('selected').value = false;
329
+ });
330
+ getColumn('selected').value = true;
331
+ this.$input.selectColor(getColumn('select').value);
332
+ break;
333
+ case 'r':
334
+ this.$input.setColor(index, value, g, b, a);
335
+ break;
336
+ case 'g':
337
+ this.$input.setColor(index, r, value, b, a);
338
+ break;
339
+ case 'b':
340
+ this.$input.setColor(index, r, g, value, a);
341
+ break;
342
+ case 'a':
343
+ this.$input.setColor(index, r, g, b, value);
344
+ break;
345
+ }
346
+ });
347
+ this.$addColor.addEventListener('click', () => {
348
+ this.$colors.data.push(createTableItem({
349
+ r: 5,
350
+ g: 5,
351
+ b: 5,
352
+ a: 1,
353
+ selected: false,
354
+ select: {
355
+ type: PgTableCellButtonIcon,
356
+ icon: IconPicker,
357
+ value: this.$colors.data.length,
358
+ },
359
+ delete: {
360
+ type: PgTableCellButtonIcon,
361
+ icon: IconTrash
362
+ }
363
+ }));
364
+ });
129
365
  }
130
366
 
131
367
  handleFile(e) {
@@ -133,7 +369,7 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
133
369
  if (files.length !== 1) {
134
370
  throw new Error('select only 1 file');
135
371
  }
136
- switch(files[0].type) {
372
+ switch (files[0].type) {
137
373
  case 'image/svg+xml':
138
374
  // Read the file
139
375
  const reader = new FileReader();
@@ -159,8 +395,9 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
159
395
  }
160
396
 
161
397
  handleChange(e: CustomEvent) {
162
- const { value } = e.detail;
163
- this.$value1.textContent = value.join('--');
398
+ this.$value1.textContent = this.$input.getLayerPaths().map((layer) => {
399
+ return layer.map(x => x.join('=')).join(';');
400
+ }).join('\n');
164
401
  }
165
402
 
166
403
  handleInput(e: CustomEvent) {
@@ -179,6 +416,30 @@ export default class XPgInputPixelEditorBasic extends HTMLElement {
179
416
  //context.strokeRect(x, y, width, height);
180
417
  }
181
418
 
419
+ handleSelectLayer(e: CustomEvent) {
420
+ const { color, index } = e.detail;
421
+ if (index !== null) {
422
+ // Update Table
423
+ this.$layers.data.forEach((layer) => {
424
+ layer.items.find(column => column.key === 'selected').value = false;
425
+ });
426
+ this.$layers.data[index].items.find(column => column.key === 'selected').value = true;
427
+ // Update input
428
+ this.$input.selectLayers([index]);
429
+ }
430
+ }
431
+
432
+ handleReference(e: any) {
433
+ const { id, callback } = e.detail;
434
+ // Test Data
435
+ const mock = new Map();
436
+ mock.set('9ee82807-ffa9-411c-abaf-7b8d46d74af4', fileOk);
437
+ if (mock.has(id)) {
438
+ callback(mock.get(id));
439
+ }
440
+ console.error('Unable to load', id);
441
+ }
442
+
182
443
  handleWidthChange(e) {
183
444
  this.$input.width = e.target.value;
184
445
  this.$debug.innerHTML = '';
@@ -0,0 +1,62 @@
1
+ export const patterns = {
2
+ '1': [
3
+ [0, 0]
4
+ ],
5
+ '3-circle': [
6
+ [0, -1],
7
+ [-1, 0],
8
+ [0, 0],
9
+ [1, 0],
10
+ [0, 1]
11
+ ],
12
+ '3-square': [
13
+ [-1, -1],
14
+ [0, -1],
15
+ [1, -1],
16
+ [-1, 0],
17
+ [0, 0],
18
+ [1, 0],
19
+ [-1, 1],
20
+ [0, 1],
21
+ [1, 1],
22
+ ],
23
+ 'heart': [
24
+ [-1, -1],
25
+ [1, -1],
26
+ [-2, 0],
27
+ [-1, 0],
28
+ [0, 0],
29
+ [1, 0],
30
+ [2, 0],
31
+ [-1, 1],
32
+ [0, 1],
33
+ [1, 1],
34
+ [0, 2],
35
+ ]
36
+ };
37
+
38
+ export const fileOk = {
39
+ "id": "9ee82807-ffa9-411c-abaf-7b8d46d74af4",
40
+ "width": 9,
41
+ "height": 6,
42
+ "transparent": null,
43
+ "colors": [
44
+ [0, 0, 0, 0],
45
+ [0, 0, 0, 1]
46
+ ],
47
+ "layers": [
48
+ {
49
+ "name": "Ok",
50
+ "exclude": false,
51
+ "locked": false,
52
+ "hidden": false,
53
+ "type": "pixel",
54
+ "opacity": 1
55
+ }
56
+ ],
57
+ "data": [
58
+ [
59
+ [1, "M2,4H3V2H2ZM3,5H2V4H1V2H2V1H3V2H4V4H3ZM8,5H7V4H6V5H5V1H6V3H7V2H8V3H7V4H8Z"]
60
+ ]
61
+ ]
62
+ };
@@ -3,12 +3,14 @@
3
3
  }
4
4
 
5
5
  [part="wrapper"] {
6
- display: flex;
6
+ display: grid;
7
+ grid-template-columns: auto;
8
+ grid-template-rows: auto;
7
9
  position: relative;
8
10
  outline: 0;
9
11
  }
10
12
 
11
- [part="wrapper"]:focus-visible::before {
13
+ [part="wrapper"]:not(.ignore):focus-visible::before {
12
14
  pointer-events: none;
13
15
  content: '';
14
16
  position: absolute;
@@ -21,7 +23,40 @@
21
23
  }
22
24
 
23
25
  canvas {
26
+ grid-column: 1;
27
+ grid-row: 1;
24
28
  touch-action: none;
25
29
  user-select: none;
26
30
  outline: 0;
31
+ }
32
+
33
+ svg {
34
+ pointer-events: none;
35
+ grid-column: 1;
36
+ grid-row: 1;
37
+ }
38
+
39
+ path {
40
+ fill: none;
41
+ stroke: #000;
42
+ stroke-width: 1px;
43
+ vector-effect: non-scaling-stroke;
44
+ stroke-dasharray: 5px;
45
+ animation: stroke 0.4s linear infinite;
46
+ shape-rendering: geometricPrecision;
47
+ stroke-dashoffset: 10px;
48
+ }
49
+
50
+ path.preview {
51
+ stroke: rgb(0 96 255);
52
+ }
53
+
54
+ path.hide {
55
+ display: none;
56
+ }
57
+
58
+ @keyframes stroke {
59
+ to {
60
+ stroke-dashoffset: 0;
61
+ }
27
62
  }
@@ -1,3 +1,25 @@
1
1
  <div part="wrapper" tabindex="0">
2
2
  <canvas part="canvas" draggable="false"></canvas>
3
+ <svg part="selection" viewBox="0 0 10 10">
4
+ <defs>
5
+ <filter id="whiteOutline" x="-50%" y="-50%" width="200%" height="200%">
6
+ <!-- Thicken the source graphic (the original stroke path) -->
7
+ <feMorphology in="SourceGraphic" operator="dilate" radius="1" result="dilated" />
8
+
9
+ <!-- Flood the dilated shape with white color -->
10
+ <feFlood flood-color="white" result="flood" />
11
+
12
+ <!-- Composite the white color with the dilated shape to create the white outline shape -->
13
+ <feComposite in="flood" in2="dilated" operator="in" result="whiteOutlineShape" />
14
+
15
+ <!-- Merge the white outline shape with the original source graphic -->
16
+ <feMerge>
17
+ <feMergeNode in="whiteOutlineShape" />
18
+ <feMergeNode in="SourceGraphic" />
19
+ </feMerge>
20
+ </filter>
21
+ </defs>
22
+ <path part="selectionPath" class="hide" d="M9,7H1V1H9Z" filter="url(#whiteOutline)" />
23
+ <path part="selectionPathPreview" class="hide preview" d="M9,7H1V1H9Z" filter="url(#whiteOutline)" />
24
+ </svg>
3
25
  </div>