@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,561 @@
1
+ import style_default from "./style.js";
2
+ import { NO_TEXT_SELECTION_CSS, WINDOWS_CSS } from "../../styles/index.js";
3
+ import { PcElement, defineElement } from "../../base/index.js";
4
+ import ChangeController from "../../ChangeController/index.js";
5
+ import { BlendMode } from "../../../lib/classes/Layer/index.js";
6
+ import { drawCheckerboard, fitSize } from "../../../lib/rendering/checkerboard/index.js";
7
+ import { CANCEL_CHOICE } from "../PcDialog/index.js";
8
+ import { html, nothing, unsafeCSS } from "lit";
9
+ // src/ui/elements/PcLayerItem/index.ts
10
+ /** Blend mode options shown in the layer's select input */
11
+ var BLEND_MODE_OPTIONS = [
12
+ {
13
+ value: BlendMode.Normal,
14
+ label: "blendMode.normal"
15
+ },
16
+ {
17
+ value: BlendMode.Screen,
18
+ label: "blendMode.screen"
19
+ },
20
+ {
21
+ value: BlendMode.Lighten,
22
+ label: "blendMode.lighten"
23
+ },
24
+ {
25
+ value: BlendMode.Multiply,
26
+ label: "blendMode.multiply"
27
+ },
28
+ {
29
+ value: BlendMode.Darken,
30
+ label: "blendMode.darken"
31
+ },
32
+ {
33
+ value: BlendMode.Overlay,
34
+ label: "blendMode.overlay"
35
+ }
36
+ ];
37
+ /** Context menu options in display order, with the translation keys of their labels */
38
+ var LAYER_ACTIONS = [
39
+ {
40
+ action: "mask",
41
+ label: "layers.createMask"
42
+ },
43
+ {
44
+ action: "duplicate",
45
+ label: "layers.duplicate"
46
+ },
47
+ {
48
+ action: "merge",
49
+ label: "layers.mergeDown"
50
+ },
51
+ {
52
+ action: "clear",
53
+ label: "layers.clear"
54
+ },
55
+ {
56
+ action: "delete",
57
+ label: "layers.delete"
58
+ },
59
+ {
60
+ action: "up",
61
+ label: "layers.moveUp"
62
+ },
63
+ {
64
+ action: "top",
65
+ label: "layers.moveToTop"
66
+ },
67
+ {
68
+ action: "down",
69
+ label: "layers.moveDown"
70
+ },
71
+ {
72
+ action: "bottom",
73
+ label: "layers.moveToBottom"
74
+ }
75
+ ];
76
+ /**
77
+ * What the user is asked before each confirmed action: the dialog's heading and message, and its choices (the first
78
+ * does the action), as translation keys. The message is given the layer's `name`.
79
+ */
80
+ var CONFIRMATIONS = {
81
+ merge: {
82
+ heading: "layers.mergeDownTitle",
83
+ message: "layers.mergeDownConfirm",
84
+ choices: [{
85
+ value: "merge",
86
+ label: "layers.mergeLayer"
87
+ }, {
88
+ value: CANCEL_CHOICE,
89
+ label: "common.dismiss",
90
+ variant: "dismiss"
91
+ }]
92
+ },
93
+ clear: {
94
+ heading: "layers.clearTitle",
95
+ message: "layers.clearConfirm",
96
+ choices: [{
97
+ value: "clear",
98
+ label: "common.clear"
99
+ }, {
100
+ value: CANCEL_CHOICE,
101
+ label: "common.dismiss",
102
+ variant: "dismiss"
103
+ }]
104
+ },
105
+ delete: {
106
+ heading: "layers.deleteTitle",
107
+ message: "layers.deleteConfirm",
108
+ choices: [{
109
+ value: "delete",
110
+ label: "common.delete"
111
+ }, {
112
+ value: CANCEL_CHOICE,
113
+ label: "common.dismiss",
114
+ variant: "dismiss"
115
+ }]
116
+ }
117
+ };
118
+ /** Thumbnail size in CSS pixels */
119
+ var THUMBNAIL_SIZE = 30;
120
+ /** Checkerboard square size in thumbnail pixels */
121
+ var THUMBNAIL_CHECKER_SIZE = 5;
122
+ /** Event a row dispatches when it opens its context menu, so other rows close theirs */
123
+ var LAYER_MENU_OPEN_EVENT = "pc-layer-menu-open";
124
+ /** Event a row dispatches to ask for a mask from the layer's alpha (Cmd/Ctrl + click on the thumbnail or name, or "Create mask") */
125
+ var LAYER_ALPHA_MASK_EVENT = "pc-layer-alpha-mask";
126
+ /** How far (CSS pixels) the pointer moves on the reorder handle before it drags the layer, rather than opening the menu */
127
+ var DRAG_THRESHOLD = 4;
128
+ /** Event a row dispatches while its layer is dragged by its reorder handle (detail: {@link LayerDragDetail}) */
129
+ var LAYER_DRAG_EVENT = "pc-layer-drag";
130
+ /** Space kept between the layer actions menu and the window's edges */
131
+ var MENU_MARGIN = 8;
132
+ /**
133
+ * Where the layer actions menu's top goes: level with the handle, moved up as far as needed to stay in the window
134
+ * (but never above its top margin).
135
+ *
136
+ * @example
137
+ * menuTop(700, 300, 800); // 492 (moved up to fit)
138
+ * menuTop(100, 300, 800); // 100
139
+ */
140
+ var menuTop = (anchorTop, menuHeight, viewportHeight, margin = 8) => Math.max(margin, Math.min(anchorTop, viewportHeight - margin - menuHeight));
141
+ /**
142
+ * One row in the layers menu: reorder handle, thumbnail and name (then opacity and blend mode under them), alpha lock (padlock) and visibility (eye) icons.
143
+ * Dragging the handle (with mouse, pen or touch) reorders the layer: the row fires {@link LAYER_DRAG_EVENT} and the
144
+ * layers menu shows where it will land. Clicking or tapping the handle, pressing Enter or Space on it, or right-clicking
145
+ * it opens the layer's actions menu (which can also reorder it). Cmd/Ctrl + click on the thumbnail or name (or "Create
146
+ * mask" in the menu) makes a mask from the layer's pixels. "Merge down…" asks first, then merges the layer into the one
147
+ * under it (not offered for the bottom layer, or when either is hidden).
148
+ *
149
+ * @example
150
+ * html`<pc-layer-item .stack=${stack} .layer=${layer}></pc-layer-item>`
151
+ */
152
+ var PcLayerItem = class extends PcElement {
153
+ static properties = {
154
+ ...PcElement.properties,
155
+ stack: { attribute: false },
156
+ layer: { attribute: false },
157
+ background: { attribute: false },
158
+ menuOpen: { state: true },
159
+ confirming: { state: true },
160
+ dragging: {
161
+ type: Boolean,
162
+ reflect: true
163
+ },
164
+ dropAction: {
165
+ attribute: "drop-action",
166
+ reflect: true
167
+ }
168
+ };
169
+ static styles = [
170
+ PcElement.styles,
171
+ unsafeCSS(NO_TEXT_SELECTION_CSS),
172
+ unsafeCSS(style_default),
173
+ unsafeCSS(WINDOWS_CSS)
174
+ ];
175
+ /** The pointer pressed on the reorder handle, where it was pressed, and whether it has started dragging */
176
+ press;
177
+ /** Whether to ignore the next click on the handle (it ended a drag) */
178
+ suppressClick = false;
179
+ changes = new ChangeController(this, () => [this.stack]);
180
+ /** Device pixels per CSS pixel (replaceable for tests) */
181
+ pixelRatio = () => window.devicePixelRatio || 1;
182
+ constructor() {
183
+ super();
184
+ this.menuOpen = false;
185
+ this.dragging = false;
186
+ }
187
+ /**
188
+ * Run a context menu action. Merging down, clearing and deleting ask for confirmation first (see `confirmed`).
189
+ */
190
+ runAction(action) {
191
+ const { stack, layer } = this;
192
+ this.menuOpen = false;
193
+ if (!stack || !layer || !this.canRun(action)) return;
194
+ switch (action) {
195
+ case "mask":
196
+ this.requestMask(layer, {
197
+ shiftKey: false,
198
+ altKey: false
199
+ });
200
+ break;
201
+ case "duplicate":
202
+ stack.duplicate(layer.id);
203
+ break;
204
+ case "merge":
205
+ case "clear":
206
+ case "delete":
207
+ this.confirming = action;
208
+ break;
209
+ case "up":
210
+ stack.moveUp(layer.id);
211
+ break;
212
+ case "top":
213
+ stack.moveToTop(layer.id);
214
+ break;
215
+ case "down":
216
+ stack.moveDown(layer.id);
217
+ break;
218
+ case "bottom": stack.moveToBottom(layer.id);
219
+ }
220
+ }
221
+ /**
222
+ * Whether a context menu action can be done to the layer now: not merging down the bottom layer (or with a hidden
223
+ * layer), deleting the only layer, or moving a layer further up or down than it can go.
224
+ */
225
+ canRun(action) {
226
+ const { stack, layer } = this;
227
+ if (!stack || !layer) return false;
228
+ const index = stack.indexOf(layer.id);
229
+ const last = stack.layers.length - 1;
230
+ switch (action) {
231
+ case "merge": return stack.canMergeDown(layer.id);
232
+ case "delete": return last > 0;
233
+ case "up":
234
+ case "top": return index > 0;
235
+ case "down":
236
+ case "bottom": return index < last;
237
+ default: return true;
238
+ }
239
+ }
240
+ /**
241
+ * Do an action the user confirmed.
242
+ */
243
+ confirmed(action) {
244
+ const { stack, layer } = this;
245
+ this.confirming = void 0;
246
+ if (!stack || !layer) return;
247
+ if (action === "merge") stack.mergeDown(layer.id);
248
+ else if (action === "clear") stack.clear(layer.id);
249
+ else stack.remove(layer.id);
250
+ }
251
+ onOutsidePointer = (event) => {
252
+ if (!event.composedPath().includes(this)) this.menuOpen = false;
253
+ };
254
+ onKeyDown = (event) => {
255
+ if (event.key === "Escape") this.menuOpen = false;
256
+ };
257
+ /**
258
+ * Open the context menu on right-click, or close it if open.
259
+ */
260
+ onContextMenu(event) {
261
+ event.preventDefault();
262
+ this.toggleMenu();
263
+ }
264
+ /**
265
+ * Open the context menu on a click or tap on the handle (or Enter or Space), or close it if open; a click that ends a
266
+ * drag does nothing.
267
+ */
268
+ onHandleClick() {
269
+ if (this.suppressClick) {
270
+ this.suppressClick = false;
271
+ return;
272
+ }
273
+ this.toggleMenu();
274
+ }
275
+ /**
276
+ * Open the context menu (closing other rows' menus), or close it if open.
277
+ */
278
+ toggleMenu() {
279
+ this.menuOpen = !this.menuOpen;
280
+ if (this.menuOpen) this.dispatchEvent(new CustomEvent(LAYER_MENU_OPEN_EVENT, {
281
+ bubbles: true,
282
+ composed: true
283
+ }));
284
+ }
285
+ disconnectedCallback() {
286
+ super.disconnectedCallback();
287
+ this.listenOutside(false);
288
+ this.endPress();
289
+ }
290
+ /** Tell the layers menu about a drag of this row's layer */
291
+ emitDrag(phase, x, y) {
292
+ this.dispatchEvent(new CustomEvent(LAYER_DRAG_EVENT, {
293
+ detail: {
294
+ layer: this.layer,
295
+ phase,
296
+ x,
297
+ y
298
+ },
299
+ bubbles: true,
300
+ composed: true
301
+ }));
302
+ }
303
+ /**
304
+ * Press on the reorder handle: follow the pointer, which drags once it has moved far enough. The pointer is followed
305
+ * on the whole window, as browsers don't always grant pointer capture; it is asked for too, so a touch keeps dragging
306
+ * after leaving the handle.
307
+ */
308
+ onHandlePointerDown(event) {
309
+ if (event.button !== 0) return;
310
+ this.press = {
311
+ pointerId: event.pointerId,
312
+ x: event.clientX,
313
+ y: event.clientY,
314
+ dragging: false
315
+ };
316
+ event.currentTarget.setPointerCapture(event.pointerId);
317
+ window.addEventListener("pointermove", this.onHandlePointerMove);
318
+ window.addEventListener("pointerup", this.onHandlePointerUp);
319
+ window.addEventListener("pointercancel", this.onHandlePointerCancel);
320
+ }
321
+ /**
322
+ * Start dragging once the pointer has moved {@link DRAG_THRESHOLD} pixels, then report where it is.
323
+ */
324
+ onHandlePointerMove = (event) => {
325
+ const press = this.press;
326
+ if (press?.pointerId !== event.pointerId) return;
327
+ if (!press.dragging) {
328
+ if (Math.hypot(event.clientX - press.x, event.clientY - press.y) < 4) return;
329
+ press.dragging = true;
330
+ window.addEventListener("keydown", this.onDragKeyDown);
331
+ this.emitDrag("start", event.clientX, event.clientY);
332
+ }
333
+ this.emitDrag("move", event.clientX, event.clientY);
334
+ };
335
+ /**
336
+ * Drop the layer where the pointer is, if it was dragged (a press without dragging opens the menu, on its click).
337
+ */
338
+ onHandlePointerUp = (event) => {
339
+ if (this.press?.pointerId !== event.pointerId) return;
340
+ if (this.press.dragging) {
341
+ this.suppressClick = true;
342
+ this.emitDrag("end", event.clientX, event.clientY);
343
+ }
344
+ this.endPress();
345
+ };
346
+ /**
347
+ * Cancel a drag when the browser cancels the pointer (e.g. a system gesture).
348
+ */
349
+ onHandlePointerCancel = (event) => {
350
+ if (this.press?.pointerId !== event.pointerId) return;
351
+ if (this.press.dragging) this.emitDrag("cancel", event.clientX, event.clientY);
352
+ this.endPress();
353
+ };
354
+ /** Escape cancels a drag, leaving the layer where it was */
355
+ onDragKeyDown = (event) => {
356
+ const press = this.press;
357
+ if (event.key !== "Escape" || !press) return;
358
+ this.suppressClick = true;
359
+ this.emitDrag("cancel", press.x, press.y);
360
+ this.endPress();
361
+ };
362
+ /** Stop following the pointer pressed on the handle */
363
+ endPress() {
364
+ this.press = void 0;
365
+ window.removeEventListener("keydown", this.onDragKeyDown);
366
+ window.removeEventListener("pointermove", this.onHandlePointerMove);
367
+ window.removeEventListener("pointerup", this.onHandlePointerUp);
368
+ window.removeEventListener("pointercancel", this.onHandlePointerCancel);
369
+ }
370
+ /**
371
+ * Start or stop listening for clicks outside and Escape while the menu is open.
372
+ */
373
+ listenOutside(listen) {
374
+ const method = listen ? "addEventListener" : "removeEventListener";
375
+ window[method]("pointerdown", this.onOutsidePointer, true);
376
+ window[method]("keydown", this.onKeyDown);
377
+ window[method]("scroll", this.onScroll, true);
378
+ }
379
+ onScroll = () => {
380
+ this.menuOpen = false;
381
+ };
382
+ /**
383
+ * Place the open layer actions menu beside the reorder handle, floating over the layers panel (so the panel's edges
384
+ * don't cut it off) and kept within the window.
385
+ */
386
+ placeMenu() {
387
+ const menu = this.renderRoot.querySelector("menu");
388
+ if (!menu) return;
389
+ const anchor = this.renderRoot.querySelector(".handle").getBoundingClientRect();
390
+ menu.style.left = `${anchor.right}px`;
391
+ menu.style.top = `${menuTop(anchor.top, menu.offsetHeight, window.innerHeight)}px`;
392
+ }
393
+ /**
394
+ * Ask for a mask following the layer's alpha (Shift adds, Alt subtracts; otherwise it replaces the mask).
395
+ */
396
+ requestMask(layer, keys) {
397
+ this.dispatchEvent(new CustomEvent(LAYER_ALPHA_MASK_EVENT, {
398
+ detail: {
399
+ layer,
400
+ shiftKey: keys.shiftKey,
401
+ altKey: keys.altKey
402
+ },
403
+ bubbles: true,
404
+ composed: true
405
+ }));
406
+ }
407
+ /**
408
+ * Clicking the row selects the layer. Cmd/Ctrl + click on the thumbnail or name also makes a mask from the layer's alpha.
409
+ */
410
+ onRowClick(event, stack, layer) {
411
+ stack.select(layer.id);
412
+ if (!event.metaKey && !event.ctrlKey) return;
413
+ const target = event.composedPath()[0];
414
+ if (!(target instanceof Element) || !target.matches(".thumbnail, .name")) return;
415
+ event.preventDefault();
416
+ this.requestMask(layer, event);
417
+ }
418
+ /**
419
+ * Rename a layer when the name input changes. Empty names are reverted.
420
+ */
421
+ onRename(event, stack, layer) {
422
+ const input = event.target;
423
+ try {
424
+ stack.rename(layer.id, input.value);
425
+ } catch {
426
+ input.value = layer.name;
427
+ }
428
+ }
429
+ updated(changed) {
430
+ if (changed.has("menuOpen")) {
431
+ this.listenOutside(this.menuOpen);
432
+ if (this.menuOpen) this.placeMenu();
433
+ }
434
+ const id = this.layer?.id;
435
+ if (this.background && id) this.background.run(`thumbnail ${id}`, () => this.drawThumbnail());
436
+ else this.drawThumbnail();
437
+ }
438
+ /**
439
+ * Draw the layer's image, scaled to fit, on a checkerboard that shows transparency.
440
+ */
441
+ drawThumbnail() {
442
+ const layer = this.layer;
443
+ const canvas = this.renderRoot.querySelector("canvas.thumbnail");
444
+ if (!layer || !canvas) return;
445
+ const ratio = this.pixelRatio();
446
+ const size = Math.round(30 * ratio);
447
+ canvas.width = size;
448
+ canvas.height = size;
449
+ const ctx = canvas.getContext("2d");
450
+ if (!ctx) return;
451
+ drawCheckerboard(ctx, size, size, 5 * ratio);
452
+ const fitted = fitSize(layer.width, layer.height, size, size);
453
+ ctx.imageSmoothingEnabled = true;
454
+ ctx.drawImage(layer.canvas, (size - fitted.width) / 2, (size - fitted.height) / 2, fitted.width, fitted.height);
455
+ }
456
+ /** The dialog asking the user to confirm an action, while asking */
457
+ renderConfirmation(layer) {
458
+ const action = this.confirming;
459
+ if (!action) return nothing;
460
+ const { heading, message, choices } = CONFIRMATIONS[action];
461
+ return html`<pc-dialog
462
+ heading=${this.t(heading)}
463
+ message=${this.t(message, { name: layer.name })}
464
+ .choices=${choices.map((choice) => ({
465
+ ...choice,
466
+ label: this.t(choice.label)
467
+ }))}
468
+ @pc-choose=${(e) => {
469
+ e.stopPropagation();
470
+ if (e.detail.value === action) this.confirmed(action);
471
+ else this.confirming = void 0;
472
+ }}
473
+ ></pc-dialog>`;
474
+ }
475
+ render() {
476
+ const { stack, layer } = this;
477
+ if (!stack || !layer) return html``;
478
+ const active = stack.active.id === layer.id;
479
+ return html`
480
+ <button
481
+ type="button"
482
+ class="handle"
483
+ aria-label=${this.t("layers.reorder", { name: layer.name })}
484
+ aria-haspopup="menu"
485
+ aria-expanded=${this.menuOpen ? "true" : "false"}
486
+ @contextmenu=${this.onContextMenu}
487
+ @click=${this.onHandleClick}
488
+ @pointerdown=${this.onHandlePointerDown}
489
+ >
490
+ ⠿
491
+ </button>
492
+ <div
493
+ class="details"
494
+ @click=${(e) => this.onRowClick(e, stack, layer)}
495
+ >
496
+ <canvas class="thumbnail" aria-hidden="true"></canvas>
497
+ <input
498
+ class="name ${active ? "active" : ""}"
499
+ aria-label=${this.t("layers.name")}
500
+ .value=${layer.name}
501
+ @change=${(e) => this.onRename(e, stack, layer)}
502
+ />
503
+ <input
504
+ type="range"
505
+ min="0"
506
+ max="100"
507
+ aria-label=${this.t("common.opacity")}
508
+ .value=${String(Math.round(layer.opacity * 100))}
509
+ @change=${(e) => stack.update(layer.id, { opacity: Number(e.target.value) / 100 })}
510
+ />
511
+ <select
512
+ aria-label=${this.t("layers.blendMode")}
513
+ @change=${(e) => stack.update(layer.id, { blendMode: e.target.value })}
514
+ >
515
+ ${BLEND_MODE_OPTIONS.map(({ value, label }) => html`<option
516
+ value=${value}
517
+ ?selected=${layer.blendMode === value}
518
+ >
519
+ ${this.t(label)}
520
+ </option>`)}
521
+ </select>
522
+ </div>
523
+ <button
524
+ type="button"
525
+ class="alpha-lock"
526
+ aria-label=${this.t("layers.alphaLock")}
527
+ aria-pressed=${layer.alphaLock}
528
+ @click=${() => stack.update(layer.id, { alphaLock: !layer.alphaLock })}
529
+ >
530
+ <img
531
+ src=${this.iconUrl(layer.alphaLock ? "locked" : "unlocked")}
532
+ alt=""
533
+ />
534
+ </button>
535
+ <button
536
+ type="button"
537
+ class="visibility"
538
+ aria-label=${this.t("layers.visible")}
539
+ aria-pressed=${layer.visible}
540
+ @click=${() => stack.update(layer.id, { visible: !layer.visible })}
541
+ >
542
+ <img src=${this.iconUrl(layer.visible ? "visible" : "hidden")} alt="" />
543
+ </button>
544
+ ${this.menuOpen ? html`<menu aria-label=${this.t("layers.actions")}>
545
+ ${LAYER_ACTIONS.map(({ action, label }) => html`<li>
546
+ <button
547
+ type="button"
548
+ data-action=${action}
549
+ ?disabled=${!this.canRun(action)}
550
+ @click=${() => this.runAction(action)}
551
+ >
552
+ ${this.t(label)}
553
+ </button>
554
+ </li>`)}
555
+ </menu>` : nothing}
556
+ ${this.renderConfirmation(layer)}
557
+ `;
558
+ }
559
+ };
560
+ defineElement("pc-layer-item", PcLayerItem);
561
+ export { BLEND_MODE_OPTIONS, CONFIRMATIONS, DRAG_THRESHOLD, LAYER_ACTIONS, LAYER_ALPHA_MASK_EVENT, LAYER_DRAG_EVENT, LAYER_MENU_OPEN_EVENT, MENU_MARGIN, PcLayerItem, THUMBNAIL_CHECKER_SIZE, THUMBNAIL_SIZE, menuTop };
@@ -0,0 +1,3 @@
1
+ // src/ui/elements/PcLayerItem/style.css?inline
2
+ var style_default = "/* A white row with space around its parts */\n:host {\n display: grid;\n grid-template-columns: 30px 1fr 30px 30px;\n align-items: center;\n column-gap: 6px;\n position: relative;\n padding: 6px;\n border: 1px solid var(--pc-surface-active);\n background: var(--pc-surface);\n}\n.name.active {\n font-weight: bold;\n}\n.thumbnail {\n width: 30px;\n height: 30px;\n}\n/* Thumbnail on the left and name on the right; under them, opacity on the left and blend mode on the right */\n.details {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) auto;\n align-items: center;\n gap: 4px 6px;\n}\n.details .name {\n grid-column: 2 / -1;\n min-width: 0;\n}\n.details input[type=\"range\"] {\n grid-column: 1 / 3;\n min-width: 0;\n margin: 0;\n}\n/* Like the chat's ⋮ menu: white and rounded, with plain items highlighted on hover. It floats beside the handle (placed\n by `placeMenu`), so the layers panel's edges don't cut it off */\nmenu {\n position: fixed;\n z-index: 20;\n min-width: 160px;\n margin: 0;\n padding: 4px 0;\n border-radius: 12px;\n list-style: none;\n background: var(--pc-surface);\n color: var(--pc-text);\n box-shadow: var(--pc-shadow);\n}\nmenu button {\n width: 100%;\n min-height: 32px;\n padding: 4px 16px;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n text-align: left;\n white-space: nowrap;\n cursor: pointer;\n}\nmenu button:hover:not(:disabled),\nmenu button:focus-visible {\n background: var(--pc-bar);\n}\n/* Actions the layer can't take (e.g. moving the top layer up) */\nmenu button:disabled {\n opacity: 0.4;\n cursor: default;\n}\n/* The reorder handle drags with mouse, pen or touch (touch drags it rather than scrolling the panel) */\n.handle {\n /* As tall as the row */\n align-self: stretch;\n cursor: grab;\n touch-action: none;\n}\n/* While dragged: the row floats with the pointer, out of the list (the layers menu places it), and the cursor shows\n what dropping would do (\"+\" duplicates on \"New Layer\") */\n:host([dragging]) {\n position: fixed;\n z-index: 10;\n opacity: 0.9;\n background: Canvas;\n box-shadow: var(--pc-shadow);\n}\n:host([dragging]) .handle {\n cursor: grabbing;\n}\n:host([drop-action=\"duplicate\"]) .handle {\n cursor: copy;\n}\n:host([drop-action=\"none\"]) .handle {\n cursor: no-drop;\n}\n/* Alpha lock and visibility: boxed icon toggles like the settings bar's, darker while on */\n.alpha-lock,\n.visibility {\n width: 30px;\n height: 30px;\n padding: 2px;\n border: 1px solid var(--pc-border);\n border-radius: 4px;\n background: var(--pc-surface);\n cursor: pointer;\n}\n.alpha-lock:hover,\n.visibility:hover {\n background: var(--pc-surface-hover);\n}\n.alpha-lock[aria-pressed=\"true\"],\n.visibility[aria-pressed=\"true\"] {\n background: var(--pc-surface-active);\n}\n.alpha-lock:focus-visible,\n.visibility:focus-visible {\n outline: var(--pc-focus-width) solid var(--pc-focus);\n}\n.alpha-lock img,\n.visibility img {\n display: block;\n width: 24px;\n height: 24px;\n margin: auto;\n}\n";
3
+ export { style_default as default };
@@ -0,0 +1,108 @@
1
+ import { PcElement } from "../../base";
2
+ import { type LayerDropAction } from "../PcLayerItem";
3
+ import "../PcLayerItem";
4
+ import type PaintCanvas from "../../../lib/classes/PaintCanvas";
5
+ /** A layer being dragged by its reorder handle, where its row floats, and where dropping it now would put it */
6
+ interface LayerDrag {
7
+ id: string;
8
+ name: string;
9
+ action: LayerDropAction;
10
+ /** Where it would land among the other layers (0 is the first row), when moving */
11
+ slot?: number | undefined;
12
+ /** The pointer, in the viewport */
13
+ x: number;
14
+ y: number;
15
+ /** Where the pointer grabbed the row, from its top left, and the row's size, so the row floats as it was grabbed */
16
+ offsetX: number;
17
+ offsetY: number;
18
+ width: number;
19
+ /** The ghost is as tall as the row, so the list doesn't shift when the row lifts out */
20
+ height: number;
21
+ }
22
+ /**
23
+ * Whether a point is inside a rectangle (edges included).
24
+ *
25
+ * @example
26
+ * isInside(element.getBoundingClientRect(), event.clientX, event.clientY);
27
+ */
28
+ export declare const isInside: (rect: DOMRect, x: number, y: number) => boolean;
29
+ /**
30
+ * Where a dragged layer would land among the other rows: before the first row whose middle is below the pointer, or
31
+ * after the last. The ghost showing the place is left out, so the place doesn't jump when the ghost moves.
32
+ *
33
+ * @param rows - the other rows' top and height, in list order
34
+ * @param ghost - the ghost's top and height, if shown
35
+ *
36
+ * @example
37
+ * dropSlot([{ top: 0, height: 30 }, { top: 30, height: 30 }], 40); // 1
38
+ */
39
+ export declare const dropSlot: (rows: readonly {
40
+ top: number;
41
+ height: number;
42
+ }[], y: number, ghost?: {
43
+ top: number;
44
+ height: number;
45
+ }) => number;
46
+ /**
47
+ * Layers menu: the user's layers from top to bottom and a "New Layer" button.
48
+ *
49
+ * Dragging a layer's reorder handle lifts its row out of the list to float with the pointer, and leaves a ghost with the
50
+ * layer's name in the list where it would land: where it was, until it is moved somewhere else. Dropping it moves it
51
+ * there, and dropping it on "New Layer" duplicates it (the cursor shows "+", and the button is
52
+ * highlighted for touch). Escape cancels the drag. Moves and duplicates are announced to screen readers.
53
+ *
54
+ * @example
55
+ * html`<pc-layers-menu .app=${app}></pc-layers-menu>`
56
+ */
57
+ export declare class PcLayersMenu extends PcElement {
58
+ static properties: {
59
+ app: {
60
+ attribute: boolean;
61
+ };
62
+ drag: {
63
+ state: boolean;
64
+ };
65
+ announcement: {
66
+ state: boolean;
67
+ };
68
+ translations: {
69
+ attribute: boolean;
70
+ };
71
+ icons: {
72
+ attribute: boolean;
73
+ };
74
+ theme: {
75
+ type: StringConstructor;
76
+ reflect: boolean;
77
+ };
78
+ };
79
+ static styles: import("lit").CSSResultGroup[];
80
+ app?: PaintCanvas;
81
+ /** The layer being dragged, if any */
82
+ drag?: LayerDrag | undefined;
83
+ /** The last move or duplicate, for screen readers */
84
+ announcement: string;
85
+ private changes;
86
+ constructor();
87
+ /**
88
+ * Follow a layer dragged by its reorder handle: show where it would land, then move or duplicate it when dropped.
89
+ */
90
+ private onLayerDrag;
91
+ /**
92
+ * What dropping the dragged layer at a point would do: nothing outside the menu, duplicate it on "New Layer" (if
93
+ * another layer can be made), otherwise move it to the place among the other rows nearest the pointer.
94
+ */
95
+ private dropTarget;
96
+ /**
97
+ * Move or duplicate the dropped layer, and tell screen readers what happened.
98
+ */
99
+ private drop;
100
+ /**
101
+ * The rows, with a ghost (the dragged layer's name) where it would land, counting only the other rows: where it was,
102
+ * unless it would move. The dragged row floats with the pointer, out of the list. Rows are keyed by layer, so each
103
+ * layer keeps its row (and a drag its handle) as the ghost moves.
104
+ */
105
+ private renderRows;
106
+ render(): import("lit").TemplateResult<1>;
107
+ }
108
+ export {};