@pictogrammers/components 0.3.2 → 0.4.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/README.md +11 -12
- package/favicon.svg +20 -0
- package/index.html +67 -49
- package/main.js +2 -0
- package/main.js.LICENSE.txt +10 -0
- package/package.json +6 -6
- package/pg/annoy/README.md +0 -5
- package/pg/annoy/__examples__/basic/basic.css +3 -0
- package/pg/annoy/__examples__/basic/basic.html +4 -7
- package/pg/annoy/__examples__/basic/basic.ts +3 -1
- package/pg/annoy/annoy.css +29 -198
- package/pg/annoy/annoy.html +5 -56
- package/pg/annoy/annoy.ts +4 -25
- package/pg/app/README.md +11 -0
- package/pg/app/__examples__/basic/basic.css +8 -0
- package/pg/app/__examples__/basic/basic.html +15 -0
- package/pg/app/__examples__/basic/basic.ts +13 -0
- package/pg/app/app.css +108 -0
- package/pg/app/app.html +16 -0
- package/pg/app/app.ts +45 -0
- package/pg/app/index.ts +3 -0
- package/pg/avatar/__examples__/basic/basic.ts +5 -3
- package/pg/button/README.md +3 -0
- package/pg/button/button.css +13 -12
- package/pg/button/button.spec.ts +35 -0
- package/pg/button/button.ts +17 -12
- package/pg/buttonLink/buttonLink.css +3 -2
- package/pg/buttonMenu/README.md +54 -0
- package/pg/buttonMenu/__examples__/basic/basic.html +6 -0
- package/pg/buttonMenu/__examples__/basic/basic.ts +43 -0
- package/pg/buttonMenu/buttonMenu.css +12 -0
- package/pg/buttonMenu/buttonMenu.html +4 -0
- package/pg/buttonMenu/buttonMenu.ts +63 -0
- package/pg/buttonMenu/index.ts +3 -0
- package/pg/buttonToggle/__examples__/basic/basic.ts +2 -2
- package/pg/buttonToggle/__examples__/persist/persist.html +10 -0
- package/pg/buttonToggle/__examples__/persist/persist.ts +35 -0
- package/pg/cardUser/__examples__/basic/basic.ts +0 -1
- package/pg/cardUser/cardUser.css +2 -10
- package/pg/cardUser/cardUser.html +0 -5
- package/pg/cardUser/cardUser.ts +0 -6
- package/pg/database/README.md +1 -1
- package/pg/database/__examples__/basic/basic.html +2 -1
- package/pg/database/__examples__/basic/basic.ts +3 -3
- package/pg/dropdown/dropdown.ts +0 -19
- package/pg/grid/__examples__/basic/basic.html +2 -2
- package/pg/grid/__examples__/basic/basic.ts +3 -2
- package/pg/grid/grid.ts +0 -1
- package/pg/icon/README.md +6 -5
- package/pg/icon/__examples__/basic/basic.html +2 -2
- package/pg/icon/__examples__/basic/basic.ts +1 -1
- package/pg/icon/icon.ts +6 -0
- package/pg/inputCheckList/__examples__/basic/basic.ts +5 -5
- package/pg/inputCheckList/inputCheckList.ts +2 -0
- package/pg/inputFileLocal/inputFileLocal.css +3 -2
- package/pg/inputPixelEditor/README.md +132 -0
- package/pg/inputPixelEditor/__examples__/basic/basic.css +29 -0
- package/pg/inputPixelEditor/__examples__/basic/basic.html +63 -0
- package/pg/inputPixelEditor/__examples__/basic/basic.ts +200 -0
- package/pg/inputPixelEditor/__examples__/basic/openUtils.ts +41 -0
- package/pg/inputPixelEditor/__examples__/basic/saveUtil.ts +35 -0
- package/pg/inputPixelEditor/index.ts +3 -0
- package/pg/inputPixelEditor/inputPixelEditor.css +27 -0
- package/pg/inputPixelEditor/inputPixelEditor.html +3 -0
- package/pg/inputPixelEditor/inputPixelEditor.ts +839 -0
- package/pg/inputPixelEditor/utils/bitmapToMask.ts +202 -0
- package/pg/inputPixelEditor/utils/cloneGrid.ts +17 -0
- package/pg/inputPixelEditor/utils/constants.ts +1 -0
- package/pg/inputPixelEditor/utils/createLayer.ts +8 -0
- package/pg/inputPixelEditor/utils/debounce.ts +5 -0
- package/pg/inputPixelEditor/utils/diffGrid.ts +26 -0
- package/pg/inputPixelEditor/utils/fillGrid.ts +11 -0
- package/pg/inputPixelEditor/utils/getEllipseOutlinePixels.ts +105 -0
- package/pg/inputPixelEditor/utils/getEllipsePixels.ts +28 -0
- package/pg/inputPixelEditor/utils/getGuides.ts +232 -0
- package/pg/inputPixelEditor/utils/getLinePixels.ts +18 -0
- package/pg/inputPixelEditor/utils/getRectangleOutlinePixels.ts +20 -0
- package/pg/inputPixelEditor/utils/getRectanglePixels.ts +15 -0
- package/pg/inputPixelEditor/utils/inputMode.ts +8 -0
- package/pg/inputPixelEditor/utils/interateGrid.ts +7 -0
- package/pg/inputPixelEditor/utils/isEmptyGrid.ts +3 -0
- package/pg/inputPixelEditor/utils/maskToBitmap.ts +66 -0
- package/pg/inputRange/__examples__/basic/basic.ts +4 -4
- package/pg/inputRange/inputRange.ts +6 -4
- package/pg/inputSelect/README.md +1 -1
- package/pg/inputSelect/__examples__/basic/basic.ts +7 -5
- package/pg/inputSelect/inputSelect.css +15 -12
- package/pg/inputSelect/inputSelect.html +3 -3
- package/pg/inputSelect/inputSelect.ts +33 -30
- package/pg/inputText/__examples__/basic/basic.ts +6 -6
- package/pg/inputText/inputText.css +1 -0
- package/pg/inputUserSelect/README.md +1 -1
- package/pg/inputUserSelect/inputUserSelect.ts +1 -1
- package/pg/listTag/__examples__/basic/basic.ts +4 -5
- package/pg/markdown/README.md +17 -3
- package/pg/markdown/__examples__/basic/basic.ts +2 -2
- package/pg/markdown/__examples__/basic/constants.ts +1 -1
- package/pg/markdown/markdown.css +11 -0
- package/pg/menu/README.md +46 -0
- package/pg/menu/__examples__/basic/basic.html +6 -0
- package/pg/menu/__examples__/basic/basic.ts +46 -0
- package/pg/menu/index.ts +3 -0
- package/pg/menu/menu.css +19 -0
- package/pg/menu/menu.html +1 -0
- package/pg/menu/menu.ts +119 -0
- package/pg/menuDivider/README.md +7 -0
- package/pg/menuDivider/__examples__/basic/basic.html +3 -0
- package/pg/menuDivider/__examples__/basic/basic.ts +28 -0
- package/pg/menuDivider/index.ts +3 -0
- package/pg/menuDivider/menuDivider.css +9 -0
- package/pg/menuDivider/menuDivider.html +1 -0
- package/pg/menuDivider/menuDivider.ts +22 -0
- package/pg/menuIcon/menuIcon.ts +43 -36
- package/pg/menuItem/README.md +32 -0
- package/pg/menuItem/__examples__/basic/basic.html +26 -0
- package/pg/menuItem/__examples__/basic/basic.ts +41 -0
- package/pg/menuItem/index.ts +3 -0
- package/pg/menuItem/menuItem.css +97 -0
- package/pg/menuItem/menuItem.html +1 -0
- package/pg/menuItem/menuItem.ts +77 -0
- package/pg/menuItemIcon/README.md +32 -0
- package/pg/menuItemIcon/__examples__/basic/basic.html +34 -0
- package/pg/menuItemIcon/__examples__/basic/basic.ts +55 -0
- package/pg/menuItemIcon/index.ts +3 -0
- package/pg/menuItemIcon/menuItemIcon.css +106 -0
- package/pg/menuItemIcon/menuItemIcon.html +4 -0
- package/pg/menuItemIcon/menuItemIcon.ts +156 -0
- package/pg/modalAlert/__examples__/basic/basic.ts +1 -1
- package/pg/modalAlert/modalAlert.css +1 -4
- package/pg/modalAlert/modalAlert.ts +18 -4
- package/pg/modification/__examples__/basic/basic.ts +1 -2
- package/pg/modification/__examples__/basic/constants.ts +25 -50
- package/pg/modification/modification.ts +1 -1
- package/pg/overlay/overlay.ts +13 -12
- package/pg/overlayContextMenu/README.md +35 -0
- package/pg/overlayContextMenu/__examples__/basic/basic.css +23 -0
- package/pg/overlayContextMenu/__examples__/basic/basic.html +7 -0
- package/pg/overlayContextMenu/__examples__/basic/basic.ts +87 -0
- package/pg/overlayContextMenu/index.ts +3 -0
- package/pg/overlayContextMenu/overlayContextMenu.css +16 -0
- package/pg/overlayContextMenu/overlayContextMenu.html +3 -0
- package/pg/overlayContextMenu/overlayContextMenu.ts +98 -0
- package/pg/overlayMenu/README.md +33 -0
- package/pg/overlayMenu/__examples__/basic/basic.css +3 -0
- package/pg/overlayMenu/__examples__/basic/basic.html +5 -0
- package/pg/overlayMenu/__examples__/basic/basic.ts +62 -0
- package/pg/overlayMenu/index.ts +3 -0
- package/pg/overlayMenu/overlayMenu.css +16 -0
- package/pg/overlayMenu/overlayMenu.html +3 -0
- package/pg/overlayMenu/overlayMenu.ts +67 -0
- package/pg/overlaySelectMenu/README.md +33 -0
- package/pg/overlaySelectMenu/__examples__/basic/basic.css +3 -0
- package/pg/overlaySelectMenu/__examples__/basic/basic.html +5 -0
- package/pg/overlaySelectMenu/__examples__/basic/basic.ts +62 -0
- package/pg/overlaySelectMenu/index.ts +3 -0
- package/pg/overlaySelectMenu/overlaySelectMenu.css +17 -0
- package/pg/overlaySelectMenu/overlaySelectMenu.html +3 -0
- package/pg/overlaySelectMenu/overlaySelectMenu.ts +96 -0
- package/pg/overlaySubMenu/README.md +35 -0
- package/pg/overlaySubMenu/index.ts +3 -0
- package/pg/overlaySubMenu/overlaySubMenu.css +27 -0
- package/pg/overlaySubMenu/overlaySubMenu.html +3 -0
- package/pg/overlaySubMenu/overlaySubMenu.ts +103 -0
- package/pg/picker/picker.ts +1 -19
- package/pg/scroll/__examples__/basic/basic.ts +1 -1
- package/pg/search/__examples__/basic/basic.ts +10 -7
- package/pg/search/search.css +2 -2
- package/pg/shared/models/user.ts +0 -2
- package/pg/tab/tab.ts +0 -10
- package/pg/tabs/partials/tab.css +42 -0
- package/pg/tabs/partials/tab.ts +70 -0
- package/pg/tabs/tabs.css +0 -53
- package/pg/tabs/tabs.ts +54 -70
- package/pg/toast/README.md +35 -6
- package/pg/toast/__examples__/basic/basic.html +7 -0
- package/pg/toast/__examples__/basic/basic.ts +76 -0
- package/pg/toast/toast.css +3 -0
- package/pg/toast/toast.ts +20 -4
- package/pg/tooltip/addTooltip.ts +3 -1
- package/pg/tooltip/tooltip.ts +1 -1
- package/pg/tree/README.md +67 -0
- package/pg/tree/__examples__/basic/basic.html +10 -0
- package/pg/tree/__examples__/basic/basic.ts +162 -0
- package/pg/tree/index.ts +3 -0
- package/pg/tree/tree.css +28 -0
- package/pg/tree/tree.html +1 -0
- package/pg/tree/tree.ts +217 -0
- package/pg/treeButtonIcon/README.md +39 -0
- package/pg/treeButtonIcon/index.ts +3 -0
- package/pg/treeButtonIcon/treeButtonIcon.css +18 -0
- package/pg/treeButtonIcon/treeButtonIcon.html +3 -0
- package/pg/treeButtonIcon/treeButtonIcon.ts +42 -0
- package/pg/treeItem/README.md +3 -0
- package/pg/treeItem/index.ts +3 -0
- package/pg/treeItem/treeItem.css +263 -0
- package/pg/treeItem/treeItem.html +16 -0
- package/pg/treeItem/treeItem.ts +558 -0
- package/pgAnnoy.js +1 -0
- package/pgApp.js +1 -0
- package/pgAvatar.js +1 -0
- package/pgButton.js +1 -0
- package/pgButtonGroup.js +1 -0
- package/pgButtonLink.js +1 -0
- package/pgButtonMenu.js +1 -0
- package/pgButtonToggle.js +1 -0
- package/pgCard.js +1 -0
- package/pgCardUser.js +1 -0
- package/pgColor.js +1 -0
- package/pgDatabase.js +1 -0
- package/pgDropdown.js +1 -0
- package/pgGrid.js +1 -0
- package/pgHeader.js +1 -0
- package/pgIcon.js +1 -0
- package/pgInputCheck.js +1 -0
- package/pgInputCheckList.js +1 -0
- package/pgInputFileLocal.js +1 -0
- package/pgInputHexRgb.js +1 -0
- package/pgInputPixelEditor.js +1 -0
- package/pgInputRange.js +1 -0
- package/pgInputSelect.js +1 -0
- package/pgInputText.js +1 -0
- package/pgInputTextIcon.js +1 -0
- package/pgInputUserSelect.js +1 -0
- package/pgListTag.js +1 -0
- package/pgMarkdown.js +2 -0
- package/pgMarkdown.js.LICENSE.txt +10 -0
- package/pgMenu.js +1 -0
- package/pgMenuDivider.js +1 -0
- package/pgMenuIcon.js +1 -0
- package/pgMenuItem.js +1 -0
- package/pgMenuItemIcon.js +1 -0
- package/pgModalAlert.js +1 -0
- package/pgModification.js +1 -0
- package/pgNav.js +1 -0
- package/pgOverlay.js +1 -0
- package/pgOverlayContextMenu.js +1 -0
- package/pgOverlayMenu.js +1 -0
- package/pgOverlaySelectMenu.js +1 -0
- package/pgOverlaySubMenu.js +1 -0
- package/pgPicker.js +1 -0
- package/pgPreview.js +1 -0
- package/pgScroll.js +1 -0
- package/pgSearch.js +1 -0
- package/pgTab.js +1 -0
- package/pgTabs.js +1 -0
- package/pgToast.js +1 -0
- package/pgToasts.js +1 -0
- package/pgTooltip.js +1 -0
- package/pgTree.js +1 -0
- package/pgTreeButtonIcon.js +1 -0
- package/pgTreeItem.js +1 -0
- package/theme-ui3.css +31 -0
- package/@types/css.d.ts +0 -4
- package/@types/html.d.ts +0 -4
- package/dist/main.js +0 -3819
- package/dist/pgAnnoy.js +0 -116
- package/dist/pgAvatar.js +0 -136
- package/dist/pgButton.js +0 -116
- package/dist/pgButtonGroup.js +0 -116
- package/dist/pgButtonLink.js +0 -116
- package/dist/pgButtonToggle.js +0 -146
- package/dist/pgCard.js +0 -116
- package/dist/pgCardUser.js +0 -196
- package/dist/pgColor.js +0 -136
- package/dist/pgDatabase.js +0 -236
- package/dist/pgDropdown.js +0 -686
- package/dist/pgGrid.js +0 -126
- package/dist/pgHeader.js +0 -116
- package/dist/pgIcon.js +0 -116
- package/dist/pgInputCheck.js +0 -116
- package/dist/pgInputCheckList.js +0 -126
- package/dist/pgInputFileLocal.js +0 -116
- package/dist/pgInputHexRgb.js +0 -126
- package/dist/pgInputRange.js +0 -116
- package/dist/pgInputSelect.js +0 -116
- package/dist/pgInputText.js +0 -116
- package/dist/pgInputTextIcon.js +0 -176
- package/dist/pgInputUserSelect.js +0 -116
- package/dist/pgListTag.js +0 -136
- package/dist/pgMarkdown.js +0 -346
- package/dist/pgMenuIcon.js +0 -206
- package/dist/pgModalAlert.js +0 -126
- package/dist/pgModification.js +0 -396
- package/dist/pgNav.js +0 -116
- package/dist/pgOverlay.js +0 -96
- package/dist/pgPicker.js +0 -116
- package/dist/pgPreview.js +0 -116
- package/dist/pgScroll.js +0 -266
- package/dist/pgSearch.js +0 -146
- package/dist/pgTab.js +0 -116
- package/dist/pgTabs.js +0 -136
- package/dist/pgToast.js +0 -136
- package/dist/pgToasts.js +0 -136
- package/dist/pgTooltip.js +0 -126
|
@@ -11,7 +11,7 @@ import template from './basic.html';
|
|
|
11
11
|
template
|
|
12
12
|
})
|
|
13
13
|
export default class XPgGridBasic extends HTMLElement {
|
|
14
|
-
|
|
14
|
+
/*
|
|
15
15
|
@Prop() fontId = 'D051337E-BC7E-11E5-A4E9-842B2B6CFE1B';
|
|
16
16
|
|
|
17
17
|
@Part() $button0: HTMLButtonElement;
|
|
@@ -77,7 +77,8 @@ export default class XPgGridBasic extends HTMLElement {
|
|
|
77
77
|
if (count === -1) {
|
|
78
78
|
this.$grid.icons = this.icons;
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
// update array, fix later
|
|
81
|
+
this.$grid.icons.push(...this.icons.slice(0, count));
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
async handleSync(e: CustomEvent) {
|
package/pg/grid/grid.ts
CHANGED
package/pg/icon/README.md
CHANGED
|
@@ -19,8 +19,9 @@ import PgIcon from '@pictogrammers/components/pg/icon';
|
|
|
19
19
|
|
|
20
20
|
## CSS Variables
|
|
21
21
|
|
|
22
|
-
| CSS Variables | Default
|
|
23
|
-
| ------------------- |
|
|
24
|
-
| `--pg-icon-color`
|
|
25
|
-
| `--pg-icon-
|
|
26
|
-
| `--pg-icon-
|
|
22
|
+
| CSS Variables | Default | Description |
|
|
23
|
+
| ------------------- | ----------- | ----------- |
|
|
24
|
+
| `--pg-icon-color` | `#453C4F` | Color |
|
|
25
|
+
| `--pg-icon-viewbox` | `0 0 24 24` | SVG viewBox |
|
|
26
|
+
| `--pg-icon-width` | `1.5rem` | Width |
|
|
27
|
+
| `--pg-icon-height` | `1.5rem` | Height |
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
Set icon to Square
|
|
12
12
|
</button>
|
|
13
13
|
|
|
14
|
-
<div class="example">
|
|
15
|
-
<pg-icon part="icon2" path="
|
|
14
|
+
<div class="example" style="--pg-icon-viewbox: 0 0 22 22">
|
|
15
|
+
<pg-icon part="icon2" path="M9 3H13V4H14V5H15V9H14V10H13V11H9V10H8V9H7V5H8V4H9V3M10 8V9H12V8H13V6H12V5H10V6H9V8H10M7 12H15V13H17V14H18V15H19V19H3V15H4V14H5V13H7V12M6 16H5V17H17V16H16V15H14V14H8V15H6V16Z"></pg-icon>
|
|
16
16
|
</div>
|
package/pg/icon/icon.ts
CHANGED
|
@@ -13,10 +13,16 @@ const noIcon = 'M0 0h24v24H0V0zm2 2v20h20V2H2z';
|
|
|
13
13
|
export default class PgIcon extends HTMLElement {
|
|
14
14
|
@Prop() path: string = noIcon;
|
|
15
15
|
|
|
16
|
+
@Part() $svg: SVGSVGElement;
|
|
16
17
|
@Part() $path: SVGPathElement;
|
|
17
18
|
|
|
18
19
|
render(changes) {
|
|
19
20
|
if (changes.path) {
|
|
21
|
+
const viewBox = getComputedStyle(this).getPropertyValue('--pg-icon-viewbox');
|
|
22
|
+
this.$svg.setAttribute('viewBox', viewBox || '0 0 24 24');
|
|
23
|
+
if (!this.path) {
|
|
24
|
+
throw new Error('invalid path set on pg-icon');
|
|
25
|
+
}
|
|
20
26
|
this.$path.setAttribute('d', this.path);
|
|
21
27
|
}
|
|
22
28
|
}
|
|
@@ -13,19 +13,19 @@ export default class XPgInputCheckListBasic extends HTMLElement {
|
|
|
13
13
|
@Part() $value: HTMLSpanElement;
|
|
14
14
|
|
|
15
15
|
connectedCallback() {
|
|
16
|
-
this.$input.value
|
|
17
|
-
this.$input.options
|
|
16
|
+
this.$input.value.push('uuid1', 'uuid3');
|
|
17
|
+
this.$input.options.push(
|
|
18
18
|
{ value: 'uuid1', label: 'Item 1' },
|
|
19
19
|
{ value: 'uuid2', label: 'Item 2' },
|
|
20
20
|
{ value: 'uuid3', label: 'Item 3', disabled: true },
|
|
21
21
|
{ value: 'uuid4', label: 'Item 4' }
|
|
22
|
-
|
|
23
|
-
this.$value.
|
|
22
|
+
);
|
|
23
|
+
this.$value.textContent = this.$input.value.join(',');
|
|
24
24
|
this.$input.addEventListener('change', this.handleChange.bind(this));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
handleChange(e) {
|
|
28
28
|
const { value } = e.detail;
|
|
29
|
-
this.$value.
|
|
29
|
+
this.$value.textContent = value.join(',');
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -52,6 +52,7 @@ export default class PgInputCheckList extends HTMLElement {
|
|
|
52
52
|
|
|
53
53
|
render(changes) {
|
|
54
54
|
if (changes.options) {
|
|
55
|
+
/*
|
|
55
56
|
list(
|
|
56
57
|
this.$list,
|
|
57
58
|
this.options,
|
|
@@ -92,6 +93,7 @@ export default class PgInputCheckList extends HTMLElement {
|
|
|
92
93
|
$item.querySelector('button').innerText = option.label;
|
|
93
94
|
}
|
|
94
95
|
);
|
|
96
|
+
*/
|
|
95
97
|
}
|
|
96
98
|
if (changes.value) {
|
|
97
99
|
//const value = [true, 'true'].includes(this.value);
|
|
@@ -42,10 +42,11 @@
|
|
|
42
42
|
bottom: -1px;
|
|
43
43
|
left: -1px;
|
|
44
44
|
border-radius: 0.25rem;
|
|
45
|
-
box-shadow: 0 0 0 3px var(--pg-
|
|
45
|
+
box-shadow: 0 0 0 3px var(--pg-focus-color, rgb(79, 143, 249, 0.6));
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
[part="label"]:focus::before {
|
|
49
|
+
pointer-events: none;
|
|
49
50
|
content: '';
|
|
50
51
|
position: absolute;
|
|
51
52
|
top: -1px;
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
bottom: -1px;
|
|
54
55
|
left: -1px;
|
|
55
56
|
border-radius: 0.25rem;
|
|
56
|
-
box-shadow: 0 0 0 3px var(--pg-
|
|
57
|
+
box-shadow: 0 0 0 3px var(--pg-focus-color, rgb(79, 143, 249, 0.5));
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
[part="file"] {
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# `<pg-input-pixel-editor>`
|
|
2
|
+
|
|
3
|
+
The `pg-input-pixel-editor` component is used to edit images. Tailored for pen or mouse input the editor can be used for various image editing tasks.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import '@pictogrammers/components/pgInputPixelEditor';
|
|
7
|
+
import { PgInputPixelEditor } from '@pictogrammers/components/pgInputPixelEditor';
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```html
|
|
11
|
+
<pg-input-pixel-editor></pg-input-pixel-editor>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Attributes
|
|
15
|
+
|
|
16
|
+
| Attributes | Tested | Description |
|
|
17
|
+
| ----------- | -------- | ----------- |
|
|
18
|
+
| `name` | | Unique name in `pg-form` |
|
|
19
|
+
| `width` | | Pixel width. Default `10` |
|
|
20
|
+
| `height` | | Pixel height. Default `10` |
|
|
21
|
+
| `size` | | Pixel size, minimum value `4`. Default `10` |
|
|
22
|
+
| `gridSize` | | Grid spacing between cells. Default `1` |
|
|
23
|
+
|
|
24
|
+
## Events
|
|
25
|
+
|
|
26
|
+
| Events | Tested | Description |
|
|
27
|
+
| ---------- | -------- | ----------- |
|
|
28
|
+
| `change` | | `{ detail: { value }` |
|
|
29
|
+
| `input` | | `{ detail: { value }` |
|
|
30
|
+
|
|
31
|
+
## Methods
|
|
32
|
+
|
|
33
|
+
See usage for each method below.
|
|
34
|
+
|
|
35
|
+
| Method | Tested | Description |
|
|
36
|
+
| ---------- | -------- | ----------- |
|
|
37
|
+
| `save(options)` | - | Save file. |
|
|
38
|
+
| `open(json)` | - | Open file. |
|
|
39
|
+
| `undo()` | - | Undo. |
|
|
40
|
+
| `hasUndo()` | - | Has undo |
|
|
41
|
+
| `hasRedo()` | - | Has redo |
|
|
42
|
+
| `redo()` | - | Redo. |
|
|
43
|
+
| `selectLayer()` | - | Select layer. |
|
|
44
|
+
| `getLayers()` | - | Get layer array. |
|
|
45
|
+
| `addLayer(option)` | - | Add layer. |
|
|
46
|
+
| `removeLayer(index)` | - | Remove layer. |
|
|
47
|
+
| `flattenLayers(layerIndexes)` | - | Flatten layers. |
|
|
48
|
+
| `moveLayer(startIndex, endIndex)` | - | Move layer. |
|
|
49
|
+
| `getColors()` | - | Get colors. |
|
|
50
|
+
| `addColor(r, g, b, a)` | - | Add color. |
|
|
51
|
+
| `removeColor(index)` | - | Remove color. |
|
|
52
|
+
| `moveColor(startIndex, endIndex)` | - | Move index. |
|
|
53
|
+
| `rotateClockwise()` | - | Rotate. |
|
|
54
|
+
| `rotateCounterclockwise()` | - | Rotate. |
|
|
55
|
+
| `move(x, y[, layer])` | - | Move. |
|
|
56
|
+
| `flipHorizontal()` | - | Flip horizontal. |
|
|
57
|
+
| `flipVertical()` | - | Flip vertical. |
|
|
58
|
+
| `invert()` | - | Invert layer. |
|
|
59
|
+
|
|
60
|
+
### `save(options)` Method
|
|
61
|
+
|
|
62
|
+
The save method allows getting the JSON representation of the current editor.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
@Part() $editor: PgInputPixelEditor;
|
|
66
|
+
|
|
67
|
+
handleSave() {
|
|
68
|
+
const json = await this.$editor.save({
|
|
69
|
+
// Include history
|
|
70
|
+
history: true,
|
|
71
|
+
});
|
|
72
|
+
// use json
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `open(json)` Method
|
|
77
|
+
|
|
78
|
+
The open method allows loading json for previously created images.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
@Part() $editor: PgInputPixelEditor;
|
|
82
|
+
|
|
83
|
+
handleOpen() {
|
|
84
|
+
const error = await this.$editor.open(json);
|
|
85
|
+
if (error) {
|
|
86
|
+
throw new Error(error.message);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## JSON Format
|
|
92
|
+
|
|
93
|
+
- `width` - Image width.
|
|
94
|
+
- `height` - Image width.
|
|
95
|
+
- `transparent` - Render transparent background.
|
|
96
|
+
|
|
97
|
+
A complete JSON storage for a 10x10 image.
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"width": 10,
|
|
102
|
+
"height": 10,
|
|
103
|
+
"transparent": true,
|
|
104
|
+
"colors": [
|
|
105
|
+
[0, 0, 0, 0],
|
|
106
|
+
[0, 0, 0, 1]
|
|
107
|
+
],
|
|
108
|
+
"layers": [
|
|
109
|
+
{
|
|
110
|
+
"name": "Layer 1",
|
|
111
|
+
"export": true,
|
|
112
|
+
"locked": false,
|
|
113
|
+
"visible": true,
|
|
114
|
+
"opacity": 1
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"data": [
|
|
118
|
+
[
|
|
119
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
120
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
121
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
122
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
123
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
124
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
125
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
126
|
+
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
|
|
127
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
128
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
129
|
+
]
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[part="debug"] {
|
|
2
|
+
background: #555;
|
|
3
|
+
padding: 1rem;
|
|
4
|
+
display: flex;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
[part="debug"] canvas {
|
|
8
|
+
border: 1px solid #FFF;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
[part="value1"] {
|
|
12
|
+
word-wrap: break-word;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.props {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: row;
|
|
18
|
+
margin-bottom: 0.5rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
label {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
h3 {
|
|
27
|
+
margin: 0.25rem 0;
|
|
28
|
+
font-size: 1.125rem;
|
|
29
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<div class="example">
|
|
2
|
+
<div class="props">
|
|
3
|
+
<label>
|
|
4
|
+
Width
|
|
5
|
+
<input part="width" type="range" min="4" max="22">
|
|
6
|
+
</label>
|
|
7
|
+
<label>
|
|
8
|
+
Height
|
|
9
|
+
<input part="height" type="range" min="4" max="22">
|
|
10
|
+
</label>
|
|
11
|
+
<label>
|
|
12
|
+
Size
|
|
13
|
+
<input part="size" type="range" step="2" min="4" max="16">
|
|
14
|
+
</label>
|
|
15
|
+
<label>
|
|
16
|
+
<input part="transparent" type="checkbox">
|
|
17
|
+
Transparent
|
|
18
|
+
</label>
|
|
19
|
+
</div>
|
|
20
|
+
<pg-input-pixel-editor part="input" width="10" height="10" size="10" style="box-shadow:0 0 0.5rem rgba(0, 0, 0, 0.2)"></pg-input-pixel-editor>
|
|
21
|
+
<div>
|
|
22
|
+
<code>onchange: <span part="value1"></span></code>
|
|
23
|
+
</div>
|
|
24
|
+
<div>
|
|
25
|
+
<code>oninput: <span part="value2"></span></code>
|
|
26
|
+
</div>
|
|
27
|
+
<div>
|
|
28
|
+
<h3>Canvas Tools</h3>
|
|
29
|
+
<button part="reset">Reset</button>
|
|
30
|
+
<button part="clear">Clear</button>
|
|
31
|
+
<button part="invert">Invert</button>
|
|
32
|
+
|
|
|
33
|
+
<button part="save">Save</button>
|
|
34
|
+
<button part="open">Open</button>
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
<h3>Drawing Tools</h3>
|
|
38
|
+
<button part="modePixel">Pixel</button>
|
|
39
|
+
<button part="modeLine">Line</button>
|
|
40
|
+
<button part="modeRectangle">Rectangle</button>
|
|
41
|
+
<button part="modeRectangleOutline">Rectangle Outline</button>
|
|
42
|
+
<button part="modeEllipse">Ellipse</button>
|
|
43
|
+
<button part="modeEllipseOutline">Ellipse Outline</button>
|
|
44
|
+
</div>
|
|
45
|
+
<div>
|
|
46
|
+
<h3>Color Tools</h3>
|
|
47
|
+
<button part="addColor">Add Color</button>
|
|
48
|
+
<pre part="colors"></pre>
|
|
49
|
+
</div>
|
|
50
|
+
<div>
|
|
51
|
+
<h3>Layer Tools</h3>
|
|
52
|
+
<button part="addLayer">Add Layer</button>
|
|
53
|
+
<pre part="layers"></pre>
|
|
54
|
+
</div>
|
|
55
|
+
<div>
|
|
56
|
+
<h3>Example Tools</h3>
|
|
57
|
+
<input part="file" type="file" />
|
|
58
|
+
<button part="saveSvg">Save SVG</button>
|
|
59
|
+
<button part="savePng">Save Image</button>
|
|
60
|
+
</div>
|
|
61
|
+
<div part="debug"></div>
|
|
62
|
+
<pre part="output" contenteditable></pre>
|
|
63
|
+
</div>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { Component, Part } from '@pictogrammers/element';
|
|
2
|
+
import PgInputPixelEditor from '../../inputPixelEditor';
|
|
3
|
+
import { maskToBitmap } from '../../utils/maskToBitmap';
|
|
4
|
+
|
|
5
|
+
import template from './basic.html';
|
|
6
|
+
import style from './basic.css';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'x-pg-input-pixel-editor-basic',
|
|
10
|
+
style,
|
|
11
|
+
template
|
|
12
|
+
})
|
|
13
|
+
export default class XPgInputPixelEditorBasic extends HTMLElement {
|
|
14
|
+
|
|
15
|
+
@Part() $input: PgInputPixelEditor;
|
|
16
|
+
@Part() $value1: HTMLSpanElement;
|
|
17
|
+
@Part() $value2: HTMLSpanElement;
|
|
18
|
+
@Part() $debug: HTMLDivElement;
|
|
19
|
+
@Part() $width: HTMLInputElement;
|
|
20
|
+
@Part() $height: HTMLInputElement;
|
|
21
|
+
@Part() $size: HTMLInputElement;
|
|
22
|
+
@Part() $transparent: HTMLInputElement;
|
|
23
|
+
|
|
24
|
+
@Part() $reset: HTMLButtonElement;
|
|
25
|
+
@Part() $clear: HTMLButtonElement;
|
|
26
|
+
@Part() $invert: HTMLButtonElement;
|
|
27
|
+
@Part() $modePixel: HTMLButtonElement;
|
|
28
|
+
@Part() $modeLine: HTMLButtonElement;
|
|
29
|
+
@Part() $modeRectangle: HTMLButtonElement;
|
|
30
|
+
@Part() $modeRectangleOutline: HTMLButtonElement;
|
|
31
|
+
@Part() $modeEllipse: HTMLButtonElement;
|
|
32
|
+
@Part() $modeEllipseOutline: HTMLButtonElement;
|
|
33
|
+
|
|
34
|
+
@Part() $save: HTMLButtonElement;
|
|
35
|
+
@Part() $open: HTMLButtonElement;
|
|
36
|
+
@Part() $output: HTMLPreElement;
|
|
37
|
+
@Part() $file: HTMLInputElement;
|
|
38
|
+
@Part() $saveSvg: HTMLInputElement;
|
|
39
|
+
@Part() $savePng: HTMLInputElement;
|
|
40
|
+
|
|
41
|
+
// MAKE A LIST COMPONENT!!!! [text | delete]
|
|
42
|
+
@Part() $colors: HTMLPreElement;
|
|
43
|
+
@Part() $layers: HTMLPreElement;
|
|
44
|
+
|
|
45
|
+
connectedCallback() {
|
|
46
|
+
this.$width.value = '10';
|
|
47
|
+
this.$height.value = '10';
|
|
48
|
+
this.$size.value = '10';
|
|
49
|
+
this.$input.addEventListener('change', this.handleChange.bind(this));
|
|
50
|
+
this.$width.addEventListener('input', this.handleWidthChange.bind(this));
|
|
51
|
+
this.$height.addEventListener('input', this.handleHeightChange.bind(this));
|
|
52
|
+
this.$size.addEventListener('input', this.handleSizeChange.bind(this));
|
|
53
|
+
this.$transparent.addEventListener('input', this.handleTransparentChange.bind(this));
|
|
54
|
+
this.$input.addEventListener('input', this.handleInput.bind(this));
|
|
55
|
+
this.$input.addEventListener('debug', this.handleDebug.bind(this));
|
|
56
|
+
this.$modePixel.addEventListener('click', () => {
|
|
57
|
+
this.$input.inputModePixel();
|
|
58
|
+
});
|
|
59
|
+
this.$modeLine.addEventListener('click', () => {
|
|
60
|
+
this.$input.inputModeLine();
|
|
61
|
+
});
|
|
62
|
+
this.$modeRectangle.addEventListener('click', () => {
|
|
63
|
+
this.$input.inputModeRectangle();
|
|
64
|
+
});
|
|
65
|
+
this.$modeRectangleOutline.addEventListener('click', () => {
|
|
66
|
+
this.$input.inputModeRectangleOutline();
|
|
67
|
+
});
|
|
68
|
+
this.$modeEllipse.addEventListener('click', () => {
|
|
69
|
+
this.$input.inputModeEllipse();
|
|
70
|
+
});
|
|
71
|
+
this.$modeEllipseOutline.addEventListener('click', () => {
|
|
72
|
+
this.$input.inputModeEllipseOutline();
|
|
73
|
+
});
|
|
74
|
+
this.$reset.addEventListener('click', () => {
|
|
75
|
+
this.$input.reset();
|
|
76
|
+
});
|
|
77
|
+
this.$clear.addEventListener('click', () => {
|
|
78
|
+
this.$input.clear();
|
|
79
|
+
});
|
|
80
|
+
this.$invert.addEventListener('click', () => {
|
|
81
|
+
this.$input.invert();
|
|
82
|
+
});
|
|
83
|
+
this.$save.addEventListener('click', async () => {
|
|
84
|
+
const json = await this.$input.save();
|
|
85
|
+
this.$output.textContent = JSON.stringify(json, null, 4);
|
|
86
|
+
});
|
|
87
|
+
this.$open.addEventListener('click', () => {
|
|
88
|
+
const json = JSON.parse(this.$output.textContent || '');
|
|
89
|
+
this.$input.open(json as any);
|
|
90
|
+
});
|
|
91
|
+
this.$file.addEventListener('change', this.handleFile.bind(this));
|
|
92
|
+
this.$saveSvg.addEventListener('click', async () => {
|
|
93
|
+
try {
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
const handle = await window.showSaveFilePicker({
|
|
96
|
+
suggestedName: 'Canvas',
|
|
97
|
+
types: [{
|
|
98
|
+
description: 'SVG Document',
|
|
99
|
+
accept: {'image/svg+xml': ['.svg']},
|
|
100
|
+
}],
|
|
101
|
+
});
|
|
102
|
+
const writable = await handle.createWritable();
|
|
103
|
+
await writable.write(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${this.$width.value} ${this.$height.value}">`);
|
|
104
|
+
await writable.write(`<path d="${'test'}" />`);
|
|
105
|
+
await writable.write('</svg>');
|
|
106
|
+
await writable.close();
|
|
107
|
+
} catch (e: any) {
|
|
108
|
+
// no save
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
this.$savePng.addEventListener('click', async () => {
|
|
112
|
+
try {
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
const handle = await window.showSaveFilePicker({
|
|
115
|
+
suggestedName: 'CanvasName',
|
|
116
|
+
types: [{
|
|
117
|
+
description: 'SVG Document',
|
|
118
|
+
accept: {'image/svg+xml': ['.svg']},
|
|
119
|
+
}],
|
|
120
|
+
});
|
|
121
|
+
const writable = await handle.createWritable();
|
|
122
|
+
await writable.write('something');
|
|
123
|
+
await writable.write
|
|
124
|
+
await writable.close();
|
|
125
|
+
} catch (e: any) {
|
|
126
|
+
// no save
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
handleFile(e) {
|
|
132
|
+
const { files } = e.currentTarget;
|
|
133
|
+
if (files.length !== 1) {
|
|
134
|
+
throw new Error('select only 1 file');
|
|
135
|
+
}
|
|
136
|
+
switch(files[0].type) {
|
|
137
|
+
case 'image/svg+xml':
|
|
138
|
+
// Read the file
|
|
139
|
+
const reader = new FileReader();
|
|
140
|
+
reader.onload = () => {
|
|
141
|
+
const content = reader.result as string;
|
|
142
|
+
const size = content.match(/viewBox="\d+ \d+ (\d+) (\d+)"/) as string[];
|
|
143
|
+
const width = parseInt(size[1], 10);
|
|
144
|
+
const height = parseInt(size[2], 10);
|
|
145
|
+
const path = (content.match(/d="([^"]+)"/) as string[])[1];
|
|
146
|
+
// Render path
|
|
147
|
+
console.log(path, size[1], size[2]);
|
|
148
|
+
this.$input.applyTemplate(maskToBitmap(path, width, height));
|
|
149
|
+
;
|
|
150
|
+
};
|
|
151
|
+
reader.onerror = () => {
|
|
152
|
+
throw new Error("Error reading the file. Please try again.");
|
|
153
|
+
};
|
|
154
|
+
reader.readAsText(files[0]);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
throw new Error('Unsupported format.');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
handleChange(e: CustomEvent) {
|
|
162
|
+
const { value } = e.detail;
|
|
163
|
+
this.$value1.textContent = value.join('--');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
handleInput(e: CustomEvent) {
|
|
167
|
+
const { value } = e.detail;
|
|
168
|
+
this.$value2.textContent = value;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
handleDebug(e: CustomEvent) {
|
|
172
|
+
const { x, y, width, height, context, baseLayer, editLayer, noEditLayer, previewLayer } = e.detail;
|
|
173
|
+
this.$debug.appendChild(baseLayer);
|
|
174
|
+
this.$debug.appendChild(editLayer);
|
|
175
|
+
this.$debug.appendChild(noEditLayer);
|
|
176
|
+
this.$debug.appendChild(previewLayer);
|
|
177
|
+
//context.strokeStyle = 'rgba(255, 0, 0, 0.3)';
|
|
178
|
+
//context.lineWidth = 1;
|
|
179
|
+
//context.strokeRect(x, y, width, height);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
handleWidthChange(e) {
|
|
183
|
+
this.$input.width = e.target.value;
|
|
184
|
+
this.$debug.innerHTML = '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
handleHeightChange(e) {
|
|
188
|
+
this.$input.height = e.target.value;
|
|
189
|
+
this.$debug.innerHTML = '';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
handleSizeChange(e) {
|
|
193
|
+
this.$input.size = e.target.value;
|
|
194
|
+
this.$debug.innerHTML = '';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
handleTransparentChange(e) {
|
|
198
|
+
this.$input.transparent = e.target.checked;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
function showOpenFilePickerPolyfill(options: any) {
|
|
2
|
+
return new Promise((resolve) => {
|
|
3
|
+
const input = document.createElement("input");
|
|
4
|
+
input.type = "file";
|
|
5
|
+
input.multiple = options.multiple;
|
|
6
|
+
input.accept = options.types
|
|
7
|
+
.map((type) => type.accept)
|
|
8
|
+
.flatMap((inst) => Object.keys(inst).flatMap((key) => inst[key]))
|
|
9
|
+
.join(",");
|
|
10
|
+
|
|
11
|
+
input.addEventListener("change", () => {
|
|
12
|
+
resolve(
|
|
13
|
+
[...(input.files as any)].map((file) => {
|
|
14
|
+
return {
|
|
15
|
+
getFile: async () =>
|
|
16
|
+
new Promise((resolve) => {
|
|
17
|
+
resolve(file);
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
input.click();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Open file with polyfill for legacy browsers.
|
|
30
|
+
*
|
|
31
|
+
* @param options
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
export function openFile(options) {
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
if (window.showOpenFilePicker) {
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
return window.showOpenFilePicker(options);
|
|
39
|
+
}
|
|
40
|
+
return showOpenFilePickerPolyfill(options);
|
|
41
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Save file with polyfill for legacy browsers.
|
|
4
|
+
*
|
|
5
|
+
* @param blob File blob
|
|
6
|
+
* @returns Promise
|
|
7
|
+
*/
|
|
8
|
+
export async function saveFile(blob) {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
if (window.showSaveFilePicker) {
|
|
11
|
+
const opts = {
|
|
12
|
+
types: [
|
|
13
|
+
{
|
|
14
|
+
description: "Text file",
|
|
15
|
+
accept: { "text/plain": [".txt"] },
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
try {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
return await window.showSaveFilePicker(opts);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.log('no save');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const downloadelem = document.createElement("a");
|
|
27
|
+
const url = URL.createObjectURL(blob);
|
|
28
|
+
document.body.appendChild(downloadelem);
|
|
29
|
+
downloadelem.href = url;
|
|
30
|
+
downloadelem.download = 'filename.txt';
|
|
31
|
+
downloadelem.click();
|
|
32
|
+
downloadelem.remove();
|
|
33
|
+
window.URL.revokeObjectURL(url);
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
[part="wrapper"] {
|
|
6
|
+
display: flex;
|
|
7
|
+
position: relative;
|
|
8
|
+
outline: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
[part="wrapper"]:focus-visible::before {
|
|
12
|
+
pointer-events: none;
|
|
13
|
+
content: '';
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: -1px;
|
|
16
|
+
right: -1px;
|
|
17
|
+
bottom: -1px;
|
|
18
|
+
left: -1px;
|
|
19
|
+
border-radius: 0.125rem;
|
|
20
|
+
box-shadow: 0 0 0 3px var(--pg-focus-color, rgb(79, 143, 249, 0.5));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
canvas {
|
|
24
|
+
touch-action: none;
|
|
25
|
+
user-select: none;
|
|
26
|
+
outline: 0;
|
|
27
|
+
}
|