@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.
Files changed (212) hide show
  1. package/README.md +30 -15
  2. package/dist/lib/brushes/StrokeEngine/index.d.ts +2 -2
  3. package/dist/lib/brushes/StrokeEngine/index.js +26 -28
  4. package/dist/lib/brushes/presets/round/index.d.ts +1 -1
  5. package/dist/lib/brushes/presets/round/index.js +12 -7
  6. package/dist/lib/brushes/presets/square/index.d.ts +1 -1
  7. package/dist/lib/brushes/presets/square/index.js +7 -3
  8. package/dist/lib/brushes/shapeImage/index.d.ts +7 -3
  9. package/dist/lib/brushes/shapeImage/index.js +15 -9
  10. package/dist/lib/brushes/shapes/index.d.ts +18 -0
  11. package/dist/lib/brushes/shapes/index.js +86 -0
  12. package/dist/lib/classes/BrushSettings/index.d.ts +53 -2
  13. package/dist/lib/classes/BrushSettings/index.js +85 -14
  14. package/dist/lib/classes/KeyboardShortcuts/index.d.ts +47 -7
  15. package/dist/lib/classes/KeyboardShortcuts/index.js +145 -20
  16. package/dist/lib/classes/PaintCanvas/index.d.ts +123 -27
  17. package/dist/lib/classes/PaintCanvas/index.js +208 -41
  18. package/dist/lib/classes/PaintCanvas/tool.d.ts +15 -0
  19. package/dist/lib/classes/PaintCanvas/tool.js +18 -0
  20. package/dist/lib/classes/Palette/index.d.ts +58 -0
  21. package/dist/lib/classes/Palette/index.js +92 -0
  22. package/dist/lib/classes/SettingsAutosave/index.d.ts +53 -0
  23. package/dist/lib/classes/SettingsAutosave/index.js +98 -0
  24. package/dist/lib/classes/ShortcutSettings/index.d.ts +63 -0
  25. package/dist/lib/classes/ShortcutSettings/index.js +110 -0
  26. package/dist/lib/classes/UiSettings/index.d.ts +68 -0
  27. package/dist/lib/classes/UiSettings/index.js +82 -0
  28. package/dist/lib/palette/index.d.ts +49 -0
  29. package/dist/lib/palette/index.js +82 -0
  30. package/dist/lib/palette/schema.d.ts +45 -0
  31. package/dist/lib/palette/schema.js +41 -0
  32. package/dist/lib/rendering/cursors/index.d.ts +2 -0
  33. package/dist/lib/rendering/cursors/index.js +3 -1
  34. package/dist/lib/rendering/sample/index.js +3 -2
  35. package/dist/lib/settings/index.d.ts +63 -0
  36. package/dist/lib/settings/index.js +93 -0
  37. package/dist/lib/settings/schema.d.ts +168 -0
  38. package/dist/lib/settings/schema.js +116 -0
  39. package/dist/lib/storage/index.d.ts +36 -5
  40. package/dist/lib/storage/index.js +87 -29
  41. package/dist/lib/utils/colour/index.d.ts +72 -0
  42. package/dist/lib/utils/colour/index.js +154 -0
  43. package/dist/lib/utils/shortcuts/index.d.ts +174 -11
  44. package/dist/lib/utils/shortcuts/index.js +391 -145
  45. package/dist/lib/validation/validators.generated.d.ts +5 -0
  46. package/dist/lib/validation/validators.generated.js +1040 -1
  47. package/dist/locales/en-GB.js +96 -3
  48. package/dist/locales/en-US.js +96 -3
  49. package/dist/locales/fr.js +96 -3
  50. package/dist/locales/ja.js +96 -3
  51. package/dist/locales/ko.js +96 -3
  52. package/dist/locales/zh-Hans.js +96 -3
  53. package/dist/locales/zh-Hant.js +96 -3
  54. package/dist/package.js +1 -1
  55. package/dist/testing/recordingCanvas.js +2 -1
  56. package/dist/ui/base/index.d.ts +2 -2
  57. package/dist/ui/dismiss/index.d.ts +21 -0
  58. package/dist/ui/dismiss/index.js +27 -0
  59. package/dist/ui/drag/index.d.ts +51 -0
  60. package/dist/ui/drag/index.js +81 -0
  61. package/dist/ui/elements/PaintCanvas/index.d.ts +57 -50
  62. package/dist/ui/elements/PaintCanvas/index.js +141 -174
  63. package/dist/ui/elements/PaintCanvas/style.js +1 -1
  64. package/dist/ui/elements/PcAppSettings/index.d.ts +59 -0
  65. package/dist/ui/elements/PcAppSettings/index.js +222 -0
  66. package/dist/ui/elements/PcBrushConfig/index.d.ts +9 -2
  67. package/dist/ui/elements/PcBrushConfig/index.js +47 -7
  68. package/dist/ui/elements/PcBrushConfig/style.js +1 -1
  69. package/dist/ui/elements/PcBrushSize/index.d.ts +53 -0
  70. package/dist/ui/elements/PcBrushSize/index.js +66 -0
  71. package/dist/ui/elements/PcBrushTest/index.d.ts +26 -0
  72. package/dist/ui/elements/PcBrushTest/index.js +73 -5
  73. package/dist/ui/elements/PcBrushTest/style.js +1 -1
  74. package/dist/ui/elements/PcCanvas/index.d.ts +22 -2
  75. package/dist/ui/elements/PcCanvas/index.js +60 -15
  76. package/dist/ui/elements/PcCanvasMap/style.js +1 -1
  77. package/dist/ui/elements/PcClipboardTools/index.d.ts +48 -0
  78. package/dist/ui/elements/PcClipboardTools/index.js +118 -0
  79. package/dist/ui/elements/PcColourPair/index.d.ts +43 -0
  80. package/dist/ui/elements/PcColourPair/index.js +125 -0
  81. package/dist/ui/elements/PcContextMenu/index.d.ts +71 -34
  82. package/dist/ui/elements/PcContextMenu/index.js +128 -97
  83. package/dist/ui/elements/PcInputSettings/index.d.ts +13 -0
  84. package/dist/ui/elements/PcInputSettings/index.js +16 -1
  85. package/dist/ui/elements/PcLayerItem/index.d.ts +13 -34
  86. package/dist/ui/elements/PcLayerItem/index.js +39 -91
  87. package/dist/ui/elements/PcLayerItem/style.js +1 -1
  88. package/dist/ui/elements/PcMenu/index.d.ts +138 -0
  89. package/dist/ui/elements/PcMenu/index.js +296 -0
  90. package/dist/ui/elements/PcNumberSlider/index.d.ts +137 -0
  91. package/dist/ui/elements/PcNumberSlider/index.js +247 -0
  92. package/dist/ui/elements/PcPane/index.d.ts +120 -0
  93. package/dist/ui/elements/PcPane/index.js +394 -0
  94. package/dist/ui/elements/PcPanel/index.d.ts +26 -8
  95. package/dist/ui/elements/PcPanel/index.js +76 -8
  96. package/dist/ui/elements/{PcBrushMenu → PcPanelBrushes}/index.d.ts +22 -21
  97. package/dist/ui/elements/{PcBrushMenu → PcPanelBrushes}/index.js +24 -57
  98. package/dist/ui/elements/PcPanelBrushes/style.js +3 -0
  99. package/dist/ui/elements/PcPanelColours/index.d.ts +171 -0
  100. package/dist/ui/elements/PcPanelColours/index.js +650 -0
  101. package/dist/ui/elements/PcPanelColours/style.js +3 -0
  102. package/dist/ui/elements/{PcLayersMenu → PcPanelLayers}/index.d.ts +17 -4
  103. package/dist/ui/elements/{PcLayersMenu → PcPanelLayers}/index.js +17 -10
  104. package/dist/ui/elements/PcPanelLayers/style.js +3 -0
  105. package/dist/ui/elements/PcPopover/index.d.ts +39 -1
  106. package/dist/ui/elements/PcPopover/index.js +72 -4
  107. package/dist/ui/elements/PcShortcutSettings/index.d.ts +69 -0
  108. package/dist/ui/elements/PcShortcutSettings/index.js +273 -0
  109. package/dist/ui/elements/PcThemePicker/index.d.ts +17 -15
  110. package/dist/ui/elements/PcThemePicker/index.js +22 -21
  111. package/dist/ui/elements/PcToolSettings/index.d.ts +48 -9
  112. package/dist/ui/elements/PcToolSettings/index.js +384 -319
  113. package/dist/ui/elements/PcToolSettings/style.js +1 -1
  114. package/dist/ui/elements/PcToolbar/index.d.ts +62 -12
  115. package/dist/ui/elements/PcToolbar/index.js +119 -57
  116. package/dist/ui/elements/PcToolbar/style.js +1 -1
  117. package/dist/ui/icons/images/icon-brush@2x.js +3 -0
  118. package/dist/ui/icons/images/icon-circle-mask@2x.js +3 -0
  119. package/dist/ui/icons/images/icon-clipboard@2x.js +3 -0
  120. package/dist/ui/icons/images/icon-cog@2x.js +3 -0
  121. package/dist/ui/icons/images/icon-cursor@2x.js +3 -0
  122. package/dist/ui/icons/images/icon-diagonal-tlbr-size@2x.js +3 -0
  123. package/dist/ui/icons/images/icon-diagonal-trbl-size@2x.js +3 -0
  124. package/dist/ui/icons/images/icon-eraser@2x.js +3 -0
  125. package/dist/ui/icons/images/icon-eyedropper@2x.js +3 -0
  126. package/dist/ui/icons/images/icon-flip-horizontal@2x.js +3 -0
  127. package/dist/ui/icons/images/icon-flip-vertical@2x.js +3 -0
  128. package/dist/ui/icons/images/icon-focus-pen@2x.js +3 -0
  129. package/dist/ui/icons/images/icon-freehand-mask@2x.js +3 -0
  130. package/dist/ui/icons/images/icon-hidden@2x.js +3 -0
  131. package/dist/ui/icons/images/icon-horizontal-size@2x.js +3 -0
  132. package/dist/ui/icons/images/icon-layers@2x.js +3 -0
  133. package/dist/ui/icons/images/icon-linked@2x.js +3 -0
  134. package/dist/ui/icons/images/icon-locked@2x.js +3 -0
  135. package/dist/ui/icons/images/icon-moon@2x.js +3 -0
  136. package/dist/ui/icons/images/icon-pan@2x.js +3 -0
  137. package/dist/ui/icons/images/icon-polygon-mask@2x.js +3 -0
  138. package/dist/ui/icons/images/icon-pressure@2x.js +3 -0
  139. package/dist/ui/icons/images/icon-randomise@2x.js +3 -0
  140. package/dist/ui/icons/images/icon-rectangle-mask@2x.js +3 -0
  141. package/dist/ui/icons/images/icon-redo@2x.js +3 -0
  142. package/dist/ui/icons/images/icon-rotate-90-left@2x.js +3 -0
  143. package/dist/ui/icons/images/icon-rotate-90-right@2x.js +3 -0
  144. package/dist/ui/icons/images/icon-rotate@2x.js +3 -0
  145. package/dist/ui/icons/images/icon-smoothing-bezier-cubic@2x.js +3 -0
  146. package/dist/ui/icons/images/icon-smoothing-bezier-quad@2x.js +3 -0
  147. package/dist/ui/icons/images/icon-smoothing-linear@2x.js +3 -0
  148. package/dist/ui/icons/images/icon-star@2x.js +3 -0
  149. package/dist/ui/icons/images/icon-sun@2x.js +3 -0
  150. package/dist/ui/icons/images/icon-tilt@2x.js +3 -0
  151. package/dist/ui/icons/images/icon-undo@2x.js +3 -0
  152. package/dist/ui/icons/images/icon-unlinked@2x.js +3 -0
  153. package/dist/ui/icons/images/icon-unlocked@2x.js +3 -0
  154. package/dist/ui/icons/images/icon-vertical-size@2x.js +3 -0
  155. package/dist/ui/icons/images/icon-visible@2x.js +3 -0
  156. package/dist/ui/icons/images/icon-zoom-in@2x.js +3 -0
  157. package/dist/ui/icons/images/icon-zoom-out@2x.js +3 -0
  158. package/dist/ui/icons/images/icon-zoom@2x.js +3 -0
  159. package/dist/ui/icons/index.d.ts +1 -1
  160. package/dist/ui/icons/index.js +84 -72
  161. package/dist/ui/index.d.ts +13 -2
  162. package/dist/ui/index.js +16 -4
  163. package/dist/ui/layout/index.d.ts +9 -1
  164. package/dist/ui/layout/index.js +11 -2
  165. package/dist/ui/tokens/index.d.ts +5 -4
  166. package/dist/ui/tokens/index.js +15 -8
  167. package/locales/en-GB.json +96 -3
  168. package/locales/en-US.json +96 -3
  169. package/locales/fr.json +96 -3
  170. package/locales/ja.json +96 -3
  171. package/locales/ko.json +96 -3
  172. package/locales/zh-Hans.json +96 -3
  173. package/locales/zh-Hant.json +96 -3
  174. package/package.json +11 -4
  175. package/dist/ui/elements/PcBrushMenu/style.js +0 -3
  176. package/dist/ui/elements/PcLayersMenu/style.js +0 -3
  177. package/dist/ui/icons/images/brush.js +0 -3
  178. package/dist/ui/icons/images/circle-mask.js +0 -3
  179. package/dist/ui/icons/images/clipboard.js +0 -3
  180. package/dist/ui/icons/images/cursor.js +0 -3
  181. package/dist/ui/icons/images/eraser.js +0 -3
  182. package/dist/ui/icons/images/eyedropper.js +0 -3
  183. package/dist/ui/icons/images/flip-horizontal.js +0 -3
  184. package/dist/ui/icons/images/flip-vertical.js +0 -3
  185. package/dist/ui/icons/images/focus-pen.js +0 -3
  186. package/dist/ui/icons/images/freehand-mask.js +0 -3
  187. package/dist/ui/icons/images/hidden.js +0 -3
  188. package/dist/ui/icons/images/layers.js +0 -3
  189. package/dist/ui/icons/images/linked.js +0 -3
  190. package/dist/ui/icons/images/locked.js +0 -3
  191. package/dist/ui/icons/images/moon.js +0 -3
  192. package/dist/ui/icons/images/pan.js +0 -3
  193. package/dist/ui/icons/images/polygon-mask.js +0 -3
  194. package/dist/ui/icons/images/pressure.js +0 -3
  195. package/dist/ui/icons/images/randomise.js +0 -3
  196. package/dist/ui/icons/images/rectangle-mask.js +0 -3
  197. package/dist/ui/icons/images/redo.js +0 -3
  198. package/dist/ui/icons/images/rotate-90-left.js +0 -3
  199. package/dist/ui/icons/images/rotate-90-right.js +0 -3
  200. package/dist/ui/icons/images/smoothing-bezier-cubic.js +0 -3
  201. package/dist/ui/icons/images/smoothing-bezier-quad.js +0 -3
  202. package/dist/ui/icons/images/smoothing-linear.js +0 -3
  203. package/dist/ui/icons/images/star.js +0 -3
  204. package/dist/ui/icons/images/sun.js +0 -3
  205. package/dist/ui/icons/images/tilt.js +0 -3
  206. package/dist/ui/icons/images/undo.js +0 -3
  207. package/dist/ui/icons/images/unlinked.js +0 -3
  208. package/dist/ui/icons/images/unlocked.js +0 -3
  209. package/dist/ui/icons/images/visible.js +0 -3
  210. package/dist/ui/icons/images/zoom-in.js +0 -3
  211. package/dist/ui/icons/images/zoom-out.js +0 -3
  212. package/dist/ui/icons/images/zoom.js +0 -3
