@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
|
@@ -2,6 +2,8 @@ import { PcElement } from "../../base";
|
|
|
2
2
|
import { BlendMode, type default as Layer } from "../../../lib/classes/Layer";
|
|
3
3
|
import type LayerStack from "../../../lib/classes/LayerStack";
|
|
4
4
|
import "../PcDialog";
|
|
5
|
+
import "../PcContextMenu";
|
|
6
|
+
import { MENU_MARGIN, menuTop } from "../PcContextMenu";
|
|
5
7
|
import { type DialogChoice } from "../PcDialog";
|
|
6
8
|
import type BackgroundWork from "../../../lib/classes/BackgroundWork";
|
|
7
9
|
/** Blend mode options shown in the layer's select input */
|
|
@@ -56,17 +58,8 @@ export interface LayerDragDetail {
|
|
|
56
58
|
x: number;
|
|
57
59
|
y: number;
|
|
58
60
|
}
|
|
59
|
-
/**
|
|
60
|
-
export
|
|
61
|
-
/**
|
|
62
|
-
* Where the layer actions menu's top goes: level with the handle, moved up as far as needed to stay in the window
|
|
63
|
-
* (but never above its top margin).
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* menuTop(700, 300, 800); // 492 (moved up to fit)
|
|
67
|
-
* menuTop(100, 300, 800); // 100
|
|
68
|
-
*/
|
|
69
|
-
export declare const menuTop: (anchorTop: number, menuHeight: number, viewportHeight: number, margin?: number) => number;
|
|
61
|
+
/** Where the layer actions menu goes and how close to the window's edges (see `pc-context-menu`) */
|
|
62
|
+
export { MENU_MARGIN, menuTop };
|
|
70
63
|
/**
|
|
71
64
|
* One row in the layers menu: reorder handle, thumbnail and name (then opacity and blend mode under them), alpha lock (padlock) and visibility (eye) icons.
|
|
72
65
|
* Dragging the handle (with mouse, pen or touch) reorders the layer: the row fires {@link LAYER_DRAG_EVENT} and the
|
|
@@ -141,28 +134,22 @@ export declare class PcLayerItem extends PcElement {
|
|
|
141
134
|
runAction(action: LayerAction): void;
|
|
142
135
|
/**
|
|
143
136
|
* Whether a context menu action can be done to the layer now: not merging down the bottom layer (or with a hidden
|
|
144
|
-
* layer), deleting the only layer,
|
|
137
|
+
* layer), deleting the only layer, moving a layer further up or down than it can go, or anything to a layer no longer
|
|
138
|
+
* in the stack (e.g. just deleted).
|
|
145
139
|
*/
|
|
146
140
|
canRun(action: LayerAction): boolean;
|
|
147
141
|
/**
|
|
148
142
|
* Do an action the user confirmed.
|
|
149
143
|
*/
|
|
150
144
|
confirmed(action: ConfirmedAction): void;
|
|
151
|
-
private readonly onOutsidePointer;
|
|
152
|
-
private readonly onKeyDown;
|
|
153
|
-
/**
|
|
154
|
-
* Open the context menu on right-click, or close it if open.
|
|
155
|
-
*/
|
|
156
|
-
private onContextMenu;
|
|
157
145
|
/**
|
|
158
|
-
*
|
|
159
|
-
* drag does nothing.
|
|
146
|
+
* Follow the context menu opening or closing, telling other rows when it opens (so they close theirs).
|
|
160
147
|
*/
|
|
161
|
-
private
|
|
148
|
+
private onMenuToggle;
|
|
162
149
|
/**
|
|
163
|
-
*
|
|
150
|
+
* A click on the handle opens the menu, unless it ends a drag (then it's stopped before reaching the menu's button).
|
|
164
151
|
*/
|
|
165
|
-
private
|
|
152
|
+
private readonly onHandleClick;
|
|
166
153
|
disconnectedCallback(): void;
|
|
167
154
|
/** Tell the layers menu about a drag of this row's layer */
|
|
168
155
|
private emitDrag;
|
|
@@ -188,16 +175,6 @@ export declare class PcLayerItem extends PcElement {
|
|
|
188
175
|
private readonly onDragKeyDown;
|
|
189
176
|
/** Stop following the pointer pressed on the handle */
|
|
190
177
|
private endPress;
|
|
191
|
-
/**
|
|
192
|
-
* Start or stop listening for clicks outside and Escape while the menu is open.
|
|
193
|
-
*/
|
|
194
|
-
private listenOutside;
|
|
195
|
-
private readonly onScroll;
|
|
196
|
-
/**
|
|
197
|
-
* Place the open layer actions menu beside the reorder handle, floating over the layers panel (so the panel's edges
|
|
198
|
-
* don't cut it off) and kept within the window.
|
|
199
|
-
*/
|
|
200
|
-
private placeMenu;
|
|
201
178
|
/**
|
|
202
179
|
* Ask for a mask following the layer's alpha (Shift adds, Alt subtracts; otherwise it replaces the mask).
|
|
203
180
|
*/
|
|
@@ -210,12 +187,14 @@ export declare class PcLayerItem extends PcElement {
|
|
|
210
187
|
* Rename a layer when the name input changes. Empty names are reverted.
|
|
211
188
|
*/
|
|
212
189
|
private onRename;
|
|
213
|
-
updated(
|
|
190
|
+
updated(): void;
|
|
214
191
|
/**
|
|
215
192
|
* Draw the layer's image, scaled to fit, on a checkerboard that shows transparency.
|
|
216
193
|
*/
|
|
217
194
|
drawThumbnail(): void;
|
|
218
195
|
/** The dialog asking the user to confirm an action, while asking */
|
|
219
196
|
private renderConfirmation;
|
|
197
|
+
/** The layer's actions, for its context menu (those it can't do now are disabled) */
|
|
198
|
+
private menuItems;
|
|
220
199
|
render(): import("lit").TemplateResult<1>;
|
|
221
200
|
}
|
|
@@ -5,6 +5,7 @@ import ChangeController from "../../ChangeController/index.js";
|
|
|
5
5
|
import { BlendMode } from "../../../lib/classes/Layer/index.js";
|
|
6
6
|
import { drawCheckerboard, fitSize } from "../../../lib/rendering/checkerboard/index.js";
|
|
7
7
|
import { CANCEL_CHOICE } from "../PcDialog/index.js";
|
|
8
|
+
import { MENU_MARGIN, menuTop } from "../PcContextMenu/index.js";
|
|
8
9
|
import { html, nothing, unsafeCSS } from "lit";
|
|
9
10
|
// src/ui/elements/PcLayerItem/index.ts
|
|
10
11
|
/** Blend mode options shown in the layer's select input */
|
|
@@ -127,17 +128,6 @@ var LAYER_ALPHA_MASK_EVENT = "pc-layer-alpha-mask";
|
|
|
127
128
|
var DRAG_THRESHOLD = 4;
|
|
128
129
|
/** Event a row dispatches while its layer is dragged by its reorder handle (detail: {@link LayerDragDetail}) */
|
|
129
130
|
var LAYER_DRAG_EVENT = "pc-layer-drag";
|
|
130
|
-
/** Space kept between the layer actions menu and the window's edges */
|
|
131
|
-
var MENU_MARGIN = 8;
|
|
132
|
-
/**
|
|
133
|
-
* Where the layer actions menu's top goes: level with the handle, moved up as far as needed to stay in the window
|
|
134
|
-
* (but never above its top margin).
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* menuTop(700, 300, 800); // 492 (moved up to fit)
|
|
138
|
-
* menuTop(100, 300, 800); // 100
|
|
139
|
-
*/
|
|
140
|
-
var menuTop = (anchorTop, menuHeight, viewportHeight, margin = 8) => Math.max(margin, Math.min(anchorTop, viewportHeight - margin - menuHeight));
|
|
141
131
|
/**
|
|
142
132
|
* One row in the layers menu: reorder handle, thumbnail and name (then opacity and blend mode under them), alpha lock (padlock) and visibility (eye) icons.
|
|
143
133
|
* Dragging the handle (with mouse, pen or touch) reorders the layer: the row fires {@link LAYER_DRAG_EVENT} and the
|
|
@@ -220,11 +210,12 @@ var PcLayerItem = class extends PcElement {
|
|
|
220
210
|
}
|
|
221
211
|
/**
|
|
222
212
|
* Whether a context menu action can be done to the layer now: not merging down the bottom layer (or with a hidden
|
|
223
|
-
* layer), deleting the only layer,
|
|
213
|
+
* layer), deleting the only layer, moving a layer further up or down than it can go, or anything to a layer no longer
|
|
214
|
+
* in the stack (e.g. just deleted).
|
|
224
215
|
*/
|
|
225
216
|
canRun(action) {
|
|
226
217
|
const { stack, layer } = this;
|
|
227
|
-
if (!stack || !layer) return false;
|
|
218
|
+
if (!stack || !layer || !stack.layers.includes(layer)) return false;
|
|
228
219
|
const index = stack.indexOf(layer.id);
|
|
229
220
|
const last = stack.layers.length - 1;
|
|
230
221
|
switch (action) {
|
|
@@ -248,43 +239,30 @@ var PcLayerItem = class extends PcElement {
|
|
|
248
239
|
else if (action === "clear") stack.clear(layer.id);
|
|
249
240
|
else stack.remove(layer.id);
|
|
250
241
|
}
|
|
251
|
-
onOutsidePointer = (event) => {
|
|
252
|
-
if (!event.composedPath().includes(this)) this.menuOpen = false;
|
|
253
|
-
};
|
|
254
|
-
onKeyDown = (event) => {
|
|
255
|
-
if (event.key === "Escape") this.menuOpen = false;
|
|
256
|
-
};
|
|
257
242
|
/**
|
|
258
|
-
*
|
|
243
|
+
* Follow the context menu opening or closing, telling other rows when it opens (so they close theirs).
|
|
259
244
|
*/
|
|
260
|
-
|
|
261
|
-
event.
|
|
262
|
-
this.
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Open the context menu on a click or tap on the handle (or Enter or Space), or close it if open; a click that ends a
|
|
266
|
-
* drag does nothing.
|
|
267
|
-
*/
|
|
268
|
-
onHandleClick() {
|
|
269
|
-
if (this.suppressClick) {
|
|
270
|
-
this.suppressClick = false;
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
this.toggleMenu();
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Open the context menu (closing other rows' menus), or close it if open.
|
|
277
|
-
*/
|
|
278
|
-
toggleMenu() {
|
|
279
|
-
this.menuOpen = !this.menuOpen;
|
|
280
|
-
if (this.menuOpen) this.dispatchEvent(new CustomEvent(LAYER_MENU_OPEN_EVENT, {
|
|
245
|
+
onMenuToggle(event) {
|
|
246
|
+
this.menuOpen = event.detail.open;
|
|
247
|
+
if (!this.menuOpen) return;
|
|
248
|
+
this.dispatchEvent(new CustomEvent(LAYER_MENU_OPEN_EVENT, {
|
|
281
249
|
bubbles: true,
|
|
282
250
|
composed: true
|
|
283
251
|
}));
|
|
284
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* A click on the handle opens the menu, unless it ends a drag (then it's stopped before reaching the menu's button).
|
|
255
|
+
*/
|
|
256
|
+
onHandleClick = {
|
|
257
|
+
handleEvent: (event) => {
|
|
258
|
+
if (!this.suppressClick) return;
|
|
259
|
+
this.suppressClick = false;
|
|
260
|
+
event.stopPropagation();
|
|
261
|
+
},
|
|
262
|
+
capture: true
|
|
263
|
+
};
|
|
285
264
|
disconnectedCallback() {
|
|
286
265
|
super.disconnectedCallback();
|
|
287
|
-
this.listenOutside(false);
|
|
288
266
|
this.endPress();
|
|
289
267
|
}
|
|
290
268
|
/** Tell the layers menu about a drag of this row's layer */
|
|
@@ -313,7 +291,7 @@ var PcLayerItem = class extends PcElement {
|
|
|
313
291
|
y: event.clientY,
|
|
314
292
|
dragging: false
|
|
315
293
|
};
|
|
316
|
-
event.
|
|
294
|
+
event.composedPath()[0].setPointerCapture(event.pointerId);
|
|
317
295
|
window.addEventListener("pointermove", this.onHandlePointerMove);
|
|
318
296
|
window.addEventListener("pointerup", this.onHandlePointerUp);
|
|
319
297
|
window.addEventListener("pointercancel", this.onHandlePointerCancel);
|
|
@@ -368,29 +346,6 @@ var PcLayerItem = class extends PcElement {
|
|
|
368
346
|
window.removeEventListener("pointercancel", this.onHandlePointerCancel);
|
|
369
347
|
}
|
|
370
348
|
/**
|
|
371
|
-
* Start or stop listening for clicks outside and Escape while the menu is open.
|
|
372
|
-
*/
|
|
373
|
-
listenOutside(listen) {
|
|
374
|
-
const method = listen ? "addEventListener" : "removeEventListener";
|
|
375
|
-
window[method]("pointerdown", this.onOutsidePointer, true);
|
|
376
|
-
window[method]("keydown", this.onKeyDown);
|
|
377
|
-
window[method]("scroll", this.onScroll, true);
|
|
378
|
-
}
|
|
379
|
-
onScroll = () => {
|
|
380
|
-
this.menuOpen = false;
|
|
381
|
-
};
|
|
382
|
-
/**
|
|
383
|
-
* Place the open layer actions menu beside the reorder handle, floating over the layers panel (so the panel's edges
|
|
384
|
-
* don't cut it off) and kept within the window.
|
|
385
|
-
*/
|
|
386
|
-
placeMenu() {
|
|
387
|
-
const menu = this.renderRoot.querySelector("menu");
|
|
388
|
-
if (!menu) return;
|
|
389
|
-
const anchor = this.renderRoot.querySelector(".handle").getBoundingClientRect();
|
|
390
|
-
menu.style.left = `${anchor.right}px`;
|
|
391
|
-
menu.style.top = `${menuTop(anchor.top, menu.offsetHeight, window.innerHeight)}px`;
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
349
|
* Ask for a mask following the layer's alpha (Shift adds, Alt subtracts; otherwise it replaces the mask).
|
|
395
350
|
*/
|
|
396
351
|
requestMask(layer, keys) {
|
|
@@ -426,11 +381,7 @@ var PcLayerItem = class extends PcElement {
|
|
|
426
381
|
input.value = layer.name;
|
|
427
382
|
}
|
|
428
383
|
}
|
|
429
|
-
updated(
|
|
430
|
-
if (changed.has("menuOpen")) {
|
|
431
|
-
this.listenOutside(this.menuOpen);
|
|
432
|
-
if (this.menuOpen) this.placeMenu();
|
|
433
|
-
}
|
|
384
|
+
updated() {
|
|
434
385
|
const id = this.layer?.id;
|
|
435
386
|
if (this.background && id) this.background.run(`thumbnail ${id}`, () => this.drawThumbnail());
|
|
436
387
|
else this.drawThumbnail();
|
|
@@ -472,23 +423,32 @@ var PcLayerItem = class extends PcElement {
|
|
|
472
423
|
}}
|
|
473
424
|
></pc-dialog>`;
|
|
474
425
|
}
|
|
426
|
+
/** The layer's actions, for its context menu (those it can't do now are disabled) */
|
|
427
|
+
menuItems() {
|
|
428
|
+
return LAYER_ACTIONS.map(({ action, label }) => ({
|
|
429
|
+
value: action,
|
|
430
|
+
label: this.t(label),
|
|
431
|
+
disabled: !this.canRun(action)
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
475
434
|
render() {
|
|
476
435
|
const { stack, layer } = this;
|
|
477
436
|
if (!stack || !layer) return html``;
|
|
478
437
|
const active = stack.active.id === layer.id;
|
|
479
438
|
return html`
|
|
480
|
-
<
|
|
481
|
-
type="button"
|
|
439
|
+
<pc-context-menu
|
|
482
440
|
class="handle"
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
441
|
+
placement="beside"
|
|
442
|
+
label=${this.t("paintCanvas.layers.reorder", { name: layer.name })}
|
|
443
|
+
menu-label=${this.t("paintCanvas.layers.actions")}
|
|
444
|
+
.open=${this.menuOpen}
|
|
445
|
+
.items=${this.menuItems()}
|
|
446
|
+
@pc-toggle=${this.onMenuToggle}
|
|
447
|
+
@pc-select=${(e) => this.runAction(e.detail.value)}
|
|
487
448
|
@click=${this.onHandleClick}
|
|
488
449
|
@pointerdown=${this.onHandlePointerDown}
|
|
450
|
+
><span slot="icon" aria-hidden="true">⠿</span></pc-context-menu
|
|
489
451
|
>
|
|
490
|
-
⠿
|
|
491
|
-
</button>
|
|
492
452
|
<div
|
|
493
453
|
class="details"
|
|
494
454
|
@click=${(e) => this.onRowClick(e, stack, layer)}
|
|
@@ -541,18 +501,6 @@ var PcLayerItem = class extends PcElement {
|
|
|
541
501
|
>
|
|
542
502
|
<img src=${this.iconUrl(layer.visible ? "visible" : "hidden")} alt="" />
|
|
543
503
|
</button>
|
|
544
|
-
${this.menuOpen ? html`<menu aria-label=${this.t("paintCanvas.layers.actions")}>
|
|
545
|
-
${LAYER_ACTIONS.map(({ action, label }) => html`<li>
|
|
546
|
-
<button
|
|
547
|
-
type="button"
|
|
548
|
-
data-action=${action}
|
|
549
|
-
?disabled=${!this.canRun(action)}
|
|
550
|
-
@click=${() => this.runAction(action)}
|
|
551
|
-
>
|
|
552
|
-
${this.t(label)}
|
|
553
|
-
</button>
|
|
554
|
-
</li>`)}
|
|
555
|
-
</menu>` : nothing}
|
|
556
504
|
${this.renderConfirmation(layer)}
|
|
557
505
|
`;
|
|
558
506
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PcLayerItem/style.css?inline
|
|
2
|
-
var style_default = "/* A white row with space around its parts */\n:host {\n display: grid;\n grid-template-columns: 30px 1fr 30px 30px;\n align-items: center;\n column-gap: 6px;\n position: relative;\n padding: 6px;\n border: 1px solid var(--pc-surface-active);\n background: var(--pc-surface);\n}\n.name.active {\n font-weight: bold;\n}\n.thumbnail {\n width: 30px;\n height: 30px;\n}\n/* Thumbnail on the left and name on the right; under them, opacity on the left and blend mode on the right
|
|
2
|
+
var style_default = "/* A white row with space around its parts. The middle column can shrink, so the row never grows wider than its panel */\n:host {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 30px 30px;\n align-items: center;\n column-gap: 6px;\n position: relative;\n padding: 6px;\n border: 1px solid var(--pc-surface-active);\n background: var(--pc-surface);\n}\n.name.active {\n font-weight: bold;\n}\n.thumbnail {\n width: 30px;\n height: 30px;\n}\n/* Thumbnail on the left and name on the right; under them, opacity on the left and blend mode on the right. The blend\n mode gets a set share of the width rather than its own: browsers size dropdowns differently (Safari and Firefox as\n wide as the longest option, Chrome as the chosen one), which would otherwise push the row wider than its panel */\n.details {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) minmax(0, 2fr);\n align-items: center;\n gap: 4px 6px;\n min-width: 0;\n}\n.details .name {\n grid-column: 2 / -1;\n}\n.details .name,\n.details select {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n}\n.details input[type=\"range\"] {\n grid-column: 1 / 3;\n min-width: 0;\n margin: 0;\n}\n/* The reorder handle drags with mouse, pen or touch (touch drags it rather than scrolling the panel) */\n.handle {\n /* As tall as the row */\n align-self: stretch;\n}\n.handle::part(button) {\n min-width: 0;\n padding: 0;\n cursor: grab;\n touch-action: none;\n}\n/* While dragged: the row floats with the pointer, out of the list (the layers menu places it), and the cursor shows\n what dropping would do (\"+\" duplicates on \"New Layer\") */\n:host([dragging]) {\n position: fixed;\n z-index: 10;\n opacity: 0.9;\n background: Canvas;\n box-shadow: var(--pc-shadow);\n}\n:host([dragging]) .handle::part(button) {\n cursor: grabbing;\n}\n:host([drop-action=\"duplicate\"]) .handle::part(button) {\n cursor: copy;\n}\n:host([drop-action=\"none\"]) .handle::part(button) {\n cursor: no-drop;\n}\n/* Alpha lock and visibility: boxed icon toggles like the settings bar's, darker while on */\n.alpha-lock,\n.visibility {\n width: 30px;\n height: 30px;\n padding: 2px;\n border: 1px solid var(--pc-border);\n border-radius: 4px;\n background: var(--pc-surface);\n cursor: pointer;\n}\n.alpha-lock:hover,\n.visibility:hover {\n background: var(--pc-surface-hover);\n}\n.alpha-lock[aria-pressed=\"true\"],\n.visibility[aria-pressed=\"true\"] {\n background: var(--pc-surface-active);\n}\n.alpha-lock:focus-visible,\n.visibility:focus-visible {\n outline: var(--pc-focus-width) solid var(--pc-focus);\n}\n.alpha-lock img,\n.visibility img {\n display: block;\n width: 24px;\n height: 24px;\n margin: auto;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { type PropertyValues } from "lit";
|
|
2
|
+
import { PcElement } from "../../base";
|
|
3
|
+
import { type KeyCombo } from "../../../lib/utils/shortcuts";
|
|
4
|
+
import "../PcIcon";
|
|
5
|
+
/** Longest shortcut label shown on a menu item (characters); longer ones are left out */
|
|
6
|
+
export declare const MAX_SHORTCUT_LABEL_LENGTH = 3;
|
|
7
|
+
/** An item in a menu that can be chosen */
|
|
8
|
+
export interface MenuItem {
|
|
9
|
+
/** Optional; items are the default kind of menu entry */
|
|
10
|
+
type?: "item";
|
|
11
|
+
/** What `pc-select` gives when it's chosen */
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/** Shown in the cancelling colour, e.g. for deleting */
|
|
16
|
+
danger?: boolean;
|
|
17
|
+
/** Makes the item a toggle, showing a checkmark on its left while on */
|
|
18
|
+
checked?: boolean;
|
|
19
|
+
/** Name of an icon to show on its left (see `icons`), when it isn't a toggle */
|
|
20
|
+
icon?: string;
|
|
21
|
+
/** The action's keyboard shortcut, shown on its right as symbols (e.g. ⌘S) when 3 characters or fewer */
|
|
22
|
+
shortcut?: KeyCombo;
|
|
23
|
+
/** Marks the current choice (e.g. the selected tool) with the `selected` class and a purple background */
|
|
24
|
+
selected?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** A non-interactive label naming the items after it (up to the next label or divider), e.g. "Tools" */
|
|
27
|
+
export interface MenuLabel {
|
|
28
|
+
type: "label";
|
|
29
|
+
label: string;
|
|
30
|
+
}
|
|
31
|
+
/** A non-interactive line between items */
|
|
32
|
+
export interface MenuDivider {
|
|
33
|
+
type: "divider";
|
|
34
|
+
}
|
|
35
|
+
/** Anything a menu can show: an item, a label or a divider */
|
|
36
|
+
export type MenuEntry = MenuItem | MenuLabel | MenuDivider;
|
|
37
|
+
/** A run of items, with the label before them if there is one */
|
|
38
|
+
interface MenuSection {
|
|
39
|
+
label?: string;
|
|
40
|
+
items: MenuItem[];
|
|
41
|
+
/** Whether a divider comes before it */
|
|
42
|
+
divided: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether a menu entry is an item that can be chosen.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* isMenuItem({ value: "grid", label: "Grid" }); // true
|
|
49
|
+
* isMenuItem({ type: "divider" }); // false
|
|
50
|
+
*/
|
|
51
|
+
export declare const isMenuItem: (entry: MenuEntry) => entry is MenuItem;
|
|
52
|
+
/**
|
|
53
|
+
* Split menu entries into sections: a label or divider starts a new one.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* menuSections([{ type: "label", label: "Tools" }, { value: "brush", label: "Brush" }]);
|
|
57
|
+
* // [{ label: "Tools", items: [{ value: "brush", label: "Brush" }], divided: false }]
|
|
58
|
+
*/
|
|
59
|
+
export declare const menuSections: (entries: readonly MenuEntry[]) => MenuSection[];
|
|
60
|
+
/**
|
|
61
|
+
* A list of menu items, e.g. a layer's actions (see `pc-context-menu` for a button that opens one). While `open`, it shows its items at `x`, `y` (in the page's viewport) and takes
|
|
62
|
+
* keyboard focus: arrow keys, Home and End move between items, Enter or Space chooses one, and Escape or Tab closes it.
|
|
63
|
+
* Items can show a checkmark (toggles) or an icon on their left, and their keyboard shortcut on their right; long
|
|
64
|
+
* labels wrap. Non-interactive labels (`{ type: "label", label }`, small bold text naming the items after them) and
|
|
65
|
+
* dividers (`{ type: "divider" }`) can go between items; keyboard focus skips them.
|
|
66
|
+
* Fires `pc-select` with the chosen item's value, and `pc-close` when it should close (after choosing, Escape, Tab, or a
|
|
67
|
+
* press outside it and its `anchor`). The implementer sets `open` to false in response.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* html`<pc-menu open .x=${10} .y=${20} label="Layer actions" .items=${items}
|
|
71
|
+
* @pc-select=${(e) => act(e.detail.value)} @pc-close=${close}></pc-menu>`
|
|
72
|
+
*/
|
|
73
|
+
export declare class PcMenu extends PcElement {
|
|
74
|
+
static properties: {
|
|
75
|
+
open: {
|
|
76
|
+
type: BooleanConstructor;
|
|
77
|
+
reflect: boolean;
|
|
78
|
+
};
|
|
79
|
+
items: {
|
|
80
|
+
attribute: boolean;
|
|
81
|
+
};
|
|
82
|
+
label: {
|
|
83
|
+
type: StringConstructor;
|
|
84
|
+
};
|
|
85
|
+
x: {
|
|
86
|
+
type: NumberConstructor;
|
|
87
|
+
};
|
|
88
|
+
y: {
|
|
89
|
+
type: NumberConstructor;
|
|
90
|
+
};
|
|
91
|
+
anchor: {
|
|
92
|
+
attribute: boolean;
|
|
93
|
+
};
|
|
94
|
+
translations: {
|
|
95
|
+
attribute: boolean;
|
|
96
|
+
};
|
|
97
|
+
icons: {
|
|
98
|
+
attribute: boolean;
|
|
99
|
+
};
|
|
100
|
+
theme: {
|
|
101
|
+
type: StringConstructor;
|
|
102
|
+
reflect: boolean;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
static styles: import("lit").CSSResultGroup[];
|
|
106
|
+
open: boolean;
|
|
107
|
+
/** Items, labels and dividers, in order */
|
|
108
|
+
items: readonly MenuEntry[];
|
|
109
|
+
/** Names the menu for screen readers */
|
|
110
|
+
label: string;
|
|
111
|
+
x: number;
|
|
112
|
+
y: number;
|
|
113
|
+
/** The element that opens it (e.g. a `pc-context-menu`'s button): pressing it doesn't count as pressing outside */
|
|
114
|
+
anchor?: Element;
|
|
115
|
+
private readonly onPointerDown;
|
|
116
|
+
constructor();
|
|
117
|
+
connectedCallback(): void;
|
|
118
|
+
disconnectedCallback(): void;
|
|
119
|
+
updated(changed: PropertyValues<this>): void;
|
|
120
|
+
/** The enabled items' buttons */
|
|
121
|
+
private buttons;
|
|
122
|
+
/** Tell listeners the menu should close */
|
|
123
|
+
close(): void;
|
|
124
|
+
/** Choose an item, then close */
|
|
125
|
+
private choose;
|
|
126
|
+
/** Move focus between items, or close */
|
|
127
|
+
private onKeyDown;
|
|
128
|
+
/** An item's left side: a checkmark while a toggle is on, its icon, or empty space */
|
|
129
|
+
private renderStart;
|
|
130
|
+
/** An item's right side: its shortcut's label, if short enough */
|
|
131
|
+
private renderEnd;
|
|
132
|
+
/** An item's button */
|
|
133
|
+
private renderItem;
|
|
134
|
+
/** A section: its divider and label, if any, and its items (grouped under the label for screen readers) */
|
|
135
|
+
private renderSection;
|
|
136
|
+
render(): import("lit").TemplateResult<1>;
|
|
137
|
+
}
|
|
138
|
+
export {};
|