@heycys/gallery 0.0.0-stage → 0.1.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 (785) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -2
  3. package/THIRD-PARTY-NOTICES.md +3253 -0
  4. package/assets/writing-preferences.md +107 -0
  5. package/bin/gallery.mjs +10 -0
  6. package/browser/editor/components/bookmark/icons.mjs +6 -0
  7. package/browser/editor/components/bookmark/index.mjs +80 -0
  8. package/browser/editor/components/bookmark/page.mjs +147 -0
  9. package/browser/editor/components/builders.mjs +19 -0
  10. package/browser/editor/components/callout/index.mjs +39 -0
  11. package/browser/editor/components/callout/page.mjs +13 -0
  12. package/browser/editor/components/code/index.mjs +327 -0
  13. package/browser/editor/components/code/page.mjs +561 -0
  14. package/browser/editor/components/colors.mjs +50 -0
  15. package/browser/editor/components/columns/index.mjs +104 -0
  16. package/browser/editor/components/columns/page.mjs +297 -0
  17. package/browser/editor/components/details/index.mjs +72 -0
  18. package/browser/editor/components/details/page.mjs +86 -0
  19. package/browser/editor/components/dialog/index.mjs +83 -0
  20. package/browser/editor/components/dialog/page.mjs +219 -0
  21. package/browser/editor/components/divider/index.mjs +48 -0
  22. package/browser/editor/components/embed/icons.mjs +11 -0
  23. package/browser/editor/components/embed/index.mjs +123 -0
  24. package/browser/editor/components/embed/page.mjs +309 -0
  25. package/browser/editor/components/figure/index.mjs +87 -0
  26. package/browser/editor/components/figure/page.mjs +33 -0
  27. package/browser/editor/components/file/icons.mjs +14 -0
  28. package/browser/editor/components/file/index.mjs +77 -0
  29. package/browser/editor/components/file/page.mjs +114 -0
  30. package/browser/editor/components/flowchart/add.mjs +123 -0
  31. package/browser/editor/components/flowchart/index.mjs +246 -0
  32. package/browser/editor/components/flowchart/page.mjs +453 -0
  33. package/browser/editor/components/heading/index.mjs +51 -0
  34. package/browser/editor/components/highlight/index.mjs +79 -0
  35. package/browser/editor/components/icon/index.mjs +57 -0
  36. package/browser/editor/components/icon/page.mjs +286 -0
  37. package/browser/editor/components/icons.mjs +45 -0
  38. package/browser/editor/components/image/crop.mjs +189 -0
  39. package/browser/editor/components/image/index.mjs +104 -0
  40. package/browser/editor/components/image/page.mjs +385 -0
  41. package/browser/editor/components/image/viewer.mjs +213 -0
  42. package/browser/editor/components/installed/index.mjs +133 -0
  43. package/browser/editor/components/installed/page.mjs +422 -0
  44. package/browser/editor/components/installed/served.mjs +35 -0
  45. package/browser/editor/components/kit.mjs +64 -0
  46. package/browser/editor/components/list/index.mjs +194 -0
  47. package/browser/editor/components/list/join.mjs +68 -0
  48. package/browser/editor/components/list/numbers.mjs +107 -0
  49. package/browser/editor/components/list/page.mjs +632 -0
  50. package/browser/editor/components/math/index.mjs +88 -0
  51. package/browser/editor/components/math/page.mjs +236 -0
  52. package/browser/editor/components/math/tex-logo.mjs +6 -0
  53. package/browser/editor/components/media/icons.mjs +19 -0
  54. package/browser/editor/components/media/page.mjs +162 -0
  55. package/browser/editor/components/media/parts.mjs +60 -0
  56. package/browser/editor/components/media/size.mjs +20 -0
  57. package/browser/editor/components/media/toolbar.mjs +37 -0
  58. package/browser/editor/components/media/write.mjs +7 -0
  59. package/browser/editor/components/pages.mjs +46 -0
  60. package/browser/editor/components/paragraph/index.mjs +43 -0
  61. package/browser/editor/components/paragraph/page.mjs +52 -0
  62. package/browser/editor/components/placeholder-bar.mjs +17 -0
  63. package/browser/editor/components/placeholder.mjs +128 -0
  64. package/browser/editor/components/quote/index.mjs +33 -0
  65. package/browser/editor/components/registry.mjs +833 -0
  66. package/browser/editor/components/rows.mjs +16 -0
  67. package/browser/editor/components/section/index.mjs +41 -0
  68. package/browser/editor/components/section/page.mjs +141 -0
  69. package/browser/editor/components/sheets/index.mjs +137 -0
  70. package/browser/editor/components/sheets/page.mjs +227 -0
  71. package/browser/editor/components/sheets/pills.mjs +226 -0
  72. package/browser/editor/components/table/grid.mjs +73 -0
  73. package/browser/editor/components/table/index.mjs +306 -0
  74. package/browser/editor/components/table/page.mjs +672 -0
  75. package/browser/editor/components/table/slots.mjs +41 -0
  76. package/browser/editor/components/widget/index.mjs +50 -0
  77. package/browser/editor/page/annotate/anchors.mjs +229 -0
  78. package/browser/editor/page/annotate/card.mjs +102 -0
  79. package/browser/editor/page/annotate/index.mjs +1629 -0
  80. package/browser/editor/page/at-menu/index.mjs +317 -0
  81. package/browser/editor/page/autosave.mjs +977 -0
  82. package/browser/editor/page/beside.mjs +21 -0
  83. package/browser/editor/page/block-info.mjs +63 -0
  84. package/browser/editor/page/block-menu/colors.mjs +82 -0
  85. package/browser/editor/page/block-menu/index.mjs +215 -0
  86. package/browser/editor/page/blocks.mjs +246 -0
  87. package/browser/editor/page/caret.mjs +679 -0
  88. package/browser/editor/page/chip-fills.mjs +126 -0
  89. package/browser/editor/page/clipboard/import/colors.mjs +192 -0
  90. package/browser/editor/page/clipboard/import/html.mjs +792 -0
  91. package/browser/editor/page/clipboard/import/inline.mjs +232 -0
  92. package/browser/editor/page/clipboard/import/languages.mjs +42 -0
  93. package/browser/editor/page/clipboard/import/markdown.mjs +760 -0
  94. package/browser/editor/page/clipboard/import/math.mjs +100 -0
  95. package/browser/editor/page/clipboard/import/office.mjs +245 -0
  96. package/browser/editor/page/clipboard/import/read.mjs +120 -0
  97. package/browser/editor/page/clipboard/import/rich.mjs +29 -0
  98. package/browser/editor/page/clipboard/import/to-blocks.mjs +290 -0
  99. package/browser/editor/page/clipboard/index.mjs +797 -0
  100. package/browser/editor/page/clipboard/own/blocks.mjs +202 -0
  101. package/browser/editor/page/clipboard/own/chart-keys.mjs +58 -0
  102. package/browser/editor/page/clipboard/own/describe.mjs +115 -0
  103. package/browser/editor/page/clipboard/own/export.mjs +167 -0
  104. package/browser/editor/page/clipboard/own/ids.mjs +39 -0
  105. package/browser/editor/page/clipboard/own/index.mjs +13 -0
  106. package/browser/editor/page/clipboard/own/rules.mjs +44 -0
  107. package/browser/editor/page/clipboard/own/selection.mjs +159 -0
  108. package/browser/editor/page/clipboard/own/writers.mjs +326 -0
  109. package/browser/editor/page/columns/index.mjs +360 -0
  110. package/browser/editor/page/commit.mjs +1798 -0
  111. package/browser/editor/page/conflicts.mjs +269 -0
  112. package/browser/editor/page/convert.mjs +830 -0
  113. package/browser/editor/page/core.mjs +1655 -0
  114. package/browser/editor/page/drag/drop.mjs +307 -0
  115. package/browser/editor/page/drag/index.mjs +335 -0
  116. package/browser/editor/page/drag/preview.mjs +121 -0
  117. package/browser/editor/page/edge-scroll.mjs +50 -0
  118. package/browser/editor/page/editor.mjs +1725 -0
  119. package/browser/editor/page/emoji-picker/emoji-tab.mjs +278 -0
  120. package/browser/editor/page/emoji-picker/glyph-html.mjs +26 -0
  121. package/browser/editor/page/emoji-picker/grid.mjs +79 -0
  122. package/browser/editor/page/emoji-picker/icon-tab.mjs +217 -0
  123. package/browser/editor/page/emoji-picker/icons.mjs +32 -0
  124. package/browser/editor/page/emoji-picker/index.mjs +164 -0
  125. package/browser/editor/page/emoji-picker/styles.mjs +2 -0
  126. package/browser/editor/page/emoji-picker/support.mjs +202 -0
  127. package/browser/editor/page/emoji-picker/upload.mjs +235 -0
  128. package/browser/editor/page/export-report.mjs +23 -0
  129. package/browser/editor/page/fills.mjs +60 -0
  130. package/browser/editor/page/find/index.mjs +107 -0
  131. package/browser/editor/page/flags.mjs +70 -0
  132. package/browser/editor/page/format-bar/bar.mjs +448 -0
  133. package/browser/editor/page/format-bar/brush.mjs +77 -0
  134. package/browser/editor/page/format-bar/colors.mjs +46 -0
  135. package/browser/editor/page/format-bar/index.mjs +404 -0
  136. package/browser/editor/page/formula/index.mjs +236 -0
  137. package/browser/editor/page/formula/panel.mjs +336 -0
  138. package/browser/editor/page/formula/symbols.mjs +156 -0
  139. package/browser/editor/page/frame.mjs +74 -0
  140. package/browser/editor/page/frames.mjs +196 -0
  141. package/browser/editor/page/geometry.mjs +400 -0
  142. package/browser/editor/page/gesture.mjs +45 -0
  143. package/browser/editor/page/handle/index.mjs +639 -0
  144. package/browser/editor/page/handle-sizes.mjs +14 -0
  145. package/browser/editor/page/hints/index.mjs +84 -0
  146. package/browser/editor/page/history.mjs +401 -0
  147. package/browser/editor/page/insert/index.mjs +243 -0
  148. package/browser/editor/page/kept.mjs +38 -0
  149. package/browser/editor/page/links/address.mjs +40 -0
  150. package/browser/editor/page/links/index.mjs +866 -0
  151. package/browser/editor/page/links/pages.mjs +131 -0
  152. package/browser/editor/page/links/views.mjs +369 -0
  153. package/browser/editor/page/look.mjs +65 -0
  154. package/browser/editor/page/made.mjs +24 -0
  155. package/browser/editor/page/margin.mjs +352 -0
  156. package/browser/editor/page/markdown/index.mjs +88 -0
  157. package/browser/editor/page/markdown/rules.mjs +33 -0
  158. package/browser/editor/page/marks.mjs +377 -0
  159. package/browser/editor/page/media-menu/index.mjs +158 -0
  160. package/browser/editor/page/menu.mjs +500 -0
  161. package/browser/editor/page/merge.mjs +100 -0
  162. package/browser/editor/page/notices.mjs +142 -0
  163. package/browser/editor/page/offered.mjs +32 -0
  164. package/browser/editor/page/outline/folds.mjs +52 -0
  165. package/browser/editor/page/outline/index.mjs +697 -0
  166. package/browser/editor/page/outline/list.mjs +172 -0
  167. package/browser/editor/page/outline/read.mjs +201 -0
  168. package/browser/editor/page/outline/strip.mjs +281 -0
  169. package/browser/editor/page/outline/tree.mjs +248 -0
  170. package/browser/editor/page/overlay-layer.mjs +227 -0
  171. package/browser/editor/page/overlays.mjs +205 -0
  172. package/browser/editor/page/own.mjs +28 -0
  173. package/browser/editor/page/pads.mjs +71 -0
  174. package/browser/editor/page/page-objects.mjs +105 -0
  175. package/browser/editor/page/panel.mjs +64 -0
  176. package/browser/editor/page/placement.mjs +58 -0
  177. package/browser/editor/page/post.mjs +41 -0
  178. package/browser/editor/page/present-links.mjs +50 -0
  179. package/browser/editor/page/quiet.mjs +48 -0
  180. package/browser/editor/page/resize/index.mjs +327 -0
  181. package/browser/editor/page/select-all/index.mjs +262 -0
  182. package/browser/editor/page/selection/delete.mjs +59 -0
  183. package/browser/editor/page/selection/index.mjs +157 -0
  184. package/browser/editor/page/selection/marquee.mjs +174 -0
  185. package/browser/editor/page/session.mjs +117 -0
  186. package/browser/editor/page/slash-menu/index.mjs +291 -0
  187. package/browser/editor/page/storage.mjs +48 -0
  188. package/browser/editor/page/sync-state.mjs +267 -0
  189. package/browser/editor/page/table/aligns.mjs +29 -0
  190. package/browser/editor/page/table/cell-bar.mjs +138 -0
  191. package/browser/editor/page/table/cells.mjs +527 -0
  192. package/browser/editor/page/table/icons.mjs +40 -0
  193. package/browser/editor/page/table/index.mjs +985 -0
  194. package/browser/editor/page/table/lists.mjs +187 -0
  195. package/browser/editor/page/table/widths.mjs +308 -0
  196. package/browser/editor/page/tex.mjs +32 -0
  197. package/browser/editor/page/text-select/index.mjs +656 -0
  198. package/browser/editor/page/tooltip.mjs +98 -0
  199. package/browser/editor/page/type-grid.mjs +82 -0
  200. package/browser/editor/page/typing/code-edges.mjs +228 -0
  201. package/browser/editor/page/typing/index.mjs +276 -0
  202. package/browser/editor/page/typing/leave.mjs +68 -0
  203. package/browser/editor/page/ui.mjs +160 -0
  204. package/browser/shared/annotations.mjs +571 -0
  205. package/browser/shared/code-folds.mjs +10 -0
  206. package/browser/shared/code-languages.mjs +70 -0
  207. package/browser/shared/code-lines.mjs +30 -0
  208. package/browser/shared/colors.mjs +28 -0
  209. package/browser/shared/component-catalog.mjs +559 -0
  210. package/browser/shared/components/bookmark.mjs +26 -0
  211. package/browser/shared/components/callout.mjs +7 -0
  212. package/browser/shared/components/chart.mjs +20 -0
  213. package/browser/shared/components/code.mjs +37 -0
  214. package/browser/shared/components/columns.mjs +16 -0
  215. package/browser/shared/components/details.mjs +15 -0
  216. package/browser/shared/components/dialog.mjs +28 -0
  217. package/browser/shared/components/diff.mjs +18 -0
  218. package/browser/shared/components/divider.mjs +6 -0
  219. package/browser/shared/components/embed.mjs +25 -0
  220. package/browser/shared/components/figure.mjs +14 -0
  221. package/browser/shared/components/file.mjs +23 -0
  222. package/browser/shared/components/heading.mjs +6 -0
  223. package/browser/shared/components/highlight.mjs +9 -0
  224. package/browser/shared/components/icon.mjs +18 -0
  225. package/browser/shared/components/image.mjs +39 -0
  226. package/browser/shared/components/index.mjs +342 -0
  227. package/browser/shared/components/installed.mjs +162 -0
  228. package/browser/shared/components/list.mjs +146 -0
  229. package/browser/shared/components/math.mjs +49 -0
  230. package/browser/shared/components/mention.mjs +33 -0
  231. package/browser/shared/components/page.mjs +37 -0
  232. package/browser/shared/components/paragraph.mjs +9 -0
  233. package/browser/shared/components/quote.mjs +6 -0
  234. package/browser/shared/components/section.mjs +8 -0
  235. package/browser/shared/components/sheets.mjs +80 -0
  236. package/browser/shared/components/state.mjs +20 -0
  237. package/browser/shared/components/table.mjs +49 -0
  238. package/browser/shared/components/text.mjs +14 -0
  239. package/browser/shared/components/widget.mjs +10 -0
  240. package/browser/shared/copy-ids.mjs +72 -0
  241. package/browser/shared/css-references.mjs +110 -0
  242. package/browser/shared/emoji/custom.mjs +91 -0
  243. package/browser/shared/emoji/data/LICENSE-mingcute.txt +202 -0
  244. package/browser/shared/emoji/data/LICENSE-tabler.txt +21 -0
  245. package/browser/shared/emoji/data/README.md +26 -0
  246. package/browser/shared/emoji/data/categories.json +1 -0
  247. package/browser/shared/emoji/data/icons.json +1 -0
  248. package/browser/shared/emoji/data/keywords-en.json +1 -0
  249. package/browser/shared/emoji/data/keywords-zh.json +1 -0
  250. package/browser/shared/emoji/data/names.json +1 -0
  251. package/browser/shared/emoji/data/positions.json +1 -0
  252. package/browser/shared/emoji/data/twemoji-index.json +1 -0
  253. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  254. package/browser/shared/emoji/data.mjs +196 -0
  255. package/browser/shared/emoji/emoji.mjs +37 -0
  256. package/browser/shared/emoji/glyphs.mjs +134 -0
  257. package/browser/shared/emoji/icon-value.mjs +90 -0
  258. package/browser/shared/escape.mjs +20 -0
  259. package/browser/shared/export-wrap.mjs +89 -0
  260. package/browser/shared/files.mjs +33 -0
  261. package/browser/shared/html-tree.mjs +53 -0
  262. package/browser/shared/http.mjs +22 -0
  263. package/browser/shared/i18n/en.mjs +1164 -0
  264. package/browser/shared/i18n/index.mjs +132 -0
  265. package/browser/shared/ids.mjs +24 -0
  266. package/browser/shared/import-types.mjs +23 -0
  267. package/browser/shared/inline-spacing.mjs +97 -0
  268. package/browser/shared/layers.mjs +42 -0
  269. package/browser/shared/media.mjs +162 -0
  270. package/browser/shared/new-names.mjs +64 -0
  271. package/browser/shared/number-reading.mjs +92 -0
  272. package/browser/shared/old-names.mjs +143 -0
  273. package/browser/shared/page-address.mjs +140 -0
  274. package/browser/shared/page-links.mjs +86 -0
  275. package/browser/shared/paths.mjs +73 -0
  276. package/browser/shared/preferences.mjs +110 -0
  277. package/browser/shared/preview-server.mjs +247 -0
  278. package/browser/shared/qa-levels.mjs +93 -0
  279. package/browser/shared/reading-place.mjs +91 -0
  280. package/browser/shared/renamed-storage.mjs +220 -0
  281. package/browser/shared/reports.mjs +46 -0
  282. package/browser/shared/search.mjs +85 -0
  283. package/browser/shared/session.mjs +76 -0
  284. package/browser/shared/table-chart.mjs +113 -0
  285. package/browser/shared/table-hides.mjs +120 -0
  286. package/browser/shared/table-slots.mjs +75 -0
  287. package/browser/shared/words.mjs +23 -0
  288. package/browser/shared/workspace.mjs +535 -0
  289. package/browser/shared/writing-preferences.mjs +68 -0
  290. package/browser/shared/zoom.mjs +57 -0
  291. package/dist/chunk-2B5E4CDJ.mjs +2 -0
  292. package/dist/chunk-2PBALTR3.mjs +57 -0
  293. package/dist/chunk-342HXE3Q.mjs +2 -0
  294. package/dist/chunk-3LA3EMDE.mjs +15 -0
  295. package/dist/chunk-43B75J5T.mjs +2 -0
  296. package/dist/chunk-4K5KC6V2.mjs +2 -0
  297. package/dist/chunk-5FRMCDPY.mjs +16 -0
  298. package/dist/chunk-5L7RYZCL.mjs +2 -0
  299. package/dist/chunk-5LEK2CBS.mjs +2 -0
  300. package/dist/chunk-5OFN5AHC.mjs +2 -0
  301. package/dist/chunk-5SIYS5HN.mjs +2 -0
  302. package/dist/chunk-5TEK3RAD.mjs +2 -0
  303. package/dist/chunk-6CYG3Z4V.mjs +2 -0
  304. package/dist/chunk-6U2SLSDN.mjs +3 -0
  305. package/dist/chunk-742D2WWJ.mjs +19 -0
  306. package/dist/chunk-7GHT2UCA.mjs +15 -0
  307. package/dist/chunk-7QQBR7PB.mjs +2 -0
  308. package/dist/chunk-A55HN5OK.mjs +2 -0
  309. package/dist/chunk-ACOPDCNB.mjs +2 -0
  310. package/dist/chunk-AGDILNWB.mjs +2 -0
  311. package/dist/chunk-ATCJYAR4.mjs +2 -0
  312. package/dist/chunk-B3VTYBYR.mjs +960 -0
  313. package/dist/chunk-C564NU2H.mjs +77 -0
  314. package/dist/chunk-C7HWOBIF.mjs +2 -0
  315. package/dist/chunk-DB4WKGYF.mjs +7 -0
  316. package/dist/chunk-E7VYDG2X.mjs +2 -0
  317. package/dist/chunk-EUX7IC5J.mjs +48 -0
  318. package/dist/chunk-EVJ3BX3M.mjs +2 -0
  319. package/dist/chunk-EZY3WC6Z.mjs +15 -0
  320. package/dist/chunk-FQGQH4KM.mjs +2 -0
  321. package/dist/chunk-G7TOXONE.mjs +6 -0
  322. package/dist/chunk-GPF4YWWB.mjs +9 -0
  323. package/dist/chunk-GRAXKKG4.mjs +2 -0
  324. package/dist/chunk-GYQV7Y4J.mjs +120 -0
  325. package/dist/chunk-HMHK3EQ6.mjs +2 -0
  326. package/dist/chunk-HQQMJCQJ.mjs +10 -0
  327. package/dist/chunk-HYMEEXKN.mjs +4 -0
  328. package/dist/chunk-IERUOGC3.mjs +6 -0
  329. package/dist/chunk-ITNLYXXV.mjs +3 -0
  330. package/dist/chunk-L4DVONOG.mjs +2 -0
  331. package/dist/chunk-LAE5NQ4B.mjs +2 -0
  332. package/dist/chunk-LC7YNQFG.mjs +2 -0
  333. package/dist/chunk-LHTFLRB6.mjs +4 -0
  334. package/dist/chunk-LKX55H76.mjs +2 -0
  335. package/dist/chunk-MAFIGVXY.mjs +2 -0
  336. package/dist/chunk-NFIBI4IP.mjs +26 -0
  337. package/dist/chunk-NSKUTQ5J.mjs +5 -0
  338. package/dist/chunk-O52JMOCZ.mjs +2 -0
  339. package/dist/chunk-P2CAZPDP.mjs +3 -0
  340. package/dist/chunk-QAIHRH3I.mjs +13 -0
  341. package/dist/chunk-QMQUXTU4.mjs +12 -0
  342. package/dist/chunk-QR6A54KJ.mjs +3 -0
  343. package/dist/chunk-QVWVFC5K.mjs +6 -0
  344. package/dist/chunk-QYKCJ7FG.mjs +8 -0
  345. package/dist/chunk-QZY6Q64C.mjs +2 -0
  346. package/dist/chunk-TDQP3DKQ.mjs +10 -0
  347. package/dist/chunk-TMYZB6AV.mjs +2 -0
  348. package/dist/chunk-TX6JH7TR.mjs +2 -0
  349. package/dist/chunk-U3SSPL4K.mjs +8 -0
  350. package/dist/chunk-UH4SIXTR.mjs +2 -0
  351. package/dist/chunk-UNUEWH4S.mjs +2 -0
  352. package/dist/chunk-UXUK4PMC.mjs +27 -0
  353. package/dist/chunk-V4CPWKMZ.mjs +2 -0
  354. package/dist/chunk-V6XZ4VIR.mjs +2 -0
  355. package/dist/chunk-VACRB2NE.mjs +3 -0
  356. package/dist/chunk-W63L7367.mjs +7 -0
  357. package/dist/chunk-W7CXPCRV.mjs +6 -0
  358. package/dist/chunk-W7XHE4CT.mjs +2 -0
  359. package/dist/chunk-XINNG4F2.mjs +4 -0
  360. package/dist/chunk-Y34NR5JL.mjs +2 -0
  361. package/dist/chunk-YEY3RSFQ.mjs +2 -0
  362. package/dist/chunk-YL2DPWVS.mjs +4 -0
  363. package/dist/chunk-YXAUQPVK.mjs +8 -0
  364. package/dist/chunk-YZ5Z6H4W.mjs +4 -0
  365. package/dist/chunk-Z52HTUW7.mjs +4 -0
  366. package/dist/chunk-ZBIM6ARY.mjs +216 -0
  367. package/dist/cli.mjs +2 -0
  368. package/dist/server.mjs +2 -0
  369. package/dist/worker.mjs +5 -0
  370. package/kit/charts.js +355 -0
  371. package/kit/code.js +164 -0
  372. package/kit/dialogs.js +157 -0
  373. package/kit/math.js +1988 -0
  374. package/kit/report.css +2821 -0
  375. package/kit/runtime.js +1707 -0
  376. package/kit/sheets.js +123 -0
  377. package/kit/state.js +217 -0
  378. package/kit/tables.js +1449 -0
  379. package/kit/tokens.js +29 -0
  380. package/kit/ui.js +561 -0
  381. package/package.json +41 -4
  382. package/release.json +25 -0
  383. package/sdk/column-widths.d.ts +56 -0
  384. package/sdk/doc-charts.d.ts +82 -0
  385. package/sdk/doc-code.d.ts +28 -0
  386. package/sdk/doc-dialogs.d.ts +4 -0
  387. package/sdk/doc-kit.d.ts +141 -0
  388. package/sdk/doc-math.d.ts +3 -0
  389. package/sdk/doc-sheets.d.ts +15 -0
  390. package/sdk/doc-state.d.ts +41 -0
  391. package/sdk/doc-tables.d.ts +24 -0
  392. package/sdk/doc-tokens.d.ts +22 -0
  393. package/sdk/index.d.ts +30 -0
  394. package/skill/SKILL.md +138 -0
  395. package/skill/agents/openai.yaml +5 -0
  396. package/skill/references/building-components.md +327 -0
  397. package/skill/references/example-report.html +356 -0
  398. package/skill/references/writing-html.md +187 -0
  399. package/skill/sdk/column-widths.d.ts +56 -0
  400. package/skill/sdk/doc-charts.d.ts +82 -0
  401. package/skill/sdk/doc-code.d.ts +28 -0
  402. package/skill/sdk/doc-dialogs.d.ts +4 -0
  403. package/skill/sdk/doc-kit.d.ts +141 -0
  404. package/skill/sdk/doc-math.d.ts +3 -0
  405. package/skill/sdk/doc-sheets.d.ts +15 -0
  406. package/skill/sdk/doc-state.d.ts +41 -0
  407. package/skill/sdk/doc-tables.d.ts +24 -0
  408. package/skill/sdk/doc-tokens.d.ts +22 -0
  409. package/skill/sdk/index.d.ts +30 -0
  410. package/starter/doc.html +21 -0
  411. package/starter/doc.json +5 -0
  412. package/vendor/d3.v7.9.0.min.js +2 -0
  413. package/vendor/katex/auto-render.min.js +1 -0
  414. package/vendor/katex/contrib/mhchem.min.js +1 -0
  415. package/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  416. package/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  417. package/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  418. package/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  419. package/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  420. package/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  421. package/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  422. package/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  423. package/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  424. package/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  425. package/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  426. package/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  427. package/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  428. package/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  429. package/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  430. package/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  431. package/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  432. package/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  433. package/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  434. package/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  435. package/vendor/katex/katex.min.css +1 -0
  436. package/vendor/katex/katex.min.js +1 -0
  437. package/vendor/pdfjs/LICENSE +177 -0
  438. package/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  439. package/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  440. package/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  441. package/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  442. package/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  443. package/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  444. package/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  445. package/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  446. package/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  447. package/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  448. package/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  449. package/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  450. package/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  451. package/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  452. package/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  453. package/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  454. package/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  455. package/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  456. package/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  457. package/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  458. package/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  459. package/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  460. package/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  461. package/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  462. package/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  463. package/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  464. package/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  465. package/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  466. package/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  467. package/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  468. package/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  469. package/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  470. package/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  471. package/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  472. package/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  473. package/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  474. package/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  475. package/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  476. package/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  477. package/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  478. package/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  479. package/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  480. package/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  481. package/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  482. package/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  483. package/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  484. package/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  485. package/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  486. package/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  487. package/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  488. package/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  489. package/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  490. package/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  491. package/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  492. package/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  493. package/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  494. package/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  495. package/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  496. package/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  497. package/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  498. package/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  499. package/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  500. package/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  501. package/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  502. package/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  503. package/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  504. package/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  505. package/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  506. package/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  507. package/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  508. package/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  509. package/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  510. package/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  511. package/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  512. package/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  513. package/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  514. package/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  515. package/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  516. package/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  517. package/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  518. package/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  519. package/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  520. package/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  521. package/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  522. package/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  523. package/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  524. package/vendor/pdfjs/cmaps/H.bcmap +0 -0
  525. package/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  526. package/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  527. package/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  528. package/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  529. package/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  530. package/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  531. package/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  532. package/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  533. package/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  534. package/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  535. package/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  536. package/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  537. package/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  538. package/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  539. package/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  540. package/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  541. package/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  542. package/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  543. package/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  544. package/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  545. package/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  546. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  547. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  548. package/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  549. package/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  550. package/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  551. package/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  552. package/vendor/pdfjs/cmaps/LICENSE +36 -0
  553. package/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  554. package/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  555. package/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  556. package/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  557. package/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  558. package/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  559. package/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  560. package/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  561. package/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  562. package/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  563. package/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  564. package/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  565. package/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  566. package/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  567. package/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  568. package/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  569. package/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  570. package/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  571. package/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  572. package/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  573. package/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  574. package/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  575. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  576. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  577. package/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  578. package/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  579. package/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  580. package/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  581. package/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  582. package/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  583. package/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  584. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  585. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  586. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  587. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  588. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  589. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  590. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  591. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  592. package/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  593. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  594. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  595. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  596. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  597. package/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  598. package/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  599. package/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  600. package/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  601. package/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  602. package/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  603. package/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  604. package/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  605. package/vendor/pdfjs/cmaps/V.bcmap +0 -0
  606. package/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  607. package/vendor/pdfjs/legacy/build/pdf.min.mjs +27 -0
  608. package/vendor/pdfjs/legacy/build/pdf.worker.min.mjs +27 -0
  609. package/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  610. package/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  611. package/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  612. package/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  613. package/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  614. package/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  615. package/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  616. package/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  617. package/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  618. package/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  619. package/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  620. package/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  621. package/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  622. package/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  623. package/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  624. package/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  625. package/vendor/types/@types/d3/LICENSE +21 -0
  626. package/vendor/types/@types/d3/index.d.ts +39 -0
  627. package/vendor/types/@types/d3/package.json +81 -0
  628. package/vendor/types/@types/d3-array/LICENSE +21 -0
  629. package/vendor/types/@types/d3-array/index.d.ts +1118 -0
  630. package/vendor/types/@types/d3-array/package.json +56 -0
  631. package/vendor/types/@types/d3-axis/LICENSE +21 -0
  632. package/vendor/types/@types/d3-axis/index.d.ts +293 -0
  633. package/vendor/types/@types/d3-axis/package.json +47 -0
  634. package/vendor/types/@types/d3-brush/LICENSE +21 -0
  635. package/vendor/types/@types/d3-brush/index.d.ts +255 -0
  636. package/vendor/types/@types/d3-brush/package.json +42 -0
  637. package/vendor/types/@types/d3-chord/LICENSE +21 -0
  638. package/vendor/types/@types/d3-chord/index.d.ts +471 -0
  639. package/vendor/types/@types/d3-chord/package.json +40 -0
  640. package/vendor/types/@types/d3-color/LICENSE +21 -0
  641. package/vendor/types/@types/d3-color/index.d.ts +669 -0
  642. package/vendor/types/@types/d3-color/package.json +55 -0
  643. package/vendor/types/@types/d3-contour/LICENSE +21 -0
  644. package/vendor/types/@types/d3-contour/index.d.ts +222 -0
  645. package/vendor/types/@types/d3-contour/package.json +38 -0
  646. package/vendor/types/@types/d3-delaunay/LICENSE +21 -0
  647. package/vendor/types/@types/d3-delaunay/index.d.ts +316 -0
  648. package/vendor/types/@types/d3-delaunay/package.json +30 -0
  649. package/vendor/types/@types/d3-dispatch/LICENSE +21 -0
  650. package/vendor/types/@types/d3-dispatch/index.d.ts +96 -0
  651. package/vendor/types/@types/d3-dispatch/package.json +51 -0
  652. package/vendor/types/@types/d3-drag/LICENSE +21 -0
  653. package/vendor/types/@types/d3-drag/index.d.ts +395 -0
  654. package/vendor/types/@types/d3-drag/package.json +42 -0
  655. package/vendor/types/@types/d3-dsv/LICENSE +21 -0
  656. package/vendor/types/@types/d3-dsv/index.d.ts +482 -0
  657. package/vendor/types/@types/d3-dsv/package.json +45 -0
  658. package/vendor/types/@types/d3-ease/LICENSE +21 -0
  659. package/vendor/types/@types/d3-ease/index.d.ts +316 -0
  660. package/vendor/types/@types/d3-ease/package.json +40 -0
  661. package/vendor/types/@types/d3-fetch/LICENSE +21 -0
  662. package/vendor/types/@types/d3-fetch/index.d.ts +282 -0
  663. package/vendor/types/@types/d3-fetch/package.json +37 -0
  664. package/vendor/types/@types/d3-force/LICENSE +21 -0
  665. package/vendor/types/@types/d3-force/index.d.ts +899 -0
  666. package/vendor/types/@types/d3-force/package.json +45 -0
  667. package/vendor/types/@types/d3-format/LICENSE +21 -0
  668. package/vendor/types/@types/d3-format/index.d.ts +337 -0
  669. package/vendor/types/@types/d3-format/package.json +45 -0
  670. package/vendor/types/@types/d3-geo/LICENSE +21 -0
  671. package/vendor/types/@types/d3-geo/index.d.ts +1371 -0
  672. package/vendor/types/@types/d3-geo/package.json +48 -0
  673. package/vendor/types/@types/d3-hierarchy/LICENSE +21 -0
  674. package/vendor/types/@types/d3-hierarchy/index.d.ts +928 -0
  675. package/vendor/types/@types/d3-hierarchy/package.json +50 -0
  676. package/vendor/types/@types/d3-interpolate/LICENSE +21 -0
  677. package/vendor/types/@types/d3-interpolate/index.d.ts +387 -0
  678. package/vendor/types/@types/d3-interpolate/package.json +47 -0
  679. package/vendor/types/@types/d3-path/LICENSE +21 -0
  680. package/vendor/types/@types/d3-path/index.d.ts +108 -0
  681. package/vendor/types/@types/d3-path/package.json +41 -0
  682. package/vendor/types/@types/d3-polygon/LICENSE +21 -0
  683. package/vendor/types/@types/d3-polygon/index.d.ts +41 -0
  684. package/vendor/types/@types/d3-polygon/package.json +40 -0
  685. package/vendor/types/@types/d3-quadtree/LICENSE +21 -0
  686. package/vendor/types/@types/d3-quadtree/index.d.ts +204 -0
  687. package/vendor/types/@types/d3-quadtree/package.json +45 -0
  688. package/vendor/types/@types/d3-random/LICENSE +21 -0
  689. package/vendor/types/@types/d3-random/index.d.ts +313 -0
  690. package/vendor/types/@types/d3-random/package.json +41 -0
  691. package/vendor/types/@types/d3-scale/LICENSE +21 -0
  692. package/vendor/types/@types/d3-scale/index.d.ts +2669 -0
  693. package/vendor/types/@types/d3-scale/package.json +53 -0
  694. package/vendor/types/@types/d3-scale-chromatic/LICENSE +21 -0
  695. package/vendor/types/@types/d3-scale-chromatic/index.d.ts +520 -0
  696. package/vendor/types/@types/d3-scale-chromatic/package.json +46 -0
  697. package/vendor/types/@types/d3-selection/LICENSE +21 -0
  698. package/vendor/types/@types/d3-selection/index.d.ts +1210 -0
  699. package/vendor/types/@types/d3-selection/package.json +56 -0
  700. package/vendor/types/@types/d3-shape/LICENSE +21 -0
  701. package/vendor/types/@types/d3-shape/index.d.ts +2792 -0
  702. package/vendor/types/@types/d3-shape/package.json +53 -0
  703. package/vendor/types/@types/d3-time/LICENSE +21 -0
  704. package/vendor/types/@types/d3-time/index.d.ts +697 -0
  705. package/vendor/types/@types/d3-time/package.json +46 -0
  706. package/vendor/types/@types/d3-time-format/LICENSE +21 -0
  707. package/vendor/types/@types/d3-time-format/index.d.ts +202 -0
  708. package/vendor/types/@types/d3-time-format/package.json +40 -0
  709. package/vendor/types/@types/d3-timer/LICENSE +21 -0
  710. package/vendor/types/@types/d3-timer/index.d.ts +68 -0
  711. package/vendor/types/@types/d3-timer/package.json +45 -0
  712. package/vendor/types/@types/d3-transition/LICENSE +21 -0
  713. package/vendor/types/@types/d3-transition/index.d.ts +664 -0
  714. package/vendor/types/@types/d3-transition/package.json +47 -0
  715. package/vendor/types/@types/d3-zoom/LICENSE +21 -0
  716. package/vendor/types/@types/d3-zoom/index.d.ts +611 -0
  717. package/vendor/types/@types/d3-zoom/package.json +48 -0
  718. package/vendor/types/@types/geojson/LICENSE +21 -0
  719. package/vendor/types/@types/geojson/index.d.ts +202 -0
  720. package/vendor/types/@types/geojson/package.json +46 -0
  721. package/vendor/typescript/LICENSE.txt +55 -0
  722. package/vendor/typescript/lib.decorators.d.ts +384 -0
  723. package/vendor/typescript/lib.decorators.legacy.d.ts +22 -0
  724. package/vendor/typescript/lib.dom.d.ts +39429 -0
  725. package/vendor/typescript/lib.dom.iterable.d.ts +571 -0
  726. package/vendor/typescript/lib.es2015.collection.d.ts +147 -0
  727. package/vendor/typescript/lib.es2015.core.d.ts +597 -0
  728. package/vendor/typescript/lib.es2015.d.ts +28 -0
  729. package/vendor/typescript/lib.es2015.generator.d.ts +77 -0
  730. package/vendor/typescript/lib.es2015.iterable.d.ts +605 -0
  731. package/vendor/typescript/lib.es2015.promise.d.ts +81 -0
  732. package/vendor/typescript/lib.es2015.proxy.d.ts +128 -0
  733. package/vendor/typescript/lib.es2015.reflect.d.ts +144 -0
  734. package/vendor/typescript/lib.es2015.symbol.d.ts +46 -0
  735. package/vendor/typescript/lib.es2015.symbol.wellknown.d.ts +326 -0
  736. package/vendor/typescript/lib.es2016.array.include.d.ts +116 -0
  737. package/vendor/typescript/lib.es2016.d.ts +21 -0
  738. package/vendor/typescript/lib.es2016.intl.d.ts +31 -0
  739. package/vendor/typescript/lib.es2017.arraybuffer.d.ts +21 -0
  740. package/vendor/typescript/lib.es2017.d.ts +26 -0
  741. package/vendor/typescript/lib.es2017.date.d.ts +31 -0
  742. package/vendor/typescript/lib.es2017.intl.d.ts +44 -0
  743. package/vendor/typescript/lib.es2017.object.d.ts +49 -0
  744. package/vendor/typescript/lib.es2017.sharedmemory.d.ts +135 -0
  745. package/vendor/typescript/lib.es2017.string.d.ts +45 -0
  746. package/vendor/typescript/lib.es2017.typedarrays.d.ts +53 -0
  747. package/vendor/typescript/lib.es2018.asyncgenerator.d.ts +77 -0
  748. package/vendor/typescript/lib.es2018.asynciterable.d.ts +53 -0
  749. package/vendor/typescript/lib.es2018.d.ts +24 -0
  750. package/vendor/typescript/lib.es2018.intl.d.ts +83 -0
  751. package/vendor/typescript/lib.es2018.promise.d.ts +30 -0
  752. package/vendor/typescript/lib.es2018.regexp.d.ts +37 -0
  753. package/vendor/typescript/lib.es2019.array.d.ts +79 -0
  754. package/vendor/typescript/lib.es2019.d.ts +24 -0
  755. package/vendor/typescript/lib.es2019.intl.d.ts +23 -0
  756. package/vendor/typescript/lib.es2019.object.d.ts +33 -0
  757. package/vendor/typescript/lib.es2019.string.d.ts +37 -0
  758. package/vendor/typescript/lib.es2019.symbol.d.ts +24 -0
  759. package/vendor/typescript/lib.es2020.bigint.d.ts +765 -0
  760. package/vendor/typescript/lib.es2020.d.ts +27 -0
  761. package/vendor/typescript/lib.es2020.date.d.ts +42 -0
  762. package/vendor/typescript/lib.es2020.intl.d.ts +474 -0
  763. package/vendor/typescript/lib.es2020.number.d.ts +28 -0
  764. package/vendor/typescript/lib.es2020.promise.d.ts +47 -0
  765. package/vendor/typescript/lib.es2020.sharedmemory.d.ts +99 -0
  766. package/vendor/typescript/lib.es2020.string.d.ts +44 -0
  767. package/vendor/typescript/lib.es2020.symbol.wellknown.d.ts +41 -0
  768. package/vendor/typescript/lib.es2021.d.ts +23 -0
  769. package/vendor/typescript/lib.es2021.intl.d.ts +166 -0
  770. package/vendor/typescript/lib.es2021.promise.d.ts +48 -0
  771. package/vendor/typescript/lib.es2021.string.d.ts +33 -0
  772. package/vendor/typescript/lib.es2021.weakref.d.ts +78 -0
  773. package/vendor/typescript/lib.es2022.array.d.ts +121 -0
  774. package/vendor/typescript/lib.es2022.d.ts +25 -0
  775. package/vendor/typescript/lib.es2022.error.d.ts +75 -0
  776. package/vendor/typescript/lib.es2022.intl.d.ts +145 -0
  777. package/vendor/typescript/lib.es2022.object.d.ts +26 -0
  778. package/vendor/typescript/lib.es2022.regexp.d.ts +39 -0
  779. package/vendor/typescript/lib.es2022.string.d.ts +25 -0
  780. package/vendor/typescript/lib.es5.d.ts +4601 -0
  781. package/vendor/typescript/package.json +4 -0
  782. package/vendor/typescript/typescript.js +446 -0
  783. package/web/assets/index-B6Ai3wsa.js +13 -0
  784. package/web/assets/index-SYPC3EZy.css +1 -0
  785. package/web/index.html +14 -0
