@lvl99dotcom/paintcanvas 0.6.0 → 0.8.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 (119) hide show
  1. package/README.md +3 -2
  2. package/dist/lib/assets/index.d.ts +92 -0
  3. package/dist/lib/assets/index.js +106 -0
  4. package/dist/lib/assets/schema.d.ts +151 -0
  5. package/dist/lib/assets/schema.js +76 -0
  6. package/dist/lib/brushes/presetFile/index.d.ts +6 -27
  7. package/dist/lib/brushes/presetFile/index.js +34 -47
  8. package/dist/lib/brushes/types/index.d.ts +2 -11
  9. package/dist/lib/classes/AssetSync/index.d.ts +45 -0
  10. package/dist/lib/classes/AssetSync/index.js +80 -0
  11. package/dist/lib/classes/ColourPalettes/index.d.ts +83 -0
  12. package/dist/lib/classes/ColourPalettes/index.js +165 -0
  13. package/dist/lib/classes/CustomPresets/index.d.ts +14 -15
  14. package/dist/lib/classes/CustomPresets/index.js +25 -10
  15. package/dist/lib/classes/LayerAutosave/index.d.ts +9 -2
  16. package/dist/lib/classes/LayerAutosave/index.js +16 -6
  17. package/dist/lib/classes/PaintCanvas/index.d.ts +124 -28
  18. package/dist/lib/classes/PaintCanvas/index.js +228 -63
  19. package/dist/lib/classes/Palette/index.d.ts +3 -2
  20. package/dist/lib/classes/Palette/index.js +3 -2
  21. package/dist/lib/classes/ProfileGraphs/index.d.ts +13 -2
  22. package/dist/lib/classes/ProfileGraphs/index.js +22 -2
  23. package/dist/lib/classes/RemoteDocumentAutosave/index.d.ts +73 -0
  24. package/dist/lib/classes/RemoteDocumentAutosave/index.js +119 -0
  25. package/dist/lib/classes/SettingsAutosave/index.d.ts +7 -3
  26. package/dist/lib/classes/SettingsAutosave/index.js +28 -7
  27. package/dist/lib/classes/SettingsExtensions/index.d.ts +67 -0
  28. package/dist/lib/classes/SettingsExtensions/index.js +88 -0
  29. package/dist/lib/classes/UiSettings/index.d.ts +24 -2
  30. package/dist/lib/classes/UiSettings/index.js +32 -7
  31. package/dist/lib/document/index.d.ts +61 -4
  32. package/dist/lib/document/index.js +173 -4
  33. package/dist/lib/document/schema.d.ts +154 -39
  34. package/dist/lib/document/schema.js +91 -25
  35. package/dist/lib/messages/schema.d.ts +176 -74
  36. package/dist/lib/messages/schema.js +2 -1
  37. package/dist/lib/palette/index.d.ts +8 -42
  38. package/dist/lib/palette/index.js +26 -59
  39. package/dist/lib/palette/schema.d.ts +111 -22
  40. package/dist/lib/palette/schema.js +51 -26
  41. package/dist/lib/presets/index.d.ts +1 -9
  42. package/dist/lib/presets/index.js +4 -10
  43. package/dist/lib/presets/schema.d.ts +118 -73
  44. package/dist/lib/presets/schema.js +28 -60
  45. package/dist/lib/profiles/profileFile/index.d.ts +10 -0
  46. package/dist/lib/profiles/profileFile/index.js +19 -0
  47. package/dist/lib/profiles/schema.d.ts +96 -3
  48. package/dist/lib/profiles/schema.js +31 -7
  49. package/dist/lib/schemas/index.d.ts +42 -0
  50. package/dist/lib/schemas/index.js +60 -0
  51. package/dist/lib/settings/index.d.ts +37 -22
  52. package/dist/lib/settings/index.js +78 -37
  53. package/dist/lib/settings/schema.d.ts +202 -77
  54. package/dist/lib/settings/schema.js +93 -86
  55. package/dist/lib/storage/index.d.ts +108 -3
  56. package/dist/lib/storage/index.js +119 -5
  57. package/dist/lib/validation/validators.generated.d.ts +19 -8
  58. package/dist/lib/validation/validators.generated.js +44723 -18889
  59. package/dist/lib/version/index.d.ts +25 -0
  60. package/dist/lib/version/index.js +35 -0
  61. package/dist/locales/en-GB.js +28 -5
  62. package/dist/locales/en-US.js +28 -5
  63. package/dist/locales/fr.js +28 -5
  64. package/dist/locales/ja.js +28 -5
  65. package/dist/locales/ko.js +28 -5
  66. package/dist/locales/zh-Hans.js +28 -5
  67. package/dist/locales/zh-Hant.js +28 -5
  68. package/dist/package.js +1 -1
  69. package/dist/testing/app.d.ts +6 -2
  70. package/dist/testing/app.js +7 -2
  71. package/dist/testing/documentStore.d.ts +26 -0
  72. package/dist/testing/documentStore.js +31 -0
  73. package/dist/ui/elements/PaintCanvas/index.d.ts +19 -5
  74. package/dist/ui/elements/PaintCanvas/index.js +41 -10
  75. package/dist/ui/elements/PcAppSettings/index.d.ts +14 -7
  76. package/dist/ui/elements/PcAppSettings/index.js +58 -33
  77. package/dist/ui/elements/PcBrushConfig/index.d.ts +1 -0
  78. package/dist/ui/elements/PcBrushConfig/index.js +8 -9
  79. package/dist/ui/elements/PcBrushTest/index.d.ts +1 -0
  80. package/dist/ui/elements/PcBrushTest/index.js +8 -7
  81. package/dist/ui/elements/PcBrushTest/style.js +1 -1
  82. package/dist/ui/elements/PcButtonMenu/index.d.ts +88 -0
  83. package/dist/ui/elements/PcButtonMenu/index.js +125 -0
  84. package/dist/ui/elements/PcCanvas/index.d.ts +9 -0
  85. package/dist/ui/elements/PcCanvas/index.js +33 -17
  86. package/dist/ui/elements/PcClipboardTools/index.d.ts +7 -4
  87. package/dist/ui/elements/PcClipboardTools/index.js +20 -26
  88. package/dist/ui/elements/PcInputSettings/index.d.ts +2 -1
  89. package/dist/ui/elements/PcInputSettings/index.js +9 -15
  90. package/dist/ui/elements/PcLayerItem/index.d.ts +21 -6
  91. package/dist/ui/elements/PcLayerItem/index.js +53 -26
  92. package/dist/ui/elements/PcLayerItem/style.js +1 -1
  93. package/dist/ui/elements/PcPanelBrushes/index.d.ts +1 -1
  94. package/dist/ui/elements/PcPanelBrushes/index.js +22 -28
  95. package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
  96. package/dist/ui/elements/PcPanelColours/index.d.ts +56 -19
  97. package/dist/ui/elements/PcPanelColours/index.js +251 -104
  98. package/dist/ui/elements/PcPanelColours/style.js +1 -1
  99. package/dist/ui/elements/PcSliderRange/index.js +3 -2
  100. package/dist/ui/elements/PcStats/index.d.ts +8 -4
  101. package/dist/ui/elements/PcStats/index.js +39 -5
  102. package/dist/ui/elements/PcToggleCheckbox/index.d.ts +13 -2
  103. package/dist/ui/elements/PcToggleCheckbox/index.js +27 -8
  104. package/dist/ui/elements/PcToolSettings/index.d.ts +1 -0
  105. package/dist/ui/elements/PcToolSettings/index.js +8 -8
  106. package/dist/ui/elements/PcVersion/index.d.ts +12 -0
  107. package/dist/ui/elements/PcVersion/index.js +43 -0
  108. package/dist/ui/index.d.ts +3 -1
  109. package/dist/ui/index.js +4 -2
  110. package/dist/ui/layout/index.d.ts +2 -2
  111. package/dist/ui/layout/index.js +2 -2
  112. package/locales/en-GB.json +28 -5
  113. package/locales/en-US.json +28 -5
  114. package/locales/fr.json +28 -5
  115. package/locales/ja.json +28 -5
  116. package/locales/ko.json +28 -5
  117. package/locales/zh-Hans.json +28 -5
  118. package/locales/zh-Hant.json +28 -5
  119. package/package.json +3 -2
