@lvl99dotcom/paintcanvas 0.4.0 → 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/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 +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/PaintCanvas/index.d.ts +46 -0
- package/dist/lib/classes/PaintCanvas/index.js +67 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +3 -2
- package/dist/lib/classes/SettingsAutosave/index.js +5 -3
- package/dist/lib/classes/UiSettings/index.d.ts +68 -0
- package/dist/lib/classes/UiSettings/index.js +82 -0
- package/dist/lib/settings/index.d.ts +1 -1
- package/dist/lib/settings/index.js +4 -2
- package/dist/lib/settings/schema.d.ts +18 -0
- package/dist/lib/settings/schema.js +14 -0
- package/dist/lib/validation/validators.generated.js +169 -1
- package/dist/locales/en-GB.js +9 -2
- package/dist/locales/en-US.js +9 -2
- package/dist/locales/fr.js +9 -2
- package/dist/locales/ja.js +9 -2
- package/dist/locales/ko.js +9 -2
- package/dist/locales/zh-Hans.js +9 -2
- package/dist/locales/zh-Hant.js +9 -2
- 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 +17 -12
- package/dist/ui/elements/PaintCanvas/index.js +34 -17
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +1 -1
- package/dist/ui/elements/PcAppSettings/index.js +1 -1
- 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 +21 -1
- package/dist/ui/elements/PcCanvas/index.js +53 -10
- 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/PcContextMenu/index.d.ts +2 -2
- 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 +2 -15
- package/dist/ui/elements/PcPanelBrushes/index.js +6 -43
- package/dist/ui/elements/PcPanelBrushes/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/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-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 +7 -2
- package/dist/ui/index.js +10 -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 +12 -7
- package/locales/en-GB.json +9 -2
- package/locales/en-US.json +9 -2
- package/locales/fr.json +9 -2
- package/locales/ja.json +9 -2
- package/locales/ko.json +9 -2
- package/locales/zh-Hans.json +9 -2
- package/locales/zh-Hant.json +9 -2
- package/package.json +11 -4
- 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,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
|
}
|
|
@@ -10,9 +10,20 @@ var TEST_AREA_WIDTH = 800;
|
|
|
10
10
|
var TEST_AREA_HEIGHT = 320;
|
|
11
11
|
/** The colour test strokes are drawn in, whatever the current colour */
|
|
12
12
|
var TEST_COLOUR = "#000000";
|
|
13
|
+
/** The colour of the circles showing a stroke's sampled points, while stroke points are shown */
|
|
14
|
+
var POINT_COLOUR = "#e8175d";
|
|
15
|
+
/** The colour of the dots showing where a stroke placed its stamps, while stroke points are shown */
|
|
16
|
+
var STAMP_COLOUR = "#1e88e5";
|
|
17
|
+
/** How long a finished stroke's points stay shown (milliseconds) */
|
|
18
|
+
var STROKE_POINTS_MS = 3e3;
|
|
19
|
+
/** Radius of the circles showing a stroke's sampled points (test area pixels) */
|
|
20
|
+
var POINT_RADIUS = 8;
|
|
13
21
|
/**
|
|
14
22
|
* A small area to try brush settings before saving them: strokes are drawn in black, at the settings' own size, on a
|
|
15
23
|
* white background at double resolution (800 × 320 pixels shown in the window's width). "Clear" (a red pill) empties it.
|
|
24
|
+
* "Show stroke points" draws the stroke's sampled points (pink circles) and where it placed stamps (blue dots) over it,
|
|
25
|
+
* like the canvas's debug overlay, to see how sampling and smoothing work. They go 3 seconds after the stroke ends, or
|
|
26
|
+
* on "Clear".
|
|
16
27
|
*
|
|
17
28
|
* @example
|
|
18
29
|
* html`<pc-brush-test .config=${config} .tips=${app.tips}></pc-brush-test>`
|
|
@@ -21,9 +32,17 @@ var PcBrushTest = class extends PcElement {
|
|
|
21
32
|
static properties = {
|
|
22
33
|
...PcElement.properties,
|
|
23
34
|
config: { attribute: false },
|
|
24
|
-
tips: { attribute: false }
|
|
35
|
+
tips: { attribute: false },
|
|
36
|
+
showPoints: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
attribute: "show-points"
|
|
39
|
+
}
|
|
25
40
|
};
|
|
26
41
|
static styles = [PcElement.styles, unsafeCSS(style_default)];
|
|
42
|
+
constructor() {
|
|
43
|
+
super();
|
|
44
|
+
this.showPoints = false;
|
|
45
|
+
}
|
|
27
46
|
/** Creates the layer and stroke canvases (replaceable for tests) */
|
|
28
47
|
createCanvas = createOffscreenCanvas;
|
|
29
48
|
layer;
|
|
@@ -31,8 +50,11 @@ var PcBrushTest = class extends PcElement {
|
|
|
31
50
|
/** The pointer drawing, if any */
|
|
32
51
|
pointerId;
|
|
33
52
|
onEngineChange = () => this.paint();
|
|
53
|
+
/** Clears the finished stroke's points once they've been shown long enough */
|
|
54
|
+
pointsTimer;
|
|
34
55
|
disconnectedCallback() {
|
|
35
56
|
super.disconnectedCallback();
|
|
57
|
+
clearTimeout(this.pointsTimer);
|
|
36
58
|
this.engine?.removeEventListener("change", this.onEngineChange);
|
|
37
59
|
}
|
|
38
60
|
/** The visible canvas */
|
|
@@ -45,6 +67,7 @@ var PcBrushTest = class extends PcElement {
|
|
|
45
67
|
if (!this.engine) {
|
|
46
68
|
this.engine = new StrokeEngine(800, 320, this.createCanvas);
|
|
47
69
|
this.engine.addEventListener("change", this.onEngineChange);
|
|
70
|
+
this.engine.setDebug(this.showPoints);
|
|
48
71
|
}
|
|
49
72
|
return {
|
|
50
73
|
layer: this.layer,
|
|
@@ -72,6 +95,7 @@ var PcBrushTest = class extends PcElement {
|
|
|
72
95
|
const config = this.config;
|
|
73
96
|
if (!config || !this.tips || event.button !== 0) return;
|
|
74
97
|
const { layer, engine } = this.drawing;
|
|
98
|
+
clearTimeout(this.pointsTimer);
|
|
75
99
|
this.pointerId = event.pointerId;
|
|
76
100
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
77
101
|
engine.begin({
|
|
@@ -98,12 +122,29 @@ var PcBrushTest = class extends PcElement {
|
|
|
98
122
|
this.pointerId = void 0;
|
|
99
123
|
this.engine?.end(this.point(event), event.timeStamp);
|
|
100
124
|
this.paint();
|
|
125
|
+
clearTimeout(this.pointsTimer);
|
|
126
|
+
this.pointsTimer = setTimeout(() => this.clearPoints(), STROKE_POINTS_MS);
|
|
127
|
+
}
|
|
128
|
+
/** Stop showing the last stroke's points and stamps (still recording the next stroke's while shown) */
|
|
129
|
+
clearPoints() {
|
|
130
|
+
clearTimeout(this.pointsTimer);
|
|
131
|
+
this.engine?.setDebug(this.showPoints);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Show or hide the last stroke's sampled points and stamps. They're recorded from the next stroke.
|
|
135
|
+
*/
|
|
136
|
+
setShowPoints(shown) {
|
|
137
|
+
const changed = shown !== this.showPoints;
|
|
138
|
+
this.showPoints = shown;
|
|
139
|
+
if (changed) this.engine?.setDebug(shown);
|
|
140
|
+
this.paint();
|
|
101
141
|
}
|
|
102
142
|
/**
|
|
103
143
|
* Empty the testing area.
|
|
104
144
|
*/
|
|
105
145
|
clear() {
|
|
106
146
|
this.engine?.cancel();
|
|
147
|
+
this.clearPoints();
|
|
107
148
|
this.layer?.context.clearRect(0, 0, 800, 320);
|
|
108
149
|
this.paint();
|
|
109
150
|
}
|
|
@@ -114,6 +155,23 @@ var PcBrushTest = class extends PcElement {
|
|
|
114
155
|
ctx.clearRect(0, 0, 800, 320);
|
|
115
156
|
const image = this.engine?.preview?.image ?? this.layer?.canvas;
|
|
116
157
|
if (image) ctx.drawImage(image, 0, 0);
|
|
158
|
+
if (this.showPoints && this.engine) this.paintPoints(ctx, this.engine);
|
|
159
|
+
}
|
|
160
|
+
/** Draw the last stroke's sampled points (circles) and stamp positions (dots) */
|
|
161
|
+
paintPoints(ctx, engine) {
|
|
162
|
+
const { points, stamps } = engine.debugTrace;
|
|
163
|
+
ctx.save();
|
|
164
|
+
ctx.fillStyle = STAMP_COLOUR;
|
|
165
|
+
for (const { x, y } of stamps) ctx.fillRect(x - 2, y - 2, 4, 4);
|
|
166
|
+
ctx.strokeStyle = POINT_COLOUR;
|
|
167
|
+
ctx.lineWidth = 2;
|
|
168
|
+
ctx.beginPath();
|
|
169
|
+
for (const { x, y } of points) {
|
|
170
|
+
ctx.moveTo(x + POINT_RADIUS, y);
|
|
171
|
+
ctx.arc(x, y, POINT_RADIUS, 0, Math.PI * 2);
|
|
172
|
+
}
|
|
173
|
+
ctx.stroke();
|
|
174
|
+
ctx.restore();
|
|
117
175
|
}
|
|
118
176
|
render() {
|
|
119
177
|
return html`
|
|
@@ -126,11 +184,21 @@ var PcBrushTest = class extends PcElement {
|
|
|
126
184
|
@pointerup=${this.onPointerUp}
|
|
127
185
|
@pointercancel=${this.onPointerUp}
|
|
128
186
|
></canvas>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
187
|
+
<div class="actions">
|
|
188
|
+
<button type="button" class="clear" @click=${() => this.clear()}>
|
|
189
|
+
${this.t("paintCanvas.common.clear")}
|
|
190
|
+
</button>
|
|
191
|
+
<label class="show-points">
|
|
192
|
+
<input
|
|
193
|
+
type="checkbox"
|
|
194
|
+
.checked=${this.showPoints}
|
|
195
|
+
@change=${(e) => this.setShowPoints(e.target.checked)}
|
|
196
|
+
/>
|
|
197
|
+
${this.t("paintCanvas.brushConfig.showStrokePoints")}
|
|
198
|
+
</label>
|
|
199
|
+
</div>
|
|
132
200
|
`;
|
|
133
201
|
}
|
|
134
202
|
};
|
|
135
203
|
defineElement("pc-brush-test", PcBrushTest);
|
|
136
|
-
export { PcBrushTest, TEST_AREA_HEIGHT, TEST_AREA_WIDTH, TEST_COLOUR };
|
|
204
|
+
export { POINT_COLOUR, PcBrushTest, STAMP_COLOUR, STROKE_POINTS_MS, TEST_AREA_HEIGHT, TEST_AREA_WIDTH, TEST_COLOUR };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcBrushTest/style.css?inline
|
|
2
|
-
var style_default = ":host {\n display: block;\n}\ncanvas {\n display: block;\n width: 100%;\n background: #fff;\n border: 1px solid var(--pc-border);\n touch-action: none;\n}\n/* \"Clear\"
|
|
2
|
+
var style_default = ":host {\n display: block;\n}\ncanvas {\n display: block;\n width: 100%;\n background: #fff;\n border: 1px solid var(--pc-border);\n touch-action: none;\n}\n/* \"Clear\", then \"Show stroke points\" */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin-top: 6px;\n}\n.show-points {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n cursor: pointer;\n}\n/* \"Clear\": a red pill */\nbutton.clear {\n padding: 4px 16px;\n border: 0;\n border-radius: 999px;\n background: var(--pc-red);\n color: #ffffff;\n font: inherit;\n font-weight: bold;\n cursor: pointer;\n}\nbutton.clear:hover {\n filter: brightness(1.1);\n}\nbutton.clear:focus-visible {\n outline: var(--pc-focus-width) solid var(--pc-focus);\n outline-offset: 2px;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -123,6 +123,8 @@ export declare class PcCanvas extends PcElement {
|
|
|
123
123
|
private drag;
|
|
124
124
|
/** Pointer drawing the current stroke, and the layer it draws on */
|
|
125
125
|
private stroke;
|
|
126
|
+
/** A press that closed a panel or menu, held until it moves far enough to count (see `onPointerDown`) */
|
|
127
|
+
private heldPress;
|
|
126
128
|
/** Pointer position over the stage (for the brush cursor), or null when outside */
|
|
127
129
|
private hover;
|
|
128
130
|
/** Name of the key held to zoom with the scroll wheel (replaceable for tests) */
|
|
@@ -256,15 +258,33 @@ export declare class PcCanvas extends PcElement {
|
|
|
256
258
|
* Get a pointer's position relative to the stage.
|
|
257
259
|
*/
|
|
258
260
|
private pointerPoint;
|
|
261
|
+
/**
|
|
262
|
+
* Send a pointer's events to the canvas until it's lifted, even outside it.
|
|
263
|
+
*/
|
|
264
|
+
private capturePointer;
|
|
265
|
+
/**
|
|
266
|
+
* Handle a press, unless it closed a panel or menu (see `isDismissingPress`): that press is held, and only starts
|
|
267
|
+
* drawing (or whatever the tool does) once it moves `DRAG_THRESHOLD` pixels, so tapping the canvas to close a panel
|
|
268
|
+
* leaves no mark.
|
|
269
|
+
*/
|
|
270
|
+
private onPointerDown;
|
|
271
|
+
/**
|
|
272
|
+
* Start a held press (see `onPointerDown`) once it moves far enough. Returns whether the pointer is still held.
|
|
273
|
+
*/
|
|
274
|
+
private releaseHeldPress;
|
|
259
275
|
/**
|
|
260
276
|
* Start panning, or zoom, depending on the tool and button. In focus pen mode, touches only pan, pinch and make
|
|
261
277
|
* gestures, and are ignored while a pen is down or just lifted (see `focusPenTouch`).
|
|
262
278
|
*/
|
|
263
|
-
private
|
|
279
|
+
private pointerDown;
|
|
264
280
|
/**
|
|
265
281
|
* Continue a stroke (using every in-between event the browser recorded), pan while dragging, and move the brush cursor.
|
|
266
282
|
*/
|
|
267
283
|
private onPointerMove;
|
|
284
|
+
/**
|
|
285
|
+
* Forget a held press lifted (or cancelled) before it moved far enough. Returns whether it was one.
|
|
286
|
+
*/
|
|
287
|
+
private dropHeldPress;
|
|
268
288
|
/**
|
|
269
289
|
* Finish a stroke (writing it into the layer) or stop panning.
|
|
270
290
|
*/
|
|
@@ -4,6 +4,8 @@ import style_default from "./style.js";
|
|
|
4
4
|
import { NO_TEXT_SELECTION_CSS } from "../../styles/index.js";
|
|
5
5
|
import { PcElement, defineElement } from "../../base/index.js";
|
|
6
6
|
import ChangeController from "../../ChangeController/index.js";
|
|
7
|
+
import { isDismissingPress } from "../../dismiss/index.js";
|
|
8
|
+
import "../../drag/index.js";
|
|
7
9
|
import "../../../lib/classes/PaintCanvas/index.js";
|
|
8
10
|
import { PASTEBOARD_COLOUR, drawScene } from "../../../lib/rendering/compositing/index.js";
|
|
9
11
|
import { drawBrushCursor } from "../../../lib/rendering/cursor/index.js";
|
|
@@ -172,6 +174,8 @@ var PcCanvas = class extends PcElement {
|
|
|
172
174
|
drag = null;
|
|
173
175
|
/** Pointer drawing the current stroke, and the layer it draws on */
|
|
174
176
|
stroke = null;
|
|
177
|
+
/** A press that closed a panel or menu, held until it moves far enough to count (see `onPointerDown`) */
|
|
178
|
+
heldPress = null;
|
|
175
179
|
/** Pointer position over the stage (for the brush cursor), or null when outside */
|
|
176
180
|
hover = null;
|
|
177
181
|
/** Name of the key held to zoom with the scroll wheel (replaceable for tests) */
|
|
@@ -425,7 +429,7 @@ var PcCanvas = class extends PcElement {
|
|
|
425
429
|
point: app.viewport.screenToCanvas(screen),
|
|
426
430
|
constrain: app.constrainProportions
|
|
427
431
|
};
|
|
428
|
-
|
|
432
|
+
this.capturePointer(event.pointerId);
|
|
429
433
|
}
|
|
430
434
|
/**
|
|
431
435
|
* Update the transform box while dragging.
|
|
@@ -499,7 +503,7 @@ var PcCanvas = class extends PcElement {
|
|
|
499
503
|
const point = this.pointerPoint(event);
|
|
500
504
|
const first = app.lasso.nodes[0];
|
|
501
505
|
const nearFirstNode = first !== void 0 && isNear(app.viewport.canvasToScreen(first), point, 8);
|
|
502
|
-
if (kind !== "polygon")
|
|
506
|
+
if (kind !== "polygon") this.capturePointer(event.pointerId);
|
|
503
507
|
app.applyLasso(app.lasso.down(kind, app.viewport.screenToCanvas(point), event, nearFirstNode));
|
|
504
508
|
}
|
|
505
509
|
/**
|
|
@@ -563,7 +567,7 @@ var PcCanvas = class extends PcElement {
|
|
|
563
567
|
pointerId: event.pointerId,
|
|
564
568
|
layerId: layer.id
|
|
565
569
|
};
|
|
566
|
-
|
|
570
|
+
this.capturePointer(event.pointerId);
|
|
567
571
|
const erasing = app.activeTool === Tool.Eraser;
|
|
568
572
|
app.strokes.begin({
|
|
569
573
|
layer,
|
|
@@ -594,12 +598,42 @@ var PcCanvas = class extends PcElement {
|
|
|
594
598
|
};
|
|
595
599
|
}
|
|
596
600
|
/**
|
|
601
|
+
* Send a pointer's events to the canvas until it's lifted, even outside it.
|
|
602
|
+
*/
|
|
603
|
+
capturePointer(pointerId) {
|
|
604
|
+
this.renderRoot.querySelector("canvas.scene")?.setPointerCapture?.(pointerId);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Handle a press, unless it closed a panel or menu (see `isDismissingPress`): that press is held, and only starts
|
|
608
|
+
* drawing (or whatever the tool does) once it moves `DRAG_THRESHOLD` pixels, so tapping the canvas to close a panel
|
|
609
|
+
* leaves no mark.
|
|
610
|
+
*/
|
|
611
|
+
onPointerDown(event) {
|
|
612
|
+
if (!this.app) return;
|
|
613
|
+
if (!isDismissingPress(event)) {
|
|
614
|
+
this.pointerDown(event);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
this.heldPress = event;
|
|
618
|
+
this.capturePointer(event.pointerId);
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Start a held press (see `onPointerDown`) once it moves far enough. Returns whether the pointer is still held.
|
|
622
|
+
*/
|
|
623
|
+
releaseHeldPress(event) {
|
|
624
|
+
const held = this.heldPress;
|
|
625
|
+
if (held?.pointerId !== event.pointerId) return false;
|
|
626
|
+
if (Math.hypot(event.clientX - held.clientX, event.clientY - held.clientY) < 4) return true;
|
|
627
|
+
this.heldPress = null;
|
|
628
|
+
this.pointerDown(held);
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
597
632
|
* Start panning, or zoom, depending on the tool and button. In focus pen mode, touches only pan, pinch and make
|
|
598
633
|
* gestures, and are ignored while a pen is down or just lifted (see `focusPenTouch`).
|
|
599
634
|
*/
|
|
600
|
-
|
|
635
|
+
pointerDown(event) {
|
|
601
636
|
const app = this.app;
|
|
602
|
-
if (!app) return;
|
|
603
637
|
if (event.pointerType === "pen") this.penDown(event);
|
|
604
638
|
if (event.pointerType === "touch") {
|
|
605
639
|
const ignored = this.focusPenTouch(event);
|
|
@@ -632,7 +666,7 @@ var PcCanvas = class extends PcElement {
|
|
|
632
666
|
pointerId: event.pointerId,
|
|
633
667
|
last: point
|
|
634
668
|
};
|
|
635
|
-
|
|
669
|
+
this.capturePointer(event.pointerId);
|
|
636
670
|
this.updateCursor();
|
|
637
671
|
} else if (app.activeTool === Tool.Zoom && event.button === 0) {
|
|
638
672
|
if (event.altKey) app.viewport.zoomOut(point);
|
|
@@ -645,6 +679,7 @@ var PcCanvas = class extends PcElement {
|
|
|
645
679
|
onPointerMove(event) {
|
|
646
680
|
const app = this.app;
|
|
647
681
|
if (!app || this.ignoredTouches.has(event.pointerId)) return;
|
|
682
|
+
if (this.releaseHeldPress(event)) return;
|
|
648
683
|
const point = this.pointerPoint(event);
|
|
649
684
|
if (this.touches.has(event.pointerId)) {
|
|
650
685
|
this.touches.set(event.pointerId, point);
|
|
@@ -680,10 +715,18 @@ var PcCanvas = class extends PcElement {
|
|
|
680
715
|
this.requestOverlay();
|
|
681
716
|
}
|
|
682
717
|
/**
|
|
718
|
+
* Forget a held press lifted (or cancelled) before it moved far enough. Returns whether it was one.
|
|
719
|
+
*/
|
|
720
|
+
dropHeldPress(event) {
|
|
721
|
+
if (this.heldPress?.pointerId !== event.pointerId) return false;
|
|
722
|
+
this.heldPress = null;
|
|
723
|
+
return true;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
683
726
|
* Finish a stroke (writing it into the layer) or stop panning.
|
|
684
727
|
*/
|
|
685
728
|
onPointerUp(event) {
|
|
686
|
-
if (this.ignoredTouches.delete(event.pointerId)) return;
|
|
729
|
+
if (this.ignoredTouches.delete(event.pointerId) || this.dropHeldPress(event)) return;
|
|
687
730
|
this.penUp(event);
|
|
688
731
|
this.touchUp(event);
|
|
689
732
|
if (this.sampling?.pointerId === event.pointerId) this.finishSample();
|
|
@@ -713,7 +756,7 @@ var PcCanvas = class extends PcElement {
|
|
|
713
756
|
* Abandon a stroke or pan when the browser cancels the pointer (e.g. a system gesture).
|
|
714
757
|
*/
|
|
715
758
|
onPointerCancel(event) {
|
|
716
|
-
if (this.ignoredTouches.delete(event.pointerId)) return;
|
|
759
|
+
if (this.ignoredTouches.delete(event.pointerId) || this.dropHeldPress(event)) return;
|
|
717
760
|
this.navigationTouches.delete(event.pointerId);
|
|
718
761
|
this.penUp(event);
|
|
719
762
|
this.touchUp(event);
|
|
@@ -791,7 +834,7 @@ var PcCanvas = class extends PcElement {
|
|
|
791
834
|
this.drag = null;
|
|
792
835
|
const [a, b] = [...this.touches.values()];
|
|
793
836
|
this.pinch = touchPair(a, b);
|
|
794
|
-
|
|
837
|
+
this.capturePointer(event.pointerId);
|
|
795
838
|
}
|
|
796
839
|
return true;
|
|
797
840
|
}
|
|
@@ -809,7 +852,7 @@ var PcCanvas = class extends PcElement {
|
|
|
809
852
|
point,
|
|
810
853
|
screen
|
|
811
854
|
};
|
|
812
|
-
|
|
855
|
+
this.capturePointer(event.pointerId);
|
|
813
856
|
this.updateCursor();
|
|
814
857
|
this.drawOverlay();
|
|
815
858
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcCanvasMap/style.css?inline
|
|
2
|
-
var style_default = ":host {\n display: block;\n position: relative;\n touch-action: none;\n /* A solid grey border, drawn outside so the map and its frame keep their size and position */\n outline: 1px solid var(--pc-border);\n}\ncanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n/* The part of the canvas the user can see */\n.frame {\n position: absolute;\n outline: 1px solid var(--pc-
|
|
2
|
+
var style_default = ":host {\n display: block;\n position: relative;\n touch-action: none;\n /* A solid grey border, drawn outside so the map and its frame keep their size and position */\n outline: 1px solid var(--pc-map-border);\n}\ncanvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n/* The part of the canvas the user can see */\n.frame {\n position: absolute;\n outline: 1px solid var(--pc-map-frame);\n pointer-events: none;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { nothing } from "lit";
|
|
2
|
+
import { PcElement } from "../../base";
|
|
3
|
+
import PaintCanvas, { Tool } from "../../../lib/classes/PaintCanvas";
|
|
4
|
+
import "../PcContextMenu";
|
|
5
|
+
/** The tools that cut, copy and paste are shown for: the brush, eraser, lassos and Move tool */
|
|
6
|
+
export declare const CLIPBOARD_TOOLS: readonly Tool[];
|
|
7
|
+
/**
|
|
8
|
+
* Cut, copy and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and Move tool
|
|
9
|
+
* (see `CLIPBOARD_TOOLS`). Cut and copy work while there's a mask and no transform is pending; paste while there's
|
|
10
|
+
* copied image data. While `narrow`, they're one ⋮ menu (`pc-context-menu`) instead.
|
|
11
|
+
*
|
|
12
|
+
* `<paint-canvas>` puts it at the end of its top pane, after the tool settings.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* html`<pc-clipboard-tools .app=${app} ?narrow=${narrow}></pc-clipboard-tools>`
|
|
16
|
+
*/
|
|
17
|
+
export declare class PcClipboardTools extends PcElement {
|
|
18
|
+
static properties: {
|
|
19
|
+
app: {
|
|
20
|
+
attribute: boolean;
|
|
21
|
+
};
|
|
22
|
+
narrow: {
|
|
23
|
+
type: BooleanConstructor;
|
|
24
|
+
reflect: boolean;
|
|
25
|
+
};
|
|
26
|
+
translations: {
|
|
27
|
+
attribute: boolean;
|
|
28
|
+
};
|
|
29
|
+
icons: {
|
|
30
|
+
attribute: boolean;
|
|
31
|
+
};
|
|
32
|
+
theme: {
|
|
33
|
+
type: StringConstructor;
|
|
34
|
+
reflect: boolean;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
static styles: import("lit").CSSResultGroup[];
|
|
38
|
+
app?: PaintCanvas;
|
|
39
|
+
/** Whether the buttons are one ⋮ menu (e.g. while the layout is narrow) */
|
|
40
|
+
narrow: boolean;
|
|
41
|
+
private changes;
|
|
42
|
+
constructor();
|
|
43
|
+
/** Cut, copy and paste, each with whether it can be done now */
|
|
44
|
+
private actions;
|
|
45
|
+
/** Hide for tools without clipboard actions (e.g. zoom) */
|
|
46
|
+
protected willUpdate(): void;
|
|
47
|
+
render(): import("lit").TemplateResult<1> | typeof nothing | import("lit").TemplateResult<1>[];
|
|
48
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Tool } from "../../../lib/classes/PaintCanvas/tool.js";
|
|
2
|
+
import { PcElement, defineElement } from "../../base/index.js";
|
|
3
|
+
import ChangeController from "../../ChangeController/index.js";
|
|
4
|
+
import { PILLS_CSS } from "../../styles/index.js";
|
|
5
|
+
import "../../../lib/classes/PaintCanvas/index.js";
|
|
6
|
+
import "../PcContextMenu/index.js";
|
|
7
|
+
import { css, html, nothing, unsafeCSS } from "lit";
|
|
8
|
+
// src/ui/elements/PcClipboardTools/index.ts
|
|
9
|
+
/** The tools that cut, copy and paste are shown for: the brush, eraser, lassos and Move tool */
|
|
10
|
+
var CLIPBOARD_TOOLS = [
|
|
11
|
+
Tool.Brush,
|
|
12
|
+
Tool.Eraser,
|
|
13
|
+
Tool.RectangleLasso,
|
|
14
|
+
Tool.CircleLasso,
|
|
15
|
+
Tool.PolygonLasso,
|
|
16
|
+
Tool.FreeformLasso,
|
|
17
|
+
Tool.Move
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Cut, copy and paste buttons for the canvas's masked image data, shown for the brush, eraser, lassos and Move tool
|
|
21
|
+
* (see `CLIPBOARD_TOOLS`). Cut and copy work while there's a mask and no transform is pending; paste while there's
|
|
22
|
+
* copied image data. While `narrow`, they're one ⋮ menu (`pc-context-menu`) instead.
|
|
23
|
+
*
|
|
24
|
+
* `<paint-canvas>` puts it at the end of its top pane, after the tool settings.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* html`<pc-clipboard-tools .app=${app} ?narrow=${narrow}></pc-clipboard-tools>`
|
|
28
|
+
*/
|
|
29
|
+
var PcClipboardTools = class extends PcElement {
|
|
30
|
+
static properties = {
|
|
31
|
+
...PcElement.properties,
|
|
32
|
+
app: { attribute: false },
|
|
33
|
+
narrow: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
reflect: true
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
static styles = [
|
|
39
|
+
PcElement.styles,
|
|
40
|
+
unsafeCSS(PILLS_CSS),
|
|
41
|
+
css`
|
|
42
|
+
:host {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex: none;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: 8px;
|
|
47
|
+
padding: 4px 8px;
|
|
48
|
+
background: var(--pc-bar);
|
|
49
|
+
border-bottom: 1px solid var(--pc-surface-active);
|
|
50
|
+
}
|
|
51
|
+
:host([hidden]) {
|
|
52
|
+
display: none;
|
|
53
|
+
}
|
|
54
|
+
`
|
|
55
|
+
];
|
|
56
|
+
changes = new ChangeController(this, () => this.app ? [
|
|
57
|
+
this.app,
|
|
58
|
+
this.app.selection,
|
|
59
|
+
this.app.transform
|
|
60
|
+
] : []);
|
|
61
|
+
constructor() {
|
|
62
|
+
super();
|
|
63
|
+
this.narrow = false;
|
|
64
|
+
}
|
|
65
|
+
/** Cut, copy and paste, each with whether it can be done now */
|
|
66
|
+
actions(app) {
|
|
67
|
+
const noCopy = !app.selection.active || app.transform.pending;
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
name: "cut",
|
|
71
|
+
label: this.t("paintCanvas.common.cut"),
|
|
72
|
+
disabled: noCopy,
|
|
73
|
+
run: () => app.cut()
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "copy",
|
|
77
|
+
label: this.t("paintCanvas.common.copy"),
|
|
78
|
+
disabled: noCopy,
|
|
79
|
+
run: () => app.copy()
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "paste",
|
|
83
|
+
label: this.t("paintCanvas.common.paste"),
|
|
84
|
+
disabled: !app.hasClipboard,
|
|
85
|
+
run: () => app.paste()
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
/** Hide for tools without clipboard actions (e.g. zoom) */
|
|
90
|
+
willUpdate() {
|
|
91
|
+
this.hidden = !this.app || !CLIPBOARD_TOOLS.includes(this.app.tool);
|
|
92
|
+
}
|
|
93
|
+
render() {
|
|
94
|
+
const app = this.app;
|
|
95
|
+
if (!app || this.hidden) return nothing;
|
|
96
|
+
const actions = this.actions(app);
|
|
97
|
+
if (this.narrow) return html`<pc-context-menu
|
|
98
|
+
class="more"
|
|
99
|
+
label=${this.t("paintCanvas.toolSettings.moreActions")}
|
|
100
|
+
.items=${actions.map(({ name, label, disabled }) => ({
|
|
101
|
+
value: name,
|
|
102
|
+
label,
|
|
103
|
+
disabled
|
|
104
|
+
}))}
|
|
105
|
+
@pc-select=${(event) => actions.find((action) => action.name === event.detail.value)?.run()}
|
|
106
|
+
></pc-context-menu>`;
|
|
107
|
+
return actions.map((action) => html`<button
|
|
108
|
+
type="button"
|
|
109
|
+
class="pill ${action.name}"
|
|
110
|
+
?disabled=${action.disabled}
|
|
111
|
+
@click=${action.run}
|
|
112
|
+
>
|
|
113
|
+
${action.label}
|
|
114
|
+
</button>`);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
defineElement("pc-clipboard-tools", PcClipboardTools);
|
|
118
|
+
export { CLIPBOARD_TOOLS, PcClipboardTools };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type PropertyValues } from "lit";
|
|
2
2
|
import { PcElement } from "../../base";
|
|
3
|
-
import { PcMenu, type
|
|
3
|
+
import { PcMenu, type MenuEntry } from "../PcMenu";
|
|
4
4
|
import "../PcMenu";
|
|
5
5
|
/** Space kept between a context menu's menu and the window's edges */
|
|
6
6
|
export declare const MENU_MARGIN = 8;
|
|
@@ -77,7 +77,7 @@ export declare class PcContextMenu extends PcElement {
|
|
|
77
77
|
/** Whether the menu is open */
|
|
78
78
|
open: boolean;
|
|
79
79
|
/** The items of its own menu, when no `pc-menu` is slotted */
|
|
80
|
-
items: readonly
|
|
80
|
+
items: readonly MenuEntry[];
|
|
81
81
|
/** Names the button for screen readers */
|
|
82
82
|
label: string;
|
|
83
83
|
/** Names the menu for screen readers (the button's `label` by default) */
|