@lvl99dotcom/paintcanvas 0.0.0-stage → 0.2.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 +94 -0
  86. package/dist/lib/i18n/index.js +182 -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 +188 -0
  144. package/dist/locales/en-US.js +188 -0
  145. package/dist/locales/fr.js +188 -0
  146. package/dist/locales/ja.js +188 -0
  147. package/dist/locales/ko.js +188 -0
  148. package/dist/locales/zh-Hans.js +188 -0
  149. package/dist/locales/zh-Hant.js +188 -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 +463 -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 +150 -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 +141 -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 +543 -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 +186 -0
  278. package/locales/en-US.json +186 -0
  279. package/locales/fr.json +186 -0
  280. package/locales/ja.json +186 -0
  281. package/locales/ko.json +186 -0
  282. package/locales/zh-Hans.json +186 -0
  283. package/locales/zh-Hant.json +186 -0
  284. package/package.json +97 -3
@@ -0,0 +1,128 @@
1
+ import { nothing } from "lit";
2
+ import { PcElement } from "../../base";
3
+ import PaintCanvas, { Tool } from "../../../lib/classes/PaintCanvas";
4
+ import type { BrushConfig } from "../../../lib/brushes/types";
5
+ /** Settings varied with pen tilt by the tilt toggle */
6
+ declare const TILT_PARAMS: readonly ["widthConfig", "heightConfig", "rotationConfig"];
7
+ /** A setting's variation config key */
8
+ type ParamKey = (typeof TILT_PARAMS)[number];
9
+ /**
10
+ * Whether a tool has settings to show in the bar.
11
+ *
12
+ * @example
13
+ * hasToolSettings(Tool.Brush); // true
14
+ * hasToolSettings(Tool.Pan); // false
15
+ */
16
+ export declare const hasToolSettings: (tool: Tool) => boolean;
17
+ /**
18
+ * Turn pressure or tilt on or off for some of a brush's settings, keeping their ranges.
19
+ *
20
+ * @example
21
+ * withSource(preset, ["widthConfig"], "usePressure", true); // { widthConfig: { ...preset.widthConfig, usePressure: true } }
22
+ */
23
+ export declare const withSource: (preset: BrushConfig, params: readonly ParamKey[], source: "usePressure" | "useTilt", on: boolean) => Partial<BrushConfig>;
24
+ /**
25
+ * An angle rounded to 2 decimal places.
26
+ *
27
+ * @example
28
+ * roundAngle(12.3456); // 12.35
29
+ */
30
+ export declare const roundAngle: (degrees: number) => number;
31
+ /** Steps of the zoom slider, across the whole zoom range */
32
+ export declare const ZOOM_SLIDER_STEPS = 1000;
33
+ /**
34
+ * A zoom level's position on the zoom slider (0 to ZOOM_SLIDER_STEPS). The scale is logarithmic, so each doubling of
35
+ * the zoom takes the same room.
36
+ *
37
+ * @example
38
+ * zoomToSlider(MIN_ZOOM); // 0
39
+ * zoomToSlider(MAX_ZOOM); // 1000
40
+ */
41
+ export declare const zoomToSlider: (zoom: number) => number;
42
+ /**
43
+ * The zoom level at a position on the zoom slider (see `zoomToSlider`).
44
+ *
45
+ * @example
46
+ * sliderToZoom(1000); // MAX_ZOOM
47
+ */
48
+ export declare const sliderToZoom: (value: number) => number;
49
+ /**
50
+ * A zoom level as a percentage, e.g. "150%" (to one decimal place below 10%).
51
+ *
52
+ * @example
53
+ * zoomPercent(0.0625); // "6.3%"
54
+ */
55
+ export declare const zoomPercent: (zoom: number) => string;
56
+ /**
57
+ * The bar of settings for the current tool, shown at the top of the canvas when the tool has any:
58
+ *
59
+ * - Brush and eraser: the preset (its name and shape; shows or hides the preset menu), width, height, constrain proportions, pressure, tilt, opacity and "Configure" (fires
60
+ * `pc-configure-brush` with the tool, "brush" or "eraser").
61
+ * - Lassos: select all, and invert selection and deselect (only while there is a mask).
62
+ * - Move, scale and rotate: width and height (in pixels or percent), constrain proportions, flip horizontal and vertical,
63
+ * angle (to 2 decimal places), rotate 90° left and right, and reset (undoes the whole transform).
64
+ * - Colour sample: point sample (the pixel under the pointer) or area sample (the average of a dragged rectangle).
65
+ * - Zoom: zoom in and out, a slider across the zoom range (logarithmic) with the zoom as a percentage, and reset (100%),
66
+ * all around the centre of the view.
67
+ *
68
+ * Changes to the brush or eraser apply to the current settings only, not the preset. Styling is structural only.
69
+ *
70
+ * @example
71
+ * html`<pc-tool-settings .app=${app}></pc-tool-settings>`
72
+ */
73
+ export declare class PcToolSettings extends PcElement {
74
+ static properties: {
75
+ app: {
76
+ attribute: boolean;
77
+ };
78
+ percent: {
79
+ state: boolean;
80
+ };
81
+ translations: {
82
+ attribute: boolean;
83
+ };
84
+ icons: {
85
+ attribute: boolean;
86
+ };
87
+ theme: {
88
+ type: StringConstructor;
89
+ reflect: boolean;
90
+ };
91
+ };
92
+ static styles: import("lit").CSSResultGroup[];
93
+ app?: PaintCanvas;
94
+ /** Whether the move tool's width and height are in percent (of the original size) instead of pixels */
95
+ percent: boolean;
96
+ private changes;
97
+ constructor();
98
+ /** Fire an event that crosses shadow DOM boundaries */
99
+ private emit;
100
+ /**
101
+ * Change the move tool's box (as it is now, not as last shown), if there is one.
102
+ */
103
+ private changeBox;
104
+ /**
105
+ * Render the focus pen mode toggle, on the right of every tool's settings: while on, only pens draw, and touches are
106
+ * ignored while a pen is down or just lifted.
107
+ */
108
+ private renderFocusPen;
109
+ /** Render the brush or eraser settings */
110
+ private renderBrush;
111
+ /** Render the mask settings */
112
+ private renderMask;
113
+ /**
114
+ * Resize the move tool's box to a width or height (in the current unit), keeping flips, and the other side in
115
+ * proportion when constrained.
116
+ */
117
+ private resizeBox;
118
+ /** A box side in the current unit, for an input */
119
+ private sideValue;
120
+ /** Render the move, scale and rotate settings */
121
+ private renderMove;
122
+ /** Render the zoom settings */
123
+ private renderZoom;
124
+ /** Render the colour sample tool's settings: point or area sampling */
125
+ private renderColourSample;
126
+ render(): import("lit").TemplateResult<1> | typeof nothing;
127
+ }
128
+ export {};
@@ -0,0 +1,543 @@
1
+ import style_default from "./style.js";
2
+ import { ICON_CONTROLS_CSS, PILLS_CSS } from "../../styles/index.js";
3
+ import { PcElement, defineElement } from "../../base/index.js";
4
+ import ChangeController from "../../ChangeController/index.js";
5
+ import { Panel, Tool } from "../../../lib/classes/PaintCanvas/index.js";
6
+ import "../../../lib/classes/BrushSettings/index.js";
7
+ import { MAX_ZOOM, MIN_ZOOM } from "../../../lib/classes/Viewport/index.js";
8
+ import { iconLabel } from "../../icons/index.js";
9
+ import { html, nothing, svg, unsafeCSS } from "lit";
10
+ import { live } from "lit/directives/live.js";
11
+ import { styleMap } from "lit/directives/style-map.js";
12
+ // src/ui/elements/PcToolSettings/index.ts
13
+ /** The lasso tools, which share the mask settings */
14
+ var MASK_TOOLS = [
15
+ Tool.RectangleLasso,
16
+ Tool.CircleLasso,
17
+ Tool.PolygonLasso,
18
+ Tool.FreeformLasso
19
+ ];
20
+ /** Settings varied with pen pressure by the pressure toggle */
21
+ var PRESSURE_PARAMS = ["widthConfig", "heightConfig"];
22
+ /** Settings varied with pen tilt by the tilt toggle */
23
+ var TILT_PARAMS = [
24
+ "widthConfig",
25
+ "heightConfig",
26
+ "rotationConfig"
27
+ ];
28
+ /**
29
+ * Whether a tool has settings to show in the bar.
30
+ *
31
+ * @example
32
+ * hasToolSettings(Tool.Brush); // true
33
+ * hasToolSettings(Tool.Pan); // false
34
+ */
35
+ var hasToolSettings = (tool) => tool === Tool.Brush || tool === Tool.Eraser || tool === Tool.Move || tool === Tool.Zoom || tool === Tool.ColourSample || MASK_TOOLS.includes(tool);
36
+ /**
37
+ * Turn pressure or tilt on or off for some of a brush's settings, keeping their ranges.
38
+ *
39
+ * @example
40
+ * withSource(preset, ["widthConfig"], "usePressure", true); // { widthConfig: { ...preset.widthConfig, usePressure: true } }
41
+ */
42
+ var withSource = (preset, params, source, on) => Object.fromEntries(params.map((param) => [param, {
43
+ ...preset[param],
44
+ [source]: on
45
+ }]));
46
+ /**
47
+ * An angle rounded to 2 decimal places.
48
+ *
49
+ * @example
50
+ * roundAngle(12.3456); // 12.35
51
+ */
52
+ var roundAngle = (degrees) => Math.round(degrees * 100) / 100;
53
+ /** Steps of the zoom slider, across the whole zoom range */
54
+ var ZOOM_SLIDER_STEPS = 1e3;
55
+ /** How many times bigger the largest zoom is than the smallest */
56
+ var ZOOM_RANGE = MAX_ZOOM / MIN_ZOOM;
57
+ /**
58
+ * A zoom level's position on the zoom slider (0 to ZOOM_SLIDER_STEPS). The scale is logarithmic, so each doubling of
59
+ * the zoom takes the same room.
60
+ *
61
+ * @example
62
+ * zoomToSlider(MIN_ZOOM); // 0
63
+ * zoomToSlider(MAX_ZOOM); // 1000
64
+ */
65
+ var zoomToSlider = (zoom) => Math.round(Math.log(zoom / MIN_ZOOM) / Math.log(ZOOM_RANGE) * ZOOM_SLIDER_STEPS);
66
+ /**
67
+ * The zoom level at a position on the zoom slider (see `zoomToSlider`).
68
+ *
69
+ * @example
70
+ * sliderToZoom(1000); // MAX_ZOOM
71
+ */
72
+ var sliderToZoom = (value) => MIN_ZOOM * ZOOM_RANGE ** (value / ZOOM_SLIDER_STEPS);
73
+ /**
74
+ * A zoom level as a percentage, e.g. "150%" (to one decimal place below 10%).
75
+ *
76
+ * @example
77
+ * zoomPercent(0.0625); // "6.3%"
78
+ */
79
+ var zoomPercent = (zoom) => {
80
+ const percent = zoom * 100;
81
+ return `${percent < 10 ? Math.round(percent * 10) / 10 : Math.round(percent)}%`;
82
+ };
83
+ /** Read a number input, or undefined if it isn't a number */
84
+ var numberValue = (event) => {
85
+ const value = event.target.valueAsNumber;
86
+ return Number.isFinite(value) ? value : void 0;
87
+ };
88
+ /**
89
+ * The bar of settings for the current tool, shown at the top of the canvas when the tool has any:
90
+ *
91
+ * - Brush and eraser: the preset (its name and shape; shows or hides the preset menu), width, height, constrain proportions, pressure, tilt, opacity and "Configure" (fires
92
+ * `pc-configure-brush` with the tool, "brush" or "eraser").
93
+ * - Lassos: select all, and invert selection and deselect (only while there is a mask).
94
+ * - Move, scale and rotate: width and height (in pixels or percent), constrain proportions, flip horizontal and vertical,
95
+ * angle (to 2 decimal places), rotate 90° left and right, and reset (undoes the whole transform).
96
+ * - Colour sample: point sample (the pixel under the pointer) or area sample (the average of a dragged rectangle).
97
+ * - Zoom: zoom in and out, a slider across the zoom range (logarithmic) with the zoom as a percentage, and reset (100%),
98
+ * all around the centre of the view.
99
+ *
100
+ * Changes to the brush or eraser apply to the current settings only, not the preset. Styling is structural only.
101
+ *
102
+ * @example
103
+ * html`<pc-tool-settings .app=${app}></pc-tool-settings>`
104
+ */
105
+ var PcToolSettings = class extends PcElement {
106
+ static properties = {
107
+ ...PcElement.properties,
108
+ app: { attribute: false },
109
+ percent: { state: true }
110
+ };
111
+ static styles = [
112
+ PcElement.styles,
113
+ unsafeCSS(ICON_CONTROLS_CSS),
114
+ unsafeCSS(PILLS_CSS),
115
+ unsafeCSS(style_default)
116
+ ];
117
+ changes = new ChangeController(this, () => {
118
+ const app = this.app;
119
+ return app ? [
120
+ app,
121
+ app.brush,
122
+ app.eraser,
123
+ app.transform,
124
+ app.selection,
125
+ app.viewport,
126
+ app.input
127
+ ] : [];
128
+ });
129
+ constructor() {
130
+ super();
131
+ this.percent = false;
132
+ }
133
+ /** Fire an event that crosses shadow DOM boundaries */
134
+ emit(type, detail) {
135
+ this.dispatchEvent(new CustomEvent(type, {
136
+ detail,
137
+ bubbles: true,
138
+ composed: true
139
+ }));
140
+ }
141
+ /**
142
+ * Change the move tool's box (as it is now, not as last shown), if there is one.
143
+ */
144
+ changeBox(app, change) {
145
+ const box = app.transform.box;
146
+ if (box) app.transform.setBox({
147
+ ...box,
148
+ ...change(box)
149
+ });
150
+ }
151
+ /**
152
+ * Render the focus pen mode toggle, on the right of every tool's settings: while on, only pens draw, and touches are
153
+ * ignored while a pen is down or just lifted.
154
+ */
155
+ renderFocusPen(app) {
156
+ return html`<label
157
+ class="icon-toggle focus-pen"
158
+ title=${this.t("toolSettings.focusPenHint")}
159
+ >
160
+ <input
161
+ type="checkbox"
162
+ .checked=${live(app.input.data.focusPen)}
163
+ @change=${(e) => app.input.update({ focusPen: e.target.checked })}
164
+ />
165
+ ${iconLabel(this.iconUrl("focusPen"), this.t("toolSettings.focusPen"))}
166
+ </label>`;
167
+ }
168
+ /** Render the brush or eraser settings */
169
+ renderBrush(app, settings, kind) {
170
+ const preset = settings.preset;
171
+ const pressure = PRESSURE_PARAMS.some((param) => preset[param]?.usePressure);
172
+ const tilt = TILT_PARAMS.some((param) => preset[param]?.useTilt);
173
+ const label = this.t(kind === "eraser" ? "tool.eraser" : "tool.brush");
174
+ const panel = kind === "eraser" ? Panel.Eraser : Panel.Brush;
175
+ return html`<div
176
+ role="toolbar"
177
+ aria-label=${this.t("toolSettings.settings", { tool: label })}
178
+ >
179
+ <button
180
+ type="button"
181
+ class="preset"
182
+ title=${this.t("toolSettings.presets", { tool: label })}
183
+ aria-expanded=${app.panel === panel ? "true" : "false"}
184
+ @click=${() => app.togglePanel(panel)}
185
+ >
186
+ <span
187
+ class=${preset.image ? "shape-preview image" : "shape-preview"}
188
+ style=${styleMap({ maskImage: typeof preset.image === "string" ? `url("${preset.image}")` : void 0 })}
189
+ ></span>
190
+ ${preset.name ?? preset.id}
191
+ </button>
192
+ <label>
193
+ ${this.t("common.width")}
194
+ <input
195
+ type="number"
196
+ class="width"
197
+ min=${1}
198
+ max=${256}
199
+ .value=${String(settings.width)}
200
+ @change=${(e) => {
201
+ const value = numberValue(e);
202
+ if (value !== void 0) settings.setSize(value, settings.height);
203
+ }}
204
+ />
205
+ </label>
206
+ <label
207
+ class="icon-toggle"
208
+ title=${this.t("toolSettings.constrainProportions")}
209
+ >
210
+ <input
211
+ type="checkbox"
212
+ class="constrain"
213
+ .checked=${preset.constrainProportions ?? false}
214
+ @change=${(e) => settings.update({ constrainProportions: e.target.checked })}
215
+ />
216
+ ${iconLabel(this.iconUrl(preset.constrainProportions ? "linked" : "unlinked"), this.t("toolSettings.constrainProportions"))}
217
+ </label>
218
+ <label>
219
+ ${this.t("common.height")}
220
+ <input
221
+ type="number"
222
+ class="height"
223
+ min=${1}
224
+ max=${256}
225
+ .value=${String(settings.height)}
226
+ @change=${(e) => {
227
+ const value = numberValue(e);
228
+ if (value !== void 0) settings.setHeight(value);
229
+ }}
230
+ />
231
+ </label>
232
+ <label class="icon-toggle" title=${this.t("toolSettings.pressure")}>
233
+ <input
234
+ type="checkbox"
235
+ class="pressure"
236
+ .checked=${pressure}
237
+ @change=${(e) => settings.update(withSource(preset, PRESSURE_PARAMS, "usePressure", e.target.checked))}
238
+ />
239
+ ${iconLabel(this.iconUrl("pressure"), this.t("toolSettings.pressure"))}
240
+ </label>
241
+ <label class="icon-toggle" title=${this.t("toolSettings.tilt")}>
242
+ <input
243
+ type="checkbox"
244
+ class="tilt"
245
+ .checked=${tilt}
246
+ @change=${(e) => settings.update(withSource(preset, TILT_PARAMS, "useTilt", e.target.checked))}
247
+ />
248
+ ${iconLabel(this.iconUrl("tilt"), this.t("toolSettings.tilt"))}
249
+ </label>
250
+ <label>
251
+ ${this.t("common.opacity")}
252
+ <input
253
+ type="number"
254
+ class="opacity"
255
+ min="0"
256
+ max="100"
257
+ .value=${String(Math.round((preset.alpha ?? 1) * 100))}
258
+ @change=${(e) => {
259
+ const value = numberValue(e);
260
+ if (value !== void 0) settings.update({ alpha: Math.max(0, Math.min(100, value)) / 100 });
261
+ }}
262
+ />
263
+ <span class="unit">%</span>
264
+ </label>
265
+ <button
266
+ type="button"
267
+ class="configure"
268
+ @click=${() => this.emit("pc-configure-brush", kind)}
269
+ >
270
+ ${this.t("toolSettings.configure")}
271
+ </button>
272
+ ${this.renderFocusPen(app)}
273
+ </div>`;
274
+ }
275
+ /** Render the mask settings */
276
+ renderMask(app) {
277
+ return html`<div
278
+ role="toolbar"
279
+ aria-label=${this.t("toolSettings.maskSettings")}
280
+ >
281
+ <button
282
+ type="button"
283
+ class="pill select-all"
284
+ @click=${() => app.selection.selectAll()}
285
+ >
286
+ ${this.t("toolSettings.selectAll")}
287
+ </button>
288
+ <button
289
+ type="button"
290
+ class="pill invert"
291
+ ?disabled=${!app.selection.active}
292
+ @click=${() => app.selection.invert()}
293
+ >
294
+ ${this.t("toolSettings.invertSelection")}
295
+ </button>
296
+ <button
297
+ type="button"
298
+ class="pill deselect"
299
+ ?disabled=${!app.selection.active}
300
+ @click=${() => app.selection.clear()}
301
+ >
302
+ ${this.t("toolSettings.deselect")}
303
+ </button>
304
+ ${this.renderFocusPen(app)}
305
+ </div>`;
306
+ }
307
+ /**
308
+ * Resize the move tool's box to a width or height (in the current unit), keeping flips, and the other side in
309
+ * proportion when constrained.
310
+ */
311
+ resizeBox(app, side, value) {
312
+ const { box, source } = app.transform;
313
+ if (!box || !source) return;
314
+ const pixels = this.percent ? source[side] * value / 100 : value;
315
+ if (pixels <= 0) return;
316
+ const other = side === "width" ? "height" : "width";
317
+ const ratio = Math.abs(box[other] / box[side]);
318
+ app.transform.setBox({
319
+ ...box,
320
+ [side]: Math.sign(box[side]) * pixels,
321
+ ...app.constrainProportions ? { [other]: Math.sign(box[other]) * pixels * ratio } : {}
322
+ });
323
+ }
324
+ /** A box side in the current unit, for an input */
325
+ sideValue(box, source, side) {
326
+ const pixels = Math.abs(box[side]);
327
+ return String(Math.round(this.percent ? pixels / source[side] * 100 : pixels));
328
+ }
329
+ /** Render the move, scale and rotate settings */
330
+ renderMove(app) {
331
+ const { box, source } = app.transform;
332
+ const disabled = !box || !source;
333
+ const side = (name, label) => html`<label>
334
+ ${label}
335
+ <input
336
+ type="number"
337
+ class=${name}
338
+ min="1"
339
+ ?disabled=${disabled}
340
+ .value=${box && source ? this.sideValue(box, source, name) : ""}
341
+ @change=${(e) => {
342
+ const value = numberValue(e);
343
+ if (value !== void 0) this.resizeBox(app, name, value);
344
+ }}
345
+ />
346
+ </label>`;
347
+ const rotate = (by) => this.changeBox(app, (current) => ({ rotation: by(current.rotation) % 360 }));
348
+ return html`<div
349
+ role="toolbar"
350
+ aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.move") })}
351
+ >
352
+ ${side("width", this.t("common.width"))}
353
+ <label
354
+ class="icon-toggle"
355
+ title=${this.t("toolSettings.constrainProportions")}
356
+ >
357
+ <input
358
+ type="checkbox"
359
+ class="constrain"
360
+ .checked=${live(app.constrainProportions)}
361
+ @change=${(e) => app.setConstrainProportions(e.target.checked)}
362
+ />
363
+ ${iconLabel(this.iconUrl(app.constrainProportions ? "linked" : "unlinked"), this.t("toolSettings.constrainProportions"))}
364
+ </label>
365
+ ${side("height", this.t("common.height"))}
366
+ <label>
367
+ <input
368
+ type="checkbox"
369
+ class="percent"
370
+ .checked=${this.percent}
371
+ @change=${(e) => this.percent = e.target.checked}
372
+ />
373
+ ${this.t("toolSettings.percent")}
374
+ </label>
375
+ <button
376
+ type="button"
377
+ class="icon-button flip-horizontal"
378
+ title=${this.t("toolSettings.flipHorizontal")}
379
+ ?disabled=${disabled}
380
+ @click=${() => this.changeBox(app, (current) => ({ width: -current.width }))}
381
+ >
382
+ ${iconLabel(this.iconUrl("flipHorizontal"), this.t("toolSettings.flipHorizontal"))}
383
+ </button>
384
+ <button
385
+ type="button"
386
+ class="icon-button flip-vertical"
387
+ title=${this.t("toolSettings.flipVertical")}
388
+ ?disabled=${disabled}
389
+ @click=${() => this.changeBox(app, (current) => ({ height: -current.height }))}
390
+ >
391
+ ${iconLabel(this.iconUrl("flipVertical"), this.t("toolSettings.flipVertical"))}
392
+ </button>
393
+ <label>
394
+ ${this.t("toolSettings.angle")}
395
+ <input
396
+ type="number"
397
+ class="angle"
398
+ step="0.01"
399
+ ?disabled=${disabled}
400
+ .value=${box ? String(roundAngle(box.rotation)) : ""}
401
+ @change=${(e) => {
402
+ const value = numberValue(e);
403
+ if (value !== void 0) rotate(() => roundAngle(value));
404
+ }}
405
+ />
406
+ <span class="unit">°</span>
407
+ </label>
408
+ <button
409
+ type="button"
410
+ class="icon-button rotate-left"
411
+ title=${this.t("toolSettings.rotateLeft")}
412
+ ?disabled=${disabled}
413
+ @click=${() => rotate((rotation) => rotation - 90)}
414
+ >
415
+ ${iconLabel(this.iconUrl("rotate90Left"), this.t("toolSettings.rotateLeft"))}
416
+ </button>
417
+ <button
418
+ type="button"
419
+ class="icon-button rotate-right"
420
+ title=${this.t("toolSettings.rotateRight")}
421
+ ?disabled=${disabled}
422
+ @click=${() => rotate((rotation) => rotation + 90)}
423
+ >
424
+ ${iconLabel(this.iconUrl("rotate90Right"), this.t("toolSettings.rotateRight"))}
425
+ </button>
426
+ <button
427
+ type="button"
428
+ class="pill reset"
429
+ ?disabled=${disabled}
430
+ @click=${() => app.cancelTransform()}
431
+ >
432
+ ${this.t("toolSettings.reset")}
433
+ </button>
434
+ ${this.renderFocusPen(app)}
435
+ </div>`;
436
+ }
437
+ /** Render the zoom settings */
438
+ renderZoom(app) {
439
+ const view = app.viewport;
440
+ const centre = {
441
+ x: view.width / 2,
442
+ y: view.height / 2
443
+ };
444
+ return html`<div
445
+ role="toolbar"
446
+ aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.zoom") })}
447
+ >
448
+ <button
449
+ type="button"
450
+ class="zoom-in"
451
+ title=${this.t("toolSettings.zoomIn")}
452
+ aria-label=${this.t("toolSettings.zoomIn")}
453
+ ?disabled=${view.zoom >= MAX_ZOOM}
454
+ @click=${() => view.zoomIn(centre)}
455
+ >
456
+ <img src=${this.iconUrl("zoomIn")} alt="" />
457
+ </button>
458
+ <button
459
+ type="button"
460
+ class="zoom-out"
461
+ title=${this.t("toolSettings.zoomOut")}
462
+ aria-label=${this.t("toolSettings.zoomOut")}
463
+ ?disabled=${view.zoom <= MIN_ZOOM}
464
+ @click=${() => view.zoomOut(centre)}
465
+ >
466
+ <img src=${this.iconUrl("zoomOut")} alt="" />
467
+ </button>
468
+ <label>
469
+ ${this.t("tool.zoom")}
470
+ <input
471
+ type="range"
472
+ class="zoom"
473
+ min="0"
474
+ max=${ZOOM_SLIDER_STEPS}
475
+ step="1"
476
+ .value=${String(zoomToSlider(view.zoom))}
477
+ @input=${(e) => view.zoomAt(centre, sliderToZoom(e.target.valueAsNumber))}
478
+ />
479
+ <output>${zoomPercent(view.zoom)}</output>
480
+ </label>
481
+ <button
482
+ type="button"
483
+ class="pill reset"
484
+ @click=${() => view.zoomAt(centre, 1)}
485
+ >
486
+ ${this.t("toolSettings.reset")}
487
+ </button>
488
+ ${this.renderFocusPen(app)}
489
+ </div>`;
490
+ }
491
+ /** Render the colour sample tool's settings: point or area sampling */
492
+ renderColourSample(app) {
493
+ const modes = [[
494
+ "point",
495
+ this.t("toolSettings.pointSample"),
496
+ svg`<circle cx="10" cy="10" r="6" /><circle cx="10" cy="10" r="1.5" fill="currentColor" /><path d="M10 1 V5 M10 15 V19 M1 10 H5 M15 10 H19" />`
497
+ ], [
498
+ "area",
499
+ this.t("toolSettings.areaSample"),
500
+ svg`<defs><linearGradient id="area-gradient"><stop offset="0" stop-color="currentColor" stop-opacity="0" /><stop offset="1" stop-color="currentColor" /></linearGradient></defs><rect x="2" y="4" width="16" height="12" fill="url(#area-gradient)" />`
501
+ ]];
502
+ return html`<div
503
+ role="toolbar"
504
+ aria-label=${this.t("toolSettings.settings", { tool: this.t("tool.colourSample") })}
505
+ >
506
+ ${modes.map(([mode, label, icon]) => html`<button
507
+ type="button"
508
+ class="sample-${mode}"
509
+ title=${label}
510
+ aria-label=${label}
511
+ aria-pressed=${app.sampleMode === mode ? "true" : "false"}
512
+ @click=${() => app.setSampleMode(mode)}
513
+ >
514
+ <svg
515
+ width="20"
516
+ height="20"
517
+ viewBox="0 0 20 20"
518
+ fill="none"
519
+ stroke="currentColor"
520
+ stroke-width="1.5"
521
+ aria-hidden="true"
522
+ >
523
+ ${icon}
524
+ </svg>
525
+ </button>`)}
526
+ ${this.renderFocusPen(app)}
527
+ </div>`;
528
+ }
529
+ render() {
530
+ const app = this.app;
531
+ if (!app) return nothing;
532
+ switch (app.tool) {
533
+ case Tool.Brush: return this.renderBrush(app, app.brush, "brush");
534
+ case Tool.Eraser: return this.renderBrush(app, app.eraser, "eraser");
535
+ case Tool.Move: return this.renderMove(app);
536
+ case Tool.Zoom: return this.renderZoom(app);
537
+ case Tool.ColourSample: return this.renderColourSample(app);
538
+ default: return MASK_TOOLS.includes(app.tool) ? this.renderMask(app) : nothing;
539
+ }
540
+ }
541
+ };
542
+ defineElement("pc-tool-settings", PcToolSettings);
543
+ export { PcToolSettings, ZOOM_SLIDER_STEPS, hasToolSettings, roundAngle, sliderToZoom, withSource, zoomPercent, zoomToSlider };
@@ -0,0 +1,3 @@
1
+ // src/ui/elements/PcToolSettings/style.css?inline
2
+ var style_default = ":host {\n display: block;\n background: var(--pc-bar);\n border-bottom: 1px solid var(--pc-surface-active);\n}\n/* An open menu's button */\nbutton[aria-expanded=\"true\"] {\n background: var(--pc-surface-active);\n}\n/* Toggles that are on, and the selected option: purple, so it's obvious (the icon stays the same) */\nbutton[aria-pressed=\"true\"],\n.icon-toggle:has(input:checked),\n.icon-toggle:has(input:checked):hover {\n border-color: var(--pc-accent);\n background: var(--pc-accent);\n color: var(--pc-accent-text);\n}\n[role=\"toolbar\"] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 36px;\n padding: 4px 8px;\n overflow-x: auto;\n white-space: nowrap;\n}\ninput[type=\"number\"] {\n width: 4.5em;\n}\n.preset {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n.shape-preview {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: var(--pc-text);\n border-radius: 50%;\n vertical-align: middle;\n}\n.shape-preview.image {\n border-radius: 0;\n mask-repeat: no-repeat;\n mask-size: contain;\n mask-position: center;\n}\n/* Icon buttons (zoom in and out) */\nbutton img {\n display: block;\n width: 24px;\n height: 24px;\n}\n/* Fields' names small and in capitals above them, as designed */\n[role=\"toolbar\"] > label:not(.icon-toggle) {\n display: inline-flex;\n flex-direction: column;\n gap: 1px;\n font-size: 10px;\n text-transform: uppercase;\n}\n/* A unit after its field (\"%\", \"°\"), beside it rather than under it */\n[role=\"toolbar\"] > label:has(.unit) {\n position: relative;\n margin-right: 14px;\n}\n.unit {\n position: absolute;\n right: -14px;\n bottom: 3px;\n font-size: 13px;\n}\n/* Focus pen mode sits on the right of every tool's settings */\n.focus-pen {\n margin-left: auto;\n}\n";
3
+ export { style_default as default };