@marimo-team/frontend 0.23.15-dev63 → 0.23.15-dev64

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.
@@ -0,0 +1 @@
1
+ import{s as v}from"./chunk-LvLJmgfZ.js";import{t as h}from"./react-Bj1aDYRI.js";import{t as x}from"./compiler-runtime-B3qBwwSJ.js";import{f,g as s}from"./useEventListener-B_w3A283.js";import{r as y}from"./constants-CDyU_g2F.js";import{T as S}from"./config-BbOTTCYY.js";import{t as b}from"./createLucideIcon-w-Qo9n0R.js";var z=b("case-sensitive",[["path",{d:"m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16",key:"d5nyq2"}],["path",{d:"M22 9v7",key:"pvm9v3"}],["path",{d:"M3.304 13h6.392",key:"1q3zxz"}],["circle",{cx:"18.5",cy:"12.5",r:"3.5",key:"z97x68"}]]),p=v(h(),1);const k=t=>{let e=null,n=async()=>(e||(e=t()),e);return{preload:n,Component:p.lazy(()=>n())}},E=typeof window<"u"&&window.parent!==window;function _(){new URLSearchParams(window.location.search).has(y.vscode)&&(!E||S()||(s.log("[vscode] Registering VS Code bindings"),C(),R(),L(),K()))}function R(){window.addEventListener("copy",()=>{var t;d({command:"copy",text:((t=window.getSelection())==null?void 0:t.toString())??""})}),window.addEventListener("cut",()=>{var e;let t=((e=window.getSelection())==null?void 0:e.toString())??"";f()&&document.execCommand("insertText",!1,""),d({command:"cut",text:t})}),window.addEventListener("message",async t=>{try{let e=t.data,n=f();switch(e.command){case"paste":if(s.log(`[vscode] Received paste mac=${n}`,e),n){let r=document.activeElement;if(!r){s.warn("[vscode] No active element to paste into"),document.execCommand("insertText",!1,e.text);return}let i=new DataTransfer;i.setData("text/plain",e.text),r.dispatchEvent(new ClipboardEvent("paste",{clipboardData:i}))}else s.log("[vscode] Not pasting on mac");return}}catch(e){s.error("Error in paste message handler",e)}})}function C(){document.addEventListener("keydown",t=>{var e,n;if((t.ctrlKey||t.metaKey)&&t.key==="c"){let r=((e=window.getSelection())==null?void 0:e.toString())??"";s.log("[vscode] Sending copy",r),d({command:"copy",text:r});return}if((t.ctrlKey||t.metaKey)&&t.key==="x"){let r=((n=window.getSelection())==null?void 0:n.toString())??"";f()&&document.execCommand("insertText",!1,""),s.log("[vscode] Sending cut",r),d({command:"cut",text:r});return}if((t.ctrlKey||t.metaKey)&&t.key==="v"){s.log("[vscode] Sending paste"),d({command:"paste"});return}})}function L(){document.addEventListener("click",t=>{let e=t.target;if(e.tagName!=="A")return;let n=e.getAttribute("href");n&&(n.startsWith("http://")||n.startsWith("https://"))&&(t.preventDefault(),d({command:"external_link",url:n}))})}function K(){document.addEventListener("contextmenu",t=>{t.preventDefault(),d({command:"context_menu"})})}function d(t){var e;(e=window.parent)==null||e.postMessage(t,"*")}var T={width:void 0,height:void 0};function D(t){let{ref:e,box:n="content-box",skip:r}=t,i=(0,p.useRef)({...T}),c=(0,p.useRef)(void 0);c.current=t.onResize,(0,p.useEffect)(()=>{if(!e.current||r||typeof window>"u"||!("ResizeObserver"in window))return;let m=new ResizeObserver(([l])=>{let u=n==="border-box"?"borderBoxSize":n==="device-pixel-content-box"?"devicePixelContentBoxSize":"contentBoxSize",o=w(l,u,"inlineSize"),a=w(l,u,"blockSize");if(i.current.width!==o||i.current.height!==a){let g={width:o,height:a};i.current.width=o,i.current.height=a,c.current&&c.current(g)}});return m.observe(e.current,{box:n}),()=>{m.disconnect()}},[n,e,r])}function w(t,e,n){return t[e]?Array.isArray(t[e])?t[e][0][n]:t[e][n]:e==="contentBoxSize"?t.contentRect[n==="inlineSize"?"width":"height"]:void 0}var P=x();function A(t){let e=(0,P.c)(6),[n,r]=(0,p.useState)(t),i;e[0]===Symbol.for("react.memo_cache_sentinel")?(i=o=>{var a;(a=o==null?void 0:o.stopPropagation)==null||a.call(o),r(!0)},e[0]=i):i=e[0];let c;e[1]===Symbol.for("react.memo_cache_sentinel")?(c=o=>{var a;(a=o==null?void 0:o.stopPropagation)==null||a.call(o),r(!1)},e[1]=c):c=e[1];let m;e[2]===Symbol.for("react.memo_cache_sentinel")?(m=o=>{var a;(a=o==null?void 0:o.stopPropagation)==null||a.call(o),r(B)},e[2]=m):m=e[2];let l;e[3]===Symbol.for("react.memo_cache_sentinel")?(l={setTrue:i,setFalse:c,toggle:m},e[3]=l):l=e[3];let u;return e[4]===n?u=e[5]:(u=[n,l],e[4]=n,e[5]=u),u}function B(t){return!t}export{k as a,d as i,D as n,z as o,_ as r,A as t};
package/dist/index.html CHANGED
@@ -66,7 +66,7 @@
66
66
  <marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
67
67
  <!-- /TODO -->
68
68
  <title>{{ title }}</title>
69
- <script type="module" crossorigin src="./assets/index-C0JtPo0J.js"></script>
69
+ <script type="module" crossorigin src="./assets/index-CD0bwvp_.js"></script>
70
70
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-TXkS1QI3.js">
71
71
  <link rel="modulepreload" crossorigin href="./assets/objects-BlG0ZrO0.js">
72
72
  <link rel="modulepreload" crossorigin href="./assets/chunk-LvLJmgfZ.js">
@@ -229,7 +229,7 @@
229
229
  <link rel="modulepreload" crossorigin href="./assets/refresh-ccw-sLaKP2vj.js">
230
230
  <link rel="modulepreload" crossorigin href="./assets/form-CgWNb44_.js">
231
231
  <link rel="modulepreload" crossorigin href="./assets/renderShortcut-BZLr8D7H.js">
232
- <link rel="modulepreload" crossorigin href="./assets/useBoolean-0INKlLC_.js">
232
+ <link rel="modulepreload" crossorigin href="./assets/useBoolean-IdEpuCDV.js">
233
233
  <link rel="modulepreload" crossorigin href="./assets/useDeepCompareMemoize-CSMoa-ga.js">
234
234
  <link rel="modulepreload" crossorigin href="./assets/types-jdbI9Q8O.js">
235
235
  <link rel="modulepreload" crossorigin href="./assets/semaphore-DtBYRzWS.js">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/frontend",
3
- "version": "0.23.15-dev63",
3
+ "version": "0.23.15-dev64",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -1,6 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import type { JSX, PropsWithChildren } from "react";
3
3
  import React from "react";
4
+ import { createPortal } from "react-dom";
4
5
  import { z } from "zod";
5
6
  import {
6
7
  NavigationMenu,
@@ -9,9 +10,11 @@ import {
9
10
  NavigationMenuLink,
10
11
  NavigationMenuList,
11
12
  NavigationMenuTrigger,
13
+ NavigationMenuViewport,
12
14
  navigationMenuTriggerStyle,
13
15
  } from "@/components/ui/navigation";
14
16
  import { Tooltip } from "@/components/ui/tooltip";
17
+ import { useResizeObserver } from "@/hooks/useResizeObserver";
15
18
  import { renderHTML } from "@/plugins/core/RenderHTML";
16
19
  import { cn } from "@/utils/cn";
17
20
  import { appendQueryParams } from "@/utils/urls";
@@ -21,6 +24,7 @@ import type {
21
24
  } from "../stateless-plugin";
22
25
  import "./navigation-menu.css";
23
26
  import { KnownQueryParams } from "@/core/constants";
27
+ import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui";
24
28
 
25
29
  interface MenuItem {
26
30
  label: string;
@@ -45,6 +49,118 @@ interface Data {
45
49
  orientation: "horizontal" | "vertical";
46
50
  }
47
51
 
52
+ interface PortalPosition {
53
+ left: number;
54
+ top: number;
55
+ }
56
+
57
+ interface HorizontalMenuGroupProps {
58
+ item: MenuItemGroup;
59
+ preserveQueryParams: (href: string) => string;
60
+ target: (href: string) => string;
61
+ }
62
+
63
+ const HorizontalMenuGroup = ({
64
+ item,
65
+ preserveQueryParams,
66
+ target,
67
+ }: HorizontalMenuGroupProps): JSX.Element => {
68
+ const triggerRef = React.useRef<React.ComponentRef<
69
+ typeof NavigationMenuTrigger
70
+ > | null>(null);
71
+
72
+ return (
73
+ <NavigationMenuPrimitive.Root
74
+ className="relative z-10 max-w-max flex-1 items-center justify-center"
75
+ orientation="horizontal"
76
+ >
77
+ <NavigationMenuList>
78
+ <NavigationMenuItem>
79
+ <NavigationMenuTrigger ref={triggerRef}>
80
+ {renderHTML({ html: item.label })}
81
+ </NavigationMenuTrigger>
82
+ <NavigationMenuContent className="w-auto">
83
+ <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ">
84
+ {item.items.map((subItem) => (
85
+ <ListItem
86
+ key={subItem.label}
87
+ label={subItem.label}
88
+ href={preserveQueryParams(subItem.href)}
89
+ target={target(subItem.href)}
90
+ >
91
+ {subItem.description &&
92
+ renderHTML({ html: subItem.description })}
93
+ </ListItem>
94
+ ))}
95
+ </ul>
96
+ </NavigationMenuContent>
97
+ </NavigationMenuItem>
98
+ </NavigationMenuList>
99
+ <NavigationMenuViewportPortal anchorRef={triggerRef}>
100
+ <NavigationMenuViewport />
101
+ </NavigationMenuViewportPortal>
102
+ </NavigationMenuPrimitive.Root>
103
+ );
104
+ };
105
+
106
+ const NavigationMenuViewportPortal = ({
107
+ anchorRef,
108
+ children,
109
+ }: PropsWithChildren<{
110
+ anchorRef: React.RefObject<HTMLElement | null>;
111
+ }>): React.ReactElement | null => {
112
+ const [position, setPosition] = React.useState<PortalPosition | null>(null);
113
+
114
+ const updatePosition = React.useCallback(() => {
115
+ if (!anchorRef.current) {
116
+ return;
117
+ }
118
+
119
+ const rect = anchorRef.current.getBoundingClientRect();
120
+ setPosition({
121
+ left: rect.left,
122
+ top: rect.bottom,
123
+ });
124
+ }, [anchorRef]);
125
+
126
+ React.useLayoutEffect(() => {
127
+ updatePosition();
128
+ }, [updatePosition]);
129
+
130
+ useResizeObserver({
131
+ ref: anchorRef,
132
+ onResize: updatePosition,
133
+ });
134
+
135
+ React.useEffect(() => {
136
+ if (typeof window === "undefined") {
137
+ return;
138
+ }
139
+
140
+ window.addEventListener("resize", updatePosition);
141
+ document.addEventListener("scroll", updatePosition, { capture: true });
142
+
143
+ return () => {
144
+ window.removeEventListener("resize", updatePosition);
145
+ document.removeEventListener("scroll", updatePosition, { capture: true });
146
+ };
147
+ }, [updatePosition]);
148
+
149
+ if (!position || typeof document === "undefined") {
150
+ return null;
151
+ }
152
+
153
+ return createPortal(
154
+ <div
155
+ className="fixed z-50"
156
+ style={{ left: position.left, top: position.top }}
157
+ >
158
+ {children}
159
+ </div>,
160
+ document.body,
161
+ );
162
+ };
163
+
48
164
  export class NavigationMenuPlugin implements IStatelessPlugin<Data> {
49
165
  tagName = "marimo-nav-menu";
50
166
 
@@ -109,30 +225,12 @@ const NavMenuComponent = ({
109
225
  const renderMenuItem = (item: MenuItem | MenuItemGroup) => {
110
226
  if ("items" in item) {
111
227
  return orientation === "horizontal" ? (
112
- <NavigationMenu orientation="horizontal" key={item.label}>
113
- <NavigationMenuList>
114
- <NavigationMenuItem>
115
- <NavigationMenuTrigger>
116
- {renderHTML({ html: item.label })}
117
- </NavigationMenuTrigger>
118
- <NavigationMenuContent>
119
- <ul className="grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ">
120
- {item.items.map((subItem) => (
121
- <ListItem
122
- key={subItem.label}
123
- label={subItem.label}
124
- href={preserveQueryParams(subItem.href)}
125
- target={target(subItem.href)}
126
- >
127
- {subItem.description &&
128
- renderHTML({ html: subItem.description })}
129
- </ListItem>
130
- ))}
131
- </ul>
132
- </NavigationMenuContent>
133
- </NavigationMenuItem>
134
- </NavigationMenuList>
135
- </NavigationMenu>
228
+ <HorizontalMenuGroup
229
+ key={item.label}
230
+ item={item}
231
+ preserveQueryParams={preserveQueryParams}
232
+ target={target}
233
+ />
136
234
  ) : (
137
235
  <NavigationMenuItem key={item.label}>
138
236
  <div
@@ -196,32 +294,30 @@ const NavMenuComponent = ({
196
294
  };
197
295
 
198
296
  const ListItem = React.forwardRef<
199
- React.ElementRef<"a">,
297
+ React.ComponentRef<"a">,
200
298
  React.ComponentPropsWithoutRef<"a"> & {
201
299
  label: string;
202
300
  }
203
301
  >(({ className, label, children, ...props }, ref) => {
204
302
  return (
205
303
  <li>
206
- <NavigationMenuLink asChild={true}>
207
- <a
208
- ref={ref}
209
- className={cn(
210
- "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-hidden transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
211
- className,
212
- )}
213
- {...props}
214
- >
215
- <div className="text-base font-medium leading-none">
216
- {renderHTML({ html: label })}
217
- </div>
218
- {children && (
219
- <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
220
- {children}
221
- </p>
222
- )}
223
- </a>
224
- </NavigationMenuLink>
304
+ <a
305
+ ref={ref}
306
+ className={cn(
307
+ "block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-hidden transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
308
+ className,
309
+ )}
310
+ {...props}
311
+ >
312
+ <div className="text-base font-medium leading-none">
313
+ {renderHTML({ html: label })}
314
+ </div>
315
+ {children && (
316
+ <p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
317
+ {children}
318
+ </p>
319
+ )}
320
+ </a>
225
321
  </li>
226
322
  );
227
323
  });
@@ -1 +0,0 @@
1
- import{s as f}from"./chunk-LvLJmgfZ.js";import{t as w}from"./react-Bj1aDYRI.js";import{t as y}from"./compiler-runtime-B3qBwwSJ.js";import{f as u,g as c}from"./useEventListener-B_w3A283.js";import{r as v}from"./constants-CDyU_g2F.js";import{T as h}from"./config-BbOTTCYY.js";import{t as x}from"./createLucideIcon-w-Qo9n0R.js";var S=x("case-sensitive",[["path",{d:"m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16",key:"d5nyq2"}],["path",{d:"M22 9v7",key:"pvm9v3"}],["path",{d:"M3.304 13h6.392",key:"1q3zxz"}],["circle",{cx:"18.5",cy:"12.5",r:"3.5",key:"z97x68"}]]),g=f(w(),1);const _=e=>{let t=null,n=async()=>(t||(t=e()),t);return{preload:n,Component:g.lazy(()=>n())}},k=typeof window<"u"&&window.parent!==window;function E(){new URLSearchParams(window.location.search).has(v.vscode)&&(!k||h()||(c.log("[vscode] Registering VS Code bindings"),L(),b(),C(),K()))}function b(){window.addEventListener("copy",()=>{var e;i({command:"copy",text:((e=window.getSelection())==null?void 0:e.toString())??""})}),window.addEventListener("cut",()=>{var t;let e=((t=window.getSelection())==null?void 0:t.toString())??"";u()&&document.execCommand("insertText",!1,""),i({command:"cut",text:e})}),window.addEventListener("message",async e=>{try{let t=e.data,n=u();switch(t.command){case"paste":if(c.log(`[vscode] Received paste mac=${n}`,t),n){let a=document.activeElement;if(!a){c.warn("[vscode] No active element to paste into"),document.execCommand("insertText",!1,t.text);return}let s=new DataTransfer;s.setData("text/plain",t.text),a.dispatchEvent(new ClipboardEvent("paste",{clipboardData:s}))}else c.log("[vscode] Not pasting on mac");return}}catch(t){c.error("Error in paste message handler",t)}})}function L(){document.addEventListener("keydown",e=>{var t,n;if((e.ctrlKey||e.metaKey)&&e.key==="c"){let a=((t=window.getSelection())==null?void 0:t.toString())??"";c.log("[vscode] Sending copy",a),i({command:"copy",text:a});return}if((e.ctrlKey||e.metaKey)&&e.key==="x"){let a=((n=window.getSelection())==null?void 0:n.toString())??"";u()&&document.execCommand("insertText",!1,""),c.log("[vscode] Sending cut",a),i({command:"cut",text:a});return}if((e.ctrlKey||e.metaKey)&&e.key==="v"){c.log("[vscode] Sending paste"),i({command:"paste"});return}})}function C(){document.addEventListener("click",e=>{let t=e.target;if(t.tagName!=="A")return;let n=t.getAttribute("href");n&&(n.startsWith("http://")||n.startsWith("https://"))&&(e.preventDefault(),i({command:"external_link",url:n}))})}function K(){document.addEventListener("contextmenu",e=>{e.preventDefault(),i({command:"context_menu"})})}function i(e){var t;(t=window.parent)==null||t.postMessage(e,"*")}var T=y();function D(e){let t=(0,T.c)(6),[n,a]=(0,g.useState)(e),s;t[0]===Symbol.for("react.memo_cache_sentinel")?(s=o=>{var r;(r=o==null?void 0:o.stopPropagation)==null||r.call(o),a(!0)},t[0]=s):s=t[0];let m;t[1]===Symbol.for("react.memo_cache_sentinel")?(m=o=>{var r;(r=o==null?void 0:o.stopPropagation)==null||r.call(o),a(!1)},t[1]=m):m=t[1];let d;t[2]===Symbol.for("react.memo_cache_sentinel")?(d=o=>{var r;(r=o==null?void 0:o.stopPropagation)==null||r.call(o),a(z)},t[2]=d):d=t[2];let l;t[3]===Symbol.for("react.memo_cache_sentinel")?(l={setTrue:s,setFalse:m,toggle:d},t[3]=l):l=t[3];let p;return t[4]===n?p=t[5]:(p=[n,l],t[4]=n,t[5]=p),p}function z(e){return!e}export{S as a,_ as i,E as n,i as r,D as t};