@lvl99dotcom/paintcanvas 0.4.0 → 0.6.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/configRanges/index.d.ts +17 -0
- package/dist/lib/brushes/configRanges/index.js +31 -1
- package/dist/lib/brushes/params/index.d.ts +2 -1
- package/dist/lib/brushes/params/index.js +7 -4
- 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/brushes/types/index.d.ts +8 -0
- package/dist/lib/classes/BrushSettings/index.d.ts +29 -2
- package/dist/lib/classes/BrushSettings/index.js +51 -14
- package/dist/lib/classes/KeyboardShortcuts/index.d.ts +31 -2
- package/dist/lib/classes/KeyboardShortcuts/index.js +66 -4
- package/dist/lib/classes/Layer/index.d.ts +10 -0
- package/dist/lib/classes/Layer/index.js +15 -1
- package/dist/lib/classes/LayerAutosave/index.d.ts +9 -15
- package/dist/lib/classes/LayerAutosave/index.js +30 -43
- package/dist/lib/classes/LayerStack/index.d.ts +15 -0
- package/dist/lib/classes/LayerStack/index.js +26 -2
- package/dist/lib/classes/PaintCanvas/index.d.ts +72 -3
- package/dist/lib/classes/PaintCanvas/index.js +106 -12
- package/dist/lib/classes/PngEncoder/index.d.ts +41 -0
- package/dist/lib/classes/PngEncoder/index.js +104 -0
- package/dist/lib/classes/ProfileGraphs/index.d.ts +87 -0
- package/dist/lib/classes/ProfileGraphs/index.js +148 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +3 -2
- package/dist/lib/classes/SettingsAutosave/index.js +6 -3
- package/dist/lib/classes/UiSettings/index.d.ts +68 -0
- package/dist/lib/classes/UiSettings/index.js +82 -0
- package/dist/lib/messages/schema.d.ts +720 -0
- package/dist/lib/presets/schema.d.ts +360 -0
- package/dist/lib/presets/schema.js +8 -1
- package/dist/lib/profiles/index.d.ts +61 -0
- package/dist/lib/profiles/index.js +131 -0
- package/dist/lib/profiles/schema.d.ts +73 -0
- package/dist/lib/profiles/schema.js +53 -0
- package/dist/lib/rendering/sample/index.d.ts +11 -0
- package/dist/lib/rendering/sample/index.js +36 -5
- package/dist/lib/settings/index.d.ts +2 -1
- package/dist/lib/settings/index.js +7 -2
- package/dist/lib/settings/schema.d.ts +67 -0
- package/dist/lib/settings/schema.js +20 -0
- package/dist/lib/validation/validators.generated.js +13191 -3655
- package/dist/locales/en-GB.js +39 -2
- package/dist/locales/en-US.js +39 -2
- package/dist/locales/fr.js +39 -2
- package/dist/locales/ja.js +39 -2
- package/dist/locales/ko.js +39 -2
- package/dist/locales/zh-Hans.js +39 -2
- package/dist/locales/zh-Hant.js +39 -2
- package/dist/package.js +1 -1
- package/dist/testing/recordingCanvas.js +2 -1
- package/dist/ui/ask/index.d.ts +48 -0
- package/dist/ui/ask/index.js +67 -0
- package/dist/ui/base/index.d.ts +10 -3
- package/dist/ui/base/index.js +19 -4
- 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 +17 -12
- package/dist/ui/elements/PaintCanvas/index.js +36 -17
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +6 -6
- package/dist/ui/elements/PcAppSettings/index.js +21 -65
- package/dist/ui/elements/PcBrushConfig/index.d.ts +34 -16
- package/dist/ui/elements/PcBrushConfig/index.js +263 -153
- 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 +79 -6
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcButton/index.d.ts +12 -3
- package/dist/ui/elements/PcButton/index.js +18 -10
- package/dist/ui/elements/PcCanvas/index.d.ts +27 -2
- package/dist/ui/elements/PcCanvas/index.js +63 -13
- package/dist/ui/elements/PcCanvas/style.js +1 -1
- package/dist/ui/elements/PcCanvasMap/style.js +1 -1
- package/dist/ui/elements/PcClipboardTools/index.d.ts +49 -0
- package/dist/ui/elements/PcClipboardTools/index.js +125 -0
- package/dist/ui/elements/PcContextMenu/index.d.ts +2 -2
- package/dist/ui/elements/PcDialog/index.d.ts +46 -10
- package/dist/ui/elements/PcDialog/index.js +102 -51
- package/dist/ui/elements/PcDialogWindow/index.d.ts +141 -0
- package/dist/ui/elements/PcDialogWindow/index.js +385 -0
- package/dist/ui/elements/PcInputSettings/index.d.ts +13 -0
- package/dist/ui/elements/PcInputSettings/index.js +16 -1
- package/dist/ui/elements/PcMenu/index.d.ts +48 -3
- package/dist/ui/elements/PcMenu/index.js +111 -19
- 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 +3 -1
- package/dist/ui/elements/PcPane/index.js +44 -7
- package/dist/ui/elements/PcPanel/index.d.ts +2 -2
- package/dist/ui/elements/PcPanel/index.js +8 -8
- package/dist/ui/elements/PcPanelBrushes/index.d.ts +5 -17
- package/dist/ui/elements/PcPanelBrushes/index.js +13 -48
- package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
- package/dist/ui/elements/PcPanelColours/index.js +2 -2
- package/dist/ui/elements/PcPanelColours/style.js +1 -1
- package/dist/ui/elements/PcPanelLayers/index.js +1 -1
- package/dist/ui/elements/PcPanelLayers/style.js +1 -1
- package/dist/ui/elements/PcPopover/index.d.ts +39 -1
- package/dist/ui/elements/PcPopover/index.js +72 -4
- package/dist/ui/elements/PcProfileEditor/index.d.ts +103 -0
- package/dist/ui/elements/PcProfileEditor/index.js +259 -0
- package/dist/ui/elements/PcProfileGraph/index.d.ts +84 -0
- package/dist/ui/elements/PcProfileGraph/index.js +317 -0
- package/dist/ui/elements/PcShortcutSettings/index.js +9 -13
- package/dist/ui/elements/PcSliderRange/index.d.ts +147 -0
- package/dist/ui/elements/PcSliderRange/index.js +307 -0
- package/dist/ui/elements/PcStats/index.d.ts +19 -4
- package/dist/ui/elements/PcStats/index.js +29 -13
- 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 +382 -318
- package/dist/ui/elements/PcToolSettings/style.js +1 -1
- package/dist/ui/elements/PcToolbar/index.d.ts +15 -0
- package/dist/ui/elements/PcToolbar/index.js +55 -14
- 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-profile-graph@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 +86 -72
- package/dist/ui/index.d.ts +13 -3
- package/dist/ui/index.js +15 -4
- package/dist/ui/layout/index.d.ts +9 -1
- package/dist/ui/layout/index.js +11 -2
- package/dist/ui/styles/index.d.ts +21 -1
- package/dist/ui/styles/index.js +73 -14
- package/dist/ui/tokens/index.d.ts +5 -4
- package/dist/ui/tokens/index.js +12 -7
- package/locales/en-GB.json +39 -2
- package/locales/en-US.json +39 -2
- package/locales/fr.json +39 -2
- package/locales/ja.json +39 -2
- package/locales/ko.json +39 -2
- package/locales/zh-Hans.json +39 -2
- package/locales/zh-Hant.json +39 -2
- package/package.json +27 -18
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import style_default from "./style.js";
|
|
2
2
|
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
3
|
+
import { markDismissingPress } from "../../dismiss/index.js";
|
|
3
4
|
import ChangeController from "../../ChangeController/index.js";
|
|
4
5
|
import PaintCanvas, { Panel } from "../../../lib/classes/PaintCanvas/index.js";
|
|
5
6
|
import KeyboardShortcuts, { SHORTCUT_EVENT } from "../../../lib/classes/KeyboardShortcuts/index.js";
|
|
@@ -13,7 +14,8 @@ import { DEFAULT_SIDE_MODES, STATE_EVENT, parseSideModes, sideModeFor } from "..
|
|
|
13
14
|
import { hasToolSettings } from "../PcToolSettings/index.js";
|
|
14
15
|
import "../PcPanel/index.js";
|
|
15
16
|
import { PANE_COLLAPSE_EVENT, PcPane } from "../PcPane/index.js";
|
|
16
|
-
import "../PcToolbar/index.js";
|
|
17
|
+
import { PcToolbar } from "../PcToolbar/index.js";
|
|
18
|
+
import "../PcClipboardTools/index.js";
|
|
17
19
|
import "../PcCanvas/index.js";
|
|
18
20
|
import "../PcCanvasMap/index.js";
|
|
19
21
|
import "../PcPanelBrushes/index.js";
|
|
@@ -40,8 +42,10 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
40
42
|
* window), with slots to add or replace content:
|
|
41
43
|
*
|
|
42
44
|
* - `header`: across the top (empty by default)
|
|
43
|
-
* - `left`: `<pc-toolbar>` (a pane) by default
|
|
44
|
-
*
|
|
45
|
+
* - `left`: `<pc-toolbar>` (a pane) by default; toolbars in the sides are minimised (their tools one button that opens a
|
|
46
|
+
* menu of them) while the layout is narrow
|
|
47
|
+
* - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) and, at its end,
|
|
48
|
+
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow) by default
|
|
45
49
|
* - `right`: a `<pc-pane>` with `<pc-panel-layers>` by default
|
|
46
50
|
* - `center`: `<pc-canvas>` by default
|
|
47
51
|
* - `overlay`: drawn over the canvas; `<pc-canvas-map>` by default
|
|
@@ -55,8 +59,9 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
55
59
|
*
|
|
56
60
|
* Each side has a mode, chosen by the layout's width from `left-modes` and `right-modes` (default `"docked,
|
|
57
61
|
* rail@600"`), which the layout gives the side's `<pc-pane>`s (see `PcPane`): `docked` beside the canvas; `rail`, a
|
|
58
|
-
* column of buttons (one per panel) that open each panel over the canvas;
|
|
59
|
-
* box that collapses to a button
|
|
62
|
+
* column of buttons (one per panel) that open each panel over the canvas; `floating`, the pane over the canvas as a
|
|
63
|
+
* box that collapses to a button; or `overlay`, a rail over the canvas without a background (the canvas fills the
|
|
64
|
+
* width behind it). Give side content in a `<pc-pane>` to have it follow the side's mode.
|
|
60
65
|
*
|
|
61
66
|
* Reports its state for styling as attributes (`narrow`, `input="pen|touch|mouse"`, `ui-hidden`, `left-mode`,
|
|
62
67
|
* `right-mode`) and as `pc-state-change` events (see `LayoutState`). Creates its own canvas unless given one, and
|
|
@@ -66,8 +71,8 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
66
71
|
* reloading the page (see `LayerAutosave`). While another window is drawing on it, the layout is blocked by a message
|
|
67
72
|
* that offers to draw here instead. Fires `pc-toast` when the drawing can't be loaded or saved.
|
|
68
73
|
*
|
|
69
|
-
* With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette
|
|
70
|
-
*
|
|
74
|
+
* With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette, colours,
|
|
75
|
+
* theme and language) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when they can't be.
|
|
71
76
|
*
|
|
72
77
|
* @example
|
|
73
78
|
* html`<paint-canvas style="height: 600px"></paint-canvas>`
|
|
@@ -137,7 +142,7 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
137
142
|
keys;
|
|
138
143
|
/** The state last reported, to report only changes */
|
|
139
144
|
reported;
|
|
140
|
-
/** Space the floating sides cover over the canvas */
|
|
145
|
+
/** Space the floating and overlay sides cover over the canvas */
|
|
141
146
|
floatingInsets = NO_INSETS;
|
|
142
147
|
resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(([entry]) => {
|
|
143
148
|
this.width = Math.round(entry?.contentRect.width ?? 0);
|
|
@@ -157,7 +162,7 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
157
162
|
onShortcut = (event) => {
|
|
158
163
|
if (event.detail.type === "save") this.saveScreenshot();
|
|
159
164
|
};
|
|
160
|
-
onDocumentPointerDown = (event) => this.
|
|
165
|
+
onDocumentPointerDown = (event) => this.closePanelOutside(event);
|
|
161
166
|
onPaneCollapse = () => this.requestUpdate();
|
|
162
167
|
constructor() {
|
|
163
168
|
super();
|
|
@@ -233,16 +238,18 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
233
238
|
const given = slot.assignedElements();
|
|
234
239
|
return (given.length ? given : [...slot.children]).filter((element) => element instanceof PcPane);
|
|
235
240
|
}
|
|
236
|
-
/** Show each side's panes in the side's mode, facing the canvas */
|
|
241
|
+
/** Show each side's panes in the side's mode, facing the canvas, with toolbars minimised while the layout is narrow */
|
|
237
242
|
setPaneModes() {
|
|
243
|
+
const narrow = this.width < this.narrowWidth;
|
|
238
244
|
for (const side of SIDES) for (const pane of this.panesIn(side)) {
|
|
239
245
|
pane.mode = this.modeOf(side);
|
|
240
246
|
pane.edge = side;
|
|
247
|
+
if (pane instanceof PcToolbar) pane.minimised = narrow;
|
|
241
248
|
}
|
|
242
249
|
}
|
|
243
|
-
/** Keep the canvas clear of floating sides when fitting it */
|
|
250
|
+
/** Keep the canvas clear of floating and overlay sides when fitting it */
|
|
244
251
|
measureFloatingSides() {
|
|
245
|
-
const width = (side) => this.panesIn(side).filter((pane) => pane.mode === "floating"
|
|
252
|
+
const width = (side) => this.panesIn(side).filter((pane) => pane.mode === "floating" ? !pane.collapsed : pane.mode === "overlay").reduce((widest, pane) => Math.max(widest, pane.getBoundingClientRect().width), 0);
|
|
246
253
|
const insets = {
|
|
247
254
|
...NO_INSETS,
|
|
248
255
|
left: width("left"),
|
|
@@ -419,12 +426,16 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
419
426
|
</div>`;
|
|
420
427
|
}
|
|
421
428
|
/**
|
|
422
|
-
* Close the colour palette on a press outside it and the
|
|
429
|
+
* Close the open panel (brush, eraser, layers, app menu or colour palette) on a press outside it and the button that
|
|
430
|
+
* opens it, marking the press (see `markDismissingPress`) so the canvas doesn't draw unless it's dragged. Presses in
|
|
431
|
+
* dialogs (e.g. one the panel opened) don't count as outside.
|
|
423
432
|
*/
|
|
424
|
-
|
|
425
|
-
const
|
|
426
|
-
if (
|
|
427
|
-
if (
|
|
433
|
+
closePanelOutside(event) {
|
|
434
|
+
const panel = this.app?.panel;
|
|
435
|
+
if (!panel) return;
|
|
436
|
+
if (event.composedPath().some((target) => target instanceof Element && (target.classList.contains("panel") && target.getRootNode() === this.renderRoot || target.matches("dialog, pc-dialog, pc-dialog-window") || target.getAttribute("data-panel") === panel || panel === Panel.Palette && target.localName === "pc-colour-pair"))) return;
|
|
437
|
+
markDismissingPress(event);
|
|
438
|
+
this.app.closePanel();
|
|
428
439
|
}
|
|
429
440
|
/** The menus the toolbar opens, floating over the canvas beside it */
|
|
430
441
|
renderPanels(app) {
|
|
@@ -473,6 +484,8 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
473
484
|
}];
|
|
474
485
|
return html`<pc-dialog
|
|
475
486
|
class="elsewhere"
|
|
487
|
+
inline
|
|
488
|
+
.dismissible=${false}
|
|
476
489
|
heading=${this.t("paintCanvas.autosave.elsewhere")}
|
|
477
490
|
message=${this.t("paintCanvas.autosave.elsewhereMessage")}
|
|
478
491
|
.choices=${choices}
|
|
@@ -502,11 +515,17 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
502
515
|
.app=${app}
|
|
503
516
|
@pc-configure-brush=${(event) => this.configure(event.detail)}
|
|
504
517
|
></pc-tool-settings
|
|
518
|
+
><pc-clipboard-tools
|
|
519
|
+
slot="end"
|
|
520
|
+
.app=${app}
|
|
521
|
+
?narrow=${this.width < this.narrowWidth}
|
|
522
|
+
></pc-clipboard-tools
|
|
505
523
|
></pc-pane>` : nothing)}
|
|
506
524
|
</div>
|
|
507
525
|
<div
|
|
508
526
|
class="center"
|
|
509
527
|
part="center"
|
|
528
|
+
style="--pc-left-inset: ${this.floatingInsets.left}px"
|
|
510
529
|
role="region"
|
|
511
530
|
aria-label=${this.t("paintCanvas.layout.canvas")}
|
|
512
531
|
?inert=${blocked}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PaintCanvas/style.css?inline
|
|
2
|
-
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n/* The tool settings fill the top pane */\n.top pc-tool-settings {\n flex: 1;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n/* A side's panes fill it */\n.side pc-pane,\n.side pc-toolbar,\n.side ::slotted(*) {\n flex: 1;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n/* The app menu: the implementer's content in a panel */\n.menu-panel:not([open]) {\n display: none;\n}\n\n/* Floating: the side's panes float over the canvas (see pc-pane), so the side takes no space */\n.side[data-mode=\"floating\"] {\n /* Beside the canvas only, so it floats over the canvas and not the tool settings */\n grid-row: 3;\n width: 0;\n}\n/*
|
|
2
|
+
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n/* The tool settings fill the top pane */\n.top pc-tool-settings {\n flex: 1;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n/* A side's panes fill it */\n.side pc-pane,\n.side pc-toolbar,\n.side ::slotted(*) {\n flex: 1;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n/* The app menu: the implementer's content in a panel */\n.menu-panel:not([open]) {\n display: none;\n}\n\n/* Floating: the side's panes float over the canvas (see pc-pane), so the side takes no space */\n.side[data-mode=\"floating\"] {\n /* Beside the canvas only, so it floats over the canvas and not the tool settings */\n grid-row: 3;\n width: 0;\n}\n/* Overlay: the side's rail sits over the canvas (beside it only, not the tool settings), so the canvas fills the\n width behind it; presses between its panes' buttons (which take presses themselves) reach the canvas */\n.side[data-mode=\"overlay\"] {\n grid-row: 3;\n grid-column: 1 / -1;\n pointer-events: none;\n}\n.side.left[data-mode=\"overlay\"] {\n justify-self: start;\n}\n.side.right[data-mode=\"overlay\"] {\n justify-self: end;\n}\n/* The toolbar's panels open beside a left overlay rail, not under it */\n:host([left-mode=\"overlay\"]) .panel {\n left: var(--pc-left-inset);\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { nothing
|
|
1
|
+
import { nothing } from "lit";
|
|
2
2
|
import { PcElement } from "../../base";
|
|
3
3
|
import "../PcShortcutSettings";
|
|
4
|
+
import "../PcDialogWindow";
|
|
4
5
|
import type PaintCanvas from "../../../lib/classes/PaintCanvas";
|
|
5
6
|
import { type SaveMethod } from "../../../lib/rendering/screenshot";
|
|
6
7
|
/**
|
|
7
8
|
* Buttons for the user's app settings: "Keyboard shortcuts", which opens a window to change them (see
|
|
8
9
|
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
9
|
-
* settings, keyboard shortcuts, colour palette and
|
|
10
|
-
* closes with its
|
|
11
|
-
* exporting fails.
|
|
10
|
+
* settings, keyboard shortcuts, colour palette, colours, profile graphs, theme and language). The window is a shaded
|
|
11
|
+
* `<pc-dialog-window>` over the whole page; it closes with its ⨉ button, Escape or a press outside it, and focus goes
|
|
12
|
+
* back to the button. Fires `pc-toast` after importing, or when importing or exporting fails.
|
|
12
13
|
*
|
|
13
14
|
* @example
|
|
14
15
|
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
@@ -40,7 +41,6 @@ export declare class PcAppSettings extends PcElement {
|
|
|
40
41
|
/** Saves exported files (replaceable for tests) */
|
|
41
42
|
saveFile: (blob: Blob, name: string) => Promise<SaveMethod | undefined>;
|
|
42
43
|
constructor();
|
|
43
|
-
protected updated(changed: PropertyValues<this>): void;
|
|
44
44
|
/** Close the keyboard shortcuts window */
|
|
45
45
|
closeShortcuts(): void;
|
|
46
46
|
/**
|
|
@@ -53,7 +53,7 @@ export declare class PcAppSettings extends PcElement {
|
|
|
53
53
|
exportFile(): Promise<void>;
|
|
54
54
|
/** Show a settings file error (one of `SETTINGS_FILE_ERRORS`) in the chosen language */
|
|
55
55
|
private toastError;
|
|
56
|
-
/** The keyboard shortcuts window
|
|
56
|
+
/** The keyboard shortcuts window, with its contents only while open */
|
|
57
57
|
private renderShortcuts;
|
|
58
58
|
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
59
59
|
}
|
|
@@ -2,6 +2,7 @@ import { SETTINGS_FILE_FORMAT } from "../../../lib/settings/schema.js";
|
|
|
2
2
|
import { ICON_CONTROLS_CSS, PILLS_CSS, WINDOWS_CSS } from "../../styles/index.js";
|
|
3
3
|
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
4
4
|
import "../PcShortcutSettings/index.js";
|
|
5
|
+
import "../PcDialogWindow/index.js";
|
|
5
6
|
import { SETTINGS_FILE_ERRORS, SettingsFileError, applySettings, collectSettings, exportSettingsFile, parseSettingsFile, settingsFileName } from "../../../lib/settings/index.js";
|
|
6
7
|
import { JSON_FILE_TYPE, saveFile } from "../../../lib/rendering/screenshot/index.js";
|
|
7
8
|
import { css, html, nothing, unsafeCSS } from "lit";
|
|
@@ -14,9 +15,9 @@ var SETTINGS_FILE_ERROR_KEYS = {
|
|
|
14
15
|
/**
|
|
15
16
|
* Buttons for the user's app settings: "Keyboard shortcuts", which opens a window to change them (see
|
|
16
17
|
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
17
|
-
* settings, keyboard shortcuts, colour palette and
|
|
18
|
-
* closes with its
|
|
19
|
-
* exporting fails.
|
|
18
|
+
* settings, keyboard shortcuts, colour palette, colours, profile graphs, theme and language). The window is a shaded
|
|
19
|
+
* `<pc-dialog-window>` over the whole page; it closes with its ⨉ button, Escape or a press outside it, and focus goes
|
|
20
|
+
* back to the button. Fires `pc-toast` after importing, or when importing or exporting fails.
|
|
20
21
|
*
|
|
21
22
|
* @example
|
|
22
23
|
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
@@ -48,32 +49,8 @@ var PcAppSettings = class extends PcElement {
|
|
|
48
49
|
flex-wrap: wrap;
|
|
49
50
|
gap: var(--pc-space-2);
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
52
|
+
pc-dialog-window {
|
|
53
|
+
--pc-dialog-width: 480px;
|
|
77
54
|
}
|
|
78
55
|
h2 {
|
|
79
56
|
margin: 0;
|
|
@@ -87,13 +64,6 @@ var PcAppSettings = class extends PcElement {
|
|
|
87
64
|
super();
|
|
88
65
|
this.shortcutsOpen = false;
|
|
89
66
|
}
|
|
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
67
|
/** Close the keyboard shortcuts window */
|
|
98
68
|
closeShortcuts() {
|
|
99
69
|
this.shortcutsOpen = false;
|
|
@@ -143,34 +113,20 @@ var PcAppSettings = class extends PcElement {
|
|
|
143
113
|
kind: "error"
|
|
144
114
|
});
|
|
145
115
|
}
|
|
146
|
-
/** The keyboard shortcuts window
|
|
116
|
+
/** The keyboard shortcuts window, with its contents only while open */
|
|
147
117
|
renderShortcuts(app) {
|
|
148
|
-
return html`<dialog
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}}
|
|
118
|
+
return html`<pc-dialog-window
|
|
119
|
+
class="shortcuts-window"
|
|
120
|
+
shaded
|
|
121
|
+
?open=${this.shortcutsOpen}
|
|
122
|
+
@pc-dismiss=${() => this.closeShortcuts()}
|
|
154
123
|
>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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>`;
|
|
124
|
+
<h2 slot="header-middle">${this.t("paintCanvas.shortcuts.title")}</h2>
|
|
125
|
+
${this.shortcutsOpen ? html`<pc-shortcut-settings
|
|
126
|
+
slot="body"
|
|
127
|
+
.settings=${app.shortcuts}
|
|
128
|
+
></pc-shortcut-settings>` : nothing}
|
|
129
|
+
</pc-dialog-window>`;
|
|
174
130
|
}
|
|
175
131
|
render() {
|
|
176
132
|
const app = this.app;
|
|
@@ -178,7 +134,7 @@ var PcAppSettings = class extends PcElement {
|
|
|
178
134
|
return html`<div class="actions">
|
|
179
135
|
<button
|
|
180
136
|
type="button"
|
|
181
|
-
class="pill shortcuts"
|
|
137
|
+
class="pill-s shortcuts"
|
|
182
138
|
aria-haspopup="dialog"
|
|
183
139
|
@click=${() => this.shortcutsOpen = true}
|
|
184
140
|
>
|
|
@@ -186,14 +142,14 @@ var PcAppSettings = class extends PcElement {
|
|
|
186
142
|
</button>
|
|
187
143
|
<button
|
|
188
144
|
type="button"
|
|
189
|
-
class="pill import"
|
|
145
|
+
class="pill-s import"
|
|
190
146
|
@click=${() => this.renderRoot.querySelector(".import-file")?.click()}
|
|
191
147
|
>
|
|
192
148
|
${this.t("paintCanvas.settings.import")}
|
|
193
149
|
</button>
|
|
194
150
|
<button
|
|
195
151
|
type="button"
|
|
196
|
-
class="pill export"
|
|
152
|
+
class="pill-s export"
|
|
197
153
|
@click=${() => void this.exportFile()}
|
|
198
154
|
>
|
|
199
155
|
${this.t("paintCanvas.settings.export")}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { nothing } from "lit";
|
|
2
|
+
import { type ConfirmFn, type PromptFn } from "../../ask";
|
|
2
3
|
import { PcElement } from "../../base";
|
|
3
4
|
import "../PcBrushTest";
|
|
5
|
+
import "../PcDialogWindow";
|
|
6
|
+
import "../PcSliderRange";
|
|
7
|
+
import "../PcProfileEditor";
|
|
4
8
|
import type PaintCanvas from "../../../lib/classes/PaintCanvas";
|
|
5
9
|
import { SmoothingType, type BrushConfig } from "../../../lib/brushes/types";
|
|
10
|
+
import { type VaryingParam } from "../../../lib/brushes/configRanges";
|
|
6
11
|
import { type ShapeImage } from "../../../lib/brushes/shapeImage";
|
|
7
|
-
|
|
8
|
-
export type ConfirmFn = (message: string) => boolean;
|
|
9
|
-
/** Asks the user for text; replaceable for tests */
|
|
10
|
-
export type PromptFn = (message: string, value: string) => string | null;
|
|
12
|
+
export type { ConfirmFn, PromptFn } from "../../ask";
|
|
11
13
|
/** The smoothing choices, in the order shown: value, translation key of the name, and icon name */
|
|
12
14
|
export declare const SMOOTHING_CHOICES: readonly [{
|
|
13
15
|
readonly value: SmoothingType.Linear;
|
|
@@ -23,14 +25,16 @@ export declare const SMOOTHING_CHOICES: readonly [{
|
|
|
23
25
|
readonly icon: "smoothingBezierCubic";
|
|
24
26
|
}];
|
|
25
27
|
/**
|
|
26
|
-
* The brush (or eraser) configuration window: a testing area, the shape (
|
|
28
|
+
* The brush (or eraser) configuration window: a testing area, the shape (pressing it picks a built-in shape from the
|
|
29
|
+
* device's own list, which says "Custom" for an uploaded or pasted one; or upload or paste one), smoothing, width, height,
|
|
27
30
|
* opacity, rotation, offsets, sample rate, spacing and snapping to the pixel grid. Width, height, opacity, rotation and the offsets can vary with
|
|
28
|
-
* pressure, tilt and randomness; when any is on, the setting has a min and max
|
|
31
|
+
* pressure, tilt and randomness; when any is on, the setting has a min and max, set with a `<pc-slider-range>`.
|
|
29
32
|
*
|
|
30
33
|
* Changes stay in the window until "Save" (fires `pc-save` with the settings, to apply to the current tool) or "Add to
|
|
31
34
|
* presets" (saves them as one of the user's presets, asking before replacing one with the same name, and selects it).
|
|
32
|
-
* "Delete preset…" shows when editing one of the user's presets.
|
|
33
|
-
*
|
|
35
|
+
* "Delete preset…" shows when editing one of the user's presets. It's a shaded `<pc-dialog-window>`, closed with its ⨉
|
|
36
|
+
* button or Escape (not a press outside it, which would lose the changes). Fires `pc-close` when closed, and `pc-toast`
|
|
37
|
+
* with a message after adding or deleting a preset, or when a shape can't be used.
|
|
34
38
|
*
|
|
35
39
|
* @example
|
|
36
40
|
* html`<pc-brush-config .app=${app} kind="brush" .config=${app.brush.preset} @pc-save=${apply}></pc-brush-config>`
|
|
@@ -55,6 +59,9 @@ export declare class PcBrushConfig extends PcElement {
|
|
|
55
59
|
busy: {
|
|
56
60
|
state: boolean;
|
|
57
61
|
};
|
|
62
|
+
editingProfile: {
|
|
63
|
+
state: boolean;
|
|
64
|
+
};
|
|
58
65
|
translations: {
|
|
59
66
|
attribute: boolean;
|
|
60
67
|
};
|
|
@@ -78,16 +85,19 @@ export declare class PcBrushConfig extends PcElement {
|
|
|
78
85
|
draft?: BrushConfig;
|
|
79
86
|
/** Whether a preset is being saved or deleted */
|
|
80
87
|
busy: boolean;
|
|
88
|
+
/** The setting whose profile graph is being edited, if any */
|
|
89
|
+
editingProfile?: VaryingParam;
|
|
90
|
+
/** Asks the user to confirm, in a dialog (replaceable for tests) */
|
|
81
91
|
confirm: ConfirmFn;
|
|
92
|
+
/** Asks the user for text, in a dialog (replaceable for tests) */
|
|
82
93
|
prompt: PromptFn;
|
|
83
94
|
/** Turns files into brush shapes (replaceable for tests) */
|
|
84
95
|
readShape: (file: File) => Promise<ShapeImage>;
|
|
85
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* Reads a brush shape from the clipboard, or else from image data copied on the canvas (replaceable for tests)
|
|
98
|
+
*/
|
|
86
99
|
readClipboard: () => Promise<ShapeImage>;
|
|
87
|
-
private readonly onKeyDown;
|
|
88
100
|
constructor();
|
|
89
|
-
connectedCallback(): void;
|
|
90
|
-
disconnectedCallback(): void;
|
|
91
101
|
protected willUpdate(changed: Map<PropertyKey, unknown>): void;
|
|
92
102
|
/** Fire an event that crosses shadow DOM boundaries */
|
|
93
103
|
private emit;
|
|
@@ -118,13 +128,21 @@ export declare class PcBrushConfig extends PcElement {
|
|
|
118
128
|
* Delete the preset being edited, after confirming.
|
|
119
129
|
*/
|
|
120
130
|
deletePreset(): Promise<void>;
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
private
|
|
131
|
+
/**
|
|
132
|
+
* Render a slider for one value (a single `<pc-slider-range>`), the same as the ranges of settings that vary.
|
|
133
|
+
*/
|
|
134
|
+
private single;
|
|
125
135
|
/** Render a setting that can vary: its value (or min and max), and its pressure, tilt and randomise icon toggles */
|
|
126
136
|
private renderParam;
|
|
137
|
+
/**
|
|
138
|
+
* Use a built-in shape (see `BUILT_IN_SHAPES`), keeping the width; they're all square, so the height is the same.
|
|
139
|
+
*/
|
|
140
|
+
private useBuiltInShape;
|
|
127
141
|
/** Render the shape and smoothing row */
|
|
128
142
|
private renderShape;
|
|
129
143
|
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
144
|
+
/** The profile graph editor for the setting being edited, while open */
|
|
145
|
+
private renderProfileEditor;
|
|
146
|
+
/** Profile graphs, when there's no canvas to keep them */
|
|
147
|
+
private readonly profiles;
|
|
130
148
|
}
|