@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,10 +1,13 @@
1
- import { PcElement } from "../../base";
1
+ import { nothing } from "lit";
2
+ import { PcPanel } from "../PcPanel";
3
+ import "../PcBrushSize";
2
4
  import type PaintCanvas from "../../../lib/classes/PaintCanvas";
3
5
  import type BrushSettings from "../../../lib/classes/BrushSettings";
4
6
  import type { BrushConfig } from "../../../lib/brushes/types";
7
+ import { DELETE_CURSOR } from "../../../lib/rendering/cursors";
5
8
  import { type SaveMethod } from "../../../lib/rendering/screenshot";
6
- /** Cursor over a preset that a click deletes (Alt/Option held) */
7
- export declare const DELETE_CURSOR: string;
9
+ /** Cursor over a preset that a click deletes (Alt/Option held): the `--pc-delete-cursor` token's default */
10
+ export { DELETE_CURSOR };
8
11
  /** Asks the user to confirm; replaceable for tests */
9
12
  export type ConfirmFn = (message: string) => boolean;
10
13
  /** Largest shape preview in a preset tile, in CSS pixels */
@@ -29,15 +32,15 @@ export declare const previewSizes: (presets: BrushConfig[]) => Map<string, {
29
32
  * tile showing its shape at its size relative to the rest of its family, five to a row. Picking a preset closes the
30
33
  * menu; holding Alt/Option shows an "X" over custom presets, and clicking one asks before deleting it.
31
34
  *
32
- * Dragging the size control up or right makes the brush bigger; down or left makes it smaller.
35
+ * Dragging the size control (`pc-brush-size`) up or right makes the brush bigger; down or left makes it smaller.
33
36
  *
34
37
  * Fires `pc-new-preset` (detail: "brush" or "eraser") for "New preset", and `pc-toast` (detail: the message) after
35
38
  * importing, exporting or deleting presets, or when that fails.
36
39
  *
37
40
  * @example
38
- * html`<pc-brush-menu kind="eraser" .app=${app}></pc-brush-menu>`
41
+ * html`<pc-panel-brushes kind="eraser" .app=${app}></pc-panel-brushes>`
39
42
  */
40
- export declare class PcBrushMenu extends PcElement {
43
+ export declare class PcPanelBrushes extends PcPanel {
41
44
  static properties: {
42
45
  app: {
43
46
  attribute: boolean;
@@ -45,6 +48,16 @@ export declare class PcBrushMenu extends PcElement {
45
48
  kind: {
46
49
  type: StringConstructor;
47
50
  };
51
+ icon: {
52
+ type: StringConstructor;
53
+ };
54
+ label: {
55
+ type: StringConstructor;
56
+ };
57
+ badge: {
58
+ type: BooleanConstructor;
59
+ reflect: boolean;
60
+ };
48
61
  translations: {
49
62
  attribute: boolean;
50
63
  };
@@ -63,8 +76,6 @@ export declare class PcBrushMenu extends PcElement {
63
76
  confirm: ConfirmFn;
64
77
  /** Saves exported presets (replaceable for tests) */
65
78
  saveFile: (blob: Blob, name: string) => Promise<SaveMethod | undefined>;
66
- /** Last pointer position while dragging the size control */
67
- private dragPoint;
68
79
  private changes;
69
80
  private readonly onKey;
70
81
  private readonly onBlur;
@@ -103,19 +114,9 @@ export declare class PcBrushMenu extends PcElement {
103
114
  * Select a preset and close the menu.
104
115
  */
105
116
  selectPreset(id: string): void;
106
- /**
107
- * Start dragging the size control.
108
- */
109
- private onPointerDown;
110
- /**
111
- * Resize while dragging: right and up are positive, left and down are negative.
112
- */
113
- private onPointerMove;
114
- /**
115
- * Stop dragging the size control.
116
- */
117
- private onPointerUp;
118
117
  /** Render a preset's tile */
119
118
  private renderTile;
120
- render(): import("lit").TemplateResult<1>;
119
+ protected get defaultIcon(): string;
120
+ protected get defaultLabel(): string;
121
+ protected renderBody(): import("lit").TemplateResult<1> | typeof nothing;
121
122
  }
@@ -1,16 +1,18 @@
1
1
  import style_default from "./style.js";
2
2
  import { BRUSH_PRESET_FILE_FORMAT } from "../../../lib/presets/schema.js";
3
3
  import { NO_TEXT_SELECTION_CSS, PILLS_CSS, WINDOWS_CSS } from "../../styles/index.js";
4
- import { PcElement, defineElement } from "../../base/index.js";
4
+ import { defineElement } from "../../base/index.js";
5
+ import { PcPanel } from "../PcPanel/index.js";
6
+ import "../PcBrushSize/index.js";
5
7
  import ChangeController from "../../ChangeController/index.js";
6
8
  import { groupPresetsByAuthor } from "../../../lib/brushes/authors/index.js";
7
9
  import "../../../lib/presets/index.js";
8
10
  import { PRESET_FILE_ERRORS, PresetFileError, exportPresetFile, parsePresetFile, presetFileName } from "../../../lib/brushes/presetFile/index.js";
9
- import { svgCursor } from "../../../lib/rendering/cursors/index.js";
11
+ import { DELETE_CURSOR } from "../../../lib/rendering/cursors/index.js";
10
12
  import { JSON_FILE_TYPE, saveFile } from "../../../lib/rendering/screenshot/index.js";
11
13
  import { html, nothing, unsafeCSS } from "lit";
12
14
  import { styleMap } from "lit/directives/style-map.js";
13
- // src/ui/elements/PcBrushMenu/index.ts
15
+ // src/ui/elements/PcPanelBrushes/index.ts
14
16
  /** Translation keys of the preset file error messages */
15
17
  var PRESET_FILE_ERROR_KEYS = {
16
18
  [PRESET_FILE_ERRORS.incompatible]: "paintCanvas.presets.fileIncompatible",
@@ -18,8 +20,6 @@ var PRESET_FILE_ERROR_KEYS = {
18
20
  [PRESET_FILE_ERRORS.export]: "paintCanvas.presets.exportFailed",
19
21
  [PRESET_FILE_ERRORS.empty]: "paintCanvas.presets.nothingToExport"
20
22
  };
21
- /** Cursor over a preset that a click deletes (Alt/Option held) */
22
- var DELETE_CURSOR = svgCursor("M6 6 L18 18 M18 6 L6 18", [12, 12], "not-allowed");
23
23
  /** Size the previews of presets without a family are measured against, so a 50px preset fills its tile */
24
24
  var UNGROUPED_FULL_SIZE = 50;
25
25
  /** Largest shape preview in a preset tile, in CSS pixels */
@@ -56,22 +56,22 @@ var previewSizes = (presets) => {
56
56
  * tile showing its shape at its size relative to the rest of its family, five to a row. Picking a preset closes the
57
57
  * menu; holding Alt/Option shows an "X" over custom presets, and clicking one asks before deleting it.
58
58
  *
59
- * Dragging the size control up or right makes the brush bigger; down or left makes it smaller.
59
+ * Dragging the size control (`pc-brush-size`) up or right makes the brush bigger; down or left makes it smaller.
60
60
  *
61
61
  * Fires `pc-new-preset` (detail: "brush" or "eraser") for "New preset", and `pc-toast` (detail: the message) after
62
62
  * importing, exporting or deleting presets, or when that fails.
63
63
  *
64
64
  * @example
65
- * html`<pc-brush-menu kind="eraser" .app=${app}></pc-brush-menu>`
65
+ * html`<pc-panel-brushes kind="eraser" .app=${app}></pc-panel-brushes>`
66
66
  */
67
- var PcBrushMenu = class extends PcElement {
67
+ var PcPanelBrushes = class extends PcPanel {
68
68
  static properties = {
69
- ...PcElement.properties,
69
+ ...PcPanel.properties,
70
70
  app: { attribute: false },
71
71
  kind: { type: String }
72
72
  };
73
73
  static styles = [
74
- PcElement.styles,
74
+ ...PcPanel.styles,
75
75
  unsafeCSS(NO_TEXT_SELECTION_CSS),
76
76
  unsafeCSS(style_default),
77
77
  unsafeCSS(WINDOWS_CSS),
@@ -80,8 +80,6 @@ var PcBrushMenu = class extends PcElement {
80
80
  confirm = (message) => window.confirm(message);
81
81
  /** Saves exported presets (replaceable for tests) */
82
82
  saveFile = (blob, name) => saveFile(blob, name, void 0, JSON_FILE_TYPE);
83
- /** Last pointer position while dragging the size control */
84
- dragPoint = null;
85
83
  changes = new ChangeController(this, () => [this.app, this.settings]);
86
84
  onKey = (event) => {
87
85
  if (event.key === "Alt") this.toggleAttribute("deleting", event.type === "keydown");
@@ -93,7 +91,6 @@ var PcBrushMenu = class extends PcElement {
93
91
  }
94
92
  connectedCallback() {
95
93
  super.connectedCallback();
96
- this.style.setProperty("--delete-cursor", DELETE_CURSOR);
97
94
  window.addEventListener("keydown", this.onKey);
98
95
  window.addEventListener("keyup", this.onKey);
99
96
  window.addEventListener("blur", this.onBlur);
@@ -217,34 +214,6 @@ var PcBrushMenu = class extends PcElement {
217
214
  this.settings?.select(id);
218
215
  this.app?.closePanel();
219
216
  }
220
- /**
221
- * Start dragging the size control.
222
- */
223
- onPointerDown(event) {
224
- this.dragPoint = {
225
- x: event.clientX,
226
- y: event.clientY
227
- };
228
- event.currentTarget.setPointerCapture(event.pointerId);
229
- }
230
- /**
231
- * Resize while dragging: right and up are positive, left and down are negative.
232
- */
233
- onPointerMove(event) {
234
- if (!this.dragPoint || !this.settings) return;
235
- const delta = event.clientX - this.dragPoint.x + (this.dragPoint.y - event.clientY);
236
- this.dragPoint = {
237
- x: event.clientX,
238
- y: event.clientY
239
- };
240
- if (delta !== 0) this.settings.resize(delta);
241
- }
242
- /**
243
- * Stop dragging the size control.
244
- */
245
- onPointerUp() {
246
- this.dragPoint = null;
247
- }
248
217
  /** Render a preset's tile */
249
218
  renderTile(settings, preset, sizes) {
250
219
  const size = sizes.get(preset.id);
@@ -271,9 +240,15 @@ var PcBrushMenu = class extends PcElement {
271
240
  </button>
272
241
  </li>`;
273
242
  }
274
- render() {
243
+ get defaultIcon() {
244
+ return this.kind === "eraser" ? "eraser" : "brush";
245
+ }
246
+ get defaultLabel() {
247
+ return this.t(this.kind === "eraser" ? "paintCanvas.tool.eraser" : "paintCanvas.tool.brush");
248
+ }
249
+ renderBody() {
275
250
  const settings = this.settings;
276
- if (!settings) return html``;
251
+ if (!settings) return nothing;
277
252
  const title = this.t(this.kind === "eraser" ? "paintCanvas.tool.eraser" : "paintCanvas.tool.brush");
278
253
  const presets = Object.values(settings.presets);
279
254
  const sizes = previewSizes(presets);
@@ -292,19 +267,11 @@ var PcBrushMenu = class extends PcElement {
292
267
  style=${styleMap({ maskImage: typeof preset.image === "string" ? `url("${preset.image}")` : void 0 })}
293
268
  ></span>
294
269
  <span class="name">${preset.name ?? preset.id}</span>
295
- <div
270
+ <pc-brush-size
296
271
  class="size"
297
- role="slider"
298
- aria-label=${this.t("paintCanvas.brushMenu.size", { tool: title })}
299
- aria-valuenow=${settings.width}
300
- title=${this.t("paintCanvas.brushMenu.dragToResize")}
301
- @pointerdown=${this.onPointerDown}
302
- @pointermove=${this.onPointerMove}
303
- @pointerup=${this.onPointerUp}
304
- @pointercancel=${this.onPointerUp}
305
- >
306
- ${settings.width === settings.height ? settings.width : `${settings.width} × ${settings.height}`}
307
- </div>
272
+ .settings=${settings}
273
+ label=${this.t("paintCanvas.brushMenu.size", { tool: title })}
274
+ ></pc-brush-size>
308
275
  </div>
309
276
  <div
310
277
  class="presets"
@@ -359,5 +326,5 @@ var PcBrushMenu = class extends PcElement {
359
326
  `;
360
327
  }
361
328
  };
362
- defineElement("pc-brush-menu", PcBrushMenu);
363
- export { DELETE_CURSOR, MAX_PREVIEW_SIZE, MIN_PREVIEW_SIZE, PcBrushMenu, previewSizes };
329
+ defineElement("pc-panel-brushes", PcPanelBrushes);
330
+ export { DELETE_CURSOR, MAX_PREVIEW_SIZE, MIN_PREVIEW_SIZE, PcPanelBrushes, previewSizes };
@@ -0,0 +1,3 @@
1
+ // src/ui/elements/PcPanelBrushes/style.css?inline
2
+ var style_default = "/* Narrower than other panels by default (set --pc-panel-width to change it) */\n:host {\n --pc-panel-default-width: 240px;\n}\n/* The current preset on one row: its shape, name and size */\n.current {\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 44px;\n padding: 4px 8px;\n border: 1px solid var(--pc-border);\n background: var(--pc-surface);\n}\n.current-shape {\n flex: none;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: var(--pc-text);\n}\n.current-shape.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: contain;\n mask-position: center;\n}\n.name {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.size {\n flex: none;\n align-self: stretch;\n margin: -4px -8px -4px 0;\n border-left: 1px solid var(--pc-border);\n}\n/* The presets scroll, at most 400px tall, or less so the whole menu fits under the settings bar in a shorter window */\n.presets {\n flex: 1 1 auto;\n min-height: 0;\n max-height: min(400px, calc(100vh - 180px));\n overflow-y: auto;\n}\nh3 {\n margin: 4px 0;\n font-size: 14px;\n}\nul {\n display: grid;\n grid-template-columns: repeat(5, 1fr);\n align-content: start;\n margin: 0;\n padding: 0;\n list-style: none;\n border: 1px solid var(--pc-border);\n background: var(--pc-bar);\n}\n:host([deleting]) li button.custom {\n cursor: var(--pc-delete-cursor);\n}\n/* Create, Import and Export side by side */\n.actions {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 6px;\n}\n.actions button.pill {\n padding: 4px 8px;\n}\n.visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\nli button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n aspect-ratio: 1;\n padding: 0;\n border: none;\n border-right: 1px solid var(--pc-border);\n border-bottom: 1px solid var(--pc-border);\n background: var(--pc-bar);\n cursor: pointer;\n}\nli button:hover {\n background: var(--pc-surface-hover);\n}\nli button[aria-pressed=\"true\"] {\n background: var(--pc-surface-active);\n}\n.shape {\n background: var(--pc-text);\n border-radius: 50%;\n}\n.shape.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: 100% 100%;\n}\n";
3
+ export { style_default as default };
@@ -0,0 +1,171 @@
1
+ import { nothing, type PropertyValues } from "lit";
2
+ import { PcPanel } from "../PcPanel";
3
+ import "../PcColourPair";
4
+ import "../PcMenu";
5
+ import "../PcDialog";
6
+ import type { default as PaintCanvas } from "../../../lib/classes/PaintCanvas";
7
+ import { type Hsl, type Rgb } from "../../../lib/utils/colour";
8
+ import { type SaveMethod } from "../../../lib/rendering/screenshot";
9
+ /** The colour models the sliders can show */
10
+ export type ColourModel = "rgb" | "hsl";
11
+ /**
12
+ * The CSS gradient a channel's slider track shows: the colours its values give, from the lowest to the highest, keeping
13
+ * the colour's other values. Red, green and blue go from none to all of that channel (e.g. red from `rgb(0, g, b)` to
14
+ * `rgb(255, g, b)`), saturation from grey to full colour, and lightness from black through the colour to white. Hue goes
15
+ * through every hue at full saturation, so it never shows as grey.
16
+ *
17
+ * @example
18
+ * channelGradient("r", { r: 0, g: 128, b: 255 }, { h: 210, s: 100, l: 50 }); // "linear-gradient(to right, #0080ff, #ff80ff)"
19
+ * channelGradient("s", { r: 77, g: 179, b: 77 }, { h: 120, s: 40, l: 50 }); // "linear-gradient(to right, #808080, #00ff00)"
20
+ */
21
+ export declare const channelGradient: (key: string, rgb: Rgb, hsl: Hsl) => string;
22
+ /** How long a touch is held on a saved colour to open its menu (milliseconds) */
23
+ export declare const LONG_PRESS_MS = 500;
24
+ /**
25
+ * The colour palette menu: the foreground and background colours (the selected one is configured), its hex value, RGB
26
+ * and HSL sliders, the saved colours, and buttons to import and export them as a JSON file.
27
+ *
28
+ * - Pressing the foreground or background colour selects it.
29
+ * - Pressing a saved colour sets the selected colour; [+] saves the selected colour.
30
+ * - A saved colour is deleted, after asking, by clicking it with Alt/Option held (the cursor shows an "X"), from its
31
+ * menu (right-click, a long press on touch screens, or the context menu key), or with Delete or Backspace. Arrow keys,
32
+ * Home and End move between saved colours.
33
+ * - Escape closes it (closes the canvas's open panel).
34
+ *
35
+ * Fires `pc-toast` after importing, or when importing or exporting fails.
36
+ *
37
+ * @example
38
+ * html`<pc-panel-colours .app=${app}></pc-panel-colours>`
39
+ */
40
+ export declare class PcPanelColours extends PcPanel {
41
+ static properties: {
42
+ app: {
43
+ attribute: boolean;
44
+ };
45
+ model: {
46
+ type: StringConstructor;
47
+ };
48
+ hexDraft: {
49
+ state: boolean;
50
+ };
51
+ menu: {
52
+ state: boolean;
53
+ };
54
+ confirming: {
55
+ state: boolean;
56
+ };
57
+ icon: {
58
+ type: StringConstructor;
59
+ };
60
+ label: {
61
+ type: StringConstructor;
62
+ };
63
+ badge: {
64
+ type: BooleanConstructor;
65
+ reflect: boolean;
66
+ };
67
+ translations: {
68
+ attribute: boolean;
69
+ };
70
+ icons: {
71
+ attribute: boolean;
72
+ };
73
+ theme: {
74
+ type: StringConstructor;
75
+ reflect: boolean;
76
+ };
77
+ };
78
+ static styles: import("lit").CSSResultGroup[];
79
+ app?: PaintCanvas;
80
+ /** The colour model the sliders show */
81
+ model: ColourModel;
82
+ /** The hex value being typed, while it differs from the colour */
83
+ hexDraft?: string;
84
+ /** The saved colour whose menu is open, and where */
85
+ menu?: {
86
+ index: number;
87
+ x: number;
88
+ y: number;
89
+ };
90
+ /** The saved colour being deleted, while asking */
91
+ confirming?: number;
92
+ /** Saves exported files (replaceable for tests) */
93
+ saveFile: (blob: Blob, name: string) => Promise<SaveMethod | undefined>;
94
+ /** The HSL values shown, kept while they give the selected colour (so hue stays put for greys) */
95
+ private hsl;
96
+ /** The saved colour that is reached with Tab (the others with arrow keys) */
97
+ private focusIndex;
98
+ /** A touch being held on a saved colour, until it opens its menu */
99
+ private press?;
100
+ /** Whether a long press opened a menu, so the click that follows is ignored */
101
+ private longPressed;
102
+ private changes;
103
+ private readonly onKey;
104
+ private readonly onBlur;
105
+ constructor();
106
+ connectedCallback(): void;
107
+ disconnectedCallback(): void;
108
+ /** The selected colour's value, e.g. `#000000` */
109
+ get colour(): string;
110
+ protected willUpdate(changed: PropertyValues<this>): void;
111
+ /** Set the selected colour */
112
+ private setColour;
113
+ /** Select the pressed colour */
114
+ private onColourClick;
115
+ /** Follow the hex value as it's typed, setting the colour once it's a full 6-digit value */
116
+ private onHexInput;
117
+ /** Set the colour from a typed hex value (including 3 digits) when done, or show the colour again if it isn't one */
118
+ private onHexChange;
119
+ /** Switch colour model with the arrow keys, Home and End, as tabs do */
120
+ private onTabKeyDown;
121
+ /** Show a colour model's sliders */
122
+ private selectModel;
123
+ /** Change one channel of the colour model shown */
124
+ private onChannel;
125
+ /** Set the selected colour from a saved colour, or ask to delete it with Alt/Option held */
126
+ private onSwatchClick;
127
+ /** Open a saved colour's menu where it was right-clicked */
128
+ private onSwatchContextMenu;
129
+ /** Start waiting for a touch held on a saved colour to open its menu */
130
+ private onSwatchPointerDown;
131
+ /** Stop waiting for a long press when the touch moves away */
132
+ private onSwatchPointerMove;
133
+ /** Stop waiting for a long press */
134
+ private cancelPress;
135
+ /**
136
+ * Move between saved colours, ask to delete one, or open its menu, with the keyboard. Keys used here don't reach the
137
+ * keyboard shortcuts (e.g. Delete doesn't also delete the masked image data).
138
+ */
139
+ private onSwatchKeyDown;
140
+ /** How many saved colours fit in a row */
141
+ private columns;
142
+ /** Focus a saved colour */
143
+ private focusSwatch;
144
+ /** Save the selected colour */
145
+ private onAdd;
146
+ /** Delete the saved colour that was asked about, if confirmed */
147
+ private onConfirm;
148
+ /** Close the palette with Escape (unless a dialog or menu is open, which closes first) */
149
+ private onKeyDown;
150
+ /**
151
+ * Import the colours in a colour palette file, adding them after the saved ones (leaving out ones already saved).
152
+ */
153
+ importFile(file: File): Promise<void>;
154
+ /**
155
+ * Export the saved colours as a colour palette file.
156
+ */
157
+ exportFile(): Promise<void>;
158
+ /** Show a palette file error (one of `PALETTE_FILE_ERRORS`) in the chosen language */
159
+ private toastError;
160
+ /** The colour model tabs and the selected model's sliders */
161
+ private renderChannels;
162
+ /** The saved colours and the [+] button */
163
+ private renderSwatches;
164
+ /** The saved colour's menu, while open */
165
+ private renderMenu;
166
+ /** The dialog asking before deleting a saved colour, while asking */
167
+ private renderConfirmation;
168
+ protected get defaultIcon(): string;
169
+ protected get defaultLabel(): string;
170
+ protected renderBody(): import("lit").TemplateResult<1> | typeof nothing;
171
+ }