@marimo-team/islands 0.24.1-dev115 → 0.24.1-dev116

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 (39) hide show
  1. package/dist/{ConnectedDataExplorerComponent-3vyrwCHu.js → ConnectedDataExplorerComponent-BabDOEkd.js} +10 -10
  2. package/dist/{ErrorBoundary-QF0xsxMw.js → ErrorBoundary-DXp6EXOC.js} +2 -2
  3. package/dist/{any-language-editor-B2e3EkTe.js → any-language-editor-CpTnK43-.js} +3 -3
  4. package/dist/{chat-ui-BgGHMO2G.js → chat-ui-B2KTPWqm.js} +15 -15
  5. package/dist/{check-C_-c2CXl.js → check-CHig47QV.js} +1 -1
  6. package/dist/{common-Cdx64lyR.js → common-mAFq987V.js} +7588 -7544
  7. package/dist/{copy-D4GHy7GA.js → copy-CD7S58CY.js} +1 -1
  8. package/dist/{dist-mymH-A_x.js → dist-3_o3T78I.js} +14 -14
  9. package/dist/{dropdown-menu-Div6gwlw.js → dropdown-menu-D1s8H8Ow.js} +123 -123
  10. package/dist/{error-banner-DmgOcFS3.js → error-banner-WDhUzJyg.js} +202 -202
  11. package/dist/{esm-CmFEQJjP.js → esm-CesmlDrs.js} +1 -1
  12. package/dist/{extends-CGTKDWHv.js → extends-BPB6_lTK.js} +3 -3
  13. package/dist/{formats-DuRRWVwb.js → formats-DrWM-ouO.js} +1 -1
  14. package/dist/{glide-data-editor-ekJ5GwaZ.js → glide-data-editor-B-3cUJQd.js} +7 -7
  15. package/dist/{glide-utils-Dwc8Eh8G.js → glide-utils-NShAPPtn.js} +2 -2
  16. package/dist/{html-to-image-u8Ik6EnK.js → html-to-image-DqqHcuV2.js} +3378 -3378
  17. package/dist/{label-DdGS_CZZ.js → label-lwzzBHUW.js} +1 -1
  18. package/dist/main.js +792 -792
  19. package/dist/{mermaid-Bt45Zzl4.js → mermaid-DWMOBSe8.js} +3 -3
  20. package/dist/{process-output-DQiqt-_U.js → process-output-D5dqSIGW.js} +3 -3
  21. package/dist/{reveal-component-tQ-rgxcQ.js → reveal-component-DU6Wrhzv.js} +8 -8
  22. package/dist/{schemas-BjeOpZLk.js → schemas-DzK6U94N.js} +1379 -1363
  23. package/dist/{select-DotAQ4jp.js → select-3qHpFKF9.js} +286 -286
  24. package/dist/{spec-BesaYkGC.js → spec-DzTo7SI8.js} +4 -4
  25. package/dist/style.css +1 -1
  26. package/dist/{toDate-CrAIOASL.js → toDate-Cq6SCTVJ.js} +2 -2
  27. package/dist/{tooltip-COXZxyl7.js → tooltip-Dt77sBeT.js} +87 -87
  28. package/dist/{useAsyncData-x0_tWDWI.js → useAsyncData-DqlulK9M.js} +1 -1
  29. package/dist/{useDateFormatter-B3V__WqX.js → useDateFormatter-Cp9Jdxls.js} +2 -2
  30. package/dist/{useDeepCompareMemoize-KaRHJEEU.js → useDeepCompareMemoize-Ceu-LMdC.js} +1 -1
  31. package/dist/{useLifecycle-x0OriHo-.js → useLifecycle-DmYfrWCI.js} +2 -2
  32. package/dist/{useTheme-Bm9_FyqO.js → useTheme-CWrCsZgw.js} +1 -1
  33. package/dist/{vega-component-nD2oP6WN.js → vega-component-Dzo_03Dh.js} +7 -7
  34. package/package.json +1 -1
  35. package/src/components/editor/Output.tsx +40 -0
  36. package/src/components/editor/__tests__/Output.test.tsx +85 -2
  37. package/src/components/ui/__tests__/fullscreen.test.tsx +88 -0
  38. package/src/components/ui/fullscreen.tsx +43 -1
  39. package/src/hooks/useEventListener.ts +1 -1
