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,67 @@
1
+ import QtQuick
2
+ import "js/Drag.js" as DragOps
3
+
4
+ // The rail's Trash SidebarRow trashes rows dragged from this window through ui/js/TrashDrop.js; it lives outside the group-indexed ui/Sidebar.qml, which sits at its recorded ceiling.
5
+ SidebarRow {
6
+ id: root
7
+
8
+ required property var rail
9
+ readonly property int railIndex: root.index + root.rail.homeLead.length + root.rail.recentEntries.length + root.rail.homeRest.length
10
+ readonly property var pane: root.rail.navigationPane
11
+ // Exposed so ui/PaneRail.qml keeps an overlay rail up while a drag rests on this row.
12
+ readonly property bool dragOver: target.containsDrag
13
+
14
+ // The drop cue is separate from the rail's own location and keyboard cursor.
15
+ lit: root.railIndex === root.rail.litIndex
16
+ highlighted: root.railIndex === root.rail.highlightedIndex
17
+ cursor: root.rail.cursorDrawn && root.railIndex === root.rail.cursorIndex
18
+ focused: root.rail.focused
19
+ trailingLabel: dropLoader.item ? dropLoader.item.label : null
20
+ onActivated: root.rail.activate(root.railIndex)
21
+ onMenuRequested: function (idx, pos) { root.rail.openRailMenu(root.railIndex, pos) }
22
+
23
+ function dropDecisions() {
24
+ if (feedback.item) return feedback.item
25
+ feedback.setSource(Qt.resolvedUrl("TrashDropHandler.qml"), { pane: Qt.binding(function () { return root.pane }) })
26
+ feedback.active = true
27
+ return feedback.item
28
+ }
29
+
30
+ Loader {
31
+ id: feedback
32
+ active: false
33
+ onStatusChanged: if (status === Loader.Error) console.warn("TrashDropHandler.qml did not load: Loader status " + status)
34
+ }
35
+
36
+ Loader {
37
+ id: dropLoader
38
+ active: root.dragOver
39
+ anchors.fill: parent
40
+ // TrashDrop always moves to Trash, regardless of the drag's copy or link modifiers.
41
+ onActiveChanged: dropLoader.setSource(dropLoader.active ? Qt.resolvedUrl("DropTarget.qml") : "", { text: DragOps.label(false, false) })
42
+ onStatusChanged: if (status === Loader.Error) throw new Error("DropTarget.qml did not load: Loader status " + status)
43
+ }
44
+
45
+ DropArea {
46
+ id: target
47
+ anchors.fill: parent
48
+ keys: [DragOps.ROWS_MIME]
49
+ onEntered: function (drag) {
50
+ var marker = drag.getDataAsString(DragOps.ROWS_MIME)
51
+ var decisions = root.dropDecisions()
52
+ if (!root.pane || !decisions || !decisions.accepts(marker, drag.urls, root.pane.path)) {
53
+ drag.accepted = false
54
+ return
55
+ }
56
+ decisions.feedback = DragOps.feedbackFor(marker, drag.urls, "")
57
+ decisions.say(decisions.line(marker, drag.urls, root.pane.path))
58
+ }
59
+ onExited: if (feedback.item) feedback.item.leaveTarget()
60
+ onDropped: function (drop) {
61
+ var decisions = root.dropDecisions()
62
+ if (decisions && decisions.drop(root.pane, drop.getDataAsString(DragOps.ROWS_MIME), drop.urls))
63
+ drop.accept(Qt.CopyAction)
64
+ if (decisions) decisions.leaveTarget()
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,353 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+
4
+ // The row becoming its own editor, per the States artboard: an accent frame around the name, the
5
+ // extension muted inside that frame, enter commits and escape abandons.
6
+ //
7
+ // A TextInput cannot colour part of its own text, and splitting the extension into a second,
8
+ // non-editable Text would stop the operator renaming a.txt to a.md. So the whole name stays editable
9
+ // and the extension is painted over it: positionToRectangle gives the exact x of the boundary, an
10
+ // opaque patch covers what the field drew there, and the muted copy goes on top. The patch yields
11
+ // whenever there is a selection to render, so selection is never hidden by it.
12
+ Item {
13
+ id: root
14
+
15
+ property string name: ""
16
+ property var pane: null
17
+ property var viewport: null
18
+ property Item editorHost: null
19
+ property bool containOnBegin: false
20
+ // GridTile supplies the first measurement later; zero would collapse an expanded predecessor.
21
+ property real extraHeight: -1
22
+ readonly property string errorText: pane ? pane.renameError : ""
23
+ readonly property bool pending: pane ? pane.renamePending : false
24
+ readonly property real errorHeight: errorText.length > 0 ? errorLabel.implicitHeight + Theme.spacing.gap : 0
25
+ readonly property real fieldHeight: height - errorHeight
26
+ readonly property alias inputItem: field
27
+ // The editor's frame and the extension's patch, so a test measures the patch against the frame's four sides.
28
+ readonly property alias frame: editFrame
29
+ readonly property alias extensionPatch: mutedExtension
30
+ // The selection drawn as one box that fills the frame's interior, so a test measures it against the frame.
31
+ readonly property alias selectionBox: selectionFill
32
+ // The error line's width where the host gives it more than the field, or -1 for the field's own.
33
+ property real errorSpan: -1
34
+ // The one height every host draws: the row's line box, or the typed line and two hairlines where a small stop's is shorter.
35
+ readonly property real lineBox: Math.max(Theme.rowHeight - 2 * Theme.spacing.rowPaddingY,
36
+ Math.ceil(typedLine.height) + 2 * Theme.spacing.hairline)
37
+ implicitHeight: root.lineBox + errorHeight
38
+
39
+ signal committed(string newName)
40
+ signal abandoned()
41
+
42
+ // Read off what is in the field right now, not off the name it opened with, so the muted run
43
+ // follows an edit that changes where the extension starts.
44
+ readonly property string current: field.text
45
+ readonly property int dot: root.current.lastIndexOf(".")
46
+ readonly property int stemEnd: root.dot > 0 ? root.dot : root.current.length
47
+ readonly property string extension: root.current.substring(root.stemEnd)
48
+
49
+ // Set by begin(), so a hide can only abandon an edit that began; see onVisibleChanged below.
50
+ property bool begun: false
51
+ property bool beginning: false
52
+ property int editIndex: -1
53
+ property string editName: ""
54
+ property var editPane: null
55
+ property var editViewport: null
56
+ property bool containmentQueued: false
57
+ property bool containing: false
58
+ onExtraHeightChanged: if (root.containOnBegin && root.viewport && root.viewport.queueRenameLayout)
59
+ root.viewport.queueRenameLayout()
60
+
61
+ function ownsEdit() {
62
+ return root.begun && root.name === root.editName
63
+ && root.pane === root.editPane && root.viewport === root.editViewport
64
+ && (!root.pane || root.pane.renamingIndex === root.editIndex)
65
+ && (!root.containOnBegin || !root.viewport || root.viewport.renameEditor === root)
66
+ }
67
+
68
+ function viewportOwnsFocus() {
69
+ return root.containOnBegin && root.viewport && root.viewport.activeFocus
70
+ && root.viewport.visible && !root.viewport.hiddenHeld
71
+ }
72
+
73
+ // A retained delegate can be visible yet culled from Grid's scene graph. Resolve its live slot.
74
+ function layoutHost() {
75
+ if (!root.containOnBegin || !root.viewport || !root.editorHost) return root.editorHost
76
+ var current = root.viewport.currentItem
77
+ var slot = current && current.renaming ? current : root.editorHost
78
+ var host = root.viewport.itemAt(slot.x + slot.width / 2, slot.y + slot.height / 2)
79
+ var editor = host ? host.editorField : null
80
+ return editor && host.renaming && editor.pane === root.pane && editor.viewport === root.viewport
81
+ && editor.name === root.name ? host : null
82
+ }
83
+
84
+ function begin(fromLayout) {
85
+ if (root.beginning) return
86
+ if (root.begun && root.containOnBegin && root.viewport && root.viewport.renameEditor
87
+ && root.viewport.renameEditor !== root
88
+ && !(fromLayout && root.layoutHost() === root.editorHost)) return
89
+ var continuing = root.ownsEdit()
90
+ var handoff = null
91
+ var previous = root.containOnBegin && root.viewport ? root.viewport.renameEditor : null
92
+ var retirement = root.containOnBegin && root.viewport ? root.viewport.renameRetirement : null
93
+ if (!continuing && previous && previous !== root
94
+ && root.pane && previous.editPane === root.pane && previous.editViewport === root.viewport
95
+ && previous.editIndex === root.pane.renamingIndex && previous.editName === root.name
96
+ && previous.ownsEdit()) {
97
+ var input = previous.inputItem
98
+ handoff = {text: input.text, cursor: input.cursorPosition,
99
+ anchor: input.cursorPosition === input.selectionStart ? input.selectionEnd : input.selectionStart,
100
+ focused: input.activeFocus || root.viewportOwnsFocus()}
101
+ }
102
+ if (!continuing && !previous && retirement && root.pane === retirement.pane
103
+ && root.viewport === retirement.viewport && root.pane.renamingIndex === retirement.index
104
+ && root.name === retirement.name && root.pane.renameRequest === retirement.request) handoff = retirement
105
+ root.beginning = true
106
+ lifecycle.stop()
107
+ root.editIndex = root.pane ? root.pane.renamingIndex : -1
108
+ root.editName = root.name
109
+ root.editPane = root.pane
110
+ root.editViewport = root.viewport
111
+ root.containmentQueued = false
112
+ root.begun = true
113
+ // A recycled same-row delegate can begin before its predecessor has lost focus or died.
114
+ if (root.containOnBegin && root.viewport) root.viewport.renameEditor = root
115
+ if (!continuing) field.text = handoff ? handoff.text : root.name
116
+ // A menu or rail that already took focus keeps it; the lifecycle timer judges that departure.
117
+ if (!handoff || (handoff.focused && root.viewportOwnsFocus())) field.forceActiveFocus()
118
+ // The stem alone, which is the part a rename usually changes.
119
+ var cut = root.name.lastIndexOf(".")
120
+ if (handoff) field.select(handoff.anchor, handoff.cursor)
121
+ else if (!continuing) field.select(0, cut > 0 ? cut : root.name.length)
122
+ if (root.containOnBegin || root.errorText.length > 0) root.queueContainment()
123
+ root.beginning = false
124
+ }
125
+
126
+ // File validation belongs to the pane; rail labels retain their existing empty-submit behavior.
127
+ function commit() {
128
+ if (!root.ownsEdit() || !root.visible || root.pending) return false
129
+ var next = field.text.trim()
130
+ if ((!root.pane && next.length === 0) || field.text === root.name || next === root.name) {
131
+ root.abandon()
132
+ return false
133
+ }
134
+ root.committed(next)
135
+ return true
136
+ }
137
+
138
+ function queueContainment() {
139
+ if (!root.begun || root.containmentQueued) return
140
+ root.containmentQueued = true
141
+ lifecycle.restart()
142
+ }
143
+ function revealEditor() {
144
+ if (!root.ownsEdit() || !root.visible || !root.pane || !field.activeFocus) return
145
+ if (root.viewport && (!root.viewport.visible || root.viewport.hiddenHeld)) return
146
+ root.containing = true
147
+ // Grid height changes reposition every tile. Contain its final position, not the old layout.
148
+ if (root.containOnBegin && root.viewport) root.viewport.forceLayout()
149
+ if (root.ownsEdit() && root.visible && field.activeFocus) root.pane.setCursor(root.editIndex, 0)
150
+ root.containing = false
151
+ }
152
+ // Let the expanded row and Grid cell height settle before containing the complete error editor.
153
+ onErrorTextChanged: if (root.visible && root.errorText.length > 0) root.queueContainment()
154
+
155
+ // The editor arms itself rather than leaving it to each row that draws one: an Item built with
156
+ // visible already true writes true over true and emits no visibleChanged, so a delegate
157
+ // constructed mid-rename came up empty with nothing holding the caret.
158
+ Component.onCompleted: if (root.visible && !root.begun) root.begin()
159
+ Component.onDestruction: {
160
+ lifecycle.stop()
161
+ if (root.containOnBegin && root.editViewport && root.editViewport.retireRenameEditor) {
162
+ // The viewport retains values only, never a method or context belonging to this field.
163
+ var retirement = root.ownsEdit() ? {pane: root.editPane, viewport: root.editViewport,
164
+ index: root.editIndex, name: root.editName, text: field.text, cursor: field.cursorPosition,
165
+ anchor: field.cursorPosition === field.selectionStart ? field.selectionEnd : field.selectionStart,
166
+ focused: field.activeFocus || root.viewportOwnsFocus(),
167
+ request: root.editPane ? root.editPane.renameRequest : null} : null
168
+ root.begun = false
169
+ root.editViewport.retireRenameEditor(root, retirement)
170
+ } else {
171
+ root.abandon()
172
+ if (root.containOnBegin && root.editViewport && root.editViewport.renameEditor === root)
173
+ root.editViewport.renameEditor = null
174
+ }
175
+ }
176
+
177
+ // Hiding is abandoning. Qt drops effective visibility before it emits this, so the focus handler
178
+ // below can never see the case, and a hidden editor left renamingIndex set with nothing alive to
179
+ // clear it, which killed the whole window's keyboard, escape included.
180
+ onVisibleChanged: {
181
+ if (root.visible) {
182
+ root.begin()
183
+ return
184
+ }
185
+ if (root.begun) lifecycle.restart()
186
+ }
187
+
188
+ function abandon() {
189
+ if (!root.ownsEdit() || root.pending) return
190
+ root.begun = false
191
+ // The enclosing ListView is a focus scope and remembers this field as its focused child, so
192
+ // giving up what begin() took is what lets the scope itself take the keys again.
193
+ field.focus = false
194
+ root.abandoned()
195
+ }
196
+
197
+ // Child timers recheck ownership after layout and die with the field, so stale editors cannot cancel or refocus replacements.
198
+ Timer {
199
+ id: lifecycle
200
+ interval: 0
201
+ onTriggered: {
202
+ var contain = root.containmentQueued
203
+ root.containmentQueued = false
204
+ if (!root.ownsEdit()) return
205
+ if (root.containOnBegin && root.editorHost && root.viewport
206
+ && root.viewport.visible && !root.viewport.hiddenHeld) {
207
+ var host = root.layoutHost()
208
+ if (host && host !== root.editorHost) {
209
+ host.editorField.begin(true)
210
+ return
211
+ }
212
+ }
213
+ if (!root.visible || !field.activeFocus) {
214
+ if (!root.visible) field.focus = false
215
+ root.abandon()
216
+ return
217
+ }
218
+ if (contain) root.revealEditor()
219
+ if (!root.ownsEdit() || root.pending || !root.viewport || !root.viewport.visible
220
+ || root.viewport.hiddenHeld) return
221
+ var top = root.mapToItem(root.viewport, 0, 0).y
222
+ if (top + root.height > 0 && top < root.viewport.height) return
223
+ root.abandon()
224
+ }
225
+ }
226
+ function queueDeparture() {
227
+ if (!root.ownsEdit() || root.pending || !root.viewport || !root.viewport.visible
228
+ || root.viewport.hiddenHeld || root.containing) return
229
+ lifecycle.restart()
230
+ }
231
+ Connections {
232
+ target: root.viewport
233
+ function onContentYChanged() { root.queueDeparture() }
234
+ }
235
+
236
+ Rectangle {
237
+ id: editFrame
238
+ width: parent.width
239
+ height: root.fieldHeight
240
+ color: Theme.color.background
241
+ border.width: Theme.spacing.hairline
242
+ border.color: root.errorText.length > 0 ? Theme.color.error : Theme.color.accent
243
+ }
244
+
245
+ FontMetrics {
246
+ id: typedLine
247
+ font: field.font
248
+ }
249
+
250
+ // The extra arguments are read only so a layout or a scroll re-runs the binding, as mutedExtension's x does.
251
+ function edgeX(position, laidOut, scrolled) { return field.x + field.positionToRectangle(position).x }
252
+ Item {
253
+ id: selectionFill
254
+ visible: field.selectionEnd > field.selectionStart && (field.activeFocus || field.persistentSelection)
255
+ readonly property real fromX: Math.max(field.x, root.edgeX(field.selectionStart, field.contentWidth, field.cursorRectangle.x))
256
+ readonly property real toX: Math.min(field.x + field.width, root.edgeX(field.selectionEnd, field.contentWidth, field.cursorRectangle.x))
257
+ x: fromX
258
+ y: Theme.spacing.hairline
259
+ width: Math.max(0, toX - fromX)
260
+ height: root.fieldHeight - 2 * Theme.spacing.hairline
261
+
262
+ Rectangle {
263
+ anchors.fill: parent
264
+ color: Theme.color.accent
265
+ }
266
+ }
267
+
268
+ TextInput {
269
+ id: field
270
+ anchors { left: parent.left; right: parent.right; top: parent.top }
271
+ height: root.fieldHeight
272
+ anchors.leftMargin: Theme.spacing.gap
273
+ anchors.rightMargin: Theme.spacing.gap
274
+ verticalAlignment: TextInput.AlignVCenter
275
+ color: Theme.color.foreground
276
+ // The selection is painted by selectionFill, which fills the interior where the field's own stops at its line.
277
+ selectionColor: "transparent"
278
+ selectedTextColor: Theme.color.background
279
+ font.family: Theme.font.family
280
+ font.pixelSize: Theme.font.body
281
+ clip: true
282
+ readOnly: root.pending
283
+ // Grid can drop child focus before pooling; preserve the selection its replacement inherits.
284
+ persistentSelection: root.containOnBegin
285
+
286
+ // Both keys are handled and accepted here rather than through onAccepted, because an
287
+ // unaccepted Return goes on to the list's own Keys handler, which reads it as "open" and
288
+ // tries to open the row under a name the rename has just taken away.
289
+ Keys.onPressed: function (event) {
290
+ if (event.key === Qt.Key_Escape) {
291
+ root.abandon()
292
+ event.accepted = true
293
+ return
294
+ }
295
+ if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
296
+ root.commit()
297
+ event.accepted = true
298
+ }
299
+ }
300
+
301
+ // Losing Qt focus while the editor is up abandons, which is the rail's own field and the
302
+ // context menu, which takes focus as it opens. A click on another row never lands here,
303
+ // because a TapHandler moves no focus; ui/js/Tap.js commits that case explicitly.
304
+ onActiveFocusChanged: if (!activeFocus && root.begun) lifecycle.restart()
305
+ }
306
+
307
+ Text {
308
+ id: errorLabel
309
+ anchors { top: field.bottom; left: parent.left }
310
+ anchors.topMargin: Theme.spacing.gap
311
+ width: root.errorSpan >= 0 ? root.errorSpan : root.width
312
+ visible: root.errorText.length > 0
313
+ text: root.errorText
314
+ color: Theme.color.error
315
+ font.family: Theme.font.family
316
+ font.pixelSize: Theme.font.caption
317
+ textFormat: Text.PlainText
318
+ wrapMode: Text.Wrap
319
+ }
320
+
321
+ // The extension, painted over the field's own copy of it. It stands down only when a selection
322
+ // actually reaches into the extension, because a patch over selected text would hide the
323
+ // selection; the usual case, the stem selected and the extension not, keeps the muted run.
324
+ Item {
325
+ id: mutedExtension
326
+ visible: root.extension.length > 0 && field.selectionEnd <= root.stemEnd
327
+ // contentWidth is read so this re-evaluates once the field has laid the new text out.
328
+ // positionToRectangle is a method, so nothing re-runs it on its own, and begin() assigns the
329
+ // text and selects the stem in one go: the boundary was measured against the layout before
330
+ // that text existed, came back 0, and the patch covered the stem instead of the extension.
331
+ // Every view drew a rename as a bare ".txt" until the first keystroke moved the selection.
332
+ x: field.contentWidth >= 0 ? field.x + field.positionToRectangle(root.stemEnd).x : field.x
333
+ // One hairline in from the frame's top and bottom, so the patch never covers the frame's sides.
334
+ y: field.y + Theme.spacing.hairline
335
+ width: Math.max(0, field.width - (x - field.x))
336
+ height: field.height - 2 * Theme.spacing.hairline
337
+ clip: true
338
+
339
+ Rectangle {
340
+ anchors.fill: parent
341
+ color: Theme.color.background
342
+ }
343
+
344
+ Text {
345
+ anchors.verticalCenter: parent.verticalCenter
346
+ text: root.extension
347
+ color: Theme.color.muted
348
+ font.family: field.font.family
349
+ font.pixelSize: field.font.pixelSize
350
+ textFormat: Text.PlainText
351
+ }
352
+ }
353
+ }
@@ -0,0 +1,11 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ import "js/Renderer.js" as Renderer
4
+
5
+ // Loaded by file: URL when the scene graph fails, because the boot directory cannot import
6
+ // ui/js/Renderer.js through qs: and the startup path must not compile it.
7
+ QtObject {
8
+ function fallbackCommand(backendName) {
9
+ return Renderer.fallbackCommand(backendName, Quickshell.env("FLEA_RENDERER_AUTOMATIC"), Quickshell.env("FLEA_BIN"))
10
+ }
11
+ }
@@ -0,0 +1,52 @@
1
+ import QtQuick
2
+ import Quickshell
3
+
4
+ // ListColumns040 board: one grab zone over a column hairline; the caller centres it on a whole pixel, the drag lives in ui/Header.qml.
5
+ Item {
6
+ id: root
7
+
8
+ property string columnKey: ""
9
+ // True while this column's drag is in flight, held by the caller, not the press.
10
+ property bool hot: false
11
+ // The accent line's x inside the zone: the centre for a column edge, the zone's first pixel for the Dual divider.
12
+ property real lineX: (width - Theme.spacing.hairline) / 2
13
+ signal pressed(var mouse)
14
+ signal moved(var mouse)
15
+ signal released()
16
+ // Before released() when the grab is taken away, so a caller can tell an aborted drag from a release.
17
+ signal canceled()
18
+ signal doubleClicked()
19
+
20
+ // FLEA_TRACE_RESIZE=1 logs each press, held move, release and cancel the zone hears.
21
+ readonly property bool trace: Quickshell.env("FLEA_TRACE_RESIZE") === "1"
22
+ function note(what) { if (root.trace) console.log("RESIZE " + (root.columnKey || "divider") + " " + what) }
23
+
24
+ width: 9 // ui/Header.qml offsets each zone by floor(width / 2), so this is the only number.
25
+
26
+ MouseArea {
27
+ id: zone
28
+ anchors.fill: parent
29
+ hoverEnabled: true
30
+ acceptedButtons: Qt.LeftButton
31
+ cursorShape: Qt.SplitHCursor
32
+ // A row's DragHandler under the Dual divider would otherwise take the grab on its first move.
33
+ preventStealing: true
34
+ onPressed: function (mouse) { root.note("press"); root.pressed(mouse) }
35
+ onPositionChanged: function (mouse) { if (zone.pressed) root.note("move"); root.moved(mouse) }
36
+ onReleased: { root.note("release"); root.released() }
37
+ onCanceled: { root.note("cancel"); root.canceled(); root.released() }
38
+ onDoubleClicked: root.doubleClicked()
39
+ }
40
+
41
+ // The accent line shows only while hovered or dragged, so it builds only then; the zone stays live at rest.
42
+ Loader {
43
+ x: root.lineX
44
+ width: Theme.spacing.hairline
45
+ height: parent.height
46
+ active: zone.containsMouse || root.hot
47
+ sourceComponent: Rectangle {
48
+ anchors.fill: parent
49
+ color: Theme.color.accent
50
+ }
51
+ }
52
+ }
package/ui/Reveal.qml ADDED
@@ -0,0 +1,54 @@
1
+ import QtQuick
2
+ import "js/Motion.js" as Motion
3
+
4
+ // The one fade every dialog and menu shares: OutCubic, Motion.durMs.open in and .close out, snapped under reduced motion.
5
+ QtObject {
6
+ id: root
7
+
8
+ // The item that fades; it declares a plain `opacity: 0` and never binds it.
9
+ property Item target: null
10
+ property bool shown: false
11
+ // A dialog's card: it rises Motion.translateUpPx into place on a fresh open only, and never moves while it fades out.
12
+ property Item lift: null
13
+
14
+ // Drives target.opacity from where it stands, so a reopen during a close fades up from there and never replays the old frame.
15
+ function drive() {
16
+ if (root.target === null) return
17
+ fade.stop()
18
+ risen.stop()
19
+ if (Theme.reducedMotion) {
20
+ root.target.opacity = root.shown ? 1 : 0
21
+ rise.y = 0
22
+ return
23
+ }
24
+ if (root.shown && root.lift !== null) {
25
+ if (root.target.opacity === 0) rise.y = Motion.translateUpPx
26
+ if (rise.y !== 0) risen.start()
27
+ }
28
+ fade.to = root.shown ? 1 : 0
29
+ fade.duration = root.shown ? Motion.durMs.open : Motion.durMs.close
30
+ fade.start()
31
+ }
32
+
33
+ onShownChanged: root.drive()
34
+ Component.onCompleted: {
35
+ if (root.lift !== null) root.lift.transform = rise
36
+ if (root.shown) root.drive()
37
+ }
38
+
39
+ property Translate rise: Translate {}
40
+ property NumberAnimation fade: NumberAnimation {
41
+ target: root.target
42
+ property: "opacity"
43
+ easing.type: Easing.OutCubic
44
+ // A close cut inside the rise leaves the card where it stood until it is gone, then rests it.
45
+ onFinished: if (!root.shown) root.rise.y = 0
46
+ }
47
+ property NumberAnimation risen: NumberAnimation {
48
+ target: root.rise
49
+ property: "y"
50
+ to: 0
51
+ duration: Motion.durMs.open
52
+ easing.type: Easing.OutCubic
53
+ }
54
+ }