@walkthru-earth/objex 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 (367) hide show
  1. package/LICENSE +396 -0
  2. package/README.md +114 -0
  3. package/dist/assets/favicon.svg +17 -0
  4. package/dist/components/CLAUDE.md +44 -0
  5. package/dist/components/browser/Breadcrumb.svelte +50 -0
  6. package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
  7. package/dist/components/browser/CreateFolderDialog.svelte +98 -0
  8. package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
  9. package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
  10. package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
  11. package/dist/components/browser/DropZone.svelte +83 -0
  12. package/dist/components/browser/DropZone.svelte.d.ts +7 -0
  13. package/dist/components/browser/FileBrowser.svelte +229 -0
  14. package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
  15. package/dist/components/browser/FileRow.svelte +112 -0
  16. package/dist/components/browser/FileRow.svelte.d.ts +9 -0
  17. package/dist/components/browser/FileTreeSidebar.svelte +559 -0
  18. package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
  19. package/dist/components/browser/RenameDialog.svelte +101 -0
  20. package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
  21. package/dist/components/browser/SearchBar.svelte +40 -0
  22. package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
  23. package/dist/components/browser/UploadButton.svelte +65 -0
  24. package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
  25. package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
  26. package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
  27. package/dist/components/editor/MilkdownEditor.svelte +98 -0
  28. package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
  29. package/dist/components/editor/SqlEditor.svelte +173 -0
  30. package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
  31. package/dist/components/editor/SqlResultBlock.svelte +199 -0
  32. package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
  33. package/dist/components/layout/ConnectionDialog.svelte +439 -0
  34. package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
  35. package/dist/components/layout/LocaleToggle.svelte +32 -0
  36. package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
  37. package/dist/components/layout/SafeLockToggle.svelte +37 -0
  38. package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
  39. package/dist/components/layout/Sidebar.svelte +314 -0
  40. package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
  41. package/dist/components/layout/StatusBar.svelte +73 -0
  42. package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
  43. package/dist/components/layout/TabBar.svelte +102 -0
  44. package/dist/components/layout/TabBar.svelte.d.ts +7 -0
  45. package/dist/components/layout/ThemeToggle.svelte +52 -0
  46. package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
  47. package/dist/components/ui/badge/badge.svelte +49 -0
  48. package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
  49. package/dist/components/ui/badge/index.d.ts +1 -0
  50. package/dist/components/ui/badge/index.js +1 -0
  51. package/dist/components/ui/button/button.svelte +82 -0
  52. package/dist/components/ui/button/button.svelte.d.ts +64 -0
  53. package/dist/components/ui/button/index.d.ts +2 -0
  54. package/dist/components/ui/button/index.js +4 -0
  55. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
  56. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
  57. package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
  58. package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
  59. package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
  60. package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
  61. package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
  62. package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
  63. package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
  64. package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
  65. package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
  66. package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
  67. package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
  68. package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
  69. package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
  70. package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
  71. package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
  72. package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
  73. package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
  74. package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
  75. package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
  76. package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
  77. package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
  78. package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
  79. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
  80. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
  81. package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
  82. package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
  83. package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
  84. package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
  85. package/dist/components/ui/context-menu/context-menu.svelte +7 -0
  86. package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
  87. package/dist/components/ui/context-menu/index.d.ts +17 -0
  88. package/dist/components/ui/context-menu/index.js +19 -0
  89. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  90. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  91. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
  92. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  93. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
  94. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  95. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  96. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  97. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
  98. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  99. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
  100. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  101. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
  102. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  103. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  104. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  105. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  106. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  107. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
  108. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  109. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  110. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  111. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
  112. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  113. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
  114. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
  115. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  116. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  117. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  118. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  119. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  120. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  121. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
  122. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  123. package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
  124. package/dist/components/ui/dropdown-menu/index.js +18 -0
  125. package/dist/components/ui/input/index.d.ts +2 -0
  126. package/dist/components/ui/input/index.js +4 -0
  127. package/dist/components/ui/input/input.svelte +52 -0
  128. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  129. package/dist/components/ui/resizable/index.d.ts +4 -0
  130. package/dist/components/ui/resizable/index.js +6 -0
  131. package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
  132. package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
  133. package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
  134. package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
  135. package/dist/components/ui/scroll-area/index.d.ts +3 -0
  136. package/dist/components/ui/scroll-area/index.js +5 -0
  137. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
  138. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
  139. package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
  140. package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
  141. package/dist/components/ui/separator/index.d.ts +2 -0
  142. package/dist/components/ui/separator/index.js +4 -0
  143. package/dist/components/ui/separator/separator.svelte +21 -0
  144. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  145. package/dist/components/ui/sheet/index.d.ts +11 -0
  146. package/dist/components/ui/sheet/index.js +13 -0
  147. package/dist/components/ui/sheet/sheet-close.svelte +7 -0
  148. package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
  149. package/dist/components/ui/sheet/sheet-content.svelte +62 -0
  150. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
  151. package/dist/components/ui/sheet/sheet-description.svelte +17 -0
  152. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
  153. package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
  154. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  155. package/dist/components/ui/sheet/sheet-header.svelte +20 -0
  156. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
  157. package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
  158. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  159. package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
  160. package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
  161. package/dist/components/ui/sheet/sheet-title.svelte +13 -0
  162. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
  163. package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
  164. package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  165. package/dist/components/ui/sheet/sheet.svelte +7 -0
  166. package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
  167. package/dist/components/ui/switch/index.d.ts +2 -0
  168. package/dist/components/ui/switch/index.js +4 -0
  169. package/dist/components/ui/switch/switch.svelte +28 -0
  170. package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
  171. package/dist/components/ui/tabs/index.d.ts +5 -0
  172. package/dist/components/ui/tabs/index.js +7 -0
  173. package/dist/components/ui/tabs/tabs-content.svelte +17 -0
  174. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  175. package/dist/components/ui/tabs/tabs-list.svelte +16 -0
  176. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
  177. package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
  178. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  179. package/dist/components/ui/tabs/tabs.svelte +19 -0
  180. package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
  181. package/dist/components/ui/tooltip/index.d.ts +6 -0
  182. package/dist/components/ui/tooltip/index.js +8 -0
  183. package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
  184. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
  185. package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
  186. package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
  187. package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
  188. package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
  189. package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  190. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  191. package/dist/components/ui/tooltip/tooltip.svelte +7 -0
  192. package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
  193. package/dist/components/viewers/ArchiveViewer.svelte +586 -0
  194. package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
  195. package/dist/components/viewers/CLAUDE.md +60 -0
  196. package/dist/components/viewers/CodeViewer.svelte +553 -0
  197. package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
  198. package/dist/components/viewers/CogViewer.svelte +1345 -0
  199. package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
  200. package/dist/components/viewers/CopcViewer.svelte +25 -0
  201. package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
  202. package/dist/components/viewers/DatabaseViewer.svelte +169 -0
  203. package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
  204. package/dist/components/viewers/FileInfo.svelte +174 -0
  205. package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
  206. package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
  207. package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
  208. package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
  209. package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
  210. package/dist/components/viewers/ImageViewer.svelte +233 -0
  211. package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
  212. package/dist/components/viewers/LoadProgress.svelte +93 -0
  213. package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
  214. package/dist/components/viewers/MapViewer.svelte +234 -0
  215. package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
  216. package/dist/components/viewers/MarkdownViewer.svelte +478 -0
  217. package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
  218. package/dist/components/viewers/MediaViewer.svelte +121 -0
  219. package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
  220. package/dist/components/viewers/ModelViewer.svelte +164 -0
  221. package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
  222. package/dist/components/viewers/NotebookViewer.svelte +389 -0
  223. package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
  224. package/dist/components/viewers/PdfViewer.svelte +278 -0
  225. package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
  226. package/dist/components/viewers/PmtilesViewer.svelte +191 -0
  227. package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
  228. package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
  229. package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
  230. package/dist/components/viewers/RawViewer.svelte +117 -0
  231. package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
  232. package/dist/components/viewers/StacMapViewer.svelte +20 -0
  233. package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
  234. package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
  235. package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
  236. package/dist/components/viewers/TableGrid.svelte +355 -0
  237. package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
  238. package/dist/components/viewers/TableStatusBar.svelte +92 -0
  239. package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
  240. package/dist/components/viewers/TableToolbar.svelte +382 -0
  241. package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
  242. package/dist/components/viewers/TableViewer.svelte +923 -0
  243. package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
  244. package/dist/components/viewers/ViewerRouter.svelte +70 -0
  245. package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
  246. package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
  247. package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
  248. package/dist/components/viewers/ZarrViewer.svelte +256 -0
  249. package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
  250. package/dist/components/viewers/map/AttributeTable.svelte +52 -0
  251. package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
  252. package/dist/components/viewers/map/MapContainer.svelte +158 -0
  253. package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
  254. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
  255. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
  256. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
  257. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
  258. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
  259. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
  260. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
  261. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
  262. package/dist/file-icons/CLAUDE.md +21 -0
  263. package/dist/file-icons/FileTypeIcon.svelte +74 -0
  264. package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
  265. package/dist/file-icons/index.d.ts +56 -0
  266. package/dist/file-icons/index.js +1070 -0
  267. package/dist/i18n/CLAUDE.md +19 -0
  268. package/dist/i18n/ar.d.ts +1 -0
  269. package/dist/i18n/ar.js +404 -0
  270. package/dist/i18n/en.d.ts +1 -0
  271. package/dist/i18n/en.js +404 -0
  272. package/dist/i18n/index.svelte.d.ts +9 -0
  273. package/dist/i18n/index.svelte.js +27 -0
  274. package/dist/index.d.ts +20 -0
  275. package/dist/index.js +13 -0
  276. package/dist/query/CLAUDE.md +22 -0
  277. package/dist/query/engine.d.ts +56 -0
  278. package/dist/query/engine.js +6 -0
  279. package/dist/query/index.d.ts +4 -0
  280. package/dist/query/index.js +19 -0
  281. package/dist/query/wasm.d.ts +20 -0
  282. package/dist/query/wasm.js +890 -0
  283. package/dist/storage/CLAUDE.md +23 -0
  284. package/dist/storage/adapter.d.ts +21 -0
  285. package/dist/storage/adapter.js +1 -0
  286. package/dist/storage/browser-azure.d.ts +25 -0
  287. package/dist/storage/browser-azure.js +271 -0
  288. package/dist/storage/browser-cloud.d.ts +32 -0
  289. package/dist/storage/browser-cloud.js +293 -0
  290. package/dist/storage/index.d.ts +11 -0
  291. package/dist/storage/index.js +37 -0
  292. package/dist/storage/url-adapter.d.ts +19 -0
  293. package/dist/storage/url-adapter.js +51 -0
  294. package/dist/stores/CLAUDE.md +29 -0
  295. package/dist/stores/browser.svelte.d.ts +28 -0
  296. package/dist/stores/browser.svelte.js +160 -0
  297. package/dist/stores/connections.svelte.d.ts +56 -0
  298. package/dist/stores/connections.svelte.js +272 -0
  299. package/dist/stores/credentials.svelte.d.ts +56 -0
  300. package/dist/stores/credentials.svelte.js +79 -0
  301. package/dist/stores/files.svelte.d.ts +20 -0
  302. package/dist/stores/files.svelte.js +76 -0
  303. package/dist/stores/query-history.svelte.d.ts +16 -0
  304. package/dist/stores/query-history.svelte.js +57 -0
  305. package/dist/stores/safelock.svelte.d.ts +8 -0
  306. package/dist/stores/safelock.svelte.js +52 -0
  307. package/dist/stores/settings.svelte.d.ts +11 -0
  308. package/dist/stores/settings.svelte.js +101 -0
  309. package/dist/stores/tab-resources.svelte.d.ts +25 -0
  310. package/dist/stores/tab-resources.svelte.js +61 -0
  311. package/dist/stores/tabs.svelte.d.ts +17 -0
  312. package/dist/stores/tabs.svelte.js +110 -0
  313. package/dist/types/notebookjs.d.ts +14 -0
  314. package/dist/types.d.ts +47 -0
  315. package/dist/types.js +1 -0
  316. package/dist/utils/CLAUDE.md +54 -0
  317. package/dist/utils/analytics.d.ts +10 -0
  318. package/dist/utils/analytics.js +38 -0
  319. package/dist/utils/archive.d.ts +70 -0
  320. package/dist/utils/archive.js +333 -0
  321. package/dist/utils/column-types.d.ts +5 -0
  322. package/dist/utils/column-types.js +137 -0
  323. package/dist/utils/deck.d.ts +98 -0
  324. package/dist/utils/deck.js +208 -0
  325. package/dist/utils/evidence-context.d.ts +22 -0
  326. package/dist/utils/evidence-context.js +56 -0
  327. package/dist/utils/export.d.ts +2 -0
  328. package/dist/utils/export.js +51 -0
  329. package/dist/utils/format.d.ts +14 -0
  330. package/dist/utils/format.js +56 -0
  331. package/dist/utils/geoarrow.d.ts +32 -0
  332. package/dist/utils/geoarrow.js +672 -0
  333. package/dist/utils/hex.d.ts +10 -0
  334. package/dist/utils/hex.js +27 -0
  335. package/dist/utils/host-detection.d.ts +23 -0
  336. package/dist/utils/host-detection.js +289 -0
  337. package/dist/utils/map-selection.d.ts +12 -0
  338. package/dist/utils/map-selection.js +45 -0
  339. package/dist/utils/markdown-sql.d.ts +30 -0
  340. package/dist/utils/markdown-sql.js +73 -0
  341. package/dist/utils/markdown.d.ts +18 -0
  342. package/dist/utils/markdown.js +146 -0
  343. package/dist/utils/model3d.d.ts +13 -0
  344. package/dist/utils/model3d.js +62 -0
  345. package/dist/utils/parquet-metadata.d.ts +58 -0
  346. package/dist/utils/parquet-metadata.js +228 -0
  347. package/dist/utils/pdf.d.ts +8 -0
  348. package/dist/utils/pdf.js +28 -0
  349. package/dist/utils/pmtiles-tile.d.ts +38 -0
  350. package/dist/utils/pmtiles-tile.js +64 -0
  351. package/dist/utils/pmtiles.d.ts +46 -0
  352. package/dist/utils/pmtiles.js +135 -0
  353. package/dist/utils/shiki.d.ts +8 -0
  354. package/dist/utils/shiki.js +98 -0
  355. package/dist/utils/storage-url.d.ts +64 -0
  356. package/dist/utils/storage-url.js +374 -0
  357. package/dist/utils/url-state.d.ts +40 -0
  358. package/dist/utils/url-state.js +113 -0
  359. package/dist/utils/url.d.ts +27 -0
  360. package/dist/utils/url.js +115 -0
  361. package/dist/utils/wkb.d.ts +43 -0
  362. package/dist/utils/wkb.js +345 -0
  363. package/dist/utils/zarr.d.ts +39 -0
  364. package/dist/utils/zarr.js +204 -0
  365. package/dist/utils.d.ts +12 -0
  366. package/dist/utils.js +5 -0
  367. package/package.json +203 -0
