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,547 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ import qs.Commons
4
+ import "." as Flea
5
+ import "js/Keymap.js" as Keymap
6
+ import "js/Settings.js" as Settings
7
+
8
+ // The settings panel the Settings board draws: one floating surface, a fixed rail of sections and a pane that scrolls inside the work-area clamp. A plain overlay and not a QQC Popup, the call ui/ContextMenu.qml already made, because the one Controls import cost 10 ms of warm startup.
9
+ Item {
10
+ id: root
11
+
12
+ property bool opened: false
13
+ property Item focusHolder: null
14
+ // Reopening keeps the last section selected in this process.
15
+ property string section: "view"
16
+ property int cursor: 0
17
+ property int selectedFavourite: -1
18
+ property int favouriteMoveTarget: -1
19
+ property bool favouriteActionPending: false
20
+ // "rail" or "pane", which side Tab last gave the cursor to.
21
+ property string side: "pane"
22
+
23
+ // Border-box 560 wide with a 150 rail and a 408 pane, the board's resolved geometry at base 14;
24
+ // ui/Theme.qml holds the derivation and the seam reports all three.
25
+ readonly property int panelWidth: Theme.settings.panelWidth
26
+ readonly property int railWidth: Theme.settings.railWidth
27
+ // The Menus board's work-area clamp: a floating surface never renders taller than its bounds
28
+ // less this margin, and the pane scrolls inside that while the rail stays put.
29
+ readonly property int clampMargin: 8
30
+ // The compact card keeps View's measured size across sections, clamped to the window.
31
+ readonly property int chromeAndBorder: Theme.chromeHeight + 2 * Theme.spacing.hairline
32
+ readonly property int paneBottomPadding: Math.round(8 * Theme.font.bodySmall / 13)
33
+ readonly property real groundOpacity: 0.5
34
+ // The card's title, for ui/Ipc.qml: a driven click on it proves the card swallows what its controls do not.
35
+ readonly property alias titleItem: title
36
+ // var, not Item: BorderSurface is a qs.Ui type qmllint cannot resolve, and Item would read as incompatible.
37
+ readonly property var cardItem: card
38
+
39
+ // Everything ui/js/Settings.js rows() reads, built once here for the keyboard's rows and the pane's.
40
+ readonly property var settingsState: ({
41
+ data: ViewState.state,
42
+ home: Quickshell.env("HOME"),
43
+ favouriteStatuses: Favourites.statuses,
44
+ pins: ShelfPins.records,
45
+ selectedFavourite: root.selectedFavourite,
46
+ about: aboutFacts.facts,
47
+ saveStatus: ViewState.saveStatus,
48
+ textSize: ViewState.textSize,
49
+ hidden: ViewState.menuHidden,
50
+ keyHints: ViewState.keyHints,
51
+ preset: ViewState.keysPreset,
52
+ baseSize: Theme.baseSize,
53
+ monitorScale: Theme.monitorScale,
54
+ cornerRadius: Style.cornerRadius,
55
+ presetKeys: Keymap.PRESET_KEYS
56
+ })
57
+ readonly property var rows: Settings.rows(root.section, root.settingsState)
58
+
59
+ // What a test reads instead of running OCR over the panel, the same idiom ui/KeymapSheet.qml's
60
+ // rows() uses: one row per line, its kind, its wording and whatever value it currently holds.
61
+ function rowsText() {
62
+ var out = []
63
+ for (var i = 0; i < root.rows.length; i++) {
64
+ var row = root.rows[i]
65
+ out.push(row.kind + "|" + row.label + "|" + (row.value !== undefined ? row.value : ""))
66
+ }
67
+ return out.join("\n")
68
+ }
69
+
70
+ function open(holder) {
71
+ root.focusHolder = holder
72
+ root.cursor = Settings.firstRow(root.rows)
73
+ root.side = "pane"
74
+ pane.contentY = 0
75
+ root.opened = true
76
+ keys.forceActiveFocus()
77
+ }
78
+
79
+ function close() {
80
+ if (!root.opened)
81
+ return
82
+ root.opened = false
83
+ if (root.focusHolder)
84
+ root.focusHolder.forceActiveFocus()
85
+ }
86
+
87
+ function showSection(id) {
88
+ root.section = id
89
+ root.cursor = Settings.firstRow(root.rows)
90
+ pane.contentY = 0
91
+ }
92
+
93
+ // Enter and Space both land here. A choice steps rather than opening a menu of its own, because
94
+ // no control the panel draws has more values than a walk can reach.
95
+ function activate(index) {
96
+ var row = root.rows[index]
97
+ if (!row || !Settings.focusable(row))
98
+ return
99
+ if (row.kind === "favourite") {
100
+ // A pin opens the folder it names, the way the sidebar opens a favourite.
101
+ if (row.pinPath !== undefined) { root.openPin(row.pinPath); return }
102
+ root.selectedFavourite = row.favouriteIndex
103
+ if (root.focusHolder && root.focusHolder.sidebar) root.focusHolder.sidebar.openFavourite(row.favouriteIndex)
104
+ return
105
+ }
106
+ // The only headings the cursor can reach: the one carrying its group's master, and the one carrying Places' own Add.
107
+ if (row.kind === "group") {
108
+ if (row.action === "addFavourite") root.addFavourite()
109
+ else if (row.action === "pinFolder") root.pinFolder()
110
+ // The shelf's master is one stored boolean rather than a set of menu ids.
111
+ else if (row.id === "shelf.enabled") ViewState.changeSetting(row.id, row.state !== "all")
112
+ else ViewState.toggleMenuGroup(row.ids)
113
+ return
114
+ }
115
+ if (row.id === "columns") { root.showSection("columns"); return }
116
+ // The folder the panel was opened over, which is the pane behind it: the same folder Places' own "Add this folder" takes, and the only one on screen to mean.
117
+ if (row.id === "startFolder") {
118
+ if (root.focusHolder) ViewState.setStartFolder(root.focusHolder.path)
119
+ return
120
+ }
121
+ if (row.id === "backView") { root.showSection("view"); return }
122
+ if (row.id === "keyboardSheet") {
123
+ var holder = root.focusHolder
124
+ root.close()
125
+ if (holder && holder.keymapSheet) holder.keymapSheet.open(holder)
126
+ return
127
+ }
128
+ // About's two web routes carry their own destination; ui/js/SettingsAbout.js names both.
129
+ if (row.url !== undefined) { Qt.openUrlExternally(row.url); return }
130
+ // Two About actions with a live state: Update Flea's value shows a check and the footer what a launch did, and Make Flea the default runs flea instead of writing ui.json.
131
+ if (row.id === "updateFlea") { UpdateCheck.activate(root.focusHolder); return }
132
+ if (row.id === "makeDefault") { DefaultClaim.toggle(); return }
133
+ if (row.id.indexOf("column:") === 0) { ViewState.toggleColumn(row.id.substring(7)); return }
134
+ if (row.kind === "check" && root.section !== "menus") {
135
+ ViewState.changeSetting(row.id, !row.on)
136
+ return
137
+ }
138
+ // Menu checks share their visibility writer; other sections write their own leaves.
139
+ if (row.id === "keyHints")
140
+ ViewState.toggleKeyHints()
141
+ else if (row.kind === "check")
142
+ ViewState.toggleMenuAction(row.id)
143
+ else
144
+ root.stepRowValue(index, 1)
145
+ }
146
+
147
+ // h, l and the two chevrons. Every writer is ui/ViewState.qml's own, which is the same state the
148
+ // Ctrl+Shift chords reach, so a keystroke and a control can never hold two different sizes.
149
+ function stepRowValue(index, direction) {
150
+ var row = root.rows[index]
151
+ if (!row || !Settings.focusable(row))
152
+ return
153
+ if (row.id === "textMode") {
154
+ ViewState.toggleTextFollow()
155
+ return
156
+ }
157
+ if (row.id === "textStop") {
158
+ ViewState.stepTextSize(direction)
159
+ return
160
+ }
161
+ // A check or a group's master is toggled by activate(), never walked, so h and l stop here.
162
+ if (row.kind !== "choice")
163
+ return
164
+ if (row.values !== undefined) {
165
+ var index = row.values.indexOf(row.selected)
166
+ var target = (index + direction + row.values.length) % row.values.length
167
+ ViewState.changeSetting(row.id, row.values[target])
168
+ return
169
+ }
170
+ var at = Settings.PRESETS.indexOf(ViewState.keysPreset)
171
+ var next = (at + direction + Settings.PRESETS.length) % Settings.PRESETS.length
172
+ ViewState.setKeysPreset(Settings.PRESETS[next])
173
+ }
174
+
175
+ // The folder the panel was opened over, which is the pane behind it: SettingsRest rule 3 puts this on the Favorites heading, where it governs the whole list.
176
+ function addFavourite() {
177
+ if (!root.focusHolder)
178
+ return
179
+ var path = root.focusHolder.path
180
+ root.favouriteActionPending = Favourites.add(path, path.substring(path.lastIndexOf("/") + 1) || path)
181
+ }
182
+
183
+ // Rule 4: removal is addressed by the row it acts on, from the row's own mark or from the x key on it.
184
+ // A pin is the shelf's own entry, so its x unpins it rather than touching Places.
185
+ function removeFavourite(index) {
186
+ var row = root.rows[index]
187
+ if (!row || row.kind !== "favourite") return
188
+ if (row.pinPath !== undefined) { ShelfPins.unpin(row.pinPath); return }
189
+ root.favouriteActionPending = Favourites.remove(row.favouriteIndex)
190
+ }
191
+
192
+ // Rule 4 again: a pin is reordered in the shelf's own pile, and a favourite in Places.
193
+ function stepFavourite(index, direction) {
194
+ var row = root.rows[index]
195
+ if (!row) return
196
+ if (row.pinPath !== undefined) { ShelfPins.move(row.pinPath, direction); return }
197
+ var to = Math.max(0, Math.min(Favourites.records.length - 1, row.favouriteIndex + direction))
198
+ if (to !== row.favouriteIndex && Favourites.move(row.favouriteIndex, to)) root.favouriteMoveTarget = to
199
+ }
200
+
201
+ function moveFavourite(index, to) {
202
+ var row = root.rows[index]
203
+ if (!row) return
204
+ if (row.pinPath !== undefined) { ShelfPins.moveTo(row.pinPath, to); return }
205
+ if (Favourites.move(row.favouriteIndex, to)) root.favouriteMoveTarget = to
206
+ }
207
+
208
+ // SettingsRest rule 4: the shelf's own Add, the folder the panel was opened over.
209
+ function pinFolder() { if (root.focusHolder) ShelfPins.pin(root.focusHolder.path) }
210
+
211
+ function openPin(path) { if (root.focusHolder && root.focusHolder.sidebar) root.focusHolder.sidebar.opened(path) }
212
+
213
+ function pickRowStop(index, stop) {
214
+ var row = root.rows[index]
215
+ if (!row || !Settings.focusable(row))
216
+ return
217
+ // A segment names the value it was clicked on where a ruler tick names a stop outright, so both arrive here addressed by index, the row decides which writer that index belongs to, and a tick lands in the same ViewState writer stepTextSize itself calls: a click, an h and a Ctrl+Shift+Plus cannot leave two different sizes stored.
218
+ if (row.id === "textMode") {
219
+ ViewState.toggleTextFollow()
220
+ return
221
+ }
222
+ if (row.values !== undefined) {
223
+ ViewState.changeSetting(row.id, row.values[stop])
224
+ return
225
+ }
226
+ if (row.kind === "choice") {
227
+ ViewState.setKeysPreset(Settings.PRESETS[stop])
228
+ return
229
+ }
230
+ ViewState.setTextSize({ mode: stop })
231
+ }
232
+
233
+ function moveCursor(delta) {
234
+ if (root.side === "rail") {
235
+ var at = Settings.SECTIONS.map(function (s) { return s.id }).indexOf(root.section)
236
+ var to = Math.max(0, Math.min(Settings.SECTIONS.length - 1, at + delta))
237
+ root.showSection(Settings.SECTIONS[to].id)
238
+ return
239
+ }
240
+ root.cursor = Settings.stepRow(root.rows, root.cursor, delta)
241
+ // A pin is a favourite-shaped row with no favourite behind it, so it selects nothing.
242
+ if (root.rows[root.cursor] && root.rows[root.cursor].favouriteIndex !== undefined)
243
+ root.selectedFavourite = root.rows[root.cursor].favouriteIndex
244
+ root.showCursor()
245
+ }
246
+
247
+ function showCursor() { pane.showCursor(root.cursor, Settings.stepRow(root.rows, root.cursor, 1) === root.cursor) }
248
+ function sectionsText() { return JSON.stringify(Settings.SECTIONS) }
249
+ function rowItemForId(id) {
250
+ for (var i = 0; i < root.rows.length; i++) {
251
+ if (root.rows[i].id === id) return pane.rowItem(i)
252
+ }
253
+ return null
254
+ }
255
+ function railItemFor(id) { return rail.itemFor(id) }
256
+ function paneScroll() { return Math.round(pane.contentHeight) + "|" + Math.round(pane.height) }
257
+ function scrollState() {
258
+ return JSON.stringify({compactHeight: pane.compactHeight,
259
+ pane: {y: pane.contentY, height: pane.height, contentHeight: pane.contentHeight},
260
+ rail: {y: rail.contentY, height: rail.height, contentHeight: rail.contentHeight}})
261
+ }
262
+
263
+ anchors.fill: parent
264
+ visible: root.opened || root.opacity > 0
265
+ // Closed means no input, even while the fade-out is still drawn.
266
+ enabled: root.opened
267
+ opacity: 0
268
+ // Above the context menu and the keymap sheet: the panel is the surface that opened last.
269
+ z: 3
270
+ Flea.Reveal { target: root; shown: root.opened; lift: card }
271
+
272
+ Rectangle {
273
+ anchors.fill: parent
274
+ color: Theme.color.background
275
+ opacity: root.groundOpacity
276
+
277
+ MouseArea {
278
+ anchors.fill: parent
279
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
280
+ hoverEnabled: true
281
+ onClicked: root.close()
282
+ onWheel: function (wheel) { wheel.accepted = true }
283
+ }
284
+ }
285
+
286
+ Rectangle {
287
+ id: card
288
+ x: Theme.cardOrigin(root.width, width)
289
+ y: Theme.cardOrigin(root.height, height)
290
+ width: Theme.cardSpan(root.panelWidth, root.width - 2 * root.clampMargin)
291
+ // Settings.html gives the rail and pane separate vertical insets.
292
+ height: Theme.cardSpan(root.chromeAndBorder + Math.max(rail.implicitHeight + 2 * Theme.settings.railPaddingY,
293
+ pane.compactHeight + root.paneBottomPadding),
294
+ root.height - 2 * root.clampMargin)
295
+ color: Theme.color.surface
296
+ border.width: Theme.spacing.hairline
297
+ border.color: Theme.color.mutedFrame
298
+ // Mirrors hyprland decoration:rounding, same as ui/KeymapSheet.qml; 0 on a stock box stays square.
299
+ radius: Style.cornerRadius
300
+ clip: true
301
+
302
+ // The control handlers above take passive grabs, so without this sink a press on a row fell
303
+ // through the card to the ground below, which closed the panel on release.
304
+ MouseArea {
305
+ anchors.fill: parent
306
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
307
+ onClicked: {}
308
+ onWheel: function (wheel) { wheel.accepted = true }
309
+ }
310
+
311
+ // The board's border-box panel: the card's own border is the two outer hairlines, so the
312
+ // 558 they leave is what the chrome, the rail and the pane are laid out inside.
313
+ Item {
314
+ anchors.fill: parent
315
+ anchors.margins: Theme.spacing.hairline
316
+
317
+ Item {
318
+ id: chrome
319
+ anchors.left: parent.left
320
+ anchors.right: parent.right
321
+ anchors.top: parent.top
322
+ height: Theme.chromeHeight
323
+
324
+ Flea.Glyph {
325
+ id: titleMark
326
+ anchors.left: parent.left
327
+ anchors.leftMargin: Theme.spacing.rowPaddingX
328
+ anchors.verticalCenter: parent.verticalCenter
329
+ width: Theme.chromeMarkSize
330
+ height: width
331
+ name: "sliders"
332
+ color: Theme.color.accent
333
+ }
334
+
335
+ Text {
336
+ id: title
337
+ anchors.left: titleMark.right
338
+ anchors.leftMargin: Theme.spacing.gap
339
+ anchors.verticalCenter: parent.verticalCenter
340
+ text: "Settings"
341
+ color: Theme.color.foreground
342
+ font.family: Theme.font.family
343
+ font.pixelSize: Theme.font.caption
344
+ font.bold: true
345
+ textFormat: Text.PlainText
346
+ }
347
+
348
+ // The board's own header mark, the one surface control a pointer has for closing the panel.
349
+ Item {
350
+ id: closeMark
351
+ anchors.right: parent.right
352
+ anchors.rightMargin: Theme.spacing.rowPaddingX
353
+ anchors.verticalCenter: parent.verticalCenter
354
+ width: Theme.hitMin
355
+ height: Theme.hitMin
356
+
357
+ Accessible.role: Accessible.Button
358
+ Accessible.name: "Close settings"
359
+ Accessible.onPressAction: root.close()
360
+
361
+ Flea.Glyph {
362
+ anchors.centerIn: parent
363
+ width: Theme.chromeMarkSize
364
+ height: Theme.chromeMarkSize
365
+ name: "x"
366
+ color: Theme.color.foreground
367
+ }
368
+
369
+ HoverHandler {
370
+ cursorShape: Qt.PointingHandCursor
371
+ }
372
+
373
+ TapHandler {
374
+ acceptedButtons: Qt.LeftButton
375
+ gesturePolicy: TapHandler.ReleaseWithinBounds
376
+ onTapped: root.close()
377
+ }
378
+ }
379
+
380
+ Text {
381
+ anchors.right: closeMark.left
382
+ anchors.rightMargin: Theme.spacing.gap
383
+ anchors.verticalCenter: parent.verticalCenter
384
+ text: "esc"
385
+ color: Theme.color.muted
386
+ font.family: Theme.font.family
387
+ font.pixelSize: Theme.font.caption
388
+ textFormat: Text.PlainText
389
+ }
390
+
391
+ Rectangle {
392
+ anchors.left: parent.left
393
+ anchors.right: parent.right
394
+ anchors.bottom: parent.bottom
395
+ height: Theme.spacing.hairline
396
+ color: Theme.color.mutedFrame
397
+ opacity: 0.4
398
+ }
399
+ }
400
+
401
+ Flea.SettingsRail {
402
+ id: rail
403
+ anchors.left: parent.left
404
+ anchors.top: chrome.bottom
405
+ anchors.topMargin: Theme.settings.railPaddingY
406
+ anchors.bottom: parent.bottom
407
+ anchors.bottomMargin: Theme.settings.railPaddingY
408
+ width: root.railWidth
409
+ section: root.section === "columns" ? "view" : root.section
410
+ focused: root.side === "rail"
411
+ onChosen: function (id) {
412
+ root.side = "rail"
413
+ root.showSection(id)
414
+ }
415
+ }
416
+
417
+ // Inside the rail's own 150, not beside it: the board's rail is a border-box whose right
418
+ // edge is this line, which is what leaves the pane the 408 the anatomy note names.
419
+ Rectangle {
420
+ anchors.right: rail.right
421
+ anchors.top: chrome.bottom
422
+ anchors.bottom: parent.bottom
423
+ width: Theme.spacing.hairline
424
+ color: Theme.color.mutedFrame
425
+ opacity: 0.4
426
+ }
427
+
428
+ Flea.SettingsPane {
429
+ id: pane
430
+ anchors.left: rail.right
431
+ anchors.right: parent.right
432
+ anchors.top: chrome.bottom
433
+ anchors.bottom: parent.bottom
434
+ anchors.bottomMargin: root.paneBottomPadding
435
+ section: root.section
436
+ values: root.settingsState
437
+ cursor: root.cursor
438
+ side: root.side
439
+ onPointerMoved: function (index) {
440
+ root.side = "pane"; root.cursor = index
441
+ if (root.rows[index].favouriteIndex !== undefined) root.selectedFavourite = root.rows[index].favouriteIndex
442
+ }
443
+ onFavouriteRemoved: function (index) { root.removeFavourite(index) }
444
+ onFavouriteMoved: function (index, to) { root.moveFavourite(index, to) }
445
+ onActivated: function (index) { root.side = "pane"; root.cursor = index; root.activate(index) }
446
+ onStepped: function (index, direction) { root.side = "pane"; root.cursor = index; root.stepRowValue(index, direction) }
447
+ onStopPicked: function (index, stop) { root.side = "pane"; root.cursor = index; root.pickRowStop(index, stop) }
448
+ }
449
+ }
450
+ }
451
+
452
+ Connections {
453
+ target: Favourites
454
+ function onExternalChanged(previousCount) {
455
+ var wasFavourite = root.cursor > 0 && root.cursor <= previousCount + 1
456
+ root.selectedFavourite = -1
457
+ root.favouriteMoveTarget = -1
458
+ root.favouriteActionPending = false
459
+ if (root.opened && root.section === "places") {
460
+ if (wasFavourite) {
461
+ root.cursor = Settings.firstRow(root.rows)
462
+ } else if (root.cursor > previousCount + 1) {
463
+ root.cursor += Favourites.records.length - previousCount
464
+ }
465
+ root.showCursor()
466
+ }
467
+ }
468
+ function onWrote() {
469
+ if (root.favouriteActionPending) {
470
+ root.favouriteActionPending = false
471
+ root.selectedFavourite = Math.min(root.selectedFavourite, Favourites.records.length - 1)
472
+ if (root.opened && root.section === "places") {
473
+ // Adding or removing a row moves every row under it, so the cursor takes the heading that carries Add rather than whatever slid into its index.
474
+ root.cursor = Settings.firstRow(root.rows)
475
+ root.showCursor()
476
+ }
477
+ }
478
+ if (root.favouriteMoveTarget < 0) return
479
+ root.selectedFavourite = root.favouriteMoveTarget
480
+ root.cursor = root.favouriteMoveTarget + 1
481
+ root.favouriteMoveTarget = -1
482
+ root.showCursor()
483
+ }
484
+ function onFailed(message) { root.favouriteMoveTarget = -1; root.favouriteActionPending = false }
485
+ }
486
+
487
+ Flea.AboutFacts { id: aboutFacts; active: root.opened && root.section === "about" }
488
+
489
+ Item {
490
+ id: keys
491
+ anchors.fill: parent
492
+ focus: true
493
+
494
+ Keys.onPressed: function (event) {
495
+ event.accepted = true
496
+ if (event.key === Qt.Key_Escape) {
497
+ root.close()
498
+ return
499
+ }
500
+ if (event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
501
+ root.side = root.side === "rail" ? "pane" : "rail"
502
+ return
503
+ }
504
+ var row = root.rows[root.cursor]
505
+ if (root.side === "pane" && row && row.kind === "favourite" && (event.modifiers & Qt.ShiftModifier)
506
+ && (event.key === Qt.Key_J || event.key === Qt.Key_K)) {
507
+ root.stepFavourite(root.cursor, event.key === Qt.Key_J ? 1 : -1)
508
+ return
509
+ }
510
+ // SettingsRest rule 4: the row's own mark is x, so x on the cursor row is the same action.
511
+ if (root.side === "pane" && row && row.kind === "favourite"
512
+ && (event.text === "x" || event.key === Qt.Key_Delete)) {
513
+ root.removeFavourite(root.cursor)
514
+ return
515
+ }
516
+ if (event.key === Qt.Key_Down || event.text === "j") {
517
+ root.moveCursor(1)
518
+ return
519
+ }
520
+ if (event.key === Qt.Key_Up || event.text === "k") {
521
+ root.moveCursor(-1)
522
+ return
523
+ }
524
+ // h and l step a control, which only the pane has; from the rail they do nothing rather
525
+ // than reaching across and changing a value the cursor is not on.
526
+ if (event.key === Qt.Key_Right || event.text === "l") {
527
+ if (root.side === "pane")
528
+ root.stepRowValue(root.cursor, 1)
529
+ return
530
+ }
531
+ if (event.key === Qt.Key_Left || event.text === "h") {
532
+ if (root.side === "pane")
533
+ root.stepRowValue(root.cursor, -1)
534
+ return
535
+ }
536
+ if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Space) {
537
+ if (root.side === "rail")
538
+ root.side = "pane"
539
+ else if (event.key !== Qt.Key_Space || (root.rows[root.cursor] &&
540
+ (root.rows[root.cursor].kind === "check" || root.rows[root.cursor].kind === "group")))
541
+ root.activate(root.cursor)
542
+ }
543
+ // Every other key stops here: an open panel that let one through would move the cursor
544
+ // in the listing behind it, which is the hidden-view keyboard defect AGENTS.md records.
545
+ }
546
+ }
547
+ }
@@ -0,0 +1,128 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import "." as Flea
4
+ import "js/Settings.js" as Settings
5
+
6
+ // The settings panel's section rail, drawn the way the window's own sidebar draws its rows: the
7
+ // accent fill and the inset bar on the chosen one, the rail row height, and the rail icon slot.
8
+ // Split out of ui/SettingsPanel.qml, which owns the panel's keyboard and its two-sided cursor.
9
+ Flickable {
10
+ id: root
11
+
12
+ property string section: ""
13
+ // True while Tab has given the panel's cursor to the rail, which is what lights the row.
14
+ property bool focused: false
15
+ readonly property real focusOpacity: Theme.washHover
16
+ implicitHeight: railColumn.implicitHeight
17
+ contentHeight: railColumn.implicitHeight
18
+ contentWidth: width
19
+ clip: true
20
+ boundsBehavior: Flickable.StopAtBounds
21
+
22
+ onSectionChanged: showCurrent()
23
+ onHeightChanged: showCurrent()
24
+ onFocusedChanged: if (focused) showCurrent()
25
+ Component.onCompleted: showCurrent()
26
+
27
+ function showCurrent() {
28
+ var item = itemFor(root.section)
29
+ if (!item) return
30
+ if (item.y < contentY) contentY = item.y
31
+ else if (item.y + item.height > contentY + height)
32
+ contentY = Math.max(0, item.y + item.height - height)
33
+ }
34
+
35
+ Flea.FastScrollHandler {
36
+ parent: root
37
+ flickable: root
38
+ }
39
+ // No bar and no lane: rows fill the rail and still scroll by wheel, touchpad and keys.
40
+
41
+ signal chosen(string id)
42
+
43
+ // The row for a section id, so a driven click can land on it: tests/ui.sh clickthrough.
44
+ function itemFor(id) {
45
+ for (var i = 0; i < rows.count; i++) {
46
+ var row = rows.itemAt(i)
47
+ if (row && row.modelData.id === id)
48
+ return row
49
+ }
50
+ return null
51
+ }
52
+
53
+ Column {
54
+ id: railColumn
55
+ width: root.width
56
+
57
+ Repeater {
58
+ id: rows
59
+ model: Settings.SECTIONS
60
+
61
+ delegate: Item {
62
+ id: railRow
63
+ required property var modelData
64
+ width: root.width
65
+ height: Theme.railRowHeight
66
+
67
+ readonly property bool current: root.section === railRow.modelData.id
68
+
69
+ Rectangle {
70
+ anchors.fill: parent
71
+ visible: railRow.current
72
+ color: Style.selectedAccentFill
73
+ }
74
+
75
+ // The inset bar the window's rail draws down the left edge of its own selected row.
76
+ Rectangle {
77
+ anchors.left: parent.left
78
+ anchors.top: parent.top
79
+ anchors.bottom: parent.bottom
80
+ visible: railRow.current
81
+ width: Theme.spacing.hairline * 2
82
+ color: Theme.color.accent
83
+ }
84
+
85
+ Rectangle {
86
+ anchors.fill: parent
87
+ color: Theme.color.foreground
88
+ opacity: root.focused && railRow.current ? root.focusOpacity : 0
89
+ }
90
+
91
+ Flea.Glyph {
92
+ id: mark
93
+ anchors.left: parent.left
94
+ anchors.leftMargin: Theme.spacing.rowPaddingX
95
+ anchors.verticalCenter: parent.verticalCenter
96
+ width: Theme.railIconSize
97
+ height: Theme.railIconSize
98
+ maxSize: Theme.railIconSize
99
+ name: railRow.modelData.glyph
100
+ color: railRow.current ? Theme.color.accent : Theme.color.mutedFrame
101
+ }
102
+
103
+ Text {
104
+ anchors.left: mark.right
105
+ anchors.leftMargin: Theme.spacing.gap
106
+ anchors.right: parent.right
107
+ anchors.rightMargin: Theme.spacing.gap
108
+ anchors.verticalCenter: parent.verticalCenter
109
+ text: railRow.modelData.label
110
+ color: Theme.color.foreground
111
+ font.family: Theme.font.family
112
+ font.pixelSize: Theme.font.body
113
+ textFormat: Text.PlainText
114
+ elide: Text.ElideRight
115
+ }
116
+
117
+ HoverHandler {
118
+ cursorShape: Qt.PointingHandCursor
119
+ }
120
+
121
+ TapHandler {
122
+ gesturePolicy: TapHandler.ReleaseWithinBounds
123
+ onTapped: root.chosen(railRow.modelData.id)
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }