flea-qml 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
@@ -0,0 +1,82 @@
1
+ import QtQuick
2
+ import QtQuick.Shapes
3
+ import "." as Flea
4
+ import "js/Icons.js" as Icons
5
+ import "js/Markdown.js" as Markdown
6
+
7
+ // The board's placeholder spans the content with a dashed muted box around a left-aligned muted image glyph and sentence on one line.
8
+ Item {
9
+ id: root
10
+
11
+ // The blocked image's host, which the sentence names.
12
+ property string host: ""
13
+ // RenderedPreviews' remote box is a 1 px CSS dashed border: 3 px dashes with 3 px gaps.
14
+ readonly property int dashPx: 3
15
+ readonly property int dashPitch: 2 * root.dashPx
16
+ // The delegate sets the width; the dashes and the sentence follow it.
17
+ height: remoteRow.implicitHeight + 2 * Theme.spacing.gap
18
+
19
+ // The dashes a side of this length holds, laid from its corner: the last one ends at the returned offset.
20
+ // Sample input: 20 answers 15, three dashes at 0, 6 and 12 ending at 15.
21
+ function dashEnd(length) {
22
+ return (Math.max(1, Math.floor((length + root.dashPx) / root.dashPitch)) - 1) * root.dashPitch + root.dashPx
23
+ }
24
+
25
+ // The four sides as SVG subpaths, each dashing from its own corner and running half a stroke inside the box.
26
+ // Sample input: (20, 10) with a 1 px hairline answers "M0 0.5 L15 0.5 M0 9.5 L15 9.5 M0.5 0 L0.5 9 M19.5 0 L19.5 9".
27
+ function borderPath(w, h) {
28
+ var half = Theme.spacing.hairline / 2
29
+ var across = root.dashEnd(w)
30
+ var down = root.dashEnd(h)
31
+ return "M0 " + half + " L" + across + " " + half + " M0 " + (h - half) + " L" + across + " " + (h - half)
32
+ + " M" + half + " 0 L" + half + " " + down + " M" + (w - half) + " 0 L" + (w - half) + " " + down
33
+ }
34
+
35
+ // One Shape draws all four sides, so a wide card builds a handful of objects instead of a Rectangle per dash.
36
+ Shape {
37
+ id: dashes
38
+ anchors.fill: parent
39
+
40
+ ShapePath {
41
+ strokeColor: Theme.color.mutedFrame
42
+ strokeWidth: Theme.spacing.hairline
43
+ fillColor: "transparent"
44
+ strokeStyle: ShapePath.DashLine
45
+ // A dash is dashPx long in units of the stroke width, which the hairline sets.
46
+ dashPattern: [root.dashPx / Theme.spacing.hairline, root.dashPx / Theme.spacing.hairline]
47
+ capStyle: ShapePath.FlatCap
48
+ PathSvg { path: root.borderPath(root.width, root.height) }
49
+ }
50
+ }
51
+
52
+ Row {
53
+ id: remoteRow
54
+ anchors.left: parent.left
55
+ anchors.leftMargin: Theme.spacing.gap
56
+ anchors.right: parent.right
57
+ anchors.rightMargin: Theme.spacing.gap
58
+ anchors.verticalCenter: parent.verticalCenter
59
+ spacing: Theme.spacing.gap
60
+
61
+ Flea.Glyph {
62
+ id: remoteMark
63
+ anchors.verticalCenter: parent.verticalCenter
64
+ width: Theme.chromeMarkSize
65
+ height: Theme.chromeMarkSize
66
+ maxSize: Theme.chromeMarkSize
67
+ name: Icons.glyphFor("image-x-generic")
68
+ color: Theme.color.mutedFrame
69
+ }
70
+
71
+ Text {
72
+ anchors.verticalCenter: parent.verticalCenter
73
+ width: parent.width - remoteMark.width - parent.spacing
74
+ text: Markdown.placeholder(root.host)
75
+ color: Theme.color.muted
76
+ font.family: Theme.font.family
77
+ font.pixelSize: Theme.font.caption
78
+ textFormat: Text.PlainText
79
+ elide: Text.ElideRight
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,155 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/CodeRuns.js" as CodeRuns
4
+
5
+ // The Source view: the file's lines coloured by the backend's code engine and numbered, asked a screen at a time through CodeLines.
6
+ Item {
7
+ id: root
8
+
9
+ // The whole text, empty while Rendered shows; a save changes it, so the lines are asked again.
10
+ property string text: ""
11
+ property string path: ""
12
+ // True on network and phone storage, where the backend is never given the path.
13
+ property bool truncate: false
14
+ property var backend: null
15
+ // The backend's name for this pane's Source ask, so a sibling pane's ask never ends it.
16
+ property string slot: "look"
17
+ property bool active: false
18
+ // The document's read or listing-size refusal also applies when no code request can be made.
19
+ property bool tooLarge: false
20
+ property bool readFailed: false
21
+ // The wrap the code view uses: a long line ends in an ellipsis until w wraps it.
22
+ property bool wrap: false
23
+ property int insetX: 0
24
+ property int insetY: 0
25
+ // The notice drawn above the first line, empty for none, and the gap between it and the text.
26
+ property string notice: ""
27
+ property int blockGap: 0
28
+ property int bodyPx: Theme.font.body
29
+ // The lines are built on the first Source view and kept after it, so a Rendered file builds no CodeLines.
30
+ property bool built: false
31
+ Component.onCompleted: root.built = root.active
32
+ onActiveChanged: if (root.active) root.built = true
33
+ readonly property bool engine: root.backend !== null && typeof root.backend.askCode === "function"
34
+ // The CodeLines once built, null before.
35
+ readonly property var lines: frame.item !== null ? frame.item.lines : null
36
+ // CodeLines' scrolling view, which the scroll bar and the wheel read.
37
+ readonly property var list: frame.item !== null ? frame.item.list : null
38
+ readonly property bool binary: root.lines !== null && root.lines.answer === "binary"
39
+ readonly property bool large: root.tooLarge || (root.lines !== null && root.lines.answer === "large")
40
+ readonly property bool failed: root.readFailed || (root.lines !== null && root.lines.answer === "failed")
41
+ readonly property bool refused: root.binary || root.large || root.failed
42
+ readonly property string status: root.large ? "This file is too large to preview." : root.failed ? "This file could not be read." : root.firstScreen ? "ready" : "loading"
43
+ // Characters of the rows the list lays out, re-read as it scrolls or an answer lands.
44
+ readonly property int laidChars: root.list === null ? 0 : root.laidOf(root.list.contentY, root.lines.stamp)
45
+ // Lines in view are answered; a file the backend refused (binary, large, failed) has no lines, so it is no screen to wait for.
46
+ readonly property bool firstScreen: root.refused || (root.lines !== null && root.lines.firstScreen)
47
+ readonly property Item noticeItem: root.list !== null && root.list.headerItem !== null ? root.list.headerItem.notice : null
48
+
49
+ function laidOf(top, stamp) {
50
+ var n = 0
51
+ var rows = root.list.contentItem.children
52
+ for (var i = 0; i < rows.length; i++)
53
+ if (rows[i].index !== undefined && rows[i].children.length === 2) {
54
+ var runs = root.lines.rowAt(rows[i].index + 1)
55
+ if (runs) n += CodeRuns.plain(runs).length
56
+ }
57
+ return n
58
+ }
59
+ function keepTop(top) {
60
+ root.list.forceLayout()
61
+ root.list.positionViewAtIndex(top, ListView.Beginning)
62
+ }
63
+ // The line at the top of the view stays at the top while the rows change width.
64
+ onWrapChanged: if (root.list !== null) Qt.callLater(root.keepTop, Math.max(0, root.list.indexAt(0, root.list.contentY + 1)))
65
+
66
+ // The notice sits above the first line and scrolls with the rows, so the list never moves under a change to it.
67
+ Component {
68
+ id: noticeHeader
69
+
70
+ Item {
71
+ id: noticeRow
72
+ // The notice's Text, which the pane and the suites read for its place.
73
+ readonly property Item notice: deepNotice
74
+ width: ListView.view.width
75
+ height: root.notice !== "" ? deepNotice.height + root.blockGap : 0
76
+ visible: root.notice !== ""
77
+ onHeightChanged: if (root.list !== null && root.notice !== "") Qt.callLater(root.list.positionViewAtBeginning)
78
+
79
+ Text {
80
+ id: deepNotice
81
+ width: noticeRow.width
82
+ visible: root.notice !== ""
83
+ text: root.notice
84
+ textFormat: Text.PlainText
85
+ elide: Text.ElideRight
86
+ color: Theme.color.muted
87
+ font.family: Theme.font.family
88
+ font.pixelSize: Theme.font.caption
89
+ }
90
+ }
91
+ }
92
+
93
+ // Without an engine the backend cannot colour a line, so the text the caller holds is drawn plain.
94
+ Loader {
95
+ id: frame
96
+ anchors.fill: parent
97
+ active: root.built
98
+
99
+ sourceComponent: Item {
100
+ id: frameItem
101
+ anchors.fill: parent
102
+ property alias lines: codeLines
103
+ Component.onCompleted: Qt.callLater(frameItem.list.positionViewAtBeginning)
104
+ // CodeLines' scrolling view, its one Flickable child.
105
+ readonly property var list: {
106
+ var kids = codeLines.children
107
+ for (var i = 0; i < kids.length; i++)
108
+ if (kids[i].contentY !== undefined) return kids[i]
109
+ return null
110
+ }
111
+
112
+ Flea.CodeLines {
113
+ id: codeLines
114
+ anchors.fill: parent
115
+ anchors.leftMargin: root.insetX
116
+ anchors.rightMargin: root.insetX
117
+ anchors.topMargin: root.insetY
118
+ anchors.bottomMargin: root.insetY
119
+ visible: !root.refused
120
+ backend: root.backend
121
+ slot: root.slot
122
+ path: root.path
123
+ fromText: root.truncate || !root.engine
124
+ text: root.text
125
+ active: root.active && !root.tooLarge
126
+ numbered: true
127
+ wrap: root.wrap
128
+ scrolls: true
129
+ pixelSize: root.bodyPx
130
+ header: noticeHeader
131
+ }
132
+
133
+ // The wheel and the bar belong to the frame, as in Rendered: the bar sits on the frame edge beside the list's top.
134
+ Flea.FastScrollHandler {
135
+ flickable: frameItem.list
136
+ visible: !root.refused
137
+ }
138
+
139
+ Flea.ViewportScrollBar {
140
+ anchors { top: parent.top; topMargin: root.insetY; right: parent.right }
141
+ flickable: frameItem.list
142
+ visible: !root.refused
143
+ }
144
+ }
145
+ }
146
+
147
+ Flea.CodeRefusal {
148
+ anchors.fill: parent
149
+ visible: root.refused
150
+ binary: root.binary
151
+ tooLarge: root.large
152
+ failed: root.failed
153
+ markName: "markdown"
154
+ }
155
+ }
@@ -0,0 +1,222 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/Markdown.js" as Markdown
4
+ import "js/MarkdownTableFit.js" as Fit
5
+ import "js/Scroll.js" as Scroll
6
+
7
+ // A table hugs its cells with Grid, Column and Row, never QtQuick.Layouts, so the preview never loads it.
8
+ Column {
9
+ id: root
10
+ objectName: "tableGrid"
11
+
12
+ // The parsed table chunk, and the preview that sets the document's size and gap.
13
+ property var block: ({ head: [], aligns: [], rows: [], measure: [], pictures: [], weights: [], words: [], cols: 0 })
14
+ property Item preview: null
15
+ // The width the block column gives the table; columns wrap inside it, and 0 means no limit.
16
+ property real availableWidth: 0
17
+ readonly property int bodyPx: root.preview.bodyPx
18
+ // A chunk after the first sits flush under its predecessor, across the gap the list puts between blocks.
19
+ y: root.block.joined === true ? -root.preview.blockGap : 0
20
+ // A table wider than its block clips to the block and scrolls sideways; the bar's lane is reserved under it, once under a chunked table's last chunk, and under no fitting table.
21
+ width: root.overflows ? root.availableWidth : root.tableWidth
22
+ clip: root.overflows
23
+ readonly property bool lane: root.overflows && root.block.last !== false
24
+ bottomPadding: root.lane ? Theme.spacing.rowPaddingX : 0
25
+ spacing: 0
26
+
27
+ // The sideways scroll, built when the table overflows and dropped when it stops: a table that fits owns no object for it, which the block cost gates count.
28
+ property Item scroller: null
29
+ function syncScroller() {
30
+ if (root.scroller === null && root.overflows) {
31
+ root.scroller = Qt.createComponent("MarkdownTableScroll.qml").createObject(root, { table: root })
32
+ } else if (root.scroller !== null && !root.overflows) {
33
+ root.scroller.destroy()
34
+ root.scroller = null
35
+ }
36
+ }
37
+ onOverflowsChanged: root.syncScroller()
38
+ Component.onCompleted: root.syncScroller()
39
+ // Every row slides by the scroll position under the clip, so a table that fits sits at zero.
40
+ readonly property real shift: root.overflows && root.scroller !== null ? -root.scroller.contentX : 0
41
+
42
+ Row {
43
+ id: headerRow
44
+ x: root.shift
45
+ spacing: root.cellGap
46
+
47
+ Repeater {
48
+ model: root.block.head.length
49
+ delegate: Flea.MarkdownText {
50
+ linkGate: Markdown.isExternalLink
51
+ width: root.textWidth(index)
52
+ bodyPx: root.bodyPx
53
+ cellPad: 2
54
+ markdown: root.block.head[index]
55
+ horizontalAlignment: root.alignAt(index)
56
+ font.bold: true
57
+ color: Theme.color.foregroundBright
58
+ }
59
+ }
60
+ }
61
+
62
+ Rectangle {
63
+ visible: root.block.head.length > 0
64
+ x: root.shift
65
+ width: root.tableWidth
66
+ height: Theme.spacing.hairline
67
+ color: Theme.color.foreground
68
+ opacity: root.preview.ruleOpacity
69
+ }
70
+
71
+ Repeater {
72
+ id: bodyRows
73
+ model: root.block.rows.length
74
+ delegate: Column {
75
+ readonly property int row: index
76
+ x: root.shift
77
+ width: root.tableWidth
78
+ spacing: 0
79
+
80
+ Row {
81
+ spacing: root.cellGap
82
+
83
+ Repeater {
84
+ model: root.columns
85
+ delegate: Flea.MarkdownText {
86
+ linkGate: Markdown.isExternalLink
87
+ width: root.textWidth(index)
88
+ bodyPx: root.bodyPx
89
+ cellPad: 2
90
+ markdown: root.cellAt(row, index)
91
+ horizontalAlignment: root.alignAt(index)
92
+ }
93
+ }
94
+ }
95
+
96
+ Rectangle {
97
+ width: root.tableWidth
98
+ height: Theme.spacing.hairline
99
+ color: Theme.color.foreground
100
+ opacity: root.preview.ruleOpacity
101
+ }
102
+ }
103
+ }
104
+
105
+ // Invisible measurers carry each column's widest cell plus a second for an image cell, since the parser cannot know the image's width.
106
+ Repeater {
107
+ id: measurers
108
+ model: root.measureTexts
109
+ delegate: Text {
110
+ objectName: "measurer"
111
+ visible: false
112
+ text: modelData
113
+ textFormat: Text.MarkdownText
114
+ font.family: Theme.font.family
115
+ font.pixelSize: root.bodyPx
116
+ // A header cell may set the width and is bold, so every measurer is: chunks without the header must agree.
117
+ font.bold: true
118
+ }
119
+ }
120
+
121
+ // The measure of each column, then the picture cell of every column that has one, in the order the measurers are built.
122
+ readonly property var measureTexts: {
123
+ var texts = []
124
+ var pictures = root.block.pictures || []
125
+ for (var c = 0; c < root.columns; c++)
126
+ texts.push(c < root.block.measure.length ? root.block.measure[c] : "")
127
+ for (var p = 0; p < root.columns; p++) {
128
+ if (p < pictures.length && pictures[p] !== "")
129
+ texts.push(pictures[p])
130
+ }
131
+ return texts
132
+ }
133
+ // The empty gap each column keeps beside its text, and the width of one glyph when the parser measured no text.
134
+ readonly property int cellGap: 14
135
+ readonly property real fallbackGlyphEm: 0.6
136
+ // A column's text width: the wider of its measure and its picture cell, once the measurers have laid out.
137
+ readonly property var columnPx: {
138
+ // Count and implicitWidth notify when a measurer arrives and lays out; itemAt alone notifies nothing.
139
+ var widths = []
140
+ var pictures = root.block.pictures || []
141
+ var next = root.columns
142
+ for (var c = 0; c < root.columns; c++) {
143
+ var own = measurers.count > c ? measurers.itemAt(c) : null
144
+ var px = own ? own.implicitWidth : 0
145
+ if (c < pictures.length && pictures[c] !== "") {
146
+ var extra = measurers.count > next ? measurers.itemAt(next) : null
147
+ px = Math.max(px, extra ? extra.implicitWidth : 0)
148
+ next++
149
+ }
150
+ widths.push(px)
151
+ }
152
+ return widths
153
+ }
154
+ // A column's text width beside its picture width: the parser weighs text alone, so the glyph price divides text by text.
155
+ readonly property var textPx: {
156
+ // Count and implicitWidth notify when a measurer arrives and lays out; itemAt alone notifies nothing.
157
+ var widths = []
158
+ for (var c = 0; c < root.columns; c++) {
159
+ var own = measurers.count > c ? measurers.itemAt(c) : null
160
+ widths.push(own ? own.implicitWidth : 0)
161
+ }
162
+ return widths
163
+ }
164
+ // Pixels a column of the parser's width weight draws: the table's measured text over its weight, so the longest word converts to pixels.
165
+ readonly property real glyphPx: {
166
+ var px = 0
167
+ var weight = 0
168
+ var weights = root.block.weights || []
169
+ for (var c = 0; c < root.columns; c++) {
170
+ if (c < weights.length && weights[c] > 0) {
171
+ px += root.textPx[c]
172
+ weight += weights[c]
173
+ }
174
+ }
175
+ return weight > 0 ? px / weight : root.bodyPx * root.fallbackGlyphEm
176
+ }
177
+ // Each column's width: natural when the table fits the block, else shared by Fit with every column keeping its longest word first.
178
+ readonly property var widths: {
179
+ var natural = []
180
+ var minimum = []
181
+ var words = root.block.words || []
182
+ for (var c = 0; c < root.columns; c++) {
183
+ // Whole pixels up: Fit floors its shares, and a text box a fraction short of its word breaks the word.
184
+ natural.push(Math.ceil(root.columnPx[c]) + root.cellGap)
185
+ minimum.push(Math.ceil((c < words.length ? words[c] : 0) * root.glyphPx) + root.cellGap)
186
+ }
187
+ // A wide glyph takes two, so no column goes under two glyphs of text.
188
+ var least = root.cellGap + Math.ceil(2 * root.glyphPx)
189
+ return root.availableWidth > 0 ? Fit.fit(natural, minimum, root.availableWidth, least) : natural
190
+ }
191
+ readonly property real tableWidth: {
192
+ var total = 0
193
+ for (var c = 0; c < root.widths.length; c++)
194
+ total += root.widths[c]
195
+ return total
196
+ }
197
+ // Wider than its block once every column holds its longest word whole; the block's width then bounds the table.
198
+ readonly property bool overflows: root.availableWidth > 0 && root.tableWidth - root.availableWidth > Scroll.OVERFLOW_PX
199
+
200
+ // The first body row, which the capture's IPC aims its wheel at.
201
+ function firstRow() { return bodyRows.itemAt(0) }
202
+
203
+ // Helpers over the block, so delegates read cells and alignment by place.
204
+ readonly property int columns: Math.max(1, root.block.cols)
205
+ function alignName(i) {
206
+ return i < root.block.aligns.length ? root.block.aligns[i] : "left"
207
+ }
208
+ function alignAt(i) {
209
+ var name = root.alignName(i)
210
+ return name === "center" ? Text.AlignHCenter : name === "right" ? Text.AlignRight : Text.AlignLeft
211
+ }
212
+ function cellAt(r, c) {
213
+ return r < root.block.rows.length && c < root.block.rows[r].length ? root.block.rows[r][c] : ""
214
+ }
215
+ function colWidth(col) {
216
+ return col < root.widths.length ? root.widths[col] : 0
217
+ }
218
+ // A cell's text stays inside its column's share minus the gap the next cell starts after, so the gap never holds ink.
219
+ function textWidth(col) {
220
+ return Math.max(0, root.colWidth(col) - root.cellGap)
221
+ }
222
+ }
@@ -0,0 +1,64 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/Scroll.js" as Scroll
4
+
5
+ // The sideways scroll of a table wider than its block: the position and extent the table's rows slide by, the bar under the table, and the wheel's arithmetic.
6
+ Flickable {
7
+ id: root
8
+ objectName: "tableScroll"
9
+
10
+ required property Item table
11
+
12
+ // A sibling of the table in the block, laid over it. A positioner would stack it as a row, so under one it takes the positioner's parent and offset.
13
+ readonly property Item flow: root.table.parent !== null && root.table.parent.move !== undefined ? root.table.parent : null
14
+ // The key every chunk of one table shares, undefined for a table in one piece.
15
+ readonly property var group: root.table.block.tableKey
16
+ parent: root.flow !== null ? root.flow.parent : root.table.parent
17
+ x: root.table.x + (root.flow !== null ? root.flow.x : 0)
18
+ y: root.table.y + (root.flow !== null ? root.flow.y : 0)
19
+ z: 1
20
+ width: root.table.width
21
+ height: root.table.height
22
+ contentWidth: root.table.tableWidth
23
+ contentHeight: root.height
24
+ // Only the wheel and the bar move it: a disabled item takes none of the presses the table's links and cells need.
25
+ enabled: false
26
+ // The chunks of one table follow one position, whichever of them the wheel is over.
27
+ onContentXChanged: if (root.route !== null) root.route.follow(root)
28
+ onWidthChanged: root.returnToBounds()
29
+ onContentWidthChanged: root.returnToBounds()
30
+
31
+ // The router calls this for a stroke it gave the table, since the disabled handler below gets no event of its own.
32
+ function wheel(event) {
33
+ return wheelHandler.handleWheel(event)
34
+ }
35
+
36
+ // Kept from the start, since the table is already going when this is destroyed with it.
37
+ property Item route: null
38
+ Component.onCompleted: {
39
+ root.route = root.table.preview !== null && root.table.preview.tableWheel ? root.table.preview.tableWheel : null
40
+ if (root.route !== null)
41
+ root.route.add(root)
42
+ }
43
+ Component.onDestruction: {
44
+ if (root.route !== null)
45
+ root.route.remove(root)
46
+ }
47
+
48
+ Flea.FastScrollHandler {
49
+ id: wheelHandler
50
+ parent: root
51
+ flickable: root
52
+ }
53
+
54
+ // The bar draws under the table, in the lane the table reserved; the lane shows it only while moving, hovered or dragged.
55
+ Flea.ViewportScrollBar {
56
+ parent: root.parent
57
+ // Only the last chunk of a table holds the lane, so a joined chunk stays flush under the one above.
58
+ visible: root.table.lane && root.contentWidth - root.width > Scroll.OVERFLOW_PX
59
+ x: root.x
60
+ y: root.y + root.height - height
61
+ flickable: root
62
+ orientation: Qt.Horizontal
63
+ }
64
+ }
@@ -0,0 +1,126 @@
1
+ import QtQuick
2
+ import "js/Scroll.js" as Scroll
3
+
4
+ // A wheel or swipe that goes sideways over a table wider than its block scrolls that table; a vertical one is left for the document's handler beneath.
5
+ MouseArea {
6
+ id: root
7
+ objectName: "tableWheel"
8
+
9
+ // The sideways scrolls alive in the document, which each adds itself to and drops itself from.
10
+ property var scrollers: []
11
+ // The table a touchpad stroke went to until it ends, and whether the stroke went to the document instead.
12
+ property var held: null
13
+ property bool documentStroke: false
14
+ // The sideways position each chunked table was last left at, by key, so a chunk built later joins it.
15
+ property var positions: ({})
16
+
17
+ anchors.fill: parent
18
+ // A press is never taken: the table's links and the document's own handler need them.
19
+ acceptedButtons: Qt.NoButton
20
+ // Over the document's FastScrollHandler (z 1000), so a sideways stroke reaches the table first.
21
+ z: 1001
22
+
23
+ function add(scroller) {
24
+ root.scrollers = root.scrollers.concat([scroller])
25
+ if (scroller.group !== undefined && root.positions[scroller.group] !== undefined)
26
+ scroller.contentX = root.positions[scroller.group]
27
+ }
28
+
29
+ // The other chunks of this scroller's table move to its position.
30
+ function follow(scroller) {
31
+ if (scroller.group === undefined)
32
+ return
33
+ root.positions[scroller.group] = scroller.contentX
34
+ for (var i = 0; i < root.scrollers.length; i++) {
35
+ var other = root.scrollers[i]
36
+ if (other && other !== scroller && other.group === scroller.group && other.contentX !== scroller.contentX)
37
+ other.contentX = scroller.contentX
38
+ }
39
+ }
40
+
41
+ function remove(scroller) {
42
+ root.scrollers = root.scrollers.filter(function (s) { return s && s !== scroller })
43
+ if (root.held === scroller)
44
+ root.held = null
45
+ }
46
+
47
+ // A new document forgets the old one's sideways places; chunks of the live one still join.
48
+ function reset() {
49
+ root.positions = {}
50
+ }
51
+
52
+ // The overflowing table under a point of this item, else null.
53
+ function scrollerAt(x, y) {
54
+ for (var i = 0; i < root.scrollers.length; i++) {
55
+ var s = root.scrollers[i]
56
+ if (!s || !s.visible || !s.table || !s.table.overflows)
57
+ continue
58
+ var at = s.mapFromItem(root, x, y)
59
+ if (at.x >= 0 && at.y >= 0 && at.x < s.width && at.y < s.height)
60
+ return s
61
+ }
62
+ return null
63
+ }
64
+
65
+ // The sideways distance of an event: Shift turns a vertical wheel notch sideways, as it does in a browser.
66
+ function across(event, axis) {
67
+ var pixel = Number(event.pixelDelta.x) || 0
68
+ var angle = Number(event.angleDelta.x) || 0
69
+ if ((event.modifiers & Qt.ShiftModifier) && pixel === 0 && angle === 0)
70
+ return axis === "pixel" ? Number(event.pixelDelta.y) || 0 : Number(event.angleDelta.y) || 0
71
+ return axis === "pixel" ? pixel : angle
72
+ }
73
+
74
+ // Sideways when its sideways travel beats its vertical in the unit the event carries, or Shift holds a notch; Shift on a vertical notch is sideways.
75
+ function sideways(event) {
76
+ var pixel = (Number(event.pixelDelta.x) || 0) !== 0 || (Number(event.pixelDelta.y) || 0) !== 0
77
+ var x = Math.abs(root.across(event, pixel ? "pixel" : "angle"))
78
+ var y = Math.abs(Number(pixel ? event.pixelDelta.y : event.angleDelta.y) || 0)
79
+ return (event.modifiers & Qt.ShiftModifier) ? x !== 0 : x > y
80
+ }
81
+
82
+ // A table's wheel takes sideways deltas only; the vertical ones stay with the document.
83
+ function sidewaysEvent(event) {
84
+ return { pixelDelta: { x: root.across(event, "pixel"), y: 0 }, angleDelta: { x: root.across(event, "angle"), y: 0 },
85
+ modifiers: event.modifiers & ~Qt.ShiftModifier, phase: event.phase !== undefined ? event.phase : Qt.NoScrollPhase, accepted: false }
86
+ }
87
+
88
+ // True when the table took the event; a false answer leaves it to the document's handler under this one.
89
+ function route(event) {
90
+ if (event.modifiers & Qt.ControlModifier)
91
+ return false
92
+ var phase = event.phase !== undefined ? event.phase : Qt.NoScrollPhase
93
+ var at = root.scrollerAt(event.x, event.y)
94
+ if (!Scroll.isTouchpad(phase)) {
95
+ if (at === null || !root.sideways(event))
96
+ return false
97
+ at.wheel(root.sidewaysEvent(event))
98
+ return true
99
+ }
100
+ if (phase === Qt.ScrollBegin) {
101
+ root.held = null
102
+ root.documentStroke = false
103
+ // The table stops its own coasting on a new touch, and the document hears the Begin as well.
104
+ if (at !== null)
105
+ at.wheel(root.sidewaysEvent(event))
106
+ return false
107
+ }
108
+ if (root.held === null && !root.documentStroke && phase !== Qt.ScrollEnd) {
109
+ if (at !== null && root.sideways(event))
110
+ root.held = at
111
+ else if ((Number(event.pixelDelta.x) || 0) !== 0 || (Number(event.pixelDelta.y) || 0) !== 0)
112
+ root.documentStroke = true
113
+ }
114
+ var taker = root.held
115
+ if (phase === Qt.ScrollEnd) {
116
+ root.held = null
117
+ root.documentStroke = false
118
+ }
119
+ if (taker === null)
120
+ return false
121
+ taker.wheel(root.sidewaysEvent(event))
122
+ return true
123
+ }
124
+
125
+ onWheel: function (wheel) { wheel.accepted = root.route(wheel) }
126
+ }