roxxie-proxy-u-prod 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (481) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +123 -0
  3. package/SOURCE.md +29 -0
  4. package/THIRD_PARTY_NOTICES.md +24 -0
  5. package/dist/assets/filters-Bu_3nHVy.bin +0 -0
  6. package/dist/assets/index-BdRlQ7d_.css +1 -0
  7. package/dist/assets/index-DcvPYWS3.js +3621 -0
  8. package/dist/assets/inject-BnVzMVpl.js +40 -0
  9. package/dist/assets/scramjet-C9HLwI-y.wasm +0 -0
  10. package/dist/defaultfavicon.png +0 -0
  11. package/dist/icon.png +0 -0
  12. package/dist/roxxie-icon.svg +12 -0
  13. package/embed.js +70 -0
  14. package/examples/single-page.html +25 -0
  15. package/package.json +42 -0
  16. package/runtime/controller.sw.js +273 -0
  17. package/runtime/index.html +18 -0
  18. package/runtime/localcontrollersw.js +7 -0
  19. package/runtime/roxxie-network.json +13 -0
  20. package/runtime/sw.js +6 -0
  21. package/scripts/build.mjs +344 -0
  22. package/scripts/smoke.mjs +123 -0
  23. package/scripts/verify.mjs +122 -0
  24. package/source/external/dreamlandjs/LICENSE +21 -0
  25. package/source/external/dreamlandjs/README.md +22 -0
  26. package/source/external/dreamlandjs/dist/core.d.ts +167 -0
  27. package/source/external/dreamlandjs/dist/core.js +2 -0
  28. package/source/external/dreamlandjs/dist/core.js.map +1 -0
  29. package/source/external/dreamlandjs/dist/core.size.html +4950 -0
  30. package/source/external/dreamlandjs/dist/js-runtime.d.ts +3 -0
  31. package/source/external/dreamlandjs/dist/js-runtime.js +2 -0
  32. package/source/external/dreamlandjs/dist/js-runtime.js.map +1 -0
  33. package/source/external/dreamlandjs/dist/jsx-runtime.d.ts +1 -0
  34. package/source/external/dreamlandjs/dist/jsx-runtime.js +2 -0
  35. package/source/external/dreamlandjs/dist/jsx-runtime.js.map +1 -0
  36. package/source/external/dreamlandjs/dist/motion.d.ts +19 -0
  37. package/source/external/dreamlandjs/dist/motion.js +2 -0
  38. package/source/external/dreamlandjs/dist/motion.js.map +1 -0
  39. package/source/external/dreamlandjs/dist/router.d.ts +48 -0
  40. package/source/external/dreamlandjs/dist/router.js +2 -0
  41. package/source/external/dreamlandjs/dist/router.js.map +1 -0
  42. package/source/external/dreamlandjs/dist/ssr.client.d.ts +3 -0
  43. package/source/external/dreamlandjs/dist/ssr.client.js +2 -0
  44. package/source/external/dreamlandjs/dist/ssr.client.js.map +1 -0
  45. package/source/external/dreamlandjs/dist/ssr.client.size.html +4950 -0
  46. package/source/external/dreamlandjs/dist/ssr.hybrid.d.ts +7 -0
  47. package/source/external/dreamlandjs/dist/ssr.hybrid.js +2 -0
  48. package/source/external/dreamlandjs/dist/ssr.hybrid.js.map +1 -0
  49. package/source/external/dreamlandjs/dist/ssr.hybrid.size.html +4950 -0
  50. package/source/external/dreamlandjs/dist/ssr.server.d.ts +11 -0
  51. package/source/external/dreamlandjs/dist/ssr.server.js +2373 -0
  52. package/source/external/dreamlandjs/dist/ssr.server.js.map +1 -0
  53. package/source/external/dreamlandjs/dist/types/core/consts.d.ts +16 -0
  54. package/source/external/dreamlandjs/dist/types/core/css/index.d.ts +11 -0
  55. package/source/external/dreamlandjs/dist/types/core/css/selectorParser.d.ts +50 -0
  56. package/source/external/dreamlandjs/dist/types/core/delegate.d.ts +10 -0
  57. package/source/external/dreamlandjs/dist/types/core/index.d.ts +9 -0
  58. package/source/external/dreamlandjs/dist/types/core/jsx/child.d.ts +2 -0
  59. package/source/external/dreamlandjs/dist/types/core/jsx/definitions.d.ts +76 -0
  60. package/source/external/dreamlandjs/dist/types/core/jsx/dom.d.ts +28 -0
  61. package/source/external/dreamlandjs/dist/types/core/jsx/index.d.ts +14 -0
  62. package/source/external/dreamlandjs/dist/types/core/state/index.d.ts +1 -0
  63. package/source/external/dreamlandjs/dist/types/core/state/pointers.d.ts +37 -0
  64. package/source/external/dreamlandjs/dist/types/core/state/state.d.ts +13 -0
  65. package/source/external/dreamlandjs/dist/types/core/state/use.d.ts +11 -0
  66. package/source/external/dreamlandjs/dist/types/core/utils.d.ts +4 -0
  67. package/source/external/dreamlandjs/dist/types/js-runtime/index.d.ts +1 -0
  68. package/source/external/dreamlandjs/dist/types/jsx-runtime/index.d.ts +2 -0
  69. package/source/external/dreamlandjs/dist/types/motion/index.d.ts +15 -0
  70. package/source/external/dreamlandjs/dist/types/router/index.d.ts +45 -0
  71. package/source/external/dreamlandjs/dist/types/ssr/client/index.d.ts +1 -0
  72. package/source/external/dreamlandjs/dist/types/ssr/common/consts.d.ts +4 -0
  73. package/source/external/dreamlandjs/dist/types/ssr/common/serialize.d.ts +4 -0
  74. package/source/external/dreamlandjs/dist/types/ssr/common/types.d.ts +21 -0
  75. package/source/external/dreamlandjs/dist/types/ssr/hybrid/index.d.ts +4 -0
  76. package/source/external/dreamlandjs/dist/types/ssr/server/index.d.ts +7 -0
  77. package/source/external/dreamlandjs/dist/types/ssr/server/vdom.d.ts +71 -0
  78. package/source/external/dreamlandjs/dist/types/util/index.d.ts +1 -0
  79. package/source/external/dreamlandjs/dist/types/util/store.d.ts +26 -0
  80. package/source/external/dreamlandjs/dist/types/vite/css-minifier.d.ts +7 -0
  81. package/source/external/dreamlandjs/dist/types/vite/index.d.ts +11 -0
  82. package/source/external/dreamlandjs/dist/util.d.ts +29 -0
  83. package/source/external/dreamlandjs/dist/util.js +2 -0
  84. package/source/external/dreamlandjs/dist/util.js.map +1 -0
  85. package/source/external/dreamlandjs/dist/vite.d.ts +19 -0
  86. package/source/external/dreamlandjs/dist/vite.js +2 -0
  87. package/source/external/dreamlandjs/dist/vite.js.map +1 -0
  88. package/source/external/dreamlandjs/package.json +101 -0
  89. package/source/external/dreamlandjs/rollup.config.ts +302 -0
  90. package/source/external/dreamlandjs/rollup.plugins.ts +1134 -0
  91. package/source/external/dreamlandjs/src/core/consts.d.ts +16 -0
  92. package/source/external/dreamlandjs/src/core/consts.js +18 -0
  93. package/source/external/dreamlandjs/src/core/css/index.ts +111 -0
  94. package/source/external/dreamlandjs/src/core/css/selectorParser.ts +313 -0
  95. package/source/external/dreamlandjs/src/core/delegate.ts +28 -0
  96. package/source/external/dreamlandjs/src/core/index.ts +31 -0
  97. package/source/external/dreamlandjs/src/core/jsx/child.ts +91 -0
  98. package/source/external/dreamlandjs/src/core/jsx/definitions.ts +125 -0
  99. package/source/external/dreamlandjs/src/core/jsx/dom.ts +49 -0
  100. package/source/external/dreamlandjs/src/core/jsx/index.ts +289 -0
  101. package/source/external/dreamlandjs/src/core/state/index.ts +1 -0
  102. package/source/external/dreamlandjs/src/core/state/pointers.ts +310 -0
  103. package/source/external/dreamlandjs/src/core/state/state.ts +112 -0
  104. package/source/external/dreamlandjs/src/core/state/use.ts +82 -0
  105. package/source/external/dreamlandjs/src/core/utils.ts +48 -0
  106. package/source/external/dreamlandjs/src/js-runtime/index.ts +4 -0
  107. package/source/external/dreamlandjs/src/jsx-runtime/index.ts +3 -0
  108. package/source/external/dreamlandjs/src/motion/index.ts +156 -0
  109. package/source/external/dreamlandjs/src/router/index.tsx +394 -0
  110. package/source/external/dreamlandjs/src/router/tsconfig.json +9 -0
  111. package/source/external/dreamlandjs/src/ssr/client/index.ts +193 -0
  112. package/source/external/dreamlandjs/src/ssr/common/consts.ts +5 -0
  113. package/source/external/dreamlandjs/src/ssr/common/serialize.ts +115 -0
  114. package/source/external/dreamlandjs/src/ssr/common/types.ts +28 -0
  115. package/source/external/dreamlandjs/src/ssr/hybrid/index.ts +144 -0
  116. package/source/external/dreamlandjs/src/ssr/server/index.ts +157 -0
  117. package/source/external/dreamlandjs/src/ssr/server/tsconfig.json +7 -0
  118. package/source/external/dreamlandjs/src/ssr/server/vdom.ts +285 -0
  119. package/source/external/dreamlandjs/src/util/index.ts +10 -0
  120. package/source/external/dreamlandjs/src/util/store.ts +134 -0
  121. package/source/external/dreamlandjs/src/vite/css-minifier.ts +222 -0
  122. package/source/external/dreamlandjs/src/vite/index.ts +60 -0
  123. package/source/external/dreamlandjs/src/vite/tsconfig.json +7 -0
  124. package/source/external/dreamlandjs/tsconfig.json +15 -0
  125. package/source/package.json +48 -0
  126. package/source/packages/adrift-protocol/package.json +31 -0
  127. package/source/packages/adrift-protocol/src/index.ts +348 -0
  128. package/source/packages/adrift-protocol/tsconfig.json +18 -0
  129. package/source/packages/cdp/LICENSE +21 -0
  130. package/source/packages/cdp/README.md +47 -0
  131. package/source/packages/cdp/dist/chobitsu.js +2 -0
  132. package/source/packages/cdp/dist/chobitsu.js.map +1 -0
  133. package/source/packages/cdp/package.json +73 -0
  134. package/source/packages/cdp/script/build.js +15 -0
  135. package/source/packages/cdp/src/Chobitsu.ts +110 -0
  136. package/source/packages/cdp/src/domains/CSS.ts +378 -0
  137. package/source/packages/cdp/src/domains/CacheStorage.ts +8 -0
  138. package/source/packages/cdp/src/domains/DOM.ts +487 -0
  139. package/source/packages/cdp/src/domains/DOMDebugger.ts +109 -0
  140. package/source/packages/cdp/src/domains/DOMStorage.ts +122 -0
  141. package/source/packages/cdp/src/domains/Debugger.ts +25 -0
  142. package/source/packages/cdp/src/domains/IndexedDB.ts +207 -0
  143. package/source/packages/cdp/src/domains/Input.ts +177 -0
  144. package/source/packages/cdp/src/domains/Network.ts +251 -0
  145. package/source/packages/cdp/src/domains/Overlay.ts +230 -0
  146. package/source/packages/cdp/src/domains/Page.ts +296 -0
  147. package/source/packages/cdp/src/domains/Runtime.ts +273 -0
  148. package/source/packages/cdp/src/domains/Storage.ts +71 -0
  149. package/source/packages/cdp/src/index.d.ts +8 -0
  150. package/source/packages/cdp/src/index.ts +153 -0
  151. package/source/packages/cdp/src/lib/connector.ts +15 -0
  152. package/source/packages/cdp/src/lib/constants.ts +1 -0
  153. package/source/packages/cdp/src/lib/evaluate.ts +59 -0
  154. package/source/packages/cdp/src/lib/mutationObserver.ts +39 -0
  155. package/source/packages/cdp/src/lib/nodeManager.ts +142 -0
  156. package/source/packages/cdp/src/lib/objManager.ts +422 -0
  157. package/source/packages/cdp/src/lib/request.ts +313 -0
  158. package/source/packages/cdp/src/lib/resources.ts +59 -0
  159. package/source/packages/cdp/src/lib/scriptMananger.ts +62 -0
  160. package/source/packages/cdp/src/lib/stylesheet.ts +146 -0
  161. package/source/packages/cdp/src/lib/util.ts +105 -0
  162. package/source/packages/cdp/tsconfig.json +16 -0
  163. package/source/packages/cdp/webpack.config.js +48 -0
  164. package/source/packages/chrome/index.html +17 -0
  165. package/source/packages/chrome/package.json +41 -0
  166. package/source/packages/chrome/public/ROXXIE_NETWORK.md +22 -0
  167. package/source/packages/chrome/public/controller.sw.js +273 -0
  168. package/source/packages/chrome/public/defaultfavicon.png +0 -0
  169. package/source/packages/chrome/public/icon.png +0 -0
  170. package/source/packages/chrome/public/localcontrollersw.js +7 -0
  171. package/source/packages/chrome/public/roxxie-icon.svg +12 -0
  172. package/source/packages/chrome/public/roxxie-network.json +13 -0
  173. package/source/packages/chrome/public/sw.js +6 -0
  174. package/source/packages/chrome/src/App.tsx +269 -0
  175. package/source/packages/chrome/src/CDP.ts +285 -0
  176. package/source/packages/chrome/src/Tab/History.ts +186 -0
  177. package/source/packages/chrome/src/Tab/Tab.tsx +219 -0
  178. package/source/packages/chrome/src/Tab/screenshot.ts +66 -0
  179. package/source/packages/chrome/src/Tab/serialize.ts +221 -0
  180. package/source/packages/chrome/src/adblock/AdBlockPlugin.test.ts +159 -0
  181. package/source/packages/chrome/src/adblock/AdBlockPlugin.ts +232 -0
  182. package/source/packages/chrome/src/adblock/AdBlockService.test.ts +148 -0
  183. package/source/packages/chrome/src/adblock/AdBlockService.ts +166 -0
  184. package/source/packages/chrome/src/adblock/NOTICE.md +14 -0
  185. package/source/packages/chrome/src/adblock/assets/filters.bin +0 -0
  186. package/source/packages/chrome/src/adblock/index.ts +18 -0
  187. package/source/packages/chrome/src/assets/favicon.ts +4 -0
  188. package/source/packages/chrome/src/components/BookmarkPopup.tsx +101 -0
  189. package/source/packages/chrome/src/components/BookmarksStrip.tsx +150 -0
  190. package/source/packages/chrome/src/components/Button.tsx +99 -0
  191. package/source/packages/chrome/src/components/Checkbox.tsx +89 -0
  192. package/source/packages/chrome/src/components/DownloadsPopup.tsx +230 -0
  193. package/source/packages/chrome/src/components/Favicon.tsx +65 -0
  194. package/source/packages/chrome/src/components/Icon.tsx +29 -0
  195. package/source/packages/chrome/src/components/Input.tsx +82 -0
  196. package/source/packages/chrome/src/components/Menu.tsx +287 -0
  197. package/source/packages/chrome/src/components/Omnibar/BookmarkButton.tsx +73 -0
  198. package/source/packages/chrome/src/components/Omnibar/CircularProgress.tsx +83 -0
  199. package/source/packages/chrome/src/components/Omnibar/Omnibar.tsx +455 -0
  200. package/source/packages/chrome/src/components/Omnibar/OmnibarButton.tsx +48 -0
  201. package/source/packages/chrome/src/components/Omnibar/Omnibox.tsx +466 -0
  202. package/source/packages/chrome/src/components/Omnibar/SiteOptionsButton.tsx +52 -0
  203. package/source/packages/chrome/src/components/Omnibar/Suggestion.tsx +186 -0
  204. package/source/packages/chrome/src/components/Omnibar/UrlInput.tsx +198 -0
  205. package/source/packages/chrome/src/components/Omnibar/suggestions.ts +468 -0
  206. package/source/packages/chrome/src/components/Omnibar/utils.ts +11 -0
  207. package/source/packages/chrome/src/components/ReportBrokenSiteModal.tsx +279 -0
  208. package/source/packages/chrome/src/components/Shell.tsx +191 -0
  209. package/source/packages/chrome/src/components/SiteInformationPopup.tsx +96 -0
  210. package/source/packages/chrome/src/components/SmallIconButton.tsx +36 -0
  211. package/source/packages/chrome/src/components/StartScreen.tsx +386 -0
  212. package/source/packages/chrome/src/components/TabStrip/DragTab.tsx +546 -0
  213. package/source/packages/chrome/src/components/TabStrip/Sidebar.tsx +820 -0
  214. package/source/packages/chrome/src/components/TabStrip/TabHoverCard.tsx +87 -0
  215. package/source/packages/chrome/src/components/TabStrip/TabStrip.tsx +510 -0
  216. package/source/packages/chrome/src/components/TopSiteButton.tsx +234 -0
  217. package/source/packages/chrome/src/consts.ts +3 -0
  218. package/source/packages/chrome/src/icons.ts +70 -0
  219. package/source/packages/chrome/src/index.ts +168 -0
  220. package/source/packages/chrome/src/migrations/0-from-legacy.ts +6 -0
  221. package/source/packages/chrome/src/migrations/1-vertical-tab-settings.ts +15 -0
  222. package/source/packages/chrome/src/migrations/index.ts +42 -0
  223. package/source/packages/chrome/src/pages/AboutPage.tsx +37 -0
  224. package/source/packages/chrome/src/pages/DownloadsPage.tsx +133 -0
  225. package/source/packages/chrome/src/pages/HistoryPage.tsx +99 -0
  226. package/source/packages/chrome/src/pages/NewTabPage.tsx +264 -0
  227. package/source/packages/chrome/src/pages/PlaygroundPage.tsx +43 -0
  228. package/source/packages/chrome/src/pages/SettingsPage.tsx +1931 -0
  229. package/source/packages/chrome/src/proxy/Controller.ts +331 -0
  230. package/source/packages/chrome/src/proxy/ProxyFrame.ts +26 -0
  231. package/source/packages/chrome/src/proxy/cache.ts +487 -0
  232. package/source/packages/chrome/src/proxy/codec.ts +11 -0
  233. package/source/packages/chrome/src/proxy/contextitems.ts +180 -0
  234. package/source/packages/chrome/src/proxy/index.ts +5 -0
  235. package/source/packages/chrome/src/proxy/roxxie.ts +85 -0
  236. package/source/packages/chrome/src/proxy/scramjet.ts +642 -0
  237. package/source/packages/chrome/src/reset.css +124 -0
  238. package/source/packages/chrome/src/runtime-base.ts +16 -0
  239. package/source/packages/chrome/src/sentry.tsx +45 -0
  240. package/source/packages/chrome/src/services/DownloadsService.ts +136 -0
  241. package/source/packages/chrome/src/services/FaviconService.ts +161 -0
  242. package/source/packages/chrome/src/services/KVWrapper.ts +169 -0
  243. package/source/packages/chrome/src/services/ProfileService.ts +94 -0
  244. package/source/packages/chrome/src/services/Service.ts +10 -0
  245. package/source/packages/chrome/src/services/SettingsService.ts +108 -0
  246. package/source/packages/chrome/src/services/TabsService.ts +161 -0
  247. package/source/packages/chrome/src/startup.test.ts +129 -0
  248. package/source/packages/chrome/src/startup.ts +161 -0
  249. package/source/packages/chrome/src/style.css +229 -0
  250. package/source/packages/chrome/src/themes.ts +756 -0
  251. package/source/packages/chrome/src/util/StatefulClass.ts +31 -0
  252. package/source/packages/chrome/src/util/index.ts +74 -0
  253. package/source/packages/chrome/src/util/memoize.ts +13 -0
  254. package/source/packages/chrome/src/vite-env.d.ts +16 -0
  255. package/source/packages/chrome/tsconfig.json +30 -0
  256. package/source/packages/chrome/vite.config.ts +47 -0
  257. package/source/packages/inject/package.json +20 -0
  258. package/source/packages/inject/src/context.ts +194 -0
  259. package/source/packages/inject/src/emulators/alwaysLastBubble.ts +168 -0
  260. package/source/packages/inject/src/emulators/anchors.ts +55 -0
  261. package/source/packages/inject/src/emulators/contextmenu.ts +46 -0
  262. package/source/packages/inject/src/emulators/history.ts +51 -0
  263. package/source/packages/inject/src/emulators/titlewatcher.ts +42 -0
  264. package/source/packages/inject/src/emulators/windowopen.ts +134 -0
  265. package/source/packages/inject/src/errorpage/errorpage.css +234 -0
  266. package/source/packages/inject/src/errorpage/errorpage.html +29 -0
  267. package/source/packages/inject/src/errorpage/errorpage.ts +76 -0
  268. package/source/packages/inject/src/index.ts +62 -0
  269. package/source/packages/inject/src/transport.ts +97 -0
  270. package/source/packages/inject/src/types.d.ts +136 -0
  271. package/source/packages/roxxie-transport/package.json +36 -0
  272. package/source/packages/roxxie-transport/src/binary.ts +398 -0
  273. package/source/packages/roxxie-transport/src/config.ts +254 -0
  274. package/source/packages/roxxie-transport/src/connection.ts +767 -0
  275. package/source/packages/roxxie-transport/src/index.ts +5 -0
  276. package/source/packages/roxxie-transport/src/tracker.ts +651 -0
  277. package/source/packages/roxxie-transport/src/transport.ts +414 -0
  278. package/source/packages/roxxie-transport/tsconfig.json +18 -0
  279. package/source/packages/scramjet/packages/controller/package.json +37 -0
  280. package/source/packages/scramjet/packages/controller/src/index.ts +861 -0
  281. package/source/packages/scramjet/packages/controller/src/inject.ts +365 -0
  282. package/source/packages/scramjet/packages/controller/src/sw.ts +231 -0
  283. package/source/packages/scramjet/packages/controller/src/symbols.ts +1 -0
  284. package/source/packages/scramjet/packages/controller/src/types.d.ts +140 -0
  285. package/source/packages/scramjet/packages/controller/src/typesEntry.ts +6 -0
  286. package/source/packages/scramjet/packages/controller/src/version.ts +30 -0
  287. package/source/packages/scramjet/packages/controller/tsconfig.json +24 -0
  288. package/source/packages/scramjet/packages/core/dist/scramjet-external.mjs +57 -0
  289. package/source/packages/scramjet/packages/core/dist/scramjet.js +13599 -0
  290. package/source/packages/scramjet/packages/core/dist/scramjet.js.map +1 -0
  291. package/source/packages/scramjet/packages/core/dist/scramjet.mjs +13649 -0
  292. package/source/packages/scramjet/packages/core/dist/scramjet.mjs.map +1 -0
  293. package/source/packages/scramjet/packages/core/dist/scramjet.wasm +0 -0
  294. package/source/packages/scramjet/packages/core/dist/scramjet_bundled.js +13601 -0
  295. package/source/packages/scramjet/packages/core/dist/scramjet_bundled.js.map +1 -0
  296. package/source/packages/scramjet/packages/core/dist/scramjet_bundled.mjs +13651 -0
  297. package/source/packages/scramjet/packages/core/dist/scramjet_bundled.mjs.map +1 -0
  298. package/source/packages/scramjet/packages/core/dist/temp-types-build/index.js +23 -0
  299. package/source/packages/scramjet/packages/core/dist/temp-types-build/index.js.map +1 -0
  300. package/source/packages/scramjet/packages/core/dist/types/Tap.d.ts +39 -0
  301. package/source/packages/scramjet/packages/core/dist/types/client/client.d.ts +115 -0
  302. package/source/packages/scramjet/packages/core/dist/types/client/entry.d.ts +5 -0
  303. package/source/packages/scramjet/packages/core/dist/types/client/events.d.ts +10 -0
  304. package/source/packages/scramjet/packages/core/dist/types/client/helpers.d.ts +1 -0
  305. package/source/packages/scramjet/packages/core/dist/types/client/index.d.ts +7 -0
  306. package/source/packages/scramjet/packages/core/dist/types/client/location.d.ts +2 -0
  307. package/source/packages/scramjet/packages/core/dist/types/client/shared/eval.d.ts +3 -0
  308. package/source/packages/scramjet/packages/core/dist/types/client/shared/sourcemaps.d.ts +19 -0
  309. package/source/packages/scramjet/packages/core/dist/types/client/shared/wrap.d.ts +4 -0
  310. package/source/packages/scramjet/packages/core/dist/types/client/singletonbox.d.ts +18 -0
  311. package/source/packages/scramjet/packages/core/dist/types/fetch/body.d.ts +3 -0
  312. package/source/packages/scramjet/packages/core/dist/types/fetch/fetch.d.ts +7 -0
  313. package/source/packages/scramjet/packages/core/dist/types/fetch/headers.d.ts +19 -0
  314. package/source/packages/scramjet/packages/core/dist/types/fetch/index.d.ts +128 -0
  315. package/source/packages/scramjet/packages/core/dist/types/fetch/parse.d.ts +23 -0
  316. package/source/packages/scramjet/packages/core/dist/types/fetch/util.d.ts +7 -0
  317. package/source/packages/scramjet/packages/core/dist/types/index.d.ts +12 -0
  318. package/source/packages/scramjet/packages/core/dist/types/shared/cookie.d.ts +26 -0
  319. package/source/packages/scramjet/packages/core/dist/types/shared/headers.d.ts +13 -0
  320. package/source/packages/scramjet/packages/core/dist/types/shared/htmlRules.d.ts +6 -0
  321. package/source/packages/scramjet/packages/core/dist/types/shared/index.d.ts +50 -0
  322. package/source/packages/scramjet/packages/core/dist/types/shared/mime.d.ts +53 -0
  323. package/source/packages/scramjet/packages/core/dist/types/shared/refresh.d.ts +7 -0
  324. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/css.d.ts +4 -0
  325. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/html.d.ts +33 -0
  326. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/index.d.ts +6 -0
  327. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/js.d.ts +11 -0
  328. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/url.d.ts +24 -0
  329. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/wasm.d.ts +7 -0
  330. package/source/packages/scramjet/packages/core/dist/types/shared/rewriters/worker.d.ts +3 -0
  331. package/source/packages/scramjet/packages/core/dist/types/shared/set-cookie-parser.d.ts +20 -0
  332. package/source/packages/scramjet/packages/core/dist/types/shared/snapshot.d.ts +186 -0
  333. package/source/packages/scramjet/packages/core/dist/types/shared/sniffEncoding.d.ts +65 -0
  334. package/source/packages/scramjet/packages/core/dist/types/shared/util.d.ts +2 -0
  335. package/source/packages/scramjet/packages/core/dist/types/symbols.d.ts +6 -0
  336. package/source/packages/scramjet/packages/core/dist/types/types.d.ts +60 -0
  337. package/source/packages/scramjet/packages/core/dist/types/typesEntry.d.ts +5 -0
  338. package/source/packages/scramjet/packages/core/lib/index.cjs +7 -0
  339. package/source/packages/scramjet/packages/core/lib/index.d.ts +8 -0
  340. package/source/packages/scramjet/packages/core/package.json +69 -0
  341. package/source/packages/scramjet/packages/core/rewriter/Cargo.lock +1985 -0
  342. package/source/packages/scramjet/packages/core/rewriter/Cargo.toml +20 -0
  343. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/Cargo.toml +15 -0
  344. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/analyze.rs +1118 -0
  345. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/ast_table.rs +927 -0
  346. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/helper_index.rs +556 -0
  347. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/lib.rs +455 -0
  348. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/reachability.rs +85 -0
  349. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/templates.rs +192 -0
  350. package/source/packages/scramjet/packages/core/rewriter/coverage-macro/src/witness.rs +597 -0
  351. package/source/packages/scramjet/packages/core/rewriter/js/Cargo.toml +18 -0
  352. package/source/packages/scramjet/packages/core/rewriter/js/src/cfg.rs +45 -0
  353. package/source/packages/scramjet/packages/core/rewriter/js/src/changes.rs +379 -0
  354. package/source/packages/scramjet/packages/core/rewriter/js/src/lib.rs +171 -0
  355. package/source/packages/scramjet/packages/core/rewriter/js/src/rewrite.rs +290 -0
  356. package/source/packages/scramjet/packages/core/rewriter/js/src/visitor.rs +967 -0
  357. package/source/packages/scramjet/packages/core/rewriter/native/Cargo.toml +22 -0
  358. package/source/packages/scramjet/packages/core/rewriter/native/src/main.rs +166 -0
  359. package/source/packages/scramjet/packages/core/rewriter/native/src/rewriter.rs +161 -0
  360. package/source/packages/scramjet/packages/core/rewriter/native/src/test_runner.rs +156 -0
  361. package/source/packages/scramjet/packages/core/rewriter/rust-toolchain.toml +5 -0
  362. package/source/packages/scramjet/packages/core/rewriter/rustfmt.toml +2 -0
  363. package/source/packages/scramjet/packages/core/rewriter/transform/Cargo.toml +16 -0
  364. package/source/packages/scramjet/packages/core/rewriter/transform/src/lib.rs +242 -0
  365. package/source/packages/scramjet/packages/core/rewriter/transform/src/transform.rs +123 -0
  366. package/source/packages/scramjet/packages/core/rewriter/wasm/Cargo.toml +22 -0
  367. package/source/packages/scramjet/packages/core/rewriter/wasm/build.sh +128 -0
  368. package/source/packages/scramjet/packages/core/rewriter/wasm/src/error.rs +56 -0
  369. package/source/packages/scramjet/packages/core/rewriter/wasm/src/jsr.rs +125 -0
  370. package/source/packages/scramjet/packages/core/rewriter/wasm/src/lib.rs +144 -0
  371. package/source/packages/scramjet/packages/core/src/Tap.ts +166 -0
  372. package/source/packages/scramjet/packages/core/src/client/client.ts +916 -0
  373. package/source/packages/scramjet/packages/core/src/client/dom/attr.ts +94 -0
  374. package/source/packages/scramjet/packages/core/src/client/dom/beacon.ts +11 -0
  375. package/source/packages/scramjet/packages/core/src/client/dom/cookie.ts +21 -0
  376. package/source/packages/scramjet/packages/core/src/client/dom/css.ts +106 -0
  377. package/source/packages/scramjet/packages/core/src/client/dom/document.ts +140 -0
  378. package/source/packages/scramjet/packages/core/src/client/dom/element.ts +783 -0
  379. package/source/packages/scramjet/packages/core/src/client/dom/fontface.ts +11 -0
  380. package/source/packages/scramjet/packages/core/src/client/dom/fragments.ts +32 -0
  381. package/source/packages/scramjet/packages/core/src/client/dom/history.ts +35 -0
  382. package/source/packages/scramjet/packages/core/src/client/dom/open.ts +59 -0
  383. package/source/packages/scramjet/packages/core/src/client/dom/origin.ts +13 -0
  384. package/source/packages/scramjet/packages/core/src/client/dom/performance.ts +50 -0
  385. package/source/packages/scramjet/packages/core/src/client/dom/protocol.ts +17 -0
  386. package/source/packages/scramjet/packages/core/src/client/dom/storage.ts +107 -0
  387. package/source/packages/scramjet/packages/core/src/client/entry.ts +12 -0
  388. package/source/packages/scramjet/packages/core/src/client/events.ts +10 -0
  389. package/source/packages/scramjet/packages/core/src/client/helpers.ts +7 -0
  390. package/source/packages/scramjet/packages/core/src/client/index.ts +7 -0
  391. package/source/packages/scramjet/packages/core/src/client/location.ts +139 -0
  392. package/source/packages/scramjet/packages/core/src/client/shared/antiantidebugger.ts +20 -0
  393. package/source/packages/scramjet/packages/core/src/client/shared/blob.ts +35 -0
  394. package/source/packages/scramjet/packages/core/src/client/shared/caches.ts +31 -0
  395. package/source/packages/scramjet/packages/core/src/client/shared/chrome.ts +90 -0
  396. package/source/packages/scramjet/packages/core/src/client/shared/err.ts +55 -0
  397. package/source/packages/scramjet/packages/core/src/client/shared/error.ts +42 -0
  398. package/source/packages/scramjet/packages/core/src/client/shared/eval.ts +40 -0
  399. package/source/packages/scramjet/packages/core/src/client/shared/event.ts +215 -0
  400. package/source/packages/scramjet/packages/core/src/client/shared/function.ts +59 -0
  401. package/source/packages/scramjet/packages/core/src/client/shared/import.ts +46 -0
  402. package/source/packages/scramjet/packages/core/src/client/shared/indexeddb.ts +18 -0
  403. package/source/packages/scramjet/packages/core/src/client/shared/opfs.ts +27 -0
  404. package/source/packages/scramjet/packages/core/src/client/shared/postmessage.ts +113 -0
  405. package/source/packages/scramjet/packages/core/src/client/shared/realm.ts +26 -0
  406. package/source/packages/scramjet/packages/core/src/client/shared/requests/eventsource.ts +17 -0
  407. package/source/packages/scramjet/packages/core/src/client/shared/requests/fetch.ts +67 -0
  408. package/source/packages/scramjet/packages/core/src/client/shared/requests/websocket.ts +389 -0
  409. package/source/packages/scramjet/packages/core/src/client/shared/requests/xmlhttprequest.ts +163 -0
  410. package/source/packages/scramjet/packages/core/src/client/shared/settimeout.ts +20 -0
  411. package/source/packages/scramjet/packages/core/src/client/shared/sourcemaps.ts +203 -0
  412. package/source/packages/scramjet/packages/core/src/client/shared/worker.ts +72 -0
  413. package/source/packages/scramjet/packages/core/src/client/shared/wrap.ts +197 -0
  414. package/source/packages/scramjet/packages/core/src/client/singletonbox.ts +52 -0
  415. package/source/packages/scramjet/packages/core/src/client/worker/importScripts.ts +13 -0
  416. package/source/packages/scramjet/packages/core/src/fetch/body.ts +93 -0
  417. package/source/packages/scramjet/packages/core/src/fetch/fetch.ts +323 -0
  418. package/source/packages/scramjet/packages/core/src/fetch/headers.ts +528 -0
  419. package/source/packages/scramjet/packages/core/src/fetch/index.ts +198 -0
  420. package/source/packages/scramjet/packages/core/src/fetch/parse.ts +149 -0
  421. package/source/packages/scramjet/packages/core/src/fetch/util.ts +81 -0
  422. package/source/packages/scramjet/packages/core/src/global.d.ts +32 -0
  423. package/source/packages/scramjet/packages/core/src/index.ts +78 -0
  424. package/source/packages/scramjet/packages/core/src/log.ts +117 -0
  425. package/source/packages/scramjet/packages/core/src/shared/cookie.ts +199 -0
  426. package/source/packages/scramjet/packages/core/src/shared/headers.ts +76 -0
  427. package/source/packages/scramjet/packages/core/src/shared/htmlRules.ts +154 -0
  428. package/source/packages/scramjet/packages/core/src/shared/index.ts +79 -0
  429. package/source/packages/scramjet/packages/core/src/shared/mime.ts +234 -0
  430. package/source/packages/scramjet/packages/core/src/shared/refresh.ts +164 -0
  431. package/source/packages/scramjet/packages/core/src/shared/rewriters/css.ts +67 -0
  432. package/source/packages/scramjet/packages/core/src/shared/rewriters/html.ts +603 -0
  433. package/source/packages/scramjet/packages/core/src/shared/rewriters/index.ts +6 -0
  434. package/source/packages/scramjet/packages/core/src/shared/rewriters/js.ts +158 -0
  435. package/source/packages/scramjet/packages/core/src/shared/rewriters/url.ts +248 -0
  436. package/source/packages/scramjet/packages/core/src/shared/rewriters/wasm.ts +58 -0
  437. package/source/packages/scramjet/packages/core/src/shared/rewriters/worker.ts +37 -0
  438. package/source/packages/scramjet/packages/core/src/shared/set-cookie-parser.ts +195 -0
  439. package/source/packages/scramjet/packages/core/src/shared/snapshot.ts +245 -0
  440. package/source/packages/scramjet/packages/core/src/shared/sniffEncoding.ts +1061 -0
  441. package/source/packages/scramjet/packages/core/src/shared/util.ts +35 -0
  442. package/source/packages/scramjet/packages/core/src/symbols.ts +9 -0
  443. package/source/packages/scramjet/packages/core/src/sync.ts +63 -0
  444. package/source/packages/scramjet/packages/core/src/types.ts +66 -0
  445. package/source/packages/scramjet/packages/core/src/typesEntry.ts +6 -0
  446. package/source/packages/scramjet/packages/core/tsconfig.json +21 -0
  447. package/source/packages/scramjet/packages/rpc/index.ts +100 -0
  448. package/source/packages/scramjet/packages/rpc/package.json +7 -0
  449. package/source/packages/scramjet/packages/utils/package.json +39 -0
  450. package/source/packages/scramjet/packages/utils/src/alwaysLastBubble.ts +172 -0
  451. package/source/packages/scramjet/packages/utils/src/catch-escaped-links.ts +34 -0
  452. package/source/packages/scramjet/packages/utils/src/event-handler-plugin.ts +86 -0
  453. package/source/packages/scramjet/packages/utils/src/global.d.ts +8 -0
  454. package/source/packages/scramjet/packages/utils/src/http-cache-plugin.ts +475 -0
  455. package/source/packages/scramjet/packages/utils/src/index.ts +26 -0
  456. package/source/packages/scramjet/packages/utils/src/link-handler-plugin.ts +75 -0
  457. package/source/packages/scramjet/packages/utils/src/typesEntry.ts +5 -0
  458. package/source/packages/scramjet/packages/utils/src/url-watcher.ts +37 -0
  459. package/source/packages/scramjet/packages/utils/src/version.ts +40 -0
  460. package/source/packages/scramjet/packages/utils/tsconfig.json +11 -0
  461. package/source/packages/scramjet/patches/htmlparser2@12.0.0.patch +124 -0
  462. package/source/packages/scramjet/rspack.config.ts +613 -0
  463. package/source/packages/scramjet/tsconfig.json +11 -0
  464. package/source/packages/tracker-protocol/package.json +31 -0
  465. package/source/packages/tracker-protocol/src/index.ts +745 -0
  466. package/source/packages/tracker-protocol/tsconfig.json +18 -0
  467. package/source/pnpm-lock.yaml +12018 -0
  468. package/source/pnpm-workspace.yaml +31 -0
  469. package/source/rspack.config.ts +103 -0
  470. package/source/scripts/update-adblock-assets.mjs +164 -0
  471. package/third_party/filter-lists/LICENSE-CC-BY-SA-3.0.txt +359 -0
  472. package/third_party/filter-lists/LICENSE-GPL-3.0.txt +674 -0
  473. package/third_party/filter-lists/LICENSE-MPL-2.0.txt +375 -0
  474. package/third_party/filter-lists/README.md +24 -0
  475. package/third_party/filter-lists/easylist.txt +83088 -0
  476. package/third_party/filter-lists/easyprivacy.txt +56361 -0
  477. package/third_party/filter-lists/manifest.json +56 -0
  478. package/third_party/filter-lists/ublock-filters.txt +10937 -0
  479. package/third_party/filter-lists/ublock-privacy.txt +3209 -0
  480. package/third_party/filter-lists/ublock-resources.json +1852 -0
  481. package/third_party/filter-lists/ublock-unbreak.txt +6026 -0