@@ -0,0 +1,88 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { act, render } from "@testing-library/react";
3
+ import { useRef } from "react";
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { useIsFullScreen } from "../fullscreen";
6
+
7
+ const FullScreenFlag = ({ label }: { label: string }) => {
8
+ const ref = useRef<HTMLDivElement>(null);
9
+ const isFullScreen = useIsFullScreen(ref);
10
+
11
+ return (
12
+ <div ref={ref} data-testid={label}>
13
+ {String(isFullScreen)}
14
+ </div>
15
+ );
16
+ };
17
+
18
+ describe("useIsFullScreen", () => {
19
+ let fullscreenElement: Element | null = null;
20
+
21
+ beforeEach(() => {
22
+ fullscreenElement = null;
23
+ Object.defineProperty(document, "fullscreenElement", {
24
+ configurable: true,
25
+ get: () => fullscreenElement,
26
+ });
27
+ });
28
+
29
+ afterEach(() => {
30
+ Reflect.deleteProperty(document, "fullscreenElement");
31
+ });
32
+
33
+ const countFullScreenListeners = (calls: unknown[][]) =>
34
+ calls.filter((call) => call[0] === "fullscreenchange").length;
35
+
36
+ it("adds one document listener for many subscribers", () => {
37
+ const addEventListener = vi.spyOn(document, "addEventListener");
38
+
39
+ render(
40
+ <>
41
+ <FullScreenFlag label="first" />
42
+ <FullScreenFlag label="second" />
43
+ <FullScreenFlag label="third" />
44
+ </>,
45
+ );
46
+
47
+ expect(countFullScreenListeners(addEventListener.mock.calls)).toBe(1);
48
+ addEventListener.mockRestore();
49
+ });
50
+
51
+ it("removes the listener when the last subscriber unmounts", () => {
52
+ const removeEventListener = vi.spyOn(document, "removeEventListener");
53
+
54
+ const { unmount } = render(
55
+ <>
56
+ <FullScreenFlag label="first" />
57
+ <FullScreenFlag label="second" />
58
+ </>,
59
+ );
60
+
61
+ expect(countFullScreenListeners(removeEventListener.mock.calls)).toBe(0);
62
+
63
+ unmount();
64
+
65
+ expect(countFullScreenListeners(removeEventListener.mock.calls)).toBe(1);
66
+ removeEventListener.mockRestore();
67
+ });
68
+
69
+ it("reports true for the full screen element only", () => {
70
+ const { getByTestId } = render(
71
+ <>
72
+ <FullScreenFlag label="first" />
73
+ <FullScreenFlag label="second" />
74
+ </>,
75
+ );
76
+
77
+ expect(getByTestId("first")).toHaveTextContent("false");
78
+ expect(getByTestId("second")).toHaveTextContent("false");
79
+
80
+ fullscreenElement = getByTestId("second");
81
+ act(() => {
82
+ document.dispatchEvent(new Event("fullscreenchange"));
83
+ });
84
+
85
+ expect(getByTestId("first")).toHaveTextContent("false");
86
+ expect(getByTestId("second")).toHaveTextContent("true");
87
+ });
88
+ });
@@ -4,7 +4,7 @@ import type { Popover } from "radix-ui";
4
4
 
5
5
  type PopoverContentProps = Popover.PopoverContentProps;
6
6
 
7
- import React, { useState } from "react";
7
+ import React, { type RefObject, useState, useSyncExternalStore } from "react";
8
8
  import { isInVscodeExtension } from "@/core/vscode/is-in-vscode";
9
9
  import { useEventListener } from "@/hooks/useEventListener";
10
10
 
@@ -27,6 +27,48 @@ export function useFullScreenElement() {
27
27
  return fullScreenElement;
28
28
  }
29
29
 
30
+ const fullScreenSubscribers = new Set<() => void>();
31
+
32
+ function notifyFullScreenSubscribers() {
33
+ for (const subscriber of fullScreenSubscribers) {
34
+ subscriber();
35
+ }
36
+ }
37
+
38
+ /**
39
+ * One document listener serves every subscriber, so the cost of a full screen
40
+ * transition does not grow with the number of mounted components.
41
+ */
42
+ function subscribeToFullScreen(onStoreChange: () => void) {
43
+ if (fullScreenSubscribers.size === 0) {
44
+ document.addEventListener("fullscreenchange", notifyFullScreenSubscribers);
45
+ }
46
+ fullScreenSubscribers.add(onStoreChange);
47
+
48
+ return () => {
49
+ fullScreenSubscribers.delete(onStoreChange);
50
+ if (fullScreenSubscribers.size === 0) {
51
+ document.removeEventListener(
52
+ "fullscreenchange",
53
+ notifyFullScreenSubscribers,
54
+ );
55
+ }
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Whether the given element is the full screen element.
61
+ *
62
+ * The hook returns a boolean, so a component re-renders only when its own
63
+ * element enters or leaves full screen.
64
+ */
65
+ export function useIsFullScreen(ref: RefObject<Element | null>): boolean {
66
+ return useSyncExternalStore(subscribeToFullScreen, () => {
67
+ const fullScreenElement = document.fullscreenElement;
68
+ return fullScreenElement !== null && fullScreenElement === ref.current;
69
+ });
70
+ }
71
+
30
72
  /**
31
73
  * HOC wrapping a Portal component to use the
32
74
  * full screen element as the container if we are in full screen mode
@@ -17,7 +17,7 @@ export function isRefObject<T>(target: unknown): target is RefObject<T | null> {
17
17
  }
18
18
 
19
19
  export function useEventListener<K extends keyof DocumentEventMap>(
20
- targetValue: Document,
20
+ targetValue: Document | null,
21
21
  type: K,
22
22
  listener: (ev: DocumentEventMap[K]) => unknown,
23
23
  options?: boolean | AddEventListenerOptions,