@marimo-team/islands 0.23.10-dev9 → 0.23.11-dev67

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 (188) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CyV83R2m.js → ConnectedDataExplorerComponent-Z3RP7Vmm.js} +31 -31
  2. package/dist/{ErrorBoundary-rULOrC_p.js → ErrorBoundary-DpbaKVv7.js} +1 -1
  3. package/dist/{any-language-editor-CiES2a2h.js → any-language-editor-CAgFD4Kd.js} +20 -20
  4. package/dist/assets/__vite-browser-external-eshhtsgZ.js +1 -0
  5. package/dist/assets/worker-CC0Oul9k.js +73 -0
  6. package/dist/{chat-ui-K84W5ecY.js → chat-ui-C4-GMW9y.js} +77 -77
  7. package/dist/{check-DTbrK0zt.js → check-BCaJeT-J.js} +1 -1
  8. package/dist/{chunk-5FQGJX7Z-BNjes6Yx.js → chunk-5FQGJX7Z-BbqSm5gU.js} +1227 -1222
  9. package/dist/{code-block-37QAKDTI-m92Yc8pv.js → code-block-37QAKDTI-O6IH6wAi.js} +1 -1
  10. package/dist/{code-visibility-v6ucEVUg.js → code-visibility-UH2371Sv.js} +1943 -1223
  11. package/dist/{copy-5jQ_kGE1.js → copy-UqRYxiOg.js} +1 -1
  12. package/dist/dist-7QfXoMdB.js +5 -0
  13. package/dist/{dist-DgnE8F-r.js → dist-A2846XWO.js} +1 -1
  14. package/dist/dist-BEXXyZig.js +5 -0
  15. package/dist/{dist-B3pZ0Ab6.js → dist-BR_gyG9L.js} +3 -3
  16. package/dist/{dist-CcXxepx6.js → dist-BSAt6RhH.js} +27 -27
  17. package/dist/{dist-Bde4a2kU.js → dist-BY018Paw.js} +8 -8
  18. package/dist/dist-BYj57OV4.js +5 -0
  19. package/dist/{dist-CUCNs1ja.js → dist-BaoDKvdy.js} +2 -2
  20. package/dist/{dist-Cy1WxgBD.js → dist-Bf7SHuNp.js} +5 -5
  21. package/dist/{dist-Bz_sYWbr.js → dist-Bk75fBZA.js} +2 -2
  22. package/dist/dist-BlSvQzNr.js +5 -0
  23. package/dist/{dist-C5VC_yzu.js → dist-BzEzfugY.js} +1 -1
  24. package/dist/dist-CCBlxAgS.js +8 -0
  25. package/dist/dist-CIDTVIUf.js +5 -0
  26. package/dist/{dist-CLUtPrdy.js → dist-CIYBwstr.js} +1 -1
  27. package/dist/{dist-BotSqB48.js → dist-C_Y3oV3C.js} +12 -12
  28. package/dist/{dist-BTfv03uy.js → dist-CcWX6tmx.js} +2 -2
  29. package/dist/{dist-BhM8gdSO.js → dist-CoXAujgg.js} +4 -4
  30. package/dist/{dist-4j4c7bjm.js → dist-CpxNdDkw.js} +3 -3
  31. package/dist/dist-CqQyhAM8.js +8 -0
  32. package/dist/dist-CwRu2Xzh.js +5 -0
  33. package/dist/{dist-BcuoonNH.js → dist-CxJDU6Bh.js} +9 -9
  34. package/dist/{dist-DxvORzUR.js → dist-D-W5ny5a.js} +8 -8
  35. package/dist/dist-D8CDTVgf.js +6 -0
  36. package/dist/dist-D8DNB0nO.js +8 -0
  37. package/dist/dist-DL6N_q-A.js +5 -0
  38. package/dist/{dist-BbbIBDiQ.js → dist-DMjWuVs8.js} +1 -1
  39. package/dist/dist-DOFbNV_b.js +8 -0
  40. package/dist/dist-DPrYzMY0.js +6 -0
  41. package/dist/{dist-h2c8sZvT.js → dist-DZORgqKY.js} +1 -1
  42. package/dist/{dist-B3P2fFpz.js → dist-DZo4nSS0.js} +14 -14
  43. package/dist/{dist-D4CewLk6.js → dist-Dax--nl9.js} +1 -1
  44. package/dist/{dist-DRfcqpxJ.js → dist-DgGbNavJ.js} +2 -2
  45. package/dist/{dist-C1BYNeCR.js → dist-Dk6PV_d3.js} +10 -10
  46. package/dist/{dist-fQ0ViXGs.js → dist-Dv_Y15yk.js} +107 -107
  47. package/dist/{dist-Bfwsv11D.js → dist-DyyjKEYf.js} +2 -2
  48. package/dist/{dist-p2qyWijU.js → dist-GZXUmt0b.js} +2 -2
  49. package/dist/{dist-CLJWPTX2.js → dist-LTU8Hdvn.js} +3 -3
  50. package/dist/{dist-DqAWR3CS.js → dist-M9Vag9Y0.js} +20 -20
  51. package/dist/{dist-DNdhYsgW.js → dist-U4F-tbMs.js} +79 -62
  52. package/dist/{dist-RqXTaiir.js → dist-abid3KgM.js} +11 -11
  53. package/dist/dist-cdmMjgsn.js +5 -0
  54. package/dist/dist-hT4QzYX-.js +1247 -0
  55. package/dist/{dist-luvabDEB.js → dist-t9Kf7xqC.js} +2 -2
  56. package/dist/{error-banner-5bz0L9hS.js → error-banner-CJXYJ6Sb.js} +11 -6
  57. package/dist/esm-BaH2eg5-.js +1171 -0
  58. package/dist/{esm-Duie8iU-.js → esm-ga2Bf3O2.js} +43 -43
  59. package/dist/{extends-CkydH1Q5.js → extends-D_hDsj6R.js} +4 -4
  60. package/dist/files/wasm-intro.py +11 -8
  61. package/dist/{formats-DHxc-FdY.js → formats-C4wO47tk.js} +1 -1
  62. package/dist/{glide-data-editor-CgIxTzAP.js → glide-data-editor-BPkCPs7L.js} +255 -255
  63. package/dist/{html-to-image-B93KtAVY.js → html-to-image-BwfcJJxA.js} +2412 -2282
  64. package/dist/{input-_2sjvfne.js → input-OdWHkobi.js} +263 -245
  65. package/dist/{label-LWtdw5i8.js → label-CC4ytI1X.js} +1 -1
  66. package/dist/main.js +7630 -7558
  67. package/dist/{mermaid-4DMBBIKO-DIdL224_.js → mermaid-4DMBBIKO-Eg3D4FVz.js} +1 -1
  68. package/dist/{mermaid-lXOw5Py9.js → mermaid-BotvIKg9.js} +4 -4
  69. package/dist/{process-output-BOXi9fnS.js → process-output-DsloEDna.js} +3 -3
  70. package/dist/{reveal-component-gRcjQbNL.js → reveal-component-BNU1V1x5.js} +698 -620
  71. package/dist/{spec-B96zNUEA.js → spec-X7FwLJni.js} +4 -4
  72. package/dist/{strings-Bu3vlb6W.js → strings-J57tzLr3.js} +47 -46
  73. package/dist/style.css +1 -1
  74. package/dist/{toDate-x-WRDCH7.js → toDate-d8RCRrRd.js} +2 -2
  75. package/dist/{tooltip-C5FYOpQc.js → tooltip-DpcyNkQ2.js} +2 -2
  76. package/dist/{types-CVvp1fKr.js → types-ChtMFmZ2.js} +1 -1
  77. package/dist/{useAsyncData-iRgKDT5s.js → useAsyncData-PonK__yh.js} +1 -1
  78. package/dist/{useDateFormatter-BA4FCquG.js → useDateFormatter-QB-3MpYr.js} +2 -2
  79. package/dist/{useDeepCompareMemoize-CkQ57VS2.js → useDeepCompareMemoize-D3NGWke6.js} +1 -1
  80. package/dist/{useLifecycle-BBO9PIph.js → useLifecycle-00mO3OSS.js} +2 -2
  81. package/dist/{useTheme-DHIrRQOe.js → useTheme-DEhDzATN.js} +1 -1
  82. package/dist/{vega-component-Dq-SH463.js → vega-component-DGPUhbDs.js} +8 -8
  83. package/dist/{zod-CoBiJ5v4.js → zod-aLSua2NL.js} +24 -23
  84. package/package.json +4 -3
  85. package/src/__tests__/setup.ts +16 -0
  86. package/src/components/chat/chat-display.tsx +2 -2
  87. package/src/components/data-table/TableBottomBar.tsx +1 -15
  88. package/src/components/data-table/TableTopBar.tsx +8 -13
  89. package/src/components/data-table/__tests__/TableBottomBar.test.tsx +6 -12
  90. package/src/components/data-table/__tests__/column-visibility-dropdown.test.tsx +227 -0
  91. package/src/components/data-table/column-visibility-dropdown.tsx +204 -0
  92. package/src/components/data-table/data-table.tsx +1 -1
  93. package/src/components/data-table/filter-by-values-picker.tsx +39 -17
  94. package/src/components/data-table/filter-pills.tsx +1 -1
  95. package/src/components/datasources/__tests__/filter-empty.test.ts +183 -0
  96. package/src/components/datasources/datasources.tsx +92 -3
  97. package/src/components/editor/cell/code/cell-editor.tsx +70 -32
  98. package/src/components/editor/cell/code/code-placeholder.css +18 -0
  99. package/src/components/editor/cell/code/code-placeholder.tsx +47 -0
  100. package/src/components/editor/cell/code/language-toggle.tsx +7 -1
  101. package/src/components/editor/chrome/wrapper/app-chrome.tsx +97 -52
  102. package/src/components/editor/chrome/wrapper/lazy-panels.ts +91 -0
  103. package/src/components/editor/chrome/wrapper/sidebar.tsx +2 -0
  104. package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +9 -2
  105. package/src/components/editor/connections/storage/__tests__/as-code.test.ts +62 -27
  106. package/src/components/editor/connections/storage/add-storage-form.tsx +5 -1
  107. package/src/components/editor/connections/storage/as-code.ts +20 -6
  108. package/src/components/editor/documentation.css +35 -0
  109. package/src/components/editor/file-tree/file-explorer.tsx +8 -18
  110. package/src/components/editor/file-tree/tree-actions.tsx +46 -1
  111. package/src/components/editor/notebook-cell.tsx +3 -3
  112. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +20 -0
  113. package/src/components/editor/renderers/slides-layout/types.ts +1 -0
  114. package/src/components/markdown/__tests__/markdown-renderer.test.tsx +43 -0
  115. package/src/components/markdown/markdown-renderer.tsx +24 -1
  116. package/src/components/slides/__tests__/minimap-actions.test.tsx +166 -0
  117. package/src/components/slides/__tests__/reveal-component.test.ts +425 -0
  118. package/src/components/slides/minimap.tsx +127 -10
  119. package/src/components/slides/reveal-component.tsx +287 -61
  120. package/src/components/slides/slide-cell-view.tsx +26 -2
  121. package/src/components/slides/slide-form.tsx +26 -4
  122. package/src/components/storage/__tests__/storage-inspector.test.ts +180 -0
  123. package/src/components/storage/storage-inspector.tsx +535 -81
  124. package/src/components/ui/combobox.tsx +51 -32
  125. package/src/components/ui/number-field.tsx +5 -1
  126. package/src/components/ui/reorderable-list.tsx +13 -0
  127. package/src/components/ui/select-core/__tests__/use-select-list.test.ts +294 -0
  128. package/src/components/ui/select-core/__tests__/utils.test.ts +222 -0
  129. package/src/components/ui/select-core/index.ts +16 -0
  130. package/src/components/ui/select-core/option-row.tsx +33 -0
  131. package/src/components/ui/select-core/render-slot.ts +20 -0
  132. package/src/components/ui/select-core/select-list.tsx +248 -0
  133. package/src/components/ui/select-core/types.ts +44 -0
  134. package/src/components/ui/select-core/use-select-list.ts +347 -0
  135. package/src/components/ui/select-core/utils.ts +121 -0
  136. package/src/components/ui/toast.tsx +1 -0
  137. package/src/core/cells/__tests__/document-changes.test.ts +2 -2
  138. package/src/core/cells/__tests__/focus.test.ts +45 -2
  139. package/src/core/cells/focus.ts +1 -1
  140. package/src/core/cells/scrollCellIntoView.ts +4 -0
  141. package/src/core/cells/utils.ts +1 -1
  142. package/src/core/codemirror/__tests__/editor-mount-scheduler.test.ts +143 -0
  143. package/src/core/codemirror/copilot/getCodes.ts +3 -1
  144. package/src/core/codemirror/editor-mount-scheduler.ts +101 -0
  145. package/src/core/codemirror/language/languages/python.ts +2 -0
  146. package/src/core/codemirror/language/languages/sql/utils.ts +3 -1
  147. package/src/core/codemirror/lsp/__tests__/markdown-renderer.test.ts +41 -0
  148. package/src/core/codemirror/lsp/markdown-renderer.ts +59 -0
  149. package/src/core/datasets/data-source-connections.ts +2 -0
  150. package/src/core/errors/errors.ts +1 -1
  151. package/src/core/storage/__tests__/state.test.ts +49 -0
  152. package/src/core/storage/__tests__/useStorageEntries.test.tsx +199 -3
  153. package/src/core/storage/state.ts +124 -13
  154. package/src/core/storage/types.ts +6 -0
  155. package/src/core/wasm/worker/bootstrap.ts +12 -4
  156. package/src/plugins/core/__test__/registerReactComponent.test.ts +96 -0
  157. package/src/plugins/core/registerReactComponent.tsx +42 -10
  158. package/src/plugins/impl/MultiselectPlugin.tsx +19 -142
  159. package/src/plugins/impl/SearchableSelect.tsx +16 -97
  160. package/src/plugins/impl/SliderPlugin.tsx +132 -18
  161. package/src/plugins/impl/__tests__/DropdownPlugin.test.tsx +5 -2
  162. package/src/plugins/impl/__tests__/MultiSelectPlugin.test.ts +1 -1
  163. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +278 -8
  164. package/src/utils/__tests__/numbers.test.ts +20 -0
  165. package/src/utils/errors.ts +9 -0
  166. package/src/utils/lazy.ts +6 -1
  167. package/src/utils/numbers.ts +27 -0
  168. package/src/utils/schedule-task.ts +71 -0
  169. package/dist/assets/__vite-browser-external-Ci2ZQfXU.js +0 -1
  170. package/dist/assets/worker-ip3AI_sN.js +0 -73
  171. package/dist/dist-0Fif7jnk.js +0 -5
  172. package/dist/dist-B5h_9sHB.js +0 -6
  173. package/dist/dist-B9M6R5ye.js +0 -5
  174. package/dist/dist-BCt3tnck.js +0 -8
  175. package/dist/dist-BUIJwMwn.js +0 -8
  176. package/dist/dist-BpquMd3k.js +0 -5
  177. package/dist/dist-BzJsqYfz.js +0 -5
  178. package/dist/dist-CA5ELXAf.js +0 -6
  179. package/dist/dist-CLBRs6Uv.js +0 -5
  180. package/dist/dist-CStVCMbq.js +0 -5
  181. package/dist/dist-CZRIEY3Y.js +0 -8
  182. package/dist/dist-CuUHbFD0.js +0 -5
  183. package/dist/dist-DV7Iabxb.js +0 -8
  184. package/dist/dist-DhHh0jLg.js +0 -1247
  185. package/dist/dist-DuEeHMvL.js +0 -5
  186. package/dist/esm-CCuYCd3R.js +0 -1171
  187. package/src/plugins/impl/multiselectFilterFn.tsx +0 -22
  188. /package/src/components/{data-table → ui}/value-chips.tsx +0 -0
@@ -0,0 +1,180 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { describe, expect, it } from "vitest";
3
+ import type { StorageEntry, StoragePathKey } from "@/core/storage/types";
4
+ import { storagePathKey } from "@/core/storage/types";
5
+ import {
6
+ filterEntries,
7
+ remoteSearchPrefix,
8
+ storageEntryKey,
9
+ } from "../storage-inspector";
10
+
11
+ function makeEntry(
12
+ overrides: Partial<StorageEntry> & { path: string },
13
+ ): StorageEntry {
14
+ return {
15
+ kind: overrides.kind ?? "file",
16
+ lastModified: overrides.lastModified ?? null,
17
+ metadata: overrides.metadata ?? {},
18
+ path: overrides.path,
19
+ size: overrides.size ?? 0,
20
+ };
21
+ }
22
+
23
+ describe("storageEntryKey", () => {
24
+ it("prefers the backend id when present (e.g. Google Drive)", () => {
25
+ const entry = makeEntry({
26
+ path: "Data Resume.pdf",
27
+ metadata: { id: "drive-file-id-123" },
28
+ });
29
+ // Two files can share a path on Drive; the id keeps keys unique.
30
+ expect(storageEntryKey(entry, 0)).toBe("drive-file-id-123");
31
+ expect(storageEntryKey(entry, 4)).toBe("drive-file-id-123");
32
+ });
33
+
34
+ it("falls back to path + index when there is no id", () => {
35
+ const entry = makeEntry({ path: "Data Resume.pdf" });
36
+ expect(storageEntryKey(entry, 0)).toBe("Data Resume.pdf::0");
37
+ expect(storageEntryKey(entry, 4)).toBe("Data Resume.pdf::4");
38
+ });
39
+
40
+ it("keeps duplicate-path entries unique via the index fallback", () => {
41
+ const entries = [
42
+ makeEntry({ path: "Data Resume.pdf" }),
43
+ makeEntry({ path: "Data Resume.pdf" }),
44
+ makeEntry({ path: "Data Resume.pdf" }),
45
+ ];
46
+ const keys = entries.map((entry, index) => storageEntryKey(entry, index));
47
+ expect(new Set(keys).size).toBe(entries.length);
48
+ });
49
+
50
+ it("ignores a non-string or empty id", () => {
51
+ expect(
52
+ storageEntryKey(makeEntry({ path: "a.pdf", metadata: { id: "" } }), 2),
53
+ ).toBe("a.pdf::2");
54
+ expect(
55
+ storageEntryKey(makeEntry({ path: "a.pdf", metadata: { id: 5 } }), 2),
56
+ ).toBe("a.pdf::2");
57
+ });
58
+ });
59
+
60
+ describe("storage inspector search", () => {
61
+ describe("remoteSearchPrefix", () => {
62
+ it("returns the parent directory of the query so backends can list it", () => {
63
+ // Object stores match prefixes on path segments, so we list the parent
64
+ // directory and filter the rest client-side.
65
+ expect(remoteSearchPrefix("folder/x")).toBe("folder/");
66
+ expect(remoteSearchPrefix("nested/folder/x")).toBe("nested/folder/");
67
+ });
68
+
69
+ it("preserves trailing slashes when the user explicitly typed one", () => {
70
+ expect(remoteSearchPrefix("folder/x/")).toBe("folder/x/");
71
+ expect(remoteSearchPrefix("nested/folder/x/")).toBe("nested/folder/x/");
72
+ expect(remoteSearchPrefix("/")).toBe("/");
73
+ });
74
+
75
+ it("returns an empty string for queries without a directory component", () => {
76
+ // Without a slash there is nothing useful to send to the backend; rely on
77
+ // local filtering instead.
78
+ expect(remoteSearchPrefix("x")).toBe("");
79
+ expect(remoteSearchPrefix("report")).toBe("");
80
+ });
81
+
82
+ it("trims leading/trailing whitespace before computing the prefix", () => {
83
+ expect(remoteSearchPrefix(" nested/folder/x ")).toBe("nested/folder/");
84
+ expect(remoteSearchPrefix(" ")).toBe("");
85
+ });
86
+ });
87
+
88
+ describe("filterEntries", () => {
89
+ it("matches loaded entries by basename, extension, and full path", () => {
90
+ const entries = [
91
+ makeEntry({ path: "data/report.csv" }),
92
+ makeEntry({ path: "logs/readme.md" }),
93
+ ];
94
+
95
+ expect(
96
+ filterEntries(entries, {
97
+ namespace: "store",
98
+ searchValue: ".csv",
99
+ entriesByPath: new Map(),
100
+ }),
101
+ ).toEqual([entries[0]]);
102
+ expect(
103
+ filterEntries(entries, {
104
+ namespace: "store",
105
+ searchValue: "data/report",
106
+ entriesByPath: new Map(),
107
+ }),
108
+ ).toEqual([entries[0]]);
109
+ expect(
110
+ filterEntries(entries, {
111
+ namespace: "store",
112
+ searchValue: "readme",
113
+ entriesByPath: new Map(),
114
+ }),
115
+ ).toEqual([entries[1]]);
116
+ });
117
+
118
+ it("returns the original entries when search is cleared", () => {
119
+ const entries = [
120
+ makeEntry({ path: "data/report.csv" }),
121
+ makeEntry({ path: "logs/readme.md" }),
122
+ ];
123
+
124
+ expect(
125
+ filterEntries(entries, {
126
+ namespace: "store",
127
+ searchValue: "",
128
+ entriesByPath: new Map(),
129
+ }),
130
+ ).toBe(entries);
131
+ });
132
+
133
+ it("keeps directories whose loaded descendants match a path query", () => {
134
+ const directory = makeEntry({ path: "data", kind: "directory" });
135
+ const child = makeEntry({ path: "data/report.csv" });
136
+ const entriesByPath = new Map<StoragePathKey, StorageEntry[]>([
137
+ [storagePathKey("store", "data/"), [child]],
138
+ ]);
139
+
140
+ expect(
141
+ filterEntries([directory], {
142
+ namespace: "store",
143
+ searchValue: "data/report",
144
+ entriesByPath,
145
+ }),
146
+ ).toEqual([directory]);
147
+ });
148
+
149
+ it("matches partial path queries against loaded sibling files (folder/x -> folder/xsomething)", () => {
150
+ // Regression test for the obstore path-segment prefix bug: typing
151
+ // "folder/x" should surface "folder/xsomething" once the folder has
152
+ // been listed locally.
153
+ const folder = makeEntry({ path: "folder/", kind: "directory" });
154
+ const matching = makeEntry({ path: "folder/xsomething" });
155
+ const matchingAlt = makeEntry({ path: "folder/xanother" });
156
+ const other = makeEntry({ path: "folder/something" });
157
+ const entriesByPath = new Map<StoragePathKey, StorageEntry[]>([
158
+ [storagePathKey("store", "folder/"), [other, matchingAlt, matching]],
159
+ ]);
160
+
161
+ expect(
162
+ filterEntries([folder], {
163
+ namespace: "store",
164
+ searchValue: "folder/x",
165
+ entriesByPath,
166
+ }),
167
+ ).toEqual([folder]);
168
+
169
+ // Same query, but applied directly to the loaded folder contents (as
170
+ // happens for the "remote results" fallback) should drop non-matches.
171
+ expect(
172
+ filterEntries([other, matchingAlt, matching], {
173
+ namespace: "store",
174
+ searchValue: "folder/x",
175
+ entriesByPath,
176
+ }),
177
+ ).toEqual([matchingAlt, matching]);
178
+ });
179
+ });
180
+ });