@marimo-team/islands 0.25.3-dev3 → 0.25.3-dev5

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 (87) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNSxdKyJ.js → ConnectedDataExplorerComponent-CNMliVzw.js} +1 -1
  2. package/dist/{ErrorBoundary-iHE9DnZC.js → ErrorBoundary-BiZWOrv4.js} +1 -1
  3. package/dist/{abnfDiagram-VCTEODGH-DQDjNXt3.js → abnfDiagram-VCTEODGH-D-Ez91gV.js} +2 -2
  4. package/dist/{any-language-editor-B9REGlD9.js → any-language-editor-DZ_YTVus.js} +1 -1
  5. package/dist/{architectureDiagram-5GKGNRK7-Nmls7Wxn.js → architectureDiagram-5GKGNRK7-CTpcNtO8.js} +1 -1
  6. package/dist/{chat-ui-BDpymeoe.js → chat-ui-0lKdOoQ3.js} +436 -437
  7. package/dist/{chunk-IMKFNOWR-CoIFEo-1.js → chunk-IMKFNOWR-DGxi-zeo.js} +1 -1
  8. package/dist/{chunk-SHT3W25Y-lHiGx3ZC.js → chunk-SHT3W25Y-CV9J3rAB.js} +1 -1
  9. package/dist/{chunk-SVP7TREG-BvsHIrY_.js → chunk-SVP7TREG-BL-9Fqgg.js} +1 -1
  10. package/dist/{chunk-TICWLB2K-BC8YIm_n.js → chunk-TICWLB2K-Cu_XMjDM.js} +1 -1
  11. package/dist/{classDiagram-ZZMXUADV-Bt98lkkv.js → classDiagram-ZZMXUADV-BXXV13Hq.js} +2 -2
  12. package/dist/{classDiagram-v2-VYDZK3BY-D9bfbcC3.js → classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js} +2 -2
  13. package/dist/{code-visibility-BCpXa0Xh.js → code-visibility-CW5_8ZOI.js} +14 -14
  14. package/dist/{common-BrBUdtPy.js → common-mzWw4FdI.js} +5466 -5236
  15. package/dist/{cynefinDiagram-5FMLGOSQ-CgWra7wt.js → cynefinDiagram-5FMLGOSQ-CH96rwba.js} +1 -1
  16. package/dist/{dagre-GXQ25YYZ-CFZ8-35c.js → dagre-GXQ25YYZ-BD3PmpFY.js} +1 -1
  17. package/dist/{data-grid-overlay-editor-Ch2SgmvG.js → data-grid-overlay-editor-CJmehSdc.js} +1 -1
  18. package/dist/{diagram-S7CK7UJ4-lCNQrW7d.js → diagram-S7CK7UJ4-BsSJJldB.js} +1 -1
  19. package/dist/{diagram-UQ7AKVKN-CQPQ6pP_.js → diagram-UQ7AKVKN-muQtNZc4.js} +1 -1
  20. package/dist/{diagram-VX7I27RA-Cf3b0llz.js → diagram-VX7I27RA-CdhuZAqR.js} +1 -1
  21. package/dist/{diagram-Z3DM3KII-Bt4QLrpn.js → diagram-Z3DM3KII-BD8mXjOj.js} +1 -1
  22. package/dist/{ebnfDiagram-PWID7BFC-D3NAyPFY.js → ebnfDiagram-PWID7BFC-BIN1sweE.js} +2 -2
  23. package/dist/{erDiagram-RLTQ6QDP-Tlu09_Nm.js → erDiagram-RLTQ6QDP-Ctp5cfoN.js} +1 -1
  24. package/dist/{error-banner-Da600cwz.js → error-banner-D-WCIiMt.js} +10 -5
  25. package/dist/{cells-C8iCYvLU.js → error-entries-DSvFWT_M.js} +2262 -2206
  26. package/dist/{feedback-button-DxXNcC6q.js → feedback-button-BcT1FBud.js} +115 -116
  27. package/dist/{flowDiagram-HODETNUW-CAYbpJmV.js → flowDiagram-HODETNUW-3EfLrlFb.js} +2 -2
  28. package/dist/{formats-BGh2thRc.js → formats-CeOmU1MU.js} +1 -1
  29. package/dist/{glide-data-editor-BQ7uKbeo.js → glide-data-editor-XckatD0j.js} +3 -3
  30. package/dist/{globals-DSavh2ZB.js → globals-jRrLCkrP.js} +1 -1
  31. package/dist/{html-to-image-CZY1pIZH.js → html-to-image-B8s5SgGm.js} +23 -23
  32. package/dist/{infoDiagram-27XIBGKW-XrDxhr0x.js → infoDiagram-27XIBGKW-DipQoHxl.js} +1 -1
  33. package/dist/{ishikawaDiagram-5VMMS53U-CD1muzov.js → ishikawaDiagram-5VMMS53U-DgFMjSGz.js} +1 -1
  34. package/dist/{kanban-definition-UXKFOSKX-Dg9W142_.js → kanban-definition-UXKFOSKX-w1ACVjgl.js} +1 -1
  35. package/dist/main.js +164 -163
  36. package/dist/{mermaid-CiAXjLpA.js → mermaid-CHo49Yv-.js} +33 -33
  37. package/dist/{mindmap-definition-YA3MSWOX-DgCidgYJ.js → mindmap-definition-YA3MSWOX-CrT0KSfX.js} +1 -1
  38. package/dist/{number-overlay-editor-D6kYaqh5.js → number-overlay-editor-pZx8dUDV.js} +1 -1
  39. package/dist/{pegDiagram-XKGWAZYB-coOYYKB6.js → pegDiagram-XKGWAZYB-BqvywNJA.js} +2 -2
  40. package/dist/{pieDiagram-E7YTZNPT-BnXTc3bj.js → pieDiagram-E7YTZNPT-BfxJ_XCc.js} +1 -1
  41. package/dist/{process-output-e4jj9Ijt.js → process-output-CKRXyszb.js} +3 -3
  42. package/dist/{railroadDiagram-O6MQD6OU-B28-u83n.js → railroadDiagram-O6MQD6OU-8vFLVTPu.js} +2 -2
  43. package/dist/{requirementDiagram-BXWQKSXE-CdYCTMu0.js → requirementDiagram-BXWQKSXE-a_MxGvxe.js} +1 -1
  44. package/dist/{reveal-component-BTBfJ3ju.js → reveal-component-79ez8-D5.js} +4 -4
  45. package/dist/{sequenceDiagram-WJ2MYXX4-CM3aRAe_.js → sequenceDiagram-WJ2MYXX4-CXFMnxGh.js} +1 -1
  46. package/dist/{stateDiagram-D77RDMKH-DOZUMVj8.js → stateDiagram-D77RDMKH-DQeA_CwI.js} +2 -2
  47. package/dist/{stateDiagram-v2-MP3YSRHH-CISYxma6.js → stateDiagram-v2-MP3YSRHH-BxxQucm1.js} +2 -2
  48. package/dist/style.css +1 -1
  49. package/dist/{swimlanes-42K2YHIH-BkSppxp8.js → swimlanes-42K2YHIH-Do6L-cYg.js} +1 -1
  50. package/dist/{swimlanesDiagram-VR7AAH4N-c8G5pGxC.js → swimlanesDiagram-VR7AAH4N-DUzPvSVU.js} +2 -2
  51. package/dist/{timeline-definition-24CTP7MA-CaMQayqK.js → timeline-definition-24CTP7MA-D3c46WM5.js} +1 -1
  52. package/dist/{toDate-BNJf01u1.js → toDate-vIXljnsr.js} +39 -38
  53. package/dist/{vega-component-DG29TAB7.js → vega-component-DTG6zxaY.js} +3 -3
  54. package/dist/{vennDiagram-4TSXK5OY-CF8pfaK3.js → vennDiagram-4TSXK5OY-BSZD8JcZ.js} +1 -1
  55. package/dist/{wardleyDiagram-VM6X3IG4-dGPu39d-.js → wardleyDiagram-VM6X3IG4-48cUWkfA.js} +1 -1
  56. package/dist/{xychartDiagram-S5SC5T6Z-CP6-9q56.js → xychartDiagram-S5SC5T6Z-CswYgYeu.js} +1 -1
  57. package/package.json +1 -1
  58. package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
  59. package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
  60. package/src/components/data-table/context-menu.tsx +125 -26
  61. package/src/components/data-table/date-filter-inputs.tsx +15 -42
  62. package/src/components/data-table/utils.ts +18 -0
  63. package/src/components/editor/Output.tsx +5 -2
  64. package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
  65. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +167 -0
  66. package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
  67. package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +82 -0
  68. package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
  69. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +434 -0
  70. package/src/components/editor/errors/send-error-report-button.tsx +66 -0
  71. package/src/components/editor/output/MarimoErrorOutput.tsx +21 -5
  72. package/src/components/editor/output/MarimoTracebackOutput.tsx +9 -0
  73. package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
  74. package/src/components/editor/output/ansi-reduce.ts +6 -0
  75. package/src/core/attachments/state.ts +21 -0
  76. package/src/core/cells/__tests__/cells.test.ts +52 -0
  77. package/src/core/cells/__tests__/error-report.test.ts +89 -0
  78. package/src/core/cells/__tests__/session.test.ts +34 -0
  79. package/src/core/cells/error-report.ts +55 -0
  80. package/src/core/cells/session.ts +9 -0
  81. package/src/core/islands/__tests__/bootstrap.test.ts +26 -0
  82. package/src/core/islands/bootstrap.ts +1 -0
  83. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +193 -0
  84. package/src/core/websocket/useMarimoKernelConnection.tsx +9 -0
  85. package/src/utils/__tests__/dates.test.ts +116 -0
  86. package/src/utils/dates.ts +94 -0
  87. package/dist/error-entries-CzoYkIQZ.js +0 -56
