@marimo-team/islands 0.16.1 → 0.16.3

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 (238) hide show
  1. package/dist/{ConnectedDataExplorerComponent-DyqLQGPc.js → ConnectedDataExplorerComponent-CareOso9.js} +2 -2
  2. package/dist/{ImageComparisonComponent-CQDGJfUA.js → ImageComparisonComponent-I_Z738Uj.js} +1 -1
  3. package/dist/{_baseUniq-B2Nna6Kt.js → _baseUniq-D-Kb4EU4.js} +1 -1
  4. package/dist/{any-language-editor-D-wq0tOG.js → any-language-editor-BRWmYor8.js} +1 -1
  5. package/dist/{architectureDiagram-W76B3OCA-C6tdnMBf.js → architectureDiagram-W76B3OCA-bZJcJYGH.js} +4 -4
  6. package/dist/assets/{worker-B0C57BK8.js → worker-DMlIUTIq.js} +18 -17
  7. package/dist/{blockDiagram-QIGZ2CNN-IagL8LCN.js → blockDiagram-QIGZ2CNN-DyXjO8fR.js} +5 -5
  8. package/dist/{c4Diagram-FPNF74CW-D3_lIWUP.js → c4Diagram-FPNF74CW-Bfs9ui2r.js} +2 -2
  9. package/dist/{channel-DCJI_DKk.js → channel-CMup9X3Z.js} +1 -1
  10. package/dist/{chunk-4BX2VUAB-B2DrODwN.js → chunk-4BX2VUAB-CW-ni6M_.js} +1 -1
  11. package/dist/{chunk-55IACEB6-BUWDsQ-t.js → chunk-55IACEB6-Bj-Indya.js} +1 -1
  12. package/dist/{chunk-FMBD7UC4-BExPNFv1.js → chunk-FMBD7UC4-9IC8qSSk.js} +1 -1
  13. package/dist/{chunk-K7UQS3LO-Cixi-Yko.js → chunk-K7UQS3LO-aapkEuWN.js} +4 -4
  14. package/dist/{chunk-QN33PNHL-B83MtvER.js → chunk-QN33PNHL-Bo5dJ5T5.js} +1 -1
  15. package/dist/{chunk-QZHKN3VN-CXvbu85X.js → chunk-QZHKN3VN-BkMzjJYY.js} +1 -1
  16. package/dist/{chunk-TVAH2DTR-CpiumCHg.js → chunk-TVAH2DTR-Wqy_C_Rn.js} +3 -3
  17. package/dist/{chunk-TZMSLE5B-DIzaZjcI.js → chunk-TZMSLE5B-DjBmEAUz.js} +1 -1
  18. package/dist/{classDiagram-v2-RKCZMP56-DyN5HPdk.js → classDiagram-KNZD7YFC-DUsaN1O4.js} +2 -2
  19. package/dist/{classDiagram-KNZD7YFC-DyN5HPdk.js → classDiagram-v2-RKCZMP56-DUsaN1O4.js} +2 -2
  20. package/dist/{clone-DrJYap2i.js → clone-Dkt_7KOK.js} +1 -1
  21. package/dist/{cose-bilkent-S5V4N54A-D39b4WrQ.js → cose-bilkent-S5V4N54A-ClBuGZWI.js} +2 -2
  22. package/dist/{dagre-5GWH7T2D-BLjRxDpS.js → dagre-5GWH7T2D-BzmDIGaM.js} +6 -6
  23. package/dist/{data-grid-overlay-editor-DTALqerV.js → data-grid-overlay-editor-NiU9Ea77.js} +2 -2
  24. package/dist/{diagram-N5W7TBWH-MM8AIKGR.js → diagram-N5W7TBWH-BlO1yw_g.js} +5 -5
  25. package/dist/{diagram-QEK2KX5R-BZGarWuJ.js → diagram-QEK2KX5R-BvK83LUx.js} +3 -3
  26. package/dist/{diagram-S2PKOQOG-CnPinN9Q.js → diagram-S2PKOQOG-DvBzRYd7.js} +3 -3
  27. package/dist/{dockerfile-U8DnCJ4X.js → dockerfile-CPQG2tLO.js} +1 -1
  28. package/dist/{erDiagram-AWTI2OKA-CvDVbxOO.js → erDiagram-AWTI2OKA-Doy9FRTX.js} +4 -4
  29. package/dist/{flowDiagram-PVAE7QVJ-C2uuBTZS.js → flowDiagram-PVAE7QVJ-D_tX_HU1.js} +5 -5
  30. package/dist/{ganttDiagram-OWAHRB6G-BEff10RF.js → ganttDiagram-OWAHRB6G-CV03BHVY.js} +4 -4
  31. package/dist/{gitGraphDiagram-NY62KEGX-wggu0kb2.js → gitGraphDiagram-NY62KEGX-w3szEguZ.js} +4 -4
  32. package/dist/{glide-data-editor-Bqh5_dzJ.js → glide-data-editor-akznFrmp.js} +3 -3
  33. package/dist/{graph-DKpp_wzf.js → graph-CjrrDHdT.js} +3 -3
  34. package/dist/index-CIJJs0Tu.js +40382 -0
  35. package/dist/{index-DzJ_YPCG.js → index-DMo6cbcV.js} +3 -3
  36. package/dist/{index-4XruEJkp.js → index-DlV2CtJb.js} +1 -1
  37. package/dist/{index-DdfF_cLK.js → index-Y-Vbae6Z.js} +1 -1
  38. package/dist/{infoDiagram-STP46IZ2-DF7KW-Op.js → infoDiagram-STP46IZ2-BcBV2j75.js} +2 -2
  39. package/dist/{journeyDiagram-BIP6EPQ6-B_jmhmqd.js → journeyDiagram-BIP6EPQ6-BTGMSgvB.js} +3 -3
  40. package/dist/{kanban-definition-6OIFK2YF-B-M9FTyw.js → kanban-definition-6OIFK2YF-aopNqZ1Y.js} +2 -2
  41. package/dist/{layout-C4oVYZZD.js → layout-Dvo9pb_w.js} +4 -4
  42. package/dist/{linear-C-HCGr0T.js → linear-CHnELER9.js} +1 -1
  43. package/dist/{main-B9x2-9f2.js → main-kLZGkzVQ.js} +41787 -40423
  44. package/dist/main.js +1 -1
  45. package/dist/{mermaid-BE4cM3Qs.js → mermaid-DgM4_4bD.js} +30 -30
  46. package/dist/{min-DTpHJ698.js → min-cX4DuL_n.js} +2 -2
  47. package/dist/{mindmap-definition-Q6HEUPPD-Cpd-hO1E.js → mindmap-definition-Q6HEUPPD-DZjbYryy.js} +3 -3
  48. package/dist/{number-overlay-editor-CvURA2Ud.js → number-overlay-editor-8MpIObf7.js} +2 -2
  49. package/dist/{pieDiagram-ADFJNKIX-D9f_f6fn.js → pieDiagram-ADFJNKIX-D6L1IYAc.js} +3 -3
  50. package/dist/{quadrantDiagram-LMRXKWRM-DgllE7xw.js → quadrantDiagram-LMRXKWRM-nOyuc3Bf.js} +2 -2
  51. package/dist/{react-plotly-BU-JRJSi.js → react-plotly-ChkfYiVe.js} +1 -1
  52. package/dist/{requirementDiagram-4UW4RH46-Dk_G8eUb.js → requirementDiagram-4UW4RH46-OVV8wsju.js} +3 -3
  53. package/dist/{sankeyDiagram-GR3RE2ED-BhLIhDc1.js → sankeyDiagram-GR3RE2ED-qZHMdnE_.js} +1 -1
  54. package/dist/{sequenceDiagram-C3RYC4MD-DHoZdMFJ.js → sequenceDiagram-C3RYC4MD-D0bOqf-t.js} +3 -3
  55. package/dist/{slides-component-DXAgdf7K.js → slides-component-CNzLDdA3.js} +1 -1
  56. package/dist/{stateDiagram-KXAO66HF-C1Ie-7Xf.js → stateDiagram-KXAO66HF-CFNCnNJS.js} +4 -4
  57. package/dist/{stateDiagram-v2-UMBNRL4Z--CRuIHtM.js → stateDiagram-v2-UMBNRL4Z-CnIh27m8.js} +2 -2
  58. package/dist/style.css +1 -1
  59. package/dist/{time-yQjlGPwa.js → time-Z7CJSfOW.js} +2 -2
  60. package/dist/{timeline-definition-XQNQX7LJ-D_PjxB1B.js → timeline-definition-XQNQX7LJ-BYLMfrvK.js} +1 -1
  61. package/dist/{treemap-75Q7IDZK--NYqQjUZ.js → treemap-75Q7IDZK-BEh1HacP.js} +5 -5
  62. package/dist/{vega-component-CCUOMM5K.js → vega-component-iMjXd3tD.js} +2 -2
  63. package/dist/{xychartDiagram-6GGTOJPD-WLKsEnzs.js → xychartDiagram-6GGTOJPD-Bmi13ZSG.js} +2 -2
  64. package/package.json +8 -8
  65. package/src/__mocks__/common.ts +5 -3
  66. package/src/__mocks__/notebook.ts +2 -2
  67. package/src/__mocks__/requests.ts +1 -0
  68. package/src/__tests__/main.test.tsx +2 -2
  69. package/src/components/ai/ai-provider-icon.tsx +2 -0
  70. package/src/components/app-config/ai-config.tsx +32 -1
  71. package/src/components/app-config/common.tsx +2 -2
  72. package/src/components/app-config/user-config-form.tsx +26 -0
  73. package/src/components/audio/audio-recorder.tsx +0 -1
  74. package/src/components/chat/acp/blocks.tsx +2 -2
  75. package/src/components/chat/acp/thread.tsx +3 -5
  76. package/src/components/chat/acp/utils.ts +5 -5
  77. package/src/components/chat/chat-panel.tsx +1 -1
  78. package/src/components/data-table/__tests__/columns.test.tsx +38 -0
  79. package/src/components/data-table/__tests__/data-table.test.tsx +2 -2
  80. package/src/components/data-table/cell-hover-template/feature.ts +1 -1
  81. package/src/components/data-table/cell-hover-template/types.ts +1 -1
  82. package/src/components/data-table/charts/__tests__/altair-generator.test.ts +1 -1
  83. package/src/components/data-table/charts/chart-spec/tooltips.ts +3 -3
  84. package/src/components/data-table/charts/components/chart-items.tsx +1 -1
  85. package/src/components/data-table/charts/components/form-fields.tsx +2 -2
  86. package/src/components/data-table/charts/constants.ts +1 -1
  87. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  88. package/src/components/data-table/column-summary/chart-spec-model.tsx +2 -2
  89. package/src/components/data-table/columns.tsx +22 -3
  90. package/src/components/data-table/data-table.tsx +35 -3
  91. package/src/components/data-table/date-popover.tsx +1 -1
  92. package/src/components/data-table/download-actions.tsx +1 -1
  93. package/src/components/data-table/range-focus/__tests__/utils.test.ts +5 -5
  94. package/src/components/data-table/renderers.tsx +22 -13
  95. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
  96. package/src/components/data-table/schemas.ts +16 -0
  97. package/src/components/data-table/types.ts +4 -3
  98. package/src/components/datasources/column-preview.tsx +9 -6
  99. package/src/components/debugger/debugger-code.tsx +1 -1
  100. package/src/components/dependency-graph/custom-node.tsx +15 -6
  101. package/src/components/dependency-graph/dependency-graph-minimap.tsx +2 -2
  102. package/src/components/dependency-graph/dependency-graph-tree.tsx +2 -2
  103. package/src/components/dependency-graph/dependency-graph.tsx +1 -1
  104. package/src/components/dependency-graph/elements.ts +7 -7
  105. package/src/components/dependency-graph/utils/changes.ts +4 -4
  106. package/src/components/editor/Cell.tsx +7 -1
  107. package/src/components/editor/ai/transport/chat-transport.tsx +1 -1
  108. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +1 -1
  109. package/src/components/editor/chrome/panels/packages-panel.tsx +1 -1
  110. package/src/components/editor/columns/storage.ts +1 -1
  111. package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +36 -0
  112. package/src/components/editor/database/__tests__/as-code.test.ts +30 -7
  113. package/src/components/editor/database/add-database-form.tsx +11 -0
  114. package/src/components/editor/database/as-code.ts +104 -5
  115. package/src/components/editor/database/schemas.ts +36 -18
  116. package/src/components/editor/errors/auto-fix.tsx +12 -2
  117. package/src/components/editor/errors/sql-validation-errors.tsx +40 -0
  118. package/src/components/editor/navigation/clipboard.ts +2 -2
  119. package/src/components/editor/output/ConsoleOutput.tsx +14 -2
  120. package/src/components/editor/output/JsonOutput.tsx +1 -1
  121. package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
  122. package/src/components/editor/output/MarimoTracebackOutput.tsx +17 -2
  123. package/src/components/editor/renderers/grid-layout/types.ts +2 -2
  124. package/src/components/editor/renderers/plugins.ts +1 -1
  125. package/src/components/editor/renderers/types.ts +1 -1
  126. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -7
  127. package/src/components/forms/form.tsx +5 -5
  128. package/src/components/ui/links.tsx +1 -0
  129. package/src/core/ai/__tests__/model-registry.test.ts +0 -10
  130. package/src/core/ai/context/providers/cell-output.ts +1 -18
  131. package/src/core/ai/context/providers/error.ts +2 -2
  132. package/src/core/ai/ids/ids.ts +1 -0
  133. package/src/core/ai/model-registry.ts +2 -1
  134. package/src/core/cells/cells.ts +5 -5
  135. package/src/core/cells/logs.ts +1 -1
  136. package/src/core/cells/types.ts +1 -1
  137. package/src/core/codemirror/__tests__/format.test.ts +6 -0
  138. package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
  139. package/src/core/codemirror/editing/commands.ts +2 -2
  140. package/src/core/codemirror/find-replace/navigate.ts +1 -1
  141. package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
  142. package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
  143. package/src/core/codemirror/language/__tests__/sql.test.ts +764 -79
  144. package/src/core/codemirror/language/languages/markdown.ts +4 -1
  145. package/src/core/codemirror/language/languages/sql/banner-validation-errors.ts +85 -0
  146. package/src/core/codemirror/language/languages/sql/completion-builder.ts +160 -0
  147. package/src/core/codemirror/language/languages/sql/completion-sources.tsx +9 -3
  148. package/src/core/codemirror/language/languages/sql/completion-store.ts +46 -50
  149. package/src/core/codemirror/language/languages/sql/renderers.tsx +485 -0
  150. package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
  151. package/src/core/codemirror/language/languages/sql/sql.ts +218 -4
  152. package/src/core/codemirror/language/languages/sql/utils.ts +4 -1
  153. package/src/core/codemirror/language/panel/panel.tsx +8 -2
  154. package/src/core/codemirror/language/panel/sql.tsx +86 -4
  155. package/src/core/codemirror/language/utils/ast.ts +3 -3
  156. package/src/core/codemirror/lsp/federated-lsp.ts +4 -4
  157. package/src/core/codemirror/lsp/lens.ts +4 -4
  158. package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
  159. package/src/core/codemirror/lsp/types.ts +1 -1
  160. package/src/core/codemirror/markdown/completions.ts +1 -1
  161. package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
  162. package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
  163. package/src/core/config/config-schema.ts +1 -0
  164. package/src/core/config/feature-flag.tsx +6 -2
  165. package/src/core/datasets/request-registry.ts +24 -1
  166. package/src/core/dom/events.ts +1 -1
  167. package/src/core/dom/outline.ts +2 -2
  168. package/src/core/dom/uiregistry.ts +2 -8
  169. package/src/core/errors/__tests__/errors.test.ts +22 -4
  170. package/src/core/errors/errors.ts +29 -1
  171. package/src/core/errors/state.ts +1 -1
  172. package/src/core/islands/bridge.ts +1 -0
  173. package/src/core/islands/main.ts +3 -2
  174. package/src/core/islands/parse.ts +1 -3
  175. package/src/core/kernel/messages.ts +2 -1
  176. package/src/core/network/CachingRequestRegistry.ts +74 -0
  177. package/src/core/network/DeferredRequestRegistry.ts +3 -1
  178. package/src/core/network/__tests__/CachingRequestRegistry.test.ts +73 -0
  179. package/src/core/network/requests-network.ts +7 -0
  180. package/src/core/network/requests-static.ts +1 -0
  181. package/src/core/network/requests-toasting.ts +1 -0
  182. package/src/core/network/types.ts +3 -1
  183. package/src/core/variables/state.ts +2 -2
  184. package/src/core/wasm/__tests__/state.test.ts +1 -1
  185. package/src/core/wasm/bridge.ts +5 -0
  186. package/src/core/websocket/useMarimoWebSocket.tsx +9 -2
  187. package/src/custom.d.ts +1 -1
  188. package/src/hooks/useCellRenderCount.ts +1 -0
  189. package/src/hooks/useResizeHandle.ts +4 -1
  190. package/src/plugins/core/RenderHTML.tsx +1 -2
  191. package/src/plugins/core/registerReactComponent.tsx +23 -19
  192. package/src/plugins/impl/DataTablePlugin.tsx +18 -6
  193. package/src/plugins/impl/FileUploadPlugin.tsx +1 -1
  194. package/src/plugins/impl/RefreshPlugin.tsx +1 -1
  195. package/src/plugins/impl/SliderPlugin.tsx +4 -0
  196. package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +27 -9
  197. package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +58 -2
  198. package/src/plugins/impl/anywidget/__tests__/model.test.ts +3 -4
  199. package/src/plugins/impl/anywidget/model.ts +2 -3
  200. package/src/plugins/impl/data-editor/types.ts +1 -1
  201. package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
  202. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
  203. package/src/plugins/impl/data-frames/types.ts +1 -1
  204. package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
  205. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +3 -3
  206. package/src/plugins/impl/vega/__tests__/loader.test.ts +2 -2
  207. package/src/plugins/impl/vega/loader.ts +1 -1
  208. package/src/plugins/impl/vega/vega-component.tsx +1 -1
  209. package/src/plugins/impl/vega/vega-loader.ts +2 -2
  210. package/src/plugins/layout/NavigationMenuPlugin.tsx +1 -1
  211. package/src/plugins/layout/RoutesPlugin.tsx +1 -2
  212. package/src/plugins/plugins.ts +2 -2
  213. package/src/stories/dataframe.stories.tsx +2 -0
  214. package/src/utils/Logger.ts +1 -1
  215. package/src/utils/__tests__/data-views.test.ts +30 -68
  216. package/src/utils/__tests__/dom.test.ts +167 -0
  217. package/src/utils/__tests__/id-tree.test.ts +49 -1
  218. package/src/utils/__tests__/storage.test.ts +1 -1
  219. package/src/utils/__tests__/traceback.test.ts +13 -2
  220. package/src/utils/arrays.ts +1 -1
  221. package/src/utils/createReducer.ts +1 -5
  222. package/src/utils/data-views.ts +6 -19
  223. package/src/utils/dom.ts +55 -0
  224. package/src/utils/edit-distance.ts +1 -1
  225. package/src/utils/fileToBase64.ts +1 -1
  226. package/src/utils/id-tree.tsx +20 -18
  227. package/src/utils/json/base64.ts +13 -0
  228. package/src/utils/json/json-parser.ts +2 -2
  229. package/src/utils/lru.ts +4 -0
  230. package/src/utils/mergeRefs.ts +1 -1
  231. package/src/utils/objects.ts +3 -3
  232. package/src/utils/pluralize.ts +1 -1
  233. package/src/utils/routes.ts +2 -2
  234. package/src/utils/sets.ts +1 -1
  235. package/src/utils/traceback.ts +45 -15
  236. package/src/utils/tracer.ts +11 -9
  237. package/dist/index-DW0BCGJE.js +0 -40315
  238. package/src/__tests__/lru.test.ts +0 -74
