@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
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
import style_default from "./style.js";
|
|
2
2
|
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
3
|
+
import { markDismissingPress } from "../../dismiss/index.js";
|
|
3
4
|
import ChangeController from "../../ChangeController/index.js";
|
|
4
5
|
import PaintCanvas, { Panel } from "../../../lib/classes/PaintCanvas/index.js";
|
|
5
6
|
import KeyboardShortcuts, { SHORTCUT_EVENT } from "../../../lib/classes/KeyboardShortcuts/index.js";
|
|
6
7
|
import { isTouchDevice } from "../../../lib/classes/InputSettings/index.js";
|
|
7
|
-
import IndexedDbLayerStore from "../../../lib/storage/index.js";
|
|
8
|
+
import IndexedDbLayerStore, { IndexedDbSettingsStore } from "../../../lib/storage/index.js";
|
|
9
|
+
import SettingsAutosave, { SETTINGS_AUTOSAVE_ERROR_EVENT } from "../../../lib/classes/SettingsAutosave/index.js";
|
|
8
10
|
import { AUTOSAVE_ERROR_EVENT, AutosaveState } from "../../../lib/classes/LayerAutosave/index.js";
|
|
9
11
|
import { isOwnAuthor } from "../../../lib/brushes/authors/index.js";
|
|
10
12
|
import { renderScreenshot, saveFile, screenshotName } from "../../../lib/rendering/screenshot/index.js";
|
|
11
13
|
import { DEFAULT_SIDE_MODES, STATE_EVENT, parseSideModes, sideModeFor } from "../../layout/index.js";
|
|
12
14
|
import { hasToolSettings } from "../PcToolSettings/index.js";
|
|
13
15
|
import "../PcPanel/index.js";
|
|
14
|
-
import "../
|
|
16
|
+
import { PANE_COLLAPSE_EVENT, PcPane } from "../PcPane/index.js";
|
|
17
|
+
import { PcToolbar } from "../PcToolbar/index.js";
|
|
18
|
+
import "../PcClipboardTools/index.js";
|
|
15
19
|
import "../PcCanvas/index.js";
|
|
16
20
|
import "../PcCanvasMap/index.js";
|
|
17
|
-
import "../
|
|
18
|
-
import "../
|
|
21
|
+
import "../PcPanelBrushes/index.js";
|
|
22
|
+
import "../PcPanelLayers/index.js";
|
|
19
23
|
import "../PcBrushConfig/index.js";
|
|
20
24
|
import "../PcStats/index.js";
|
|
25
|
+
import "../PcPanelColours/index.js";
|
|
21
26
|
import "../PcDialog/index.js";
|
|
22
27
|
import { html, nothing, unsafeCSS } from "lit";
|
|
23
28
|
// src/ui/elements/PaintCanvas/index.ts
|
|
29
|
+
/** The sides */
|
|
30
|
+
var SIDES = ["left", "right"];
|
|
24
31
|
/** No space kept clear */
|
|
25
32
|
var NO_INSETS = {
|
|
26
33
|
top: 0,
|
|
@@ -30,29 +37,31 @@ var NO_INSETS = {
|
|
|
30
37
|
};
|
|
31
38
|
/** The choice that takes the drawing over from another window */
|
|
32
39
|
var TAKE_OVER_CHOICE = "take-over";
|
|
33
|
-
/** Elements that can take keyboard focus */
|
|
34
|
-
var FOCUSABLE = "button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])";
|
|
35
40
|
/**
|
|
36
41
|
* A ready-made painting app: the drawing elements arranged around the canvas, sized to its container (not the
|
|
37
42
|
* window), with slots to add or replace content:
|
|
38
43
|
*
|
|
39
44
|
* - `header`: across the top (empty by default)
|
|
40
|
-
* - `left`: `<pc-toolbar>` by default
|
|
41
|
-
*
|
|
42
|
-
* - `
|
|
45
|
+
* - `left`: `<pc-toolbar>` (a pane) by default; toolbars in the sides are minimised (their tools one button that opens a
|
|
46
|
+
* menu of them) while the layout is narrow
|
|
47
|
+
* - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) and, at its end,
|
|
48
|
+
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow) by default
|
|
49
|
+
* - `right`: a `<pc-pane>` with `<pc-panel-layers>` by default
|
|
43
50
|
* - `center`: `<pc-canvas>` by default
|
|
44
51
|
* - `overlay`: drawn over the canvas; `<pc-canvas-map>` by default
|
|
45
52
|
* - `bottom`: under the canvas (empty by default)
|
|
46
53
|
* - `footer`: across the bottom; `<pc-stats>` by default
|
|
47
|
-
* - `menu`: the app menu the toolbar's menu button opens (the button shows only with a menu)
|
|
54
|
+
* - `menu`: the app menu the toolbar's menu button opens, shown in a `<pc-panel>` (the button shows only with a menu)
|
|
48
55
|
*
|
|
49
56
|
* Content given for a slot replaces its default; an empty element clears it. Empty slots take no space. Hiding the
|
|
50
|
-
* interface (Tab key) leaves only the canvas and overlay.
|
|
51
|
-
*
|
|
57
|
+
* interface (Tab key) leaves only the canvas and overlay. While a side has a `<pc-panel-layers>` (as the right side
|
|
58
|
+
* does by default), the toolbar has no layers menu button.
|
|
52
59
|
*
|
|
53
60
|
* Each side has a mode, chosen by the layout's width from `left-modes` and `right-modes` (default `"docked,
|
|
54
|
-
* rail@600"`): `docked` beside the canvas; `rail`, a
|
|
55
|
-
* the canvas;
|
|
61
|
+
* rail@600"`), which the layout gives the side's `<pc-pane>`s (see `PcPane`): `docked` beside the canvas; `rail`, a
|
|
62
|
+
* column of buttons (one per panel) that open each panel over the canvas; `floating`, the pane over the canvas as a
|
|
63
|
+
* box that collapses to a button; or `overlay`, a rail over the canvas without a background (the canvas fills the
|
|
64
|
+
* width behind it). Give side content in a `<pc-pane>` to have it follow the side's mode.
|
|
56
65
|
*
|
|
57
66
|
* Reports its state for styling as attributes (`narrow`, `input="pen|touch|mouse"`, `ui-hidden`, `left-mode`,
|
|
58
67
|
* `right-mode`) and as `pc-state-change` events (see `LayoutState`). Creates its own canvas unless given one, and
|
|
@@ -62,10 +71,16 @@ var FOCUSABLE = "button, [href], input, select, textarea, [tabindex]:not([tabind
|
|
|
62
71
|
* reloading the page (see `LayerAutosave`). While another window is drawing on it, the layout is blocked by a message
|
|
63
72
|
* that offers to draw here instead. Fires `pc-toast` when the drawing can't be loaded or saved.
|
|
64
73
|
*
|
|
74
|
+
* With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette, colours,
|
|
75
|
+
* theme and language) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when they can't be.
|
|
76
|
+
*
|
|
65
77
|
* @example
|
|
66
78
|
* html`<paint-canvas style="height: 600px"></paint-canvas>`
|
|
67
79
|
* html`<paint-canvas .app=${canvas} right-modes="docked, rail@800">
|
|
68
|
-
* <pc-
|
|
80
|
+
* <pc-pane slot="right">
|
|
81
|
+
* <pc-panel-layers .app=${canvas}></pc-panel-layers>
|
|
82
|
+
* <pc-panel icon="chat" label="Chat"><my-chat></my-chat></pc-panel>
|
|
83
|
+
* </pc-pane>
|
|
69
84
|
* </paint-canvas>`
|
|
70
85
|
*/
|
|
71
86
|
var PaintCanvasElement = class extends PcElement {
|
|
@@ -94,11 +109,13 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
94
109
|
},
|
|
95
110
|
shortcuts: { type: Boolean },
|
|
96
111
|
store: { type: String },
|
|
112
|
+
settingsStore: {
|
|
113
|
+
type: String,
|
|
114
|
+
attribute: "settings-store"
|
|
115
|
+
},
|
|
97
116
|
width: { state: true },
|
|
98
117
|
input: { state: true },
|
|
99
|
-
configuring: { state: true }
|
|
100
|
-
collapsed: { state: true },
|
|
101
|
-
openPanel: { state: true }
|
|
118
|
+
configuring: { state: true }
|
|
102
119
|
};
|
|
103
120
|
static styles = [PcElement.styles, unsafeCSS(style_default)];
|
|
104
121
|
/** Saves files (replaceable for tests) */
|
|
@@ -108,13 +125,10 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
108
125
|
ownAutosave;
|
|
109
126
|
/** The autosave whose errors are shown */
|
|
110
127
|
watchedAutosave;
|
|
128
|
+
/** Keeps the app settings under the `settings-store` name, if any */
|
|
129
|
+
ownSettingsAutosave;
|
|
111
130
|
/** Whether drawing was blocked when shortcuts were last watched */
|
|
112
131
|
blockedShortcuts = false;
|
|
113
|
-
/** The panels in each side's slot */
|
|
114
|
-
panels = {
|
|
115
|
-
left: [],
|
|
116
|
-
right: []
|
|
117
|
-
};
|
|
118
132
|
/** Whether each side's slot has a layers menu (the toolbar's isn't needed then) */
|
|
119
133
|
sideLayers = {
|
|
120
134
|
left: false,
|
|
@@ -128,14 +142,11 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
128
142
|
keys;
|
|
129
143
|
/** The state last reported, to report only changes */
|
|
130
144
|
reported;
|
|
131
|
-
/** Space the floating sides cover over the canvas */
|
|
145
|
+
/** Space the floating and overlay sides cover over the canvas */
|
|
132
146
|
floatingInsets = NO_INSETS;
|
|
133
|
-
/** The rail button that opened the open panel, to return focus to */
|
|
134
|
-
opener;
|
|
135
147
|
resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(([entry]) => {
|
|
136
148
|
this.width = Math.round(entry?.contentRect.width ?? 0);
|
|
137
149
|
}) : void 0;
|
|
138
|
-
panelObserver = new MutationObserver(() => this.requestUpdate());
|
|
139
150
|
onPointerDown = (event) => {
|
|
140
151
|
const kind = event.pointerType;
|
|
141
152
|
this.input = kind === "pen" || kind === "touch" ? kind : "mouse";
|
|
@@ -144,20 +155,15 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
144
155
|
message: this.t("paintCanvas.autosave.failed"),
|
|
145
156
|
kind: "error"
|
|
146
157
|
});
|
|
158
|
+
onSettingsAutosaveError = () => emit(this, "pc-toast", {
|
|
159
|
+
message: this.t("paintCanvas.settings.saveFailed"),
|
|
160
|
+
kind: "error"
|
|
161
|
+
});
|
|
147
162
|
onShortcut = (event) => {
|
|
148
163
|
if (event.detail.type === "save") this.saveScreenshot();
|
|
149
164
|
};
|
|
150
|
-
onDocumentPointerDown = (event) =>
|
|
151
|
-
|
|
152
|
-
if (!panel) return;
|
|
153
|
-
const path = event.composedPath();
|
|
154
|
-
if (!path.includes(panel) && !(this.opener && path.includes(this.opener))) this.closePanel(false);
|
|
155
|
-
};
|
|
156
|
-
onKeyDown = (event) => {
|
|
157
|
-
if (event.key !== "Escape" || !this.openPanel) return;
|
|
158
|
-
event.preventDefault();
|
|
159
|
-
this.closePanel(true);
|
|
160
|
-
};
|
|
165
|
+
onDocumentPointerDown = (event) => this.closePanelOutside(event);
|
|
166
|
+
onPaneCollapse = () => this.requestUpdate();
|
|
161
167
|
constructor() {
|
|
162
168
|
super();
|
|
163
169
|
this.leftModes = DEFAULT_SIDE_MODES;
|
|
@@ -167,10 +173,6 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
167
173
|
this.shortcuts = true;
|
|
168
174
|
this.width = 0;
|
|
169
175
|
this.input = isTouchDevice() ? "touch" : "mouse";
|
|
170
|
-
this.collapsed = {
|
|
171
|
-
left: true,
|
|
172
|
-
right: true
|
|
173
|
-
};
|
|
174
176
|
}
|
|
175
177
|
/** Whether another window is drawing on the stored drawing, so this one is blocked */
|
|
176
178
|
get blocked() {
|
|
@@ -195,36 +197,25 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
195
197
|
this.app ??= new PaintCanvas();
|
|
196
198
|
super.connectedCallback();
|
|
197
199
|
this.resizeObserver?.observe(this);
|
|
198
|
-
this.panelObserver.observe(this, {
|
|
199
|
-
subtree: true,
|
|
200
|
-
attributes: true,
|
|
201
|
-
attributeFilter: [
|
|
202
|
-
"icon",
|
|
203
|
-
"label",
|
|
204
|
-
"badge"
|
|
205
|
-
]
|
|
206
|
-
});
|
|
207
200
|
this.addEventListener("pointerdown", this.onPointerDown, true);
|
|
208
|
-
this.addEventListener(
|
|
201
|
+
this.addEventListener(PANE_COLLAPSE_EVENT, this.onPaneCollapse);
|
|
209
202
|
document.addEventListener("pointerdown", this.onDocumentPointerDown, true);
|
|
210
203
|
this.watchShortcuts();
|
|
211
204
|
}
|
|
212
205
|
disconnectedCallback() {
|
|
213
206
|
super.disconnectedCallback();
|
|
214
207
|
this.resizeObserver?.disconnect();
|
|
215
|
-
this.panelObserver.disconnect();
|
|
216
208
|
this.removeEventListener("pointerdown", this.onPointerDown, true);
|
|
217
|
-
this.removeEventListener(
|
|
209
|
+
this.removeEventListener(PANE_COLLAPSE_EVENT, this.onPaneCollapse);
|
|
218
210
|
document.removeEventListener("pointerdown", this.onDocumentPointerDown, true);
|
|
219
211
|
this.unwatchShortcuts();
|
|
220
212
|
}
|
|
221
213
|
willUpdate(changed) {
|
|
222
214
|
super.willUpdate(changed);
|
|
223
215
|
if (changed.has("app") || changed.has("store")) this.useStore(changed.get("app"));
|
|
216
|
+
if (changed.has("app") || changed.has("settingsStore")) this.useSettingsStore();
|
|
224
217
|
this.watchAutosaveErrors();
|
|
225
218
|
if (this.isConnected && (changed.has("app") || changed.has("shortcuts") || this.blocked !== this.blockedShortcuts)) this.watchShortcuts();
|
|
226
|
-
const panel = this.openPanel;
|
|
227
|
-
if (panel && this.modeOf(this.sideOf(panel)) !== "rail") this.closePanel(false);
|
|
228
219
|
}
|
|
229
220
|
updated() {
|
|
230
221
|
const state = this.state;
|
|
@@ -238,11 +229,27 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
238
229
|
this.reported = report;
|
|
239
230
|
this.dispatchEvent(new CustomEvent(STATE_EVENT, { detail: state }));
|
|
240
231
|
}
|
|
232
|
+
this.setPaneModes();
|
|
241
233
|
this.measureFloatingSides();
|
|
242
234
|
}
|
|
243
|
-
/**
|
|
235
|
+
/** The panes in a side: the default one, or those given for it */
|
|
236
|
+
panesIn(side) {
|
|
237
|
+
const slot = this.renderRoot.querySelector(`slot[name="${side}"]`);
|
|
238
|
+
const given = slot.assignedElements();
|
|
239
|
+
return (given.length ? given : [...slot.children]).filter((element) => element instanceof PcPane);
|
|
240
|
+
}
|
|
241
|
+
/** Show each side's panes in the side's mode, facing the canvas, with toolbars minimised while the layout is narrow */
|
|
242
|
+
setPaneModes() {
|
|
243
|
+
const narrow = this.width < this.narrowWidth;
|
|
244
|
+
for (const side of SIDES) for (const pane of this.panesIn(side)) {
|
|
245
|
+
pane.mode = this.modeOf(side);
|
|
246
|
+
pane.edge = side;
|
|
247
|
+
if (pane instanceof PcToolbar) pane.minimised = narrow;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/** Keep the canvas clear of floating and overlay sides when fitting it */
|
|
244
251
|
measureFloatingSides() {
|
|
245
|
-
const width = (side) => this.
|
|
252
|
+
const width = (side) => this.panesIn(side).filter((pane) => pane.mode === "floating" ? !pane.collapsed : pane.mode === "overlay").reduce((widest, pane) => Math.max(widest, pane.getBoundingClientRect().width), 0);
|
|
246
253
|
const insets = {
|
|
247
254
|
...NO_INSETS,
|
|
248
255
|
left: width("left"),
|
|
@@ -267,6 +274,20 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
267
274
|
}
|
|
268
275
|
if (app.autosave?.store.name !== name) this.ownAutosave = app.useLayerStore(new IndexedDbLayerStore(name));
|
|
269
276
|
}
|
|
277
|
+
/** Keeps the app settings under the `settings-store` name, if any (e.g. to wait until they are restored with `ready`) */
|
|
278
|
+
get settingsAutosave() {
|
|
279
|
+
return this.ownSettingsAutosave;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Keep the canvas's app settings under the `settings-store` name, stopping the previous settings autosave (which
|
|
283
|
+
* saves any change waiting to be saved).
|
|
284
|
+
*/
|
|
285
|
+
useSettingsStore() {
|
|
286
|
+
this.ownSettingsAutosave?.stop();
|
|
287
|
+
const name = this.settingsStore || void 0;
|
|
288
|
+
this.ownSettingsAutosave = name === void 0 ? void 0 : new SettingsAutosave(this.app, new IndexedDbSettingsStore(name));
|
|
289
|
+
this.ownSettingsAutosave?.addEventListener(SETTINGS_AUTOSAVE_ERROR_EVENT, this.onSettingsAutosaveError);
|
|
290
|
+
}
|
|
270
291
|
/** Show errors from the canvas's current autosave */
|
|
271
292
|
watchAutosaveErrors() {
|
|
272
293
|
const autosave = this.app?.autosave;
|
|
@@ -339,40 +360,6 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
339
360
|
}
|
|
340
361
|
};
|
|
341
362
|
}
|
|
342
|
-
/** Which side a panel is in */
|
|
343
|
-
sideOf(panel) {
|
|
344
|
-
return panel.slot === "left" ? "left" : "right";
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Open a panel from its rail button (closing any other), or close it if it's open. Focus moves into the panel.
|
|
348
|
-
*/
|
|
349
|
-
togglePanel(panel, opener) {
|
|
350
|
-
if (this.openPanel === panel) {
|
|
351
|
-
this.closePanel(true);
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
if (this.openPanel) this.closePanel(false);
|
|
355
|
-
this.openPanel = panel;
|
|
356
|
-
this.opener = opener;
|
|
357
|
-
panel.toggleAttribute("data-pc-open", true);
|
|
358
|
-
const focusable = panel.querySelector(FOCUSABLE);
|
|
359
|
-
if (focusable) focusable.focus();
|
|
360
|
-
else {
|
|
361
|
-
panel.tabIndex = -1;
|
|
362
|
-
panel.focus();
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Close the panel open from a rail, moving focus back to its rail button if asked.
|
|
367
|
-
*/
|
|
368
|
-
closePanel(returnFocus) {
|
|
369
|
-
const panel = this.openPanel;
|
|
370
|
-
if (!panel) return;
|
|
371
|
-
panel.removeAttribute("data-pc-open");
|
|
372
|
-
this.openPanel = void 0;
|
|
373
|
-
if (returnFocus) this.opener?.focus();
|
|
374
|
-
this.opener = void 0;
|
|
375
|
-
}
|
|
376
363
|
/** Follow which slots have content given (their defaults aren't needed) */
|
|
377
364
|
onSlotChange(event) {
|
|
378
365
|
const slot = event.target;
|
|
@@ -388,16 +375,12 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
388
375
|
>${this.filled[name] ? nothing : fallback}</slot
|
|
389
376
|
>`;
|
|
390
377
|
}
|
|
391
|
-
/** Follow
|
|
378
|
+
/** Follow whether a side given content has a layers menu */
|
|
392
379
|
onSideSlotChange(side, event) {
|
|
393
380
|
const assigned = event.target.assignedElements();
|
|
394
|
-
this.panels = {
|
|
395
|
-
...this.panels,
|
|
396
|
-
[side]: assigned.filter((element) => element.localName === "pc-panel")
|
|
397
|
-
};
|
|
398
381
|
this.sideLayers = {
|
|
399
382
|
...this.sideLayers,
|
|
400
|
-
[side]: assigned.some((element) => element.matches("pc-layers
|
|
383
|
+
[side]: assigned.some((element) => element.matches("pc-panel-layers, :has(pc-panel-layers)"))
|
|
401
384
|
};
|
|
402
385
|
this.onSlotChange(event);
|
|
403
386
|
}
|
|
@@ -408,99 +391,74 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
408
391
|
}
|
|
409
392
|
/** Whether a side has a layers menu, replacing the toolbar's */
|
|
410
393
|
get layersInSide() {
|
|
411
|
-
return this.sideLayers.left || this.sideLayers.right;
|
|
412
|
-
}
|
|
413
|
-
/** The toolbar shown on the left unless the implementer gives other content */
|
|
414
|
-
renderToolbar(app) {
|
|
415
|
-
return html`<pc-toolbar
|
|
416
|
-
.app=${app}
|
|
417
|
-
.menu=${this.hasMenu}
|
|
418
|
-
.layers=${!this.layersInSide}
|
|
419
|
-
.menuText=${this.menuText}
|
|
420
|
-
.menuLabel=${this.menuLabel}
|
|
421
|
-
></pc-toolbar>`;
|
|
422
|
-
}
|
|
423
|
-
/** A side's rail buttons, one per panel */
|
|
424
|
-
renderRail(side, label) {
|
|
425
|
-
const panels = this.panels[side];
|
|
426
|
-
if (panels.length === 0) return nothing;
|
|
427
|
-
return html`<div
|
|
428
|
-
class="rail"
|
|
429
|
-
part="${side}-rail"
|
|
430
|
-
role="toolbar"
|
|
431
|
-
aria-orientation="vertical"
|
|
432
|
-
aria-label=${label}
|
|
433
|
-
>
|
|
434
|
-
${panels.map((panel) => html`<button
|
|
435
|
-
type="button"
|
|
436
|
-
title=${panel.label}
|
|
437
|
-
aria-label=${panel.badge ? this.t("paintCanvas.layout.new", { name: panel.label }) : panel.label}
|
|
438
|
-
aria-expanded=${String(this.openPanel === panel)}
|
|
439
|
-
@click=${(event) => this.togglePanel(panel, event.currentTarget)}
|
|
440
|
-
>
|
|
441
|
-
<img src=${this.iconUrl(panel.icon)} alt="" />
|
|
442
|
-
${panel.badge ? html`<span class="badge"></span>` : nothing}
|
|
443
|
-
</button>`)}
|
|
444
|
-
</div>`;
|
|
394
|
+
return this.sideLayers.left || this.sideLayers.right || !this.filled.right;
|
|
445
395
|
}
|
|
446
|
-
/** A side,
|
|
396
|
+
/** A side's default content: the toolbar on the left, and the layers on the right */
|
|
397
|
+
renderSideDefault(side, app, label) {
|
|
398
|
+
if (side === "left") return html`<pc-toolbar
|
|
399
|
+
.app=${app}
|
|
400
|
+
.menu=${this.hasMenu}
|
|
401
|
+
.layers=${!this.layersInSide}
|
|
402
|
+
.menuText=${this.menuText}
|
|
403
|
+
.menuLabel=${this.menuLabel}
|
|
404
|
+
label=${label}
|
|
405
|
+
></pc-toolbar>`;
|
|
406
|
+
return html`<pc-pane label=${label}
|
|
407
|
+
><pc-panel-layers slot="start" .app=${app}></pc-panel-layers
|
|
408
|
+
></pc-pane>`;
|
|
409
|
+
}
|
|
410
|
+
/** A side: its panes, in its mode (set on them after rendering) */
|
|
447
411
|
renderSide(side, app, blocked) {
|
|
448
|
-
const mode = this.modeOf(side);
|
|
449
412
|
const label = this.t(side === "left" ? "paintCanvas.layout.tools" : "paintCanvas.layout.panels");
|
|
450
|
-
const slot = html`<slot
|
|
451
|
-
name=${side}
|
|
452
|
-
@slotchange=${(event) => this.onSideSlotChange(side, event)}
|
|
453
|
-
>${side === "left" && !this.filled.left ? this.renderToolbar(app) : nothing}</slot
|
|
454
|
-
>`;
|
|
455
|
-
let content = slot;
|
|
456
|
-
if (mode === "rail") content = side === "left" ? html`${slot}${this.renderRail(side, label)}` : html`${this.renderRail(side, label)}${slot}`;
|
|
457
|
-
else if (mode === "floating") {
|
|
458
|
-
const collapsed = this.collapsed[side];
|
|
459
|
-
const arrows = side === "left" ? ["»", "«"] : ["«", "»"];
|
|
460
|
-
content = html`<div
|
|
461
|
-
class=${collapsed ? "float collapsed" : "float"}
|
|
462
|
-
part="${side}-float"
|
|
463
|
-
>
|
|
464
|
-
<button
|
|
465
|
-
type="button"
|
|
466
|
-
class="collapse"
|
|
467
|
-
aria-expanded=${String(!collapsed)}
|
|
468
|
-
aria-label=${this.t(collapsed ? "paintCanvas.layout.show" : "paintCanvas.layout.hide", { name: label })}
|
|
469
|
-
@click=${() => this.collapsed = {
|
|
470
|
-
...this.collapsed,
|
|
471
|
-
[side]: !collapsed
|
|
472
|
-
}}
|
|
473
|
-
>
|
|
474
|
-
${collapsed ? arrows[0] : arrows[1]}
|
|
475
|
-
</button>
|
|
476
|
-
<div class="content" ?hidden=${collapsed}>${slot}</div>
|
|
477
|
-
</div>`;
|
|
478
|
-
}
|
|
479
413
|
return html`<div
|
|
480
414
|
class="side ${side}"
|
|
481
415
|
part=${side}
|
|
482
|
-
data-mode=${
|
|
416
|
+
data-mode=${this.modeOf(side)}
|
|
483
417
|
role="region"
|
|
484
418
|
aria-label=${label}
|
|
485
419
|
?inert=${blocked}
|
|
486
420
|
>
|
|
487
|
-
|
|
421
|
+
<slot
|
|
422
|
+
name=${side}
|
|
423
|
+
@slotchange=${(event) => this.onSideSlotChange(side, event)}
|
|
424
|
+
>${this.filled[side] ? nothing : this.renderSideDefault(side, app, label)}</slot
|
|
425
|
+
>
|
|
488
426
|
</div>`;
|
|
489
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* Close the open panel (brush, eraser, layers, app menu or colour palette) on a press outside it and the button that
|
|
430
|
+
* opens it, marking the press (see `markDismissingPress`) so the canvas doesn't draw unless it's dragged. Presses in
|
|
431
|
+
* dialogs (e.g. one the panel opened) don't count as outside.
|
|
432
|
+
*/
|
|
433
|
+
closePanelOutside(event) {
|
|
434
|
+
const panel = this.app?.panel;
|
|
435
|
+
if (!panel) return;
|
|
436
|
+
if (event.composedPath().some((target) => target instanceof Element && (target.classList.contains("panel") && target.getRootNode() === this.renderRoot || target.matches("dialog, pc-dialog") || target.getAttribute("data-panel") === panel || panel === Panel.Palette && target.localName === "pc-colour-pair"))) return;
|
|
437
|
+
markDismissingPress(event);
|
|
438
|
+
this.app.closePanel();
|
|
439
|
+
}
|
|
490
440
|
/** The menus the toolbar opens, floating over the canvas beside it */
|
|
491
441
|
renderPanels(app) {
|
|
492
|
-
const brushMenu = (kind) => html`<pc-
|
|
442
|
+
const brushMenu = (kind) => html`<pc-panel-brushes
|
|
493
443
|
class="panel top-panel"
|
|
494
444
|
kind=${kind}
|
|
495
445
|
.app=${app}
|
|
496
446
|
@pc-new-preset=${() => this.newPreset(kind)}
|
|
497
|
-
></pc-
|
|
447
|
+
></pc-panel-brushes>`;
|
|
498
448
|
return html`${app.panel === Panel.Brush ? brushMenu("brush") : nothing}
|
|
499
449
|
${app.panel === Panel.Eraser ? brushMenu("eraser") : nothing}
|
|
500
|
-
${app.panel === Panel.Layers && !this.layersInSide ? html`<pc-layers
|
|
501
|
-
|
|
450
|
+
${app.panel === Panel.Layers && !this.layersInSide ? html`<pc-panel-layers class="panel" .app=${app}></pc-panel-layers>` : nothing}
|
|
451
|
+
${app.panel === Panel.Palette ? html`<pc-panel-colours
|
|
452
|
+
class="panel top-panel"
|
|
453
|
+
.app=${app}
|
|
454
|
+
></pc-panel-colours>` : nothing}
|
|
455
|
+
<pc-panel
|
|
456
|
+
class="panel menu-panel"
|
|
457
|
+
label=${this.menuLabel || this.t("paintCanvas.toolbar.menu")}
|
|
458
|
+
?open=${app.panel === Panel.Menu}
|
|
459
|
+
>
|
|
502
460
|
<slot name="menu" @slotchange=${this.onMenuSlotChange}></slot>
|
|
503
|
-
</
|
|
461
|
+
</pc-panel>`;
|
|
504
462
|
}
|
|
505
463
|
/** The brush configuration window, while open */
|
|
506
464
|
renderConfig(app) {
|
|
@@ -549,14 +507,23 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
549
507
|
aria-label=${this.t("paintCanvas.layout.toolSettings")}
|
|
550
508
|
?inert=${blocked}
|
|
551
509
|
>
|
|
552
|
-
${this.slotWithDefault("top", showsToolSettings ? html`<pc-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
510
|
+
${this.slotWithDefault("top", showsToolSettings ? html`<pc-pane orientation="horizontal" edge="top"
|
|
511
|
+
><pc-tool-settings
|
|
512
|
+
slot="middle"
|
|
513
|
+
.app=${app}
|
|
514
|
+
@pc-configure-brush=${(event) => this.configure(event.detail)}
|
|
515
|
+
></pc-tool-settings
|
|
516
|
+
><pc-clipboard-tools
|
|
517
|
+
slot="end"
|
|
518
|
+
.app=${app}
|
|
519
|
+
?narrow=${this.width < this.narrowWidth}
|
|
520
|
+
></pc-clipboard-tools
|
|
521
|
+
></pc-pane>` : nothing)}
|
|
556
522
|
</div>
|
|
557
523
|
<div
|
|
558
524
|
class="center"
|
|
559
525
|
part="center"
|
|
526
|
+
style="--pc-left-inset: ${this.floatingInsets.left}px"
|
|
560
527
|
role="region"
|
|
561
528
|
aria-label=${this.t("paintCanvas.layout.canvas")}
|
|
562
529
|
?inert=${blocked}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PaintCanvas/style.css?inline
|
|
2
|
-
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n.menu-panel:not([open]) {\n display: none;\n}\n\n/*
|
|
2
|
+
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n/* The tool settings fill the top pane */\n.top pc-tool-settings {\n flex: 1;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n/* A side's panes fill it */\n.side pc-pane,\n.side pc-toolbar,\n.side ::slotted(*) {\n flex: 1;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n/* The app menu: the implementer's content in a panel */\n.menu-panel:not([open]) {\n display: none;\n}\n\n/* Floating: the side's panes float over the canvas (see pc-pane), so the side takes no space */\n.side[data-mode=\"floating\"] {\n /* Beside the canvas only, so it floats over the canvas and not the tool settings */\n grid-row: 3;\n width: 0;\n}\n/* Overlay: the side's rail sits over the canvas (beside it only, not the tool settings), so the canvas fills the\n width behind it; presses between its panes' buttons (which take presses themselves) reach the canvas */\n.side[data-mode=\"overlay\"] {\n grid-row: 3;\n grid-column: 1 / -1;\n pointer-events: none;\n}\n.side.left[data-mode=\"overlay\"] {\n justify-self: start;\n}\n.side.right[data-mode=\"overlay\"] {\n justify-self: end;\n}\n/* The toolbar's panels open beside a left overlay rail, not under it */\n:host([left-mode=\"overlay\"]) .panel {\n left: var(--pc-left-inset);\n}\n/* While another window is drawing, its message covers only the layout (not the whole page) */\npc-dialog.elsewhere {\n position: absolute;\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { nothing, type PropertyValues } from "lit";
|
|
2
|
+
import { PcElement } from "../../base";
|
|
3
|
+
import "../PcShortcutSettings";
|
|
4
|
+
import type PaintCanvas from "../../../lib/classes/PaintCanvas";
|
|
5
|
+
import { type SaveMethod } from "../../../lib/rendering/screenshot";
|
|
6
|
+
/**
|
|
7
|
+
* Buttons for the user's app settings: "Keyboard shortcuts", which opens a window to change them (see
|
|
8
|
+
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
9
|
+
* settings, keyboard shortcuts, colour palette, colours, theme and language). The window is a modal `<dialog>` above the whole page; it
|
|
10
|
+
* closes with its Close button, Escape, or a press on the backdrop, and the browser gives focus back to the button. Fires `pc-toast` after importing, or when importing or
|
|
11
|
+
* exporting fails.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
15
|
+
*/
|
|
16
|
+
export declare class PcAppSettings extends PcElement {
|
|
17
|
+
static properties: {
|
|
18
|
+
app: {
|
|
19
|
+
attribute: boolean;
|
|
20
|
+
};
|
|
21
|
+
shortcutsOpen: {
|
|
22
|
+
type: BooleanConstructor;
|
|
23
|
+
attribute: string;
|
|
24
|
+
};
|
|
25
|
+
translations: {
|
|
26
|
+
attribute: boolean;
|
|
27
|
+
};
|
|
28
|
+
icons: {
|
|
29
|
+
attribute: boolean;
|
|
30
|
+
};
|
|
31
|
+
theme: {
|
|
32
|
+
type: StringConstructor;
|
|
33
|
+
reflect: boolean;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
static styles: import("lit").CSSResultGroup[];
|
|
37
|
+
app?: PaintCanvas;
|
|
38
|
+
/** Whether the keyboard shortcuts window is open */
|
|
39
|
+
shortcutsOpen: boolean;
|
|
40
|
+
/** Saves exported files (replaceable for tests) */
|
|
41
|
+
saveFile: (blob: Blob, name: string) => Promise<SaveMethod | undefined>;
|
|
42
|
+
constructor();
|
|
43
|
+
protected updated(changed: PropertyValues<this>): void;
|
|
44
|
+
/** Close the keyboard shortcuts window */
|
|
45
|
+
closeShortcuts(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Import the settings in a settings file, using the parts it has.
|
|
48
|
+
*/
|
|
49
|
+
importFile(file: File): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Export the settings as a settings file.
|
|
52
|
+
*/
|
|
53
|
+
exportFile(): Promise<void>;
|
|
54
|
+
/** Show a settings file error (one of `SETTINGS_FILE_ERRORS`) in the chosen language */
|
|
55
|
+
private toastError;
|
|
56
|
+
/** The keyboard shortcuts window: a modal dialog, with its contents only while open */
|
|
57
|
+
private renderShortcuts;
|
|
58
|
+
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
59
|
+
}
|