@@ -1,4 +1,6 @@
1
1
  import StrokeLog from "../StrokeLog";
2
+ import { Tool } from "./tool";
3
+ import { isHexColour } from "../../utils/colour";
2
4
  import BackgroundWork from "../BackgroundWork";
3
5
  import type { DrawableLayer } from "../../rendering/compositing";
4
6
  import BrushSettings from "../BrushSettings";
@@ -16,25 +18,14 @@ import type { LayerStoreLike } from "../../storage";
16
18
  import type { AssetAuthor, BrushConfig } from "../../brushes/types";
17
19
  import CustomPresets, { type PresetStoreLike } from "../CustomPresets";
18
20
  import InputSettings from "../InputSettings";
21
+ import UiSettings from "../UiSettings";
22
+ import Palette from "../Palette";
23
+ import ShortcutSettings from "../ShortcutSettings";
19
24
  import ExternalSheets from "../ExternalSheets";
20
25
  import { type CanvasMessage, type PatchMessage, type StrokeMessage } from "../../messages";
21
26
  import { type BoundingBox } from "../../image";
22
27
  import { type PaintCanvasDocument } from "../../document";
23
- /** Drawing and navigation tools */
24
- export declare enum Tool {
25
- Brush = "brush",
26
- Eraser = "eraser",
27
- /** Move, scale and rotate */
28
- Move = "move",
29
- RectangleLasso = "rectangle-lasso",
30
- CircleLasso = "circle-lasso",
31
- PolygonLasso = "polygon-lasso",
32
- FreeformLasso = "freeform-lasso",
33
- Pan = "pan",
34
- Zoom = "zoom",
35
- /** Set the current colour from the canvas (eyedropper) */
36
- ColourSample = "colour-sample"
37
- }
28
+ export { Tool };
38
29
  /** How the colour sample tool samples: the pixel under the pointer, or the average of a dragged rectangle */