@@ -0,0 +1,485 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import {
4
+ ColumnsIcon,
5
+ DatabaseIcon,
6
+ EyeIcon,
7
+ HashIcon,
8
+ InfoIcon,
9
+ KeyIcon,
10
+ LayersIcon,
11
+ TableIcon,
12
+ } from "lucide-react";
13
+ import type React from "react";
14
+ import { DATA_TYPE_ICON } from "@/components/datasets/icons";
15
+ import { Badge } from "@/components/ui/badge";
16
+ import type {
17
+ Database,
18
+ DatabaseSchema,
19
+ DataTable,
20
+ DataTableColumn,
21
+ DataType,
22
+ } from "@/core/kernel/messages";
23
+
24
+ // Configuration constants
25
+ const PREVIEW_ITEM_LIMIT = 5;
26
+
27
+ // Color mappings for data types (Tailwind-safe)
28
+ const DATA_TYPE_COLORS: Record<DataType, string> = {
29
+ boolean: "bg-[var(--orange-4)] text-[var(--orange-11)]",
30
+ date: "bg-[var(--grass-4)] text-[var(--grass-11)]",
31
+ time: "bg-[var(--grass-4)] text-[var(--grass-11)]",
32
+ datetime: "bg-[var(--grass-4)] text-[var(--grass-11)]",
33
+ number: "bg-[var(--purple-4)] text-[var(--purple-11)]",
34
+ integer: "bg-[var(--purple-4)] text-[var(--purple-11)]",
35
+ string: "bg-[var(--blue-4)] text-[var(--blue-11)]",
36
+ unknown: "bg-[var(--slate-4)] text-[var(--slate-11)]",
37
+ };
38
+
39
+ // Source type colors
40
+ const SOURCE_TYPE_COLORS = {
41
+ local: "bg-[var(--blue-4)] text-[var(--blue-11)]",
42
+ duckdb: "bg-[var(--amber-4)] text-[var(--amber-11)]",
43
+ connection: "bg-[var(--green-4)] text-[var(--green-11)]",
44
+ catalog: "bg-[var(--purple-4)] text-[var(--purple-11)]",
45
+ } as const;
46
+
47
+ const CONTAINER_STYLES = "p-3 min-w-[250px] flex flex-col divide-y";
48
+
49
+ // Helper components and functions
50
+ const SectionHeader: React.FC<{
51
+ icon: React.ReactNode;
52
+ title: string;
53
+ badge?: React.ReactNode;
54
+ }> = ({ icon, title, badge }) => (
55
+ <div className="flex items-center gap-2 pb-2">
56
+ {icon}
57
+ <h3 className="font-semibold text-sm">{title}</h3>
58
+ {badge}
59
+ </div>
60
+ );
61
+
62
+ const MetadataRow: React.FC<{
63
+ label: string;
64
+ value: React.ReactNode;
65
+ }> = ({ label, value }) => (
66
+ <div className="flex items-center justify-between text-xs">
67
+ <span className="text-[var(--slate-11)]">{label}:</span>
68
+ {value}
69
+ </div>
70
+ );
71
+
72
+ const StatisticItem: React.FC<{
73
+ icon: React.ReactNode;
74
+ text: string;
75
+ }> = ({ icon, text }) => (
76
+ <div className="flex items-center gap-1">
77
+ {icon}
78
+ <span className="text-xs text-[var(--slate-11)]">{text}</span>
79
+ </div>
80
+ );
81
+
82
+ const PreviewList: React.FC<{
83
+ title?: string;
84
+ items: React.ReactNode[];
85
+ totalCount: number;
86
+ limit?: number;
87
+ }> = ({ title = "", items, totalCount, limit = PREVIEW_ITEM_LIMIT }) => {
88
+ const visibleItems = items.slice(0, limit);
89
+ const hasMore = totalCount > limit;
90
+
91
+ return (
92
+ <div className="py-2">
93
+ {title && (
94
+ <h4 className="text-xs font-medium text-[var(--slate-11)] mb-2">
95
+ {title}:
96
+ </h4>
97
+ )}
98
+ <div className="flex flex-col gap-1 overflow-y-auto">
99
+ {visibleItems}
100
+ {hasMore && (
101
+ <div className="text-xs text-[var(--slate-10)] text-center py-1">
102
+ ... and {totalCount - limit} more
103
+ </div>
104
+ )}
105
+ </div>
106
+ </div>
107
+ );
108
+ };
109
+
110
+ const getDataTypeColorClass = (dataType: DataType): string => {
111
+ return DATA_TYPE_COLORS[dataType] || DATA_TYPE_COLORS.unknown;
112
+ };
113
+
114
+ export const renderTableInfo = (table: DataTable): React.ReactNode => {
115
+ const tableIcon =
116
+ table.type === "view" ? (
117
+ <EyeIcon className="w-4 h-4 text-[var(--blue-9)]" />
118
+ ) : (
119
+ <TableIcon className="w-4 h-4 text-[var(--green-9)]" />
120
+ );
121
+
122
+ const typeBadge = (
123
+ <Badge
124
+ variant="secondary"
125
+ className={`text-xs ${
126
+ table.type === "view"
127
+ ? "bg-[var(--blue-4)] text-[var(--blue-11)]"
128
+ : "bg-[var(--green-4)] text-[var(--green-11)]"
129
+ }`}
130
+ >
131
+ {table.type}
132
+ </Badge>
133
+ );
134
+
135
+ const columnItems = table.columns.map((column) => {
136
+ const TypeIcon = DATA_TYPE_ICON[column.type];
137
+ return (
138
+ <div
139
+ key={column.name}
140
+ className="flex items-center justify-between text-xs rounded"
141
+ >
142
+ <div className="flex items-center gap-2">
143
+ <TypeIcon className="w-3 h-3 text-[var(--slate-9)]" />
144
+ <span className="font-mono">{column.name}</span>
145
+ </div>
146
+ <Badge
147
+ variant="outline"
148
+ className={`text-xs ${getDataTypeColorClass(column.type)}`}
149
+ >
150
+ {column.type}
151
+ </Badge>
152
+ </div>
153
+ );
154
+ });
155
+
156
+ const hasPrimaryKeys = table.primary_keys && table.primary_keys.length > 0;
157
+ const hasIndexes = table.indexes && table.indexes.length > 0;
158
+
159
+ return (
160
+ <div className={`${CONTAINER_STYLES} min-w-[300px]`}>
161
+ <SectionHeader icon={tableIcon} title={table.name} badge={typeBadge} />
162
+
163
+ {/* Metadata */}
164
+ <div className="flex flex-col gap-2 py-2">
165
+ <MetadataRow
166
+ label="Source"
167
+ value={
168
+ <Badge
169
+ variant="outline"
170
+ className={`text-xs ${SOURCE_TYPE_COLORS[table.source_type]}`}
171
+ >
172
+ {table.source}
173
+ </Badge>
174
+ }
175
+ />
176
+
177
+ {table.variable_name && (
178
+ <MetadataRow
179
+ label="Variable"
180
+ value={
181
+ <code className="text-xs bg-[var(--slate-4)] px-1 rounded">
182
+ {table.variable_name}
183
+ </code>
184
+ }
185
+ />
186
+ )}
187
+
188
+ {table.engine && (
189
+ <MetadataRow
190
+ label="Engine"
191
+ value={
192
+ <code className="text-xs bg-[var(--slate-4)] px-1 rounded">
193
+ {table.engine}
194
+ </code>
195
+ }
196
+ />
197
+ )}
198
+ </div>
199
+
200
+ {/* Statistics */}
201
+ {(table.num_columns != null || table.num_rows != null) && (
202
+ <div className="grid grid-cols-2 gap-2 py-2">
203
+ {table.num_columns != null && (
204
+ <StatisticItem
205
+ icon={<ColumnsIcon className="w-3 h-3 text-[var(--slate-9)]" />}
206
+ text={`${table.num_columns} columns`}
207
+ />
208
+ )}
209
+ {table.num_rows != null && (
210
+ <StatisticItem
211
+ icon={<HashIcon className="w-3 h-3 text-[var(--slate-9)]" />}
212
+ text={`${table.num_rows} rows`}
213
+ />
214
+ )}
215
+ </div>
216
+ )}
217
+
218
+ {/* Empty Info */}
219
+ {table.columns.length === 0 && renderEmptyInfo("column")}
220
+
221
+ {/* Primary Keys & Indexes */}
222
+ {(hasPrimaryKeys || hasIndexes) && (
223
+ <div className="flex flex-col gap-2 py-2">
224
+ {hasPrimaryKeys && (
225
+ <div className="flex flex-row gap-1">
226
+ <div className="flex items-center gap-1">
227
+ <KeyIcon className="w-3 h-3 text-[var(--amber-9)]" />
228
+ <span className="text-xs font-medium text-[var(--slate-11)]">
229
+ Primary Keys:
230
+ </span>
231
+ </div>
232
+ {table.primary_keys?.map((key) => (
233
+ <Badge
234
+ key={key}
235
+ variant="outline"
236
+ className="text-xs text-[var(--slate-11)]"
237
+ >
238
+ {key}
239
+ </Badge>
240
+ ))}
241
+ </div>
242
+ )}
243
+
244
+ {hasIndexes && (
245
+ <div className="flex flex-row gap-1">
246
+ <div className="flex items-center gap-1 mb-1">
247
+ <LayersIcon className="w-3 h-3 text-[var(--purple-9)]" />
248
+ <span className="text-xs font-medium text-[var(--slate-11)]">
249
+ Indexes:
250
+ </span>
251
+ </div>
252
+ {table.indexes?.map((index) => (
253
+ <Badge
254
+ key={index}
255
+ variant="outline"
256
+ className="text-xs text-[var(--slate-11)]"
257
+ >
258
+ {index}
259
+ </Badge>
260
+ ))}
261
+ </div>
262
+ )}
263
+ </div>
264
+ )}
265
+
266
+ {/* Sample Columns Preview */}
267
+ {table.columns.length > 0 && (
268
+ <PreviewList items={columnItems} totalCount={table.columns.length} />
269
+ )}
270
+ </div>
271
+ );
272
+ };
273
+
274
+ export const renderColumnInfo = (column: DataTableColumn): React.ReactNode => {
275
+ const TypeIcon = DATA_TYPE_ICON[column.type];
276
+
277
+ const typeBadge = (
278
+ <Badge
279
+ variant="outline"
280
+ className={`text-xs ${getDataTypeColorClass(column.type)}`}
281
+ >
282
+ {column.type}
283
+ </Badge>
284
+ );
285
+
286
+ const sampleItems =
287
+ column.sample_values?.map((value, index) => (
288
+ <div
289
+ key={index}
290
+ className="text-xs bg-[var(--slate-3)] rounded font-mono"
291
+ >
292
+ {value === null || value === undefined ? "null" : String(value)}
293
+ </div>
294
+ )) || [];
295
+
296
+ return (
297
+ <div className={CONTAINER_STYLES}>
298
+ <SectionHeader
299
+ icon={<TypeIcon className="w-4 h-4 text-[var(--slate-9)]" />}
300
+ title={column.name}
301
+ badge={typeBadge}
302
+ />
303
+
304
+ {/* Type Information */}
305
+ <div className="flex flex-col gap-2 mt-2">
306
+ <MetadataRow
307
+ label="Type"
308
+ value={<span className="font-medium">{column.type}</span>}
309
+ />
310
+ <MetadataRow
311
+ label="External Type"
312
+ value={
313
+ <code className="text-xs bg-[var(--slate-4)] px-1 rounded">
314
+ {column.external_type}
315
+ </code>
316
+ }
317
+ />
318
+ </div>
319
+
320
+ {/* Sample Values */}
321
+ {column.sample_values && column.sample_values.length > 0 && (
322
+ <PreviewList
323
+ title="Sample Values"
324
+ items={sampleItems}
325
+ totalCount={column.sample_values.length}
326
+ />
327
+ )}
328
+ </div>
329
+ );
330
+ };
331
+
332
+ export const renderDatabaseInfo = (database: Database): React.ReactNode => {
333
+ const dialectBadge = (
334
+ <Badge
335
+ variant="outline"
336
+ className="text-xs bg-[var(--blue-4)] text-[var(--blue-11)]"
337
+ >
338
+ {database.dialect}
339
+ </Badge>
340
+ );
341
+
342
+ const schemaItems = database.schemas.map((schema) => (
343
+ <div
344
+ key={schema.name}
345
+ className="flex items-center justify-between text-xs rounded hover:bg-[var(--slate-3)]"
346
+ >
347
+ <div className="flex items-center gap-2">
348
+ <LayersIcon className="w-3 h-3 text-[var(--slate-9)]" />
349
+ <span>{schema.name}</span>
350
+ </div>
351
+ <Badge variant="outline" className="text-xs">
352
+ {schema.tables.length} tables
353
+ </Badge>
354
+ </div>
355
+ ));
356
+
357
+ return (
358
+ <div className={CONTAINER_STYLES}>
359
+ <SectionHeader
360
+ icon={<DatabaseIcon className="w-4 h-4 text-[var(--blue-9)]" />}
361
+ title={database.name}
362
+ badge={dialectBadge}
363
+ />
364
+ {/* Metadata */}
365
+ <div className="flex flex-col gap-2 py-2">
366
+ <MetadataRow
367
+ label="Dialect"
368
+ value={<span className="font-medium">{database.dialect}</span>}
369
+ />
370
+
371
+ {database.engine && (
372
+ <MetadataRow
373
+ label="Engine"
374
+ value={
375
+ <code className="text-xs bg-[var(--slate-4)] px-1 rounded">
376
+ {database.engine}
377
+ </code>
378
+ }
379
+ />
380
+ )}
381
+ </div>
382
+ {/* Schema Statistics */}
383
+ <div className="py-2">
384
+ <StatisticItem
385
+ icon={<LayersIcon className="w-3 h-3 text-[var(--slate-9)]" />}
386
+ text={`${database.schemas.length} schema${database.schemas.length === 1 ? "" : "s"}`}
387
+ />
388
+ </div>
389
+ {/* Empty Info */}
390
+ {database.schemas.length === 0 && renderEmptyInfo("schema")}
391
+
392
+ {/* Schema Preview */}
393
+ {database.schemas.length > 0 && (
394
+ <PreviewList
395
+ title="Schemas"
396
+ items={schemaItems}
397
+ totalCount={database.schemas.length}
398
+ />
399
+ )}
400
+ </div>
401
+ );
402
+ };
403
+
404
+ export const renderSchemaInfo = (schema: DatabaseSchema): React.ReactNode => {
405
+ const schemaBadge = (
406
+ <Badge
407
+ variant="outline"
408
+ className="text-xs bg-[var(--green-4)] text-[var(--green-11)]"
409
+ >
410
+ Schema
411
+ </Badge>
412
+ );
413
+
414
+ const tableItems = schema.tables.map((table) => (
415
+ <div
416
+ key={table.name}
417
+ className="flex items-center justify-between text-xs rounded hover:bg-[var(--slate-3)]"
418
+ >
419
+ <div className="flex items-center gap-2">
420
+ {table.type === "view" ? (
421
+ <EyeIcon className="w-3 h-3 text-[var(--blue-9)]" />
422
+ ) : (
423
+ <TableIcon className="w-3 h-3 text-[var(--green-9)]" />
424
+ )}
425
+ <span>{table.name}</span>
426
+ </div>
427
+ <Badge
428
+ variant="outline"
429
+ className={`text-xs ${
430
+ table.type === "view"
431
+ ? "bg-[var(--blue-4)] text-[var(--blue-11)]"
432
+ : "bg-[var(--green-4)] text-[var(--green-11)]"
433
+ }`}
434
+ >
435
+ {table.type}
436
+ </Badge>
437
+ </div>
438
+ ));
439
+
440
+ return (
441
+ <div className={CONTAINER_STYLES}>
442
+ <SectionHeader
443
+ icon={<LayersIcon className="w-4 h-4 text-[var(--green-9)]" />}
444
+ title={schema.name}
445
+ badge={schemaBadge}
446
+ />
447
+
448
+ {/* Table Statistics */}
449
+ <div className="py-2">
450
+ <StatisticItem
451
+ icon={<TableIcon className="w-3 h-3 text-[var(--slate-9)]" />}
452
+ text={`${schema.tables.length} table${schema.tables.length === 1 ? "" : "s"}`}
453
+ />
454
+ </div>
455
+
456
+ {/* Empty Info */}
457
+ {schema.tables.length === 0 && renderEmptyInfo("table")}
458
+
459
+ {/* Table Preview */}
460
+ {schema.tables.length > 0 && (
461
+ <PreviewList
462
+ title="Tables"
463
+ items={tableItems}
464
+ totalCount={schema.tables.length}
465
+ />
466
+ )}
467
+ </div>
468
+ );
469
+ };
470
+
471
+ export const renderEmptyInfo = (
472
+ type: "column" | "table" | "schema" | "database",
473
+ ) => {
474
+ return (
475
+ <div className="flex items-start gap-2 mt-3">
476
+ <InfoIcon size={10} className="mt-1 text-[var(--slate-10)] shrink-0" />
477
+ <span className="text-xs text-[var(--slate-11)]">
478
+ No {type} information available.{" \n"}
479
+ <span className="text-[var(--blue-10)]">
480
+ Introspect to see more details.
481
+ </span>
482
+ </span>
483
+ </div>
484
+ );
485
+ };
@@ -0,0 +1,20 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import { useAtom } from "jotai";
4
+ import { atomWithStorage } from "jotai/utils";
5
+ import { store } from "@/core/state/jotai";
6
+
7
+ const BASE_KEY = "marimo:notebook-sql-mode";
8
+
9
+ export type SQLMode = "validate" | "default";
10
+
11
+ const sqlModeAtom = atomWithStorage<SQLMode>(BASE_KEY, "default");
12
+
13
+ export function useSQLMode() {
14
+ const [sqlMode, setSQLMode] = useAtom(sqlModeAtom);
15
+ return { sqlMode, setSQLMode };
16
+ }
17
+
18
+ export function getSQLMode() {
19
+ return store.get(sqlModeAtom);
20
+ }