@@ -0,0 +1,164 @@
1
+ // Taken over from notion-lite (its src/ui/media-picker/index.js), as it is: only what it imports is
2
+ // Gallery's own (support.mjs, src/shared/emoji/). Its notes, below, are notion-lite's.
3
+ /* 图标选择器(Notion 485357 MediaPicker,页签由 569553 m 给:表情符号 / 图标 / 上传;尺寸、颜色是线上实测):标注图标、选项卡图标、页面图标共用。
4
+ * 宽 408(569553 popupWidth);“表情符号”“图标”页签高 390(tabHeight),“上传”页签没给高度,随内容。
5
+ * 页签栏(eU):高 40、左右 8、底下一条 --ca-borSecTra;“表情符号 / 图标 / 上传”,选中的下面 2px 线;右边“移除”(灰色文字按钮)。
6
+ * 打开时当前图标是 Notion 图标就在“图标”页签,否则在“表情符号”(569553 d;Notion 的当前页签只记在内存里)
7
+ * 筛选行(ec):只有“表情符号”“图标”页签有。上 4 下 10;里面左右 8、间距 8:输入框(放大镜、“筛选…”、有字时的清除按钮)
8
+ * + “随机”(28×28 带边框)+ 页签自己的按钮(表情:选肤色;图标:选图标颜色),两个页签共用同一个筛选词(onFilterChange 同时改两边)
9
+ * “上传”页签(569553 custom → 963369,./upload.js):上传 / 拖进来 / 粘贴一张图片或图片链接,“保存”就用它当图标;
10
+ * 勾上“添加到表情符号库”再起个名字,就同时存成自定义表情(以后在“表情符号”页签的“自定义”里)
11
+ * 随机:选上但不关菜单(keepVisible)
12
+ * 键盘:焦点一直在输入框,方向键在格子间移动,回车选中,Esc 先关小浮层、再关菜单;“上传”页签里 Esc 关菜单,Ctrl+V 粘贴图片 / 链接
13
+ * 上传、存自定义表情:一开始就关菜单(569553 p:onStart 关掉选择器),存好以后再换图标
14
+ * openMediaPicker({ origin, value, isCallout, onPick(value | null, { keepVisible }) })——null 是“移除”。
15
+ * 依赖:ui(popup、icons、tooltip)、src/shared/emoji/icon-value(图标的值)、./emoji-tab、./icon-tab、./upload
16
+ */
17
+ import { openPopup, closePopup } from './support.mjs';
18
+ import { icon } from './support.mjs';
19
+ import { hoverTooltip, hideTooltip } from './support.mjs';
20
+ import { iconKind } from '../../../shared/emoji/icon-value.mjs';
21
+ import { createEmojiTab } from './emoji-tab.mjs';
22
+ import { createIconTab } from './icon-tab.mjs';
23
+ import { createUploadForm } from './upload.mjs';
24
+ import { t } from "../../../shared/i18n/index.mjs";
25
+
26
+ const WIDTH = 408, TAB_HEIGHT = 390;
27
+ let current = null;
28
+
29
+ /* “上传”页签:963369 showTitle false、largeEmoji、allowUrlPaste、confirmToAdd */
30
+ function createUploadTab(env) {
31
+ const form = createUploadForm({
32
+ largeEmoji: true, allowUrlPaste: true, confirmToAdd: true,
33
+ onCancel: env.close,
34
+ onStart: env.close,
35
+ onDone: env.uploaded,
36
+ });
37
+ return {
38
+ el: form.el, right: null, noFilter: true,
39
+ load: () => Promise.resolve(),
40
+ render() {}, move() {}, activateFocused() {}, random() {}, destroy() {},
41
+ focus: form.focus,
42
+ paste: form.paste,
43
+ };
44
+ }
45
+
46
+ export function openMediaPicker({ origin, value, isCallout = false, onPick, only = null }) {
47
+ if (current && !current.popup.closed) closePopup(current.popup);
48
+ const el = document.createElement('div');
49
+ el.className = 'notion-media-menu';
50
+ el.tabIndex = -1;
51
+ el.style.width = `${WIDTH}px`;
52
+ el.innerHTML =
53
+ `<div class="nmm-header">` +
54
+ `<div class="nmm-tabbar">` +
55
+ `<div role="tablist" class="nmm-tabs">` +
56
+ `<div class="nmm-tab-wrap"><div role="tab" class="nmm-tab" data-tab="emoji">${t("表情符号")}</div><div class="nmm-tab-line"></div></div>` +
57
+ `<div class="nmm-tab-wrap"><div role="tab" class="nmm-tab" data-tab="icon">${t("图标")}</div><div class="nmm-tab-line"></div></div>` +
58
+ `<div class="nmm-tab-wrap"><div role="tab" class="nmm-tab" data-tab="upload">${t("上传")}</div><div class="nmm-tab-line"></div></div>` +
59
+ `</div>` +
60
+ `<div class="nmm-tabbar-right"><div role="button" tabindex="0" class="nmm-text-button" data-act="remove">${t("移除")}</div></div>` +
61
+ `</div>` +
62
+ `<div class="nmm-filter-row"><div class="nmm-filter">` +
63
+ `<div class="nmm-input"><div class="nmm-input-icon">${icon('magnifyingGlassSmall', 16)}</div>` +
64
+ `<input type="text" role="combobox" placeholder="${t("筛选…")}" autocomplete="off" spellcheck="false" aria-autocomplete="list" aria-haspopup="grid" aria-expanded="true">` +
65
+ `<div role="button" tabindex="0" aria-label="${t("清除输入")}" class="nmm-clear" data-act="clear" hidden>${icon('xMarkCircle', 20)}</div></div>` +
66
+ `<div class="nmm-filter-right"><div class="nmm-tab-left"></div><div role="button" tabindex="0" aria-label="${t("随机")}" class="nmm-random" data-act="random">${icon('arrowIntersectRightSmall', 14)}</div><div class="nmm-tab-button"></div></div>` +
67
+ `</div></div>` +
68
+ `</div>` +
69
+ `<div class="nmm-content"></div>`;
70
+
71
+ const input = el.querySelector('input'), clear = el.querySelector('.nmm-clear'), filterRow = el.querySelector('.nmm-filter-row');
72
+ const content = el.querySelector('.nmm-content'), tabButton = el.querySelector('.nmm-tab-button'), tabLeft = el.querySelector('.nmm-tab-left');
73
+ let sub = null;
74
+
75
+ const close = () => { if (!popup.closed) closePopup(popup); };
76
+ const env = {
77
+ isCallout,
78
+ filter: () => input.value,
79
+ close,
80
+ submit(v) { close(); onPick(v, {}); },
81
+ keepOpenPick(v) { onPick(v, { keepVisible: true }); },
82
+ /* 上传完、存好自定义表情(569553 u:关掉选择器,换图标) */
83
+ uploaded(v) { close(); onPick(v, {}); },
84
+ refocus() { if (!popup.closed) (active.noFilter ? active.focus() : input.focus({ preventScroll: true })); },
85
+ /* 菜单上面的一层小浮层(肤色变体、选肤色、图标颜色、选颜色菜单);onKey 接管输入框的按键 */
86
+ openSub(anchor, node, onKey, { gap = 4 } = {}) {
87
+ env.closeSub();
88
+ node.addEventListener('mousedown', e => e.preventDefault());
89
+ sub = { popup: openPopup({ origin: anchor.getBoundingClientRect(), placement: 'bottom', align: 'start', gap, content: node, onClose: () => { sub = null; } }), onKey };
90
+ },
91
+ closeSub() {
92
+ if (sub && !sub.popup.closed) closePopup(sub.popup);
93
+ sub = null;
94
+ },
95
+ };
96
+ const tabs = { emoji: createEmojiTab(env), icon: createIconTab(env), upload: createUploadTab(env) };
97
+ // Some tabs only (`only`: a Sheet tab's icon is an emoji): the others go from the tab bar.
98
+ if (only) el.querySelectorAll('.nmm-tab-wrap').forEach(wrap => { if (!only.includes(wrap.querySelector('[data-tab]').dataset.tab)) wrap.remove(); });
99
+ let active = null;
100
+
101
+ function show(name) {
102
+ env.closeSub();
103
+ active = tabs[name];
104
+ for (const tab of el.querySelectorAll('.nmm-tab[data-tab]')) {
105
+ const on = tab.dataset.tab === name;
106
+ tab.classList.toggle('selected', on);
107
+ tab.setAttribute('aria-selected', String(on));
108
+ tab.parentElement.classList.toggle('selected', on);
109
+ }
110
+ filterRow.hidden = !!active.noFilter; // 485357 ec:只有表情 / 图标页签有筛选行
111
+ el.style.height = active.noFilter ? '' : `${TAB_HEIGHT}px`;
112
+ content.replaceChildren(active.el);
113
+ tabButton.replaceChildren(...(active.right ? [active.right] : []));
114
+ tabLeft.replaceChildren(...(active.left ? [active.left] : [])); // the 图标 tab's set (icon-tab.mjs)
115
+ hideTooltip();
116
+ active.render(input.value);
117
+ active.load().then(() => { if (!popup.closed && active === tabs[name]) active.render(input.value); });
118
+ if (popup) popup.place();
119
+ if (active.noFilter) active.focus(); else input.focus({ preventScroll: true });
120
+ }
121
+
122
+ const onInput = () => { clear.hidden = !input.value; active.render(input.value); };
123
+ input.addEventListener('input', onInput);
124
+ input.addEventListener('keydown', e => {
125
+ if (sub) return sub.onKey(e);
126
+ if (e.isComposing) return;
127
+ if (e.key.startsWith('Arrow')) { e.preventDefault(); active.move(e.key); }
128
+ else if (e.key === 'Enter') { e.preventDefault(); active.activateFocused(); }
129
+ else if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); close(); }
130
+ });
131
+ /* 上传页签里(焦点不在筛选框):Esc 关菜单 */
132
+ el.addEventListener('keydown', e => {
133
+ if (e.target === input || e.key !== 'Escape' || e.isComposing) return;
134
+ e.preventDefault(); e.stopPropagation(); close();
135
+ });
136
+ /* 上传页签:Ctrl+V 粘贴图片 / 图片链接(963369 onPaste) */
137
+ const onPaste = e => { if (active.paste && !popup.closed && !sub) active.paste(e); };
138
+ document.addEventListener('paste', onPaste, true);
139
+ // 焦点留在输入框(上传页签里的输入框、按钮照常)
140
+ el.addEventListener('mousedown', e => { if (e.target !== input && !e.target.closest('.nmm-upload input')) e.preventDefault(); });
141
+ el.addEventListener('click', e => {
142
+ const tab = e.target.closest('.nmm-tab[data-tab]');
143
+ if (tab && !tab.classList.contains('selected')) return show(tab.dataset.tab);
144
+ const act = e.target.closest('[data-act]')?.dataset.act;
145
+ if (act === 'remove') { close(); onPick(null, {}); }
146
+ else if (act === 'clear') { input.value = ''; onInput(); input.focus(); }
147
+ else if (act === 'random') active.random();
148
+ });
149
+ hoverTooltip(el.querySelector('.nmm-random'), t("随机"), { placement: 'bottom' });
150
+
151
+ let popup = null;
152
+ popup = openPopup({
153
+ origin, placement: 'bottom', align: 'start', gap: 4, content: el,
154
+ onClose: () => {
155
+ env.closeSub(); hideTooltip();
156
+ document.removeEventListener('paste', onPaste, true);
157
+ for (const tab of Object.values(tabs)) tab.destroy();
158
+ current = null;
159
+ },
160
+ });
161
+ current = { popup };
162
+ show(iconKind(value) === 'glyph' ? 'icon' : 'emoji');
163
+ return popup;
164
+ }
@@ -0,0 +1,2 @@
1
+ // notion-lite's media-picker.css, as it is (support.mjs style() adds it with Notion's tokens).
2
+ export const PICKER_CSS = "/* 图标选择器(./index.js、./emoji-tab.js、./icon-tab.js;数值是线上实测) */\n.notion-media-menu { display: flex; flex-direction: column; max-height: calc(100vh - 24px); border-radius: 10px; background: var(--c-popBac); box-shadow: var(--c-shaOutLg); overflow: hidden; color: var(--c-texPri); font-size: 14px; line-height: 1.2; }\n\n/* 页签栏:高 40,左右 8,底下一条线;页签 28 高、左右 8、圆角 6;选中的下面 2px 线(左右缩进 8) */\n.nmm-header { flex-shrink: 0; }\n.nmm-tabbar { display: flex; height: 40px; padding: 0 8px; box-shadow: inset 0 -1px 0 var(--ca-borSecTra); overflow: auto hidden; scrollbar-width: none; }\n.nmm-tabs { display: flex; }\n.nmm-tab-wrap { position: relative; padding: 6px 0; }\n.nmm-tab { display: inline-flex; align-items: center; height: 28px; padding: 0 8px; border-radius: 6px; white-space: nowrap; color: var(--c-texTer); cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-tab:hover { background: var(--ca-bacIntTra); }\n.nmm-tab.selected { color: var(--c-texPri); }\n.nmm-tab.disabled { cursor: default; background: none; }\n.nmm-tab-line { position: absolute; left: 8px; right: 8px; bottom: 0; height: 2px; background: var(--c-texPri); }\n.nmm-tab-wrap:not(.selected) .nmm-tab-line { display: none; }\n.nmm-tabbar-right { display: flex; align-items: center; margin-inline-start: auto; }\n/* 图标页签:随机按钮左边,写着现在这一套图标的名字(MingCute / Tabler),点一下换成另一套(icon-tab.mjs) */\n.nmm-set-toggle { display: flex; align-items: center; justify-content: center; min-width: 74px; height: 28px; box-sizing: border-box; margin-inline-end: 6px; padding: 0 8px; border: 1px solid var(--ca-borPriTra); border-radius: 6px; color: var(--c-texSec); font-size: 12px; font-weight: 500; white-space: nowrap; cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-set-toggle:hover { background: var(--ca-bacIntTra); }\n.nmm-tab-left:empty { display: none; }\n.nmm-tab-left { display: flex; }\n.nmm-text-button { display: flex; align-items: center; height: 28px; padding: 0 8px; border-radius: 6px; color: var(--c-texTer); cursor: pointer; white-space: nowrap; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-text-button:hover { background: var(--ca-bacIntTra); }\n\n/* 筛选行:上 4 下 10;里面 4px 8px、间距 8 */\n.nmm-filter-row { margin: 4px 0 10px; }\n.nmm-filter { display: flex; align-items: center; gap: 8px; height: 36px; padding: 4px 8px; }\n.nmm-input { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; height: 28px; padding: 3px 6px; border-radius: 6px; background: var(--ca-graBacPriTra); box-shadow: inset 0 0 0 1px var(--ca-borPriTra); cursor: text; line-height: 20px; }\n.nmm-input:focus-within { box-shadow: var(--c-inpBluFocRin); }\n.nmm-input-icon { width: 16px; height: 16px; margin-inline-end: 6px; --nmm-icon: var(--c-icoSec); }\n.nmm-input input { flex: 1; min-width: 0; height: 20px; border: none; outline: none; background: transparent; padding: 0; font: inherit; font-size: 14px; line-height: 20px; color: var(--c-texPri); }\n.nmm-input input::placeholder { color: var(--c-texTer); }\n.nmm-clear { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 24px; height: 24px; margin: -2px -4px -2px 0; border-radius: 20px; --nmm-icon: var(--c-icoTer); cursor: pointer; }\n.nmm-clear[hidden] { display: none; }\n.nmm-clear:hover { background: var(--ca-bacIntTra); }\n.nmm-filter-right { display: flex; flex: 0 0 auto; }\n.nmm-random, .nmm-color-button { display: flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 28px; height: 28px; box-sizing: border-box; border: 1px solid var(--ca-borPriTra); border-radius: 6px; --nmm-icon: var(--c-icoPri); cursor: pointer; transition: background 100ms ease-in-out; }\n.nmm-random:hover, .nmm-color-button:hover { background: var(--ca-bacIntTra); }\n.nmm-skin-wrap { margin-inline-start: 6px; }\n.nmm-skin { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0 6px; border-radius: 6px; font-size: 20px; line-height: 24px; cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-skin:hover { background: var(--ca-bacIntTra); }\n\n/* 列表区:高 300。表情:列表(最高 305,下 6)+ 分类栏;图标:列表占满 */\n.nmm-content { display: flex; flex-direction: column; flex: 1; min-height: 0; }\n.nmm-body { display: flex; flex-direction: column; flex: 1; min-height: 0; }\n.nmm-scroller { flex: 1 1 auto; min-height: 0; max-height: 305px; padding-bottom: 6px; overflow: hidden auto; }\n.nmm-icon-scroller { max-height: none; padding-bottom: 0; }\n.nmm-section { display: flex; flex-direction: column; gap: 1px; }\n.nmm-section-title { display: flex; margin: 6px 0 8px; padding: 6px 8px 0; font-size: 12px; font-weight: 500; line-height: 12px; color: var(--c-texSec); user-select: none; }\n.nmm-section-title-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.nmm-rows { display: flex; flex-direction: column; padding: 0 12px; }\n.nmm-row { display: flex; }\n.nmm-cell { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 32px; height: 32px; border-radius: 4px; font-size: 24px; line-height: 36px; cursor: pointer; user-select: none; }\n.nmm-cell.focused { background: var(--ca-bacIntTra); }\n.nmm-cell.focus-visible { box-shadow: var(--c-butBluFocRin); }\n.nmm-cell img { display: block; }\n/* 图标页签:每组外面 4px,标题没有上内边距、行高 14.4;格子圆角 8 */\n.nmm-icon-grid .nmm-section { padding: 4px; }\n.nmm-icon-grid .nmm-section-title { padding: 0 8px; line-height: 14.4px; }\n.nmm-icon-cell { border-radius: 8px; }\n/* 无结果:外层 4px,说明文字 12px / 500 */\n.nmm-empty { padding: 4px; }\n.nmm-empty-caption { display: flex; align-items: center; height: 20px; margin: 2px 0 2px 2px; padding: 4px 8px; font-size: 12px; font-weight: 500; line-height: 16.8px; color: var(--c-texSec); }\n\n/* 分类栏:上边一条线,内边距 8 12 10,按钮 32×32、图标 22、圆角 6 */\n.nmm-categories { display: flex; justify-content: space-between; flex-shrink: 0; padding: 8px 12px 10px; border-top: 1px solid var(--c-borSec); }\n.nmm-categories[hidden] { display: none; }\n.nmm-category { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 6px; --nmm-icon: var(--c-icoSec); cursor: pointer; transition: background 100ms ease-in-out; }\n.nmm-category:hover, .nmm-category.focused { background: var(--ca-bacIntTra); }\n.nmm-category.disabled { opacity: .4; cursor: default; background: none; }\n\n/* 小浮层:肤色变体 / 选肤色(一排,padding 4);图标颜色变体(两行各 5 个,行内边距 2、间距 1);选图标颜色的菜单(宽 134) */\n.nmm-variations, .nmm-icon-variations, .nmm-color-menu { border-radius: 10px; background: var(--c-popBac); box-shadow: var(--c-shaOutLg); }\n.nmm-variations { display: flex; padding: 4px; }\n.nmm-icon-variations-row { display: flex; padding: 2px; gap: 1px; }\n.nmm-color-menu { width: 134px; padding: 4px 0; }\n.nmm-color-row { display: flex; padding: 4px; gap: 4px; }\n.nmm-color-row.dim { opacity: .5; }\n.nmm-color-swatch { display: flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 6px; opacity: .4; cursor: pointer; transition: background 100ms ease-in-out; }\n.nmm-color-swatch.selected { opacity: 1; }\n.nmm-color-swatch:hover { background: var(--ca-bacIntTra); }\n.nmm-color-ask { display: flex; flex-direction: row-reverse; justify-content: center; gap: 4px; margin: 4px 0 0; padding: 4px 4px 0; border-top: 1px solid var(--ca-borSecTra); }\n.nmm-color-ask-item { display: flex; align-items: center; width: 100%; height: 28px; padding-inline: 6px; border-radius: 6px; font-size: 14px; cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-color-ask-item:hover { background: var(--ca-bacIntTra); }\n.nmm-color-ask-label { flex: 1; margin-inline-start: 6px; white-space: nowrap; }\n.nmm-switch { display: flex; flex-shrink: 0; width: 26px; height: 14px; padding: 2px; margin-inline-end: 4px; box-sizing: content-box; border-radius: 44px; background: var(--ca-swiTogDesTraBgVar); transition: background 200ms; }\n.nmm-switch.on { background: var(--c-bluBacAccPri); }\n.nmm-switch-knob { width: 14px; height: 14px; border-radius: 44px; background: white; transition: transform 200ms ease-out; }\n.nmm-switch.on .nmm-switch-knob { transform: translateX(12px); }\n\n/* 自定义表情(./emoji-tab.js,943244 S):“添加表情符号”的圆形加号(28×28、外边距 2、1px --c-borPri、圆角 15,加号 16 --c-icoSec);\n 无结果时的“添加表情符号”按钮(28 高、4px 8px、左右外边距 12、圆角 6、1px --c-borPri、14px / 500、间距 6,加号 --c-icoPri) */\n.nmm-cell.nmm-add-cell { width: 28px; height: 28px; margin: 2px; box-sizing: border-box; border: 1px solid var(--c-borPri); border-radius: 15px; --nmm-icon: var(--c-icoSec); }\n.nmm-empty.with-add { display: flex; flex-direction: column; }\n.nmm-empty.with-add .nmm-empty-caption { height: 20px; margin: 0 0 2px 2px; box-sizing: content-box; }\n.nmm-cell.nmm-add-button { display: flex; align-items: center; justify-content: flex-start; gap: 6px; width: auto; height: 28px; margin: 0 12px; padding: 4px 8px; box-sizing: border-box; border: 1px solid var(--c-borPri); border-radius: 6px; font-size: 14px; font-weight: 500; line-height: 1.2; white-space: nowrap; --nmm-icon: var(--c-icoPri); }\n.nmm-cell img.notion-custom-emoji { object-fit: contain; color: transparent; }\n\n/* “上传”页签 / “添加表情符号”浮层(./upload.js,963369;数值见那里开头) */\n.nmm-upload { display: flex; flex-direction: column; padding: 0 16px; font-size: 14px; color: var(--c-texPri); }\n.nmm-upload-title { margin-top: 12px; font-size: 14px; font-weight: 600; }\n.nmm-upload-description { margin-top: 2px; font-size: 12px; color: var(--c-texSec); }\n.nmm-upload-zone-wrap { display: flex; flex-direction: column; align-items: stretch; margin-top: 20px; }\n.nmm-upload-zone { border-radius: 4px; background: var(--ca-bacSecTra); }\n.nmm-upload-zone-wrap.dragover .nmm-upload-zone { background: var(--ca-bluBacSecTra); }\n.nmm-upload-button { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 14px; border-radius: 6px; font-weight: 500; line-height: 1.2; white-space: nowrap; color: var(--c-texSec); --nmm-icon: var(--c-icoSec); cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-upload-button:hover { background: var(--ca-bacIntTra); }\n.nmm-upload-preview { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px; }\n.nmm-upload.large .nmm-upload-preview { padding: 16px; }\n.nmm-upload-preview.with-replace { padding-bottom: 4px; }\n.nmm-upload-preview-label { margin-bottom: 4px; font-size: 12px; color: var(--c-texSec); }\n.nmm-upload-preview-row { display: flex; align-items: center; gap: 6px; }\n.nmm-upload-preview-row img { width: 48px; height: 48px; padding: 8px; box-sizing: border-box; border: 1px solid var(--ca-borPriTra); border-radius: 8px; object-fit: cover; }\n.nmm-upload.large .nmm-upload-preview-row img { width: 80px; height: 80px; padding: 6px; }\n.nmm-upload-zone.contain .nmm-upload-preview-row img { object-fit: contain; }\n.nmm-upload-preview-row img.light { background: var(--c-whi); }\n.nmm-upload-preview-row img.dark { background: var(--c-priBla); }\n.nmm-upload-replace { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px; border-radius: 6px; font-size: 12px; font-weight: 500; line-height: 1.2; color: var(--c-graTexAccPri); --nmm-icon: var(--c-graTexAccPri); cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-upload-replace:hover { background: var(--ca-graBacIntTra); }\n.nmm-upload-paste { margin-top: 10px; font-size: 12px; color: var(--c-texTer); text-align: center; }\n.nmm-upload-error { margin-top: 10px; font-size: 12px; color: var(--c-redTexAccPri); text-align: center; }\n.nmm-upload-confirm { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 14px; cursor: pointer; user-select: none; }\n.nmm-upload-checkbox { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 14px; height: 14px; box-sizing: border-box; border: 1px solid var(--ca-borStrTra); border-radius: 3px; cursor: pointer; transition: background .2s ease-out; }\n.nmm-upload-checkbox[aria-checked=\"true\"] { border: none; background: var(--c-bluBacAccPri); }\n.nmm-upload-name { display: block; margin-top: 20px; }\n.nmm-upload-name-label { margin-bottom: 6px; font-size: 12px; font-weight: 500; color: var(--c-texSec); }\n.nmm-upload-input { display: flex; align-items: center; height: 28px; padding: 3px 6px; border-radius: 6px; background: var(--ca-bacSecTra); box-shadow: 0 0 0 1px var(--ca-borPriTra); cursor: text; }\n.nmm-upload-input:focus-within { box-shadow: var(--c-inpBluFocRin); }\n.nmm-upload-input input { flex: 1; min-width: 0; height: 20px; border: none; outline: none; background: transparent; padding: 0; font: inherit; font-size: 14px; line-height: 20px; color: var(--c-texPri); }\n.nmm-upload-input input::placeholder { color: var(--c-texTer); }\n.nmm-upload-name-error { margin-top: 10px; font-size: 12px; color: var(--c-redTexAccPri); }\n.nmm-upload-name-error[hidden], .nmm-upload [hidden] { display: none; }\n.nmm-upload-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 16px 0 12px; }\n.nmm-upload-secondary, .nmm-upload-save { display: inline-flex; align-items: center; justify-content: center; height: 28px; padding: 0 8px; border-radius: 6px; font-size: 14px; font-weight: 500; line-height: 1.2; white-space: nowrap; cursor: pointer; user-select: none; transition: background 100ms ease-in-out; }\n.nmm-upload-secondary { color: var(--c-texSec); }\n.nmm-upload-secondary:hover { background: var(--ca-bacIntTra); }\n.nmm-upload-save { background: var(--c-bluBacAccPri); color: var(--c-texInvPri); }\n.nmm-upload-save:not(.disabled):hover { filter: brightness(.94); }\n.nmm-upload-save.disabled { opacity: .4; cursor: default; }\n/* “添加表情符号”浮层(749527 tM → 747369 Popup,最小宽 280) */\n.nmm-custom-emoji-popup { min-width: 280px; border-radius: 10px; background: var(--c-popBac); box-shadow: var(--c-shaOutLg); }\n\n/* 图标:编辑器自己的线条图(../icons.mjs),颜色由所在处的 --nmm-icon 定 */\n.notion-popup-layer svg:not(.ge-glyph) { fill: none; stroke: var(--nmm-icon, currentColor); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }\n.nmm-upload-checkbox { --nmm-icon: #fff; }\n.nmm-upload-checkbox svg { stroke-width: 2; }";
@@ -0,0 +1,202 @@
1
+ import { Z } from "../../../shared/layers.mjs";
2
+ import { escapeMarkup } from "../../../shared/escape.mjs";
3
+ import { icon } from "./icons.mjs";
4
+ import { setEmojiLibraryStorage } from "../../../shared/emoji/custom.mjs";
5
+ import { UPLOAD_LIMITS, sizeLimit } from "../../../shared/media.mjs";
6
+ import { blobBase64, failure, postAnswer } from "../post.mjs";
7
+ import { hideTooltip as hideBubble, showTooltipAt } from "../tooltip.mjs";
8
+ import { placeBox } from "../placement.mjs";
9
+ import { addStyle, mount } from "../ui.mjs";
10
+ import { PICKER_CSS } from "./styles.mjs";
11
+ import { t } from "../../../shared/i18n/index.mjs";
12
+
13
+ // What notion-lite's icon picker (its ui/media-picker/, taken over as they are: index, emoji-tab,
14
+ // icon-tab, upload, grid) stands on, made here: its popups (ui/popup.js: placed by an origin, a
15
+ // side and an alignment, flipped where they do not fit, kept 12px inside the window, fading in;
16
+ // a press outside every one closes them all, one inside closes those above it), its tooltip
17
+ // (ui/tooltip.js: the editor's own, tooltip.mjs), its snackbar (the editor's status line), the storage its uploads and custom
18
+ // emojis go to (this Gallery's server: the report's own folder, the workspace's library) and its
19
+ // styles (Notion's, its tokens in light and dark). Everything drawn carries data-doc-dev.
20
+
21
+ export const esc = (s) => escapeMarkup(String(s ?? "")).replaceAll("'", "&#39;");
22
+ export { icon };
23
+
24
+ // ---------- styles ----------
25
+
26
+ // Notion's tokens the picker uses (notion-lite's view/theme/notion-vars.css), light and dark.
27
+ const TOKENS = `
28
+ --ca-bacIntTra: light-dark(rgba(33,27,23,.05), rgba(255,255,255,.055));
29
+ --ca-bacSecTra: light-dark(rgba(66,35,3,.03), rgba(252,252,252,.03));
30
+ --ca-bluBacSecTra: light-dark(rgba(0,124,215,.094), rgba(67,155,255,.24));
31
+ --ca-borPriTra: light-dark(rgba(28,19,1,.11), rgba(255,255,235,.1));
32
+ --ca-borSecTra: light-dark(rgba(42,28,0,.07), rgba(255,255,243,.082));
33
+ --ca-borStrTra: light-dark(rgba(27,21,0,.19), rgba(255,252,235,.306));
34
+ --ca-graBacIntTra: light-dark(rgba(33,27,23,.05), rgba(255,255,255,.055));
35
+ --ca-graBacPriTra: light-dark(rgba(66,35,3,.03), rgba(252,252,252,.03));
36
+ --ca-swiTogDesTraBgVar: light-dark(rgba(206,205,202,.3), rgba(202,204,206,.3));
37
+ --c-bacAccPri: #2c2c2b; --c-bluBacAccPri: #2783de; --c-graTexAccPri: #8e8b86; --c-redTexAccPri: #e56458;
38
+ --c-texInvPri: #f0efed; --c-texInvSec: #ada9a3;
39
+ --c-borPri: light-dark(#e6e5e3, #383836); --c-borSec: light-dark(#f0efed, #2c2c2b);
40
+ --c-butBluFocRin: light-dark(0px 0px 0px 2px #f8f8f7, 0px 0px 0px 2px #191919), 0px 0px 0px 4px #2383e2;
41
+ --c-icoPri: light-dark(#383836, #e6e5e3); --c-icoSec: light-dark(#8e8b86, #ada9a3); --c-icoTer: light-dark(#ada9a3, #7d7a75);
42
+ --c-inpBluFocRin: 0px 0px 0px 1px #2383e2 inset, 0px 0px 0px 1px #2383e2;
43
+ --c-popBac: light-dark(#fff, #252525); --c-priBla: light-dark(#000, #fff); --c-whi: light-dark(#fff, #000);
44
+ --c-shaOutLg: 0px 20px 24px 0px light-dark(rgba(25,25,25,.05), rgba(25,25,25,.2)), 0px 5px 8px 0px light-dark(rgba(25,25,25,.027), rgba(25,25,25,.118)), 0px 0px 0px 1px light-dark(rgba(42,28,0,.07), #383836);
45
+ --c-texPri: light-dark(#2c2c2b, #f0efed); --c-texSec: light-dark(#7d7a75, #ada9a3); --c-texTer: light-dark(#a19e99, #7d7a75);
46
+ `;
47
+ const FONT = `ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", Helvetica, "PingFang SC", "Microsoft YaHei", Arial, sans-serif`;
48
+
49
+ /** The picker's styles (notion-lite's media-picker.css, popup.css), added once. */
50
+ export function style() {
51
+ addStyle(`
52
+ .notion-popup-layer { ${TOKENS} }
53
+ .notion-popup-layer { position: fixed; inset: 0; pointer-events: none; z-index: ${Z.menu}; font: 14px/1.2 ${FONT}; color: var(--c-texPri); }
54
+ .notion-popup { position: fixed; pointer-events: auto; opacity: 0; transition: opacity 200ms; }
55
+ .notion-popup.shown { opacity: 1; }
56
+ .notion-popup-layer .notion-scroller { scrollbar-width: thin; scrollbar-color: var(--ca-borPriTra) transparent; }
57
+ ${PICKER_CSS}
58
+ `);
59
+ }
60
+
61
+ // ---------- popups ----------
62
+
63
+ const MARGIN = 12;
64
+ const stack = [];
65
+ let layer = null;
66
+
67
+ function ensureLayer() {
68
+ style();
69
+ if (!layer?.isConnected) {
70
+ layer = document.createElement("div");
71
+ layer.className = "notion-popup-layer";
72
+ mount(layer);
73
+ }
74
+ return layer;
75
+ }
76
+ document.addEventListener("mousedown", (event) => {
77
+ if (!stack.length) return;
78
+ const inside = stack.findLastIndex((popup) => popup.el.contains(event.target));
79
+ if (inside === stack.length - 1) return;
80
+ closePopup(stack[inside + 1]);
81
+ }, true);
82
+
83
+ /** Whether a popup is open (a press outside it closes it). */
84
+ export const popupOpen = () => stack.length > 0;
85
+
86
+ /** A popup holding `content`: { el, closed, close(), place(origin) }. */
87
+ export function openPopup({ origin, placement = "bottom", align = "start", gap = 0, content, onClose, className = "" }) {
88
+ const el = document.createElement("div");
89
+ el.className = "notion-popup" + (className ? ` ${className}` : "");
90
+ el.append(content);
91
+ ensureLayer().append(el);
92
+ const popup = { el, closed: false, close: () => closePopup(popup), place: (next) => place(popup, next || popup.origin), origin, placement, align, gap, onClose };
93
+ stack.push(popup);
94
+ place(popup, origin);
95
+ requestAnimationFrame(() => el.classList.add("shown"));
96
+ return popup;
97
+ }
98
+
99
+ export function closePopup(popup) {
100
+ const at = stack.indexOf(popup);
101
+ if (at < 0) return;
102
+ for (const each of stack.splice(at).reverse()) { // those above it go with it
103
+ each.closed = true;
104
+ each.el.remove();
105
+ each.onClose?.();
106
+ }
107
+ }
108
+
109
+ function place(popup, origin) {
110
+ popup.origin = origin;
111
+ const { el, placement, align, gap } = popup;
112
+ const { left, top } = placeBox(origin, { width: el.offsetWidth, height: el.offsetHeight }, { placement, align, gap, margin: MARGIN });
113
+ el.style.top = `${top}px`;
114
+ el.style.left = `${left}px`;
115
+ }
116
+
117
+ // ---------- the tooltip ----------
118
+
119
+ // The editor's own (tooltip.mjs): the picker only decides when it shows (a pause of 150ms, never
120
+ // while the keys move) and where (below, left edge or centered).
121
+ let timer = 0;
122
+ let keyboardMode = false;
123
+ addEventListener("keydown", () => { keyboardMode = true; }, true);
124
+ addEventListener("mousemove", () => { keyboardMode = false; }, true);
125
+
126
+ export function showTooltip(origin, text, { placement = "bottom", align = "center" } = {}) {
127
+ showTooltipAt(origin, text, { placement, align });
128
+ }
129
+ export const isKeyboardMode = () => keyboardMode;
130
+ export function hideTooltip() {
131
+ clearTimeout(timer);
132
+ hideBubble();
133
+ }
134
+ export function hoverTooltip(target, content, { placement = "top", align, delay = 150 } = {}) {
135
+ target.addEventListener("mouseenter", () => {
136
+ clearTimeout(timer);
137
+ if (keyboardMode) return;
138
+ timer = setTimeout(() => {
139
+ if (target.isConnected) showTooltip(target.getBoundingClientRect(), typeof content === "function" ? content() : content, { placement, align });
140
+ }, delay);
141
+ });
142
+ target.addEventListener("mouseleave", hideTooltip);
143
+ target.addEventListener("mousedown", hideTooltip);
144
+ }
145
+
146
+ // ---------- the snackbar, the storage ----------
147
+
148
+ let say = (text) => console.info(text);
149
+ /** The editor's status line, for what the picker tells the reader. */
150
+ export const showSnackbar = (text) => say(text);
151
+
152
+ const MAX_SIDE = 512; // px: an icon shows at 56; a larger image is made this size before it is sent
153
+ const MAX_BYTES = UPLOAD_LIMITS.icon; // what the server keeps of an icon's image (shared/media.mjs)
154
+
155
+ // An image as the server takes it: a raster image larger than MAX_SIDE made that size (PNG), others as they are.
156
+ async function shrink(blob) {
157
+ if (!/^image\/(png|jpeg|webp|avif)$/.test(blob.type)) return blob;
158
+ const bitmap = await createImageBitmap(blob).catch(() => null);
159
+ if (!bitmap || Math.max(bitmap.width, bitmap.height) <= MAX_SIDE) return blob;
160
+ const scale = MAX_SIDE / Math.max(bitmap.width, bitmap.height);
161
+ const canvas = new OffscreenCanvas(Math.round(bitmap.width * scale), Math.round(bitmap.height * scale));
162
+ canvas.getContext("2d").drawImage(bitmap, 0, 0, canvas.width, canvas.height);
163
+ return canvas.convertToBlob({ type: "image/png" });
164
+ }
165
+
166
+ let server = null; // { slug, token }
167
+ async function post(route, body) {
168
+ const answer = await postAnswer(`/__gallery/edit/${route}`, server.token, { slug: server.slug, ...body });
169
+ if (!answer.ok) throw new Error(failure(answer, t("请求失败")));
170
+ return answer;
171
+ }
172
+
173
+ /** Where uploads go: the report's own folder (assets/), and the workspace's emoji library. */
174
+ export const uiStorage = {
175
+ /** An image the reader chose: stored in the report's folder; its path there (assets/<file>). */
176
+ async saveFile(blob, name) {
177
+ const image = await shrink(blob);
178
+ if (image.size > MAX_BYTES) throw new Error(t("图片太大(最多 {0})", sizeLimit("icon")));
179
+ return (await post("upload", { name, type: image.type, data: await blobBase64(image) })).path;
180
+ },
181
+ /** An image from a link: downloaded by the server into the report's folder; its path, or null. */
182
+ async importImage(url, name) {
183
+ try {
184
+ return (await post("upload", { name, url })).path;
185
+ } catch {
186
+ return null;
187
+ }
188
+ },
189
+ };
190
+
191
+ /**
192
+ * The page's: `slug` and `token` (the edit service's), and `notify(text)`, the status line. The
193
+ * emoji library answers through the same server (custom.mjs).
194
+ */
195
+ export function connectPicker({ slug, token, notify }) {
196
+ server = { slug, token };
197
+ say = notify;
198
+ setEmojiLibraryStorage({
199
+ loadEmojiLibrary: () => fetch(`/__gallery/edit/emoji-library`).then((response) => response.json()).then((answer) => answer.list ?? []).catch(() => []),
200
+ addEmoji: async ({ name, url }) => (await post("emoji-library", { name, url })).entry,
201
+ });
202
+ }
@@ -0,0 +1,235 @@
1
+ // Taken over from notion-lite (its src/ui/media-picker/upload.js), as it is: only what it imports is
2
+ // Gallery's own (support.mjs, src/shared/emoji/). Its notes, below, are notion-lite's.
3
+ /* 上传图片做图标 / 添加自定义表情(963369 CustomEmojiUploadPopup;数值、文案照源码,文案取自中文语言包)。两处用:
4
+ * 图标选择器的“上传”页签(569553 custom → customEmoji 页签:没有标题、大预览、能粘贴链接、可以勾“添加到表情符号库”)
5
+ * 表情页的“添加表情符号”浮层(749527 tM:有标题、小预览、不能粘贴链接、直接存成自定义表情;浮层最小宽 280)
6
+ * 布局(外层左右 16、14px,从上到下):
7
+ * 标题(上 12、14px / 600)+ 说明(上 2、12px、--c-texSec)——只有浮层有
8
+ * 放图片的区域(上 20、--ca-bacSecTra 底、圆角 4):
9
+ * 没图片:整块是一个按钮(内边距 14、间距 8、14px / 500、--c-texSec、居中):图片图标 +“上传图片”
10
+ * 有图片:一列居中(内边距 16 / 12,有“替换”时下 4,间距 4):“预览”(12px、--c-texSec、下 4)+ 一亮一暗两张(间距 6;
11
+ * 80 / 48 见方、内边距 6 / 8、圆角 8、1px --ca-borPriTra;存成表情时 contain、否则 cover)+ 灰色“替换”(能粘贴链接时没有)
12
+ * 把文件拖进来:只收图片,别的显示“仅支持图片”
13
+ * 粘贴提示(上 10、12px、--c-texTer、居中)“或Ctrl+V粘贴图片或链接”——能粘贴链接、还没图片、没出错时
14
+ * 错误(上 10、12px、红、居中)
15
+ * 勾选框(上 12、间距 8、14px;框 14)“添加到表情符号库”——能勾、有图片时
16
+ * 表情符号名称(上 20;标签 12px / 500 / --c-texSec、下 6;输入框;错误 上 10、12px、红)——要存成表情、
17
+ * 并且(不能粘贴链接,或者已经有图片)时;选了文件、名字还空着(或者还是上一个文件名生成的)就用文件名生成
18
+ * 底部(上 16 下 12、两端对齐、间距 8):左边灰色“返回”(能粘贴链接、有图片时:全部清掉重来)或“取消”(关掉);右边蓝色“保存”
19
+ * 保存(963369 r 的保存按钮):
20
+ * 要存成表情(浮层;或者勾了“添加到表情符号库”):名字必填、合法、不重名,才能点;图片存到本地 → 记进表情库 →
21
+ * 提示“已将 {name} 添加到表情符号库” → onDone(表情字符串);失败提示“无法保存此表情符号。请重试。”
22
+ * 不存成表情:有图片就能点 → onDone(图片网址);失败提示“出了些问题。”(recordIcon.uploadFileTab.uploadError.message)
23
+ * 一开始就调 onStart()(Notion 上传开始就关掉选择器,401558 QM 的 onStart → 569553 p)
24
+ * 粘贴(能粘贴链接、还没图片时,963369 onPaste):剪贴板里有图片文件就用它,别的文件“仅支持图片”;
25
+ * 是文字就当图片链接试着加载,加载不了显示“粘贴的链接不包含图像。使用Ctrl+V粘贴其他链接”
26
+ * 本地化(和 Notion 的差别):图片存进本地(../storage 接到 model/local-store:上传的文件存 local-data/files/,粘贴的链接也下载一份,
27
+ * 下载不了才记原网址);“工作空间表情符号库”说成“表情符号库”,浮层说明改成本机;没有数量上限、没有手机版的链接输入框。
28
+ * createUploadForm(opts) → { el, focus(), paste(e) }
29
+ * opts:{ showTitle, largeEmoji, allowUrlPaste, confirmToAdd, onCancel(), onStart(), onDone(value) }
30
+ * 依赖:lib/dom、ui(storage、icons、snackbar、tooltip)、ui/emoji/custom
31
+ */
32
+ import { esc } from './support.mjs';
33
+ import { uiStorage } from './support.mjs';
34
+ import { icon } from './support.mjs';
35
+ import { showSnackbar } from './support.mjs';
36
+ import { shortcut } from '../tooltip.mjs';
37
+ import { addCustomEmoji, validateCustomEmojiName, nameFromFileName, prepareNameCheck } from '../../../shared/emoji/custom.mjs';
38
+ import { t } from "../../../shared/i18n/index.mjs";
39
+
40
+ /* 963369 y:选文件时收的类型;149646 Dn:图片 */
41
+ const ACCEPT = 'image/jpeg, image/png, image/gif, image/webp, image/avif, image/svg+xml';
42
+ /* 链接里的文件名(不带扩展名,存的时候按类型补):下载到本地时用 */
43
+ const urlBaseName = url => { try { return decodeURIComponent(new URL(url, location.href).pathname.split('/').pop()).replace(/\.[a-z0-9]{1,5}$/i, '') || 'image'; } catch { return 'image'; } };
44
+ const isImage = file => /^image\//.test(file?.type || '');
45
+ const PASTE = shortcut('mod+v'); // 406410 dK({ name: "paste" })
46
+ /* 名字为什么不行(shared/emoji/custom.mjs validateCustomEmojiName 的原因),界面的语言 */
47
+ const NAME_ERRORS = { chars: t("名称只能包含小写字母、数字、连字符或下划线"), long: t("名称必须少于 50 个字符"), taken: t("名称已被占用") };
48
+
49
+ const T = {
50
+ title: t("添加自定义表情符号"),
51
+ description: t("本机所有页面都可以使用自定义表情符号"),
52
+ upload: t("上传图片"),
53
+ replace: t("替换"),
54
+ preview: t("预览"),
55
+ pastePrompt: t("或{0}粘贴图片或链接", PASTE),
56
+ imageError: t("仅支持图片"),
57
+ urlPasteHintImageError: t("粘贴的链接不包含图像。<br>使用{0}粘贴其他链接", esc(PASTE)),
58
+ confirmToAdd: t("添加到表情符号库"),
59
+ nameLabel: t("表情符号名称"),
60
+ namePlaceholder: t("搭建快乐!"),
61
+ back: t("返回"),
62
+ cancel: t("取消"),
63
+ save: t("保存"),
64
+ };
65
+
66
+ export function createUploadForm({ showTitle = false, largeEmoji = false, allowUrlPaste = false, confirmToAdd = false, onCancel, onStart, onDone }) {
67
+ const el = document.createElement('div');
68
+ el.className = 'nmm-upload' + (largeEmoji ? ' large' : '');
69
+ el.innerHTML =
70
+ (showTitle ? `<div class="nmm-upload-title">${T.title}</div><div class="nmm-upload-description">${T.description}</div>` : '') +
71
+ `<div class="nmm-upload-zone-wrap"><div class="nmm-upload-zone"></div></div>` +
72
+ `<div class="nmm-upload-paste" hidden>${esc(T.pastePrompt)}</div>` +
73
+ `<div class="nmm-upload-error" hidden></div>` +
74
+ `<label class="nmm-upload-confirm" hidden><div role="checkbox" tabindex="0" aria-checked="false" class="nmm-upload-checkbox"></div>${T.confirmToAdd}</label>` +
75
+ `<label class="nmm-upload-name" hidden><div class="nmm-upload-name-label">${T.nameLabel}</div>` +
76
+ `<div class="nmm-upload-input"><input type="text" placeholder="${T.namePlaceholder}" autocomplete="off" spellcheck="false"></div>` +
77
+ `<div class="nmm-upload-name-error" hidden></div></label>` +
78
+ `<div class="nmm-upload-footer"><div role="button" tabindex="0" class="nmm-upload-secondary" data-act="secondary"></div>` +
79
+ `<div role="button" tabindex="0" class="nmm-upload-save" data-act="save">${T.save}</div></div>` +
80
+ `<input type="file" accept="${ACCEPT}" hidden>`;
81
+
82
+ const zone = el.querySelector('.nmm-upload-zone'), wrap = el.querySelector('.nmm-upload-zone-wrap');
83
+ const paste = el.querySelector('.nmm-upload-paste'), error = el.querySelector('.nmm-upload-error');
84
+ const confirm = el.querySelector('.nmm-upload-confirm'), checkbox = el.querySelector('.nmm-upload-checkbox');
85
+ const nameBox = el.querySelector('.nmm-upload-name'), nameInput = nameBox.querySelector('input'), nameError = el.querySelector('.nmm-upload-name-error');
86
+ const secondary = el.querySelector('[data-act="secondary"]'), save = el.querySelector('[data-act="save"]');
87
+ const fileInput = el.querySelector('input[type="file"]');
88
+
89
+ /* 963369 r 的状态:image { type: 'file', file } | { type: 'url', url };preview 是预览图地址 */
90
+ let image = null, preview = null, errorHTML = null, name = '', nameErr = null, checked = false, busy = false;
91
+ const savingAsEmoji = () => !confirmToAdd || checked; // 963369 D
92
+ const disabled = () => busy || (savingAsEmoji() ? !name || !image || !!nameErr : !image); // 963369 H
93
+
94
+ function update() {
95
+ const hadFocus = el.contains(document.activeElement); // 重画放图片的区域时焦点别丢(Esc、粘贴还要接着用)
96
+ zone.innerHTML = preview
97
+ ? `<div class="nmm-upload-preview${allowUrlPaste ? '' : ' with-replace'}"><div class="nmm-upload-preview-label">${T.preview}</div>` +
98
+ `<div class="nmm-upload-preview-row"><img class="light" alt="Light Mode Image" src="${esc(preview)}"><img class="dark" alt="Dark Mode Image" src="${esc(preview)}"></div>` +
99
+ (allowUrlPaste ? '' : `<div role="button" tabindex="0" class="nmm-upload-replace" data-act="choose" aria-label="${T.replace}">${icon('arrowCircleLoopBackwardSmall', 14)}<div>${T.replace}</div></div>`) + `</div>`
100
+ : `<div role="button" tabindex="0" class="nmm-upload-button" data-act="choose">${icon('photo', 20)}<span>${T.upload}</span></div>`;
101
+ zone.classList.toggle('contain', savingAsEmoji());
102
+ paste.hidden = !(allowUrlPaste && !image && !errorHTML);
103
+ error.hidden = !errorHTML;
104
+ error.innerHTML = errorHTML || '';
105
+ confirm.hidden = !(confirmToAdd && image);
106
+ checkbox.setAttribute('aria-checked', String(checked));
107
+ checkbox.innerHTML = checked ? `<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true"><path d="m3.5 8.5 3 3 6-7"/></svg>` : '';
108
+ const showName = savingAsEmoji() && (!allowUrlPaste || !!image);
109
+ const wasHidden = nameBox.hidden;
110
+ nameBox.hidden = !showName;
111
+ nameError.hidden = !nameErr;
112
+ nameError.textContent = nameErr ? NAME_ERRORS[nameErr] : '';
113
+ secondary.textContent = allowUrlPaste && image ? T.back : T.cancel;
114
+ save.classList.toggle('disabled', disabled());
115
+ save.setAttribute('aria-disabled', String(disabled()));
116
+ if (showName && wasHidden) nameInput.focus(); // 963369 G:名称输入框 autoFocus
117
+ else if (hadFocus && (!el.contains(document.activeElement) || document.activeElement === save && disabled())) {
118
+ (el.querySelector('[data-act="choose"]') || save).focus({ preventScroll: true });
119
+ }
120
+ }
121
+
122
+ /* 963369 F:空格换成“-”,再校验 */
123
+ function setName(value) {
124
+ name = value.replace(/ /g, '-');
125
+ if (nameInput.value !== name) nameInput.value = name;
126
+ nameErr = validateCustomEmojiName(name);
127
+ update();
128
+ }
129
+ prepareNameCheck().then(() => { if (name) setName(name); }); // 查重的数据到了再校验一次
130
+
131
+ /* 963369 N 的 onFileChanged:名字还空着,或者还是上一个文件名生成的,就用这个文件名 */
132
+ function setFile(file) {
133
+ errorHTML = null;
134
+ const prevDerived = image?.type === 'file' ? nameFromFileName(image.file.name) : null;
135
+ if (file.name && (name === '' || prevDerived === name)) setName(nameFromFileName(file.name));
136
+ image = { type: 'file', file };
137
+ const reader = new FileReader();
138
+ reader.onload = () => { if (image?.file === file) { preview = reader.result; update(); } };
139
+ reader.readAsDataURL(file);
140
+ update();
141
+ }
142
+
143
+ /* 963369 U:当图片链接试着加载 */
144
+ function tryUrl(text) {
145
+ const url = text.trim(), probe = new Image();
146
+ probe.onload = () => { image = { type: 'url', url }; preview = url; errorHTML = null; update(); };
147
+ probe.onerror = () => { errorHTML = T.urlPasteHintImageError; update(); };
148
+ probe.src = url;
149
+ }
150
+
151
+ function reset() { // “返回”
152
+ image = null; preview = null; errorHTML = null; name = ''; nameErr = null; checked = false;
153
+ nameInput.value = '';
154
+ update();
155
+ }
156
+
157
+ /* 图片存到本地:文件 → local-data/files;链接 → 下载一份,下载不了记原网址 */
158
+ async function storeImage() {
159
+ if (image.type === 'file') return uiStorage.saveFile(image.file, image.file.name || 'image');
160
+ return (await uiStorage.importImage(image.url, name || urlBaseName(image.url))) || image.url;
161
+ }
162
+
163
+ async function submit() {
164
+ if (disabled()) return;
165
+ busy = true;
166
+ update();
167
+ const asEmoji = savingAsEmoji(), emojiName = name;
168
+ onStart?.();
169
+ try {
170
+ const url = await storeImage();
171
+ if (!asEmoji) return onDone(url);
172
+ const value = await addCustomEmoji({ name: emojiName, url });
173
+ showSnackbar(t("已将 {0} 添加到表情符号库", emojiName)); // uploadCustomEmoji.success(本地化:工作空间 → 表情符号库)
174
+ onDone(value);
175
+ } catch {
176
+ showSnackbar(asEmoji ? t("无法保存此表情符号。请重试。") : t("出了些问题。"));
177
+ } finally {
178
+ busy = false;
179
+ if (el.isConnected) update();
180
+ }
181
+ }
182
+
183
+ const choose = () => { fileInput.value = ''; fileInput.click(); };
184
+ fileInput.addEventListener('change', () => {
185
+ const file = fileInput.files?.[0];
186
+ if (!file) return;
187
+ if (!isImage(file)) { errorHTML = T.imageError; update(); return; } // 149646 B7
188
+ setFile(file);
189
+ });
190
+ el.addEventListener('click', e => {
191
+ const act = e.target.closest('[data-act]')?.dataset.act;
192
+ if (act === 'choose') choose();
193
+ else if (act === 'save') submit();
194
+ else if (act === 'secondary') { if (allowUrlPaste && image) reset(); else onCancel?.(); }
195
+ else if (e.target.closest('.nmm-upload-confirm')) { e.preventDefault(); checked = !checked; update(); }
196
+ });
197
+ el.addEventListener('keydown', e => {
198
+ if (e.key === 'Enter' && e.target === nameInput) { e.preventDefault(); submit(); return; }
199
+ if ((e.key === 'Enter' || e.key === ' ') && e.target.matches('[role="button"], [role="checkbox"]')) { e.preventDefault(); e.target.click(); }
200
+ });
201
+ nameInput.addEventListener('input', () => setName(nameInput.value));
202
+
203
+ /* 777875:拖文件进来(只收第一个;不是图片“仅支持图片”) */
204
+ const hasFiles = e => [...(e.dataTransfer?.types || [])].includes('Files');
205
+ wrap.addEventListener('dragover', e => { if (!hasFiles(e)) return; e.preventDefault(); e.stopPropagation(); wrap.classList.add('dragover'); });
206
+ wrap.addEventListener('dragleave', e => { if (!wrap.contains(e.relatedTarget)) wrap.classList.remove('dragover'); });
207
+ wrap.addEventListener('drop', e => {
208
+ if (!hasFiles(e)) return;
209
+ e.preventDefault(); e.stopPropagation();
210
+ wrap.classList.remove('dragover');
211
+ const file = e.dataTransfer.files[0];
212
+ if (!file) return;
213
+ if (!isImage(file)) { errorHTML = T.imageError; update(); return; }
214
+ setFile(file);
215
+ });
216
+
217
+ update();
218
+ return {
219
+ el,
220
+ focus() { (nameBox.hidden ? el.querySelector('[data-act="choose"]') : nameInput)?.focus({ preventScroll: true }); },
221
+ /* 963369 onPaste(451753 u:先看文件,再看文字) */
222
+ paste(e) {
223
+ if (!allowUrlPaste || image || e.target === nameInput) return;
224
+ e.preventDefault();
225
+ const files = [...(e.clipboardData?.files || [])];
226
+ if (files.length) {
227
+ if (!isImage(files[0])) { errorHTML = T.imageError; update(); return; }
228
+ setFile(files[0]);
229
+ return;
230
+ }
231
+ const text = e.clipboardData?.getData('text/plain');
232
+ if (text) tryUrl(text);
233
+ },
234
+ };
235
+ }