@lvl99dotcom/paintcanvas 0.4.0 → 0.6.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 (224) hide show
  1. package/README.md +30 -15
  2. package/dist/lib/brushes/configRanges/index.d.ts +17 -0
  3. package/dist/lib/brushes/configRanges/index.js +31 -1
  4. package/dist/lib/brushes/params/index.d.ts +2 -1
  5. package/dist/lib/brushes/params/index.js +7 -4
  6. package/dist/lib/brushes/presets/round/index.d.ts +1 -1
  7. package/dist/lib/brushes/presets/round/index.js +12 -7
  8. package/dist/lib/brushes/presets/square/index.d.ts +1 -1
  9. package/dist/lib/brushes/presets/square/index.js +7 -3
  10. package/dist/lib/brushes/shapeImage/index.d.ts +7 -3
  11. package/dist/lib/brushes/shapeImage/index.js +15 -9
  12. package/dist/lib/brushes/shapes/index.d.ts +18 -0
  13. package/dist/lib/brushes/shapes/index.js +86 -0
  14. package/dist/lib/brushes/types/index.d.ts +8 -0
  15. package/dist/lib/classes/BrushSettings/index.d.ts +29 -2
  16. package/dist/lib/classes/BrushSettings/index.js +51 -14
  17. package/dist/lib/classes/KeyboardShortcuts/index.d.ts +31 -2
  18. package/dist/lib/classes/KeyboardShortcuts/index.js +66 -4
  19. package/dist/lib/classes/Layer/index.d.ts +10 -0
  20. package/dist/lib/classes/Layer/index.js +15 -1
  21. package/dist/lib/classes/LayerAutosave/index.d.ts +9 -15
  22. package/dist/lib/classes/LayerAutosave/index.js +30 -43
  23. package/dist/lib/classes/LayerStack/index.d.ts +15 -0
  24. package/dist/lib/classes/LayerStack/index.js +26 -2
  25. package/dist/lib/classes/PaintCanvas/index.d.ts +72 -3
  26. package/dist/lib/classes/PaintCanvas/index.js +106 -12
  27. package/dist/lib/classes/PngEncoder/index.d.ts +41 -0
  28. package/dist/lib/classes/PngEncoder/index.js +104 -0
  29. package/dist/lib/classes/ProfileGraphs/index.d.ts +87 -0
  30. package/dist/lib/classes/ProfileGraphs/index.js +148 -0
  31. package/dist/lib/classes/SettingsAutosave/index.d.ts +3 -2
  32. package/dist/lib/classes/SettingsAutosave/index.js +6 -3
  33. package/dist/lib/classes/UiSettings/index.d.ts +68 -0
  34. package/dist/lib/classes/UiSettings/index.js +82 -0
  35. package/dist/lib/messages/schema.d.ts +720 -0
  36. package/dist/lib/presets/schema.d.ts +360 -0
  37. package/dist/lib/presets/schema.js +8 -1
  38. package/dist/lib/profiles/index.d.ts +61 -0
  39. package/dist/lib/profiles/index.js +131 -0
  40. package/dist/lib/profiles/schema.d.ts +73 -0
  41. package/dist/lib/profiles/schema.js +53 -0
  42. package/dist/lib/rendering/sample/index.d.ts +11 -0
  43. package/dist/lib/rendering/sample/index.js +36 -5
  44. package/dist/lib/settings/index.d.ts +2 -1
  45. package/dist/lib/settings/index.js +7 -2
  46. package/dist/lib/settings/schema.d.ts +67 -0
  47. package/dist/lib/settings/schema.js +20 -0
  48. package/dist/lib/validation/validators.generated.js +13191 -3655
  49. package/dist/locales/en-GB.js +39 -2
  50. package/dist/locales/en-US.js +39 -2
  51. package/dist/locales/fr.js +39 -2
  52. package/dist/locales/ja.js +39 -2
  53. package/dist/locales/ko.js +39 -2
  54. package/dist/locales/zh-Hans.js +39 -2
  55. package/dist/locales/zh-Hant.js +39 -2
  56. package/dist/package.js +1 -1
  57. package/dist/testing/recordingCanvas.js +2 -1
  58. package/dist/ui/ask/index.d.ts +48 -0
  59. package/dist/ui/ask/index.js +67 -0
  60. package/dist/ui/base/index.d.ts +10 -3
  61. package/dist/ui/base/index.js +19 -4
  62. package/dist/ui/dismiss/index.d.ts +21 -0
  63. package/dist/ui/dismiss/index.js +27 -0
  64. package/dist/ui/drag/index.d.ts +51 -0
  65. package/dist/ui/drag/index.js +81 -0
  66. package/dist/ui/elements/PaintCanvas/index.d.ts +17 -12
  67. package/dist/ui/elements/PaintCanvas/index.js +36 -17
  68. package/dist/ui/elements/PaintCanvas/style.js +1 -1
  69. package/dist/ui/elements/PcAppSettings/index.d.ts +6 -6
  70. package/dist/ui/elements/PcAppSettings/index.js +21 -65
  71. package/dist/ui/elements/PcBrushConfig/index.d.ts +34 -16
  72. package/dist/ui/elements/PcBrushConfig/index.js +263 -153
  73. package/dist/ui/elements/PcBrushConfig/style.js +1 -1
  74. package/dist/ui/elements/PcBrushSize/index.d.ts +53 -0
  75. package/dist/ui/elements/PcBrushSize/index.js +66 -0
  76. package/dist/ui/elements/PcBrushTest/index.d.ts +26 -0
  77. package/dist/ui/elements/PcBrushTest/index.js +79 -6
  78. package/dist/ui/elements/PcBrushTest/style.js +1 -1
  79. package/dist/ui/elements/PcButton/index.d.ts +12 -3
  80. package/dist/ui/elements/PcButton/index.js +18 -10
  81. package/dist/ui/elements/PcCanvas/index.d.ts +27 -2
  82. package/dist/ui/elements/PcCanvas/index.js +63 -13
  83. package/dist/ui/elements/PcCanvas/style.js +1 -1
  84. package/dist/ui/elements/PcCanvasMap/style.js +1 -1
  85. package/dist/ui/elements/PcClipboardTools/index.d.ts +49 -0
  86. package/dist/ui/elements/PcClipboardTools/index.js +125 -0
  87. package/dist/ui/elements/PcContextMenu/index.d.ts +2 -2
  88. package/dist/ui/elements/PcDialog/index.d.ts +46 -10
  89. package/dist/ui/elements/PcDialog/index.js +102 -51
  90. package/dist/ui/elements/PcDialogWindow/index.d.ts +141 -0
  91. package/dist/ui/elements/PcDialogWindow/index.js +385 -0
  92. package/dist/ui/elements/PcInputSettings/index.d.ts +13 -0
  93. package/dist/ui/elements/PcInputSettings/index.js +16 -1
  94. package/dist/ui/elements/PcMenu/index.d.ts +48 -3
  95. package/dist/ui/elements/PcMenu/index.js +111 -19
  96. package/dist/ui/elements/PcNumberSlider/index.d.ts +137 -0
  97. package/dist/ui/elements/PcNumberSlider/index.js +247 -0
  98. package/dist/ui/elements/PcPane/index.d.ts +3 -1
  99. package/dist/ui/elements/PcPane/index.js +44 -7
  100. package/dist/ui/elements/PcPanel/index.d.ts +2 -2
  101. package/dist/ui/elements/PcPanel/index.js +8 -8
  102. package/dist/ui/elements/PcPanelBrushes/index.d.ts +5 -17
  103. package/dist/ui/elements/PcPanelBrushes/index.js +13 -48
  104. package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
  105. package/dist/ui/elements/PcPanelColours/index.js +2 -2
  106. package/dist/ui/elements/PcPanelColours/style.js +1 -1
  107. package/dist/ui/elements/PcPanelLayers/index.js +1 -1
  108. package/dist/ui/elements/PcPanelLayers/style.js +1 -1
  109. package/dist/ui/elements/PcPopover/index.d.ts +39 -1
  110. package/dist/ui/elements/PcPopover/index.js +72 -4
  111. package/dist/ui/elements/PcProfileEditor/index.d.ts +103 -0
  112. package/dist/ui/elements/PcProfileEditor/index.js +259 -0
  113. package/dist/ui/elements/PcProfileGraph/index.d.ts +84 -0
  114. package/dist/ui/elements/PcProfileGraph/index.js +317 -0
  115. package/dist/ui/elements/PcShortcutSettings/index.js +9 -13
  116. package/dist/ui/elements/PcSliderRange/index.d.ts +147 -0
  117. package/dist/ui/elements/PcSliderRange/index.js +307 -0
  118. package/dist/ui/elements/PcStats/index.d.ts +19 -4
  119. package/dist/ui/elements/PcStats/index.js +29 -13
  120. package/dist/ui/elements/PcThemePicker/index.d.ts +17 -15
  121. package/dist/ui/elements/PcThemePicker/index.js +22 -21
  122. package/dist/ui/elements/PcToolSettings/index.d.ts +48 -9
  123. package/dist/ui/elements/PcToolSettings/index.js +382 -318
  124. package/dist/ui/elements/PcToolSettings/style.js +1 -1
  125. package/dist/ui/elements/PcToolbar/index.d.ts +15 -0
  126. package/dist/ui/elements/PcToolbar/index.js +55 -14
  127. package/dist/ui/elements/PcToolbar/style.js +1 -1
  128. package/dist/ui/icons/images/icon-brush@2x.js +3 -0
  129. package/dist/ui/icons/images/icon-circle-mask@2x.js +3 -0
  130. package/dist/ui/icons/images/icon-clipboard@2x.js +3 -0
  131. package/dist/ui/icons/images/icon-cog@2x.js +3 -0
  132. package/dist/ui/icons/images/icon-cursor@2x.js +3 -0
  133. package/dist/ui/icons/images/icon-diagonal-tlbr-size@2x.js +3 -0
  134. package/dist/ui/icons/images/icon-diagonal-trbl-size@2x.js +3 -0
  135. package/dist/ui/icons/images/icon-eraser@2x.js +3 -0
  136. package/dist/ui/icons/images/icon-eyedropper@2x.js +3 -0
  137. package/dist/ui/icons/images/icon-flip-horizontal@2x.js +3 -0
  138. package/dist/ui/icons/images/icon-flip-vertical@2x.js +3 -0
  139. package/dist/ui/icons/images/icon-focus-pen@2x.js +3 -0
  140. package/dist/ui/icons/images/icon-freehand-mask@2x.js +3 -0
  141. package/dist/ui/icons/images/icon-hidden@2x.js +3 -0
  142. package/dist/ui/icons/images/icon-horizontal-size@2x.js +3 -0
  143. package/dist/ui/icons/images/icon-layers@2x.js +3 -0
  144. package/dist/ui/icons/images/icon-linked@2x.js +3 -0
  145. package/dist/ui/icons/images/icon-locked@2x.js +3 -0
  146. package/dist/ui/icons/images/icon-moon@2x.js +3 -0
  147. package/dist/ui/icons/images/icon-pan@2x.js +3 -0
  148. package/dist/ui/icons/images/icon-polygon-mask@2x.js +3 -0
  149. package/dist/ui/icons/images/icon-pressure@2x.js +3 -0
  150. package/dist/ui/icons/images/icon-profile-graph@2x.js +3 -0
  151. package/dist/ui/icons/images/icon-randomise@2x.js +3 -0
  152. package/dist/ui/icons/images/icon-rectangle-mask@2x.js +3 -0
  153. package/dist/ui/icons/images/icon-redo@2x.js +3 -0
  154. package/dist/ui/icons/images/icon-rotate-90-left@2x.js +3 -0
  155. package/dist/ui/icons/images/icon-rotate-90-right@2x.js +3 -0
  156. package/dist/ui/icons/images/icon-rotate@2x.js +3 -0
  157. package/dist/ui/icons/images/icon-smoothing-bezier-cubic@2x.js +3 -0
  158. package/dist/ui/icons/images/icon-smoothing-bezier-quad@2x.js +3 -0
  159. package/dist/ui/icons/images/icon-smoothing-linear@2x.js +3 -0
  160. package/dist/ui/icons/images/icon-star@2x.js +3 -0
  161. package/dist/ui/icons/images/icon-sun@2x.js +3 -0
  162. package/dist/ui/icons/images/icon-tilt@2x.js +3 -0
  163. package/dist/ui/icons/images/icon-undo@2x.js +3 -0
  164. package/dist/ui/icons/images/icon-unlinked@2x.js +3 -0
  165. package/dist/ui/icons/images/icon-unlocked@2x.js +3 -0
  166. package/dist/ui/icons/images/icon-vertical-size@2x.js +3 -0
  167. package/dist/ui/icons/images/icon-visible@2x.js +3 -0
  168. package/dist/ui/icons/images/icon-zoom-in@2x.js +3 -0
  169. package/dist/ui/icons/images/icon-zoom-out@2x.js +3 -0
  170. package/dist/ui/icons/images/icon-zoom@2x.js +3 -0
  171. package/dist/ui/icons/index.d.ts +1 -1
  172. package/dist/ui/icons/index.js +86 -72
  173. package/dist/ui/index.d.ts +13 -3
  174. package/dist/ui/index.js +15 -4
  175. package/dist/ui/layout/index.d.ts +9 -1
  176. package/dist/ui/layout/index.js +11 -2
  177. package/dist/ui/styles/index.d.ts +21 -1
  178. package/dist/ui/styles/index.js +73 -14
  179. package/dist/ui/tokens/index.d.ts +5 -4
  180. package/dist/ui/tokens/index.js +12 -7
  181. package/locales/en-GB.json +39 -2
  182. package/locales/en-US.json +39 -2
  183. package/locales/fr.json +39 -2
  184. package/locales/ja.json +39 -2
  185. package/locales/ko.json +39 -2
  186. package/locales/zh-Hans.json +39 -2
  187. package/locales/zh-Hant.json +39 -2
  188. package/package.json +27 -18
  189. package/dist/ui/icons/images/brush.js +0 -3
  190. package/dist/ui/icons/images/circle-mask.js +0 -3
  191. package/dist/ui/icons/images/clipboard.js +0 -3
  192. package/dist/ui/icons/images/cursor.js +0 -3
  193. package/dist/ui/icons/images/eraser.js +0 -3
  194. package/dist/ui/icons/images/eyedropper.js +0 -3
  195. package/dist/ui/icons/images/flip-horizontal.js +0 -3
  196. package/dist/ui/icons/images/flip-vertical.js +0 -3
  197. package/dist/ui/icons/images/focus-pen.js +0 -3
  198. package/dist/ui/icons/images/freehand-mask.js +0 -3
  199. package/dist/ui/icons/images/hidden.js +0 -3
  200. package/dist/ui/icons/images/layers.js +0 -3
  201. package/dist/ui/icons/images/linked.js +0 -3
  202. package/dist/ui/icons/images/locked.js +0 -3
  203. package/dist/ui/icons/images/moon.js +0 -3
  204. package/dist/ui/icons/images/pan.js +0 -3
  205. package/dist/ui/icons/images/polygon-mask.js +0 -3
  206. package/dist/ui/icons/images/pressure.js +0 -3
  207. package/dist/ui/icons/images/randomise.js +0 -3
  208. package/dist/ui/icons/images/rectangle-mask.js +0 -3
  209. package/dist/ui/icons/images/redo.js +0 -3
  210. package/dist/ui/icons/images/rotate-90-left.js +0 -3
  211. package/dist/ui/icons/images/rotate-90-right.js +0 -3
  212. package/dist/ui/icons/images/smoothing-bezier-cubic.js +0 -3
  213. package/dist/ui/icons/images/smoothing-bezier-quad.js +0 -3
  214. package/dist/ui/icons/images/smoothing-linear.js +0 -3
  215. package/dist/ui/icons/images/star.js +0 -3
  216. package/dist/ui/icons/images/sun.js +0 -3
  217. package/dist/ui/icons/images/tilt.js +0 -3
  218. package/dist/ui/icons/images/undo.js +0 -3
  219. package/dist/ui/icons/images/unlinked.js +0 -3
  220. package/dist/ui/icons/images/unlocked.js +0 -3
  221. package/dist/ui/icons/images/visible.js +0 -3
  222. package/dist/ui/icons/images/zoom-in.js +0 -3
  223. package/dist/ui/icons/images/zoom-out.js +0 -3
  224. package/dist/ui/icons/images/zoom.js +0 -3