@@ -14,18 +14,24 @@ import Lasso, { type LassoResult } from "../../selection/Lasso";
14
14
  import Transformer from "../../transform/Transformer";
15
15
  import { type CanvasFactory, type LayerConfig } from "../Layer";
16
16
  import LayerAutosave, { type AutosaveOptions } from "../LayerAutosave";
17
- import type { LayerStoreLike } from "../../storage";
17
+ import type { AssetStores, DocumentStoreLike, LayerStoreLike } from "../../storage";
18
+ import RemoteDocumentAutosave, { type RemoteAutosaveOptions } from "../RemoteDocumentAutosave";
19
+ import type { ProfileGraph } from "../../profiles";
18
20
  import type { AssetAuthor, BrushConfig } from "../../brushes/types";
19
- import CustomPresets, { type PresetStoreLike } from "../CustomPresets";
21
+ import CustomPresets from "../CustomPresets";
22
+ import AssetSync from "../AssetSync";
23
+ import ColourPalettes from "../ColourPalettes";
24
+ import type { ColourPalette } from "../../palette";
20
25
  import InputSettings from "../InputSettings";
21
- import UiSettings from "../UiSettings";
26
+ import UiSettings, { type Rendering } from "../UiSettings";
22
27
  import Palette from "../Palette";
