@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.
- package/dist/assets/{edit-page-Cj3IcXFr.js → edit-page-DyphOdrb.js} +5 -5
- package/dist/assets/{index-C0JtPo0J.js → index-CD0bwvp_.js} +21 -21
- package/dist/assets/useBoolean-IdEpuCDV.js +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/plugins/layout/NavigationMenuPlugin.tsx +140 -44
- package/dist/assets/useBoolean-0INKlLC_.js +0 -1
|
@@ -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-
|
|
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-
|
|
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,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
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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.
|
|
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
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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};
|