@@ -0,0 +1,234 @@
1
+ <script lang="ts">
2
+ import type maplibregl from 'maplibre-gl';
3
+ import { onDestroy } from 'svelte';
4
+ import { t } from '../../i18n/index.svelte.js';
5
+ import { getAdapter } from '../../storage/index.js';
6
+ import { tabResources } from '../../stores/tab-resources.svelte.js';
7
+ import type { Tab } from '../../types';
8
+ import { setupSelectionLayer, updateSelection } from '../../utils/map-selection.js';
9
+ import AttributeTable from './map/AttributeTable.svelte';
10
+ import MapContainer from './map/MapContainer.svelte';
11
+
12
+ let { tab }: { tab: Tab } = $props();
13
+
14
+ let abortController: AbortController | null = null;
15
+ let loading = $state(true);
16
+ let error = $state<string | null>(null);
17
+ let geojsonData = $state.raw<any>(null);
18
+ let selectedFeature = $state<Record<string, any> | null>(null);
19
+ let showAttributes = $state(false);
20
+ let bounds = $state<[number, number, number, number] | undefined>();
21
+
22
+ $effect(() => {
23
+ if (!tab) return;
24
+ loadGeoJson();
25
+ });
26
+
27
+ function cleanup() {
28
+ abortController?.abort();
29
+ abortController = null;
30
+ geojsonData = null;
31
+ selectedFeature = null;
32
+ bounds = undefined;
33
+ }
34
+
35
+ $effect(() => {
36
+ if (!tab) return;
37
+ const unregister = tabResources.register(tab.id, cleanup);
38
+ return unregister;
39
+ });
40
+
41
+ onDestroy(cleanup);
42
+
43
+ async function loadGeoJson() {
44
+ abortController?.abort();
45
+ abortController = new AbortController();
46
+ const { signal } = abortController;
47
+
48
+ loading = true;
49
+ error = null;
50
+
51
+ try {
52
+ const adapter = getAdapter(tab.source, tab.connectionId);
53
+ const data = await adapter.read(tab.path, undefined, undefined, signal);
54
+ const text = new TextDecoder().decode(data);
55
+ geojsonData = JSON.parse(text);
56
+
57
+ // Compute bounds from features
58
+ if (geojsonData.bbox) {
59
+ bounds = geojsonData.bbox as [number, number, number, number];
60
+ } else {
61
+ bounds = computeBounds(geojsonData);
62
+ }
63
+ } catch (err) {
64
+ if (err instanceof DOMException && err.name === 'AbortError') return;
65
+ error = err instanceof Error ? err.message : String(err);
66
+ } finally {
67
+ loading = false;
68
+ }
69
+ }
70
+
71
+ function computeBounds(geojson: any): [number, number, number, number] | undefined {
72
+ let minLng = Infinity,
73
+ minLat = Infinity,
74
+ maxLng = -Infinity,
75
+ maxLat = -Infinity;
76
+ let found = false;
77
+
78
+ function processCoord(coord: number[]) {
79
+ if (coord.length >= 2) {
80
+ found = true;
81
+ minLng = Math.min(minLng, coord[0]);
82
+ minLat = Math.min(minLat, coord[1]);
83
+ maxLng = Math.max(maxLng, coord[0]);
84
+ maxLat = Math.max(maxLat, coord[1]);
85
+ }
86
+ }
87
+
88
+ function processCoords(coords: any) {
89
+ if (!coords) return;
90
+ if (typeof coords[0] === 'number') {
91
+ processCoord(coords);
92
+ } else {
93
+ for (const c of coords) processCoords(c);
94
+ }
95
+ }
96
+
97
+ function processGeometry(geom: any) {
98
+ if (!geom) return;
99
+ if (geom.coordinates) processCoords(geom.coordinates);
100
+ if (geom.geometries) geom.geometries.forEach(processGeometry);
101
+ }
102
+
103
+ if (geojson.type === 'FeatureCollection') {
104
+ for (const f of geojson.features || []) processGeometry(f.geometry);
105
+ } else if (geojson.type === 'Feature') {
106
+ processGeometry(geojson.geometry);
107
+ } else {
108
+ processGeometry(geojson);
109
+ }
110
+
111
+ return found ? [minLng, minLat, maxLng, maxLat] : undefined;
112
+ }
113
+
114
+ function onMapReady(map: maplibregl.Map) {
115
+ if (!geojsonData) return;
116
+
117
+ map.addSource('geojson-source', {
118
+ type: 'geojson',
119
+ data: geojsonData
120
+ });
121
+
122
+ // Fill layer for polygons (orange)
123
+ map.addLayer({
124
+ id: 'geojson-fill',
125
+ type: 'fill',
126
+ source: 'geojson-source',
127
+ filter: ['==', '$type', 'Polygon'],
128
+ paint: {
129
+ 'fill-color': '#e8793d',
130
+ 'fill-opacity': 0.35
131
+ }
132
+ });
133
+
134
+ // Outline layer for polygons (orange)
135
+ map.addLayer({
136
+ id: 'geojson-polygon-outline',
137
+ type: 'line',
138
+ source: 'geojson-source',
139
+ filter: ['==', '$type', 'Polygon'],
140
+ paint: {
141
+ 'line-color': '#e65100',
142
+ 'line-width': 2.5
143
+ }
144
+ });
145
+
146
+ // Line layer for linestrings (teal)
147
+ map.addLayer({
148
+ id: 'geojson-line',
149
+ type: 'line',
150
+ source: 'geojson-source',
151
+ filter: ['==', '$type', 'LineString'],
152
+ paint: {
153
+ 'line-color': '#00838f',
154
+ 'line-width': 2.5
155
+ }
156
+ });
157
+
158
+ // Circle layer for points (blue)
159
+ map.addLayer({
160
+ id: 'geojson-points',
161
+ type: 'circle',
162
+ source: 'geojson-source',
163
+ filter: ['==', '$type', 'Point'],
164
+ paint: {
165
+ 'circle-radius': 7,
166
+ 'circle-color': '#4285f4',
167
+ 'circle-stroke-width': 1.5,
168
+ 'circle-stroke-color': '#fff'
169
+ }
170
+ });
171
+
172
+ // Selection highlight
173
+ setupSelectionLayer(map);
174
+
175
+ // Click handler
176
+ for (const layerId of [
177
+ 'geojson-fill',
178
+ 'geojson-polygon-outline',
179
+ 'geojson-line',
180
+ 'geojson-points'
181
+ ]) {
182
+ map.on('click', layerId, (e: any) => {
183
+ if (e.features && e.features.length > 0) {
184
+ selectedFeature = { ...e.features[0].properties };
185
+ showAttributes = true;
186
+ updateSelection(map, e.features[0] as GeoJSON.Feature);
187
+ }
188
+ });
189
+
190
+ map.on('mouseenter', layerId, () => {
191
+ map.getCanvas().style.cursor = 'pointer';
192
+ });
193
+
194
+ map.on('mouseleave', layerId, () => {
195
+ map.getCanvas().style.cursor = '';
196
+ });
197
+ }
198
+ }
199
+ </script>
200
+
201
+ <div class="relative flex h-full overflow-hidden">
202
+ {#if loading}
203
+ <div class="flex flex-1 items-center justify-center">
204
+ <p class="text-sm text-zinc-400">{t('map.loadingData')}</p>
205
+ </div>
206
+ {:else if error}
207
+ <div class="flex flex-1 items-center justify-center">
208
+ <p class="text-sm text-red-400">{error}</p>
209
+ </div>
210
+ {:else}
211
+ <div class="flex-1">
212
+ <MapContainer {onMapReady} {bounds} />
213
+ </div>
214
+
215
+ {#if selectedFeature}
216
+ <div class="absolute right-2 top-2 z-10 flex gap-1">
217
+ <button
218
+ class="rounded bg-card/80 px-2 py-1 text-xs text-card-foreground backdrop-blur-sm hover:bg-card"
219
+ class:ring-1={showAttributes}
220
+ class:ring-primary={showAttributes}
221
+ onclick={() => (showAttributes = !showAttributes)}
222
+ >
223
+ {t('map.attributes')}
224
+ </button>
225
+ </div>
226
+ {/if}
227
+
228
+ <AttributeTable
229
+ feature={selectedFeature}
230
+ visible={showAttributes}
231
+ onClose={() => (showAttributes = false)}
232
+ />
233
+ {/if}
234
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { Tab } from '../../types';
2
+ type $$ComponentProps = {
3
+ tab: Tab;
4
+ };
5
+ declare const MapViewer: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type MapViewer = ReturnType<typeof MapViewer>;
7
+ export default MapViewer;
@@ -0,0 +1,478 @@
1
+ <script lang="ts">
2
+ import { onDestroy, tick } from 'svelte';
3
+ import SqlResultBlock from '../editor/SqlResultBlock.svelte';
4
+ import { Badge } from '../ui/badge/index.js';
5
+ import { Button } from '../ui/button/index.js';
6
+ import { t } from '../../i18n/index.svelte.js';
7
+ import { getAdapter } from '../../storage/index.js';
8
+ import { tabResources } from '../../stores/tab-resources.svelte.js';
9
+ import type { Tab } from '../../types';
10
+ import { EvidenceContext } from '../../utils/evidence-context';
11
+ import { detectRTL, processDirection, renderMarkdown } from '../../utils/markdown';
12
+ import {
13
+ interpolateTemplates,
14
+ markSqlBlocks,
15
+ parseMarkdownDocument
16
+ } from '../../utils/markdown-sql';
17
+
18
+ let mermaidInitialized = false;
19
+ const CAIRO_FONT = '"Cairo", sans-serif';
20
+ const SYSTEM_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
21
+
22
+ let { tab }: { tab: Tab } = $props();
23
+
24
+ let abortController: AbortController | null = null;
25
+ let html = $state('');
26
+ let rawMarkdown = $state('');
27
+ let loading = $state(true);
28
+ let error = $state<string | null>(null);
29
+ let editMode = $state(false);
30
+ let sqlResults = $state<
31
+ Map<string, { columns: string[]; rows: Record<string, any>[]; error?: string }>
32
+ >(new Map());
33
+ let hasSqlBlocks = $state(false);
34
+ let contentDir = $state<'ltr' | 'rtl'>('ltr');
35
+ let contentEl: HTMLElement | undefined = $state();
36
+
37
+ function cleanup() {
38
+ abortController?.abort();
39
+ abortController = null;
40
+ html = '';
41
+ rawMarkdown = '';
42
+ sqlResults = new Map();
43
+ }
44
+
45
+ $effect(() => {
46
+ const id = tab.id;
47
+ const unregister = tabResources.register(id, cleanup);
48
+ return unregister;
49
+ });
50
+ onDestroy(cleanup);
51
+
52
+ $effect(() => {
53
+ if (!tab) return;
54
+ loadMarkdown();
55
+ });
56
+
57
+ async function loadMarkdown() {
58
+ abortController?.abort();
59
+ abortController = new AbortController();
60
+ const { signal } = abortController;
61
+
62
+ loading = true;
63
+ error = null;
64
+
65
+ try {
66
+ const adapter = getAdapter(tab.source, tab.connectionId);
67
+ const data = await adapter.read(tab.path, undefined, undefined, signal);
68
+ rawMarkdown = new TextDecoder().decode(data);
69
+
70
+ const isRTL = detectRTL(rawMarkdown);
71
+ contentDir = isRTL ? 'rtl' : 'ltr';
72
+
73
+ // Parse for SQL blocks
74
+ const parsed = parseMarkdownDocument(rawMarkdown);
75
+ hasSqlBlocks = parsed.sqlBlocks.length > 0;
76
+
77
+ if (parsed.sqlBlocks.length > 0) {
78
+ // Execute SQL blocks in parallel
79
+ const ctx = new EvidenceContext(
80
+ tab.connectionId ?? '',
81
+ tab.path.split('/').slice(0, -1).join('/')
82
+ );
83
+
84
+ const results = new Map<
85
+ string,
86
+ { columns: string[]; rows: Record<string, any>[]; error?: string }
87
+ >();
88
+
89
+ await Promise.all(
90
+ parsed.sqlBlocks.map(async (block) => {
91
+ try {
92
+ const rows = await ctx.executeSql(block.sql, block.name);
93
+ const columns = ctx.getColumns(block.name);
94
+ results.set(block.name, { columns, rows });
95
+ } catch (err) {
96
+ results.set(block.name, {
97
+ columns: [],
98
+ rows: [],
99
+ error: err instanceof Error ? err.message : String(err)
100
+ });
101
+ }
102
+ })
103
+ );
104
+
105
+ sqlResults = results;
106
+
107
+ // Interpolate templates and render
108
+ const interpolated = interpolateTemplates(parsed.content, ctx.getAllResults());
109
+ const markedContent = markSqlBlocks(interpolated);
110
+ let rendered = await renderMarkdown(markedContent);
111
+ html = processDirection(rendered, isRTL);
112
+ } else {
113
+ let rendered = await renderMarkdown(rawMarkdown);
114
+ html = processDirection(rendered, isRTL);
115
+ }
116
+ } catch (err) {
117
+ if (err instanceof DOMException && err.name === 'AbortError') return;
118
+ error = err instanceof Error ? err.message : String(err);
119
+ } finally {
120
+ loading = false;
121
+ }
122
+
123
+ // After loading is false and DOM has mounted the article
124
+ if (!error) {
125
+ await tick();
126
+ await renderMermaidDiagrams();
127
+ wireCodeCopyButtons();
128
+ }
129
+ }
130
+
131
+ function wireCodeCopyButtons() {
132
+ if (!contentEl) return;
133
+ for (const btn of contentEl.querySelectorAll('.code-copy-btn')) {
134
+ btn.addEventListener('click', async () => {
135
+ const code = decodeURIComponent((btn as HTMLElement).dataset.code ?? '');
136
+ try {
137
+ await navigator.clipboard.writeText(code);
138
+ btn.classList.add('copied');
139
+ setTimeout(() => btn.classList.remove('copied'), 2000);
140
+ } catch {
141
+ // clipboard not available
142
+ }
143
+ });
144
+ }
145
+ }
146
+
147
+ async function renderMermaidDiagrams() {
148
+ if (!contentEl) return;
149
+ const mermaidNodes = contentEl.querySelectorAll('.mermaid');
150
+ if (mermaidNodes.length === 0) return;
151
+
152
+ try {
153
+ const mermaid = (await import('mermaid')).default;
154
+ // Always use Cairo — it supports both Arabic and Latin scripts
155
+ const fontFamily = CAIRO_FONT;
156
+ if (!mermaidInitialized) {
157
+ mermaid.initialize({
158
+ startOnLoad: false,
159
+ theme: 'default',
160
+ securityLevel: 'loose',
161
+ fontFamily: fontFamily,
162
+ themeVariables: { fontFamily },
163
+ flowchart: { useMaxWidth: true },
164
+ sequence: { useMaxWidth: true },
165
+ gantt: { useMaxWidth: true }
166
+ });
167
+ mermaidInitialized = true;
168
+ }
169
+ await mermaid.run({ nodes: mermaidNodes as NodeListOf<HTMLElement> });
170
+
171
+ // Post-process SVGs: make responsive + force font on all text elements
172
+ for (const node of mermaidNodes) {
173
+ const svg = node.querySelector('svg');
174
+ if (!svg) continue;
175
+ const width = svg.getAttribute('width');
176
+ const height = svg.getAttribute('height');
177
+ if (width && height && !svg.getAttribute('viewBox')) {
178
+ svg.setAttribute('viewBox', `0 0 ${parseFloat(width)} ${parseFloat(height)}`);
179
+ }
180
+ svg.removeAttribute('width');
181
+ svg.removeAttribute('height');
182
+
183
+ // Force Cairo on SVG root
184
+ svg.style.fontFamily = fontFamily;
185
+
186
+ // Force font on all text/tspan elements inside the SVG
187
+ for (const el of svg.querySelectorAll('text, tspan')) {
188
+ (el as SVGElement).style.fontFamily = fontFamily;
189
+ }
190
+
191
+ // Force font on foreignObject content (used by some diagram types)
192
+ for (const el of svg.querySelectorAll(
193
+ 'foreignObject div, foreignObject span, foreignObject p'
194
+ )) {
195
+ (el as HTMLElement).style.fontFamily = fontFamily;
196
+ }
197
+ }
198
+ } catch (err) {
199
+ console.warn('Mermaid rendering failed:', err);
200
+ }
201
+ }
202
+
203
+ async function saveMarkdown(markdown: string) {
204
+ try {
205
+ const adapter = getAdapter(tab.source, tab.connectionId);
206
+ const data = new TextEncoder().encode(markdown);
207
+ await adapter.put(tab.path, data, 'text/markdown');
208
+ rawMarkdown = markdown;
209
+ editMode = false;
210
+ await loadMarkdown();
211
+ } catch (err) {
212
+ error = err instanceof Error ? err.message : String(err);
213
+ }
214
+ }
215
+ </script>
216
+
217
+ <div class="flex h-full flex-col">
218
+ <div
219
+ class="flex items-center gap-1 border-b border-zinc-200 px-2 py-1.5 sm:gap-2 sm:px-4 dark:border-zinc-800"
220
+ >
221
+ <span class="truncate max-w-[120px] text-sm font-medium text-zinc-700 sm:max-w-none dark:text-zinc-300">{tab.name}</span>
222
+ <Badge variant="secondary">{t('markdown.badge')}</Badge>
223
+ {#if hasSqlBlocks}
224
+ <Badge variant="outline" class="border-blue-200 text-blue-600 dark:border-blue-800 dark:text-blue-300">
225
+ {t('markdown.evidence')}
226
+ </Badge>
227
+ {/if}
228
+
229
+ <div class="ms-auto">
230
+ <Button
231
+ variant="ghost"
232
+ size="sm"
233
+ class="h-7 px-2 text-xs {editMode ? 'text-blue-500' : ''}"
234
+ onclick={() => (editMode = !editMode)}
235
+ >
236
+ {editMode ? t('markdown.view') : t('markdown.edit')}
237
+ </Button>
238
+ </div>
239
+ </div>
240
+
241
+ <div class="flex-1 overflow-auto">
242
+ {#if loading}
243
+ <div class="flex h-full items-center justify-center">
244
+ <p class="text-sm text-zinc-400">Loading...</p>
245
+ </div>
246
+ {:else if error}
247
+ <div class="flex h-full items-center justify-center">
248
+ <p class="text-sm text-red-400">{error}</p>
249
+ </div>
250
+ {:else if editMode}
251
+ {#await import('../editor/MilkdownEditor.svelte') then MilkdownEditor}
252
+ <MilkdownEditor.default
253
+ initialValue={rawMarkdown}
254
+ onSave={saveMarkdown}
255
+ />
256
+ {/await}
257
+ {:else}
258
+ <article
259
+ bind:this={contentEl}
260
+ dir={contentDir}
261
+ class="prose prose-zinc dark:prose-invert max-w-none p-6 lg:p-8"
262
+ class:md-rtl={contentDir === 'rtl'}
263
+ >
264
+ {@html html}
265
+
266
+ <!-- Render SQL result blocks -->
267
+ {#each [...sqlResults.entries()] as [name, result]}
268
+ <SqlResultBlock
269
+ columns={result.columns}
270
+ rows={result.rows}
271
+ queryName={name}
272
+ error={result.error ?? null}
273
+ />
274
+ {/each}
275
+ </article>
276
+ {/if}
277
+ </div>
278
+ </div>
279
+
280
+ <style>
281
+ /* ========== FONT — Cairo for RTL content (supports Arabic + Latin) ========== */
282
+ article.md-rtl {
283
+ font-family: var(--font-cairo, "Cairo", sans-serif);
284
+ }
285
+
286
+ /* ========== CODE BLOCK WRAPPER (copy button + shiki) ========== */
287
+ article :global(.code-block-wrapper) {
288
+ position: relative;
289
+ margin: 1rem 0;
290
+ }
291
+ article :global(.code-copy-btn) {
292
+ position: absolute;
293
+ top: 8px;
294
+ right: 8px;
295
+ z-index: 2;
296
+ display: flex;
297
+ align-items: center;
298
+ gap: 6px;
299
+ padding: 4px 8px;
300
+ border: none;
301
+ border-radius: 4px;
302
+ background: rgba(255, 255, 255, 0.1);
303
+ color: rgba(255, 255, 255, 0.6);
304
+ cursor: pointer;
305
+ font-size: 11px;
306
+ opacity: 0;
307
+ transition: opacity 0.15s;
308
+ }
309
+ article :global(.code-block-wrapper:hover .code-copy-btn) {
310
+ opacity: 1;
311
+ }
312
+ article :global(.code-copy-btn:hover) {
313
+ background: rgba(255, 255, 255, 0.2);
314
+ color: rgba(255, 255, 255, 0.9);
315
+ }
316
+ article :global(.code-copy-btn.copied) {
317
+ opacity: 1;
318
+ color: #4ade80;
319
+ }
320
+ article :global(.code-copy-btn.copied)::after {
321
+ content: '✓';
322
+ margin-left: 2px;
323
+ }
324
+ article :global(.code-lang) {
325
+ text-transform: uppercase;
326
+ font-weight: 500;
327
+ letter-spacing: 0.03em;
328
+ }
329
+ /* Dark mode: swap copy button colors for light code block bg */
330
+ :global(.dark) article :global(.code-copy-btn) {
331
+ background: rgba(0, 0, 0, 0.1);
332
+ color: rgba(0, 0, 0, 0.5);
333
+ }
334
+ :global(.dark) article :global(.code-copy-btn:hover) {
335
+ background: rgba(0, 0, 0, 0.2);
336
+ color: rgba(0, 0, 0, 0.8);
337
+ }
338
+ :global(.dark) article :global(.code-copy-btn.copied) {
339
+ color: #16a34a;
340
+ }
341
+
342
+ /* ========== CODE BLOCKS — always LTR, reversed theme ========== */
343
+ article :global(pre) {
344
+ direction: ltr;
345
+ text-align: left;
346
+ border-radius: 6px;
347
+ padding: 1rem;
348
+ overflow-x: auto;
349
+ font-size: 0.9em;
350
+ line-height: 1.5;
351
+ }
352
+ /* Fallback for plain pre blocks not styled by Shiki (reversed: dark in light) */
353
+ article :global(pre:not([style])) {
354
+ background-color: #24292e;
355
+ color: #e1e4e8;
356
+ border: 1px solid #444d56;
357
+ }
358
+ article :global(code) {
359
+ direction: ltr;
360
+ text-align: left;
361
+ font-family: 'SF Mono', 'Fira Code', Consolas, Monaco, Menlo, monospace;
362
+ font-size: 0.9em;
363
+ }
364
+ article :global(:not(pre) > code) {
365
+ background-color: rgba(175, 184, 193, 0.2);
366
+ padding: 0.2em 0.4em;
367
+ border-radius: 4px;
368
+ }
369
+ article :global(pre code) {
370
+ background-color: transparent;
371
+ padding: 0;
372
+ color: inherit;
373
+ font-size: inherit;
374
+ }
375
+
376
+ /* ========== TABLES ========== */
377
+ article :global(table) {
378
+ width: 100%;
379
+ max-width: 100%;
380
+ border-collapse: collapse;
381
+ margin: 1rem 0;
382
+ table-layout: fixed;
383
+ }
384
+ article :global(th) {
385
+ padding: 0.5rem;
386
+ text-align: center;
387
+ border-width: 1px;
388
+ border-style: solid;
389
+ word-wrap: break-word;
390
+ overflow-wrap: break-word;
391
+ }
392
+ article :global(td) {
393
+ padding: 0.5rem;
394
+ border: 1px solid #ccc;
395
+ text-align: center;
396
+ word-wrap: break-word;
397
+ overflow-wrap: break-word;
398
+ }
399
+ article :global(tr:nth-child(even)) {
400
+ background-color: #f5f5f5;
401
+ }
402
+
403
+ /* ========== BLOCK ELEMENTS — overflow safety ========== */
404
+ article :global(h1),
405
+ article :global(h2),
406
+ article :global(h3),
407
+ article :global(h4),
408
+ article :global(h5),
409
+ article :global(h6),
410
+ article :global(p),
411
+ article :global(ul),
412
+ article :global(ol),
413
+ article :global(li),
414
+ article :global(blockquote),
415
+ article :global(div),
416
+ article :global(span) {
417
+ max-width: 100%;
418
+ overflow-wrap: break-word;
419
+ }
420
+
421
+ /* ========== LINKS ========== */
422
+ article :global(a) {
423
+ text-decoration: none;
424
+ word-break: break-all;
425
+ }
426
+
427
+ /* ========== MERMAID DIAGRAMS ========== */
428
+ article :global(.mermaid) {
429
+ display: block;
430
+ margin: 1.5rem auto;
431
+ text-align: center;
432
+ direction: ltr;
433
+ max-width: 100%;
434
+ overflow-x: auto;
435
+ }
436
+ article :global(.mermaid svg) {
437
+ display: block;
438
+ margin: 0 auto;
439
+ max-width: 100%;
440
+ width: auto;
441
+ height: auto;
442
+ }
443
+
444
+ /* ========== RTL ADJUSTMENTS ========== */
445
+ article[dir='rtl'] {
446
+ text-align: right;
447
+ }
448
+ article[dir='rtl'] :global(blockquote) {
449
+ border-right-width: 4px;
450
+ border-right-style: solid;
451
+ border-left: none;
452
+ padding-right: 1rem;
453
+ padding-left: 0;
454
+ margin-right: 0;
455
+ }
456
+ article[dir='rtl'] :global(ul),
457
+ article[dir='rtl'] :global(ol) {
458
+ padding-right: 2em;
459
+ padding-left: 0;
460
+ }
461
+
462
+ /* ========== DARK MODE OVERRIDES ========== */
463
+ /* Reversed fallback: light code blocks in dark mode */
464
+ :global(.dark) article :global(pre:not([style])) {
465
+ background-color: #f6f8fa;
466
+ color: #24292e;
467
+ border-color: #e1e4e8;
468
+ }
469
+ :global(.dark) article :global(:not(pre) > code) {
470
+ background-color: rgba(110, 118, 129, 0.3);
471
+ }
472
+ :global(.dark) article :global(td) {
473
+ border-color: #444;
474
+ }
475
+ :global(.dark) article :global(tr:nth-child(even)) {
476
+ background-color: rgba(255, 255, 255, 0.05);
477
+ }
478
+ </style>