@lvl99dotcom/paintcanvas 0.0.0-stage → 0.3.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 (284) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +131 -2
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +5 -0
  5. package/dist/lib/brushes/BrushTipCache/index.d.ts +32 -0
  6. package/dist/lib/brushes/BrushTipCache/index.js +60 -0
  7. package/dist/lib/brushes/StrokeEngine/index.d.ts +171 -0
  8. package/dist/lib/brushes/StrokeEngine/index.js +324 -0
  9. package/dist/lib/brushes/StrokePath/index.d.ts +53 -0
  10. package/dist/lib/brushes/StrokePath/index.js +161 -0
  11. package/dist/lib/brushes/StrokeSampler/index.d.ts +55 -0
  12. package/dist/lib/brushes/StrokeSampler/index.js +75 -0
  13. package/dist/lib/brushes/authors/index.d.ts +55 -0
  14. package/dist/lib/brushes/authors/index.js +60 -0
  15. package/dist/lib/brushes/configRanges/index.d.ts +52 -0
  16. package/dist/lib/brushes/configRanges/index.js +206 -0
  17. package/dist/lib/brushes/index.d.ts +5 -0
  18. package/dist/lib/brushes/index.js +19 -0
  19. package/dist/lib/brushes/params/index.d.ts +108 -0
  20. package/dist/lib/brushes/params/index.js +139 -0
  21. package/dist/lib/brushes/presetFile/index.d.ts +32 -0
  22. package/dist/lib/brushes/presetFile/index.js +55 -0
  23. package/dist/lib/brushes/presets/drawing/brush-pen.js +3 -0
  24. package/dist/lib/brushes/presets/drawing/felt-pen.js +3 -0
  25. package/dist/lib/brushes/presets/drawing/index.d.ts +13 -0
  26. package/dist/lib/brushes/presets/drawing/index.js +88 -0
  27. package/dist/lib/brushes/presets/drawing/pencil-2b.js +3 -0
  28. package/dist/lib/brushes/presets/drawing/pencil-hb.js +3 -0
  29. package/dist/lib/brushes/presets/painting/grass.js +3 -0
  30. package/dist/lib/brushes/presets/painting/hair.js +3 -0
  31. package/dist/lib/brushes/presets/painting/index.d.ts +18 -0
  32. package/dist/lib/brushes/presets/painting/index.js +118 -0
  33. package/dist/lib/brushes/presets/painting/splatter.js +3 -0
  34. package/dist/lib/brushes/presets/painting/textured-paint.js +3 -0
  35. package/dist/lib/brushes/presets/painting/watery-paint.js +3 -0
  36. package/dist/lib/brushes/presets/round/index.d.ts +9 -0
  37. package/dist/lib/brushes/presets/round/index.js +44 -0
  38. package/dist/lib/brushes/presets/round/round.js +3 -0
  39. package/dist/lib/brushes/presets/round/soft-round.js +3 -0
  40. package/dist/lib/brushes/presets/sized/index.d.ts +20 -0
  41. package/dist/lib/brushes/presets/sized/index.js +30 -0
  42. package/dist/lib/brushes/presets/sketching/index.d.ts +14 -0
  43. package/dist/lib/brushes/presets/sketching/index.js +107 -0
  44. package/dist/lib/brushes/presets/square/index.d.ts +7 -0
  45. package/dist/lib/brushes/presets/square/index.js +22 -0
  46. package/dist/lib/brushes/presets/square/square.js +3 -0
  47. package/dist/lib/brushes/shapeImage/index.d.ts +40 -0
  48. package/dist/lib/brushes/shapeImage/index.js +61 -0
  49. package/dist/lib/brushes/types/index.d.ts +243 -0
  50. package/dist/lib/brushes/types/index.js +20 -0
  51. package/dist/lib/classes/BackgroundWork/index.d.ts +55 -0
  52. package/dist/lib/classes/BackgroundWork/index.js +97 -0
  53. package/dist/lib/classes/BrushSettings/index.d.ts +91 -0
  54. package/dist/lib/classes/BrushSettings/index.js +152 -0
  55. package/dist/lib/classes/CustomPresets/index.d.ts +53 -0
  56. package/dist/lib/classes/CustomPresets/index.js +71 -0
  57. package/dist/lib/classes/ExternalSheets/index.d.ts +64 -0
  58. package/dist/lib/classes/ExternalSheets/index.js +112 -0
  59. package/dist/lib/classes/GestureTracker/index.d.ts +62 -0
  60. package/dist/lib/classes/GestureTracker/index.js +122 -0
  61. package/dist/lib/classes/History/index.d.ts +83 -0
  62. package/dist/lib/classes/History/index.js +126 -0
  63. package/dist/lib/classes/HistoryGuard/index.d.ts +58 -0
  64. package/dist/lib/classes/HistoryGuard/index.js +97 -0
  65. package/dist/lib/classes/InputSettings/index.d.ts +74 -0
  66. package/dist/lib/classes/InputSettings/index.js +101 -0
  67. package/dist/lib/classes/KeyboardShortcuts/index.d.ts +48 -0
  68. package/dist/lib/classes/KeyboardShortcuts/index.js +137 -0
  69. package/dist/lib/classes/Layer/index.d.ts +86 -0
  70. package/dist/lib/classes/Layer/index.js +111 -0
  71. package/dist/lib/classes/LayerAutosave/index.d.ts +180 -0
  72. package/dist/lib/classes/LayerAutosave/index.js +346 -0
  73. package/dist/lib/classes/LayerStack/index.d.ts +177 -0
  74. package/dist/lib/classes/LayerStack/index.js +394 -0
  75. package/dist/lib/classes/PaintCanvas/index.d.ts +537 -0
  76. package/dist/lib/classes/PaintCanvas/index.js +965 -0
  77. package/dist/lib/classes/StrokeLog/index.d.ts +149 -0
  78. package/dist/lib/classes/StrokeLog/index.js +257 -0
  79. package/dist/lib/classes/Viewport/index.d.ts +108 -0
  80. package/dist/lib/classes/Viewport/index.js +194 -0
  81. package/dist/lib/document/index.d.ts +17 -0
  82. package/dist/lib/document/index.js +25 -0
  83. package/dist/lib/document/schema.d.ts +132 -0
  84. package/dist/lib/document/schema.js +110 -0
  85. package/dist/lib/i18n/index.d.ts +131 -0
  86. package/dist/lib/i18n/index.js +277 -0
  87. package/dist/lib/image/index.d.ts +90 -0
  88. package/dist/lib/image/index.js +147 -0
  89. package/dist/lib/messages/PatchSender/index.d.ts +75 -0
  90. package/dist/lib/messages/PatchSender/index.js +125 -0
  91. package/dist/lib/messages/index.d.ts +26 -0
  92. package/dist/lib/messages/index.js +59 -0
  93. package/dist/lib/messages/schema.d.ts +1775 -0
  94. package/dist/lib/messages/schema.js +192 -0
  95. package/dist/lib/presets/index.d.ts +32 -0
  96. package/dist/lib/presets/index.js +35 -0
  97. package/dist/lib/presets/schema.d.ts +753 -0
  98. package/dist/lib/presets/schema.js +181 -0
  99. package/dist/lib/rendering/BrushTip/index.d.ts +63 -0
  100. package/dist/lib/rendering/BrushTip/index.js +112 -0
  101. package/dist/lib/rendering/checkerboard/index.d.ts +22 -0
  102. package/dist/lib/rendering/checkerboard/index.js +31 -0
  103. package/dist/lib/rendering/compositing/index.d.ts +64 -0
  104. package/dist/lib/rendering/compositing/index.js +124 -0
  105. package/dist/lib/rendering/cursor/index.d.ts +14 -0
  106. package/dist/lib/rendering/cursor/index.js +39 -0
  107. package/dist/lib/rendering/cursors/index.d.ts +18 -0
  108. package/dist/lib/rendering/cursors/index.js +23 -0
  109. package/dist/lib/rendering/maskOutline/index.d.ts +22 -0
  110. package/dist/lib/rendering/maskOutline/index.js +78 -0
  111. package/dist/lib/rendering/outline/index.d.ts +36 -0
  112. package/dist/lib/rendering/outline/index.js +120 -0
  113. package/dist/lib/rendering/sample/index.d.ts +55 -0
  114. package/dist/lib/rendering/sample/index.js +83 -0
  115. package/dist/lib/rendering/screenshot/index.d.ts +67 -0
  116. package/dist/lib/rendering/screenshot/index.js +96 -0
  117. package/dist/lib/rendering/transformBox/index.d.ts +10 -0
  118. package/dist/lib/rendering/transformBox/index.js +57 -0
  119. package/dist/lib/selection/Lasso/index.d.ts +70 -0
  120. package/dist/lib/selection/Lasso/index.js +156 -0
  121. package/dist/lib/selection/Selection/index.d.ts +86 -0
  122. package/dist/lib/selection/Selection/index.js +228 -0
  123. package/dist/lib/selection/geometry/index.d.ts +37 -0
  124. package/dist/lib/selection/geometry/index.js +57 -0
  125. package/dist/lib/storage/index.d.ts +63 -0
  126. package/dist/lib/storage/index.js +114 -0
  127. package/dist/lib/transform/Transformer/index.d.ts +124 -0
  128. package/dist/lib/transform/Transformer/index.js +286 -0
  129. package/dist/lib/transform/geometry/index.d.ts +95 -0
  130. package/dist/lib/transform/geometry/index.js +258 -0
  131. package/dist/lib/utils/array/index.d.ts +10 -0
  132. package/dist/lib/utils/array/index.js +21 -0
  133. package/dist/lib/utils/gestures/index.d.ts +35 -0
  134. package/dist/lib/utils/gestures/index.js +81 -0
  135. package/dist/lib/utils/navigation/index.d.ts +51 -0
  136. package/dist/lib/utils/navigation/index.js +59 -0
  137. package/dist/lib/utils/random/index.d.ts +18 -0
  138. package/dist/lib/utils/random/index.js +27 -0
  139. package/dist/lib/utils/shortcuts/index.d.ts +74 -0
  140. package/dist/lib/utils/shortcuts/index.js +189 -0
  141. package/dist/lib/validation/validators.generated.d.ts +27 -0
  142. package/dist/lib/validation/validators.generated.js +19826 -0
  143. package/dist/locales/en-GB.js +181 -0
  144. package/dist/locales/en-US.js +181 -0
  145. package/dist/locales/fr.js +181 -0
  146. package/dist/locales/ja.js +181 -0
  147. package/dist/locales/ko.js +181 -0
  148. package/dist/locales/zh-Hans.js +181 -0
  149. package/dist/locales/zh-Hant.js +181 -0
  150. package/dist/package.js +3 -0
  151. package/dist/testing/app.d.ts +7 -0
  152. package/dist/testing/app.js +16 -0
  153. package/dist/testing/elements.d.ts +42 -0
  154. package/dist/testing/elements.js +58 -0
  155. package/dist/testing/fakeCanvas.d.ts +21 -0
  156. package/dist/testing/fakeCanvas.js +26 -0
  157. package/dist/testing/layerStore.d.ts +26 -0
  158. package/dist/testing/layerStore.js +43 -0
  159. package/dist/testing/locks.d.ts +15 -0
  160. package/dist/testing/locks.js +41 -0
  161. package/dist/testing/recordingCanvas.d.ts +14 -0
  162. package/dist/testing/recordingCanvas.js +28 -0
  163. package/dist/testing/recordingContext.d.ts +10 -0
  164. package/dist/testing/recordingContext.js +19 -0
  165. package/dist/ui/ChangeController/index.d.ts +40 -0
  166. package/dist/ui/ChangeController/index.js +62 -0
  167. package/dist/ui/base/index.d.ts +69 -0
  168. package/dist/ui/base/index.js +94 -0
  169. package/dist/ui/elements/PaintCanvas/index.d.ts +249 -0
  170. package/dist/ui/elements/PaintCanvas/index.js +584 -0
  171. package/dist/ui/elements/PaintCanvas/style.js +3 -0
  172. package/dist/ui/elements/PcBrushConfig/index.d.ts +130 -0
  173. package/dist/ui/elements/PcBrushConfig/index.js +465 -0
  174. package/dist/ui/elements/PcBrushConfig/style.js +3 -0
  175. package/dist/ui/elements/PcBrushMenu/index.d.ts +121 -0
  176. package/dist/ui/elements/PcBrushMenu/index.js +362 -0
  177. package/dist/ui/elements/PcBrushMenu/style.js +3 -0
  178. package/dist/ui/elements/PcBrushTest/index.d.ts +71 -0
  179. package/dist/ui/elements/PcBrushTest/index.js +136 -0
  180. package/dist/ui/elements/PcBrushTest/style.js +3 -0
  181. package/dist/ui/elements/PcButton/index.d.ts +57 -0
  182. package/dist/ui/elements/PcButton/index.js +124 -0
  183. package/dist/ui/elements/PcButtonGroup/index.d.ts +44 -0
  184. package/dist/ui/elements/PcButtonGroup/index.js +93 -0
  185. package/dist/ui/elements/PcCanvas/index.d.ts +356 -0
  186. package/dist/ui/elements/PcCanvas/index.js +1004 -0
  187. package/dist/ui/elements/PcCanvas/style.js +3 -0
  188. package/dist/ui/elements/PcCanvasMap/index.d.ts +96 -0
  189. package/dist/ui/elements/PcCanvasMap/index.js +187 -0
  190. package/dist/ui/elements/PcCanvasMap/style.js +3 -0
  191. package/dist/ui/elements/PcContextMenu/index.d.ts +72 -0
  192. package/dist/ui/elements/PcContextMenu/index.js +148 -0
  193. package/dist/ui/elements/PcDialog/index.d.ts +63 -0
  194. package/dist/ui/elements/PcDialog/index.js +114 -0
  195. package/dist/ui/elements/PcIcon/index.d.ts +36 -0
  196. package/dist/ui/elements/PcIcon/index.js +43 -0
  197. package/dist/ui/elements/PcIconToggle/index.d.ts +46 -0
  198. package/dist/ui/elements/PcIconToggle/index.js +87 -0
  199. package/dist/ui/elements/PcInfoTip/index.d.ts +40 -0
  200. package/dist/ui/elements/PcInfoTip/index.js +95 -0
  201. package/dist/ui/elements/PcInputSettings/index.d.ts +69 -0
  202. package/dist/ui/elements/PcInputSettings/index.js +154 -0
  203. package/dist/ui/elements/PcLayerItem/index.d.ts +221 -0
  204. package/dist/ui/elements/PcLayerItem/index.js +561 -0
  205. package/dist/ui/elements/PcLayerItem/style.js +3 -0
  206. package/dist/ui/elements/PcLayersMenu/index.d.ts +108 -0
  207. package/dist/ui/elements/PcLayersMenu/index.js +208 -0
  208. package/dist/ui/elements/PcLayersMenu/style.js +3 -0
  209. package/dist/ui/elements/PcMatch/index.d.ts +31 -0
  210. package/dist/ui/elements/PcMatch/index.js +58 -0
  211. package/dist/ui/elements/PcPanel/index.d.ts +43 -0
  212. package/dist/ui/elements/PcPanel/index.js +51 -0
  213. package/dist/ui/elements/PcPopover/index.d.ts +48 -0
  214. package/dist/ui/elements/PcPopover/index.js +86 -0
  215. package/dist/ui/elements/PcSlider/index.d.ts +57 -0
  216. package/dist/ui/elements/PcSlider/index.js +88 -0
  217. package/dist/ui/elements/PcStats/index.d.ts +54 -0
  218. package/dist/ui/elements/PcStats/index.js +144 -0
  219. package/dist/ui/elements/PcThemePicker/index.d.ts +56 -0
  220. package/dist/ui/elements/PcThemePicker/index.js +134 -0
  221. package/dist/ui/elements/PcToast/index.d.ts +58 -0
  222. package/dist/ui/elements/PcToast/index.js +110 -0
  223. package/dist/ui/elements/PcToggleCheckbox/index.d.ts +37 -0
  224. package/dist/ui/elements/PcToggleCheckbox/index.js +105 -0
  225. package/dist/ui/elements/PcToolSettings/index.d.ts +128 -0
  226. package/dist/ui/elements/PcToolSettings/index.js +549 -0
  227. package/dist/ui/elements/PcToolSettings/style.js +3 -0
  228. package/dist/ui/elements/PcToolbar/index.d.ts +71 -0
  229. package/dist/ui/elements/PcToolbar/index.js +190 -0
  230. package/dist/ui/elements/PcToolbar/style.js +3 -0
  231. package/dist/ui/icons/images/brush.js +3 -0
  232. package/dist/ui/icons/images/circle-mask.js +3 -0
  233. package/dist/ui/icons/images/clipboard.js +3 -0
  234. package/dist/ui/icons/images/cursor.js +3 -0
  235. package/dist/ui/icons/images/eraser.js +3 -0
  236. package/dist/ui/icons/images/eyedropper.js +3 -0
  237. package/dist/ui/icons/images/flip-horizontal.js +3 -0
  238. package/dist/ui/icons/images/flip-vertical.js +3 -0
  239. package/dist/ui/icons/images/focus-pen.js +3 -0
  240. package/dist/ui/icons/images/freehand-mask.js +3 -0
  241. package/dist/ui/icons/images/hidden.js +3 -0
  242. package/dist/ui/icons/images/layers.js +3 -0
  243. package/dist/ui/icons/images/linked.js +3 -0
  244. package/dist/ui/icons/images/locked.js +3 -0
  245. package/dist/ui/icons/images/moon.js +3 -0
  246. package/dist/ui/icons/images/pan.js +3 -0
  247. package/dist/ui/icons/images/polygon-mask.js +3 -0
  248. package/dist/ui/icons/images/pressure.js +3 -0
  249. package/dist/ui/icons/images/randomise.js +3 -0
  250. package/dist/ui/icons/images/rectangle-mask.js +3 -0
  251. package/dist/ui/icons/images/redo.js +3 -0
  252. package/dist/ui/icons/images/rotate-90-left.js +3 -0
  253. package/dist/ui/icons/images/rotate-90-right.js +3 -0
  254. package/dist/ui/icons/images/smoothing-bezier-cubic.js +3 -0
  255. package/dist/ui/icons/images/smoothing-bezier-quad.js +3 -0
  256. package/dist/ui/icons/images/smoothing-linear.js +3 -0
  257. package/dist/ui/icons/images/star.js +3 -0
  258. package/dist/ui/icons/images/sun.js +3 -0
  259. package/dist/ui/icons/images/tilt.js +3 -0
  260. package/dist/ui/icons/images/undo.js +3 -0
  261. package/dist/ui/icons/images/unlinked.js +3 -0
  262. package/dist/ui/icons/images/unlocked.js +3 -0
  263. package/dist/ui/icons/images/visible.js +3 -0
  264. package/dist/ui/icons/images/zoom-in.js +3 -0
  265. package/dist/ui/icons/images/zoom-out.js +3 -0
  266. package/dist/ui/icons/images/zoom.js +3 -0
  267. package/dist/ui/icons/index.d.ts +42 -0
  268. package/dist/ui/icons/index.js +130 -0
  269. package/dist/ui/index.d.ts +21 -0
  270. package/dist/ui/index.js +22 -0
  271. package/dist/ui/layout/index.d.ts +88 -0
  272. package/dist/ui/layout/index.js +96 -0
  273. package/dist/ui/styles/index.d.ts +13 -0
  274. package/dist/ui/styles/index.js +195 -0
  275. package/dist/ui/tokens/index.d.ts +29 -0
  276. package/dist/ui/tokens/index.js +114 -0
  277. package/locales/en-GB.json +179 -0
  278. package/locales/en-US.json +179 -0
  279. package/locales/fr.json +179 -0
  280. package/locales/ja.json +179 -0
  281. package/locales/ko.json +179 -0
  282. package/locales/zh-Hans.json +179 -0
  283. package/locales/zh-Hant.json +179 -0
  284. package/package.json +97 -3