@@ -0,0 +1,1931 @@
1
+ import { css, type FC } from "dreamland/core";
2
+ import type { Tab } from "../Tab/Tab";
3
+ import type { IconifyIcon } from "@iconify/types";
4
+ import { versionInfo } from "@mercuryworkshop/scramjet/bundled";
5
+ import { Icon } from "@components/Icon";
6
+ import { Checkbox } from "@components/Checkbox";
7
+ import { Button } from "@components/Button";
8
+ import { Input } from "@components/Input";
9
+ import { AVAILABLE_SEARCH_ENGINES } from "@components/Omnibar/suggestions";
10
+ import { THEMES } from "../themes";
11
+ import type { TabLayoutMode } from "../services/SettingsService";
12
+
13
+ import {
14
+ iconSettings,
15
+ iconOptions,
16
+ iconSearchOutline as iconSearch,
17
+ iconExtension,
18
+ iconPrivacy,
19
+ iconAbout,
20
+ iconBrush,
21
+ iconAdd,
22
+ iconBack,
23
+ iconClose,
24
+ iconForwards,
25
+ iconMore,
26
+ iconRefresh,
27
+ } from "../icons";
28
+ import { settingsService } from "..";
29
+
30
+ function ThemePreview(this: FC<{ theme: (typeof THEMES)[number] }>) {
31
+ const theme = this.theme;
32
+
33
+ return (
34
+ <div
35
+ aria-hidden="true"
36
+ style={`--preview-frame: ${theme.tokens.frame}; --preview-toolbar: ${theme.tokens.toolbar}; --preview-toolbar-text: ${theme.tokens.toolbar_text}; --preview-tab-text: ${theme.tokens.tab_background_text}; --preview-field: ${theme.tokens.toolbar_field}; --preview-field-text: ${theme.tokens.toolbar_field_text}; --preview-accent: ${theme.tokens.tab_line}; --preview-icons: ${theme.tokens.icons}; --preview-border: ${theme.tokens.popup_border}; --preview-separator: ${theme.tokens.toolbar_top_separator};`}
37
+ >
38
+ <div class="preview-window">
39
+ <div class="preview-tabstrip">
40
+ <div class="preview-tab active">
41
+ <span class="preview-site">
42
+ <span class="preview-favicon"></span>
43
+ <span class="preview-tab-title"></span>
44
+ </span>
45
+ <Icon class="preview-close" icon={iconClose} />
46
+ </div>
47
+ <div class="preview-tab">
48
+ <span class="preview-site">
49
+ <span class="preview-favicon"></span>
50
+ <span class="preview-tab-title short"></span>
51
+ </span>
52
+ <Icon class="preview-close" icon={iconClose} />
53
+ </div>
54
+ <Icon class="preview-add" icon={iconAdd} />
55
+ </div>
56
+ <div class="preview-toolbar">
57
+ <div class="preview-nav-controls">
58
+ <Icon class="preview-control" icon={iconBack} />
59
+ <Icon class="preview-control disabled" icon={iconForwards} />
60
+ <Icon class="preview-control" icon={iconRefresh} />
61
+ </div>
62
+ <div class="preview-field">
63
+ <Icon class="preview-site-indicator" icon={iconOptions} />
64
+ <span class="preview-address"></span>
65
+ </div>
66
+ <Icon class="preview-menu" icon={iconMore} />
67
+ </div>
68
+ </div>
69
+ </div>
70
+ );
71
+ }
72
+
73
+ ThemePreview.style = css`
74
+ :scope {
75
+ height: 4rem;
76
+ }
77
+
78
+ .preview-window {
79
+ height: 100%;
80
+ overflow: hidden;
81
+ }
82
+
83
+ .preview-tabstrip {
84
+ height: 2.25rem;
85
+ padding-inline: 0.2rem;
86
+ background: var(--preview-frame);
87
+ color: var(--preview-tab-text);
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 0.2rem;
91
+ }
92
+
93
+ .preview-tab {
94
+ width: min(34%, 10rem);
95
+ min-width: 4.5rem;
96
+ height: 1.75rem;
97
+ padding: 0 0.45rem;
98
+ border-radius: 0.25rem;
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: space-between;
102
+ opacity: 0.68;
103
+ }
104
+
105
+ .preview-tab.active {
106
+ background: var(--preview-toolbar);
107
+ color: var(--preview-toolbar-text);
108
+ opacity: 1;
109
+ outline: 1px solid var(--preview-border);
110
+ outline-offset: -1px;
111
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
112
+ }
113
+
114
+ .preview-favicon {
115
+ width: 0.63rem;
116
+ height: 0.63rem;
117
+ border-radius: 50%;
118
+ background: var(--preview-accent);
119
+ flex: none;
120
+ }
121
+
122
+ .preview-tab-title {
123
+ width: 58%;
124
+ height: 2px;
125
+ border-radius: 1px;
126
+ background: currentColor;
127
+ opacity: 0.42;
128
+ }
129
+
130
+ .preview-tab-title.short {
131
+ width: 42%;
132
+ }
133
+
134
+ .preview-site {
135
+ display: flex;
136
+ gap: 0.35rem;
137
+ flex-grow: 1;
138
+ align-items: center;
139
+ }
140
+
141
+ .preview-close {
142
+ width: 0.45rem;
143
+ height: 0.45rem;
144
+ flex: none;
145
+ opacity: 0.65;
146
+ }
147
+
148
+ .preview-add {
149
+ width: 0.7rem;
150
+ height: 0.7rem;
151
+ margin: 0 0 0.2rem 0.1rem;
152
+ align-self: center;
153
+ opacity: 0.75;
154
+ flex: none;
155
+ }
156
+
157
+ .preview-toolbar {
158
+ height: 2rem;
159
+ padding: 0.25rem 0.4rem;
160
+ background: var(--preview-toolbar);
161
+ border-bottom: 1px solid var(--preview-separator);
162
+ display: flex;
163
+ align-items: center;
164
+ gap: 0.35rem;
165
+ color: var(--preview-icons);
166
+ }
167
+
168
+ .preview-nav-controls {
169
+ display: flex;
170
+ align-items: center;
171
+ gap: 0.25rem;
172
+ color: var(--preview-icons);
173
+ font-size: 0.9rem;
174
+ }
175
+
176
+ .preview-control {
177
+ width: 0.8rem;
178
+ height: 0.8rem;
179
+ flex: none;
180
+ }
181
+
182
+ .preview-control.disabled {
183
+ opacity: 0.38;
184
+ }
185
+
186
+ .preview-field {
187
+ height: 1.35rem;
188
+ min-width: 0;
189
+ flex: 1;
190
+ border-radius: 4px;
191
+ background: var(--preview-field);
192
+ color: var(--preview-field-text);
193
+ display: flex;
194
+ align-items: center;
195
+ gap: 0.35rem;
196
+ padding: 0 0.5rem;
197
+ font-size: 0.8rem;
198
+ }
199
+
200
+ .preview-site-indicator {
201
+ width: 0.5rem;
202
+ height: 0.5rem;
203
+ color: var(--preview-accent);
204
+ flex: none;
205
+ }
206
+
207
+ .preview-address {
208
+ width: 26%;
209
+ height: 2px;
210
+ border-radius: 1px;
211
+ background: currentColor;
212
+ opacity: 0.3;
213
+ }
214
+
215
+ .preview-menu {
216
+ width: 0.8rem;
217
+ height: 0.8rem;
218
+ opacity: 0.8;
219
+ flex: none;
220
+ }
221
+ `;
222
+
223
+ type SidebarLocation = "left" | "right";
224
+
225
+ const LAYOUT_OPTIONS: readonly {
226
+ id: TabLayoutMode;
227
+ name: string;
228
+ description: string;
229
+ }[] = [
230
+ {
231
+ id: "horizontal",
232
+ name: "Default",
233
+ description: "Tabs in a single row above the address bar.",
234
+ },
235
+ {
236
+ id: "bottom",
237
+ name: "Bottom",
238
+ description: "Tabs along the bottom edge of the window.",
239
+ },
240
+ {
241
+ id: "compact",
242
+ name: "Compact",
243
+ description: "Tabs beside the address bar in one compact row.",
244
+ },
245
+ {
246
+ id: "hybrid",
247
+ name: "Hybrid",
248
+ description: "Vertical tabs beside a horizontal address bar.",
249
+ },
250
+ {
251
+ id: "vertical",
252
+ name: "Vertical",
253
+ description: "Tabs and address controls together in a sidebar.",
254
+ },
255
+ ];
256
+
257
+ function LayoutPreview(
258
+ this: FC<{ layout: TabLayoutMode; sidebar?: SidebarLocation }>
259
+ ) {
260
+ const sidebar = this.sidebar ?? "left";
261
+
262
+ return (
263
+ <div
264
+ aria-hidden="true"
265
+ class={`layout-preview layout-${this.layout} sidebar-${sidebar}`}
266
+ >
267
+ <div class="layout-tab-region">
268
+ <div class="layout-vertical-field">
269
+ <span class="layout-field-dot"></span>
270
+ <span class="layout-field-line"></span>
271
+ </div>
272
+ <div class="layout-tabs">
273
+ <span class="layout-tab active">
274
+ <span class="layout-favicon"></span>
275
+ <span class="layout-tab-line"></span>
276
+ </span>
277
+ <span class="layout-tab">
278
+ <span class="layout-favicon secondary"></span>
279
+ <span class="layout-tab-line short"></span>
280
+ </span>
281
+ <span class="layout-tab third">
282
+ <span class="layout-favicon tertiary"></span>
283
+ <span class="layout-tab-line"></span>
284
+ </span>
285
+ </div>
286
+ </div>
287
+
288
+ <div class="layout-toolbar">
289
+ <div class="layout-field">
290
+ <span class="layout-field-dot"></span>
291
+ <span class="layout-field-line"></span>
292
+ </div>
293
+ <div class="layout-inline-tabs">
294
+ <span class="layout-inline-tab active">
295
+ <span class="layout-favicon"></span>
296
+ <span class="layout-tab-line"></span>
297
+ </span>
298
+ <span class="layout-inline-tab">
299
+ <span class="layout-favicon secondary"></span>
300
+ <span class="layout-tab-line short"></span>
301
+ </span>
302
+ </div>
303
+ <span class="layout-menu-dots">
304
+ <span></span>
305
+ <span></span>
306
+ <span></span>
307
+ </span>
308
+ </div>
309
+
310
+ <div class="layout-content">
311
+ <div class="layout-page">
312
+ <span class="layout-page-heading"></span>
313
+ <div class="layout-page-body">
314
+ <span class="layout-page-image"></span>
315
+ <div class="layout-page-copy">
316
+ <span></span>
317
+ <span></span>
318
+ <span class="short"></span>
319
+ <span class="shorter"></span>
320
+ </div>
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ );
326
+ }
327
+
328
+ LayoutPreview.style = css`
329
+ :scope {
330
+ display: grid;
331
+ height: 7.25rem;
332
+ }
333
+
334
+ .layout-preview {
335
+ height: 100%;
336
+ overflow: hidden;
337
+ background: var(--ntp_background);
338
+ color: var(--toolbar_text);
339
+ }
340
+
341
+ .layout-horizontal {
342
+ grid-template:
343
+ "tabs" 1.6rem
344
+ "toolbar" 1.45rem
345
+ "content" 1fr / 1fr;
346
+ }
347
+
348
+ .layout-bottom {
349
+ grid-template:
350
+ "toolbar" 1.45rem
351
+ "content" 1fr
352
+ "tabs" 1.6rem / 1fr;
353
+ }
354
+
355
+ .layout-compact {
356
+ grid-template:
357
+ "toolbar" 1.7rem
358
+ "content" 1fr / 1fr;
359
+ }
360
+
361
+ .layout-hybrid {
362
+ grid-template:
363
+ "tabs toolbar" 1.45rem
364
+ "tabs content" 1fr / 29% 1fr;
365
+ }
366
+
367
+ .layout-hybrid.sidebar-right {
368
+ grid-template:
369
+ "toolbar tabs" 1.45rem
370
+ "content tabs" 1fr / 1fr 29%;
371
+ }
372
+
373
+ .layout-vertical {
374
+ grid-template: "tabs content" 1fr / 39% 1fr;
375
+ }
376
+
377
+ .layout-vertical.sidebar-right {
378
+ grid-template: "content tabs" 1fr / 1fr 39%;
379
+ }
380
+
381
+ .layout-tab-region {
382
+ grid-area: tabs;
383
+ min-width: 0;
384
+ min-height: 0;
385
+ padding: 0.2rem 0.25rem;
386
+ background: var(--frame);
387
+ display: flex;
388
+ align-items: center;
389
+ gap: 0.2rem;
390
+ position: relative;
391
+ z-index: 1;
392
+ }
393
+
394
+ .layout-horizontal .layout-tab-region {
395
+ border-bottom: 1px solid var(--text-15);
396
+ }
397
+
398
+ .layout-bottom .layout-tab-region {
399
+ border-top: 1px solid var(--popup_border);
400
+ }
401
+
402
+ .layout-tabs {
403
+ min-width: 0;
404
+ flex: 1;
405
+ display: flex;
406
+ align-items: center;
407
+ gap: 0.18rem;
408
+ }
409
+
410
+ .layout-tab,
411
+ .layout-inline-tab {
412
+ min-width: 0;
413
+ display: flex;
414
+ align-items: center;
415
+ gap: 0.2rem;
416
+ color: var(--tab_background_text);
417
+ opacity: 0.65;
418
+ }
419
+
420
+ .layout-tab {
421
+ height: 1.1rem;
422
+ width: 31%;
423
+ padding-inline: 0.25rem;
424
+ border-radius: 0.2rem;
425
+ }
426
+
427
+ .layout-tab.active,
428
+ .layout-inline-tab.active {
429
+ background: var(--toolbar);
430
+ color: var(--toolbar_text);
431
+ opacity: 1;
432
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
433
+ }
434
+
435
+ .layout-favicon {
436
+ width: 0.32rem;
437
+ height: 0.32rem;
438
+ border-radius: 50%;
439
+ background: var(--tab_line);
440
+ flex: none;
441
+ }
442
+
443
+ .layout-favicon.secondary {
444
+ background: var(--tab_loading);
445
+ opacity: 0.75;
446
+ }
447
+
448
+ .layout-favicon.tertiary {
449
+ background: var(--icons);
450
+ opacity: 0.55;
451
+ }
452
+
453
+ .layout-tab-line {
454
+ width: 62%;
455
+ height: 2px;
456
+ border-radius: 1px;
457
+ background: currentColor;
458
+ opacity: 0.38;
459
+ }
460
+
461
+ .layout-tab-line.short {
462
+ width: 42%;
463
+ }
464
+
465
+ .layout-toolbar {
466
+ grid-area: toolbar;
467
+ min-width: 0;
468
+ padding: 0.2rem 0.3rem;
469
+ background: var(--toolbar);
470
+ display: flex;
471
+ align-items: center;
472
+ gap: 0.25rem;
473
+ position: relative;
474
+ z-index: 1;
475
+ }
476
+
477
+ .layout-menu-dots {
478
+ display: flex;
479
+ align-items: center;
480
+ gap: 0.09rem;
481
+ flex: none;
482
+ }
483
+
484
+ .layout-menu-dots span {
485
+ width: 0.13rem;
486
+ height: 0.13rem;
487
+ border-radius: 50%;
488
+ background: currentColor;
489
+ opacity: 0.5;
490
+ }
491
+
492
+ .layout-field,
493
+ .layout-vertical-field {
494
+ min-width: 0;
495
+ background: var(--toolbar_field);
496
+ color: var(--toolbar_field_text);
497
+ display: flex;
498
+ align-items: center;
499
+ gap: 0.2rem;
500
+ border-radius: 0.2rem;
501
+ box-shadow: inset 0 0 0 1px var(--text-10);
502
+ }
503
+
504
+ .layout-field {
505
+ height: 0.85rem;
506
+ padding-inline: 0.3rem;
507
+ flex: 1;
508
+ }
509
+
510
+ .layout-field-dot {
511
+ width: 0.28rem;
512
+ height: 0.28rem;
513
+ border-radius: 50%;
514
+ background: var(--tab_line);
515
+ flex: none;
516
+ }
517
+
518
+ .layout-field-line {
519
+ width: 38%;
520
+ height: 0.16rem;
521
+ border-radius: 999px;
522
+ background: currentColor;
523
+ opacity: 0.22;
524
+ }
525
+
526
+ .layout-inline-tabs,
527
+ .layout-vertical-field {
528
+ display: none;
529
+ }
530
+
531
+ .layout-compact .layout-tab-region {
532
+ display: none;
533
+ }
534
+
535
+ .layout-compact .layout-field {
536
+ flex: 0 1 38%;
537
+ }
538
+
539
+ .layout-compact .layout-inline-tabs {
540
+ min-width: 0;
541
+ align-self: stretch;
542
+ flex: 1;
543
+ display: flex;
544
+ align-items: center;
545
+ gap: 0.15rem;
546
+ }
547
+
548
+ .layout-inline-tab {
549
+ width: 42%;
550
+ height: 1.1rem;
551
+ padding-inline: 0.25rem;
552
+ border-radius: 0.2rem;
553
+ }
554
+
555
+ .layout-hybrid .layout-tab-region,
556
+ .layout-vertical .layout-tab-region {
557
+ padding: 0.4rem 0.35rem;
558
+ flex-direction: column;
559
+ align-items: stretch;
560
+ gap: 0.25rem;
561
+ border-right: 1px solid var(--text-15);
562
+ }
563
+
564
+ .layout-hybrid.sidebar-right .layout-tab-region,
565
+ .layout-vertical.sidebar-right .layout-tab-region {
566
+ border-right: none;
567
+ border-left: 1px solid var(--text-15);
568
+ }
569
+
570
+ .layout-hybrid .layout-tabs,
571
+ .layout-vertical .layout-tabs {
572
+ flex: none;
573
+ width: 100%;
574
+ flex-direction: column;
575
+ align-items: stretch;
576
+ gap: 0.18rem;
577
+ }
578
+
579
+ .layout-hybrid .layout-tab,
580
+ .layout-vertical .layout-tab {
581
+ width: 100%;
582
+ height: 0.8rem;
583
+ padding-inline: 0.2rem;
584
+ }
585
+
586
+ .layout-hybrid .layout-tab.third,
587
+ .layout-vertical .layout-tab.third {
588
+ display: flex;
589
+ }
590
+
591
+ .layout-vertical .layout-vertical-field {
592
+ height: 0.85rem;
593
+ padding-inline: 0.25rem;
594
+ display: flex;
595
+ }
596
+
597
+ .layout-vertical .layout-toolbar {
598
+ display: none;
599
+ }
600
+
601
+ .layout-content {
602
+ grid-area: content;
603
+ min-width: 0;
604
+ min-height: 0;
605
+ background: var(--ntp_background);
606
+ color: var(--ntp_text);
607
+ display: flex;
608
+ align-items: flex-start;
609
+ justify-content: flex-start;
610
+ padding: 0.8rem 0.75rem;
611
+ }
612
+
613
+ .layout-page {
614
+ width: min(82%, 7rem);
615
+ display: flex;
616
+ flex-direction: column;
617
+ align-items: flex-start;
618
+ gap: 0.38rem;
619
+ }
620
+
621
+ .layout-page-body {
622
+ width: 100%;
623
+ display: flex;
624
+ align-items: flex-start;
625
+ gap: 0.4rem;
626
+ }
627
+
628
+ .layout-page-copy {
629
+ min-width: 0;
630
+ flex: 1;
631
+ display: flex;
632
+ flex-direction: column;
633
+ gap: 0.3rem;
634
+ }
635
+
636
+ .layout-page-copy span {
637
+ width: 82%;
638
+ height: 0.16rem;
639
+ border-radius: 999px;
640
+ background: currentColor;
641
+ opacity: 0.12;
642
+ }
643
+
644
+ .layout-page-heading {
645
+ width: 45%;
646
+ height: 0.25rem;
647
+ border-radius: 999px;
648
+ background: currentColor;
649
+ opacity: 0.25;
650
+ }
651
+
652
+ .layout-page-copy span.short {
653
+ width: 62%;
654
+ }
655
+
656
+ .layout-page-copy span.shorter {
657
+ width: 48%;
658
+ }
659
+
660
+ .layout-page-image {
661
+ width: 1.35rem;
662
+ aspect-ratio: 3 / 4;
663
+ border-radius: 0.22rem;
664
+ background: var(--ntp-text-10);
665
+ flex: none;
666
+ }
667
+ `;
668
+
669
+ export function SettingsPage(
670
+ this: FC<{ tab: Tab; selected: string }, { searchQuery: string }>
671
+ ) {
672
+ this.searchQuery = "";
673
+
674
+ const button = (id: string, icon: IconifyIcon, name: string) => {
675
+ return (
676
+ <div
677
+ class="nav-button"
678
+ class:active={use(this.selected).map((s) => s === id)}
679
+ on:click={() => {
680
+ this.selected = id;
681
+ // this.tab.url = new URL(`puter://settings/${id}`);
682
+ this.tab.history.push(new URL(`puter://settings/${id}`));
683
+ }}
684
+ >
685
+ <Icon icon={icon} />
686
+ <span>{name}</span>
687
+ </div>
688
+ );
689
+ };
690
+
691
+ use(this.selected).listen((s) => {
692
+ console.log("Selected settings category:", s);
693
+ });
694
+
695
+ return (
696
+ <div class="settings-page">
697
+ <div class="sidebar">
698
+ <h1>Settings</h1>
699
+ <nav class="navigation">
700
+ {button("general", iconSettings, "General")}
701
+ {button("appearance", iconBrush, "Appearance")}
702
+ {button("search", iconSearch, "Search")}
703
+ {button("privacy", iconPrivacy, "Privacy & Security")}
704
+ {/* {button("extensions", iconExtension, "Extensions")} */}
705
+ {button("about", iconAbout, "About")}
706
+ </nav>
707
+ </div>
708
+ <div class="content">
709
+ <div class="search-container">
710
+ <Input placeholder="Find in Settings" value={use(this.searchQuery)} />
711
+ </div>
712
+ <div class="settings-content">
713
+ <h1>
714
+ {use(this.selected).map(
715
+ (s) => s.charAt(0).toUpperCase() + s.slice(1)
716
+ )}
717
+ </h1>
718
+ {/* General Tab */}
719
+ {use(this.selected).map((selected) =>
720
+ selected === "general" ? (
721
+ <div class="settings-tab">
722
+ <section class="setting-section">
723
+ <div class="section-header">
724
+ <h2>Startup</h2>
725
+ </div>
726
+ <div class="section-content">
727
+ <div class="setting-group">
728
+ <h4>When Browser Starts</h4>
729
+ <div class="radio-group">
730
+ <div class="radio-option">
731
+ <input
732
+ type="radio"
733
+ id="startup-new-tab"
734
+ name="startupPage"
735
+ value="new-tab"
736
+ checked={use(
737
+ settingsService.settings.startupPage
738
+ ).map((v) => v === "new-tab")}
739
+ on:change={() => {
740
+ settingsService.settings.startupPage = "new-tab";
741
+ }}
742
+ />
743
+ <label for="startup-new-tab">Open New Tab Page</label>
744
+ </div>
745
+ <div class="radio-option">
746
+ <input
747
+ type="radio"
748
+ id="startup-continue"
749
+ name="startupPage"
750
+ value="continue"
751
+ checked={use(
752
+ settingsService.settings.startupPage
753
+ ).map((v) => v === "continue")}
754
+ on:change={() => {
755
+ settingsService.settings.startupPage = "continue";
756
+ }}
757
+ />
758
+ <label for="startup-continue">
759
+ Continue where you left off
760
+ </label>
761
+ </div>
762
+ </div>
763
+ </div>
764
+ </div>
765
+ </section>
766
+
767
+ <section class="setting-section">
768
+ <div class="section-header">
769
+ <h2>Bookmarks</h2>
770
+ </div>
771
+ <div class="section-content">
772
+ <div class="setting-group">
773
+ <div
774
+ class="checkbox-option"
775
+ class:disabled={use(
776
+ settingsService.settings.tabLayout
777
+ ).map((layout) => layout === "vertical")}
778
+ >
779
+ <Checkbox
780
+ value={use(settingsService.settings.showBookmarksBar)}
781
+ id="show-bookmarks-bar"
782
+ disabled={use(settingsService.settings.tabLayout).map(
783
+ (layout) => layout === "vertical"
784
+ )}
785
+ />
786
+ {use(settingsService.settings.tabLayout)
787
+ .map((layout) => layout === "vertical")
788
+ .and(
789
+ <label
790
+ for="show-bookmarks-bar"
791
+ class="label-multiline"
792
+ >
793
+ <span>Always show bookmarks bar</span>
794
+ <span class="description">
795
+ Bookmarks are always shown in vertical mode.
796
+ </span>
797
+ </label>
798
+ )
799
+ .or(
800
+ <label for="show-bookmarks-bar">
801
+ Show bookmarks bar
802
+ </label>
803
+ )}
804
+ </div>
805
+ </div>
806
+ </div>
807
+ </section>
808
+ </div>
809
+ ) : null
810
+ )}
811
+
812
+ {/* Appearance Tab */}
813
+ {use(this.selected).map((selected) =>
814
+ selected === "appearance" ? (
815
+ <div class="settings-tab">
816
+ {/* <section class="setting-section">
817
+ <div class="section-header">
818
+ <h2>Page Appearance</h2>
819
+ <p class="description">
820
+ Control the appearance of websites you visit.
821
+ </p>
822
+ </div>
823
+ <div class="section-content">
824
+ <div class="setting-group">
825
+ <div class="radio-group">
826
+ <div class="radio-option">
827
+ <input
828
+ type="radio"
829
+ id="appearance-system"
830
+ name="appearance"
831
+ value="system"
832
+ checked={
833
+ settingsService.settings.appearance === "system"
834
+ }
835
+ on:change={() => {
836
+ settingsService.settings.appearance = "system";
837
+ }}
838
+ />
839
+ <label for="appearance-system">System Default</label>
840
+ </div>
841
+ <div class="radio-option">
842
+ <input
843
+ type="radio"
844
+ id="appearance-dark"
845
+ name="appearance"
846
+ value="dark"
847
+ checked={
848
+ settingsService.settings.appearance === "dark"
849
+ }
850
+ on:change={() => {
851
+ settingsService.settings.appearance = "dark";
852
+ }}
853
+ />
854
+ <label for="appearance-dark">Dark</label>
855
+ </div>
856
+ <div class="radio-option">
857
+ <input
858
+ type="radio"
859
+ id="appearance-light"
860
+ name="appearance"
861
+ value="light"
862
+ checked={
863
+ settingsService.settings.appearance === "light"
864
+ }
865
+ on:change={() => {
866
+ settingsService.settings.appearance = "light";
867
+ }}
868
+ />
869
+ <label for="appearance-light">Light</label>
870
+ </div>
871
+ </div>
872
+ </div>
873
+ </div>
874
+ </section> */}
875
+ <section class="setting-section">
876
+ <div class="section-header">
877
+ <h2>Browser Layout (Beta)</h2>
878
+ <p class="description">Choose where tabs are displayed.</p>
879
+ </div>
880
+ <div class="section-content">
881
+ <div class="setting-group">
882
+ {use(settingsService.settings.verticalTabJustify).map(
883
+ (sidebar) => (
884
+ <div class="layout-grid">
885
+ {LAYOUT_OPTIONS.map((option) => (
886
+ <label
887
+ for={`layout-${option.id}`}
888
+ class="layout-card"
889
+ class:selected={use(
890
+ settingsService.settings.tabLayout
891
+ ).map((value) => value === option.id)}
892
+ >
893
+ <input
894
+ class="layout-radio"
895
+ type="radio"
896
+ id={`layout-${option.id}`}
897
+ name="layout"
898
+ value={option.id}
899
+ checked={use(
900
+ settingsService.settings.tabLayout
901
+ ).map((value) => value === option.id)}
902
+ on:change={() => {
903
+ settingsService.settings.tabLayout =
904
+ option.id;
905
+ }}
906
+ />
907
+ <LayoutPreview
908
+ layout={option.id}
909
+ sidebar={sidebar}
910
+ />
911
+ <span class="layout-info">
912
+ <span class="layout-name">{option.name}</span>
913
+ <span class="description">
914
+ {option.description}
915
+ </span>
916
+ </span>
917
+ </label>
918
+ ))}
919
+ </div>
920
+ )
921
+ )}
922
+ </div>
923
+ </div>
924
+ </section>
925
+ {use(settingsService.settings.tabLayout)
926
+ .map((l) => l === "hybrid" || l === "vertical")
927
+ .and(
928
+ <section class="setting-section">
929
+ <div class="section-header">
930
+ <h2>Sidebar Location</h2>
931
+ <p class="description">
932
+ Choose which side of the screen the sidebar is on.
933
+ </p>
934
+ </div>
935
+ <div class="section-content">
936
+ <div class="setting-group">
937
+ {use(settingsService.settings.tabLayout).map(
938
+ (layout) => (
939
+ <div class="layout-grid sidebar-location-grid">
940
+ {(["left", "right"] as const).map((sidebar) => (
941
+ <label
942
+ for={`sidebar-${sidebar}`}
943
+ class="layout-card"
944
+ class:selected={use(
945
+ settingsService.settings
946
+ .verticalTabJustify
947
+ ).map((value) => value === sidebar)}
948
+ >
949
+ <input
950
+ class="layout-radio"
951
+ type="radio"
952
+ id={`sidebar-${sidebar}`}
953
+ name="sidebar-location"
954
+ value={sidebar}
955
+ checked={use(
956
+ settingsService.settings
957
+ .verticalTabJustify
958
+ ).map((value) => value === sidebar)}
959
+ on:change={() => {
960
+ settingsService.settings.verticalTabJustify =
961
+ sidebar;
962
+ }}
963
+ />
964
+ <LayoutPreview
965
+ layout={
966
+ layout === "vertical"
967
+ ? "vertical"
968
+ : "hybrid"
969
+ }
970
+ sidebar={sidebar}
971
+ />
972
+ <span class="layout-info compact">
973
+ <span class="layout-name">
974
+ {sidebar === "left" ? "Left" : "Right"}
975
+ </span>
976
+ </span>
977
+ </label>
978
+ ))}
979
+ </div>
980
+ )
981
+ )}
982
+ </div>
983
+ </div>
984
+ </section>
985
+ )}
986
+ <section class="setting-section">
987
+ <div class="section-header">
988
+ <h2>UI Density</h2>
989
+ <p class="description">
990
+ Adjust the spacing and sizing of UI elements.
991
+ </p>
992
+ </div>
993
+ <div class="section-content">
994
+ <div class="setting-group">
995
+ <div class="radio-group">
996
+ <div class="radio-option">
997
+ <input
998
+ type="radio"
999
+ id="ui-dense"
1000
+ name="ui-dense"
1001
+ value="compact"
1002
+ checked={
1003
+ settingsService.settings.uiProfile === "compact"
1004
+ }
1005
+ on:change={() => {
1006
+ settingsService.settings.uiProfile = "compact";
1007
+ }}
1008
+ />
1009
+ <label for="ui-dense" class="label-multiline">
1010
+ <span>Compact</span>
1011
+ <span class="description">
1012
+ Reduced spacing for smaller screens.
1013
+ </span>
1014
+ </label>
1015
+ </div>
1016
+ <div class="radio-option">
1017
+ <input
1018
+ type="radio"
1019
+ id="ui-default"
1020
+ name="ui-dense"
1021
+ value="default"
1022
+ checked={
1023
+ settingsService.settings.uiProfile === "default"
1024
+ }
1025
+ on:change={() => {
1026
+ settingsService.settings.uiProfile = "default";
1027
+ }}
1028
+ />
1029
+ <label for="ui-default" class="label-multiline">
1030
+ <span>Comfortable</span>
1031
+ <span class="description">
1032
+ Balanced spacing for most screens.
1033
+ </span>
1034
+ </label>
1035
+ </div>
1036
+ <div class="radio-option">
1037
+ <input
1038
+ type="radio"
1039
+ id="ui-sparse"
1040
+ name="ui-dense"
1041
+ value="touch"
1042
+ checked={
1043
+ settingsService.settings.uiProfile === "touch"
1044
+ }
1045
+ on:change={() => {
1046
+ settingsService.settings.uiProfile = "touch";
1047
+ }}
1048
+ />
1049
+ <label for="ui-sparse" class="label-multiline">
1050
+ <span>Cozy</span>
1051
+ <span class="description">
1052
+ More sparse layout optimized for touchscreens.
1053
+ </span>
1054
+ </label>
1055
+ </div>
1056
+ </div>
1057
+ </div>
1058
+ </div>
1059
+ </section>
1060
+ <section class="setting-section">
1061
+ <div class="section-header">
1062
+ <h2>Browser Theme</h2>
1063
+ <p class="description">
1064
+ Customize the look of the browser.
1065
+ </p>
1066
+ </div>
1067
+ <div class="section-content" style="padding-left: 0;">
1068
+ <div class="setting-group">
1069
+ <h4>Dark</h4>
1070
+ <div class="theme-grid">
1071
+ {THEMES.filter(
1072
+ (theme) => theme.appearance === "dark"
1073
+ ).map((theme) => (
1074
+ <div
1075
+ class="theme-card"
1076
+ class:selected={use(
1077
+ settingsService.settings.themeId
1078
+ ).map((id) => id === theme.id)}
1079
+ on:click={() => {
1080
+ settingsService.settings.themeId = theme.id;
1081
+ }}
1082
+ >
1083
+ <ThemePreview theme={theme} />
1084
+ <div class="theme-info">
1085
+ <h5>{theme.name}</h5>
1086
+ <p>{theme.description}</p>
1087
+ </div>
1088
+ </div>
1089
+ ))}
1090
+ </div>
1091
+ <br />
1092
+ <h4>Light</h4>
1093
+ <div class="theme-grid">
1094
+ {THEMES.filter(
1095
+ (theme) => theme.appearance === "light"
1096
+ ).map((theme) => (
1097
+ <div
1098
+ class="theme-card"
1099
+ class:selected={use(
1100
+ settingsService.settings.themeId
1101
+ ).map((id) => id === theme.id)}
1102
+ on:click={() => {
1103
+ settingsService.settings.themeId = theme.id;
1104
+ }}
1105
+ >
1106
+ <ThemePreview theme={theme} />
1107
+ <div class="theme-info">
1108
+ <h5>{theme.name}</h5>
1109
+ <p>{theme.description}</p>
1110
+ </div>
1111
+ </div>
1112
+ ))}
1113
+ </div>
1114
+ </div>
1115
+ </div>
1116
+ </section>
1117
+ </div>
1118
+ ) : null
1119
+ )}
1120
+
1121
+ {/* Search Tab */}
1122
+ {use(this.selected).map((selected) =>
1123
+ selected === "search" ? (
1124
+ <div class="settings-tab">
1125
+ <section class="setting-section">
1126
+ <div class="section-header">
1127
+ <h3>Default Search Engine</h3>
1128
+ <p class="description">
1129
+ Choose which search engine to use when searching from the
1130
+ address bar
1131
+ </p>
1132
+ </div>
1133
+ <div class="section-content">
1134
+ <div class="setting-group">
1135
+ <select
1136
+ class="select-input"
1137
+ value={use(
1138
+ settingsService.settings.defaultSearchEngine
1139
+ )}
1140
+ >
1141
+ {Object.keys(AVAILABLE_SEARCH_ENGINES).map((key) => (
1142
+ <option value={key}>
1143
+ {
1144
+ AVAILABLE_SEARCH_ENGINES[
1145
+ key as keyof typeof AVAILABLE_SEARCH_ENGINES
1146
+ ].name
1147
+ }
1148
+ </option>
1149
+ ))}
1150
+ </select>
1151
+ </div>
1152
+ </div>
1153
+ </section>
1154
+
1155
+ <section class="setting-section">
1156
+ <div class="section-header">
1157
+ <h2>Search Suggestions</h2>
1158
+ </div>
1159
+ <div class="section-content">
1160
+ <div class="setting-group">
1161
+ <div class="checkbox-option">
1162
+ <Checkbox
1163
+ id="search-suggestions"
1164
+ value={use(
1165
+ settingsService.settings.searchSuggestionsEnabled
1166
+ )}
1167
+ />
1168
+ <label for="search-suggestions">
1169
+ Show search and site suggestions in the address bar
1170
+ </label>
1171
+ </div>
1172
+ </div>
1173
+ </div>
1174
+ </section>
1175
+ </div>
1176
+ ) : null
1177
+ )}
1178
+
1179
+ {/* Privacy Tab */}
1180
+ {use(this.selected).map((selected) =>
1181
+ selected === "privacy" ? (
1182
+ <div class="settings-tab">
1183
+ <section class="setting-section">
1184
+ <div class="section-header">
1185
+ <h2>Trackers & Site Data</h2>
1186
+ <p class="description">
1187
+ Control how the browser handles ads, trackers, and your
1188
+ data
1189
+ </p>
1190
+ </div>
1191
+ <div class="section-content">
1192
+ <div class="setting-group">
1193
+ <div class="checkbox-option">
1194
+ <Checkbox
1195
+ id="block-trackers"
1196
+ value={use(settingsService.settings.blockTrackers)}
1197
+ />
1198
+ <label for="block-trackers">
1199
+ Block ads and trackers
1200
+ </label>
1201
+ </div>
1202
+
1203
+ <div class="checkbox-option">
1204
+ <Checkbox
1205
+ id="do-not-track"
1206
+ value={use(settingsService.settings.doNotTrack)}
1207
+ />
1208
+ <label for="do-not-track">
1209
+ Send 'Do Not Track' with browsing requests
1210
+ </label>
1211
+ </div>
1212
+ </div>
1213
+ </div>
1214
+ </section>
1215
+ <section class="setting-section">
1216
+ <div class="section-header">
1217
+ <h2>Browsing History</h2>
1218
+ <p class="description">
1219
+ Control what data is saved or cleared
1220
+ </p>
1221
+ </div>
1222
+ <div class="section-content">
1223
+ <div class="setting-group">
1224
+ <div class="checkbox-option">
1225
+ <Checkbox
1226
+ id="clear-history"
1227
+ value={use(
1228
+ settingsService.settings.clearHistoryOnExit
1229
+ )}
1230
+ />
1231
+ <label for="clear-history">
1232
+ Clear history when browser closes
1233
+ </label>
1234
+ </div>
1235
+ <br />
1236
+ <Button variant="primary">Clear Browsing Data...</Button>
1237
+ </div>
1238
+ </div>
1239
+ </section>
1240
+ </div>
1241
+ ) : null
1242
+ )}
1243
+
1244
+ {/* Extensions Tab */}
1245
+ {use(this.selected).map((selected) =>
1246
+ selected === "extensions" ? (
1247
+ <div class="settings-tab">
1248
+ <section class="setting-section">
1249
+ <div class="section-header">
1250
+ <h3>Installed Extensions</h3>
1251
+ <p class="description">Manage your browser extensions</p>
1252
+ </div>
1253
+ <div class="section-content">
1254
+ <div class="extensions-list">
1255
+ <div class="extension-item">
1256
+ <div class="extension-info">
1257
+ <div class="extension-icon">
1258
+ <span class="icon-inner">
1259
+ <Icon icon={iconExtension} />
1260
+ </span>
1261
+ </div>
1262
+ <div class="extension-details">
1263
+ <h4>No extensions installed</h4>
1264
+ <p>Extensions will appear here once installed</p>
1265
+ </div>
1266
+ </div>
1267
+ </div>
1268
+ </div>
1269
+ </div>
1270
+ </section>
1271
+
1272
+ <section class="setting-section">
1273
+ <div class="section-header">
1274
+ <h2>Developer Mode</h2>
1275
+ </div>
1276
+ <div class="section-content">
1277
+ <div class="setting-group">
1278
+ <div class="checkbox-option">
1279
+ <Checkbox
1280
+ id="dev-mode"
1281
+ value={use(
1282
+ settingsService.settings.extensionsDevMode
1283
+ )}
1284
+ />
1285
+ <label for="dev-mode">Enable developer mode</label>
1286
+ </div>
1287
+
1288
+ {use(settingsService.settings.extensionsDevMode).map(
1289
+ (enabled) =>
1290
+ enabled && (
1291
+ <div class="dev-buttons">
1292
+ <Button variant="primary">Load Unpacked</Button>
1293
+ <Button variant="secondary">
1294
+ Pack Extension
1295
+ </Button>
1296
+ </div>
1297
+ )
1298
+ )}
1299
+ </div>
1300
+ </div>
1301
+ </section>
1302
+ </div>
1303
+ ) : null
1304
+ )}
1305
+
1306
+ {/* About Tab */}
1307
+ {use(this.selected).map((selected) =>
1308
+ selected === "about" ? (
1309
+ <div class="settings-tab">
1310
+ <section class="setting-section">
1311
+ <div class="section-header"></div>
1312
+ <div class="section-content">
1313
+ <div class="about-info">
1314
+ <img
1315
+ class="browser-logo"
1316
+ src={`${import.meta.env.BASE_URL}roxxie-icon.svg`}
1317
+ alt="Roxxie Proxy U logo"
1318
+ />
1319
+ <div class="browser-info">
1320
+ <h3>Roxxie Proxy U</h3>
1321
+ <p>
1322
+ Scramjet Version: {versionInfo.version} (
1323
+ {versionInfo.build})
1324
+ </p>
1325
+ <p>© {__COPYRIGHT_YEAR__} Puter Technologies</p>
1326
+ </div>
1327
+ </div>
1328
+ </div>
1329
+ </section>
1330
+
1331
+ <section class="setting-section">
1332
+ <div class="section-header">
1333
+ <h3>Open Source</h3>
1334
+ </div>
1335
+ <div class="section-content">
1336
+ <p>
1337
+ Roxxie Proxy U is open source software built from Browser.js
1338
+ and Adrift.
1339
+ </p>
1340
+ <a
1341
+ href="https://github.com/HeyPuter/browser.js"
1342
+ class="link"
1343
+ >
1344
+ Browser.js upstream
1345
+ </a>
1346
+ </div>
1347
+ </section>
1348
+ </div>
1349
+ ) : null
1350
+ )}
1351
+ </div>
1352
+ </div>
1353
+ </div>
1354
+ );
1355
+ }
1356
+
1357
+ SettingsPage.style = css`
1358
+ :scope {
1359
+ width: 100%;
1360
+ height: 100%;
1361
+ display: flex;
1362
+ font-family:
1363
+ system-ui,
1364
+ -apple-system,
1365
+ BlinkMacSystemFont,
1366
+ "Segoe UI",
1367
+ Roboto,
1368
+ Oxygen,
1369
+ Ubuntu,
1370
+ Cantarell,
1371
+ "Open Sans",
1372
+ "Helvetica Neue",
1373
+ sans-serif;
1374
+ background: var(--ntp_background);
1375
+ color: var(--ntp_text);
1376
+ overflow: hidden;
1377
+ }
1378
+
1379
+ h1,
1380
+ h2,
1381
+ h3,
1382
+ h4,
1383
+ p {
1384
+ margin: 0;
1385
+ padding: 0;
1386
+ }
1387
+
1388
+ h1 {
1389
+ font-size: 1.5rem;
1390
+ font-weight: 700;
1391
+ margin-bottom: 2rem;
1392
+ }
1393
+
1394
+ .settings-content h1 {
1395
+ margin-bottom: 2.75rem;
1396
+ }
1397
+
1398
+ h2 {
1399
+ font-size: 1.2rem;
1400
+ font-weight: 700;
1401
+ margin-bottom: 0.5rem;
1402
+ color: var(--ntp_text);
1403
+ }
1404
+
1405
+ h3 {
1406
+ font-size: 1.08rem;
1407
+ font-weight: 600;
1408
+ color: var(--ntp_text);
1409
+ margin-bottom: 0.8rem;
1410
+ }
1411
+
1412
+ h4 {
1413
+ font-size: 0.925rem;
1414
+ font-weight: 550;
1415
+ color: var(--ntp_text);
1416
+ margin-bottom: 0.7rem;
1417
+ }
1418
+
1419
+ h5 {
1420
+ font-size: 0.87rem;
1421
+ font-weight: 500;
1422
+ color: var(--ntp_text);
1423
+ margin-bottom: 0.5rem;
1424
+ }
1425
+
1426
+ p {
1427
+ color: var(--ntp-text-70);
1428
+ font-size: 0.9rem;
1429
+ line-height: 1.5;
1430
+ }
1431
+
1432
+ .sidebar {
1433
+ width: max(20rem, 250px);
1434
+ padding: var(--space-xxl);
1435
+ background: var(--toolbar);
1436
+ border-right: 1px solid var(--text-15);
1437
+ display: flex;
1438
+ flex-direction: column;
1439
+ overflow-y: auto;
1440
+ }
1441
+
1442
+ .navigation {
1443
+ display: flex;
1444
+ flex-direction: column;
1445
+ gap: 0.25rem;
1446
+ }
1447
+
1448
+ .nav-button {
1449
+ display: flex;
1450
+ align-items: center;
1451
+ gap: var(--space-lg);
1452
+ padding: var(--space-lg) var(--space-xl);
1453
+ border-radius: var(--radius-md);
1454
+ cursor: pointer;
1455
+ transition:
1456
+ background-color 0.05s ease-out,
1457
+ color 0.05s ease-out,
1458
+ font-weight 0.1s ease-out;
1459
+ font-size: 0.95rem;
1460
+ color: var(--toolbar_text);
1461
+ }
1462
+
1463
+ .nav-button:hover {
1464
+ background: var(--text-10);
1465
+ }
1466
+
1467
+ .nav-button.active {
1468
+ background: var(--accent-10);
1469
+ color: var(--tab_line);
1470
+ font-weight: 600;
1471
+ }
1472
+
1473
+ .content {
1474
+ flex: 1;
1475
+ display: flex;
1476
+ flex-direction: column;
1477
+ overflow: hidden;
1478
+ }
1479
+
1480
+ input {
1481
+ font-family: inherit;
1482
+ }
1483
+
1484
+ .search-container {
1485
+ position: absolute;
1486
+ top: 0;
1487
+ right: 0;
1488
+ width: 24rem;
1489
+ z-index: 5;
1490
+ padding: 1.5rem;
1491
+ }
1492
+
1493
+ .search-input input {
1494
+ width: 100%;
1495
+ height: 2.5rem;
1496
+ padding: 0 2.5rem;
1497
+ border-radius: 6px;
1498
+ border: 1px solid var(--ntp-text-20);
1499
+ background: var(--toolbar_field);
1500
+ color: var(--toolbar_field_text);
1501
+ font-size: 0.95rem;
1502
+ outline: none;
1503
+ transition: all 0.2s ease;
1504
+ }
1505
+
1506
+ .search-input input:focus {
1507
+ border-color: var(--tab_line);
1508
+ box-shadow: 0 0 0 2px var(--accent-20);
1509
+ }
1510
+
1511
+ .search-input .icon {
1512
+ position: absolute;
1513
+ left: 0.75rem;
1514
+ top: 50%;
1515
+ transform: translateY(-50%);
1516
+ color: color-mix(in srgb, var(--ntp_text) 50%, transparent);
1517
+ }
1518
+
1519
+ .clear-search {
1520
+ position: absolute;
1521
+ right: 0.5rem;
1522
+ top: 50%;
1523
+ transform: translateY(-50%);
1524
+ background: none;
1525
+ border: none;
1526
+ color: color-mix(in srgb, var(--ntp_text) 50%, transparent);
1527
+ font-size: 1.2rem;
1528
+ cursor: pointer;
1529
+ display: flex;
1530
+ align-items: center;
1531
+ justify-content: center;
1532
+ width: 1.5rem;
1533
+ height: 1.5rem;
1534
+ border-radius: 50%;
1535
+ }
1536
+
1537
+ .clear-search:hover {
1538
+ background: var(--ntp-text-10);
1539
+ }
1540
+
1541
+ .settings-content {
1542
+ flex: 1;
1543
+ padding: 2rem;
1544
+ overflow-y: auto;
1545
+ }
1546
+
1547
+ .settings-tab {
1548
+ max-width: max(50rem, 80vw);
1549
+ }
1550
+
1551
+ .setting-section {
1552
+ margin-bottom: 2rem;
1553
+ padding-bottom: 2rem;
1554
+ border-bottom: 1px solid var(--ntp-text-15);
1555
+ }
1556
+
1557
+ .setting-section:last-child {
1558
+ border-bottom: none;
1559
+ margin-bottom: 0;
1560
+ padding-bottom: 0;
1561
+ }
1562
+
1563
+ .section-header {
1564
+ margin-bottom: 1rem;
1565
+ }
1566
+
1567
+ .description {
1568
+ margin-block: 0.33rem;
1569
+ color: var(--ntp-text-60);
1570
+ }
1571
+
1572
+ .section-content {
1573
+ padding-left: 0.5rem;
1574
+ }
1575
+
1576
+ .setting-group {
1577
+ margin-bottom: 1.5rem;
1578
+ }
1579
+
1580
+ .setting-group:last-child {
1581
+ margin-bottom: 0;
1582
+ }
1583
+
1584
+ .label-multiline {
1585
+ display: flex;
1586
+ flex-direction: column;
1587
+ gap: 2.5px;
1588
+ }
1589
+
1590
+ .label-multiline .description {
1591
+ font-size: 0.85rem;
1592
+ color: var(--ntp-text-60);
1593
+ }
1594
+
1595
+ .checkbox-option:has(.label-multiline),
1596
+ .radio-option:has(.label-multiline) {
1597
+ align-items: flex-start;
1598
+ }
1599
+
1600
+ .radio-group {
1601
+ display: flex;
1602
+ flex-direction: column;
1603
+ gap: var(--space-lg);
1604
+ }
1605
+
1606
+ .radio-option,
1607
+ .checkbox-option {
1608
+ display: flex;
1609
+ align-items: center;
1610
+ gap: var(--space-md);
1611
+ margin-bottom: var(--space-md);
1612
+ }
1613
+
1614
+ .radio-option:last-child,
1615
+ .checkbox-option:last-child {
1616
+ margin-bottom: 0;
1617
+ }
1618
+
1619
+ .radio-option label,
1620
+ .checkbox-option label {
1621
+ font-size: 0.95rem;
1622
+ cursor: pointer;
1623
+ }
1624
+
1625
+ .checkbox-option.disabled label {
1626
+ cursor: not-allowed;
1627
+ opacity: 0.65;
1628
+ }
1629
+
1630
+ input[type="radio"],
1631
+ input[type="checkbox"] {
1632
+ accent-color: var(--tab_line);
1633
+ margin: 0;
1634
+ }
1635
+
1636
+ .layout-grid {
1637
+ display: grid;
1638
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr));
1639
+ gap: 0.8rem;
1640
+ }
1641
+
1642
+ .sidebar-location-grid {
1643
+ grid-template-columns: repeat(2, minmax(0, 18rem));
1644
+ max-width: 36.8rem;
1645
+ }
1646
+
1647
+ .layout-card {
1648
+ min-width: 0;
1649
+ border: 1px solid var(--ntp-text-15);
1650
+ border-radius: var(--radius-md);
1651
+ overflow: hidden;
1652
+ background: var(--toolbar_field);
1653
+ cursor: pointer;
1654
+ display: flex;
1655
+ flex-direction: column;
1656
+ transition:
1657
+ border-color 0.15s ease,
1658
+ box-shadow 0.15s ease,
1659
+ transform 0.15s ease;
1660
+ }
1661
+
1662
+ .layout-card:hover {
1663
+ border-color: var(--tab_line);
1664
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1665
+ transform: translateY(-1px);
1666
+ }
1667
+
1668
+ .layout-card:focus-within {
1669
+ outline: 2px solid var(--tab_line);
1670
+ outline-offset: 2px;
1671
+ }
1672
+
1673
+ .layout-card.selected {
1674
+ border-color: var(--tab_line);
1675
+ box-shadow: 0 0 0 3px var(--accent-20);
1676
+ }
1677
+
1678
+ .layout-radio {
1679
+ position: absolute;
1680
+ width: 1px;
1681
+ height: 1px;
1682
+ margin: -1px;
1683
+ padding: 0;
1684
+ overflow: hidden;
1685
+ clip: rect(0 0 0 0);
1686
+ clip-path: inset(50%);
1687
+ white-space: nowrap;
1688
+ }
1689
+
1690
+ .layout-info {
1691
+ padding: var(--space-lg) var(--space-md);
1692
+ display: flex;
1693
+ flex: 1;
1694
+ flex-direction: column;
1695
+ gap: 0.25rem;
1696
+ background: var(--toolbar_field);
1697
+ color: var(--toolbar_field_text);
1698
+ }
1699
+
1700
+ .layout-info.compact {
1701
+ flex: none;
1702
+ }
1703
+
1704
+ .layout-name {
1705
+ font-size: 0.95rem;
1706
+ font-weight: 600;
1707
+ }
1708
+
1709
+ .layout-info .description {
1710
+ font-size: 0.8rem;
1711
+ line-height: 1.3;
1712
+ color: var(--field-text-60);
1713
+ }
1714
+
1715
+ .setting-hint {
1716
+ margin: 0.25rem 0 0;
1717
+ font-size: 0.85rem;
1718
+ color: var(--ntp-text-60);
1719
+ }
1720
+
1721
+ .zoom-control {
1722
+ display: flex;
1723
+ align-items: center;
1724
+ gap: 1rem;
1725
+ }
1726
+
1727
+ .zoom-value {
1728
+ min-width: 3rem;
1729
+ font-size: 0.95rem;
1730
+ font-weight: 500;
1731
+ }
1732
+
1733
+ input[type="range"] {
1734
+ flex: 1;
1735
+ max-width: 20rem;
1736
+ accent-color: var(--tab_line);
1737
+ }
1738
+
1739
+ select {
1740
+ font-family: inherit;
1741
+ }
1742
+
1743
+ .select-input {
1744
+ padding: var(--space-md);
1745
+ border-radius: var(--radius-md);
1746
+ border: 1px solid var(--ntp-text-20);
1747
+ background: var(--toolbar_field);
1748
+ color: var(--toolbar_field_text);
1749
+ font-size: 0.9rem;
1750
+ min-width: 15rem;
1751
+ outline: none;
1752
+ }
1753
+
1754
+ .select-input:focus {
1755
+ border-color: var(--tab_line);
1756
+ }
1757
+
1758
+ .action-button {
1759
+ margin-top: var(--space-xl);
1760
+ background: var(--toolbar_field);
1761
+ border: 1px solid var(--ntp-text-20);
1762
+ color: var(--toolbar_field_text);
1763
+ padding: var(--space-md) var(--space-xl);
1764
+ border-radius: var(--radius-md);
1765
+ font-size: 0.9rem;
1766
+ cursor: pointer;
1767
+ transition: all 0.2s ease;
1768
+ }
1769
+
1770
+ .action-button:hover {
1771
+ background: var(--text-10);
1772
+ }
1773
+
1774
+ .dev-buttons {
1775
+ display: flex;
1776
+ gap: var(--space-lg);
1777
+ }
1778
+
1779
+ .extensions-list {
1780
+ border: 1px solid var(--ntp-text-15);
1781
+ border-radius: 6px;
1782
+ overflow: hidden;
1783
+ }
1784
+
1785
+ .extension-item {
1786
+ padding: 1rem;
1787
+ border-bottom: 1px solid var(--ntp-text-15);
1788
+ }
1789
+
1790
+ .extension-item:last-child {
1791
+ border-bottom: none;
1792
+ }
1793
+
1794
+ .extension-info {
1795
+ display: flex;
1796
+ align-items: center;
1797
+ gap: 1rem;
1798
+ }
1799
+
1800
+ .extension-icon {
1801
+ width: 3.25rem;
1802
+ height: 3.25rem;
1803
+ font-size: 2.25rem;
1804
+ border-radius: 6px;
1805
+ background: var(--ntp-text-10);
1806
+ color: color-mix(in srgb, var(--ntp_text) 50%, transparent);
1807
+ display: flex;
1808
+ align-items: center;
1809
+ justify-content: center;
1810
+ }
1811
+
1812
+ .extension-icon .icon-inner {
1813
+ transform: translate(2px, 2px);
1814
+ transform-origin: top right;
1815
+ }
1816
+
1817
+ .extension-details h4 {
1818
+ margin-bottom: 0.25rem;
1819
+ }
1820
+
1821
+ .extension-details p {
1822
+ font-size: 0.85rem;
1823
+ color: var(--ntp-text-60);
1824
+ }
1825
+
1826
+ .about-info {
1827
+ display: flex;
1828
+ align-items: center;
1829
+ gap: 1.5rem;
1830
+ margin-bottom: 1.5rem;
1831
+ }
1832
+
1833
+ .browser-logo {
1834
+ width: 5rem;
1835
+ height: 5rem;
1836
+ }
1837
+
1838
+ .browser-info h3 {
1839
+ font-size: 1.5rem;
1840
+ margin-bottom: 0.25rem;
1841
+ }
1842
+
1843
+ .browser-info p {
1844
+ margin-bottom: 0.25rem;
1845
+ }
1846
+
1847
+ .link {
1848
+ display: inline-block;
1849
+ margin-top: 0.75rem;
1850
+ color: var(--tab_line);
1851
+ text-decoration: none;
1852
+ }
1853
+
1854
+ .link:hover {
1855
+ text-decoration: underline;
1856
+ }
1857
+
1858
+ .placeholder {
1859
+ position: relative;
1860
+ overflow: hidden;
1861
+ }
1862
+
1863
+ .placeholder::after {
1864
+ content: "";
1865
+ position: absolute;
1866
+ top: 0;
1867
+ left: 0;
1868
+ width: 100%;
1869
+ height: 100%;
1870
+ background: linear-gradient(
1871
+ 90deg,
1872
+ var(--ntp-text-5) 0%,
1873
+ var(--ntp-text-10) 50%,
1874
+ var(--ntp-text-5) 100%
1875
+ );
1876
+ animation: shimmer 1.5s infinite;
1877
+ background-size: 200% 100%;
1878
+ }
1879
+
1880
+ @keyframes shimmer {
1881
+ 0% {
1882
+ background-position: -200% 0;
1883
+ }
1884
+ 100% {
1885
+ background-position: 200% 0;
1886
+ }
1887
+ }
1888
+
1889
+ .theme-grid {
1890
+ display: grid;
1891
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 40rem), 1fr));
1892
+ gap: 1rem;
1893
+ margin-top: 0.75rem;
1894
+ }
1895
+
1896
+ .theme-card {
1897
+ border-radius: var(--radius-md);
1898
+ overflow: hidden;
1899
+ cursor: pointer;
1900
+ transition: all 0.2s ease;
1901
+ background: var(--toolbar_field);
1902
+ }
1903
+
1904
+ .theme-card:hover {
1905
+ border-color: var(--tab_line);
1906
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1907
+ }
1908
+
1909
+ .theme-card.selected {
1910
+ border-color: var(--tab_line);
1911
+ box-shadow: 0 0 0 3px var(--accent-20);
1912
+ }
1913
+
1914
+ .theme-info {
1915
+ padding: var(--space-lg) var(--space-md);
1916
+ }
1917
+
1918
+ .theme-info h5 {
1919
+ margin: 0.25rem 0;
1920
+ font-size: 0.95rem;
1921
+ font-weight: 600;
1922
+ color: var(--toolbar_field_text);
1923
+ }
1924
+
1925
+ .theme-info p {
1926
+ margin: 0;
1927
+ font-size: 0.8rem;
1928
+ color: var(--field-text-60);
1929
+ line-height: 1.3;
1930
+ }
1931
+ `;