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,412 @@
1
+ import QtQuick
2
+ import QtQuick.Layouts
3
+ import QtQuick.Shapes
4
+ import Quickshell
5
+ import Quickshell.Wayland
6
+ import qs.Commons
7
+ import qs.Commons as Commons
8
+ import qs.Ui
9
+
10
+ // Centered speed test overlay shared by the network and disk speed tests. No
11
+ // card: like the Tucson's floating cluster, the two dials sit directly on a
12
+ // darkened scrim -- open 270° arcs, faint tick rings, hubless gradient
13
+ // needles, and a digital readout in the middle. Esc, the scrim, or the corner
14
+ // dismiss close it; the needles sweep to full scale and back on open, then
15
+ // track the live readings. Callers name the dials, the unit, and the scale.
16
+ PanelWindow {
17
+ id: root
18
+ // Right-to-left languages read this window mirrored.
19
+ Binding { target: root.contentItem; property: "LayoutMirroring.enabled"; value: Commons.I18n.rightToLeft }
20
+ Binding { target: root.contentItem; property: "LayoutMirroring.childrenInherit"; value: true }
21
+
22
+
23
+ required property string fontFamily
24
+ required property bool running
25
+ required property string leftLabel
26
+ required property string rightLabel
27
+ property string unit: "Mbps"
28
+ property string title: ""
29
+ property string layerNamespace: "omarchy-speed-test"
30
+ property string runAgainTooltip: Commons.I18n.t("speedtest.measureAgain")
31
+ property real leftValue: 0
32
+ property real rightValue: 0
33
+ property bool leftLive: false
34
+ property bool rightLive: false
35
+ property string error: ""
36
+ property bool open: false
37
+ // Full-scale latch points for the dials, smallest first. The first stop is
38
+ // the base scale a fresh run starts from.
39
+ property var scaleStops: [100, 250, 500, 1000, 2500, 5000, 10000]
40
+ property real fullScale: scaleStops[0]
41
+
42
+ signal closeRequested()
43
+ signal runAgainRequested()
44
+
45
+ readonly property bool failed: error !== ""
46
+
47
+ function resetScale() {
48
+ fullScale = scaleStops[0]
49
+ }
50
+
51
+ function expandScale(value) {
52
+ // Either reading ranges the entire cluster upward. Keeping this latch on
53
+ // the overlay ensures both dials always describe the same scale.
54
+ for (var i = 0; i < scaleStops.length; i++) {
55
+ if (value <= scaleStops[i] * 0.92) {
56
+ if (scaleStops[i] > fullScale) fullScale = scaleStops[i]
57
+ return
58
+ }
59
+ }
60
+ fullScale = scaleStops[scaleStops.length - 1]
61
+ }
62
+
63
+ onRunningChanged: if (running) resetScale()
64
+ onScaleStopsChanged: resetScale()
65
+ onLeftValueChanged: expandScale(leftValue)
66
+ onRightValueChanged: expandScale(rightValue)
67
+
68
+ Behavior on fullScale {
69
+ NumberAnimation { duration: Style.duration(400); easing.type: Easing.OutCubic }
70
+ }
71
+
72
+ // The scrim below is a fixed near-black regardless of theme, so text and
73
+ // ticks on it need a fixed light palette, not the themed bar.foreground.
74
+ readonly property color onScrim: "white"
75
+ readonly property color onScrimDim: Qt.rgba(1, 1, 1, 0.55)
76
+ readonly property color onScrimUrgent: "#ff6b6b"
77
+
78
+ visible: open
79
+ // The window is instantiated hidden, so re-acquire focus after mapping and
80
+ // fire the ignition sweep once the surface is actually on screen.
81
+ onOpenChanged: {
82
+ if (open) Qt.callLater(function() {
83
+ if (!root.open) return
84
+ keyCatcher.forceActiveFocus()
85
+ leftDial.ignite()
86
+ rightDial.ignite()
87
+ })
88
+ }
89
+ anchors { top: true; bottom: true; left: true; right: true }
90
+ color: "transparent"
91
+ exclusionMode: ExclusionMode.Ignore
92
+ WlrLayershell.namespace: root.layerNamespace
93
+ WlrLayershell.layer: WlrLayer.Overlay
94
+ WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
95
+
96
+ // Deep scrim: with no card behind them, the floating dials need the
97
+ // backdrop to carry the contrast on any wallpaper, like the near-black
98
+ // panel behind a real cluster.
99
+ Rectangle {
100
+ anchors.fill: parent
101
+ color: Qt.rgba(0, 0, 0, 0.78)
102
+
103
+ MouseArea {
104
+ anchors.fill: parent
105
+ onClicked: root.closeRequested()
106
+ }
107
+ }
108
+
109
+ Item {
110
+ id: keyCatcher
111
+ anchors.fill: parent
112
+ focus: true
113
+
114
+ Keys.onEscapePressed: root.closeRequested()
115
+ Keys.onReturnPressed: if (!root.running) root.runAgainRequested()
116
+ Keys.onEnterPressed: if (!root.running) root.runAgainRequested()
117
+
118
+ Item {
119
+ id: cluster
120
+ anchors.centerIn: parent
121
+ width: content.implicitWidth
122
+ height: content.implicitHeight
123
+ // Narrow or heavily scaled outputs: shrink the whole cluster rather
124
+ // than clipping it at the screen edge.
125
+ scale: Math.min(1,
126
+ (keyCatcher.width - Style.space(32)) / Math.max(1, width),
127
+ (keyCatcher.height - Style.space(32)) / Math.max(1, height))
128
+
129
+ // Swallow clicks so only the scrim outside the cluster dismisses.
130
+ MouseArea { anchors.fill: parent; onClicked: {} }
131
+
132
+ ColumnLayout {
133
+ id: content
134
+ anchors.fill: parent
135
+ spacing: Style.space(16)
136
+
137
+ Text {
138
+ textFormat: Text.PlainText
139
+ visible: root.title !== ""
140
+ text: root.title.toUpperCase()
141
+ color: root.onScrimDim
142
+ font.family: root.fontFamily
143
+ font.pixelSize: Style.font.caption
144
+ font.bold: true
145
+ font.letterSpacing: 2
146
+ Layout.fillWidth: true
147
+ horizontalAlignment: Text.AlignHCenter
148
+ }
149
+
150
+ Row {
151
+ spacing: Style.space(48)
152
+ Layout.alignment: Qt.AlignHCenter
153
+
154
+ SpeedDial {
155
+ id: leftDial
156
+ label: root.leftLabel
157
+ value: root.leftValue
158
+ live: root.leftLive
159
+ }
160
+
161
+ SpeedDial {
162
+ id: rightDial
163
+ label: root.rightLabel
164
+ value: root.rightValue
165
+ live: root.rightLive
166
+ }
167
+ }
168
+
169
+ // Centered on the dial pair. Fades rather than unmounts while a run
170
+ // is in flight, so the cluster never shifts.
171
+ Button {
172
+ text: Commons.I18n.t("speedtest.runAgain")
173
+ tooltipText: root.runAgainTooltip
174
+ bordered: true
175
+ enabled: !root.running
176
+ opacity: root.running ? 0 : 1
177
+ foreground: root.onScrim
178
+ fontFamily: root.fontFamily
179
+ fontSize: Style.font.bodySmall
180
+ horizontalPadding: Style.space(14)
181
+ verticalPadding: Style.space(4)
182
+ Layout.alignment: Qt.AlignHCenter
183
+ onClicked: root.runAgainRequested()
184
+
185
+ Behavior on opacity {
186
+ NumberAnimation { duration: Style.duration(240); easing.type: Easing.OutCubic }
187
+ }
188
+ }
189
+
190
+ Text {
191
+ textFormat: Text.PlainText
192
+ visible: root.failed
193
+ text: root.error
194
+ color: root.onScrimUrgent
195
+ font.family: root.fontFamily
196
+ font.pixelSize: Style.font.bodySmall
197
+ wrapMode: Text.Wrap
198
+ Layout.fillWidth: true
199
+ Layout.maximumWidth: Style.space(440)
200
+ horizontalAlignment: Text.AlignHCenter
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ // One floating cluster dial: an open 270° scale with the gap at the
207
+ // bottom, a faint tick ring, a glowing accent value arc, a hubless needle
208
+ // that fades toward the pivot, and a digital readout in the middle. All
209
+ // writes to the needle funnel through `shown` so the ignition sweep and
210
+ // live readings share one animation.
211
+ component SpeedDial: Item {
212
+ id: dial
213
+
214
+ required property string label
215
+ required property real value
216
+ required property bool live
217
+
218
+ readonly property real diameter: Style.space(210)
219
+ // 0° = 3 o'clock, increasing clockwise (PathAngleArc's convention).
220
+ readonly property real dialStart: 135
221
+ readonly property real dialSweep: 270
222
+ readonly property int tickCount: 46
223
+ readonly property real arcWidth: Style.space(4)
224
+ readonly property real arcRadius: diameter / 2 - arcWidth
225
+ readonly property color trackColor: Qt.rgba(1, 1, 1, 0.14)
226
+ readonly property color minorTickColor: Qt.rgba(1, 1, 1, 0.12)
227
+ readonly property color majorTickColor: Qt.rgba(1, 1, 1, 0.3)
228
+ // The dial that isn't measuring yet sits dimmed until it gets a figure.
229
+ readonly property bool engaged: live || value > 0
230
+
231
+ property real shown: 0
232
+ // The digital readout stays on the real figure while the ignition sweep
233
+ // drives the needle -- a cluster sweeps its gauges, not its numerals.
234
+ readonly property real reading: ignition.running ? value : shown
235
+ readonly property real fullScale: root.fullScale
236
+ readonly property real fraction: fullScale > 0 ? Math.max(0, Math.min(1, shown / fullScale)) : 0
237
+ readonly property bool arcVisible: fraction > 0.004
238
+
239
+ width: diameter
240
+ height: diameter
241
+ opacity: engaged ? 1 : 0.5
242
+
243
+ Behavior on opacity {
244
+ NumberAnimation { duration: Style.duration(240); easing.type: Easing.OutCubic }
245
+ }
246
+
247
+ // Live readings land once a second; glide between them rather than snap.
248
+ Behavior on shown {
249
+ enabled: !ignition.running
250
+ NumberAnimation { duration: Style.duration(600); easing.type: Easing.OutCubic }
251
+ }
252
+
253
+ onValueChanged: {
254
+ if (!ignition.running) shown = value
255
+ }
256
+
257
+ function ignite() {
258
+ ignition.restart()
259
+ }
260
+
261
+ // Car-cluster power-on: needle sweeps to full scale and falls back before
262
+ // the live figures take over.
263
+ SequentialAnimation {
264
+ id: ignition
265
+ NumberAnimation { target: dial; property: "shown"; to: dial.fullScale; duration: Style.duration(550); easing.type: Easing.InOutCubic }
266
+ NumberAnimation { target: dial; property: "shown"; to: 0; duration: Style.duration(650); easing.type: Easing.OutCubic }
267
+ onFinished: dial.shown = dial.value
268
+ }
269
+
270
+ Shape {
271
+ anchors.fill: parent
272
+ preferredRendererType: Shape.CurveRenderer
273
+
274
+ // Track: the full scale, always visible, dim.
275
+ ShapePath {
276
+ strokeWidth: dial.arcWidth
277
+ strokeColor: dial.trackColor
278
+ fillColor: "transparent"
279
+ capStyle: ShapePath.RoundCap
280
+
281
+ PathAngleArc {
282
+ centerX: dial.width / 2
283
+ centerY: dial.height / 2
284
+ radiusX: dial.arcRadius
285
+ radiusY: dial.arcRadius
286
+ startAngle: dial.dialStart
287
+ sweepAngle: dial.dialSweep
288
+ }
289
+ }
290
+
291
+ // Soft under-glow beneath the value arc, standing in for the backlit
292
+ // ring of a real cluster. Both arcs go transparent at rest, or their
293
+ // round caps would leave a stray dot at the foot of the scale.
294
+ ShapePath {
295
+ strokeWidth: dial.arcWidth * 3
296
+ strokeColor: dial.arcVisible ? Qt.rgba(Commons.Color.accent.r, Commons.Color.accent.g, Commons.Color.accent.b, 0.18) : "transparent"
297
+ fillColor: "transparent"
298
+ capStyle: ShapePath.RoundCap
299
+
300
+ PathAngleArc {
301
+ centerX: dial.width / 2
302
+ centerY: dial.height / 2
303
+ radiusX: dial.arcRadius
304
+ radiusY: dial.arcRadius
305
+ startAngle: dial.dialStart
306
+ sweepAngle: dial.dialSweep * dial.fraction
307
+ }
308
+ }
309
+
310
+ // Value: fills behind the needle.
311
+ ShapePath {
312
+ strokeWidth: dial.arcWidth
313
+ strokeColor: dial.arcVisible ? Commons.Color.accent : "transparent"
314
+ fillColor: "transparent"
315
+ capStyle: ShapePath.RoundCap
316
+
317
+ PathAngleArc {
318
+ centerX: dial.width / 2
319
+ centerY: dial.height / 2
320
+ radiusX: dial.arcRadius
321
+ radiusY: dial.arcRadius
322
+ startAngle: dial.dialStart
323
+ sweepAngle: dial.dialSweep * dial.fraction
324
+ }
325
+ }
326
+ }
327
+
328
+ // Faint tick ring just inside the arc; every fifth tick is a major.
329
+ Repeater {
330
+ model: dial.tickCount
331
+
332
+ Item {
333
+ required property int index
334
+ readonly property bool major: index % 5 === 0
335
+
336
+ anchors.fill: parent
337
+ rotation: dial.dialStart + (index / (dial.tickCount - 1)) * dial.dialSweep - 270
338
+
339
+ Rectangle {
340
+ anchors.horizontalCenter: parent.horizontalCenter
341
+ y: dial.arcWidth * 2 + (parent.major ? 0 : Style.space(2))
342
+ width: parent.major ? Math.max(2, Style.space(2)) : 1
343
+ height: parent.major ? Style.space(10) : Style.space(6)
344
+ radius: width / 2
345
+ color: parent.major ? dial.majorTickColor : dial.minorTickColor
346
+ }
347
+ }
348
+ }
349
+
350
+ // Hubless needle: a slender sliver that fades out toward the pivot, so
351
+ // it reads as floating like the rest of the cluster.
352
+ Item {
353
+ anchors.fill: parent
354
+ rotation: dial.dialStart + dial.fraction * dial.dialSweep - 270
355
+
356
+ Rectangle {
357
+ anchors.horizontalCenter: parent.horizontalCenter
358
+ y: dial.arcWidth * 2 + Style.space(10)
359
+ width: Math.max(2, Style.space(3))
360
+ height: dial.diameter * 0.32
361
+ radius: width / 2
362
+
363
+ gradient: Gradient {
364
+ GradientStop { position: 0.0; color: Commons.Color.accent }
365
+ GradientStop { position: 0.55; color: Commons.Color.accent }
366
+ GradientStop { position: 1.0; color: "transparent" }
367
+ }
368
+ }
369
+ }
370
+
371
+ Column {
372
+ anchors.horizontalCenter: parent.horizontalCenter
373
+ anchors.top: parent.verticalCenter
374
+ anchors.topMargin: Style.space(14)
375
+ spacing: 0
376
+
377
+ Text {
378
+ textFormat: Text.PlainText
379
+ anchors.horizontalCenter: parent.horizontalCenter
380
+ // Written in the interface language's decimal separator and digits.
381
+ text: Commons.I18n.formatNumber(dial.reading, dial.reading < 10 ? 1 : 0)
382
+ color: root.onScrim
383
+ font.family: root.fontFamily
384
+ font.pixelSize: Style.font.display
385
+ font.bold: true
386
+ }
387
+
388
+ Text {
389
+ textFormat: Text.PlainText
390
+ anchors.horizontalCenter: parent.horizontalCenter
391
+ text: root.unit
392
+ color: root.onScrimDim
393
+ font.family: root.fontFamily
394
+ font.pixelSize: Style.font.caption
395
+ }
396
+ }
397
+
398
+ // The 90° gap at the bottom of the scale is where a cluster prints its
399
+ // unit; here it names the direction.
400
+ Text {
401
+ textFormat: Text.PlainText
402
+ anchors.horizontalCenter: parent.horizontalCenter
403
+ anchors.bottom: parent.bottom
404
+ text: dial.label
405
+ color: root.onScrimDim
406
+ font.family: root.fontFamily
407
+ font.pixelSize: Style.font.caption
408
+ font.bold: true
409
+ font.letterSpacing: 1.5
410
+ }
411
+ }
412
+ }
@@ -0,0 +1,58 @@
1
+ import QtQuick
2
+ import QtQuick.Controls
3
+ import qs.Commons
4
+ import qs.Commons as Commons
5
+
6
+ // Single-line text input with the kit's focus + selection styling. Inherits
7
+ // from Qt Quick Controls TextField so the underlying type's API (text,
8
+ // placeholderText, accepted, editingFinished, validator, ...) is available
9
+ // to callers without re-exposing each property.
10
+ //
11
+ // Defaults bind to qs.Commons.Color so a caller with no theme overrides
12
+ // just works; foreground / accent / selectionTint can be overridden per
13
+ // instance. activeFocus and mouse hover / panel cursor use the same
14
+ // hover-cursor defaults, so text inputs match Button, Toggle, and Dropdown.
15
+ //
16
+ // Sizing is driven by font.pixelSize + verticalPadding. The default 30px
17
+ // implicitHeight fits dialog forms; inline callers (wifi's row-embedded
18
+ // passphrase prompt) drop verticalPadding to match a 22-26px row.
19
+ TextField {
20
+ id: root
21
+
22
+ property color foreground: Commons.Color.foreground
23
+ property color accent: Commons.Color.accent
24
+ property color selectionTint: Style.selectionFillFor(foreground, accent)
25
+ property bool password: false
26
+ property real horizontalPadding: Style.spacing.controlPaddingX
27
+ property real verticalPadding: Style.spacing.inputPaddingY
28
+
29
+ // Panel-cursor flag. When true (and the field isn't already focused),
30
+ // the background paints the shared hover/cursor state.
31
+ // For mouse-enter/leave the consumer reads QQC TextField's inherited
32
+ // `hovered` property (via onHoveredChanged) — we don't add a sibling
33
+ // signal because the inherited property would shadow it.
34
+ property bool hasCursor: false
35
+
36
+ readonly property bool _focused: activeFocus
37
+ readonly property bool _hot: hovered || hasCursor
38
+ readonly property var _borderSpec: Border.controlSpec(_focused ? "focus" : (_hot ? "hover-cursor" : "normal"), root.foreground, root.accent)
39
+
40
+ echoMode: password ? TextInput.Password : TextInput.Normal
41
+ font.family: Style.font.family
42
+ font.pixelSize: Style.font.body
43
+ color: foreground
44
+ selectionColor: selectionTint
45
+ selectedTextColor: foreground
46
+ placeholderTextColor: Qt.darker(foreground, 1.6)
47
+
48
+ leftPadding: horizontalPadding + Border.left(_borderSpec)
49
+ rightPadding: horizontalPadding + Border.right(_borderSpec)
50
+ topPadding: verticalPadding + Border.top(_borderSpec)
51
+ bottomPadding: verticalPadding + Border.bottom(_borderSpec)
52
+
53
+ background: BorderSurface {
54
+ color: Style.controlFill(root._focused, root._hot, root.foreground, root.accent)
55
+ borderSpec: root._borderSpec
56
+ radius: Style.cornerRadius
57
+ }
58
+ }
@@ -0,0 +1,118 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import qs.Commons as Commons
4
+
5
+ // Labeled toggle row: title + optional description on the left, a
6
+ // `ToggleSwitch` on the right. Clicking anywhere on the row emits `clicked()`;
7
+ // consumers flip `checked` in response (the component is stateless about the
8
+ // actual value so it composes cleanly with model-driven UI).
9
+ //
10
+ // Cursor and focus styling match the rest of the kit: hasCursor / mouse
11
+ // hover and activeFocus share the hover-cursor defaults.
12
+ //
13
+ // `rounded` is forwarded to the switch, which auto-detects from
14
+ // Style.cornerRadius: pill shape when Hyprland corners are rounded, square on
15
+ // sharp. Callers can override per-instance.
16
+ BorderSurface {
17
+ id: root
18
+
19
+ property string label: ""
20
+ property string description: ""
21
+ property bool checked: false
22
+
23
+ // Panel-cursor flag. Same role as Button.hasCursor:
24
+ // panels with their own keyboard cursor bind this to drive the highlight
25
+ // separately from activeFocus. Visuals use the same hover-cursor tokens.
26
+ property bool hasCursor: false
27
+
28
+ // Switch shape follows the theme by default: pill on round, square on sharp.
29
+ // Override per-instance if a caller wants the opposite.
30
+ property bool rounded: Style.cornerRadius > 0
31
+
32
+ property color foreground: Commons.Color.foreground
33
+ property color accent: Commons.Color.accent
34
+ property string fontFamily: Style.font.family
35
+ property real titleSize: Style.font.subtitle
36
+ property real descriptionSize: Style.font.caption
37
+
38
+ signal clicked()
39
+ signal hovered(bool isHovered)
40
+
41
+ activeFocusOnTab: true
42
+ Keys.onReturnPressed: root.clicked()
43
+ Keys.onEnterPressed: root.clicked()
44
+ Keys.onSpacePressed: root.clicked()
45
+
46
+ implicitHeight: Math.max(54, content.implicitHeight + Style.spacing.huge)
47
+ implicitWidth: Style.space(240)
48
+ radius: Style.cornerRadius
49
+
50
+ readonly property bool _hot: hasCursor || mouse.containsMouse
51
+ readonly property var _borderSpec: Border.controlSpec(activeFocus ? "focus" : (_hot ? "hover-cursor" : "normal"), foreground, accent)
52
+
53
+ color: Style.controlFill(activeFocus, _hot, foreground, accent)
54
+ borderSpec: _borderSpec
55
+
56
+ Behavior on color { ColorAnimation { duration: Style.duration(100) } }
57
+
58
+ Row {
59
+ id: content
60
+ anchors.left: parent.left
61
+ anchors.right: parent.right
62
+ anchors.verticalCenter: parent.verticalCenter
63
+ anchors.leftMargin: root.borderLeft + Style.spacing.rowPaddingX
64
+ anchors.rightMargin: root.borderRight + Style.spacing.rowPaddingX
65
+ spacing: Style.spacing.rowPaddingX
66
+
67
+ Column {
68
+ width: parent.width - track.width - parent.spacing
69
+ spacing: Style.spacing.xs
70
+ anchors.verticalCenter: parent.verticalCenter
71
+
72
+ Text {
73
+ textFormat: Text.PlainText
74
+ text: root.label
75
+ color: root.foreground
76
+ font.family: root.fontFamily
77
+ font.pixelSize: root.titleSize
78
+ font.bold: true
79
+ elide: Text.ElideRight
80
+ width: parent.width
81
+ }
82
+
83
+ Text {
84
+ textFormat: Text.PlainText
85
+ visible: root.description !== ""
86
+ text: root.description
87
+ color: Qt.darker(root.foreground, 1.5)
88
+ font.family: root.fontFamily
89
+ font.pixelSize: root.descriptionSize
90
+ wrapMode: Text.WordWrap
91
+ width: parent.width
92
+ }
93
+ }
94
+
95
+ // The row owns the click, so the switch is presentation only here.
96
+ ToggleSwitch {
97
+ id: track
98
+ checked: root.checked
99
+ rounded: root.rounded
100
+ foreground: root.foreground
101
+ accent: root.accent
102
+ interactive: false
103
+ anchors.verticalCenter: parent.verticalCenter
104
+ }
105
+ }
106
+
107
+ MouseArea {
108
+ id: mouse
109
+ anchors.fill: parent
110
+ hoverEnabled: true
111
+ cursorShape: Qt.PointingHandCursor
112
+ onClicked: root.clicked()
113
+ }
114
+
115
+ HoverHandler {
116
+ onHoveredChanged: root.hovered(hovered)
117
+ }
118
+ }
@@ -0,0 +1,115 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import qs.Commons as Commons
4
+
5
+ // Bare on/off switch: a track with a sliding knob and no label. This is the
6
+ // switch `Toggle` parks at the end of its labeled row, factored out so panel
7
+ // headers and other compact controls render the identical thing.
8
+ //
9
+ // The caller owns the value: bind `checked` to real state and flip it in
10
+ // response to `toggled()`. Services that already track a desired state
11
+ // optimistically (see the Tailscale service's `_desired`) get an instant knob
12
+ // throw for free, because `checked` is already the optimistic value.
13
+ //
14
+ // `busy` marks an operation in flight and swallows further clicks, but leaves
15
+ // hover, cursor, and tooltips alone so the control does not flicker every time
16
+ // a background refresh runs.
17
+ //
18
+ // The cursor is a ring drawn outside the track rather than a state on the
19
+ // track itself: themes give normal chrome a stronger border than hover-cursor
20
+ // (0.4 vs 0.25 by default), which is right for controls that are borderless at
21
+ // rest but would make a bordered track go *fainter* under the cursor. On the
22
+ // panel background the ring reads immediately. `cursorRing` follows
23
+ // `interactive` — a switch whose surrounding row owns the click owns the
24
+ // cursor too.
25
+ //
26
+ // `rounded` auto-detects from Style.cornerRadius so the switch follows the
27
+ // theme: pill shape when Hyprland corners are rounded, square on sharp.
28
+ Item {
29
+ id: root
30
+
31
+ property bool checked: false
32
+ property bool busy: false
33
+ // The knob is placed by x, so a mirrored (right-to-left) layout throws it
34
+ // toward the left when on.
35
+ readonly property bool mirrored: LayoutMirroring.enabled
36
+
37
+ // Off when the surrounding row owns the click, as in `Toggle`.
38
+ property bool interactive: true
39
+
40
+ // Panel-cursor flag. Same role as Button.hasCursor: panels with their own
41
+ // keyboard cursor bind this to drive the highlight separately from hover.
42
+ property bool hasCursor: false
43
+
44
+ property bool cursorRing: interactive
45
+ property int cursorPad: Style.space(6)
46
+ property bool rounded: Style.cornerRadius > 0
47
+ property color foreground: Commons.Color.foreground
48
+ property color accent: Commons.Color.accent
49
+
50
+ signal toggled()
51
+ signal hovered(bool isHovered)
52
+
53
+ readonly property alias containsMouse: mouse.containsMouse
54
+ readonly property bool hot: hasCursor || mouse.containsMouse
55
+
56
+ // `trackHeight` is settable so a compact placement — a switch riding a panel
57
+ // section header, say — can ask for a genuinely smaller control instead of
58
+ // scaling a big one down, which lands the track and knob on fractional pixels
59
+ // and blurs their edges. The derived sizes only carry floors low enough to
60
+ // stay out of an override's way; at the default track height each one is
61
+ // already above its floor, so nothing about the normal switch changes.
62
+ property int trackHeight: Math.max(22, Math.round(Style.spacing.controlHeight * 0.55))
63
+ property int trackWidth: Math.round(trackHeight * 1.9)
64
+ property int knobSize: Math.max(6, Math.round(trackHeight * 0.72))
65
+ property int knobInset: Math.max(1, Math.round((trackHeight - knobSize) / 2))
66
+
67
+ readonly property int _pad: cursorRing ? cursorPad : 0
68
+
69
+ implicitWidth: trackWidth + _pad * 2
70
+ implicitHeight: trackHeight + _pad * 2
71
+
72
+ BorderSurface {
73
+ anchors.fill: parent
74
+ visible: root.cursorRing && root.hot
75
+ color: "transparent"
76
+ radius: Style.cornerRadius
77
+ borderSpec: Border.controlSpec("hover-cursor", root.foreground, root.accent)
78
+ }
79
+
80
+ BorderSurface {
81
+ id: track
82
+ width: root.trackWidth
83
+ height: root.trackHeight
84
+ anchors.centerIn: parent
85
+ radius: root.rounded ? height / 2 : 0
86
+ color: root.checked
87
+ ? Style.selectedFillFor(root.foreground, root.accent)
88
+ : Style.normalFillFor(root.foreground, root.accent)
89
+ borderSpec: Border.controlSpec(root.checked ? "selected" : "normal", root.foreground, root.accent)
90
+
91
+ Behavior on color { ColorAnimation { duration: Style.duration(120) } }
92
+
93
+ Rectangle {
94
+ width: root.knobSize
95
+ height: root.knobSize
96
+ radius: root.rounded ? height / 2 : 0
97
+ x: root.checked !== root.mirrored ? track.width - width - root.knobInset : root.knobInset
98
+ anchors.verticalCenter: parent.verticalCenter
99
+ color: root.checked ? Style.selectedStateColor(root.foreground, root.accent) : Qt.darker(root.foreground, 1.25)
100
+
101
+ Behavior on x { NumberAnimation { duration: Style.duration(120); easing.type: Easing.OutCubic } }
102
+ Behavior on color { ColorAnimation { duration: Style.duration(120) } }
103
+ }
104
+ }
105
+
106
+ MouseArea {
107
+ id: mouse
108
+ anchors.fill: parent
109
+ enabled: root.interactive
110
+ hoverEnabled: true
111
+ cursorShape: Qt.PointingHandCursor
112
+ onContainsMouseChanged: root.hovered(containsMouse)
113
+ onClicked: if (!root.busy) root.toggled()
114
+ }
115
+ }