@@ -0,0 +1,96 @@
1
+ // src/ui/layout/index.ts
2
+ /** All side modes */
3
+ var SIDE_MODES = [
4
+ "docked",
5
+ "rail",
6
+ "floating"
7
+ ];
8
+ /** Side modes used unless the implementer chooses others: docked, and a rail below 600px wide */
9
+ var DEFAULT_SIDE_MODES = "docked, rail@600";
10
+ /** Layout width (CSS pixels) below which the layout counts as narrow, unless the implementer chooses another */
11
+ var DEFAULT_NARROW_WIDTH = 600;
12
+ /**
13
+ * Read a side's modes, e.g. `"docked, rail@600, floating@400"`: docked, a rail below 600px wide, and floating below
14
+ * 400px. Unknown modes and widths that aren't numbers are left out.
15
+ *
16
+ * @example
17
+ * parseSideModes("docked, rail@600"); // [{ mode: "docked" }, { mode: "rail", below: 600 }]
18
+ */
19
+ var parseSideModes = (text) => text.split(",").map((part) => part.trim().split("@")).filter(([mode, below]) => SIDE_MODES.includes(mode) && (below === void 0 || Number.isFinite(Number(below)))).map(([mode, below]) => below === void 0 ? { mode } : {
20
+ mode,
21
+ below: Number(below)
22
+ });
23
+ /**
24
+ * The side mode for a layout width: the rule with the smallest width the layout is below, otherwise the rule without
25
+ * a width (docked if there's none).
26
+ *
27
+ * @example
28
+ * sideModeFor(parseSideModes("docked, rail@600, floating@400"), 500); // "rail"
29
+ */
30
+ var sideModeFor = (rules, width) => {
31
+ let chosen = rules.find((rule) => rule.below === void 0)?.mode ?? "docked";
32
+ let limit = Infinity;
33
+ for (const rule of rules) if (rule.below !== void 0 && width < rule.below && rule.below < limit) {
34
+ chosen = rule.mode;
35
+ limit = rule.below;
36
+ }
37
+ return chosen;
38
+ };
39
+ /** Event the layout dispatches when its state changes (detail: `LayoutState`) */
40
+ var STATE_EVENT = "pc-state-change";
41
+ /**
42
+ * Whether a layout state meets a condition: space-separated terms that must all hold, each `narrow`, `ui-hidden`,
43
+ * `input:pen`, `input:touch`, `input:mouse`, `left:<mode>` or `right:<mode>`, optionally negated with `!`.
44
+ *
45
+ * @example
46
+ * matchesState("narrow !input:pen", state);
47
+ */
48
+ var matchesState = (condition, state) => condition.split(/\s+/).filter(Boolean).every((term) => {
49
+ const negated = term.startsWith("!");
50
+ const [name, value] = (negated ? term.slice(1) : term).split(":");
51
+ return (name === "narrow" ? state.narrow : name === "ui-hidden" ? state.uiHidden : name === "input" ? state.input === value : name === "left" ? state.leftMode === value : name === "right" ? state.rightMode === value : false) !== negated;
52
+ });
53
+ /**
54
+ * The nearest `<paint-canvas>` layout around an element, looking through shadow roots, if any.
55
+ */
56
+ var findLayout = (element) => {
57
+ let node = element;
58
+ while (node) {
59
+ if (node instanceof Element && node.tagName === "PAINT-CANVAS") return node;
60
+ node = node.parentNode instanceof ShadowRoot ? node.parentNode.host : node.parentNode ?? null;
61
+ }
62
+ };
63
+ /**
64
+ * Keeps a Lit element up to date with the state of the `<paint-canvas>` layout it's in (see `LayoutState`), so it can
65
+ * render differently per device or size. `state` is undefined outside a layout.
66
+ *
67
+ * @example
68
+ * class MyThing extends LitElement {
69
+ * private layout = new LayoutStateController(this);
70
+ * override render() {
71
+ * return this.layout.state?.narrow ? html`…` : html`…`;
72
+ * }
73
+ * }
74
+ */
75
+ var LayoutStateController = class {
76
+ host;
77
+ source;
78
+ onChange = () => this.host.requestUpdate();
79
+ constructor(host) {
80
+ this.host = host;
81
+ host.addController(this);
82
+ }
83
+ /** The layout's state, if the element is in a layout */
84
+ get state() {
85
+ return this.source?.state;
86
+ }
87
+ hostConnected() {
88
+ this.source = findLayout(this.host);
89
+ this.source?.addEventListener(STATE_EVENT, this.onChange);
90
+ }
91
+ hostDisconnected() {
92
+ this.source?.removeEventListener(STATE_EVENT, this.onChange);
93
+ this.source = void 0;
94
+ }
95
+ };
96
+ export { DEFAULT_NARROW_WIDTH, DEFAULT_SIDE_MODES, LayoutStateController, SIDE_MODES, STATE_EVENT, findLayout, matchesState, parseSideModes, sideModeFor };
@@ -0,0 +1,13 @@
1
+ /** Windows, menus and dialog buttons: affirmative buttons purple, cancel and close buttons pink */
2
+ export declare const windows: import("lit").CSSResult;
3
+ /** Interface controls whose text isn't selected by clicking or dragging (form fields stay selectable) */
4
+ export declare const noTextSelection: import("lit").CSSResult;
5
+ /** Icon toggles (a checkbox hidden behind its icon, purple while on) and boxed icon buttons */
6
+ export declare const iconControls: import("lit").CSSResult;
7
+ /** Small purple pill buttons, e.g. "Configure", "New Layer", "Import" */
8
+ export declare const pills: import("lit").CSSResult;
9
+ /** The shared styles as text, e.g. for `unsafeCSS` */
10
+ export declare const WINDOWS_CSS: string;
11
+ export declare const NO_TEXT_SELECTION_CSS: string;
12
+ export declare const ICON_CONTROLS_CSS: string;
13
+ export declare const PILLS_CSS: string;
@@ -0,0 +1,195 @@
1
+ import { css } from "lit";
2
+ // src/ui/styles/index.ts
3
+ /** Windows, menus and dialog buttons: affirmative buttons purple, cancel and close buttons pink */
4
+ var windows = css`
5
+ button,
6
+ input,
7
+ select,
8
+ textarea {
9
+ font-family: inherit;
10
+ }
11
+ [role="dialog"],
12
+ .window {
13
+ padding: var(--pc-space-3);
14
+ border-radius: var(--pc-radius);
15
+ background: var(--pc-surface-raised);
16
+ color: var(--pc-text);
17
+ box-shadow: var(--pc-shadow);
18
+ }
19
+ .menu-surface {
20
+ background: var(--pc-surface-raised);
21
+ color: var(--pc-text);
22
+ box-shadow: var(--pc-shadow);
23
+ }
24
+ button.affirmative,
25
+ button[type="submit"],
26
+ button.cancel,
27
+ button.close {
28
+ min-height: var(--pc-control-size);
29
+ padding: var(--pc-space-1) var(--pc-space-3);
30
+ border: 0;
31
+ border-radius: var(--pc-radius-pill);
32
+ color: var(--pc-accent-text);
33
+ font: inherit;
34
+ font-weight: bold;
35
+ cursor: pointer;
36
+ }
37
+ button.affirmative,
38
+ button[type="submit"] {
39
+ background: var(--pc-accent);
40
+ }
41
+ button.cancel,
42
+ button.close {
43
+ background: var(--pc-cancel);
44
+ color: var(--pc-cancel-text);
45
+ }
46
+ button.affirmative:hover,
47
+ button[type="submit"]:hover,
48
+ button.cancel:hover,
49
+ button.close:hover {
50
+ filter: brightness(1.15);
51
+ }
52
+ button.affirmative:focus-visible,
53
+ button[type="submit"]:focus-visible,
54
+ button.cancel:focus-visible,
55
+ button.close:focus-visible {
56
+ outline: var(--pc-focus-width) solid var(--pc-focus);
57
+ outline-offset: 2px;
58
+ }
59
+ button.affirmative:disabled,
60
+ button[type="submit"]:disabled,
61
+ button.cancel:disabled,
62
+ button.close:disabled {
63
+ opacity: 0.5;
64
+ filter: none;
65
+ cursor: default;
66
+ }
67
+ button.close.dismiss {
68
+ border: 0;
69
+ background: transparent;
70
+ color: var(--pc-dismiss-text);
71
+ }
72
+ button.close.dismiss:hover {
73
+ filter: none;
74
+ text-decoration: underline;
75
+ }
76
+ `;
77
+ /** Interface controls whose text isn't selected by clicking or dragging (form fields stay selectable) */
78
+ var noTextSelection = css`
79
+ :host {
80
+ user-select: none;
81
+ -webkit-user-select: none;
82
+ -webkit-touch-callout: none;
83
+ }
84
+ input,
85
+ select,
86
+ textarea {
87
+ user-select: text;
88
+ -webkit-user-select: text;
89
+ }
90
+ `;
91
+ /** Icon toggles (a checkbox hidden behind its icon, purple while on) and boxed icon buttons */
92
+ var iconControls = css`
93
+ .icon-toggle {
94
+ position: relative;
95
+ display: inline-flex;
96
+ padding: 2px;
97
+ border: 1px solid var(--pc-border);
98
+ border-radius: var(--pc-radius-small);
99
+ background: var(--pc-surface);
100
+ cursor: pointer;
101
+ }
102
+ .icon-toggle:hover {
103
+ background: var(--pc-surface-hover);
104
+ }
105
+ .icon-toggle:has(input:checked),
106
+ .icon-toggle:has(input:checked):hover {
107
+ border-color: var(--pc-accent);
108
+ background: var(--pc-accent);
109
+ }
110
+ .icon-toggle:has(input:focus-visible) {
111
+ outline: var(--pc-focus-width) solid var(--pc-focus);
112
+ }
113
+ .icon-toggle input {
114
+ position: absolute;
115
+ inset: 0;
116
+ margin: 0;
117
+ opacity: 0;
118
+ cursor: pointer;
119
+ }
120
+ .icon-toggle img,
121
+ button.icon-button img {
122
+ display: block;
123
+ width: var(--pc-icon-size);
124
+ height: var(--pc-icon-size);
125
+ filter: var(--pc-icon-filter);
126
+ }
127
+ .icon-toggle:has(input:disabled) {
128
+ opacity: 0.4;
129
+ cursor: default;
130
+ }
131
+ .visually-hidden {
132
+ position: absolute;
133
+ width: 1px;
134
+ height: 1px;
135
+ overflow: hidden;
136
+ clip-path: inset(50%);
137
+ white-space: nowrap;
138
+ }
139
+ button.icon-button {
140
+ display: inline-flex;
141
+ padding: 2px;
142
+ border: 1px solid var(--pc-border);
143
+ border-radius: var(--pc-radius-small);
144
+ background: var(--pc-surface);
145
+ cursor: pointer;
146
+ }
147
+ button.icon-button:hover:not(:disabled) {
148
+ background: var(--pc-surface-hover);
149
+ }
150
+ button.icon-button[aria-pressed="true"] {
151
+ border-color: var(--pc-accent);
152
+ background: var(--pc-accent);
153
+ }
154
+ button.icon-button:disabled {
155
+ opacity: 0.4;
156
+ cursor: default;
157
+ }
158
+ button.icon-button:focus-visible {
159
+ outline: var(--pc-focus-width) solid var(--pc-focus);
160
+ }
161
+ `;
162
+ /** Small purple pill buttons, e.g. "Configure", "New Layer", "Import" */
163
+ var pills = css`
164
+ button.configure,
165
+ button.pill {
166
+ min-height: 30px;
167
+ padding: var(--pc-space-1) var(--pc-space-3);
168
+ border: 0;
169
+ border-radius: var(--pc-radius-pill);
170
+ background: var(--pc-accent);
171
+ color: var(--pc-accent-text);
172
+ font: inherit;
173
+ font-weight: bold;
174
+ cursor: pointer;
175
+ }
176
+ button.configure:hover:not(:disabled),
177
+ button.pill:hover:not(:disabled) {
178
+ filter: brightness(1.15);
179
+ }
180
+ button.configure:focus-visible,
181
+ button.pill:focus-visible {
182
+ outline: var(--pc-focus-width) solid var(--pc-focus);
183
+ outline-offset: 2px;
184
+ }
185
+ button.pill:disabled {
186
+ background: var(--pc-disabled);
187
+ cursor: default;
188
+ }
189
+ `;
190
+ /** The shared styles as text, e.g. for `unsafeCSS` */
191
+ var WINDOWS_CSS = windows.cssText;
192
+ var NO_TEXT_SELECTION_CSS = noTextSelection.cssText;
193
+ var ICON_CONTROLS_CSS = iconControls.cssText;
194
+ var PILLS_CSS = pills.cssText;
195
+ export { ICON_CONTROLS_CSS, NO_TEXT_SELECTION_CSS, PILLS_CSS, WINDOWS_CSS, iconControls, noTextSelection, pills, windows };
@@ -0,0 +1,29 @@
1
+ /** Design token values, by name (without the `--pc-` prefix) */
2
+ export type TokenValues = Readonly<Record<string, string>>;
3
+ /** The light theme's tokens: colours, spacing, corner radius, fonts and focus ring */
4
+ export declare const LIGHT_TOKENS: TokenValues;
5
+ /** The dark theme's tokens that differ from the light theme's */
6
+ export declare const DARK_TOKENS: TokenValues;
7
+ /**
8
+ * The page-level stylesheet: light tokens on the page, so every element inherits them and the implementer can override
9
+ * any token on `:root` or any ancestor. `data-pc-theme="dark"` on an ancestor switches what's inside it to the dark
10
+ * theme, and `data-pc-theme="auto"` follows the device.
11
+ */
12
+ export declare const PAGE_TOKENS_CSS: string;
13
+ /** The design tokens as text: the page-level stylesheet (kept for including in the implementer's own stylesheets) */
14
+ export declare const TOKENS_CSS: string;
15
+ /**
16
+ * Elements' shared styles: a `theme` attribute switches one element (and what's inside it) to the light, dark or
17
+ * automatic theme, and `.pc-visually-hidden` hides text from view but not from screen readers.
18
+ *
19
+ * @example
20
+ * static styles = [tokens, css`button { color: var(--pc-text); }`];
21
+ */
22
+ export declare const tokens: import("lit").CSSResult;
23
+ /** Marks the page-level token stylesheet, so it's added once */
24
+ export declare const TOKENS_STYLE_ID = "pc-tokens";
25
+ /**
26
+ * Add the page-level token stylesheet to a document (once), before its other styles so the implementer's own
27
+ * stylesheets override it. PaintCanvas's elements do this when they're added to the page.
28
+ */
29
+ export declare const installTokens: (document?: Document) => void;
@@ -0,0 +1,114 @@
1
+ import { unsafeCSS } from "lit";
2
+ // src/ui/tokens/index.ts
3
+ /** The light theme's tokens: colours, spacing, corner radius, fonts and focus ring */
4
+ var LIGHT_TOKENS = {
5
+ blue: "#2c6bff",
6
+ purple: "#8f3de8",
7
+ pink: "#f40f95",
8
+ "pink-dark": "#d10b7e",
9
+ red: "#fb234a",
10
+ orange: "#fe7e07",
11
+ yellow: "#ffd52c",
12
+ green: "#6dc905",
13
+ mint: "#21e887",
14
+ cyan: "#13c3f4",
15
+ surface: "#ffffff",
16
+ "surface-raised": "#ffffff",
17
+ "surface-hover": "#dddddd",
18
+ "surface-active": "#cccccc",
19
+ bar: "#eeeeee",
20
+ border: "#999999",
21
+ text: "#000000",
22
+ "text-muted": "#666666",
23
+ shadow: "0 4px 16px rgb(0 0 0 / 25%)",
24
+ backdrop: "rgb(0 0 0 / 40%)",
25
+ accent: "#8f3de8",
26
+ "accent-text": "#ffffff",
27
+ cancel: "#f40f95",
28
+ "cancel-text": "#ffffff",
29
+ "dismiss-text": "#d10b7e",
30
+ disabled: "#999999",
31
+ "icon-filter": "none",
32
+ "space-1": "4px",
33
+ "space-2": "8px",
34
+ "space-3": "16px",
35
+ "radius-small": "4px",
36
+ radius: "8px",
37
+ "radius-pill": "999px",
38
+ "control-size": "32px",
39
+ "icon-size": "24px",
40
+ font: "Arial, Helvetica, sans-serif",
41
+ "font-size": "14px",
42
+ "font-size-small": "12px",
43
+ focus: "#000000",
44
+ "focus-width": "3px",
45
+ "color-scheme": "light"
46
+ };
47
+ /** The dark theme's tokens that differ from the light theme's */
48
+ var DARK_TOKENS = {
49
+ surface: "#1e1e1e",
50
+ "surface-raised": "#2a2a2a",
51
+ "surface-hover": "#3a3a3a",
52
+ "surface-active": "#4a4a4a",
53
+ bar: "#252525",
54
+ border: "#6b6b6b",
55
+ text: "#f2f2f2",
56
+ "text-muted": "#b0b0b0",
57
+ shadow: "0 4px 16px rgb(0 0 0 / 60%)",
58
+ backdrop: "rgb(0 0 0 / 60%)",
59
+ accent: "#a463f0",
60
+ "dismiss-text": "#ff5cb8",
61
+ disabled: "#6b6b6b",
62
+ "icon-filter": "none",
63
+ focus: "#ffffff",
64
+ "color-scheme": "dark"
65
+ };
66
+ /**
67
+ * Token values as CSS declarations.
68
+ *
69
+ * @example
70
+ * declarations({ text: "#000" }); // "--pc-text: #000;"
71
+ */
72
+ var declarations = (values) => Object.entries(values).map(([name, value]) => `--pc-${name}: ${value};`).join(" ");
73
+ /**
74
+ * The page-level stylesheet: light tokens on the page, so every element inherits them and the implementer can override
75
+ * any token on `:root` or any ancestor. `data-pc-theme="dark"` on an ancestor switches what's inside it to the dark
76
+ * theme, and `data-pc-theme="auto"` follows the device.
77
+ */
78
+ var PAGE_TOKENS_CSS = `:root, [data-pc-theme="light"] { ${declarations(LIGHT_TOKENS)} }
79
+ [data-pc-theme="dark"] { ${declarations(DARK_TOKENS)} }
80
+ @media (prefers-color-scheme: dark) { [data-pc-theme="auto"] { ${declarations(DARK_TOKENS)} } }`;
81
+ /** The design tokens as text: the page-level stylesheet (kept for including in the implementer's own stylesheets) */
82
+ var TOKENS_CSS = PAGE_TOKENS_CSS;
83
+ /**
84
+ * Elements' shared styles: a `theme` attribute switches one element (and what's inside it) to the light, dark or
85
+ * automatic theme, and `.pc-visually-hidden` hides text from view but not from screen readers.
86
+ *
87
+ * @example
88
+ * static styles = [tokens, css`button { color: var(--pc-text); }`];
89
+ */
90
+ var tokens = unsafeCSS(`:host([theme="light"]) { ${declarations(LIGHT_TOKENS)} }
91
+ :host([theme="dark"]) { ${declarations({
92
+ ...LIGHT_TOKENS,
93
+ ...DARK_TOKENS
94
+ })} }
95
+ @media (prefers-color-scheme: dark) { :host([theme="auto"]) { ${declarations({
96
+ ...LIGHT_TOKENS,
97
+ ...DARK_TOKENS
98
+ })} } }
99
+ :host { color: var(--pc-text); color-scheme: var(--pc-color-scheme); }
100
+ .pc-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }`);
101
+ /** Marks the page-level token stylesheet, so it's added once */
102
+ var TOKENS_STYLE_ID = "pc-tokens";
103
+ /**
104
+ * Add the page-level token stylesheet to a document (once), before its other styles so the implementer's own
105
+ * stylesheets override it. PaintCanvas's elements do this when they're added to the page.
106
+ */
107
+ var installTokens = (document = window.document) => {
108
+ if (document.getElementById("pc-tokens")) return;
109
+ const style = document.createElement("style");
110
+ style.id = TOKENS_STYLE_ID;
111
+ style.textContent = PAGE_TOKENS_CSS;
112
+ document.head.prepend(style);
113
+ };
114
+ export { DARK_TOKENS, LIGHT_TOKENS, PAGE_TOKENS_CSS, TOKENS_CSS, TOKENS_STYLE_ID, installTokens, tokens };
@@ -0,0 +1,179 @@
1
+ {
2
+ "paintCanvas.common.cancel": "Cancel",
3
+ "paintCanvas.common.close": "Close",
4
+ "paintCanvas.common.dismiss": "Dismiss",
5
+ "paintCanvas.common.save": "Save",
6
+ "paintCanvas.common.delete": "Delete",
7
+ "paintCanvas.common.clear": "Clear",
8
+ "paintCanvas.common.copy": "Copy",
9
+ "paintCanvas.common.paste": "Paste",
10
+ "paintCanvas.common.undo": "Undo",
11
+ "paintCanvas.common.redo": "Redo",
12
+ "paintCanvas.common.off": "Off",
13
+ "paintCanvas.common.moreInformation": "More information",
14
+ "paintCanvas.common.width": "Width",
15
+ "paintCanvas.common.height": "Height",
16
+ "paintCanvas.common.opacity": "Opacity",
17
+ "paintCanvas.tool.brush": "Brush",
18
+ "paintCanvas.tool.eraser": "Eraser",
19
+ "paintCanvas.tool.move": "Move, scale and rotate",
20
+ "paintCanvas.tool.rectangleLasso": "Rectangle lasso",
21
+ "paintCanvas.tool.circleLasso": "Circle lasso",
22
+ "paintCanvas.tool.polygonLasso": "Polygon lasso",
23
+ "paintCanvas.tool.freeformLasso": "Freeform lasso",
24
+ "paintCanvas.tool.pan": "Pan",
25
+ "paintCanvas.tool.zoom": "Zoom",
26
+ "paintCanvas.tool.colourSample": "Colour sample",
27
+ "paintCanvas.tool.withShortcut": "{tool} ({shortcut})",
28
+ "paintCanvas.toolbar.label": "Tools",
29
+ "paintCanvas.toolbar.currentColour": "Current colour",
30
+ "paintCanvas.toolbar.layers": "Layers",
31
+ "paintCanvas.toolbar.menu": "Menu",
32
+ "paintCanvas.toolbar.undoWithShortcut": "Undo ({shortcut})",
33
+ "paintCanvas.toolbar.redoWithShortcut": "Redo ({shortcut})",
34
+ "paintCanvas.toolSettings.settings": "{tool} settings",
35
+ "paintCanvas.toolSettings.presets": "{tool} presets",
36
+ "paintCanvas.toolSettings.configure": "Configure",
37
+ "paintCanvas.toolSettings.constrainProportions": "Constrain proportions",
38
+ "paintCanvas.toolSettings.pressure": "Pressure",
39
+ "paintCanvas.toolSettings.tilt": "Tilt",
40
+ "paintCanvas.toolSettings.focusPen": "Focus pen mode",
41
+ "paintCanvas.toolSettings.focusPenHint": "Focus pen mode: only the pen draws",
42
+ "paintCanvas.toolSettings.flipHorizontal": "Flip horizontal",
43
+ "paintCanvas.toolSettings.flipVertical": "Flip vertical",
44
+ "paintCanvas.toolSettings.rotateLeft": "Rotate 90° left",
45
+ "paintCanvas.toolSettings.rotateRight": "Rotate 90° right",
46
+ "paintCanvas.toolSettings.maskSettings": "Mask settings",
47
+ "paintCanvas.toolSettings.zoomIn": "Zoom in",
48
+ "paintCanvas.toolSettings.zoomOut": "Zoom out",
49
+ "paintCanvas.toolSettings.pointSample": "Point sample",
50
+ "paintCanvas.toolSettings.areaSample": "Area sample",
51
+ "paintCanvas.brushMenu.presets": "{tool} presets",
52
+ "paintCanvas.brushMenu.size": "{tool} size",
53
+ "paintCanvas.brushMenu.dragToResize": "Drag sideways to resize",
54
+ "paintCanvas.brushMenu.newPreset": "New preset",
55
+ "paintCanvas.brushMenu.create": "Create",
56
+ "paintCanvas.brushMenu.import": "Import",
57
+ "paintCanvas.brushMenu.export": "Export",
58
+ "paintCanvas.presets.myPresets": "My presets",
59
+ "paintCanvas.presets.unknownAuthor": "Unknown",
60
+ "paintCanvas.presets.deleteConfirm": "Delete \"{name}\"? This can't be undone.",
61
+ "paintCanvas.presets.deleted": "Deleted \"{name}\"",
62
+ "paintCanvas.presets.deleteFailed": "Couldn't delete \"{name}\"",
63
+ "paintCanvas.presets.saved": "Saved \"{name}\" to My presets",
64
+ "paintCanvas.presets.saveFailed": "Couldn't save \"{name}\"",
65
+ "paintCanvas.presets.replaceConfirm": "You already have a preset called \"{name}\". Replace it?",
66
+ "paintCanvas.presets.imported.one": "Imported {count} brush preset",
67
+ "paintCanvas.presets.imported.other": "Imported {count} brush presets",
68
+ "paintCanvas.presets.fileIncompatible": "Brush preset JSON file not compatible",
69
+ "paintCanvas.presets.fileReadFailed": "Failed to read brush preset JSON file",
70
+ "paintCanvas.presets.exportFailed": "Error exporting brush preset JSON file",
71
+ "paintCanvas.presets.nothingToExport": "No brush presets to export",
72
+ "paintCanvas.brushConfig.brushTitle": "Brush configuration",
73
+ "paintCanvas.brushConfig.eraserTitle": "Eraser configuration",
74
+ "paintCanvas.brushConfig.presetName": "Name of the preset",
75
+ "paintCanvas.brushConfig.shape": "Shape",
76
+ "paintCanvas.brushConfig.upload": "Upload",
77
+ "paintCanvas.brushConfig.paste": "Paste",
78
+ "paintCanvas.brushConfig.rotation": "Rotation",
79
+ "paintCanvas.brushConfig.offsetX": "Offset X",
80
+ "paintCanvas.brushConfig.offsetY": "Offset Y",
81
+ "paintCanvas.brushConfig.spacing": "Spacing",
82
+ "paintCanvas.brushConfig.sampleRate": "Sample rate",
83
+ "paintCanvas.brushConfig.smoothing": "Smoothing",
84
+ "paintCanvas.brushConfig.smoothingLinear": "Linear",
85
+ "paintCanvas.brushConfig.smoothingQuadratic": "Quadratic curve",
86
+ "paintCanvas.brushConfig.smoothingCubic": "Cubic curve",
87
+ "paintCanvas.brushConfig.randomise": "Randomise",
88
+ "paintCanvas.brushConfig.deletePreset": "Delete preset…",
89
+ "paintCanvas.brushConfig.shapeFailed": "Couldn't use the brush shape",
90
+ "paintCanvas.brushConfig.test": "Test",
91
+ "paintCanvas.brushConfig.testArea": "Brush testing area",
92
+ "paintCanvas.shape.notPng": "Brush shapes must be PNG images",
93
+ "paintCanvas.shape.tooLarge": "Brush shape images can be up to 2 MB",
94
+ "paintCanvas.shape.readFailed": "Couldn't read the brush shape image",
95
+ "paintCanvas.shape.noPngToPaste": "There is no PNG image to paste",
96
+ "paintCanvas.layers.label": "Layers",
97
+ "paintCanvas.layers.new": "New Layer",
98
+ "paintCanvas.layers.defaultName": "Layer {number}",
99
+ "paintCanvas.layers.name": "Layer name",
100
+ "paintCanvas.layers.visible": "Visible",
101
+ "paintCanvas.layers.alphaLock": "Alpha lock",
102
+ "paintCanvas.layers.blendMode": "Blending mode",
103
+ "paintCanvas.layers.actions": "Layer actions",
104
+ "paintCanvas.layers.reorder": "Reorder {name}: drag, or press for actions",
105
+ "paintCanvas.layers.duplicate": "Duplicate",
106
+ "paintCanvas.layers.createMask": "Create mask",
107
+ "paintCanvas.layers.moveUp": "Move up",
108
+ "paintCanvas.layers.moveDown": "Move down",
109
+ "paintCanvas.layers.moveToTop": "Move to top",
110
+ "paintCanvas.layers.moveToBottom": "Move to bottom",
111
+ "paintCanvas.layers.mergeDown": "Merge down…",
112
+ "paintCanvas.layers.mergeDownConfirm": "Are you sure you want to merge this layer with the layer under it?",
113
+ "paintCanvas.layers.mergeLayer": "Merge layer",
114
+ "paintCanvas.layers.clearConfirm": "Clear all image data on \"{name}\"?",
115
+ "paintCanvas.layers.deleteConfirm": "Delete \"{name}\"?",
116
+ "paintCanvas.blendMode.normal": "Normal",
117
+ "paintCanvas.blendMode.screen": "Screen",
118
+ "paintCanvas.blendMode.lighten": "Lighten",
119
+ "paintCanvas.blendMode.multiply": "Multiply",
120
+ "paintCanvas.blendMode.darken": "Darken",
121
+ "paintCanvas.blendMode.overlay": "Overlay",
122
+ "paintCanvas.canvas.label": "Drawing canvas",
123
+ "paintCanvas.canvas.map": "Canvas map",
124
+ "paintCanvas.canvas.loading": "Loading the canvas…",
125
+ "paintCanvas.inputSettings.title": "Controls",
126
+ "paintCanvas.inputSettings.scrollPan": "Scroll or two-finger swipe to pan",
127
+ "paintCanvas.inputSettings.touchPan": "Two-finger drag to pan",
128
+ "paintCanvas.inputSettings.pinchZoom": "Pinch to zoom",
129
+ "paintCanvas.inputSettings.modifierScrollZoom": "{key} + scroll to zoom",
130
+ "paintCanvas.inputSettings.focusPen": "Focus pen mode: fingers and palms never draw",
131
+ "paintCanvas.inputSettings.gestures": "Touch gestures",
132
+ "paintCanvas.inputSettings.language": "Language",
133
+ "paintCanvas.gesture.tap2": "Tap with two fingers",
134
+ "paintCanvas.gesture.tap3": "Tap with three fingers",
135
+ "paintCanvas.gesture.swipeUp3": "Swipe up with three fingers",
136
+ "paintCanvas.gesture.swipeDown3": "Swipe down with three fingers",
137
+ "paintCanvas.gesture.swipeLeft3": "Swipe left with three fingers",
138
+ "paintCanvas.gesture.swipeRight3": "Swipe right with three fingers",
139
+ "paintCanvas.gesture.swipeIn3": "Swipe in with three fingers",
140
+ "paintCanvas.gesture.swipeOut3": "Swipe out with three fingers",
141
+ "paintCanvas.toolSettings.selectAll": "Select all",
142
+ "paintCanvas.toolSettings.invertSelection": "Invert selection",
143
+ "paintCanvas.toolSettings.deselect": "Deselect",
144
+ "paintCanvas.toolSettings.percent": "Percent",
145
+ "paintCanvas.toolSettings.reset": "Reset",
146
+ "paintCanvas.brushMenu.importFile": "Import presets file",
147
+ "paintCanvas.brushConfig.name": "Name",
148
+ "paintCanvas.brushConfig.snapToPixelGrid": "Snap to pixel grid",
149
+ "paintCanvas.brushConfig.addToPresets": "Add to presets",
150
+ "paintCanvas.brushConfig.variation": "{param}: {source}",
151
+ "paintCanvas.layers.mergeDownTitle": "Merge down",
152
+ "paintCanvas.layers.clear": "Clear…",
153
+ "paintCanvas.layers.delete": "Delete…",
154
+ "paintCanvas.layers.clearTitle": "Clear layer",
155
+ "paintCanvas.layers.deleteTitle": "Delete layer",
156
+ "paintCanvas.toolSettings.angle": "Angle",
157
+ "paintCanvas.layout.tools": "Tools",
158
+ "paintCanvas.layout.toolSettings": "Tool settings",
159
+ "paintCanvas.layout.panels": "Panels",
160
+ "paintCanvas.layout.status": "Status",
161
+ "paintCanvas.layout.canvas": "Canvas",
162
+ "paintCanvas.layout.show": "Show {name}",
163
+ "paintCanvas.layout.hide": "Hide {name}",
164
+ "paintCanvas.layout.new": "{name} (new)",
165
+ "paintCanvas.brushConfig.newPresetName": "New brush",
166
+ "paintCanvas.autosave.elsewhere": "You are already drawing in another window",
167
+ "paintCanvas.autosave.elsewhereMessage": "This drawing is open in another window or tab, and only one can draw on it at a time. Choose \"Draw here instead\" to continue in this window; the other one stops.",
168
+ "paintCanvas.autosave.takeOver": "Draw here instead",
169
+ "paintCanvas.autosave.failed": "Couldn't keep the drawing in this browser",
170
+ "paintCanvas.stats.label": "Canvas details",
171
+ "paintCanvas.stats.size": "Canvas: {width} × {height} px",
172
+ "paintCanvas.stats.zoom": "Zoom: {zoom}",
173
+ "paintCanvas.stats.colour": "Colour: {colour}",
174
+ "paintCanvas.stats.stored": "Stored: {size}",
175
+ "paintCanvas.theme.label": "Theme",
176
+ "paintCanvas.theme.light": "Light",
177
+ "paintCanvas.theme.dark": "Dark",
178
+ "paintCanvas.theme.auto": "Auto"
179
+ }