39
30
  export type SampleMode = "point" | "area";
40
31
  /** Toggleable panels */
@@ -43,7 +34,9 @@ export declare enum Panel {
43
34
  Eraser = "eraser",
44
35
  Layers = "layers",
45
36
  /** The implementer's own app menu */
46
- Menu = "menu"
37
+ Menu = "menu",
38
+ /** The colour palette: the foreground and background colours, their values and the saved colours */
39
+ Palette = "palette"
47
40
  }
48
41
  /** Panels opened by tools */
49
42
  export declare const TOOL_PANELS: Partial<Record<Tool, Panel>>;
@@ -51,8 +44,15 @@ export declare const TOOL_PANELS: Partial<Record<Tool, Panel>>;
51
44
  export declare const DEFAULT_CANVAS_SIZE = 2000;
52
45
  /** Largest canvas width or height allowed when the `maxCanvasSize` option isn't given */
53
46
  export declare const MAX_CANVAS_SIZE = 2000;
54
- /** Drawing colour to start with */
47
+ /** Foreground colour to start with */
55
48
  export declare const DEFAULT_COLOUR = "#000000";
49
+ /** Background colour to start with */
50
+ export declare const DEFAULT_BACKGROUND_COLOUR = "#ffffff";
51
+ /**
52
+ * One of the two colours: the foreground colour (painted by the brush and foreground fills) or the background colour
53
+ * (painted by the eraser and Delete when the layer's alpha lock is on, and by background fills).
54
+ */
55
+ export type ColourSlot = "foreground" | "background";
56
56
  /** Owner of the custom presets when the `ownerId` option isn't given */
57
57
  export declare const DEFAULT_OWNER_ID = "local";
58
58
  /** Author name of presets made with `newPreset` when the `presetAuthor` option isn't given */
@@ -65,11 +65,16 @@ export interface PaintCanvasNames {
65
65
  filePrefix: string;
66
66
  /** The `format` written in exported brush preset files */
67
67
  presetFileFormat: string;
68
+ /** The `format` written in exported colour palette files */
69
+ paletteFileFormat: string;
70
+ /** The `format` written in exported settings files */
71
+ settingsFileFormat: string;
68
72
  /** Author name of presets made by a user without a handle, e.g. from `presetAuthor` */
69
73
  unknownAuthor: string;
70
74
  }
71
75
  /** PaintCanvas's own names */
72
76
  export declare const DEFAULT_NAMES: Readonly<PaintCanvasNames>;
77
+ export { isHexColour };
73
78
  /** How much the canvas holds, e.g. to show in a stats panel */
74
79
  export interface CanvasStats {
75
80
  /** Canvas width in pixels */
@@ -121,9 +126,16 @@ export interface PaintCanvasOptions {
121
126
  names?: Partial<PaintCanvasNames>;
122
127
  /** Where to keep the user's layers so the drawing survives reloading the page (see `useLayerStore`) */
123
128
  layerStore?: LayerStoreLike;
129
+ /**
130
+ * The system clipboard, which copying and cutting also put a PNG of the copied image data on so other apps (and brush
131
+ * shapes) can use it (the browser's by default; `null` for none)
132
+ */
133
+ systemClipboard?: SystemClipboardLike | null;
124
134
  }
135
+ /** The part of the system clipboard PaintCanvas writes to (the browser's `navigator.clipboard`) */
136
+ export type SystemClipboardLike = Pick<Clipboard, "write">;
125
137
  /**
126
- * The painting engine: canvas size, layers, brush and eraser settings, custom presets, the selected tool, colour,
138
+ * The painting engine: canvas size, layers, brush and eraser settings, custom presets, the selected tool, foreground and background colours,
127
139
  * selection, transforms, clipboard, undo/redo history, viewport and input settings. Where its data is kept and who it
128
140
  * is shared with are up to the implementer (see `onMessage` and `receive`).
129
141
  *
@@ -134,6 +146,7 @@ export interface PaintCanvasOptions {
134
146
  * const canvas = new PaintCanvas({ width: 1000, height: 800 });
135
147
  * canvas.selectTool(Tool.Brush, { fromToolbar: true });
136
148
  * canvas.setColour("#ff0000");
149
+ * canvas.setColour("#ffffff", "background");
137
150
  */
138
151
  export default class PaintCanvas extends EventTarget {
139
152
  /** Brush settings */
@@ -154,6 +167,12 @@ export default class PaintCanvas extends EventTarget {
154
167
  readonly background: BackgroundWork;
155
168
  /** How the user's input devices control the canvas (scrolling, pinching, touch gestures, focus pen mode) */
156
169
  readonly input: InputSettings;
170
+ /** The user's interface choices (theme and language), kept with the other app settings */
171
+ readonly ui: UiSettings;
172
+ /** The user's saved colours, shown as swatches */
173
+ readonly palette: Palette;
174
+ /** The user's keyboard shortcuts: each configurable action's key combination */
175
+ readonly shortcuts: ShortcutSettings;
157
176
  /** The user's pointer position over the canvas, in canvas pixels (undefined when off the canvas) */
158
177
  pointer?: Point;
159
178
  /** Selected tool */
@@ -190,9 +209,14 @@ export default class PaintCanvas extends EventTarget {
190
209
  private sendingStrokes;
191
210
  /** Whether a stroke from elsewhere is being drawn (it isn't sent again) */
192
211
  private replaying;
193
- private currentColour;
212
+ private currentColours;
213
+ private currentSelectedColour;
194
214
  /** Image data copied with cut or copy, and the area it was copied from */
195
215
  private clipboard?;
216
+ /** How many times image data has been copied (see `copyCount`) */
217
+ private copies;
218
+ /** The system clipboard copies are also put on, if any */
219
+ private readonly systemClipboard?;
196
220
  /** Drawings from elsewhere */
197
221
  private externalSheets;
198
222
  /** Who receives the drawing messages this canvas sends */
@@ -416,30 +440,83 @@ export default class PaintCanvas extends EventTarget {
416
440
  */
417
441
  copy(): Rect | undefined;
418
442
  /**
419
- * Copy the masked image data of the selected layer to the clipboard, then erase it from the layer as one undoable
420
- * action.
443
+ * How many times image data has been copied or cut, to tell whether it was copied here since something else may have
444
+ * been copied in another app (see `KeyboardShortcuts`).
445
+ */
446
+ get copyCount(): number;
447
+ /** Whether there is copied image data to paste (see `copy` and `cut`) */
448
+ get hasClipboard(): boolean;
449
+ /**
450
+ * The copied image data as a PNG, if there is any (e.g. to use as a brush shape).
451
+ *
452
+ * @example
453
+ * const png = await canvas.copiedPng(); // Blob of type "image/png", or undefined
454
+ */
455
+ copiedPng(): Promise<Blob | undefined>;
456
+ /**
457
+ * Put copied image data on the system clipboard as a PNG, if there is one and the browser can. The item is made
458
+ * straight away (some browsers only allow writing while handling the key press or click) with the PNG to follow.
459
+ * Failing (e.g. the page isn't focused) changes nothing: the image data can still be pasted here.
460
+ */
461
+ private writeSystemClipboard;
462
+ /**
463
+ * Copy the masked image data of the selected layer to the clipboard, then remove it from the layer as one undoable
464
+ * action (see `deleteMasked`).
421
465
  */
422
466
  cut(): void;
423
467
  /**
424
- * Erase the masked image data from the selected layer as one undoable action (Delete or Backspace). Needs a mask with
468
+ * Erase the masked image data from the selected layer as one undoable action (Delete or Backspace). When the layer's
469
+ * alpha lock is on, it is painted with the background colour instead, keeping its transparency. Needs a mask with
425
470
  * image data inside it; does nothing during a stroke or while a transform is pending.
426
471
  */
427
472
  deleteMasked(): void;
473
+ /**
474
+ * Fill the selected layer with the foreground or background colour as one undoable action: only the masked area when
475
+ * there is a mask (partly where it is partly), and only existing pixels when the layer's alpha lock is on. Does
476
+ * nothing during a stroke or while a transform is pending.
477
+ *
478
+ * @example
479
+ * canvas.fill("foreground");
480
+ */
481
+ fill(slot: ColourSlot): void;
482
+ /**
483
+ * The area a fill changes: the mask's bounds (or the whole canvas without a mask), cut to the selected layer's image
484
+ * data when its alpha lock is on. None if that is empty.
485
+ */
486
+ private fillArea;
428
487
  /**
429
488
  * The bounds of the selected layer's image data inside the mask, if there is a mask with image data inside it. None
430
489
  * during a stroke or while a transform is pending.
431
490
  */
432
491
  private maskedArea;
433
492
  /**
434
- * Erase the mask's part of an area from the selected layer, as one undoable action.
493
+ * Erase the mask's part of an area from the selected layer, or paint it with the background colour when the layer's
494
+ * alpha lock is on, as one undoable action.
495
+ */
496
+ private clearMasked;
497
+ /**
498
+ * Paint a colour over an area of the selected layer, cut to the mask if there is one (partly where it is partly), as
499
+ * one undoable action. Only existing pixels are painted when the layer's alpha lock is on.
435
500
  */
436
- private eraseMasked;
501
+ private paintArea;
437
502
  /**
438
503
  * Show the clipboard's image data over the selected layer where it was copied from, and select the Move tool to place,
439
504
  * scale and rotate it. It is written into the layer (and sent) on Enter or when switching to another tool; Escape
440
505
  * discards it. A pending transform is applied first.
441
506
  */
442
507
  paste(): void;
508
+ /**
509
+ * Show an image from elsewhere (e.g. pasted from another app) over the selected layer, in the middle of the part of
510
+ * the canvas in view, and select the Move tool to place, scale and rotate it, like `paste`. An image larger than the
511
+ * canvas is shrunk to fit it. Does nothing during a stroke.
512
+ *
513
+ * @example
514
+ * canvas.pasteImage(await createImageBitmap(file));
515
+ */
516
+ pasteImage(source: CanvasImageSource & {
517
+ width: number;
518
+ height: number;
519
+ }): void;
443
520
  /**
444
521
  * Apply a finished lasso action to the mask: a shape is added, subtracted or replaces it; a plain click deselects.
445
522
  */
@@ -468,12 +545,31 @@ export default class PaintCanvas extends EventTarget {
468
545
  get activeTool(): Tool;
469
546
  /** The user's layers */
470
547
  get layers(): LayerStack;
471
- /** Current drawing colour as a hex string, e.g. `#000000` */
548
+ /** Current foreground colour as a hex string, e.g. `#000000` (the same as `colours.foreground`) */
472
549
  get colour(): string;
550
+ /** Current foreground and background colours as hex strings, e.g. `{ foreground: "#000000", background: "#ffffff" }` */
551
+ get colours(): Readonly<Record<ColourSlot, string>>;
552
+ /** Which colour is selected for configuration, e.g. by a colour picker or the colour sample tool ("foreground" by default) */
553
+ get selectedColour(): ColourSlot;
554
+ /**
555
+ * Set the foreground colour, or the background colour. Must be a 6-digit hex colour, e.g. `#ff0000`.
556
+ *
557
+ * @example
558
+ * canvas.setColour("#ff0000"); // foreground
559
+ * canvas.setColour("#ffffff", "background");
560
+ */
561
+ setColour(colour: string, slot?: ColourSlot): void;
562
+ /**
563
+ * Select which colour is configured, e.g. by a colour picker or the colour sample tool. One colour is always selected.
564
+ *
565
+ * @example
566
+ * canvas.selectColour("background");
567
+ */
568
+ selectColour(slot: ColourSlot): void;
473
569
  /**
474
- * Set the drawing colour. Must be a 6-digit hex colour, e.g. `#ff0000`.
570
+ * Swap the foreground and background colours. The selected colour stays the same slot.
475
571
  */
476
- setColour(colour: string): void;
572
+ swapColours(): void;
477
573
  /**
478
574
  * Change the canvas size, from 1 to the maximum canvas size (`maxCanvasSize` option). Replaces all layers.
479
575
  */
@@ -1,4 +1,6 @@
1
1
  import StrokeLog from "../StrokeLog/index.js";
2
+ import { Tool } from "./tool.js";
3
+ import { isHexColour } from "../../utils/colour/index.js";
2
4
  import BackgroundWork from "../BackgroundWork/index.js";
3
5
  import BrushSettings from "../BrushSettings/index.js";
4
6
  import LayerStack from "../LayerStack/index.js";
@@ -17,6 +19,12 @@ import "../../presets/index.js";
17
19
  import CustomPresets from "../CustomPresets/index.js";
18
20
  import { BRUSH_PRESET_FILE_FORMAT } from "../../presets/schema.js";
19
21
  import InputSettings from "../InputSettings/index.js";
22
+ import UiSettings from "../UiSettings/index.js";
23
+ import Palette from "../Palette/index.js";
24
+ import ShortcutSettings from "../ShortcutSettings/index.js";
25
+ import { PALETTE_FILE_FORMAT } from "../../palette/schema.js";
26
+ import "../../palette/index.js";
27
+ import { SETTINGS_FILE_FORMAT } from "../../settings/schema.js";
20
28
  import ExternalSheets from "../ExternalSheets/index.js";
21
29
  import PatchSender from "../../messages/PatchSender/index.js";
22
30
  import { createPatchMessage, validateCanvasMessage } from "../../messages/index.js";
@@ -28,22 +36,6 @@ import { DOCUMENT_FORMAT } from "../../document/schema.js";
28
36
  import { isValidDocument } from "../../document/index.js";
29
37
  import { averageColour, flattenArea, pixelRect, readPixels } from "../../rendering/sample/index.js";
30
38
  // src/lib/classes/PaintCanvas/index.ts
31
- /** Drawing and navigation tools */
32
- var Tool = /* @__PURE__ */ function(Tool) {
33
- Tool["Brush"] = "brush";
34
- Tool["Eraser"] = "eraser";
35
- /** Move, scale and rotate */
36
- Tool["Move"] = "move";
37
- Tool["RectangleLasso"] = "rectangle-lasso";
38
- Tool["CircleLasso"] = "circle-lasso";
39
- Tool["PolygonLasso"] = "polygon-lasso";
40
- Tool["FreeformLasso"] = "freeform-lasso";
41
- Tool["Pan"] = "pan";
42
- Tool["Zoom"] = "zoom";
43
- /** Set the current colour from the canvas (eyedropper) */
44
- Tool["ColourSample"] = "colour-sample";
45
- return Tool;
46
- }({});
47
39
  /** Toggleable panels */
48
40
  var Panel = /* @__PURE__ */ function(Panel) {
49
41
  Panel["Brush"] = "brush";
@@ -51,19 +43,23 @@ var Panel = /* @__PURE__ */ function(Panel) {
51
43
  Panel["Layers"] = "layers";
52
44
  /** The implementer's own app menu */
53
45
  Panel["Menu"] = "menu";
46
+ /** The colour palette: the foreground and background colours, their values and the saved colours */
47
+ Panel["Palette"] = "palette";
54
48
  return Panel;
55
49
  }({});
56
50
  /** Panels opened by tools */
57
51
  var TOOL_PANELS = {
58
- ["brush"]: "brush",
59
- ["eraser"]: "eraser"
52
+ [Tool.Brush]: "brush",
53
+ [Tool.Eraser]: "eraser"
60
54
  };
61
55
  /** Canvas width and height when none is given */
62
56
  var DEFAULT_CANVAS_SIZE = 2e3;
63
57
  /** Largest canvas width or height allowed when the `maxCanvasSize` option isn't given */
64
58
  var MAX_CANVAS_SIZE = 2e3;
65
- /** Drawing colour to start with */
59
+ /** Foreground colour to start with */
66
60
  var DEFAULT_COLOUR = "#000000";
61
+ /** Background colour to start with */
62
+ var DEFAULT_BACKGROUND_COLOUR = "#ffffff";
67
63
  /** Owner of the custom presets when the `ownerId` option isn't given */
68
64
  var DEFAULT_OWNER_ID = "local";
69
65
  /** Author name of presets made with `newPreset` when the `presetAuthor` option isn't given */
@@ -73,10 +69,10 @@ var DEFAULT_NAMES = {
73
69
  app: BUILT_IN_AUTHOR,
74
70
  filePrefix: "paintcanvas",
75
71
  presetFileFormat: BRUSH_PRESET_FILE_FORMAT,
72
+ paletteFileFormat: PALETTE_FILE_FORMAT,
73
+ settingsFileFormat: SETTINGS_FILE_FORMAT,
76
74
  unknownAuthor: UNKNOWN_AUTHOR
77
75
  };
78
- /** Pattern for colour input values */
79
- var COLOUR_PATTERN = /^#[0-9a-f]{6}$/i;
80
76
  /**
81
77
  * A canvas's pixels as a PNG data URL.
82
78
  */
@@ -98,7 +94,7 @@ var decodePatch = async (patch) => {
98
94
  return new ImageData(await decodeRgbaDeflate(patch.data, patch.coords), width, height);
99
95
  };
100
96
  /**
101
- * The painting engine: canvas size, layers, brush and eraser settings, custom presets, the selected tool, colour,
97
+ * The painting engine: canvas size, layers, brush and eraser settings, custom presets, the selected tool, foreground and background colours,
102
98
  * selection, transforms, clipboard, undo/redo history, viewport and input settings. Where its data is kept and who it
103
99
  * is shared with are up to the implementer (see `onMessage` and `receive`).
104
100
  *
@@ -109,6 +105,7 @@ var decodePatch = async (patch) => {
109
105
  * const canvas = new PaintCanvas({ width: 1000, height: 800 });
110
106
  * canvas.selectTool(Tool.Brush, { fromToolbar: true });
111
107
  * canvas.setColour("#ff0000");
108
+ * canvas.setColour("#ffffff", "background");
112
109
  */
113
110
  var PaintCanvas = class extends EventTarget {
114
111
  /** Brush settings */
@@ -129,10 +126,16 @@ var PaintCanvas = class extends EventTarget {
129
126
  background = new BackgroundWork(this.strokeLog);
130
127
  /** How the user's input devices control the canvas (scrolling, pinching, touch gestures, focus pen mode) */
131
128
  input = new InputSettings();
129
+ /** The user's interface choices (theme and language), kept with the other app settings */
130
+ ui = new UiSettings();
131
+ /** The user's saved colours, shown as swatches */
132
+ palette = new Palette();
133
+ /** The user's keyboard shortcuts: each configurable action's key combination */
134
+ shortcuts = new ShortcutSettings();
132
135
  /** The user's pointer position over the canvas, in canvas pixels (undefined when off the canvas) */
133
136
  pointer;
134
137
  /** Selected tool */
135
- tool = "brush";
138
+ tool = Tool.Brush;
136
139
  /** Tool used temporarily while a key is held (e.g. Space for pan), overriding the selected tool */
137
140
  heldTool = null;
138
141
  /** Open panel, if any */
@@ -186,9 +189,17 @@ var PaintCanvas = class extends EventTarget {
186
189
  sendingStrokes = false;
187
190
  /** Whether a stroke from elsewhere is being drawn (it isn't sent again) */
188
191
  replaying = false;
189
- currentColour = DEFAULT_COLOUR;
192
+ currentColours = {
193
+ foreground: DEFAULT_COLOUR,
194
+ background: DEFAULT_BACKGROUND_COLOUR
195
+ };
196
+ currentSelectedColour = "foreground";
190
197
  /** Image data copied with cut or copy, and the area it was copied from */
191
198
  clipboard;
199
+ /** How many times image data has been copied (see `copyCount`) */
200
+ copies = 0;
201
+ /** The system clipboard copies are also put on, if any */
202
+ systemClipboard;
192
203
  /** Drawings from elsewhere */
193
204
  externalSheets;
194
205
  /** Who receives the drawing messages this canvas sends */
@@ -229,6 +240,7 @@ var PaintCanvas = class extends EventTarget {
229
240
  this.customPresets.addEventListener("change", () => this.listCustomPresets());
230
241
  this.customPresets.load().catch(() => void 0);
231
242
  this.createCanvas = options.createCanvas ?? createOffscreenCanvas;
243
+ this.systemClipboard = options.systemClipboard === null ? void 0 : options.systemClipboard ?? globalThis.navigator?.clipboard;
232
244
  this.canvasWidth = DEFAULT_CANVAS_SIZE;
233
245
  this.canvasHeight = DEFAULT_CANVAS_SIZE;
234
246
  this.layerStack = new LayerStack(this.canvasWidth, this.canvasHeight, this.createCanvas, this.maxLayers);
@@ -642,7 +654,7 @@ var PaintCanvas = class extends EventTarget {
642
654
  */
643
655
  syncTransform() {
644
656
  const transformer = this.transformer;
645
- if (this.tool !== "move") {
657
+ if (this.tool !== Tool.Move) {
646
658
  if (transformer.pending) this.commitTransform();
647
659
  else if (transformer.active) {
648
660
  transformer.reset();
@@ -713,23 +725,87 @@ var PaintCanvas = class extends EventTarget {
713
725
  image,
714
726
  area
715
727
  };
728
+ this.copies++;
729
+ this.writeSystemClipboard(image);
730
+ this.notify();
716
731
  return area;
717
732
  }
718
733
  /**
719
- * Copy the masked image data of the selected layer to the clipboard, then erase it from the layer as one undoable
720
- * action.
734
+ * How many times image data has been copied or cut, to tell whether it was copied here since something else may have
735
+ * been copied in another app (see `KeyboardShortcuts`).
736
+ */
737
+ get copyCount() {
738
+ return this.copies;
739
+ }
740
+ /** Whether there is copied image data to paste (see `copy` and `cut`) */
741
+ get hasClipboard() {
742
+ return this.clipboard !== void 0;
743
+ }
744
+ /**
745
+ * The copied image data as a PNG, if there is any (e.g. to use as a brush shape).
746
+ *
747
+ * @example
748
+ * const png = await canvas.copiedPng(); // Blob of type "image/png", or undefined
749
+ */
750
+ async copiedPng() {
751
+ return this.clipboard?.image.convertToBlob({ type: "image/png" });
752
+ }
753
+ /**
754
+ * Put copied image data on the system clipboard as a PNG, if there is one and the browser can. The item is made
755
+ * straight away (some browsers only allow writing while handling the key press or click) with the PNG to follow.
756
+ * Failing (e.g. the page isn't focused) changes nothing: the image data can still be pasted here.
757
+ */
758
+ writeSystemClipboard(image) {
759
+ if (!this.systemClipboard || typeof ClipboardItem === "undefined") return;
760
+ const item = new ClipboardItem({ "image/png": image.convertToBlob({ type: "image/png" }) });
761
+ this.systemClipboard.write([item]).catch(() => void 0);
762
+ }
763
+ /**
764
+ * Copy the masked image data of the selected layer to the clipboard, then remove it from the layer as one undoable
765
+ * action (see `deleteMasked`).
721
766
  */
722
767
  cut() {
723
768
  const area = this.copy();
724
- if (area) this.eraseMasked(area);
769
+ if (area) this.clearMasked(area);
725
770
  }
726
771
  /**
727
- * Erase the masked image data from the selected layer as one undoable action (Delete or Backspace). Needs a mask with
772
+ * Erase the masked image data from the selected layer as one undoable action (Delete or Backspace). When the layer's
773
+ * alpha lock is on, it is painted with the background colour instead, keeping its transparency. Needs a mask with
728
774
  * image data inside it; does nothing during a stroke or while a transform is pending.
729
775
  */
730
776
  deleteMasked() {
731
777
  const area = this.maskedArea();
732
- if (area) this.eraseMasked(area);
778
+ if (area) this.clearMasked(area);
779
+ }
780
+ /**
781
+ * Fill the selected layer with the foreground or background colour as one undoable action: only the masked area when
782
+ * there is a mask (partly where it is partly), and only existing pixels when the layer's alpha lock is on. Does
783
+ * nothing during a stroke or while a transform is pending.
784
+ *
785
+ * @example
786
+ * canvas.fill("foreground");
787
+ */
788
+ fill(slot) {
789
+ if (this.strokeEngine.drawing || this.transformer.pending) return;
790
+ const area = this.fillArea();
791
+ if (area) this.paintArea(area, this.currentColours[slot]);
792
+ }
793
+ /**
794
+ * The area a fill changes: the mask's bounds (or the whole canvas without a mask), cut to the selected layer's image
795
+ * data when its alpha lock is on. None if that is empty.
796
+ */
797
+ fillArea() {
798
+ const { width, height } = this;
799
+ const layer = this.layerStack.active;
800
+ const mask = this.currentSelection.mask;
801
+ const maskData = mask ? mask.getContext("2d").getImageData(0, 0, width, height).data : void 0;
802
+ if (layer.alphaLock) return contentBounds(layer.context.getImageData(0, 0, width, height).data, width, height, maskData);
803
+ return maskData ? contentBounds(maskData, width, height) : {
804
+ x: 0,
805
+ y: 0,
806
+ width,
807
+ height
808
+ };
733
809
  }
734
810
  /**
735
811
  * The bounds of the selected layer's image data inside the mask, if there is a mask with image data inside it. None
@@ -742,12 +818,18 @@ var PaintCanvas = class extends EventTarget {
742
818
  return contentBounds(this.layerStack.active.context.getImageData(0, 0, width, height).data, width, height, mask.getContext("2d").getImageData(0, 0, width, height).data);
743
819
  }
744
820
  /**
745
- * Erase the mask's part of an area from the selected layer, as one undoable action.
821
+ * Erase the mask's part of an area from the selected layer, or paint it with the background colour when the layer's
822
+ * alpha lock is on, as one undoable action.
746
823
  */
747
- eraseMasked(area) {
824
+ clearMasked(area) {
825
+ const layer = this.layerStack.active;
826
+ if (layer.alphaLock) {
827
+ this.paintArea(area, this.currentColours.background);
828
+ return;
829
+ }
748
830
  const mask = this.currentSelection.mask;
749
831
  const maskPiece = copyArea(this.createCanvas, mask, area);
750
- this.layerStack.changeImage(this.layerStack.active.id, area, (ctx) => {
832
+ this.layerStack.changeImage(layer.id, area, (ctx) => {
751
833
  ctx.save();
752
834
  ctx.globalCompositeOperation = "destination-out";
753
835
  ctx.drawImage(maskPiece, area.x, area.y);
@@ -755,6 +837,28 @@ var PaintCanvas = class extends EventTarget {
755
837
  });
756
838
  }
757
839
  /**
840
+ * Paint a colour over an area of the selected layer, cut to the mask if there is one (partly where it is partly), as
841
+ * one undoable action. Only existing pixels are painted when the layer's alpha lock is on.
842
+ */
843
+ paintArea(area, colour) {
844
+ const layer = this.layerStack.active;
845
+ const mask = this.currentSelection.mask;
846
+ const paint = this.createCanvas(area.width, area.height);
847
+ const paintCtx = paint.getContext("2d");
848
+ if (mask) {
849
+ paintCtx.drawImage(copyArea(this.createCanvas, mask, area), 0, 0);
850
+ paintCtx.globalCompositeOperation = "source-in";
851
+ }
852
+ paintCtx.fillStyle = colour;
853
+ paintCtx.fillRect(0, 0, area.width, area.height);
854
+ this.layerStack.changeImage(layer.id, area, (ctx) => {
855
+ ctx.save();
856
+ ctx.globalCompositeOperation = layer.alphaLock ? "source-atop" : "source-over";
857
+ ctx.drawImage(paint, area.x, area.y);
858
+ ctx.restore();
859
+ });
860
+ }
861
+ /**
758
862
  * Show the clipboard's image data over the selected layer where it was copied from, and select the Move tool to place,
759
863
  * scale and rotate it. It is written into the layer (and sent) on Enter or when switching to another tool; Escape
760
864
  * discards it. A pending transform is applied first.
@@ -763,10 +867,36 @@ var PaintCanvas = class extends EventTarget {
763
867
  const clipboard = this.clipboard;
764
868
  if (!clipboard || this.strokeEngine.drawing) return;
765
869
  if (this.transformer.pending) this.commitTransform();
766
- this.selectTool("move");
870
+ this.selectTool(Tool.Move);
767
871
  this.transformer.float(this.layerStack.active, clipboard.image, clipboard.area);
768
872
  }
769
873
  /**
874
+ * Show an image from elsewhere (e.g. pasted from another app) over the selected layer, in the middle of the part of
875
+ * the canvas in view, and select the Move tool to place, scale and rotate it, like `paste`. An image larger than the
876
+ * canvas is shrunk to fit it. Does nothing during a stroke.
877
+ *
878
+ * @example
879
+ * canvas.pasteImage(await createImageBitmap(file));
880
+ */
881
+ pasteImage(source) {
882
+ if (this.strokeEngine.drawing) return;
883
+ const scale = Math.min(1, this.canvasWidth / source.width, this.canvasHeight / source.height);
884
+ const width = Math.max(1, Math.round(source.width * scale));
885
+ const height = Math.max(1, Math.round(source.height * scale));
886
+ const image = this.createCanvas(width, height);
887
+ image.getContext("2d").drawImage(source, 0, 0, width, height);
888
+ const view = this.view.visibleRect();
889
+ const area = {
890
+ x: Math.round(view.x + (view.width - width) / 2),
891
+ y: Math.round(view.y + (view.height - height) / 2),
892
+ width,
893
+ height
894
+ };
895
+ if (this.transformer.pending) this.commitTransform();
896
+ this.selectTool(Tool.Move);
897
+ this.transformer.float(this.layerStack.active, image, area);
898
+ }
899
+ /**
770
900
  * Apply a finished lasso action to the mask: a shape is added, subtracted or replaces it; a plain click deselects.
771
901
  */
772
902
  applyLasso(result) {
@@ -827,16 +957,53 @@ var PaintCanvas = class extends EventTarget {
827
957
  get layers() {
828
958
  return this.layerStack;
829
959
  }
830
- /** Current drawing colour as a hex string, e.g. `#000000` */
960
+ /** Current foreground colour as a hex string, e.g. `#000000` (the same as `colours.foreground`) */
831
961
  get colour() {
832
- return this.currentColour;
962
+ return this.currentColours.foreground;
963
+ }
964
+ /** Current foreground and background colours as hex strings, e.g. `{ foreground: "#000000", background: "#ffffff" }` */
965
+ get colours() {
966
+ return this.currentColours;
967
+ }
968
+ /** Which colour is selected for configuration, e.g. by a colour picker or the colour sample tool ("foreground" by default) */
969
+ get selectedColour() {
970
+ return this.currentSelectedColour;
971
+ }
972
+ /**
973
+ * Set the foreground colour, or the background colour. Must be a 6-digit hex colour, e.g. `#ff0000`.
974
+ *
975
+ * @example
976
+ * canvas.setColour("#ff0000"); // foreground
977
+ * canvas.setColour("#ffffff", "background");
978
+ */
979
+ setColour(colour, slot = "foreground") {
980
+ if (!isHexColour(colour)) throw new Error(`Invalid colour ${colour}`);
981
+ this.currentColours = {
982
+ ...this.currentColours,
983
+ [slot]: colour.toLowerCase()
984
+ };
985
+ this.notify();
986
+ }
987
+ /**
988
+ * Select which colour is configured, e.g. by a colour picker or the colour sample tool. One colour is always selected.
989
+ *
990
+ * @example
991
+ * canvas.selectColour("background");
992
+ */
993
+ selectColour(slot) {
994
+ if (slot === this.currentSelectedColour) return;
995
+ this.currentSelectedColour = slot;
996
+ this.notify();
833
997
  }
834
998
  /**
835
- * Set the drawing colour. Must be a 6-digit hex colour, e.g. `#ff0000`.
999
+ * Swap the foreground and background colours. The selected colour stays the same slot.
836
1000
  */
837
- setColour(colour) {
838
- if (!COLOUR_PATTERN.test(colour)) throw new Error(`Invalid colour ${colour}`);
839
- this.currentColour = colour.toLowerCase();
1001
+ swapColours() {
1002
+ const { foreground, background } = this.currentColours;
1003
+ this.currentColours = {
1004
+ foreground: background,
1005
+ background: foreground
1006
+ };
840
1007
  this.notify();
841
1008
  }
842
1009
  /**
@@ -963,4 +1130,4 @@ var PaintCanvas = class extends EventTarget {
963
1130
  this.dispatchEvent(new Event("change"));
964
1131
  }
965
1132
  };
966
- export { DEFAULT_AUTHOR, DEFAULT_CANVAS_SIZE, DEFAULT_COLOUR, DEFAULT_NAMES, DEFAULT_OWNER_ID, MAX_CANVAS_SIZE, Panel, TOOL_PANELS, Tool, PaintCanvas as default };
1133
+ export { DEFAULT_AUTHOR, DEFAULT_BACKGROUND_COLOUR, DEFAULT_CANVAS_SIZE, DEFAULT_COLOUR, DEFAULT_NAMES, DEFAULT_OWNER_ID, MAX_CANVAS_SIZE, Panel, TOOL_PANELS, Tool, PaintCanvas as default, isHexColour };
@@ -0,0 +1,15 @@
1
+ /** Drawing and navigation tools */
2
+ export declare enum Tool {
3
+ Brush = "brush",
4
+ Eraser = "eraser",
5
+ /** Move, scale and rotate */
6
+ Move = "move",
7
+ RectangleLasso = "rectangle-lasso",
8
+ CircleLasso = "circle-lasso",
9
+ PolygonLasso = "polygon-lasso",
10
+ FreeformLasso = "freeform-lasso",
11
+ Pan = "pan",
12
+ Zoom = "zoom",
13
+ /** Set the current colour from the canvas (eyedropper) */
14
+ ColourSample = "colour-sample"
15
+ }