@lvl99dotcom/paintcanvas 0.0.0-stage → 0.2.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/LICENSE +201 -0
- package/README.md +131 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/lib/brushes/BrushTipCache/index.d.ts +32 -0
- package/dist/lib/brushes/BrushTipCache/index.js +60 -0
- package/dist/lib/brushes/StrokeEngine/index.d.ts +171 -0
- package/dist/lib/brushes/StrokeEngine/index.js +324 -0
- package/dist/lib/brushes/StrokePath/index.d.ts +53 -0
- package/dist/lib/brushes/StrokePath/index.js +161 -0
- package/dist/lib/brushes/StrokeSampler/index.d.ts +55 -0
- package/dist/lib/brushes/StrokeSampler/index.js +75 -0
- package/dist/lib/brushes/authors/index.d.ts +55 -0
- package/dist/lib/brushes/authors/index.js +60 -0
- package/dist/lib/brushes/configRanges/index.d.ts +52 -0
- package/dist/lib/brushes/configRanges/index.js +206 -0
- package/dist/lib/brushes/index.d.ts +5 -0
- package/dist/lib/brushes/index.js +19 -0
- package/dist/lib/brushes/params/index.d.ts +108 -0
- package/dist/lib/brushes/params/index.js +139 -0
- package/dist/lib/brushes/presetFile/index.d.ts +32 -0
- package/dist/lib/brushes/presetFile/index.js +55 -0
- package/dist/lib/brushes/presets/drawing/brush-pen.js +3 -0
- package/dist/lib/brushes/presets/drawing/felt-pen.js +3 -0
- package/dist/lib/brushes/presets/drawing/index.d.ts +13 -0
- package/dist/lib/brushes/presets/drawing/index.js +88 -0
- package/dist/lib/brushes/presets/drawing/pencil-2b.js +3 -0
- package/dist/lib/brushes/presets/drawing/pencil-hb.js +3 -0
- package/dist/lib/brushes/presets/painting/grass.js +3 -0
- package/dist/lib/brushes/presets/painting/hair.js +3 -0
- package/dist/lib/brushes/presets/painting/index.d.ts +18 -0
- package/dist/lib/brushes/presets/painting/index.js +118 -0
- package/dist/lib/brushes/presets/painting/splatter.js +3 -0
- package/dist/lib/brushes/presets/painting/textured-paint.js +3 -0
- package/dist/lib/brushes/presets/painting/watery-paint.js +3 -0
- package/dist/lib/brushes/presets/round/index.d.ts +9 -0
- package/dist/lib/brushes/presets/round/index.js +44 -0
- package/dist/lib/brushes/presets/round/round.js +3 -0
- package/dist/lib/brushes/presets/round/soft-round.js +3 -0
- package/dist/lib/brushes/presets/sized/index.d.ts +20 -0
- package/dist/lib/brushes/presets/sized/index.js +30 -0
- package/dist/lib/brushes/presets/sketching/index.d.ts +14 -0
- package/dist/lib/brushes/presets/sketching/index.js +107 -0
- package/dist/lib/brushes/presets/square/index.d.ts +7 -0
- package/dist/lib/brushes/presets/square/index.js +22 -0
- package/dist/lib/brushes/presets/square/square.js +3 -0
- package/dist/lib/brushes/shapeImage/index.d.ts +40 -0
- package/dist/lib/brushes/shapeImage/index.js +61 -0
- package/dist/lib/brushes/types/index.d.ts +243 -0
- package/dist/lib/brushes/types/index.js +20 -0
- package/dist/lib/classes/BackgroundWork/index.d.ts +55 -0
- package/dist/lib/classes/BackgroundWork/index.js +97 -0
- package/dist/lib/classes/BrushSettings/index.d.ts +91 -0
- package/dist/lib/classes/BrushSettings/index.js +152 -0
- package/dist/lib/classes/CustomPresets/index.d.ts +53 -0
- package/dist/lib/classes/CustomPresets/index.js +71 -0
- package/dist/lib/classes/ExternalSheets/index.d.ts +64 -0
- package/dist/lib/classes/ExternalSheets/index.js +112 -0
- package/dist/lib/classes/GestureTracker/index.d.ts +62 -0
- package/dist/lib/classes/GestureTracker/index.js +122 -0
- package/dist/lib/classes/History/index.d.ts +83 -0
- package/dist/lib/classes/History/index.js +126 -0
- package/dist/lib/classes/HistoryGuard/index.d.ts +58 -0
- package/dist/lib/classes/HistoryGuard/index.js +97 -0
- package/dist/lib/classes/InputSettings/index.d.ts +74 -0
- package/dist/lib/classes/InputSettings/index.js +101 -0
- package/dist/lib/classes/KeyboardShortcuts/index.d.ts +48 -0
- package/dist/lib/classes/KeyboardShortcuts/index.js +137 -0
- package/dist/lib/classes/Layer/index.d.ts +86 -0
- package/dist/lib/classes/Layer/index.js +111 -0
- package/dist/lib/classes/LayerAutosave/index.d.ts +180 -0
- package/dist/lib/classes/LayerAutosave/index.js +346 -0
- package/dist/lib/classes/LayerStack/index.d.ts +177 -0
- package/dist/lib/classes/LayerStack/index.js +394 -0
- package/dist/lib/classes/PaintCanvas/index.d.ts +537 -0
- package/dist/lib/classes/PaintCanvas/index.js +965 -0
- package/dist/lib/classes/StrokeLog/index.d.ts +149 -0
- package/dist/lib/classes/StrokeLog/index.js +257 -0
- package/dist/lib/classes/Viewport/index.d.ts +108 -0
- package/dist/lib/classes/Viewport/index.js +194 -0
- package/dist/lib/document/index.d.ts +17 -0
- package/dist/lib/document/index.js +25 -0
- package/dist/lib/document/schema.d.ts +132 -0
- package/dist/lib/document/schema.js +110 -0
- package/dist/lib/i18n/index.d.ts +94 -0
- package/dist/lib/i18n/index.js +182 -0
- package/dist/lib/image/index.d.ts +90 -0
- package/dist/lib/image/index.js +147 -0
- package/dist/lib/messages/PatchSender/index.d.ts +75 -0
- package/dist/lib/messages/PatchSender/index.js +125 -0
- package/dist/lib/messages/index.d.ts +26 -0
- package/dist/lib/messages/index.js +59 -0
- package/dist/lib/messages/schema.d.ts +1775 -0
- package/dist/lib/messages/schema.js +192 -0
- package/dist/lib/presets/index.d.ts +32 -0
- package/dist/lib/presets/index.js +35 -0
- package/dist/lib/presets/schema.d.ts +753 -0
- package/dist/lib/presets/schema.js +181 -0
- package/dist/lib/rendering/BrushTip/index.d.ts +63 -0
- package/dist/lib/rendering/BrushTip/index.js +112 -0
- package/dist/lib/rendering/checkerboard/index.d.ts +22 -0
- package/dist/lib/rendering/checkerboard/index.js +31 -0
- package/dist/lib/rendering/compositing/index.d.ts +64 -0
- package/dist/lib/rendering/compositing/index.js +124 -0
- package/dist/lib/rendering/cursor/index.d.ts +14 -0
- package/dist/lib/rendering/cursor/index.js +39 -0
- package/dist/lib/rendering/cursors/index.d.ts +18 -0
- package/dist/lib/rendering/cursors/index.js +23 -0
- package/dist/lib/rendering/maskOutline/index.d.ts +22 -0
- package/dist/lib/rendering/maskOutline/index.js +78 -0
- package/dist/lib/rendering/outline/index.d.ts +36 -0
- package/dist/lib/rendering/outline/index.js +120 -0
- package/dist/lib/rendering/sample/index.d.ts +55 -0
- package/dist/lib/rendering/sample/index.js +83 -0
- package/dist/lib/rendering/screenshot/index.d.ts +67 -0
- package/dist/lib/rendering/screenshot/index.js +96 -0
- package/dist/lib/rendering/transformBox/index.d.ts +10 -0
- package/dist/lib/rendering/transformBox/index.js +57 -0
- package/dist/lib/selection/Lasso/index.d.ts +70 -0
- package/dist/lib/selection/Lasso/index.js +156 -0
- package/dist/lib/selection/Selection/index.d.ts +86 -0
- package/dist/lib/selection/Selection/index.js +228 -0
- package/dist/lib/selection/geometry/index.d.ts +37 -0
- package/dist/lib/selection/geometry/index.js +57 -0
- package/dist/lib/storage/index.d.ts +63 -0
- package/dist/lib/storage/index.js +114 -0
- package/dist/lib/transform/Transformer/index.d.ts +124 -0
- package/dist/lib/transform/Transformer/index.js +286 -0
- package/dist/lib/transform/geometry/index.d.ts +95 -0
- package/dist/lib/transform/geometry/index.js +258 -0
- package/dist/lib/utils/array/index.d.ts +10 -0
- package/dist/lib/utils/array/index.js +21 -0
- package/dist/lib/utils/gestures/index.d.ts +35 -0
- package/dist/lib/utils/gestures/index.js +81 -0
- package/dist/lib/utils/navigation/index.d.ts +51 -0
- package/dist/lib/utils/navigation/index.js +59 -0
- package/dist/lib/utils/random/index.d.ts +18 -0
- package/dist/lib/utils/random/index.js +27 -0
- package/dist/lib/utils/shortcuts/index.d.ts +74 -0
- package/dist/lib/utils/shortcuts/index.js +189 -0
- package/dist/lib/validation/validators.generated.d.ts +27 -0
- package/dist/lib/validation/validators.generated.js +19826 -0
- package/dist/locales/en-GB.js +188 -0
- package/dist/locales/en-US.js +188 -0
- package/dist/locales/fr.js +188 -0
- package/dist/locales/ja.js +188 -0
- package/dist/locales/ko.js +188 -0
- package/dist/locales/zh-Hans.js +188 -0
- package/dist/locales/zh-Hant.js +188 -0
- package/dist/package.js +3 -0
- package/dist/testing/app.d.ts +7 -0
- package/dist/testing/app.js +16 -0
- package/dist/testing/elements.d.ts +42 -0
- package/dist/testing/elements.js +58 -0
- package/dist/testing/fakeCanvas.d.ts +21 -0
- package/dist/testing/fakeCanvas.js +26 -0
- package/dist/testing/layerStore.d.ts +26 -0
- package/dist/testing/layerStore.js +43 -0
- package/dist/testing/locks.d.ts +15 -0
- package/dist/testing/locks.js +41 -0
- package/dist/testing/recordingCanvas.d.ts +14 -0
- package/dist/testing/recordingCanvas.js +28 -0
- package/dist/testing/recordingContext.d.ts +10 -0
- package/dist/testing/recordingContext.js +19 -0
- package/dist/ui/ChangeController/index.d.ts +40 -0
- package/dist/ui/ChangeController/index.js +62 -0
- package/dist/ui/base/index.d.ts +69 -0
- package/dist/ui/base/index.js +94 -0
- package/dist/ui/elements/PaintCanvas/index.d.ts +249 -0
- package/dist/ui/elements/PaintCanvas/index.js +584 -0
- package/dist/ui/elements/PaintCanvas/style.js +3 -0
- package/dist/ui/elements/PcBrushConfig/index.d.ts +130 -0
- package/dist/ui/elements/PcBrushConfig/index.js +463 -0
- package/dist/ui/elements/PcBrushConfig/style.js +3 -0
- package/dist/ui/elements/PcBrushMenu/index.d.ts +121 -0
- package/dist/ui/elements/PcBrushMenu/index.js +362 -0
- package/dist/ui/elements/PcBrushMenu/style.js +3 -0
- package/dist/ui/elements/PcBrushTest/index.d.ts +71 -0
- package/dist/ui/elements/PcBrushTest/index.js +136 -0
- package/dist/ui/elements/PcBrushTest/style.js +3 -0
- package/dist/ui/elements/PcButton/index.d.ts +57 -0
- package/dist/ui/elements/PcButton/index.js +124 -0
- package/dist/ui/elements/PcButtonGroup/index.d.ts +44 -0
- package/dist/ui/elements/PcButtonGroup/index.js +93 -0
- package/dist/ui/elements/PcCanvas/index.d.ts +356 -0
- package/dist/ui/elements/PcCanvas/index.js +1004 -0
- package/dist/ui/elements/PcCanvas/style.js +3 -0
- package/dist/ui/elements/PcCanvasMap/index.d.ts +96 -0
- package/dist/ui/elements/PcCanvasMap/index.js +187 -0
- package/dist/ui/elements/PcCanvasMap/style.js +3 -0
- package/dist/ui/elements/PcContextMenu/index.d.ts +72 -0
- package/dist/ui/elements/PcContextMenu/index.js +148 -0
- package/dist/ui/elements/PcDialog/index.d.ts +63 -0
- package/dist/ui/elements/PcDialog/index.js +114 -0
- package/dist/ui/elements/PcIcon/index.d.ts +36 -0
- package/dist/ui/elements/PcIcon/index.js +43 -0
- package/dist/ui/elements/PcIconToggle/index.d.ts +46 -0
- package/dist/ui/elements/PcIconToggle/index.js +87 -0
- package/dist/ui/elements/PcInfoTip/index.d.ts +40 -0
- package/dist/ui/elements/PcInfoTip/index.js +95 -0
- package/dist/ui/elements/PcInputSettings/index.d.ts +69 -0
- package/dist/ui/elements/PcInputSettings/index.js +150 -0
- package/dist/ui/elements/PcLayerItem/index.d.ts +221 -0
- package/dist/ui/elements/PcLayerItem/index.js +561 -0
- package/dist/ui/elements/PcLayerItem/style.js +3 -0
- package/dist/ui/elements/PcLayersMenu/index.d.ts +108 -0
- package/dist/ui/elements/PcLayersMenu/index.js +208 -0
- package/dist/ui/elements/PcLayersMenu/style.js +3 -0
- package/dist/ui/elements/PcMatch/index.d.ts +31 -0
- package/dist/ui/elements/PcMatch/index.js +58 -0
- package/dist/ui/elements/PcPanel/index.d.ts +43 -0
- package/dist/ui/elements/PcPanel/index.js +51 -0
- package/dist/ui/elements/PcPopover/index.d.ts +48 -0
- package/dist/ui/elements/PcPopover/index.js +86 -0
- package/dist/ui/elements/PcSlider/index.d.ts +57 -0
- package/dist/ui/elements/PcSlider/index.js +88 -0
- package/dist/ui/elements/PcStats/index.d.ts +54 -0
- package/dist/ui/elements/PcStats/index.js +141 -0
- package/dist/ui/elements/PcThemePicker/index.d.ts +56 -0
- package/dist/ui/elements/PcThemePicker/index.js +134 -0
- package/dist/ui/elements/PcToast/index.d.ts +58 -0
- package/dist/ui/elements/PcToast/index.js +110 -0
- package/dist/ui/elements/PcToggleCheckbox/index.d.ts +37 -0
- package/dist/ui/elements/PcToggleCheckbox/index.js +105 -0
- package/dist/ui/elements/PcToolSettings/index.d.ts +128 -0
- package/dist/ui/elements/PcToolSettings/index.js +543 -0
- package/dist/ui/elements/PcToolSettings/style.js +3 -0
- package/dist/ui/elements/PcToolbar/index.d.ts +71 -0
- package/dist/ui/elements/PcToolbar/index.js +190 -0
- package/dist/ui/elements/PcToolbar/style.js +3 -0
- package/dist/ui/icons/images/brush.js +3 -0
- package/dist/ui/icons/images/circle-mask.js +3 -0
- package/dist/ui/icons/images/clipboard.js +3 -0
- package/dist/ui/icons/images/cursor.js +3 -0
- package/dist/ui/icons/images/eraser.js +3 -0
- package/dist/ui/icons/images/eyedropper.js +3 -0
- package/dist/ui/icons/images/flip-horizontal.js +3 -0
- package/dist/ui/icons/images/flip-vertical.js +3 -0
- package/dist/ui/icons/images/focus-pen.js +3 -0
- package/dist/ui/icons/images/freehand-mask.js +3 -0
- package/dist/ui/icons/images/hidden.js +3 -0
- package/dist/ui/icons/images/layers.js +3 -0
- package/dist/ui/icons/images/linked.js +3 -0
- package/dist/ui/icons/images/locked.js +3 -0
- package/dist/ui/icons/images/moon.js +3 -0
- package/dist/ui/icons/images/pan.js +3 -0
- package/dist/ui/icons/images/polygon-mask.js +3 -0
- package/dist/ui/icons/images/pressure.js +3 -0
- package/dist/ui/icons/images/randomise.js +3 -0
- package/dist/ui/icons/images/rectangle-mask.js +3 -0
- package/dist/ui/icons/images/redo.js +3 -0
- package/dist/ui/icons/images/rotate-90-left.js +3 -0
- package/dist/ui/icons/images/rotate-90-right.js +3 -0
- package/dist/ui/icons/images/smoothing-bezier-cubic.js +3 -0
- package/dist/ui/icons/images/smoothing-bezier-quad.js +3 -0
- package/dist/ui/icons/images/smoothing-linear.js +3 -0
- package/dist/ui/icons/images/star.js +3 -0
- package/dist/ui/icons/images/sun.js +3 -0
- package/dist/ui/icons/images/tilt.js +3 -0
- package/dist/ui/icons/images/undo.js +3 -0
- package/dist/ui/icons/images/unlinked.js +3 -0
- package/dist/ui/icons/images/unlocked.js +3 -0
- package/dist/ui/icons/images/visible.js +3 -0
- package/dist/ui/icons/images/zoom-in.js +3 -0
- package/dist/ui/icons/images/zoom-out.js +3 -0
- package/dist/ui/icons/images/zoom.js +3 -0
- package/dist/ui/icons/index.d.ts +42 -0
- package/dist/ui/icons/index.js +130 -0
- package/dist/ui/index.d.ts +21 -0
- package/dist/ui/index.js +22 -0
- package/dist/ui/layout/index.d.ts +88 -0
- package/dist/ui/layout/index.js +96 -0
- package/dist/ui/styles/index.d.ts +13 -0
- package/dist/ui/styles/index.js +195 -0
- package/dist/ui/tokens/index.d.ts +29 -0
- package/dist/ui/tokens/index.js +114 -0
- package/locales/en-GB.json +186 -0
- package/locales/en-US.json +186 -0
- package/locales/fr.json +186 -0
- package/locales/ja.json +186 -0
- package/locales/ko.json +186 -0
- package/locales/zh-Hans.json +186 -0
- package/locales/zh-Hant.json +186 -0
- package/package.json +97 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { nothing } from "lit";
|
|
2
|
+
import { PcElement } from "../../base";
|
|
3
|
+
import PaintCanvas, { Tool } from "../../../lib/classes/PaintCanvas";
|
|
4
|
+
import type { BrushConfig } from "../../../lib/brushes/types";
|
|
5
|
+
/** Settings varied with pen tilt by the tilt toggle */
|
|
6
|
+
declare const TILT_PARAMS: readonly ["widthConfig", "heightConfig", "rotationConfig"];
|
|
7
|
+
/** A setting's variation config key */
|
|
8
|
+
type ParamKey = (typeof TILT_PARAMS)[number];
|
|
9
|
+
/**
|
|
10
|
+
* Whether a tool has settings to show in the bar.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* hasToolSettings(Tool.Brush); // true
|
|
14
|
+
* hasToolSettings(Tool.Pan); // false
|
|
15
|
+
*/
|
|
16
|
+
export declare const hasToolSettings: (tool: Tool) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Turn pressure or tilt on or off for some of a brush's settings, keeping their ranges.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* withSource(preset, ["widthConfig"], "usePressure", true); // { widthConfig: { ...preset.widthConfig, usePressure: true } }
|
|
22
|
+
*/
|
|
23
|
+
export declare const withSource: (preset: BrushConfig, params: readonly ParamKey[], source: "usePressure" | "useTilt", on: boolean) => Partial<BrushConfig>;
|
|
24
|
+
/**
|
|
25
|
+
* An angle rounded to 2 decimal places.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* roundAngle(12.3456); // 12.35
|
|
29
|
+
*/
|
|
30
|
+
export declare const roundAngle: (degrees: number) => number;
|
|
31
|
+
/** Steps of the zoom slider, across the whole zoom range */
|
|
32
|
+
export declare const ZOOM_SLIDER_STEPS = 1000;
|
|
33
|
+
/**
|
|
34
|
+
* A zoom level's position on the zoom slider (0 to ZOOM_SLIDER_STEPS). The scale is logarithmic, so each doubling of
|
|
35
|
+
* the zoom takes the same room.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* zoomToSlider(MIN_ZOOM); // 0
|
|
39
|
+
* zoomToSlider(MAX_ZOOM); // 1000
|
|
40
|
+
*/
|
|
41
|
+
export declare const zoomToSlider: (zoom: number) => number;
|
|
42
|
+
/**
|
|
43
|
+
* The zoom level at a position on the zoom slider (see `zoomToSlider`).
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* sliderToZoom(1000); // MAX_ZOOM
|
|
47
|
+
*/
|
|
48
|
+
export declare const sliderToZoom: (value: number) => number;
|
|
49
|
+
/**
|
|
50
|
+
* A zoom level as a percentage, e.g. "150%" (to one decimal place below 10%).
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* zoomPercent(0.0625); // "6.3%"
|
|
54
|
+
*/
|
|
55
|
+
export declare const zoomPercent: (zoom: number) => string;
|
|
56
|
+
/**
|
|
57
|
+
* The bar of settings for the current tool, shown at the top of the canvas when the tool has any:
|
|
58
|
+
*
|
|
59
|
+
* - Brush and eraser: the preset (its name and shape; shows or hides the preset menu), width, height, constrain proportions, pressure, tilt, opacity and "Configure" (fires
|
|
60
|
+
* `pc-configure-brush` with the tool, "brush" or "eraser").
|
|
61
|
+
* - Lassos: select all, and invert selection and deselect (only while there is a mask).
|
|
62
|
+
* - Move, scale and rotate: width and height (in pixels or percent), constrain proportions, flip horizontal and vertical,
|
|
63
|
+
* angle (to 2 decimal places), rotate 90° left and right, and reset (undoes the whole transform).
|
|
64
|
+
* - Colour sample: point sample (the pixel under the pointer) or area sample (the average of a dragged rectangle).
|
|
65
|
+
* - Zoom: zoom in and out, a slider across the zoom range (logarithmic) with the zoom as a percentage, and reset (100%),
|
|
66
|
+
* all around the centre of the view.
|
|
67
|
+
*
|
|
68
|
+
* Changes to the brush or eraser apply to the current settings only, not the preset. Styling is structural only.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* html`<pc-tool-settings .app=${app}></pc-tool-settings>`
|
|
72
|
+
*/
|
|
73
|
+
export declare class PcToolSettings extends PcElement {
|
|
74
|
+
static properties: {
|
|
75
|
+
app: {
|
|
76
|
+
attribute: boolean;
|
|
77
|
+
};
|
|
78
|
+
percent: {
|
|
79
|
+
state: boolean;
|
|
80
|
+
};
|
|
81
|
+
translations: {
|
|
82
|
+
attribute: boolean;
|
|
83
|
+
};
|
|
84
|
+
icons: {
|
|
85
|
+
attribute: boolean;
|
|
86
|
+
};
|
|
87
|
+
theme: {
|
|
88
|
+
type: StringConstructor;
|
|
89
|
+
reflect: boolean;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
static styles: import("lit").CSSResultGroup[];
|
|
93
|
+
app?: PaintCanvas;
|
|
94
|
+
/** Whether the move tool's width and height are in percent (of the original size) instead of pixels */
|
|
95
|
+
percent: boolean;
|
|
96
|
+
private changes;
|
|
97
|
+
constructor();
|
|
98
|
+
/** Fire an event that crosses shadow DOM boundaries */
|
|
99
|
+
private emit;
|
|
100
|
+
/**
|
|
101
|
+
* Change the move tool's box (as it is now, not as last shown), if there is one.
|
|
102
|
+
*/
|
|
103
|
+
private changeBox;
|
|
104
|
+
/**
|
|
105
|
+
* Render the focus pen mode toggle, on the right of every tool's settings: while on, only pens draw, and touches are
|
|
106
|
+
* ignored while a pen is down or just lifted.
|
|
107
|
+
*/
|
|
108
|
+
private renderFocusPen;
|
|
109
|
+
/** Render the brush or eraser settings */
|
|
110
|
+
private renderBrush;
|
|
111
|
+
/** Render the mask settings */
|
|
112
|
+
private renderMask;
|
|
113
|
+
/**
|
|
114
|
+
* Resize the move tool's box to a width or height (in the current unit), keeping flips, and the other side in
|
|
115
|
+
* proportion when constrained.
|
|
116
|
+
*/
|
|
117
|
+
private resizeBox;
|
|
118
|
+
/** A box side in the current unit, for an input */
|
|
119
|
+
private sideValue;
|
|
120
|
+
/** Render the move, scale and rotate settings */
|
|
121
|
+
private renderMove;
|
|
122
|
+
/** Render the zoom settings */
|
|
123
|
+
private renderZoom;
|
|
124
|
+
/** Render the colour sample tool's settings: point or area sampling */
|
|
125
|
+
private renderColourSample;
|
|
126
|
+
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
127
|
+
}
|
|
128
|
+
export {};
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import style_default from "./style.js";
|
|
2
|
+
import { ICON_CONTROLS_CSS, PILLS_CSS } from "../../styles/index.js";
|
|
3
|
+
import { PcElement, defineElement } from "../../base/index.js";
|
|
4
|
+
import ChangeController from "../../ChangeController/index.js";
|
|
5
|
+
import { Panel, Tool } from "../../../lib/classes/PaintCanvas/index.js";
|
|
6
|
+
import "../../../lib/classes/BrushSettings/index.js";
|
|
7
|
+
import { MAX_ZOOM, MIN_ZOOM } from "../../../lib/classes/Viewport/index.js";
|
|
8
|
+
import { iconLabel } from "../../icons/index.js";
|
|
9
|
+
import { html, nothing, svg, unsafeCSS } from "lit";
|
|
10
|
+
import { live } from "lit/directives/live.js";
|
|
11
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
12
|
+
// src/ui/elements/PcToolSettings/index.ts
|
|
13
|
+
/** The lasso tools, which share the mask settings */
|
|
14
|
+
var MASK_TOOLS = [
|
|
15
|
+
Tool.RectangleLasso,
|
|
16
|
+
Tool.CircleLasso,
|
|
17
|
+
Tool.PolygonLasso,
|
|
18
|
+
Tool.FreeformLasso
|
|
19
|
+
];
|
|
20
|
+
/** Settings varied with pen pressure by the pressure toggle */
|
|
21
|
+
var PRESSURE_PARAMS = ["widthConfig", "heightConfig"];
|
|
22
|
+
/** Settings varied with pen tilt by the tilt toggle */
|
|
23
|
+
var TILT_PARAMS = [
|
|
24
|
+
"widthConfig",
|
|
25
|
+
"heightConfig",
|
|
26
|
+
"rotationConfig"
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Whether a tool has settings to show in the bar.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* hasToolSettings(Tool.Brush); // true
|
|
33
|
+
* hasToolSettings(Tool.Pan); // false
|
|
34
|
+
*/
|
|
35
|
+
var hasToolSettings = (tool) => tool === Tool.Brush || tool === Tool.Eraser || tool === Tool.Move || tool === Tool.Zoom || tool === Tool.ColourSample || MASK_TOOLS.includes(tool);
|
|
36
|
+
/**
|
|
37
|
+
* Turn pressure or tilt on or off for some of a brush's settings, keeping their ranges.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* withSource(preset, ["widthConfig"], "usePressure", true); // { widthConfig: { ...preset.widthConfig, usePressure: true } }
|
|
41
|
+
*/
|
|
42
|
+
var withSource = (preset, params, source, on) => Object.fromEntries(params.map((param) => [param, {
|
|
43
|
+
...preset[param],
|
|
44
|
+
[source]: on
|
|
45
|
+
}]));
|
|
46
|
+
/**
|
|
47
|
+
* An angle rounded to 2 decimal places.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* roundAngle(12.3456); // 12.35
|
|
51
|
+
*/
|
|
52
|
+
var roundAngle = (degrees) => Math.round(degrees * 100) / 100;
|
|
53
|
+
/** Steps of the zoom slider, across the whole zoom range */
|
|
54
|
+
var ZOOM_SLIDER_STEPS = 1e3;
|
|
55
|
+
/** How many times bigger the largest zoom is than the smallest */
|
|
56
|
+
var ZOOM_RANGE = MAX_ZOOM / MIN_ZOOM;
|
|
57
|
+
/**
|
|
58
|
+
* A zoom level's position on the zoom slider (0 to ZOOM_SLIDER_STEPS). The scale is logarithmic, so each doubling of
|
|
59
|
+
* the zoom takes the same room.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* zoomToSlider(MIN_ZOOM); // 0
|
|
63
|
+
* zoomToSlider(MAX_ZOOM); // 1000
|
|
64
|
+
*/
|
|
65
|
+
var zoomToSlider = (zoom) => Math.round(Math.log(zoom / MIN_ZOOM) / Math.log(ZOOM_RANGE) * ZOOM_SLIDER_STEPS);
|
|
66
|
+
/**
|
|
67
|
+
* The zoom level at a position on the zoom slider (see `zoomToSlider`).
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* sliderToZoom(1000); // MAX_ZOOM
|
|
71
|
+
*/
|
|
72
|
+
var sliderToZoom = (value) => MIN_ZOOM * ZOOM_RANGE ** (value / ZOOM_SLIDER_STEPS);
|
|
73
|
+
/**
|
|
74
|
+
* A zoom level as a percentage, e.g. "150%" (to one decimal place below 10%).
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* zoomPercent(0.0625); // "6.3%"
|
|
78
|
+
*/
|
|
79
|
+
var zoomPercent = (zoom) => {
|
|
80
|
+
const percent = zoom * 100;
|
|
81
|
+
return `${percent < 10 ? Math.round(percent * 10) / 10 : Math.round(percent)}%`;
|
|
82
|
+
};
|
|
83
|
+
/** Read a number input, or undefined if it isn't a number */
|
|
84
|
+
var numberValue = (event) => {
|
|
85
|
+
const value = event.target.valueAsNumber;
|
|
86
|
+
return Number.isFinite(value) ? value : void 0;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* The bar of settings for the current tool, shown at the top of the canvas when the tool has any:
|
|
90
|
+
*
|
|
91
|
+
* - Brush and eraser: the preset (its name and shape; shows or hides the preset menu), width, height, constrain proportions, pressure, tilt, opacity and "Configure" (fires
|
|
92
|
+
* `pc-configure-brush` with the tool, "brush" or "eraser").
|
|
93
|
+
* - Lassos: select all, and invert selection and deselect (only while there is a mask).
|
|
94
|
+
* - Move, scale and rotate: width and height (in pixels or percent), constrain proportions, flip horizontal and vertical,
|
|
95
|
+
* angle (to 2 decimal places), rotate 90° left and right, and reset (undoes the whole transform).
|
|
96
|
+
* - Colour sample: point sample (the pixel under the pointer) or area sample (the average of a dragged rectangle).
|
|
97
|
+
* - Zoom: zoom in and out, a slider across the zoom range (logarithmic) with the zoom as a percentage, and reset (100%),
|
|
98
|
+
* all around the centre of the view.
|
|
99
|
+
*
|
|
100
|
+
* Changes to the brush or eraser apply to the current settings only, not the preset. Styling is structural only.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* html`<pc-tool-settings .app=${app}></pc-tool-settings>`
|
|
104
|
+
*/
|
|
105
|
+
var PcToolSettings = class extends PcElement {
|
|
106
|
+
static properties = {
|
|
107
|
+
...PcElement.properties,
|
|
108
|
+
app: { attribute: false },
|
|
109
|
+
percent: { state: true }
|
|
110
|
+
};
|
|
111
|
+
static styles = [
|
|
112
|
+
PcElement.styles,
|
|
113
|
+
unsafeCSS(ICON_CONTROLS_CSS),
|
|
114
|
+
unsafeCSS(PILLS_CSS),
|
|
115
|
+
unsafeCSS(style_default)
|
|
116
|
+
];
|
|
117
|
+
changes = new ChangeController(this, () => {
|
|
118
|
+
const app = this.app;
|
|
119
|
+
return app ? [
|
|
120
|
+
app,
|
|
121
|
+
app.brush,
|
|
122
|
+
app.eraser,
|
|
123
|
+
app.transform,
|
|
124
|
+
app.selection,
|
|
125
|
+
app.viewport,
|
|
126
|
+
app.input
|
|
127
|
+
] : [];
|
|
128
|
+
});
|
|
129
|
+
constructor() {
|
|
130
|
+
super();
|
|
131
|
+
this.percent = false;
|
|
132
|
+
}
|
|
133
|
+
/** Fire an event that crosses shadow DOM boundaries */
|
|
134
|
+
emit(type, detail) {
|
|
135
|
+
this.dispatchEvent(new CustomEvent(type, {
|
|
136
|
+
detail,
|
|
137
|
+
bubbles: true,
|
|
138
|
+
composed: true
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Change the move tool's box (as it is now, not as last shown), if there is one.
|
|
143
|
+
*/
|
|
144
|
+
changeBox(app, change) {
|
|
145
|
+
const box = app.transform.box;
|
|
146
|
+
if (box) app.transform.setBox({
|
|
147
|
+
...box,
|
|
148
|
+
...change(box)
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Render the focus pen mode toggle, on the right of every tool's settings: while on, only pens draw, and touches are
|
|
153
|
+
* ignored while a pen is down or just lifted.
|
|
154
|
+
*/
|
|
155
|
+
renderFocusPen(app) {
|
|
156
|
+
return html`<label
|
|
157
|
+
class="icon-toggle focus-pen"
|
|
158
|
+
title=${this.t("toolSettings.focusPenHint")}
|
|
159
|
+
>
|
|
160
|
+
<input
|
|
161
|
+
type="checkbox"
|
|
162
|
+
.checked=${live(app.input.data.focusPen)}
|
|
163
|
+
@change=${(e) => app.input.update({ focusPen: e.target.checked })}
|
|
164
|
+
/>
|
|
165
|
+
${iconLabel(this.iconUrl("focusPen"), this.t("toolSettings.focusPen"))}
|
|
166
|
+
</label>`;
|
|
167
|
+
}
|
|
168
|
+
/** Render the brush or eraser settings */
|
|
169
|
+
renderBrush(app, settings, kind) {
|
|
170
|
+
const preset = settings.preset;
|
|
171
|
+
const pressure = PRESSURE_PARAMS.some((param) => preset[param]?.usePressure);
|
|
172
|
+
const tilt = TILT_PARAMS.some((param) => preset[param]?.useTilt);
|
|
173
|
+
const label = this.t(kind === "eraser" ? "tool.eraser" : "tool.brush");
|
|
174
|
+
const panel = kind === "eraser" ? Panel.Eraser : Panel.Brush;
|
|
175
|
+
return html`<div
|
|
176
|
+
role="toolbar"
|
|
177
|
+
aria-label=${this.t("toolSettings.settings", { tool: label })}
|
|
178
|
+
>
|
|
179
|
+
<button
|
|
180
|
+
type="button"
|
|
181
|
+
class="preset"
|
|
182
|
+
title=${this.t("toolSettings.presets", { tool: label })}
|
|
183
|
+
aria-expanded=${app.panel === panel ? "true" : "false"}
|
|
184
|
+
@click=${() => app.togglePanel(panel)}
|
|
185
|
+
>
|
|
186
|
+
<span
|
|
187
|
+
class=${preset.image ? "shape-preview image" : "shape-preview"}
|
|
188
|
+
style=${styleMap({ maskImage: typeof preset.image === "string" ? `url("${preset.image}")` : void 0 })}
|
|
189
|
+
></span>
|
|
190
|
+
${preset.name ?? preset.id}
|
|
191
|
+
</button>
|
|
192
|
+
<label>
|
|
193
|
+
${this.t("common.width")}
|
|
194
|
+
<input
|
|
195
|
+
type="number"
|
|
196
|
+
class="width"
|
|
197
|
+
min=${1}
|
|
198
|
+
max=${256}
|
|
199
|
+
.value=${String(settings.width)}
|
|
200
|
+
@change=${(e) => {
|
|
201
|
+
const value = numberValue(e);
|
|
202
|
+
if (value !== void 0) settings.setSize(value, settings.height);
|
|
203
|
+
}}
|
|
204
|
+
/>
|
|
205
|
+
</label>
|
|
206
|
+
<label
|
|
207
|
+
class="icon-toggle"
|
|
208
|
+
title=${this.t("toolSettings.constrainProportions")}
|
|
209
|
+
>
|
|
210
|
+
<input
|
|
211
|
+
type="checkbox"
|
|
212
|
+
class="constrain"
|
|
213
|
+
.checked=${preset.constrainProportions ?? false}
|
|
214
|
+
@change=${(e) => settings.update({ constrainProportions: e.target.checked })}
|
|
215
|
+
/>
|
|
216
|
+
${iconLabel(this.iconUrl(preset.constrainProportions ? "linked" : "unlinked"), this.t("toolSettings.constrainProportions"))}
|
|
217
|
+
</label>
|
|
218
|
+
<label>
|
|
219
|
+
${this.t("common.height")}
|
|
220
|
+
<input
|
|
221
|
+
type="number"
|
|
222
|
+
class="height"
|
|
223
|
+
min=${1}
|
|
224
|
+
max=${256}
|
|
225
|
+
.value=${String(settings.height)}
|
|
226
|
+
@change=${(e) => {
|
|
227
|
+
const value = numberValue(e);
|
|
228
|
+
if (value !== void 0) settings.setHeight(value);
|
|
229
|
+
}}
|
|
230
|
+
/>
|
|
231
|
+
</label>
|
|
232
|
+
<label class="icon-toggle" title=${this.t("toolSettings.pressure")}>
|
|
233
|
+
<input
|
|
234
|
+
type="checkbox"
|
|
235
|
+
class="pressure"
|
|
236
|
+
.checked=${pressure}
|
|
237
|
+
@change=${(e) => settings.update(withSource(preset, PRESSURE_PARAMS, "usePressure", e.target.checked))}
|
|
238
|
+
/>
|
|
239
|
+
${iconLabel(this.iconUrl("pressure"), this.t("toolSettings.pressure"))}
|
|
240
|
+
</label>
|
|
241
|
+
<label class="icon-toggle" title=${this.t("toolSettings.tilt")}>
|
|
242
|
+
<input
|
|
243
|
+
type="checkbox"
|
|
244
|
+
class="tilt"
|
|
245
|
+
.checked=${tilt}
|
|
246
|
+
@change=${(e) => settings.update(withSource(preset, TILT_PARAMS, "useTilt", e.target.checked))}
|
|
247
|
+
/>
|
|
248
|
+
${iconLabel(this.iconUrl("tilt"), this.t("toolSettings.tilt"))}
|
|
249
|
+
</label>
|
|
250
|
+
<label>
|
|
251
|
+
${this.t("common.opacity")}
|
|
252
|
+
<input
|
|
253
|
+
type="number"
|
|
254
|
+
class="opacity"
|
|
255
|
+
min="0"
|
|
256
|
+
max="100"
|
|
257
|
+
.value=${String(Math.round((preset.alpha ?? 1) * 100))}
|
|
258
|
+
@change=${(e) => {
|
|
259
|
+
const value = numberValue(e);
|
|
260
|
+
if (value !== void 0) settings.update({ alpha: Math.max(0, Math.min(100, value)) / 100 });
|
|
261
|
+
}}
|
|
262
|
+
/>
|
|
263
|
+
<span class="unit">%</span>
|
|
264
|
+
</label>
|
|
265
|
+
<button
|
|
266
|
+
type="button"
|
|
267
|
+
class="configure"
|
|
268
|
+
@click=${() => this.emit("pc-configure-brush", kind)}
|
|
269
|
+
>
|
|
270
|
+
${this.t("toolSettings.configure")}
|
|
271
|
+
</button>
|
|
272
|
+
${this.renderFocusPen(app)}
|
|
273
|
+
</div>`;
|
|
274
|
+
}
|
|
275
|
+
/** Render the mask settings */
|
|
276
|
+
renderMask(app) {
|
|
277
|
+
return html`<div
|
|
278
|
+
role="toolbar"
|
|
279
|
+
aria-label=${this.t("toolSettings.maskSettings")}
|
|
280
|
+
>
|
|
281
|
+
<button
|
|
282
|
+
type="button"
|
|
283
|
+
class="pill select-all"
|
|
284
|
+
@click=${() => app.selection.selectAll()}
|
|
285
|
+
>
|
|
286
|
+
${this.t("toolSettings.selectAll")}
|
|
287
|
+
</button>
|
|
288
|
+
<button
|
|
289
|
+
type="button"
|
|
290
|
+
class="pill invert"
|
|
291
|
+
?disabled=${!app.selection.active}
|
|
292
|
+
@click=${() => app.selection.invert()}
|
|
293
|
+
>
|
|
294
|
+
${this.t("toolSettings.invertSelection")}
|
|
295
|
+
</button>
|
|
296
|
+
<button
|
|
297
|
+
type="button"
|
|
298
|
+
class="pill deselect"
|
|
299
|
+
?disabled=${!app.selection.active}
|
|
300
|
+
@click=${() => app.selection.clear()}
|
|
301
|
+
>
|
|
302
|
+
${this.t("toolSettings.deselect")}
|
|
303
|
+
</button>
|
|
304
|
+
${this.renderFocusPen(app)}
|
|
305
|
+
</div>`;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Resize the move tool's box to a width or height (in the current unit), keeping flips, and the other side in
|
|
309
|
+
* proportion when constrained.
|
|
310
|
+
*/
|
|
311
|
+
resizeBox(app, side, value) {
|
|
312
|
+
const { box, source } = app.transform;
|
|
313
|
+
if (!box || !source) return;
|
|
314
|
+
const pixels = this.percent ? source[side] * value / 100 : value;
|
|
315
|
+
if (pixels <= 0) return;
|
|
316
|
+
const other = side === "width" ? "height" : "width";
|
|
317
|
+
const ratio = Math.abs(box[other] / box[side]);
|
|
318
|
+
app.transform.setBox({
|
|
319
|
+
...box,
|
|
320
|
+
[side]: Math.sign(box[side]) * pixels,
|
|
321
|
+
...app.constrainProportions ? { [other]: Math.sign(box[other]) * pixels * ratio } : {}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/** A box side in the current unit, for an input */
|
|
325
|
+
sideValue(box, source, side) {
|
|
326
|
+
const pixels = Math.abs(box[side]);
|
|
327
|
+
return String(Math.round(this.percent ? pixels / source[side] * 100 : pixels));
|
|
328
|
+
}
|
|
329
|
+
/** Render the move, scale and rotate settings */
|
|
330
|
+
renderMove(app) {
|
|
331
|
+
const { box, source } = app.transform;
|
|
332
|
+
const disabled = !box || !source;
|
|
333
|
+
const side = (name, label) => html`<label>
|
|
334
|
+
${label}
|
|
335
|
+
<input
|
|
336
|
+
type="number"
|
|
337
|
+
class=${name}
|
|
338
|
+
min="1"
|
|
339
|
+
?disabled=${disabled}
|
|
340
|
+
.value=${box && source ? this.sideValue(box, source, name) : ""}
|
|
341
|
+
@change=${(e) => {
|
|
342
|
+
const value = numberValue(e);
|
|
343
|
+
if (value !== void 0) this.resizeBox(app, name, value);
|
|
344
|
+
}}
|
|
345
|
+
/>
|
|
346
|
+
</label>`;
|
|
347
|
+
const rotate = (by) => this.changeBox(app, (current) => ({ rotation: by(current.rotation) % 360 }));
|
|
348
|
+
return html`<div
|
|
349
|
+
role="toolbar"
|
|
350
|
+
aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.move") })}
|
|
351
|
+
>
|
|
352
|
+
${side("width", this.t("common.width"))}
|
|
353
|
+
<label
|
|
354
|
+
class="icon-toggle"
|
|
355
|
+
title=${this.t("toolSettings.constrainProportions")}
|
|
356
|
+
>
|
|
357
|
+
<input
|
|
358
|
+
type="checkbox"
|
|
359
|
+
class="constrain"
|
|
360
|
+
.checked=${live(app.constrainProportions)}
|
|
361
|
+
@change=${(e) => app.setConstrainProportions(e.target.checked)}
|
|
362
|
+
/>
|
|
363
|
+
${iconLabel(this.iconUrl(app.constrainProportions ? "linked" : "unlinked"), this.t("toolSettings.constrainProportions"))}
|
|
364
|
+
</label>
|
|
365
|
+
${side("height", this.t("common.height"))}
|
|
366
|
+
<label>
|
|
367
|
+
<input
|
|
368
|
+
type="checkbox"
|
|
369
|
+
class="percent"
|
|
370
|
+
.checked=${this.percent}
|
|
371
|
+
@change=${(e) => this.percent = e.target.checked}
|
|
372
|
+
/>
|
|
373
|
+
${this.t("toolSettings.percent")}
|
|
374
|
+
</label>
|
|
375
|
+
<button
|
|
376
|
+
type="button"
|
|
377
|
+
class="icon-button flip-horizontal"
|
|
378
|
+
title=${this.t("toolSettings.flipHorizontal")}
|
|
379
|
+
?disabled=${disabled}
|
|
380
|
+
@click=${() => this.changeBox(app, (current) => ({ width: -current.width }))}
|
|
381
|
+
>
|
|
382
|
+
${iconLabel(this.iconUrl("flipHorizontal"), this.t("toolSettings.flipHorizontal"))}
|
|
383
|
+
</button>
|
|
384
|
+
<button
|
|
385
|
+
type="button"
|
|
386
|
+
class="icon-button flip-vertical"
|
|
387
|
+
title=${this.t("toolSettings.flipVertical")}
|
|
388
|
+
?disabled=${disabled}
|
|
389
|
+
@click=${() => this.changeBox(app, (current) => ({ height: -current.height }))}
|
|
390
|
+
>
|
|
391
|
+
${iconLabel(this.iconUrl("flipVertical"), this.t("toolSettings.flipVertical"))}
|
|
392
|
+
</button>
|
|
393
|
+
<label>
|
|
394
|
+
${this.t("toolSettings.angle")}
|
|
395
|
+
<input
|
|
396
|
+
type="number"
|
|
397
|
+
class="angle"
|
|
398
|
+
step="0.01"
|
|
399
|
+
?disabled=${disabled}
|
|
400
|
+
.value=${box ? String(roundAngle(box.rotation)) : ""}
|
|
401
|
+
@change=${(e) => {
|
|
402
|
+
const value = numberValue(e);
|
|
403
|
+
if (value !== void 0) rotate(() => roundAngle(value));
|
|
404
|
+
}}
|
|
405
|
+
/>
|
|
406
|
+
<span class="unit">°</span>
|
|
407
|
+
</label>
|
|
408
|
+
<button
|
|
409
|
+
type="button"
|
|
410
|
+
class="icon-button rotate-left"
|
|
411
|
+
title=${this.t("toolSettings.rotateLeft")}
|
|
412
|
+
?disabled=${disabled}
|
|
413
|
+
@click=${() => rotate((rotation) => rotation - 90)}
|
|
414
|
+
>
|
|
415
|
+
${iconLabel(this.iconUrl("rotate90Left"), this.t("toolSettings.rotateLeft"))}
|
|
416
|
+
</button>
|
|
417
|
+
<button
|
|
418
|
+
type="button"
|
|
419
|
+
class="icon-button rotate-right"
|
|
420
|
+
title=${this.t("toolSettings.rotateRight")}
|
|
421
|
+
?disabled=${disabled}
|
|
422
|
+
@click=${() => rotate((rotation) => rotation + 90)}
|
|
423
|
+
>
|
|
424
|
+
${iconLabel(this.iconUrl("rotate90Right"), this.t("toolSettings.rotateRight"))}
|
|
425
|
+
</button>
|
|
426
|
+
<button
|
|
427
|
+
type="button"
|
|
428
|
+
class="pill reset"
|
|
429
|
+
?disabled=${disabled}
|
|
430
|
+
@click=${() => app.cancelTransform()}
|
|
431
|
+
>
|
|
432
|
+
${this.t("toolSettings.reset")}
|
|
433
|
+
</button>
|
|
434
|
+
${this.renderFocusPen(app)}
|
|
435
|
+
</div>`;
|
|
436
|
+
}
|
|
437
|
+
/** Render the zoom settings */
|
|
438
|
+
renderZoom(app) {
|
|
439
|
+
const view = app.viewport;
|
|
440
|
+
const centre = {
|
|
441
|
+
x: view.width / 2,
|
|
442
|
+
y: view.height / 2
|
|
443
|
+
};
|
|
444
|
+
return html`<div
|
|
445
|
+
role="toolbar"
|
|
446
|
+
aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.zoom") })}
|
|
447
|
+
>
|
|
448
|
+
<button
|
|
449
|
+
type="button"
|
|
450
|
+
class="zoom-in"
|
|
451
|
+
title=${this.t("toolSettings.zoomIn")}
|
|
452
|
+
aria-label=${this.t("toolSettings.zoomIn")}
|
|
453
|
+
?disabled=${view.zoom >= MAX_ZOOM}
|
|
454
|
+
@click=${() => view.zoomIn(centre)}
|
|
455
|
+
>
|
|
456
|
+
<img src=${this.iconUrl("zoomIn")} alt="" />
|
|
457
|
+
</button>
|
|
458
|
+
<button
|
|
459
|
+
type="button"
|
|
460
|
+
class="zoom-out"
|
|
461
|
+
title=${this.t("toolSettings.zoomOut")}
|
|
462
|
+
aria-label=${this.t("toolSettings.zoomOut")}
|
|
463
|
+
?disabled=${view.zoom <= MIN_ZOOM}
|
|
464
|
+
@click=${() => view.zoomOut(centre)}
|
|
465
|
+
>
|
|
466
|
+
<img src=${this.iconUrl("zoomOut")} alt="" />
|
|
467
|
+
</button>
|
|
468
|
+
<label>
|
|
469
|
+
${this.t("tool.zoom")}
|
|
470
|
+
<input
|
|
471
|
+
type="range"
|
|
472
|
+
class="zoom"
|
|
473
|
+
min="0"
|
|
474
|
+
max=${ZOOM_SLIDER_STEPS}
|
|
475
|
+
step="1"
|
|
476
|
+
.value=${String(zoomToSlider(view.zoom))}
|
|
477
|
+
@input=${(e) => view.zoomAt(centre, sliderToZoom(e.target.valueAsNumber))}
|
|
478
|
+
/>
|
|
479
|
+
<output>${zoomPercent(view.zoom)}</output>
|
|
480
|
+
</label>
|
|
481
|
+
<button
|
|
482
|
+
type="button"
|
|
483
|
+
class="pill reset"
|
|
484
|
+
@click=${() => view.zoomAt(centre, 1)}
|
|
485
|
+
>
|
|
486
|
+
${this.t("toolSettings.reset")}
|
|
487
|
+
</button>
|
|
488
|
+
${this.renderFocusPen(app)}
|
|
489
|
+
</div>`;
|
|
490
|
+
}
|
|
491
|
+
/** Render the colour sample tool's settings: point or area sampling */
|
|
492
|
+
renderColourSample(app) {
|
|
493
|
+
const modes = [[
|
|
494
|
+
"point",
|
|
495
|
+
this.t("toolSettings.pointSample"),
|
|
496
|
+
svg`<circle cx="10" cy="10" r="6" /><circle cx="10" cy="10" r="1.5" fill="currentColor" /><path d="M10 1 V5 M10 15 V19 M1 10 H5 M15 10 H19" />`
|
|
497
|
+
], [
|
|
498
|
+
"area",
|
|
499
|
+
this.t("toolSettings.areaSample"),
|
|
500
|
+
svg`<defs><linearGradient id="area-gradient"><stop offset="0" stop-color="currentColor" stop-opacity="0" /><stop offset="1" stop-color="currentColor" /></linearGradient></defs><rect x="2" y="4" width="16" height="12" fill="url(#area-gradient)" />`
|
|
501
|
+
]];
|
|
502
|
+
return html`<div
|
|
503
|
+
role="toolbar"
|
|
504
|
+
aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.colourSample") })}
|
|
505
|
+
>
|
|
506
|
+
${modes.map(([mode, label, icon]) => html`<button
|
|
507
|
+
type="button"
|
|
508
|
+
class="sample-${mode}"
|
|
509
|
+
title=${label}
|
|
510
|
+
aria-label=${label}
|
|
511
|
+
aria-pressed=${app.sampleMode === mode ? "true" : "false"}
|
|
512
|
+
@click=${() => app.setSampleMode(mode)}
|
|
513
|
+
>
|
|
514
|
+
<svg
|
|
515
|
+
width="20"
|
|
516
|
+
height="20"
|
|
517
|
+
viewBox="0 0 20 20"
|
|
518
|
+
fill="none"
|
|
519
|
+
stroke="currentColor"
|
|
520
|
+
stroke-width="1.5"
|
|
521
|
+
aria-hidden="true"
|
|
522
|
+
>
|
|
523
|
+
${icon}
|
|
524
|
+
</svg>
|
|
525
|
+
</button>`)}
|
|
526
|
+
${this.renderFocusPen(app)}
|
|
527
|
+
</div>`;
|
|
528
|
+
}
|
|
529
|
+
render() {
|
|
530
|
+
const app = this.app;
|
|
531
|
+
if (!app) return nothing;
|
|
532
|
+
switch (app.tool) {
|
|
533
|
+
case Tool.Brush: return this.renderBrush(app, app.brush, "brush");
|
|
534
|
+
case Tool.Eraser: return this.renderBrush(app, app.eraser, "eraser");
|
|
535
|
+
case Tool.Move: return this.renderMove(app);
|
|
536
|
+
case Tool.Zoom: return this.renderZoom(app);
|
|
537
|
+
case Tool.ColourSample: return this.renderColourSample(app);
|
|
538
|
+
default: return MASK_TOOLS.includes(app.tool) ? this.renderMask(app) : nothing;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
defineElement("pc-tool-settings", PcToolSettings);
|
|
543
|
+
export { PcToolSettings, ZOOM_SLIDER_STEPS, hasToolSettings, roundAngle, sliderToZoom, withSource, zoomPercent, zoomToSlider };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// src/ui/elements/PcToolSettings/style.css?inline
|
|
2
|
+
var style_default = ":host {\n display: block;\n background: var(--pc-bar);\n border-bottom: 1px solid var(--pc-surface-active);\n}\n/* An open menu's button */\nbutton[aria-expanded=\"true\"] {\n background: var(--pc-surface-active);\n}\n/* Toggles that are on, and the selected option: purple, so it's obvious (the icon stays the same) */\nbutton[aria-pressed=\"true\"],\n.icon-toggle:has(input:checked),\n.icon-toggle:has(input:checked):hover {\n border-color: var(--pc-accent);\n background: var(--pc-accent);\n color: var(--pc-accent-text);\n}\n[role=\"toolbar\"] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 36px;\n padding: 4px 8px;\n overflow-x: auto;\n white-space: nowrap;\n}\ninput[type=\"number\"] {\n width: 4.5em;\n}\n.preset {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n.shape-preview {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: var(--pc-text);\n border-radius: 50%;\n vertical-align: middle;\n}\n.shape-preview.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: contain;\n mask-position: center;\n}\n/* Icon buttons (zoom in and out) */\nbutton img {\n display: block;\n width: 24px;\n height: 24px;\n}\n/* Fields' names small and in capitals above them, as designed */\n[role=\"toolbar\"] > label:not(.icon-toggle) {\n display: inline-flex;\n flex-direction: column;\n gap: 1px;\n font-size: 10px;\n text-transform: uppercase;\n}\n/* A unit after its field (\"%\", \"°\"), beside it rather than under it */\n[role=\"toolbar\"] > label:has(.unit) {\n position: relative;\n margin-right: 14px;\n}\n.unit {\n position: absolute;\n right: -14px;\n bottom: 3px;\n font-size: 13px;\n}\n/* Focus pen mode sits on the right of every tool's settings */\n.focus-pen {\n margin-left: auto;\n}\n";
|
|
3
|
+
export { style_default as default };
|