23
28
  import ProfileGraphs from "../ProfileGraphs";
24
29
  import ShortcutSettings from "../ShortcutSettings";
30
+ import SettingsExtensions from "../SettingsExtensions";
25
31
  import ExternalSheets from "../ExternalSheets";
26
32
  import { type CanvasMessage, type PatchMessage, type StrokeMessage } from "../../messages";
27
33
  import { type BoundingBox } from "../../image";
28
- import { type PaintCanvasDocument } from "../../document";
34
+ import { type DocumentFile, type DocumentInfo, type DrawingDocument } from "../../document";
29
35
  export { Tool };
30
36
  /** How the colour sample tool samples: the pixel under the pointer, or the average of a dragged rectangle */
31
37
  export type SampleMode = "point" | "area";
@@ -54,8 +60,6 @@ export declare const DEFAULT_BACKGROUND_COLOUR = "#ffffff";
54
60
  * (painted by the eraser and Delete when the layer's alpha lock is on, and by background fills).
55
61
  */
56
62
  export type ColourSlot = "foreground" | "background";
57
- /** Owner of the custom presets when the `ownerId` option isn't given */
58
- export declare const DEFAULT_OWNER_ID = "local";
59
63
  /** Author name of presets made with `newPreset` when the `presetAuthor` option isn't given */
60
64
  export declare const DEFAULT_AUTHOR = "Unknown";
61
65
  /** Names the implementer can change: what users see and what files are called */
@@ -64,12 +68,6 @@ export interface PaintCanvasNames {
64
68
  app: string;
65
69
  /** Start of the names of saved files, e.g. screenshots and exported presets */
66
70
  filePrefix: string;
67
- /** The `format` written in exported brush preset files */
68
- presetFileFormat: string;
69
- /** The `format` written in exported colour palette files */
70
- paletteFileFormat: string;
71
- /** The `format` written in exported settings files */
72
- settingsFileFormat: string;
73
71
  /** Author name of presets made by a user without a handle, e.g. from `presetAuthor` */
74
72
  unknownAuthor: string;
75
73
  }
@@ -93,6 +91,11 @@ export interface CanvasStats {
93
91
  /** Most undo steps kept */
94
92
  historyLimit: number;
95
93
  }
94
+ /** Options for `PaintCanvas.createDocument` */
95
+ export interface CreateDocumentOptions {
96
+ /** Whether to include a thumbnail (default true) */
97
+ thumbnail?: boolean;
98
+ }
96
99
  /** Receives the drawing messages PaintCanvas sends; a returned promise that rejects means a patch wasn't delivered */
97
100
  export type MessageListener = (message: CanvasMessage) => void | Promise<void>;
98
101
  /** Options for sending drawing messages (see `startSending`) */
@@ -116,21 +119,27 @@ export interface PaintCanvasOptions {
116
119
  /** Most layers the user can have (default `DEFAULT_MAX_LAYERS`) */
117
120
  maxLayers?: number;
118
121
  /**
119
- * Creates the canvases the engine draws in: layers, stroke buffers, masks and copies. `createMemoryCanvas` by default,
120
- * keeping pixels in regular memory so saving and copying don't stall phones; pass `createOffscreenCanvas` to keep them
121
- * on the GPU instead (replaceable for tests).
122
+ * Where the canvases draw (`cpu` by default): `cpu` keeps their pixels in regular memory (`createMemoryCanvas`) so
123
+ * saving and copying don't stall phones; `gpu` asks the browser to keep them on the GPU (`createOffscreenCanvas`).
124
+ * Browsers fix this when a canvas is made, so it can't change while the canvas runs: to follow the user's choice
125
+ * (`ui.data.rendering`), pass the one they made last time (`<paint-canvas>` does this with its `settings-store`).
126
+ */
127
+ rendering?: Rendering;
128
+ /**
129
+ * Creates the canvases the engine draws in: layers, stroke buffers, masks and copies. Chosen by `rendering` unless
130
+ * given (replaceable for tests).
122
131
  */
123
132
  createCanvas?: CanvasFactory;
124
- /** Where custom brush presets are kept (defaults to keeping them in memory only) */
125
- presetStore?: PresetStoreLike;
126
- /** Who the custom presets belong to, passed to the preset store (default `DEFAULT_OWNER_ID`) */
127
- ownerId?: string;
133
+ /** Where the user's assets (brush presets, colour palettes, profile graphs) are kept (see `useAssetStores`) */
134
+ stores?: AssetStores;
128
135
  /** Gives the author of presets made with `newPreset` (asked each time, so it can follow name changes) */
129
136
  presetAuthor?: () => AssetAuthor;
130
137
  /** Names to use instead of PaintCanvas's own (see `DEFAULT_NAMES`) */
131
138
  names?: Partial<PaintCanvasNames>;
132
139
  /** Where to keep the user's layers so the drawing survives reloading the page (see `useLayerStore`) */
133
140
  layerStore?: LayerStoreLike;
141
+ /** Where to keep the whole drawing away from the browser, saved less often (see `useRemoteDocumentStore`) */
142
+ remoteDocumentStore?: DocumentStoreLike;
134
143
  /**
135
144
  * The system clipboard, which copying and cutting also put a PNG of the copied image data on so other apps (and brush
136
145
  * shapes) can use it (the browser's by default; `null` for none)
@@ -172,12 +181,26 @@ export default class PaintCanvas extends EventTarget {
172
181
  readonly background: BackgroundWork;
173
182
  /** How the user's input devices control the canvas (scrolling, pinching, touch gestures, focus pen mode) */
174
183
  readonly input: InputSettings;
175
- /** The user's interface choices (theme and language), kept with the other app settings */
184
+ /** The user's interface choices (theme, language and where canvases draw), kept with the other app settings */
176
185
  readonly ui: UiSettings;
177
186
  /** The user's saved colours, shown as swatches */
178
187
  readonly palette: Palette;
179
188
  /** The user's own profile graphs (and the presets), for shaping how brush settings vary */
180
189
  readonly profiles: ProfileGraphs;
190
+ /** The drawing's details (see `documentInfo`) */
191
+ private info;
192
+ /** Keeps the drawing in a remote store */
193
+ private remoteDocumentAutosave?;
194
+ /** Settings wrapper apps add to the app settings (see `SettingsExtension`) */
195
+ readonly settingsExtensions: SettingsExtensions;
196
+ /** The user's own colour palettes (the one PaintCanvas comes with is `palette`) */
197
+ readonly palettes: ColourPalettes;
198
+ /** Where the user's assets are kept */
199
+ private stores;
200
+ /** Keeps the colour palettes in their store */
201
+ private palettesAutosave?;
202
+ /** Keeps the profile graphs in their store */
203
+ private profilesAutosave?;
181
204
  /** The user's keyboard shortcuts: each configurable action's key combination */
182
205
  readonly shortcuts: ShortcutSettings;
183
206
  /** The user's pointer position over the canvas, in canvas pixels (undefined when off the canvas) */
@@ -233,10 +256,11 @@ export default class PaintCanvas extends EventTarget {
233
256
  /** The layer stack whose changes are being sent */
234
257
  private sendingLayers?;
235
258
  private readonly onLayersChangeToSend;
259
+ /** Where the canvases draw, chosen when the canvas started (the user's choice for next time is `ui.data.rendering`) */
260
+ readonly rendering: Rendering;
236
261
  /** Creates the canvases the app draws on (fake ones in tests) */
237
262
  readonly createCanvas: CanvasFactory;
238
263
  /** Who the custom presets belong to (passed to the preset store) */
239
- readonly ownerId: string;
240
264
  /** The largest canvas width or height allowed */
241
265
  readonly maxCanvasSize: number;
242
266
  /** Most layers the user can have */
@@ -308,23 +332,60 @@ export default class PaintCanvas extends EventTarget {
308
332
  * transport.onMessage((from, message) => canvas.receive(from, message));
309
333
  */
310
334
  receive(source: string, message: unknown): Promise<boolean>;
335
+ /** The drawing's details: its ID, name, authors and when it was made and last opened */
336
+ get documentInfo(): Readonly<DocumentInfo>;
337
+ /**
338
+ * Rename the drawing. Returns whether it was renamed (not if the name is empty).
339
+ *
340
+ * @example
341
+ * canvas.renameDocument("Sunset at sea");
342
+ */
343
+ renameDocument(name: string): boolean;
344
+ /**
345
+ * Use details of a drawing being restored (e.g. kept in the browser), marking it opened now.
346
+ */
347
+ restoreDocumentInfo(info: DocumentInfo): void;
348
+ /**
349
+ * Start a new drawing: new details (a new ID, the user as its author, made now), and the layers replaced with one
350
+ * empty layer. Undo history starts again.
351
+ *
352
+ * @example
353
+ * canvas.newDocument("Sketch");
354
+ */
355
+ newDocument(name?: string): void;
356
+ /**
357
+ * The drawing as a document (see `DrawingDocument`): its details, size, the user's layers and drawings from elsewhere
358
+ * as PNG blobs, and a thumbnail (at most `THUMBNAIL_SIZE` pixels on its longest side) unless left out. The user is
359
+ * added to its authors.
360
+ *
361
+ * @example
362
+ * await myStore.save(await canvas.createDocument());
363
+ */
364
+ createDocument({ thumbnail, }?: CreateDocumentOptions): Promise<DrawingDocument>;
365
+ /**
366
+ * Replace the drawing with a document (e.g. from a store): its details (marked opened now), size, layers and drawings
367
+ * from elsewhere. Undo history starts again. Returns whether it was opened: not when it has too many layers, is too
368
+ * big, doesn't have its selected layer, or an image can't be decoded, and then nothing changes.
369
+ *
370
+ * @example
371
+ * await canvas.openDocument(await myStore.load(id));
372
+ */
373
+ openDocument(document: DrawingDocument): Promise<boolean>;
311
374
  /**
312
- * The drawing as a document: its size, the user's layers and drawings from elsewhere, with PNG images (see
313
- * `PaintCanvasDocument`). Turn it into JSON to save it as a file.
375
+ * The drawing as a document file (see `DocumentFile`): turn it into JSON to save it as a file.
314
376
  *
315
377
  * @example
316
378
  * const json = JSON.stringify(await canvas.exportDocument());
317
379
  */
318
- exportDocument(): Promise<PaintCanvasDocument>;
380
+ exportDocument(): Promise<DocumentFile>;
319
381
  /**
320
- * Replace the drawing with a document (e.g. read from a file): its size, layers and drawings from elsewhere. Undo
321
- * history starts again. Returns whether it was loaded: not when the document is invalid or an image can't be
322
- * decoded, and then nothing changes.
382
+ * Replace the drawing with a document file (e.g. read from a file, see `documentFromFile`). Returns whether it was
383
+ * opened: not when it isn't a valid document or can't be opened (see `openDocument`), and then nothing changes.
323
384
  *
324
385
  * @example
325
386
  * await canvas.importDocument(JSON.parse(text));
326
387
  */
327
- importDocument(document: unknown): Promise<boolean>;
388
+ importDocument(file: unknown): Promise<boolean>;
328
389
  /**
329
390
  * Replace the canvas size and the user's layers (top first, each with its image) and select one by ID. Undo history
330
391
  * starts again. Throws if the size or number of layers isn't allowed.
@@ -333,6 +394,32 @@ export default class PaintCanvas extends EventTarget {
333
394
  * canvas.restoreLayers(800, 600, [{ id: "a", name: "Sketch" }], [sketchImage], "a");
334
395
  */
335
396
  restoreLayers(width: number, height: number, layers: readonly LayerConfig[], images: readonly CanvasImageSource[], activeLayer: string): void;
397
+ /** Where the user's assets are kept (see `useAssetStores`) */
398
+ get assetStores(): Readonly<AssetStores>;
399
+ /** Keeps the user's profile graphs in their store, while one is used (see `useAssetStores`) */
400
+ get profileSync(): AssetSync<ProfileGraph> | undefined;
401
+ /** Keeps the user's colour palettes in their store, while one is used (see `useAssetStores`) */
402
+ get paletteSync(): AssetSync<ColourPalette> | undefined;
403
+ /**
404
+ * Keep the user's assets in stores, by kind: custom brush presets are loaded from theirs (in place of the current
405
+ * ones) and saved when they change; colour palettes and profile graphs saved there are added and changes saved (see
406
+ * `AssetSync`). Assets of a kind without a store are kept in memory only.
407
+ *
408
+ * @example
409
+ * canvas.useAssetStores({ brushes: new IndexedDbAssetStore("brushes"), profiles: new IndexedDbAssetStore("profiles") });
410
+ */
411
+ useAssetStores(stores: AssetStores): void;
412
+ /** Keeps the drawing in a remote store, while one is used (see `useRemoteDocumentStore`) */
413
+ get remoteAutosave(): RemoteDocumentAutosave | undefined;
414
+ /**
415
+ * Keep the whole drawing in a remote store (e.g. the user's account online), or stop, without one: changes are saved
416
+ * every few minutes (see `RemoteDocumentAutosave`), or when asked with `canvas.remoteAutosave.save()`. Returns the
417
+ * autosave.
418
+ *
419
+ * @example
420
+ * canvas.useRemoteDocumentStore(myAccountStore, { intervalMs: 10 * 60 * 1000 });
421
+ */
422
+ useRemoteDocumentStore(store: DocumentStoreLike | undefined, options?: RemoteAutosaveOptions): RemoteDocumentAutosave | undefined;
336
423
  /** Keeps the user's layers in a store, while one is used (see `useLayerStore`) */
337
424
  get autosave(): LayerAutosave | undefined;
338
425
  /**
@@ -553,6 +640,13 @@ export default class PaintCanvas extends EventTarget {
553
640
  * own presets are the ones with this handle (see `isOwnAuthor`).
554
641
  */
555
642
  get authorHandle(): string;
643
+ /**
644
+ * The author of assets the user makes, e.g. colour palettes (from the `presetAuthor` option).
645
+ *
646
+ * @example
647
+ * app.palettes.create("Sunset", [], app.author);
648
+ */
649
+ get author(): AssetAuthor;
556
650
  /**
557
651
  * Make a new custom preset from settings: a new ID, the given name, and the author from the `presetAuthor` option.
558
652
  *
@@ -652,5 +746,7 @@ export default class PaintCanvas extends EventTarget {
652
746
  /**
653
747
  * Dispatch a `change` event.
654
748
  */
749
+ /** Use the drawing's details and tell listeners */
750
+ private setDocumentInfo;
655
751
  protected notify(): void;
656
752
  }