@@ -6,7 +6,9 @@ var zh_Hant_default = {
6
6
  "paintCanvas.common.save": "儲存",
7
7
  "paintCanvas.common.delete": "刪除",
8
8
  "paintCanvas.common.clear": "清除",
9
+ "paintCanvas.common.cut": "剪下",
9
10
  "paintCanvas.common.copy": "拷貝",
11
+ "paintCanvas.common.copyMerged": "合併拷貝",
10
12
  "paintCanvas.common.paste": "貼上",
11
13
  "paintCanvas.common.undo": "復原",
12
14
  "paintCanvas.common.redo": "重做",
@@ -14,7 +16,33 @@ var zh_Hant_default = {
14
16
  "paintCanvas.common.moreInformation": "更多資訊",
15
17
  "paintCanvas.common.width": "寬度",
16
18
  "paintCanvas.common.height": "高度",
19
+ "paintCanvas.common.size": "大小",
17
20
  "paintCanvas.common.opacity": "不透明度",
21
+ "paintCanvas.range.low": "{label}(最小)",
22
+ "paintCanvas.range.high": "{label}(最大)",
23
+ "paintCanvas.profileGraph.point": "點 {number}:{x}, {y}",
24
+ "paintCanvas.profileGraph.remove": "刪除點",
25
+ "paintCanvas.profileGraph.linear": "尖角(線性)",
26
+ "paintCanvas.profileGraph.bezier": "平滑(三次貝茲)",
27
+ "paintCanvas.profiles.linear": "線性",
28
+ "paintCanvas.profiles.overweight": "偏重",
29
+ "paintCanvas.profiles.underweight": "偏輕",
30
+ "paintCanvas.profileEditor.title": "{param}曲線",
31
+ "paintCanvas.profileEditor.button": "{param}:曲線",
32
+ "paintCanvas.profileEditor.custom": "自訂",
33
+ "paintCanvas.profileEditor.actions": "曲線操作",
34
+ "paintCanvas.profileEditor.new": "新增曲線",
35
+ "paintCanvas.profileEditor.duplicate": "複製…",
36
+ "paintCanvas.profileEditor.rename": "重新命名…",
37
+ "paintCanvas.profileEditor.delete": "刪除…",
38
+ "paintCanvas.profileEditor.reset": "重設",
39
+ "paintCanvas.profileEditor.name": "名稱",
40
+ "paintCanvas.profileEditor.saveHeading": "儲存曲線",
41
+ "paintCanvas.profileEditor.renameHeading": "重新命名曲線",
42
+ "paintCanvas.profileEditor.deleteHeading": "刪除曲線",
43
+ "paintCanvas.profileEditor.deleteConfirm": "刪除「{name}」?此操作無法復原。",
44
+ "paintCanvas.profileEditor.replaceHeading": "取代曲線",
45
+ "paintCanvas.profileEditor.replaceConfirm": "已有名為「{name}」的曲線。要取代嗎?",
18
46
  "paintCanvas.tool.brush": "筆刷",
19
47
  "paintCanvas.tool.eraser": "橡皮擦",
20
48
  "paintCanvas.tool.move": "移動、縮放和旋轉",
@@ -62,6 +90,8 @@ var zh_Hant_default = {
62
90
  "paintCanvas.toolSettings.presets": "{tool}預設",
63
91
  "paintCanvas.toolSettings.configure": "詳細設定",
64
92
  "paintCanvas.toolSettings.constrainProportions": "維持比例",
93
+ "paintCanvas.toolSettings.sizeSettings": "尺寸設定",
94
+ "paintCanvas.toolSettings.moreActions": "更多操作",
65
95
  "paintCanvas.toolSettings.pressure": "壓力感應",
66
96
  "paintCanvas.toolSettings.tilt": "傾斜",
67
97
  "paintCanvas.toolSettings.focusPen": "僅限觸控筆模式",
@@ -77,7 +107,7 @@ var zh_Hant_default = {
77
107
  "paintCanvas.toolSettings.areaSample": "區域平均取色",
78
108
  "paintCanvas.brushMenu.presets": "{tool}預設",
79
109
  "paintCanvas.brushMenu.size": "{tool}大小",
80
- "paintCanvas.brushMenu.dragToResize": "左右拖曳以調整大小",
110
+ "paintCanvas.numberSlider.hint": "左右拖曳以變更,點一下以輸入",
81
111
  "paintCanvas.brushMenu.newPreset": "新預設",
82
112
  "paintCanvas.brushMenu.create": "建立",
83
113
  "paintCanvas.brushMenu.import": "匯入",
@@ -85,6 +115,9 @@ var zh_Hant_default = {
85
115
  "paintCanvas.presets.myPresets": "我的預設",
86
116
  "paintCanvas.presets.unknownAuthor": "未知",
87
117
  "paintCanvas.presets.deleteConfirm": "要刪除「{name}」嗎?此動作無法復原。",
118
+ "paintCanvas.presets.deleteHeading": "刪除預設",
119
+ "paintCanvas.presets.replaceHeading": "取代預設",
120
+ "paintCanvas.presets.replace": "取代",
88
121
  "paintCanvas.presets.deleted": "已刪除「{name}」",
89
122
  "paintCanvas.presets.deleteFailed": "無法刪除「{name}」",
90
123
  "paintCanvas.presets.saved": "已將「{name}」儲存到我的預設",
@@ -100,6 +133,8 @@ var zh_Hant_default = {
100
133
  "paintCanvas.brushConfig.eraserTitle": "橡皮擦詳細設定",
101
134
  "paintCanvas.brushConfig.presetName": "預設名稱",
102
135
  "paintCanvas.brushConfig.shape": "形狀",
136
+ "paintCanvas.brushConfig.chooseShape": "選擇形狀",
137
+ "paintCanvas.brushConfig.customShape": "自訂",
103
138
  "paintCanvas.brushConfig.upload": "上傳",
104
139
  "paintCanvas.brushConfig.paste": "貼上",
105
140
  "paintCanvas.brushConfig.rotation": "旋轉",
@@ -116,6 +151,7 @@ var zh_Hant_default = {
116
151
  "paintCanvas.brushConfig.shapeFailed": "無法使用此筆刷形狀",
117
152
  "paintCanvas.brushConfig.test": "試畫",
118
153
  "paintCanvas.brushConfig.testArea": "筆刷試畫區域",
154
+ "paintCanvas.brushConfig.showStrokePoints": "顯示筆畫點",
119
155
  "paintCanvas.shape.notPng": "筆刷形狀必須是 PNG 影像",
120
156
  "paintCanvas.shape.tooLarge": "筆刷形狀影像最大為 2 MB",
121
157
  "paintCanvas.shape.readFailed": "無法讀取筆刷形狀影像",
@@ -175,6 +211,7 @@ var zh_Hant_default = {
175
211
  "paintCanvas.brushConfig.snapToPixelGrid": "對齊像素格線",
176
212
  "paintCanvas.brushConfig.addToPresets": "加入預設",
177
213
  "paintCanvas.brushConfig.variation": "{param}:{source}",
214
+ "paintCanvas.brushConfig.varyWith": "{param}:變化依據",
178
215
  "paintCanvas.layers.mergeDownTitle": "向下合併",
179
216
  "paintCanvas.layers.clear": "清除…",
180
217
  "paintCanvas.layers.delete": "刪除…",
@@ -262,6 +299,6 @@ var zh_Hant_default = {
262
299
  "paintCanvas.theme.label": "主題",
263
300
  "paintCanvas.theme.light": "淺色",
264
301
  "paintCanvas.theme.dark": "深色",
265
- "paintCanvas.theme.auto": "自動"
302
+ "paintCanvas.theme.system": "跟隨系統"
266
303
  };
267
304
  export { zh_Hant_default as default };
package/dist/package.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // package.json
2
- var version = "0.4.0";
2
+ var version = "0.6.0";
3
3
  export { version };
@@ -12,7 +12,8 @@ var createRecordingCanvasFactory = () => {
12
12
  const canvas = {
13
13
  width,
14
14
  height,
15
- getContext: () => ctx
15
+ getContext: () => ctx,
16
+ convertToBlob: async ({ type = "image/png" } = {}) => new Blob([], { type })
16
17
  };
17
18
  created.push({
18
19
  canvas,
@@ -0,0 +1,48 @@
1
+ import "../elements/PcDialog";
2
+ import type Translations from "../../lib/i18n";
3
+ import { type DialogField } from "../elements/PcDialog";
4
+ /** The choice that agrees, in the dialogs `askConfirm` and `askText` show */
5
+ export declare const OK_CHOICE = "ok";
6
+ /** What to ask */
7
+ export interface AskOptions {
8
+ heading: string;
9
+ message?: string;
10
+ /** The button that agrees */
11
+ confirm: string;
12
+ /** The button that doesn't */
13
+ cancel: string;
14
+ /** Whether agreeing removes or replaces something (the button is pink) */
15
+ cancelling?: boolean;
16
+ }
17
+ /** What to ask for text: as `AskOptions`, with the field's label and the text it starts with */
18
+ export interface AskTextOptions extends AskOptions, DialogField {
19
+ }
20
+ /** Asks the user to confirm, resolving true if they agree */
21
+ export type ConfirmFn = (options: AskOptions) => boolean | Promise<boolean>;
22
+ /** Asks the user for text, resolving with it, or null if they don't give it */
23
+ export type PromptFn = (options: AskTextOptions) => string | null | Promise<string | null>;
24
+ /**
25
+ * Ask the user to confirm in a dialog shown in `parent`, resolving true if they agree (false for the cancel button,
26
+ * Escape or a press outside it).
27
+ *
28
+ * @example
29
+ * if (await askConfirm(this.renderRoot, { heading: "Delete preset", message: 'Delete "Ink"?', confirm: "Delete",
30
+ * cancel: "Cancel", cancelling: true })) remove();
31
+ */
32
+ export declare const askConfirm: (parent: Node, options: AskOptions) => Promise<boolean>;
33
+ /**
34
+ * Ask the user for text in a dialog shown in `parent`, resolving with what they typed when they agree (or press Enter),
35
+ * or null if they cancel.
36
+ *
37
+ * @example
38
+ * const name = await askText(this.renderRoot, { heading: "Add to presets", label: "Name", value: "Ink",
39
+ * confirm: "Save", cancel: "Cancel" });
40
+ */
41
+ export declare const askText: (parent: Node, { label, value, ...options }: AskTextOptions) => Promise<string | null>;
42
+ /**
43
+ * The question asked before deleting one of the user's brush presets, in the chosen language.
44
+ *
45
+ * @example
46
+ * await askConfirm(this.renderRoot, deletePresetQuestion(this.translations, "Ink"));
47
+ */
48
+ export declare const deletePresetQuestion: (translations: Pick<Translations, "t">, name: string) => AskOptions;
@@ -0,0 +1,67 @@
1
+ import { CANCEL_CHOICE } from "../elements/PcDialog/index.js";
2
+ // src/ui/ask/index.ts
3
+ /** The choice that agrees, in the dialogs `askConfirm` and `askText` show */
4
+ var OK_CHOICE = "ok";
5
+ /**
6
+ * Show a dialog in a parent (e.g. an element's shadow root) until the user chooses, then remove it. The choice doesn't
7
+ * reach the parent's listeners.
8
+ */
9
+ var ask = (parent, options, field) => new Promise((resolve) => {
10
+ const dialog = document.createElement("pc-dialog");
11
+ dialog.heading = options.heading;
12
+ dialog.message = options.message ?? "";
13
+ dialog.field = field;
14
+ dialog.choices = [{
15
+ value: "ok",
16
+ label: options.confirm,
17
+ cancelling: options.cancelling
18
+ }, {
19
+ value: CANCEL_CHOICE,
20
+ label: options.cancel,
21
+ variant: "dismiss"
22
+ }];
23
+ dialog.addEventListener("pc-choose", (event) => {
24
+ event.stopPropagation();
25
+ dialog.remove();
26
+ resolve(event.detail);
27
+ }, { once: true });
28
+ parent.appendChild(dialog);
29
+ });
30
+ /**
31
+ * Ask the user to confirm in a dialog shown in `parent`, resolving true if they agree (false for the cancel button,
32
+ * Escape or a press outside it).
33
+ *
34
+ * @example
35
+ * if (await askConfirm(this.renderRoot, { heading: "Delete preset", message: 'Delete "Ink"?', confirm: "Delete",
36
+ * cancel: "Cancel", cancelling: true })) remove();
37
+ */
38
+ var askConfirm = async (parent, options) => (await ask(parent, options)).value === "ok";
39
+ /**
40
+ * Ask the user for text in a dialog shown in `parent`, resolving with what they typed when they agree (or press Enter),
41
+ * or null if they cancel.
42
+ *
43
+ * @example
44
+ * const name = await askText(this.renderRoot, { heading: "Add to presets", label: "Name", value: "Ink",
45
+ * confirm: "Save", cancel: "Cancel" });
46
+ */
47
+ var askText = async (parent, { label, value, ...options }) => {
48
+ const choice = await ask(parent, options, {
49
+ label,
50
+ value
51
+ });
52
+ return choice.value === "ok" ? choice.text : null;
53
+ };
54
+ /**
55
+ * The question asked before deleting one of the user's brush presets, in the chosen language.
56
+ *
57
+ * @example
58
+ * await askConfirm(this.renderRoot, deletePresetQuestion(this.translations, "Ink"));
59
+ */
60
+ var deletePresetQuestion = (translations, name) => ({
61
+ heading: translations.t("paintCanvas.presets.deleteHeading"),
62
+ message: translations.t("paintCanvas.presets.deleteConfirm", { name }),
63
+ confirm: translations.t("paintCanvas.common.delete"),
64
+ cancel: translations.t("paintCanvas.common.cancel"),
65
+ cancelling: true
66
+ });
67
+ export { OK_CHOICE, askConfirm, askText, deletePresetQuestion };
@@ -16,8 +16,15 @@ export declare const defineElement: (name: string, constructor: CustomElementCon
16
16
  * emit(this, "pc-select", { value: "duplicate" });
17
17
  */
18
18
  export declare const emit: <T>(target: EventTarget, type: string, detail?: T) => boolean;
19
+ /** The least font size of form fields on touch screens: iOS zooms the page in on fields with smaller text */
20
+ export declare const TOUCH_FIELD_FONT_SIZE = "16px";
19
21
  /**
20
- * The base of PaintCanvas's elements: the design tokens, the translations and icons they use (shared ones unless
22
+ * Form fields' text on touch screens: at least 16px, so iOS doesn't zoom the page in when one is focused (which is
23
+ * hard to undo). It wins over elements' own field sizes, as zooming makes the whole interface hard to use.
24
+ */
25
+ export declare const touchFields: import("lit").CSSResult;
26
+ /**
27
+ * The base of PaintCanvas's elements: the design tokens, 16px form fields on touch screens (see `touchFields`), the translations and icons they use (shared ones unless
21
28
  * given others), and re-rendering when either changes.
22
29
  *
23
30
  * @example
@@ -45,8 +52,8 @@ export declare class PcElement extends LitElement {
45
52
  translations: Translations;
46
53
  /** The icons the element shows */
47
54
  icons: IconRegistry;
48
- /** "light" (default), "dark", or "auto" to follow the device (see the design tokens) */
49
- theme?: "light" | "dark" | "auto";
55
+ /** "light", "dark", or "system" to follow the device (see the design tokens). Without one, it has its ancestors' theme. */
56
+ theme?: "light" | "dark" | "system";
50
57
  /** The translations and icons being listened to */
51
58
  private watched;
52
59
  private readonly onSourceChange;
@@ -1,7 +1,7 @@
1
1
  import { installTokens, tokens } from "../tokens/index.js";
2
2
  import { icons } from "../icons/index.js";
3
3
  import { translations } from "../../lib/i18n/index.js";
4
- import { LitElement } from "lit";
4
+ import { LitElement, css, unsafeCSS } from "lit";
5
5
  // src/ui/base/index.ts
6
6
  /**
7
7
  * Register a custom element unless the name is already registered (e.g. by another copy of PaintCanvas, or after hot
@@ -25,8 +25,23 @@ var emit = (target, type, detail) => target.dispatchEvent(new CustomEvent(type,
25
25
  composed: true,
26
26
  cancelable: true
27
27
  }));
28
+ /** The least font size of form fields on touch screens: iOS zooms the page in on fields with smaller text */
29
+ var TOUCH_FIELD_FONT_SIZE = "16px";
28
30
  /**
29
- * The base of PaintCanvas's elements: the design tokens, the translations and icons they use (shared ones unless
31
+ * Form fields' text on touch screens: at least 16px, so iOS doesn't zoom the page in when one is focused (which is
32
+ * hard to undo). It wins over elements' own field sizes, as zooming makes the whole interface hard to use.
33
+ */
34
+ var touchFields = css`
35
+ @media (pointer: coarse) {
36
+ input,
37
+ select,
38
+ textarea {
39
+ font-size: max(${unsafeCSS(TOUCH_FIELD_FONT_SIZE)}, 1em) !important;
40
+ }
41
+ }
42
+ `;
43
+ /**
44
+ * The base of PaintCanvas's elements: the design tokens, 16px form fields on touch screens (see `touchFields`), the translations and icons they use (shared ones unless
30
45
  * given others), and re-rendering when either changes.
31
46
  *
32
47
  * @example
@@ -37,7 +52,7 @@ var emit = (target, type, detail) => target.dispatchEvent(new CustomEvent(type,
37
52
  * }
38
53
  */
39
54
  var PcElement = class extends LitElement {
40
- static styles = [tokens];
55
+ static styles = [tokens, touchFields];
41
56
  static properties = {
42
57
  translations: { attribute: false },
43
58
  icons: { attribute: false },
@@ -91,4 +106,4 @@ var PcElement = class extends LitElement {
91
106
  this.watched = [];
92
107
  }
93
108
  };
94
- export { PcElement, defineElement, emit };
109
+ export { PcElement, TOUCH_FIELD_FONT_SIZE, defineElement, emit, touchFields };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Note that a press closed a panel or menu (by landing outside it), so what it landed on can treat it differently, e.g.
3
+ * the canvas only draws once it's dragged (see `isDismissingPress`). Call it from a capturing `pointerdown` listener,
4
+ * which runs before the listeners of what was pressed.
5
+ *
6
+ * @example
7
+ * document.addEventListener("pointerdown", (event) => {
8
+ * if (open && !event.composedPath().includes(panel)) {
9
+ * markDismissingPress(event);
10
+ * close();
11
+ * }
12
+ * }, true);
13
+ */
14
+ export declare const markDismissingPress: (event: Event) => void;
15
+ /**
16
+ * Whether a press closed a panel or menu (see `markDismissingPress`).
17
+ *
18
+ * @example
19
+ * if (isDismissingPress(event)) return; // just closing something
20
+ */
21
+ export declare const isDismissingPress: (event: Event) => boolean;
@@ -0,0 +1,27 @@
1
+ // src/ui/dismiss/index.ts
2
+ /** Presses that closed a panel or menu by landing outside it */
3
+ var dismissingPresses = /* @__PURE__ */ new WeakSet();
4
+ /**
5
+ * Note that a press closed a panel or menu (by landing outside it), so what it landed on can treat it differently, e.g.
6
+ * the canvas only draws once it's dragged (see `isDismissingPress`). Call it from a capturing `pointerdown` listener,
7
+ * which runs before the listeners of what was pressed.
8
+ *
9
+ * @example
10
+ * document.addEventListener("pointerdown", (event) => {
11
+ * if (open && !event.composedPath().includes(panel)) {
12
+ * markDismissingPress(event);
13
+ * close();
14
+ * }
15
+ * }, true);
16
+ */
17
+ var markDismissingPress = (event) => {
18
+ dismissingPresses.add(event);
19
+ };
20
+ /**
21
+ * Whether a press closed a panel or menu (see `markDismissingPress`).
22
+ *
23
+ * @example
24
+ * if (isDismissingPress(event)) return; // just closing something
25
+ */
26
+ var isDismissingPress = (event) => dismissingPresses.has(event);
27
+ export { isDismissingPress, markDismissingPress };
@@ -0,0 +1,51 @@
1
+ /** How far (in pixels) a press must move before it counts as a drag, where a press can also be a tap */
2
+ export declare const DRAG_THRESHOLD = 4;
3
+ /** A pointer position in the viewport */
4
+ interface Point {
5
+ x: number;
6
+ y: number;
7
+ }
8
+ /**
9
+ * How much a pointer moved between two points as one value: right and up are positive, left and down negative.
10
+ *
11
+ * @example
12
+ * dragDelta({ x: 0, y: 0 }, { x: 5, y: -5 }); // 10
13
+ */
14
+ export declare const dragDelta: (from: Point, to: Point) => number;
15
+ /**
16
+ * Turns pressing and dragging on an element into changes of a value: dragging right or up gives positive deltas, left
17
+ * or down negative ones (see `dragDelta`), in whole pixels (keeping any fraction for the next move). With a `threshold`, the press only becomes a drag once the pointer has moved
18
+ * that far from where it was pressed, so a press that barely moves can still be a tap (e.g. to focus a field).
19
+ *
20
+ * The element is given the pointer while dragging, so the drag carries on outside it.
21
+ *
22
+ * @example
23
+ * const drag = new PointerDrag((delta) => brush.resize(delta));
24
+ * html`<div @pointerdown=${drag.start} @pointermove=${drag.move} @pointerup=${drag.end} @pointercancel=${drag.end}></div>`
25
+ */
26
+ export declare class PointerDrag {
27
+ private readonly onDelta;
28
+ private readonly threshold;
29
+ /** Where the press started */
30
+ private origin;
31
+ /** The last position a delta was given from, once dragging */
32
+ private last;
33
+ /** Movement not yet given, under a whole pixel (pens can move by fractions of a pixel) */
34
+ private remainder;
35
+ constructor(onDelta: (delta: number) => void, threshold?: number);
36
+ /** Whether the press has become a drag */
37
+ get dragging(): boolean;
38
+ /**
39
+ * Start a press (on `pointerdown`).
40
+ */
41
+ readonly start: (event: PointerEvent) => void;
42
+ /**
43
+ * Give the change since the last move, once the press has become a drag (on `pointermove`).
44
+ */
45
+ readonly move: (event: PointerEvent) => void;
46
+ /**
47
+ * End the press (on `pointerup` or `pointercancel`). Returns whether it was a drag.
48
+ */
49
+ readonly end: () => boolean;
50
+ }
51
+ export {};
@@ -0,0 +1,81 @@
1
+ // src/ui/drag/index.ts
2
+ /** How far (in pixels) a press must move before it counts as a drag, where a press can also be a tap */
3
+ var DRAG_THRESHOLD = 4;
4
+ /**
5
+ * How much a pointer moved between two points as one value: right and up are positive, left and down negative.
6
+ *
7
+ * @example
8
+ * dragDelta({ x: 0, y: 0 }, { x: 5, y: -5 }); // 10
9
+ */
10
+ var dragDelta = (from, to) => to.x - from.x + (from.y - to.y);
11
+ /**
12
+ * Turns pressing and dragging on an element into changes of a value: dragging right or up gives positive deltas, left
13
+ * or down negative ones (see `dragDelta`), in whole pixels (keeping any fraction for the next move). With a `threshold`, the press only becomes a drag once the pointer has moved
14
+ * that far from where it was pressed, so a press that barely moves can still be a tap (e.g. to focus a field).
15
+ *
16
+ * The element is given the pointer while dragging, so the drag carries on outside it.
17
+ *
18
+ * @example
19
+ * const drag = new PointerDrag((delta) => brush.resize(delta));
20
+ * html`<div @pointerdown=${drag.start} @pointermove=${drag.move} @pointerup=${drag.end} @pointercancel=${drag.end}></div>`
21
+ */
22
+ var PointerDrag = class {
23
+ onDelta;
24
+ threshold;
25
+ /** Where the press started */
26
+ origin = null;
27
+ /** The last position a delta was given from, once dragging */
28
+ last = null;
29
+ /** Movement not yet given, under a whole pixel (pens can move by fractions of a pixel) */
30
+ remainder = 0;
31
+ constructor(onDelta, threshold = 0) {
32
+ this.onDelta = onDelta;
33
+ this.threshold = threshold;
34
+ }
35
+ /** Whether the press has become a drag */
36
+ get dragging() {
37
+ return this.last !== null;
38
+ }
39
+ /**
40
+ * Start a press (on `pointerdown`).
41
+ */
42
+ start = (event) => {
43
+ this.origin = {
44
+ x: event.clientX,
45
+ y: event.clientY
46
+ };
47
+ this.last = this.threshold > 0 ? null : this.origin;
48
+ this.remainder = 0;
49
+ event.currentTarget.setPointerCapture?.(event.pointerId);
50
+ };
51
+ /**
52
+ * Give the change since the last move, once the press has become a drag (on `pointermove`).
53
+ */
54
+ move = (event) => {
55
+ if (!this.origin) return;
56
+ const point = {
57
+ x: event.clientX,
58
+ y: event.clientY
59
+ };
60
+ if (!this.last) {
61
+ if (Math.hypot(point.x - this.origin.x, point.y - this.origin.y) < this.threshold) return;
62
+ this.last = this.origin;
63
+ event.preventDefault();
64
+ }
65
+ const total = this.remainder + dragDelta(this.last, point);
66
+ const delta = Math.trunc(total);
67
+ this.remainder = total - delta;
68
+ this.last = point;
69
+ if (delta !== 0) this.onDelta(delta);
70
+ };
71
+ /**
72
+ * End the press (on `pointerup` or `pointercancel`). Returns whether it was a drag.
73
+ */
74
+ end = () => {
75
+ const dragged = this.dragging;
76
+ this.origin = null;
77
+ this.last = null;
78
+ return dragged;
79
+ };
80
+ };
81
+ export { DRAG_THRESHOLD, PointerDrag, dragDelta };
@@ -5,8 +5,8 @@ import type { BrushConfig } from "../../../lib/brushes/types";
5
5
  import { type SaveMethod } from "../../../lib/rendering/screenshot";
6
6
  import { type InputKind, type LayoutState } from "../../layout";
7
7
  import "../PcPanel";
8
- import "../PcToolbar";
9
8
  import "../PcToolSettings";
9
+ import "../PcClipboardTools";
10
10
  import "../PcCanvas";
11
11
  import "../PcCanvasMap";
12
12
  import "../PcPanelBrushes";
@@ -20,8 +20,10 @@ import "../PcDialog";
20
20
  * window), with slots to add or replace content:
21
21
  *
22
22
  * - `header`: across the top (empty by default)
23
- * - `left`: `<pc-toolbar>` (a pane) by default
24
- * - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) by default
23
+ * - `left`: `<pc-toolbar>` (a pane) by default; toolbars in the sides are minimised (their tools one button that opens a
24
+ * menu of them) while the layout is narrow
25
+ * - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) and, at its end,
26
+ * `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow) by default
25
27
  * - `right`: a `<pc-pane>` with `<pc-panel-layers>` by default
26
28
  * - `center`: `<pc-canvas>` by default
27
29
  * - `overlay`: drawn over the canvas; `<pc-canvas-map>` by default
@@ -35,8 +37,9 @@ import "../PcDialog";
35
37
  *
36
38
  * Each side has a mode, chosen by the layout's width from `left-modes` and `right-modes` (default `"docked,
37
39
  * rail@600"`), which the layout gives the side's `<pc-pane>`s (see `PcPane`): `docked` beside the canvas; `rail`, a
38
- * column of buttons (one per panel) that open each panel over the canvas; or `floating`, the pane over the canvas as a
39
- * box that collapses to a button. Give side content in a `<pc-pane>` to have it follow the side's mode.
40
+ * column of buttons (one per panel) that open each panel over the canvas; `floating`, the pane over the canvas as a
41
+ * box that collapses to a button; or `overlay`, a rail over the canvas without a background (the canvas fills the
42
+ * width behind it). Give side content in a `<pc-pane>` to have it follow the side's mode.
40
43
  *
41
44
  * Reports its state for styling as attributes (`narrow`, `input="pen|touch|mouse"`, `ui-hidden`, `left-mode`,
42
45
  * `right-mode`) and as `pc-state-change` events (see `LayoutState`). Creates its own canvas unless given one, and
@@ -46,8 +49,8 @@ import "../PcDialog";
46
49
  * reloading the page (see `LayerAutosave`). While another window is drawing on it, the layout is blocked by a message
47
50
  * that offers to draw here instead. Fires `pc-toast` when the drawing can't be loaded or saved.
48
51
  *
49
- * With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette and
50
- * colours) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when they can't be.
52
+ * With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette, colours,
53
+ * theme and language) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when they can't be.
51
54
  *
52
55
  * @example
53
56
  * html`<paint-canvas style="height: 600px"></paint-canvas>`
@@ -163,7 +166,7 @@ export declare class PaintCanvasElement extends PcElement {
163
166
  private keys?;
164
167
  /** The state last reported, to report only changes */
165
168
  private reported?;
166
- /** Space the floating sides cover over the canvas */
169
+ /** Space the floating and overlay sides cover over the canvas */
167
170
  private floatingInsets;
168
171
  private readonly resizeObserver?;
169
172
  private readonly onPointerDown;
@@ -185,9 +188,9 @@ export declare class PaintCanvasElement extends PcElement {
185
188
  protected updated(): void;
186
189
  /** The panes in a side: the default one, or those given for it */
187
190
  private panesIn;
188
- /** Show each side's panes in the side's mode, facing the canvas */
191
+ /** Show each side's panes in the side's mode, facing the canvas, with toolbars minimised while the layout is narrow */
189
192
  private setPaneModes;
190
- /** Keep the canvas clear of floating sides when fitting it */
193
+ /** Keep the canvas clear of floating and overlay sides when fitting it */
191
194
  private measureFloatingSides;
192
195
  /**
193
196
  * Keep the canvas's layers under the `store` name, replacing an autosave the layout started earlier (also on the
@@ -238,9 +241,11 @@ export declare class PaintCanvasElement extends PcElement {
238
241
  /** A side: its panes, in its mode (set on them after rendering) */
239
242
  private renderSide;
240
243
  /**
241
- * Close the colour palette on a press outside it and the colours that open it.
244
+ * Close the open panel (brush, eraser, layers, app menu or colour palette) on a press outside it and the button that
245
+ * opens it, marking the press (see `markDismissingPress`) so the canvas doesn't draw unless it's dragged. Presses in
246
+ * dialogs (e.g. one the panel opened) don't count as outside.
242
247
  */
243
- private closePaletteOutside;
248
+ private closePanelOutside;
244
249
  /** The menus the toolbar opens, floating over the canvas beside it */
245
250
  private renderPanels;
246
251
  /** The brush configuration window, while open */