@@ -9,7 +9,7 @@ import "./chunk-4HAMMTFA-D4eFPyFh.js";
9
9
  import "./chunk-GVQU2GXP-Cwbt-lF0.js";
10
10
  import "./chunk-L3NEJ4N5-n-zgIVSy.js";
11
11
  import { o as n } from "./chunk-OSK3NFVY-DXa-Cxbn.js";
12
- import { c as r } from "./mermaid-CiAXjLpA.js";
12
+ import { c as r } from "./mermaid-CHo49Yv-.js";
13
13
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/swimlanes-42K2YHIH.mjs
14
14
  var i = 5, a = 1e-5, o = 1e-6;
15
15
  function s(e) {
@@ -9,11 +9,11 @@ import "./chunk-4HAMMTFA-D4eFPyFh.js";
9
9
  import "./chunk-GVQU2GXP-Cwbt-lF0.js";
10
10
  import "./chunk-L3NEJ4N5-n-zgIVSy.js";
11
11
  import "./chunk-OSK3NFVY-DXa-Cxbn.js";
12
- import "./mermaid-CiAXjLpA.js";
12
+ import "./mermaid-CHo49Yv-.js";
13
13
  import "./chunk-F27PBJKO-ufseIn5y.js";
14
14
  import "./chunk-XXDRQBXY-Dnl5VBqG.js";
15
15
  import "./chunk-POPQ4Y6H-hYOXbYH_.js";
16
- import { r as t, t as n } from "./chunk-SHT3W25Y-lHiGx3ZC.js";
16
+ import { r as t, t as n } from "./chunk-SHT3W25Y-CV9J3rAB.js";
17
17
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/swimlanesDiagram-VR7AAH4N.mjs
18
18
  var r = n({
19
19
  defaultLayout: "swimlane",
@@ -3,7 +3,7 @@ import { p as t } from "./chunk-75Z2AOVW-D7gxIs2Q.js";
3
3
  import { n, t as r } from "./src-CA_m4ONl.js";
4
4
  import { n as i, t as a } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
5
5
  import { $ as o, J as s, a as c, b as l, et as u, nt as d, o as f, x as p } from "./chunk-DU6HZSFF-BwiyaNpg.js";
6
- import { p as m } from "./mermaid-CiAXjLpA.js";
6
+ import { p as m } from "./mermaid-CHo49Yv-.js";
7
7
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/timeline-definition-24CTP7MA.mjs
8
8
  var h = (function() {
9
9
  var e = /* @__PURE__ */ i(function(e, t, n, r) {
@@ -465,54 +465,55 @@ function M({ href: e, queryParams: t, keys: n }) {
465
465
  let m = f.toString();
466
466
  return m ? `${o}?${m}${s}` : e;
467
467
  }
468
- a(null);
469
- var N = (0, O.init)({ length: 6 });
470
- function P() {
471
- return `s_${N()}`;
468
+ //#endregion
469
+ //#region src/core/kernel/session.ts
470
+ var N = a(null), P = (0, O.init)({ length: 6 });
471
+ function F() {
472
+ return `s_${P()}`;
472
473
  }
473
- function F(e) {
474
+ function I(e) {
474
475
  return e ? /^s_[\da-z]{6}$/.test(e) : !1;
475
476
  }
476
- var I = null;
477
- function L() {
478
- let e = o.get(v) === "edit", n = new URL(window.location.href).searchParams.get(s.sessionId), r = F(n) ? n : null;
477
+ var L = null;
478
+ function R() {
479
+ let e = o.get(v) === "edit", n = new URL(window.location.href).searchParams.get(s.sessionId), r = I(n) ? n : null;
479
480
  return k((t) => {
480
481
  if (!e) {
481
482
  t.delete(s.sessionId), t.delete(s.kiosk);
482
483
  return;
483
484
  }
484
485
  t.has(s.kiosk) || t.delete(s.sessionId);
485
- }), r === null ? (t.debug("Starting a new session", { sessionId: n }), P()) : e ? (t.debug("Connecting to existing session", { sessionId: r }), r) : (t.debug("Ignoring session_id from URL outside the editor", { sessionId: r }), P());
486
+ }), r === null ? (t.debug("Starting a new session", { sessionId: n }), F()) : e ? (t.debug("Connecting to existing session", { sessionId: r }), r) : (t.debug("Ignoring session_id from URL outside the editor", { sessionId: r }), F());
486
487
  }
487
- function R() {
488
- return I === null && (I = L()), I;
488
+ function z() {
489
+ return L === null && (L = R()), L;
489
490
  }
490
491
  //#endregion
491
492
  //#region src/core/static/static-state.ts
492
- function z(e) {
493
+ function B(e) {
493
494
  if (typeof e != "object" || !e || Array.isArray(e)) return !1;
494
495
  for (let t of Object.values(e)) if (typeof t != "string") return !1;
495
496
  return !0;
496
497
  }
497
- function B(e) {
498
+ function V(e) {
498
499
  if (typeof e != "object" || !e || Array.isArray(e)) return !1;
499
500
  let t = e;
500
- return !(!z(t.files) || t.modelNotifications !== void 0 && !Array.isArray(t.modelNotifications));
501
- }
502
- function V() {
503
- let e = typeof window > "u" ? void 0 : window.__MARIMO_STATIC__;
504
- return B(e) ? e : void 0;
501
+ return !(!B(t.files) || t.modelNotifications !== void 0 && !Array.isArray(t.modelNotifications));
505
502
  }
506
503
  function H() {
507
- return V() !== void 0;
504
+ let e = typeof window > "u" ? void 0 : window.__MARIMO_STATIC__;
505
+ return V(e) ? e : void 0;
508
506
  }
509
507
  function U() {
510
- let e = V();
508
+ return H() !== void 0;
509
+ }
510
+ function W() {
511
+ let e = H();
511
512
  return l(e !== void 0, "Not a static notebook"), e.files;
512
513
  }
513
514
  //#endregion
514
515
  //#region src/core/runtime/runtime.ts
515
- var W = class {
516
+ var G = class {
516
517
  initialHealthyCheck = new m();
517
518
  config;
518
519
  lazy;
@@ -535,7 +536,7 @@ var W = class {
535
536
  return this.httpURL.origin === window.location.origin;
536
537
  }
537
538
  get isServerless() {
538
- return p() || c() || H();
539
+ return p() || c() || U();
539
540
  }
540
541
  formatHttpURL({ path: e = "", searchParams: t, restrictToKnownQueryParams: n = !0 }) {
541
542
  let r = this.httpURL, i = new URLSearchParams(window.location.search);
@@ -559,7 +560,7 @@ var W = class {
559
560
  searchParams: t,
560
561
  restrictToKnownQueryParams: !1
561
562
  });
562
- return G(this.appendCrossOriginAuth(n).toString());
563
+ return K(this.appendCrossOriginAuth(n).toString());
563
564
  }
564
565
  getSessionSearchParams(e) {
565
566
  let t = new URL(this.config.url), n = new URLSearchParams(t.search);
@@ -645,17 +646,17 @@ var W = class {
645
646
  }
646
647
  headers() {
647
648
  let e = {
648
- "Marimo-Session-Id": R(),
649
+ "Marimo-Session-Id": z(),
649
650
  "Marimo-Server-Token": this.config.serverToken ?? "",
650
651
  "x-runtime-url": this.httpURL.toString()
651
652
  };
652
653
  return this.config.authToken && (e.Authorization = `Bearer ${this.config.authToken}`), e;
653
654
  }
654
655
  sessionHeaders() {
655
- return { "Marimo-Session-Id": R() };
656
+ return { "Marimo-Session-Id": z() };
656
657
  }
657
658
  };
658
- function G(e) {
659
+ function K(e) {
659
660
  if (!e.startsWith("http")) {
660
661
  t.warn(`URL must start with http: ${e}`);
661
662
  let n = new URL(e);
@@ -665,29 +666,29 @@ function G(e) {
665
666
  }
666
667
  //#endregion
667
668
  //#region src/core/runtime/config.ts
668
- function K() {
669
+ function q() {
669
670
  let e = new URL(document.baseURI);
670
671
  return e.search = "", e.hash = "", e.toString();
671
672
  }
672
- var q = {
673
+ var J = {
673
674
  lazy: !0,
674
- url: K()
675
- }, J = a(q), Y = a((e) => {
676
- let t = e(J);
677
- return new W(t, t.lazy);
675
+ url: q()
676
+ }, Y = a(J), ee = a((e) => {
677
+ let t = e(Y);
678
+ return new G(t, t.lazy);
678
679
  });
679
680
  function X() {
680
- return o.get(Y);
681
+ return o.get(ee);
681
682
  }
682
- function ee(e) {
683
+ function te(e) {
683
684
  if (e.startsWith("http")) return new URL(e);
684
685
  let t = X().httpURL.toString();
685
686
  return t.startsWith("blob:") && (t = t.replace("blob:", "")), new URL(e, t);
686
687
  }
687
688
  //#endregion
688
689
  //#region ../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/constants.js
689
- var te = 365.2425, ne = 6048e5, re = 864e5, Z = 86400;
690
- Z * 7, Z * te / 12 * 3;
690
+ var ne = 365.2425, re = 6048e5, ie = 864e5, Z = 86400;
691
+ Z * 7, Z * ne / 12 * 3;
691
692
  var Q = Symbol.for("constructDateFrom");
692
693
  //#endregion
693
694
  //#region ../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/constructFrom.js
@@ -696,8 +697,8 @@ function $(e, t) {
696
697
  }
697
698
  //#endregion
698
699
  //#region ../node_modules/.pnpm/date-fns@4.4.0/node_modules/date-fns/toDate.js
699
- function ie(e, t) {
700
+ function ae(e, t) {
700
701
  return $(t || e, e);
701
702
  }
702
703
  //#endregion
703
- export { u as S, x as _, ee as a, p as b, H as c, k as d, D as f, b as g, y as h, ne as i, M as l, v as m, $ as n, X as o, g as p, re as r, U as s, ie as t, j as u, _ as v, f as x, m as y };
704
+ export { u as C, f as S, b as _, te as a, m as b, U as c, j as d, k as f, y as g, v as h, re as i, N as l, g as m, $ as n, X as o, D as p, ie as r, W as s, ae as t, M as u, x as v, p as x, _ as y };
@@ -3,15 +3,15 @@ import { g as t, h as n, m as r, o as i } from "./button-CvjkwdSk.js";
3
3
  import { t as a } from "./react-sHtZdjeP.js";
4
4
  import { t as o } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { t as s } from "./tooltip-BO1REbqs.js";
6
- import { S as c, a as l } from "./toDate-BNJf01u1.js";
6
+ import { C as c, a as l } from "./toDate-vIXljnsr.js";
7
7
  import { t as u } from "./jsx-runtime-3BD1kT0s.js";
8
- import { n as d } from "./error-banner-Da600cwz.js";
8
+ import { n as d } from "./error-banner-D-WCIiMt.js";
9
9
  import { t as f } from "./debounce-C3jyATpc.js";
10
10
  import { A as p, n as ee } from "./useTheme-CRnjkku0.js";
11
11
  import { c as m } from "./arrays-CN1djC4k.js";
12
12
  import { t as te } from "./objects-CzUgoMIF.js";
13
13
  import { t as h } from "./useAsyncData-Deh5kszT.js";
14
- import { a as ne, i as re, n as ie, t as g } from "./formats-BGh2thRc.js";
14
+ import { a as ne, i as re, n as ie, t as g } from "./formats-CeOmU1MU.js";
15
15
  import { M as ae, n as oe } from "./vega-loader.browser-DNST6uVf.js";
16
16
  import { t as se } from "./react-vega-BED0DjiB.js";
17
17
  import { a as ce, n as _ } from "./loader-BQOfjTIJ.js";
@@ -3,7 +3,7 @@ import { t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { $ as r, H as i, K as a, U as o, a as s, b as c, c as l, et as u, f as d, nt as f, tt as p, v as m, w as h, y as g } from "./chunk-DU6HZSFF-BwiyaNpg.js";
5
5
  import { t as _ } from "./rough.esm-CtV9AnV1.js";
6
- import { p as v } from "./mermaid-CiAXjLpA.js";
6
+ import { p as v } from "./mermaid-CHo49Yv-.js";
7
7
  //#region ../node_modules/.pnpm/khroma@2.1.0/node_modules/khroma/dist/methods/transparentize.js
8
8
  var y = (e, t) => p(e, "a", -t), b = 1e-10;
9
9
  function x(e, t) {
@@ -2,7 +2,7 @@ import { i as e } from "./chunk-75Z2AOVW-D7gxIs2Q.js";
2
2
  import { n as t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { D as r, H as i, K as a, U as o, a as s, b as c, c as l, v as u, w as d, x as f, y as p } from "./chunk-DU6HZSFF-BwiyaNpg.js";
5
- import { p as m } from "./mermaid-CiAXjLpA.js";
5
+ import { p as m } from "./mermaid-CHo49Yv-.js";
6
6
  import { n as h } from "./mermaid-parser.core-DxuSfYwJ.js";
7
7
  import { t as g } from "./chunk-JWPE2WC7-DJvv1t8U.js";
8
8
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/wardleyDiagram-VM6X3IG4.mjs
@@ -9,7 +9,7 @@ import { n as s } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
9
9
  import { D as c, H as l, K as u, U as d, a as f, b as p, c as m, f as h, v as g, w as _, y as v, z as y } from "./chunk-DU6HZSFF-BwiyaNpg.js";
10
10
  import "./chunk-PWAF6VOD-CQw5qATZ.js";
11
11
  import { t as b } from "./chunk-GMAD6QVW-BhaJx0X3.js";
12
- import { p as x } from "./mermaid-CiAXjLpA.js";
12
+ import { p as x } from "./mermaid-CHo49Yv-.js";
13
13
  //#region ../node_modules/.pnpm/d3-scale@4.0.2/node_modules/d3-scale/src/band.js
14
14
  function S() {
15
15
  var e = t().unknown(void 0), r = e.domain, i = e.range, o = 0, s = 1, c, l, u = !1, d = 0, f = 0, p = .5;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev3",
3
+ "version": "0.25.3-dev5",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,176 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
4
+ import { buildCellFilter } from "../context-menu";
5
+
6
+ describe("buildCellFilter", () => {
7
+ // Use a non-UTC, non-DST-ambiguous offset so date-only parsing bugs
8
+ // (UTC vs. local midnight) can't hide behind a host machine that
9
+ // happens to run in UTC.
10
+ let originalTimezone: string | undefined;
11
+ beforeAll(() => {
12
+ originalTimezone = process.env.TZ;
13
+ process.env.TZ = "America/New_York";
14
+ });
15
+ afterAll(() => {
16
+ process.env.TZ = originalTimezone;
17
+ });
18
+
19
+ it("builds an equality filter for a normal date value", () => {
20
+ const filter = buildCellFilter({
21
+ type: "date",
22
+ value: "2024-01-15",
23
+ comparison: "eq",
24
+ dataType: "date",
25
+ dtype: "date",
26
+ });
27
+ expect(filter).toEqual({
28
+ type: "date",
29
+ operator: "==",
30
+ // Must be local midnight, not `new Date("2024-01-15")` (UTC
31
+ // midnight), or the filter shifts by a day in UTC- timezones.
32
+ value: new Date(2024, 0, 15),
33
+ });
34
+ });
35
+
36
+ it("returns undefined for an empty-string date value in a non-temporal-looking context", () => {
37
+ const filter = buildCellFilter({
38
+ type: "date",
39
+ value: "",
40
+ comparison: "eq",
41
+ dataType: "date",
42
+ dtype: "date",
43
+ });
44
+ expect(filter).toBeUndefined();
45
+ });
46
+
47
+ it("returns undefined for an unparsable date value instead of an Invalid Date filter", () => {
48
+ const filter = buildCellFilter({
49
+ type: "date",
50
+ value: "not-a-date",
51
+ comparison: "eq",
52
+ dataType: "date",
53
+ dtype: "date",
54
+ });
55
+ expect(filter).toBeUndefined();
56
+ });
57
+
58
+ it("builds an equality filter for a normal datetime value", () => {
59
+ const filter = buildCellFilter({
60
+ type: "datetime",
61
+ value: "2024-01-15 08:30:00",
62
+ comparison: "eq",
63
+ dataType: "datetime",
64
+ dtype: "datetime64[ns]",
65
+ });
66
+ expect(filter).toEqual({
67
+ type: "datetime",
68
+ operator: "==",
69
+ value: new Date(2024, 0, 15, 8, 30, 0),
70
+ });
71
+ });
72
+
73
+ it("returns undefined for an unparsable datetime value", () => {
74
+ const filter = buildCellFilter({
75
+ type: "datetime",
76
+ value: "not-a-datetime",
77
+ comparison: "eq",
78
+ dataType: "datetime",
79
+ dtype: "datetime64[ns]",
80
+ });
81
+ expect(filter).toBeUndefined();
82
+ });
83
+
84
+ it("builds an equality filter for a normal time value", () => {
85
+ const filter = buildCellFilter({
86
+ type: "time",
87
+ value: "08:30:00",
88
+ comparison: "eq",
89
+ dataType: "time",
90
+ });
91
+ expect(filter).toEqual({
92
+ type: "time",
93
+ operator: "==",
94
+ value: new Date(1970, 0, 1, 8, 30, 0),
95
+ });
96
+ });
97
+
98
+ it("returns undefined instead of an unparsable time value", () => {
99
+ const filter = buildCellFilter({
100
+ type: "time",
101
+ value: "25:00:00",
102
+ comparison: "eq",
103
+ dataType: "time",
104
+ });
105
+ expect(filter).toBeUndefined();
106
+ });
107
+
108
+ it("maps a NaT date value to is_null instead of an invalid Date filter", () => {
109
+ const filter = buildCellFilter({
110
+ type: "date",
111
+ value: "NaT",
112
+ comparison: "eq",
113
+ dataType: "date",
114
+ dtype: "date",
115
+ });
116
+ expect(filter).toEqual({ type: "date", operator: "is_null" });
117
+ });
118
+
119
+ it("maps a NaT datetime value to is_not_null for the neq comparison", () => {
120
+ const filter = buildCellFilter({
121
+ type: "datetime",
122
+ value: "NaT",
123
+ comparison: "neq",
124
+ dataType: "datetime",
125
+ dtype: "datetime64[ns]",
126
+ });
127
+ expect(filter).toEqual({ type: "datetime", operator: "is_not_null" });
128
+ });
129
+
130
+ it("does not treat the string 'NaT' in a non-temporal column as a sentinel", () => {
131
+ const filter = buildCellFilter({
132
+ type: "text",
133
+ value: "NaT",
134
+ comparison: "eq",
135
+ dataType: "string",
136
+ });
137
+ expect(filter).toEqual({ type: "text", operator: "equals", text: "NaT" });
138
+ });
139
+
140
+ it("maps an actual null value to is_null", () => {
141
+ const filter = buildCellFilter({
142
+ type: "number",
143
+ value: null,
144
+ comparison: "eq",
145
+ dataType: "number",
146
+ });
147
+ expect(filter).toEqual({ type: "number", operator: "is_null" });
148
+ });
149
+
150
+ it("builds a literal (always-false) equality filter for a NaN number value", () => {
151
+ // NaN is a real float value, not a missing-value marker like null/NaT,
152
+ // and the backend's is_null() (narwhals/polars semantics) doesn't match
153
+ // it, so it falls through to a normal (if unsatisfiable) == filter.
154
+ const filter = buildCellFilter({
155
+ type: "number",
156
+ value: Number.NaN,
157
+ comparison: "eq",
158
+ dataType: "number",
159
+ });
160
+ expect(filter).toEqual({
161
+ type: "number",
162
+ operator: "==",
163
+ value: Number.NaN,
164
+ });
165
+ });
166
+
167
+ it("builds a literal equality filter for a normal number value", () => {
168
+ const filter = buildCellFilter({
169
+ type: "number",
170
+ value: 42,
171
+ comparison: "eq",
172
+ dataType: "number",
173
+ });
174
+ expect(filter).toEqual({ type: "number", operator: "==", value: 42 });
175
+ });
176
+ });
@@ -1,7 +1,30 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { dateToLocalISODate } from "@/utils/dates";
4
- import { parsePastedRange } from "../date-filter-inputs";
4
+ import { parsePastedDate, parsePastedRange } from "../date-filter-inputs";
5
+
6
+ describe("parsePastedDate", () => {
7
+ it("parses a time-only string for the time filter type", () => {
8
+ const result = parsePastedDate("time", "2:30 PM");
9
+ expect(result).toEqual(new Date(1970, 0, 1, 14, 30));
10
+ });
11
+
12
+ it("parses a local ISO datetime for the datetime filter type", () => {
13
+ const result = parsePastedDate("datetime", "2026-02-01T08:30:00");
14
+ expect(result).toEqual(new Date(2026, 1, 1, 8, 30, 0));
15
+ });
16
+
17
+ it("falls back to the Date constructor for other formats", () => {
18
+ const result = parsePastedDate("datetime", "Feb 1, 2026 08:30:00");
19
+ expect(result).toBeDefined();
20
+ expect(result?.getFullYear()).toBe(2026);
21
+ });
22
+
23
+ it("returns undefined for an empty or unparsable string", () => {
24
+ expect(parsePastedDate("date", "")).toBeUndefined();
25
+ expect(parsePastedDate("time", "not-a-time")).toBeUndefined();
26
+ });
27
+ });
5
28
 
6
29
  describe("parsePastedRange", () => {
7
30
  it.each([
@@ -1,12 +1,19 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import type { DataType } from "@/core/kernel/messages";
4
+ import { assertNever } from "@/utils/assertNever";
5
+ import { copyToClipboard } from "@/utils/copy";
6
+ import {
7
+ parseLocalISODate,
8
+ parseLocalISODateTime,
9
+ parseTimeToDate,
10
+ } from "@/utils/dates";
11
+ import { Logger } from "@/utils/Logger";
3
12
  import type { Cell } from "@tanstack/react-table";
4
13
  import { useAtomValue } from "jotai";
5
14
  import { CopyIcon, FilterIcon, SquareStack } from "lucide-react";
6
15
  import type { RefObject } from "react";
7
16
  import useEvent from "react-use-event-hook";
8
- import { copyToClipboard } from "@/utils/copy";
9
- import { Logger } from "@/utils/Logger";
10
17
  import {
11
18
  ContextMenu,
12
19
  ContextMenuContent,
@@ -16,13 +23,94 @@ import {
16
23
  ContextMenuTrigger,
17
24
  } from "../ui/context-menu";
18
25
  import { DATA_CELL_ID } from "./cell-utils";
19
- import {
20
- Filter,
21
- isMembershipFilterType,
22
- type MembershipFilterType,
23
- } from "./filters";
26
+ import { type FilterType, Filter } from "./filters";
24
27
  import { selectedCellsAtom } from "./range-focus/atoms";
25
- import { getClipboardContent, getRawValue } from "./utils";
28
+ import { getClipboardContent, getRawValue, isNullishSentinel } from "./utils";
29
+
30
+ type Comparison = "eq" | "neq";
31
+
32
+ const symbolOp = {
33
+ eq: "==",
34
+ neq: "!=",
35
+ } as const;
36
+
37
+ const textOp = {
38
+ eq: "equals",
39
+ neq: "does_not_equal",
40
+ } as const;
41
+
42
+ export function buildCellFilter({
43
+ type,
44
+ value,
45
+ comparison = "eq",
46
+ dataType,
47
+ dtype,
48
+ }: {
49
+ type: FilterType;
50
+ value: unknown;
51
+ comparison?: Comparison;
52
+ dataType?: DataType;
53
+ dtype?: string;
54
+ }) {
55
+ if (isNullishSentinel(value, dataType, dtype)) {
56
+ return { type, operator: comparison === "eq" ? "is_null" : "is_not_null" };
57
+ }
58
+
59
+ switch (type) {
60
+ case "number":
61
+ if (typeof value !== "number") {
62
+ return undefined;
63
+ }
64
+
65
+ return Filter.number({
66
+ operator: symbolOp[comparison],
67
+ value,
68
+ });
69
+ case "text":
70
+ return Filter.text({
71
+ operator: textOp[comparison],
72
+ text: value as string,
73
+ });
74
+ case "date": {
75
+ const date = parseLocalISODate(value as string);
76
+ if (!date) {
77
+ return undefined;
78
+ }
79
+ return Filter.date({
80
+ operator: symbolOp[comparison],
81
+ value: date,
82
+ });
83
+ }
84
+ case "datetime": {
85
+ const date = parseLocalISODateTime(value as string);
86
+ if (!date) {
87
+ return undefined;
88
+ }
89
+ return Filter.datetime({
90
+ operator: symbolOp[comparison],
91
+ value: date,
92
+ });
93
+ }
94
+ case "time": {
95
+ const time = parseTimeToDate(value as string);
96
+ if (!time) {
97
+ return undefined;
98
+ }
99
+ return Filter.time({
100
+ operator: symbolOp[comparison],
101
+ value: time,
102
+ });
103
+ }
104
+ case "boolean": {
105
+ const target = comparison === "eq" ? value : !(value as boolean);
106
+ return Filter.boolean({
107
+ operator: target ? "is_true" : "is_false",
108
+ });
109
+ }
110
+ default:
111
+ assertNever(type);
112
+ }
113
+ }
26
114
 
27
115
  export const DataTableContextMenu = <TData,>({
28
116
  contextMenuRef,
@@ -102,19 +190,34 @@ export const CellContextMenu = <TData,>({
102
190
 
103
191
  const column = cell.column;
104
192
  const filterType = column.columnDef.meta?.filterType;
105
- const membershipFilterType: MembershipFilterType | undefined =
106
- column.getCanFilter() && filterType && isMembershipFilterType(filterType)
107
- ? filterType
193
+ const dataType = column.columnDef.meta?.dataType;
194
+ const dtype = column.columnDef.meta?.dtype;
195
+
196
+ const canFilter = Boolean(filterType && column.getCanFilter());
197
+ const buildFilter = (comparison: Comparison) =>
198
+ canFilter
199
+ ? buildCellFilter({
200
+ type: filterType as FilterType,
201
+ value: rawValue,
202
+ comparison,
203
+ dataType,
204
+ dtype,
205
+ })
108
206
  : undefined;
207
+ const eqFilter = buildFilter("eq");
208
+ const canFilterByValue = eqFilter !== undefined;
209
+
210
+ const handleFilterCellByValue = (comparison: Comparison) => {
211
+ if (!filterType) {
212
+ return;
213
+ }
214
+
215
+ const filter = comparison === "eq" ? eqFilter : buildFilter("neq");
216
+
217
+ if (!filter) {
218
+ return;
219
+ }
109
220
 
110
- const handleFilterCell = (
111
- type: MembershipFilterType,
112
- operator: "in" | "not_in",
113
- ) => {
114
- const filter =
115
- type === "number"
116
- ? Filter.number({ operator, values: [rawValue] })
117
- : Filter.text({ operator, values: [rawValue] });
118
221
  column.setFilterValue(filter);
119
222
  };
120
223
 
@@ -130,18 +233,14 @@ export const CellContextMenu = <TData,>({
130
233
  Copy selected cells
131
234
  </ContextMenuItem>
132
235
  )}
133
- {membershipFilterType && (
236
+ {canFilterByValue && (
134
237
  <>
135
238
  <ContextMenuSeparator />
136
- <ContextMenuItem
137
- onClick={() => handleFilterCell(membershipFilterType, "in")}
138
- >
239
+ <ContextMenuItem onClick={() => handleFilterCellByValue("eq")}>
139
240
  <FilterIcon className="mo-dropdown-icon h-3 w-3" />
140
241
  Filter by this value
141
242
  </ContextMenuItem>
142
- <ContextMenuItem
143
- onClick={() => handleFilterCell(membershipFilterType, "not_in")}
144
- >
243
+ <ContextMenuItem onClick={() => handleFilterCellByValue("neq")}>
145
244
  <FilterIcon className="mo-dropdown-icon h-3 w-3" />
146
245
  Remove rows with this value
147
246
  </ContextMenuItem>