@lvl99dotcom/paintcanvas 0.3.1 → 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.
- package/README.md +30 -15
- package/dist/lib/brushes/StrokeEngine/index.d.ts +2 -2
- package/dist/lib/brushes/StrokeEngine/index.js +26 -28
- package/dist/lib/brushes/presets/round/index.d.ts +1 -1
- package/dist/lib/brushes/presets/round/index.js +12 -7
- package/dist/lib/brushes/presets/square/index.d.ts +1 -1
- package/dist/lib/brushes/presets/square/index.js +7 -3
- package/dist/lib/brushes/shapeImage/index.d.ts +7 -3
- package/dist/lib/brushes/shapeImage/index.js +15 -9
- package/dist/lib/brushes/shapes/index.d.ts +18 -0
- package/dist/lib/brushes/shapes/index.js +86 -0
- package/dist/lib/classes/BrushSettings/index.d.ts +53 -2
- package/dist/lib/classes/BrushSettings/index.js +85 -14
- package/dist/lib/classes/KeyboardShortcuts/index.d.ts +47 -7
- package/dist/lib/classes/KeyboardShortcuts/index.js +145 -20
- package/dist/lib/classes/PaintCanvas/index.d.ts +123 -27
- package/dist/lib/classes/PaintCanvas/index.js +208 -41
- package/dist/lib/classes/PaintCanvas/tool.d.ts +15 -0
- package/dist/lib/classes/PaintCanvas/tool.js +18 -0
- package/dist/lib/classes/Palette/index.d.ts +58 -0
- package/dist/lib/classes/Palette/index.js +92 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +53 -0
- package/dist/lib/classes/SettingsAutosave/index.js +98 -0
- package/dist/lib/classes/ShortcutSettings/index.d.ts +63 -0
- package/dist/lib/classes/ShortcutSettings/index.js +110 -0
- package/dist/lib/classes/UiSettings/index.d.ts +68 -0
- package/dist/lib/classes/UiSettings/index.js +82 -0
- package/dist/lib/palette/index.d.ts +49 -0
- package/dist/lib/palette/index.js +82 -0
- package/dist/lib/palette/schema.d.ts +45 -0
- package/dist/lib/palette/schema.js +41 -0
- package/dist/lib/rendering/cursors/index.d.ts +2 -0
- package/dist/lib/rendering/cursors/index.js +3 -1
- package/dist/lib/rendering/sample/index.js +3 -2
- package/dist/lib/settings/index.d.ts +63 -0
- package/dist/lib/settings/index.js +93 -0
- package/dist/lib/settings/schema.d.ts +168 -0
- package/dist/lib/settings/schema.js +116 -0
- package/dist/lib/storage/index.d.ts +36 -5
- package/dist/lib/storage/index.js +87 -29
- package/dist/lib/utils/colour/index.d.ts +72 -0
- package/dist/lib/utils/colour/index.js +154 -0
- package/dist/lib/utils/shortcuts/index.d.ts +174 -11
- package/dist/lib/utils/shortcuts/index.js +391 -145
- package/dist/lib/validation/validators.generated.d.ts +5 -0
- package/dist/lib/validation/validators.generated.js +1040 -1
- package/dist/locales/en-GB.js +96 -3
- package/dist/locales/en-US.js +96 -3
- package/dist/locales/fr.js +96 -3
- package/dist/locales/ja.js +96 -3
- package/dist/locales/ko.js +96 -3
- package/dist/locales/zh-Hans.js +96 -3
- package/dist/locales/zh-Hant.js +96 -3
- package/dist/package.js +1 -1
- package/dist/testing/recordingCanvas.js +2 -1
- package/dist/ui/base/index.d.ts +2 -2
- package/dist/ui/dismiss/index.d.ts +21 -0
- package/dist/ui/dismiss/index.js +27 -0
- package/dist/ui/drag/index.d.ts +51 -0
- package/dist/ui/drag/index.js +81 -0
- package/dist/ui/elements/PaintCanvas/index.d.ts +57 -50
- package/dist/ui/elements/PaintCanvas/index.js +141 -174
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +59 -0
- package/dist/ui/elements/PcAppSettings/index.js +222 -0
- package/dist/ui/elements/PcBrushConfig/index.d.ts +9 -2
- package/dist/ui/elements/PcBrushConfig/index.js +47 -7
- package/dist/ui/elements/PcBrushConfig/style.js +1 -1
- package/dist/ui/elements/PcBrushSize/index.d.ts +53 -0
- package/dist/ui/elements/PcBrushSize/index.js +66 -0
- package/dist/ui/elements/PcBrushTest/index.d.ts +26 -0
- package/dist/ui/elements/PcBrushTest/index.js +73 -5
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcCanvas/index.d.ts +22 -2
- package/dist/ui/elements/PcCanvas/index.js +60 -15
- package/dist/ui/elements/PcCanvasMap/style.js +1 -1
- package/dist/ui/elements/PcClipboardTools/index.d.ts +48 -0
- package/dist/ui/elements/PcClipboardTools/index.js +118 -0
- package/dist/ui/elements/PcColourPair/index.d.ts +43 -0
- package/dist/ui/elements/PcColourPair/index.js +125 -0
- package/dist/ui/elements/PcContextMenu/index.d.ts +71 -34
- package/dist/ui/elements/PcContextMenu/index.js +128 -97
- package/dist/ui/elements/PcInputSettings/index.d.ts +13 -0
- package/dist/ui/elements/PcInputSettings/index.js +16 -1
- package/dist/ui/elements/PcLayerItem/index.d.ts +13 -34
- package/dist/ui/elements/PcLayerItem/index.js +39 -91
- package/dist/ui/elements/PcLayerItem/style.js +1 -1
- package/dist/ui/elements/PcMenu/index.d.ts +138 -0
- package/dist/ui/elements/PcMenu/index.js +296 -0
- package/dist/ui/elements/PcNumberSlider/index.d.ts +137 -0
- package/dist/ui/elements/PcNumberSlider/index.js +247 -0
- package/dist/ui/elements/PcPane/index.d.ts +120 -0
- package/dist/ui/elements/PcPane/index.js +394 -0
- package/dist/ui/elements/PcPanel/index.d.ts +26 -8
- package/dist/ui/elements/PcPanel/index.js +76 -8
- package/dist/ui/elements/{PcBrushMenu → PcPanelBrushes}/index.d.ts +22 -21
- package/dist/ui/elements/{PcBrushMenu → PcPanelBrushes}/index.js +24 -57
- package/dist/ui/elements/PcPanelBrushes/style.js +3 -0
- package/dist/ui/elements/PcPanelColours/index.d.ts +171 -0
- package/dist/ui/elements/PcPanelColours/index.js +650 -0
- package/dist/ui/elements/PcPanelColours/style.js +3 -0
- package/dist/ui/elements/{PcLayersMenu → PcPanelLayers}/index.d.ts +17 -4
- package/dist/ui/elements/{PcLayersMenu → PcPanelLayers}/index.js +17 -10
- package/dist/ui/elements/PcPanelLayers/style.js +3 -0
- package/dist/ui/elements/PcPopover/index.d.ts +39 -1
- package/dist/ui/elements/PcPopover/index.js +72 -4
- package/dist/ui/elements/PcShortcutSettings/index.d.ts +69 -0
- package/dist/ui/elements/PcShortcutSettings/index.js +273 -0
- package/dist/ui/elements/PcThemePicker/index.d.ts +17 -15
- package/dist/ui/elements/PcThemePicker/index.js +22 -21
- package/dist/ui/elements/PcToolSettings/index.d.ts +48 -9
- package/dist/ui/elements/PcToolSettings/index.js +384 -319
- package/dist/ui/elements/PcToolSettings/style.js +1 -1
- package/dist/ui/elements/PcToolbar/index.d.ts +62 -12
- package/dist/ui/elements/PcToolbar/index.js +119 -57
- package/dist/ui/elements/PcToolbar/style.js +1 -1
- package/dist/ui/icons/images/icon-brush@2x.js +3 -0
- package/dist/ui/icons/images/icon-circle-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-clipboard@2x.js +3 -0
- package/dist/ui/icons/images/icon-cog@2x.js +3 -0
- package/dist/ui/icons/images/icon-cursor@2x.js +3 -0
- package/dist/ui/icons/images/icon-diagonal-tlbr-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-diagonal-trbl-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-eraser@2x.js +3 -0
- package/dist/ui/icons/images/icon-eyedropper@2x.js +3 -0
- package/dist/ui/icons/images/icon-flip-horizontal@2x.js +3 -0
- package/dist/ui/icons/images/icon-flip-vertical@2x.js +3 -0
- package/dist/ui/icons/images/icon-focus-pen@2x.js +3 -0
- package/dist/ui/icons/images/icon-freehand-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-hidden@2x.js +3 -0
- package/dist/ui/icons/images/icon-horizontal-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-layers@2x.js +3 -0
- package/dist/ui/icons/images/icon-linked@2x.js +3 -0
- package/dist/ui/icons/images/icon-locked@2x.js +3 -0
- package/dist/ui/icons/images/icon-moon@2x.js +3 -0
- package/dist/ui/icons/images/icon-pan@2x.js +3 -0
- package/dist/ui/icons/images/icon-polygon-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-pressure@2x.js +3 -0
- package/dist/ui/icons/images/icon-randomise@2x.js +3 -0
- package/dist/ui/icons/images/icon-rectangle-mask@2x.js +3 -0
- package/dist/ui/icons/images/icon-redo@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate-90-left@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate-90-right@2x.js +3 -0
- package/dist/ui/icons/images/icon-rotate@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-bezier-cubic@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-bezier-quad@2x.js +3 -0
- package/dist/ui/icons/images/icon-smoothing-linear@2x.js +3 -0
- package/dist/ui/icons/images/icon-star@2x.js +3 -0
- package/dist/ui/icons/images/icon-sun@2x.js +3 -0
- package/dist/ui/icons/images/icon-tilt@2x.js +3 -0
- package/dist/ui/icons/images/icon-undo@2x.js +3 -0
- package/dist/ui/icons/images/icon-unlinked@2x.js +3 -0
- package/dist/ui/icons/images/icon-unlocked@2x.js +3 -0
- package/dist/ui/icons/images/icon-vertical-size@2x.js +3 -0
- package/dist/ui/icons/images/icon-visible@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom-in@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom-out@2x.js +3 -0
- package/dist/ui/icons/images/icon-zoom@2x.js +3 -0
- package/dist/ui/icons/index.d.ts +1 -1
- package/dist/ui/icons/index.js +84 -72
- package/dist/ui/index.d.ts +13 -2
- package/dist/ui/index.js +16 -4
- package/dist/ui/layout/index.d.ts +9 -1
- package/dist/ui/layout/index.js +11 -2
- package/dist/ui/tokens/index.d.ts +5 -4
- package/dist/ui/tokens/index.js +15 -8
- package/locales/en-GB.json +96 -3
- package/locales/en-US.json +96 -3
- package/locales/fr.json +96 -3
- package/locales/ja.json +96 -3
- package/locales/ko.json +96 -3
- package/locales/zh-Hans.json +96 -3
- package/locales/zh-Hant.json +96 -3
- package/package.json +11 -4
- package/dist/ui/elements/PcBrushMenu/style.js +0 -3
- package/dist/ui/elements/PcLayersMenu/style.js +0 -3
- package/dist/ui/icons/images/brush.js +0 -3
- package/dist/ui/icons/images/circle-mask.js +0 -3
- package/dist/ui/icons/images/clipboard.js +0 -3
- package/dist/ui/icons/images/cursor.js +0 -3
- package/dist/ui/icons/images/eraser.js +0 -3
- package/dist/ui/icons/images/eyedropper.js +0 -3
- package/dist/ui/icons/images/flip-horizontal.js +0 -3
- package/dist/ui/icons/images/flip-vertical.js +0 -3
- package/dist/ui/icons/images/focus-pen.js +0 -3
- package/dist/ui/icons/images/freehand-mask.js +0 -3
- package/dist/ui/icons/images/hidden.js +0 -3
- package/dist/ui/icons/images/layers.js +0 -3
- package/dist/ui/icons/images/linked.js +0 -3
- package/dist/ui/icons/images/locked.js +0 -3
- package/dist/ui/icons/images/moon.js +0 -3
- package/dist/ui/icons/images/pan.js +0 -3
- package/dist/ui/icons/images/polygon-mask.js +0 -3
- package/dist/ui/icons/images/pressure.js +0 -3
- package/dist/ui/icons/images/randomise.js +0 -3
- package/dist/ui/icons/images/rectangle-mask.js +0 -3
- package/dist/ui/icons/images/redo.js +0 -3
- package/dist/ui/icons/images/rotate-90-left.js +0 -3
- package/dist/ui/icons/images/rotate-90-right.js +0 -3
- package/dist/ui/icons/images/smoothing-bezier-cubic.js +0 -3
- package/dist/ui/icons/images/smoothing-bezier-quad.js +0 -3
- package/dist/ui/icons/images/smoothing-linear.js +0 -3
- package/dist/ui/icons/images/star.js +0 -3
- package/dist/ui/icons/images/sun.js +0 -3
- package/dist/ui/icons/images/tilt.js +0 -3
- package/dist/ui/icons/images/undo.js +0 -3
- package/dist/ui/icons/images/unlinked.js +0 -3
- package/dist/ui/icons/images/unlocked.js +0 -3
- package/dist/ui/icons/images/visible.js +0 -3
- package/dist/ui/icons/images/zoom-in.js +0 -3
- package/dist/ui/icons/images/zoom-out.js +0 -3
- package/dist/ui/icons/images/zoom.js +0 -3
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { SETTINGS_FILE_FORMAT } from "../../../lib/settings/schema.js";
|
|
2
|
+
import { ICON_CONTROLS_CSS, PILLS_CSS, WINDOWS_CSS } from "../../styles/index.js";
|
|
3
|
+
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
4
|
+
import "../PcShortcutSettings/index.js";
|
|
5
|
+
import { SETTINGS_FILE_ERRORS, SettingsFileError, applySettings, collectSettings, exportSettingsFile, parseSettingsFile, settingsFileName } from "../../../lib/settings/index.js";
|
|
6
|
+
import { JSON_FILE_TYPE, saveFile } from "../../../lib/rendering/screenshot/index.js";
|
|
7
|
+
import { css, html, nothing, unsafeCSS } from "lit";
|
|
8
|
+
// src/ui/elements/PcAppSettings/index.ts
|
|
9
|
+
/** Translation keys of the settings file error messages */
|
|
10
|
+
var SETTINGS_FILE_ERROR_KEYS = {
|
|
11
|
+
[SETTINGS_FILE_ERRORS.incompatible]: "paintCanvas.settings.fileIncompatible",
|
|
12
|
+
[SETTINGS_FILE_ERRORS.read]: "paintCanvas.settings.fileReadFailed"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Buttons for the user's app settings: "Keyboard shortcuts", which opens a window to change them (see
|
|
16
|
+
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
17
|
+
* settings, keyboard shortcuts, colour palette, colours, theme and language). The window is a modal `<dialog>` above the whole page; it
|
|
18
|
+
* closes with its Close button, Escape, or a press on the backdrop, and the browser gives focus back to the button. Fires `pc-toast` after importing, or when importing or
|
|
19
|
+
* exporting fails.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
23
|
+
*/
|
|
24
|
+
var PcAppSettings = class extends PcElement {
|
|
25
|
+
static properties = {
|
|
26
|
+
...PcElement.properties,
|
|
27
|
+
app: { attribute: false },
|
|
28
|
+
shortcutsOpen: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
attribute: "shortcuts-open"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
static styles = [
|
|
34
|
+
PcElement.styles,
|
|
35
|
+
unsafeCSS(WINDOWS_CSS),
|
|
36
|
+
unsafeCSS(ICON_CONTROLS_CSS),
|
|
37
|
+
unsafeCSS(PILLS_CSS),
|
|
38
|
+
css`
|
|
39
|
+
:host {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: var(--pc-space-2);
|
|
43
|
+
font-family: var(--pc-font);
|
|
44
|
+
font-size: var(--pc-font-size);
|
|
45
|
+
}
|
|
46
|
+
.actions {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-wrap: wrap;
|
|
49
|
+
gap: var(--pc-space-2);
|
|
50
|
+
}
|
|
51
|
+
/* A modal window in the browser's top layer, above everything on the page */
|
|
52
|
+
dialog {
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
width: min(480px, calc(100vw - 2 * var(--pc-space-3)));
|
|
55
|
+
max-height: calc(100vh - 2 * var(--pc-space-3));
|
|
56
|
+
padding: 0;
|
|
57
|
+
border: 0;
|
|
58
|
+
border-radius: var(--pc-radius);
|
|
59
|
+
background: var(--pc-surface-raised);
|
|
60
|
+
color: var(--pc-text);
|
|
61
|
+
box-shadow: var(--pc-shadow);
|
|
62
|
+
}
|
|
63
|
+
dialog::backdrop {
|
|
64
|
+
background: var(--pc-backdrop);
|
|
65
|
+
}
|
|
66
|
+
.window {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: var(--pc-space-3);
|
|
70
|
+
box-shadow: none;
|
|
71
|
+
}
|
|
72
|
+
.header {
|
|
73
|
+
display: flex;
|
|
74
|
+
gap: var(--pc-space-2);
|
|
75
|
+
align-items: center;
|
|
76
|
+
justify-content: space-between;
|
|
77
|
+
}
|
|
78
|
+
h2 {
|
|
79
|
+
margin: 0;
|
|
80
|
+
font-size: 1.2em;
|
|
81
|
+
}
|
|
82
|
+
`
|
|
83
|
+
];
|
|
84
|
+
/** Saves exported files (replaceable for tests) */
|
|
85
|
+
saveFile = (blob, name) => saveFile(blob, name, void 0, JSON_FILE_TYPE);
|
|
86
|
+
constructor() {
|
|
87
|
+
super();
|
|
88
|
+
this.shortcutsOpen = false;
|
|
89
|
+
}
|
|
90
|
+
updated(changed) {
|
|
91
|
+
if (!changed.has("shortcutsOpen")) return;
|
|
92
|
+
const dialog = this.renderRoot.querySelector("dialog");
|
|
93
|
+
if (!dialog) return;
|
|
94
|
+
if (this.shortcutsOpen && !dialog.open) dialog.showModal();
|
|
95
|
+
else if (!this.shortcutsOpen && dialog.open) dialog.close();
|
|
96
|
+
}
|
|
97
|
+
/** Close the keyboard shortcuts window */
|
|
98
|
+
closeShortcuts() {
|
|
99
|
+
this.shortcutsOpen = false;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Import the settings in a settings file, using the parts it has.
|
|
103
|
+
*/
|
|
104
|
+
async importFile(file) {
|
|
105
|
+
const app = this.app;
|
|
106
|
+
if (!app) return;
|
|
107
|
+
let text;
|
|
108
|
+
try {
|
|
109
|
+
text = await file.text();
|
|
110
|
+
} catch {
|
|
111
|
+
this.toastError(SETTINGS_FILE_ERRORS.read);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
applySettings(app, parseSettingsFile(text, [app.names.settingsFileFormat, SETTINGS_FILE_FORMAT]));
|
|
116
|
+
emit(this, "pc-toast", {
|
|
117
|
+
message: this.t("paintCanvas.settings.imported"),
|
|
118
|
+
kind: "success"
|
|
119
|
+
});
|
|
120
|
+
} catch (error) {
|
|
121
|
+
this.toastError(error instanceof SettingsFileError ? error.message : SETTINGS_FILE_ERRORS.read);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Export the settings as a settings file.
|
|
126
|
+
*/
|
|
127
|
+
async exportFile() {
|
|
128
|
+
const app = this.app;
|
|
129
|
+
if (!app) return;
|
|
130
|
+
try {
|
|
131
|
+
await this.saveFile(new Blob([exportSettingsFile(collectSettings(app), app.names.settingsFileFormat)], { type: "application/json" }), settingsFileName(void 0, app.names.filePrefix));
|
|
132
|
+
} catch {
|
|
133
|
+
emit(this, "pc-toast", {
|
|
134
|
+
message: this.t("paintCanvas.settings.exportFailed"),
|
|
135
|
+
kind: "error"
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Show a settings file error (one of `SETTINGS_FILE_ERRORS`) in the chosen language */
|
|
140
|
+
toastError(message) {
|
|
141
|
+
emit(this, "pc-toast", {
|
|
142
|
+
message: this.t(SETTINGS_FILE_ERROR_KEYS[message]),
|
|
143
|
+
kind: "error"
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** The keyboard shortcuts window: a modal dialog, with its contents only while open */
|
|
147
|
+
renderShortcuts(app) {
|
|
148
|
+
return html`<dialog
|
|
149
|
+
aria-labelledby="shortcuts-title"
|
|
150
|
+
@close=${() => this.closeShortcuts()}
|
|
151
|
+
@click=${(e) => {
|
|
152
|
+
if (e.target === e.currentTarget) this.closeShortcuts();
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
${this.shortcutsOpen ? html`<div class="window">
|
|
156
|
+
<div class="header">
|
|
157
|
+
<h2 id="shortcuts-title">
|
|
158
|
+
${this.t("paintCanvas.shortcuts.title")}
|
|
159
|
+
</h2>
|
|
160
|
+
<button
|
|
161
|
+
type="button"
|
|
162
|
+
class="close dismiss"
|
|
163
|
+
autofocus
|
|
164
|
+
@click=${() => this.closeShortcuts()}
|
|
165
|
+
>
|
|
166
|
+
${this.t("paintCanvas.common.close")}
|
|
167
|
+
</button>
|
|
168
|
+
</div>
|
|
169
|
+
<pc-shortcut-settings
|
|
170
|
+
.settings=${app.shortcuts}
|
|
171
|
+
></pc-shortcut-settings>
|
|
172
|
+
</div>` : nothing}
|
|
173
|
+
</dialog>`;
|
|
174
|
+
}
|
|
175
|
+
render() {
|
|
176
|
+
const app = this.app;
|
|
177
|
+
if (!app) return nothing;
|
|
178
|
+
return html`<div class="actions">
|
|
179
|
+
<button
|
|
180
|
+
type="button"
|
|
181
|
+
class="pill shortcuts"
|
|
182
|
+
aria-haspopup="dialog"
|
|
183
|
+
@click=${() => this.shortcutsOpen = true}
|
|
184
|
+
>
|
|
185
|
+
${this.t("paintCanvas.shortcuts.title")}
|
|
186
|
+
</button>
|
|
187
|
+
<button
|
|
188
|
+
type="button"
|
|
189
|
+
class="pill import"
|
|
190
|
+
@click=${() => this.renderRoot.querySelector(".import-file")?.click()}
|
|
191
|
+
>
|
|
192
|
+
${this.t("paintCanvas.settings.import")}
|
|
193
|
+
</button>
|
|
194
|
+
<button
|
|
195
|
+
type="button"
|
|
196
|
+
class="pill export"
|
|
197
|
+
@click=${() => void this.exportFile()}
|
|
198
|
+
>
|
|
199
|
+
${this.t("paintCanvas.settings.export")}
|
|
200
|
+
</button>
|
|
201
|
+
<!-- Chosen through "Import settings" -->
|
|
202
|
+
<label class="visually-hidden">
|
|
203
|
+
${this.t("paintCanvas.settings.importFile")}
|
|
204
|
+
<input
|
|
205
|
+
type="file"
|
|
206
|
+
class="import-file"
|
|
207
|
+
tabindex="-1"
|
|
208
|
+
accept="application/json,.json"
|
|
209
|
+
@change=${(e) => {
|
|
210
|
+
const input = e.target;
|
|
211
|
+
const file = input.files?.[0];
|
|
212
|
+
input.value = "";
|
|
213
|
+
if (file) this.importFile(file);
|
|
214
|
+
}}
|
|
215
|
+
/>
|
|
216
|
+
</label>
|
|
217
|
+
</div>
|
|
218
|
+
${this.renderShortcuts(app)}`;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
defineElement("pc-app-settings", PcAppSettings);
|
|
222
|
+
export { PcAppSettings };
|
|
@@ -23,7 +23,8 @@ export declare const SMOOTHING_CHOICES: readonly [{
|
|
|
23
23
|
readonly icon: "smoothingBezierCubic";
|
|
24
24
|
}];
|
|
25
25
|
/**
|
|
26
|
-
* The brush (or eraser) configuration window: a testing area, the shape (
|
|
26
|
+
* The brush (or eraser) configuration window: a testing area, the shape (pressing it picks a built-in shape from the
|
|
27
|
+
* device's own list, which says "Custom" for an uploaded or pasted one; or upload or paste one), smoothing, width, height,
|
|
27
28
|
* opacity, rotation, offsets, sample rate, spacing and snapping to the pixel grid. Width, height, opacity, rotation and the offsets can vary with
|
|
28
29
|
* pressure, tilt and randomness; when any is on, the setting has a min and max.
|
|
29
30
|
*
|
|
@@ -82,7 +83,9 @@ export declare class PcBrushConfig extends PcElement {
|
|
|
82
83
|
prompt: PromptFn;
|
|
83
84
|
/** Turns files into brush shapes (replaceable for tests) */
|
|
84
85
|
readShape: (file: File) => Promise<ShapeImage>;
|
|
85
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Reads a brush shape from the clipboard, or else from image data copied on the canvas (replaceable for tests)
|
|
88
|
+
*/
|
|
86
89
|
readClipboard: () => Promise<ShapeImage>;
|
|
87
90
|
private readonly onKeyDown;
|
|
88
91
|
constructor();
|
|
@@ -124,6 +127,10 @@ export declare class PcBrushConfig extends PcElement {
|
|
|
124
127
|
private slider;
|
|
125
128
|
/** Render a setting that can vary: its value (or min and max), and its pressure, tilt and randomise icon toggles */
|
|
126
129
|
private renderParam;
|
|
130
|
+
/**
|
|
131
|
+
* Use a built-in shape (see `BUILT_IN_SHAPES`), keeping the width; they're all square, so the height is the same.
|
|
132
|
+
*/
|
|
133
|
+
private useBuiltInShape;
|
|
127
134
|
/** Render the shape and smoothing row */
|
|
128
135
|
private renderShape;
|
|
129
136
|
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
@@ -6,8 +6,10 @@ import "../PcBrushTest/index.js";
|
|
|
6
6
|
import { SmoothingType } from "../../../lib/brushes/types/index.js";
|
|
7
7
|
import { PARAM_LIMITS, VARIATION_SOURCES, readRange, toggleSource, writeRange } from "../../../lib/brushes/configRanges/index.js";
|
|
8
8
|
import { SHAPE_ERRORS, ShapeImageError, readClipboardShape, readShapeImage } from "../../../lib/brushes/shapeImage/index.js";
|
|
9
|
+
import { BUILT_IN_SHAPES, builtInShapeId } from "../../../lib/brushes/shapes/index.js";
|
|
9
10
|
import "../../../lib/brushes/StrokeSampler/index.js";
|
|
10
11
|
import { html, nothing, unsafeCSS } from "lit";
|
|
12
|
+
import { live } from "lit/directives/live.js";
|
|
11
13
|
import { styleMap } from "lit/directives/style-map.js";
|
|
12
14
|
// src/ui/elements/PcBrushConfig/index.ts
|
|
13
15
|
/** The smoothing choices, in the order shown: value, translation key of the name, and icon name */
|
|
@@ -40,6 +42,8 @@ var SOURCE_LABELS = {
|
|
|
40
42
|
tilt: "paintCanvas.toolSettings.tilt",
|
|
41
43
|
randomise: "paintCanvas.brushConfig.randomise"
|
|
42
44
|
};
|
|
45
|
+
/** The shape picker's value for a shape the user uploaded or pasted */
|
|
46
|
+
var CUSTOM_SHAPE = "custom";
|
|
43
47
|
/** Translation keys of the brush shape error messages */
|
|
44
48
|
var SHAPE_ERROR_KEYS = {
|
|
45
49
|
[SHAPE_ERRORS.type]: "paintCanvas.shape.notPng",
|
|
@@ -55,7 +59,8 @@ var numberValue = (event) => {
|
|
|
55
59
|
return Number.isFinite(value) ? value : void 0;
|
|
56
60
|
};
|
|
57
61
|
/**
|
|
58
|
-
* The brush (or eraser) configuration window: a testing area, the shape (
|
|
62
|
+
* The brush (or eraser) configuration window: a testing area, the shape (pressing it picks a built-in shape from the
|
|
63
|
+
* device's own list, which says "Custom" for an uploaded or pasted one; or upload or paste one), smoothing, width, height,
|
|
59
64
|
* opacity, rotation, offsets, sample rate, spacing and snapping to the pixel grid. Width, height, opacity, rotation and the offsets can vary with
|
|
60
65
|
* pressure, tilt and randomness; when any is on, the setting has a min and max.
|
|
61
66
|
*
|
|
@@ -88,8 +93,10 @@ var PcBrushConfig = class extends PcElement {
|
|
|
88
93
|
prompt = (message, value) => window.prompt(message, value);
|
|
89
94
|
/** Turns files into brush shapes (replaceable for tests) */
|
|
90
95
|
readShape = readShapeImage;
|
|
91
|
-
/**
|
|
92
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Reads a brush shape from the clipboard, or else from image data copied on the canvas (replaceable for tests)
|
|
98
|
+
*/
|
|
99
|
+
readClipboard = () => readClipboardShape(navigator.clipboard, {}, async () => this.app?.copiedPng());
|
|
93
100
|
onKeyDown = (event) => {
|
|
94
101
|
if (event.key === "Escape") this.close();
|
|
95
102
|
};
|
|
@@ -295,15 +302,48 @@ var PcBrushConfig = class extends PcElement {
|
|
|
295
302
|
</label>`)}
|
|
296
303
|
</div>`;
|
|
297
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Use a built-in shape (see `BUILT_IN_SHAPES`), keeping the width; they're all square, so the height is the same.
|
|
307
|
+
*/
|
|
308
|
+
useBuiltInShape(id) {
|
|
309
|
+
const shape = BUILT_IN_SHAPES.find((built) => built.id === id);
|
|
310
|
+
if (!shape) return;
|
|
311
|
+
const width = this.draft?.width ?? 1;
|
|
312
|
+
this.change({
|
|
313
|
+
image: shape.image,
|
|
314
|
+
height: width
|
|
315
|
+
});
|
|
316
|
+
}
|
|
298
317
|
/** Render the shape and smoothing row */
|
|
299
318
|
renderShape(draft) {
|
|
319
|
+
const shapeId = builtInShapeId(draft.image);
|
|
300
320
|
const smoothing = draft.smoothingType === SmoothingType.None || draft.smoothingType === void 0 ? SmoothingType.Linear : draft.smoothingType;
|
|
301
321
|
return html`<div class="row shape-row">
|
|
302
322
|
<span class="label">${this.t("paintCanvas.brushConfig.shape")}</span>
|
|
303
|
-
<span
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
323
|
+
<span class="shape-picker">
|
|
324
|
+
<span
|
|
325
|
+
class=${draft.image ? "shape-preview image" : "shape-preview"}
|
|
326
|
+
style=${styleMap({ maskImage: typeof draft.image === "string" ? `url("${draft.image}")` : void 0 })}
|
|
327
|
+
></span>
|
|
328
|
+
<!-- Over the shape, so pressing it opens the device's own list -->
|
|
329
|
+
<select
|
|
330
|
+
class="shape-select"
|
|
331
|
+
aria-label=${this.t("paintCanvas.brushConfig.shape")}
|
|
332
|
+
title=${this.t("paintCanvas.brushConfig.chooseShape")}
|
|
333
|
+
?disabled=${this.busy}
|
|
334
|
+
@change=${(e) => this.useBuiltInShape(e.target.value)}
|
|
335
|
+
>
|
|
336
|
+
${shapeId === void 0 ? html`<option value=${CUSTOM_SHAPE} .selected=${true}>
|
|
337
|
+
${this.t("paintCanvas.brushConfig.customShape")}
|
|
338
|
+
</option>` : nothing}
|
|
339
|
+
${BUILT_IN_SHAPES.map((shape) => html`<option
|
|
340
|
+
value=${shape.id}
|
|
341
|
+
.selected=${live(shape.id === shapeId)}
|
|
342
|
+
>
|
|
343
|
+
${shape.name}
|
|
344
|
+
</option>`)}
|
|
345
|
+
</select>
|
|
346
|
+
</span>
|
|
307
347
|
<button
|
|
308
348
|
type="button"
|
|
309
349
|
class="pill upload"
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcBrushConfig/style.css?inline
|
|
2
|
-
var style_default = ":host {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--pc-backdrop);\n}\n[role=\"dialog\"] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n width: min(560px, 95vw);\n max-height: 95vh;\n overflow: auto;\n padding: 8px;\n background: var(--pc-surface);\n}\n.row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n}\n.row > .label {\n width: 6em;\n}\ninput[type=\"number\"] {\n width: 4.5em;\n}\ninput[type=\"range\"] {\n flex: 1;\n min-width: 60px;\n}\n.shape-preview {\n display: inline-block;\n width: 40px;\n height: 40px;\n background: var(--pc-text);\n border-radius: 50%;\n}\n.shape-preview.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: contain;\n mask-position: center;\n}\n/* The name, with \"Close\" on the right */\n.header .close {\n margin-left: auto;\n}\n/* The shape (preview, Upload and Paste) and the smoothing icons on one row */\n.shape-row {\n flex-wrap: nowrap;\n}\n
|
|
2
|
+
var style_default = ":host {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--pc-backdrop);\n}\n[role=\"dialog\"] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n width: min(560px, 95vw);\n max-height: 95vh;\n overflow: auto;\n padding: 8px;\n background: var(--pc-surface);\n}\n.row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n}\n.row > .label {\n width: 6em;\n}\ninput[type=\"number\"] {\n width: 4.5em;\n}\ninput[type=\"range\"] {\n flex: 1;\n min-width: 60px;\n}\n.shape-preview {\n display: inline-block;\n width: 40px;\n height: 40px;\n background: var(--pc-text);\n border-radius: 50%;\n}\n.shape-preview.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: contain;\n mask-position: center;\n}\n/* The name, with \"Close\" on the right */\n.header .close {\n margin-left: auto;\n}\n/* The shape (preview, Upload and Paste) and the smoothing icons on one row */\n.shape-row {\n flex-wrap: nowrap;\n}\n/* The shape, with an invisible list over it: pressing the shape opens the device's own list of shapes */\n.shape-picker {\n position: relative;\n display: inline-flex;\n flex: none;\n border-radius: var(--pc-radius-small);\n}\n.shape-picker:hover {\n background: var(--pc-surface-hover);\n}\n.shape-picker:focus-within {\n outline: var(--pc-focus-width) solid var(--pc-focus);\n}\n.shape-select {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\nfieldset.smoothing {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0 0 0 auto;\n padding: 0;\n border: 0;\n}\nfieldset.smoothing legend {\n float: left;\n margin-right: 4px;\n padding: 0;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { nothing } from "lit";
|
|
2
|
+
import { PcElement } from "../../base";
|
|
3
|
+
import "../PcNumberSlider";
|
|
4
|
+
import { type default as BrushSettings } from "../../../lib/classes/BrushSettings";
|
|
5
|
+
/**
|
|
6
|
+
* A brush's size as text: one number when the width and height are the same, otherwise "width × height".
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* sizeText({ width: 20, height: 20 }); // "20"
|
|
10
|
+
* sizeText({ width: 30, height: 10 }); // "30 × 10"
|
|
11
|
+
*/
|
|
12
|
+
export declare const sizeText: ({ width, height, }: {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}) => string;
|
|
16
|
+
/**
|
|
17
|
+
* A brush or eraser's size, as a `pc-number-slider`: pressed and dragged right or up it gets bigger, left or down
|
|
18
|
+
* smaller, keeping its proportions (see `BrushSettings.resize`). Tapping it lets you type the larger side's size. With
|
|
19
|
+
* keyboard focus, the arrow keys change it by a pixel and Page Up and Page Down by a step (like `]` and `[`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* html`<pc-brush-size .settings=${app.brush} label="Brush size"></pc-brush-size>`
|
|
23
|
+
*/
|
|
24
|
+
export declare class PcBrushSize extends PcElement {
|
|
25
|
+
static properties: {
|
|
26
|
+
settings: {
|
|
27
|
+
attribute: boolean;
|
|
28
|
+
};
|
|
29
|
+
label: {
|
|
30
|
+
type: StringConstructor;
|
|
31
|
+
};
|
|
32
|
+
translations: {
|
|
33
|
+
attribute: boolean;
|
|
34
|
+
};
|
|
35
|
+
icons: {
|
|
36
|
+
attribute: boolean;
|
|
37
|
+
};
|
|
38
|
+
theme: {
|
|
39
|
+
type: StringConstructor;
|
|
40
|
+
reflect: boolean;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
static styles: import("lit").CSSResultGroup[];
|
|
44
|
+
/** The brush or eraser settings it shows and changes */
|
|
45
|
+
settings?: BrushSettings;
|
|
46
|
+
/** Its name for screen readers, e.g. "Brush size" */
|
|
47
|
+
label: string;
|
|
48
|
+
private changes;
|
|
49
|
+
constructor();
|
|
50
|
+
/** Resize to the slider's value (the larger side), keeping the proportions */
|
|
51
|
+
private onChange;
|
|
52
|
+
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
53
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PcElement, defineElement } from "../../base/index.js";
|
|
2
|
+
import ChangeController from "../../ChangeController/index.js";
|
|
3
|
+
import "../PcNumberSlider/index.js";
|
|
4
|
+
import { BRUSH_SIZE_STEP } from "../../../lib/classes/BrushSettings/index.js";
|
|
5
|
+
import { css, html, nothing } from "lit";
|
|
6
|
+
import { live } from "lit/directives/live.js";
|
|
7
|
+
// src/ui/elements/PcBrushSize/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* A brush's size as text: one number when the width and height are the same, otherwise "width × height".
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* sizeText({ width: 20, height: 20 }); // "20"
|
|
13
|
+
* sizeText({ width: 30, height: 10 }); // "30 × 10"
|
|
14
|
+
*/
|
|
15
|
+
var sizeText = ({ width, height }) => width === height ? String(width) : `${width} × ${height}`;
|
|
16
|
+
/**
|
|
17
|
+
* A brush or eraser's size, as a `pc-number-slider`: pressed and dragged right or up it gets bigger, left or down
|
|
18
|
+
* smaller, keeping its proportions (see `BrushSettings.resize`). Tapping it lets you type the larger side's size. With
|
|
19
|
+
* keyboard focus, the arrow keys change it by a pixel and Page Up and Page Down by a step (like `]` and `[`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* html`<pc-brush-size .settings=${app.brush} label="Brush size"></pc-brush-size>`
|
|
23
|
+
*/
|
|
24
|
+
var PcBrushSize = class extends PcElement {
|
|
25
|
+
static properties = {
|
|
26
|
+
...PcElement.properties,
|
|
27
|
+
settings: { attribute: false },
|
|
28
|
+
label: { type: String }
|
|
29
|
+
};
|
|
30
|
+
static styles = [PcElement.styles, css`
|
|
31
|
+
:host {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
}
|
|
34
|
+
pc-number-slider {
|
|
35
|
+
flex: 1;
|
|
36
|
+
}
|
|
37
|
+
`];
|
|
38
|
+
changes = new ChangeController(this, () => [this.settings]);
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
this.label = "";
|
|
42
|
+
}
|
|
43
|
+
/** Resize to the slider's value (the larger side), keeping the proportions */
|
|
44
|
+
onChange(event) {
|
|
45
|
+
const settings = this.settings;
|
|
46
|
+
settings.resize(event.detail.value - settings.largerSide);
|
|
47
|
+
this.requestUpdate();
|
|
48
|
+
}
|
|
49
|
+
render() {
|
|
50
|
+
const settings = this.settings;
|
|
51
|
+
if (!settings) return nothing;
|
|
52
|
+
const larger = settings.largerSide;
|
|
53
|
+
return html`<pc-number-slider
|
|
54
|
+
exportparts="control, field"
|
|
55
|
+
min=${1}
|
|
56
|
+
max=${256}
|
|
57
|
+
page-step=${Math.max(1, Math.round(larger * BRUSH_SIZE_STEP))}
|
|
58
|
+
label=${this.label}
|
|
59
|
+
.value=${live(larger)}
|
|
60
|
+
.text=${sizeText(settings)}
|
|
61
|
+
@pc-change=${this.onChange}
|
|
62
|
+
></pc-number-slider>`;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
defineElement("pc-brush-size", PcBrushSize);
|
|
66
|
+
export { PcBrushSize, sizeText };
|
|
@@ -8,9 +8,18 @@ export declare const TEST_AREA_WIDTH = 800;
|
|
|
8
8
|
export declare const TEST_AREA_HEIGHT = 320;
|
|
9
9
|
/** The colour test strokes are drawn in, whatever the current colour */
|
|
10
10
|
export declare const TEST_COLOUR = "#000000";
|
|
11
|
+
/** The colour of the circles showing a stroke's sampled points, while stroke points are shown */
|
|
12
|
+
export declare const POINT_COLOUR = "#e8175d";
|
|
13
|
+
/** The colour of the dots showing where a stroke placed its stamps, while stroke points are shown */
|
|
14
|
+
export declare const STAMP_COLOUR = "#1e88e5";
|
|
15
|
+
/** How long a finished stroke's points stay shown (milliseconds) */
|
|
16
|
+
export declare const STROKE_POINTS_MS = 3000;
|
|
11
17
|
/**
|
|
12
18
|
* A small area to try brush settings before saving them: strokes are drawn in black, at the settings' own size, on a
|
|
13
19
|
* white background at double resolution (800 × 320 pixels shown in the window's width). "Clear" (a red pill) empties it.
|
|
20
|
+
* "Show stroke points" draws the stroke's sampled points (pink circles) and where it placed stamps (blue dots) over it,
|
|
21
|
+
* like the canvas's debug overlay, to see how sampling and smoothing work. They go 3 seconds after the stroke ends, or
|
|
22
|
+
* on "Clear".
|
|
14
23
|
*
|
|
15
24
|
* @example
|
|
16
25
|
* html`<pc-brush-test .config=${config} .tips=${app.tips}></pc-brush-test>`
|
|
@@ -23,6 +32,10 @@ export declare class PcBrushTest extends PcElement {
|
|
|
23
32
|
tips: {
|
|
24
33
|
attribute: boolean;
|
|
25
34
|
};
|
|
35
|
+
showPoints: {
|
|
36
|
+
type: BooleanConstructor;
|
|
37
|
+
attribute: string;
|
|
38
|
+
};
|
|
26
39
|
translations: {
|
|
27
40
|
attribute: boolean;
|
|
28
41
|
};
|
|
@@ -39,6 +52,9 @@ export declare class PcBrushTest extends PcElement {
|
|
|
39
52
|
config?: BrushConfig;
|
|
40
53
|
/** Brush shapes */
|
|
41
54
|
tips?: BrushTipCache;
|
|
55
|
+
/** Whether the last stroke's sampled points and stamps are drawn over it */
|
|
56
|
+
showPoints: boolean;
|
|
57
|
+
constructor();
|
|
42
58
|
/** Creates the layer and stroke canvases (replaceable for tests) */
|
|
43
59
|
createCanvas: CanvasFactory;
|
|
44
60
|
private layer?;
|
|
@@ -46,6 +62,8 @@ export declare class PcBrushTest extends PcElement {
|
|
|
46
62
|
/** The pointer drawing, if any */
|
|
47
63
|
private pointerId?;
|
|
48
64
|
private readonly onEngineChange;
|
|
65
|
+
/** Clears the finished stroke's points once they've been shown long enough */
|
|
66
|
+
private pointsTimer?;
|
|
49
67
|
disconnectedCallback(): void;
|
|
50
68
|
/** The visible canvas */
|
|
51
69
|
private get canvas();
|
|
@@ -61,11 +79,19 @@ export declare class PcBrushTest extends PcElement {
|
|
|
61
79
|
private onPointerMove;
|
|
62
80
|
/** Finish the test stroke */
|
|
63
81
|
private onPointerUp;
|
|
82
|
+
/** Stop showing the last stroke's points and stamps (still recording the next stroke's while shown) */
|
|
83
|
+
private clearPoints;
|
|
84
|
+
/**
|
|
85
|
+
* Show or hide the last stroke's sampled points and stamps. They're recorded from the next stroke.
|
|
86
|
+
*/
|
|
87
|
+
setShowPoints(shown: boolean): void;
|
|
64
88
|
/**
|
|
65
89
|
* Empty the testing area.
|
|
66
90
|
*/
|
|
67
91
|
clear(): void;
|
|
68
92
|
/** Show the layer (with any stroke in progress) on the visible canvas */
|
|
69
93
|
private paint;
|
|
94
|
+
/** Draw the last stroke's sampled points (circles) and stamp positions (dots) */
|
|
95
|
+
private paintPoints;
|
|
70
96
|
render(): import("lit").TemplateResult<1>;
|
|
71
97
|
}
|