@marimo-team/islands 0.25.2-dev121 → 0.25.2-dev123
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/{ErrorBoundary-Bo3Tg7Jh.js → ErrorBoundary-DwtvpxIv.js} +1 -1
- package/dist/{code-visibility-WFM7uHBf.js → code-visibility-C5K6EQNt.js} +1 -1
- package/dist/{common-BLHW2E-1.js → common-CpPQFLxA.js} +1 -1
- package/dist/{data-grid-overlay-editor-Dt75J_Qe.js → data-grid-overlay-editor-rL_cgvYA.js} +1 -1
- package/dist/{feedback-button-pfhtTNjh.js → feedback-button-DhkM0S0C.js} +2 -2
- package/dist/{glide-data-editor-B3x7mDpj.js → glide-data-editor-TNcL0ZIF.js} +3 -3
- package/dist/{globals-6B7ecxsC.js → globals-CwtFrEmN.js} +1 -1
- package/dist/main.js +36 -28
- package/dist/{number-overlay-editor-CyJwIeU1.js → number-overlay-editor-ZgUJMA6H.js} +1 -1
- package/dist/{reveal-component-CPohnNHB.js → reveal-component-CRHNdWDY.js} +2 -2
- package/package.json +1 -1
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +4 -3
- package/src/components/storage/__tests__/storage-file-viewer.test.tsx +2 -1
- package/src/core/codemirror/language/__tests__/sql.test.ts +4 -3
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +18 -11
- package/src/core/islands/bridge.ts +2 -2
- package/src/core/kernel/messages.ts +1 -1
- package/src/core/wasm/bridge.ts +2 -2
- package/src/core/wasm/worker/types.ts +2 -2
- package/src/plugins/impl/NumberPlugin.tsx +20 -3
- package/src/plugins/impl/__tests__/NumberPlugin.test.tsx +159 -1
|
@@ -135,7 +135,7 @@ function F(e) {
|
|
|
135
135
|
}
|
|
136
136
|
//#endregion
|
|
137
137
|
//#region src/components/editor/boundary/ErrorBoundary.tsx
|
|
138
|
-
var I = (0, T.lazy)(() => import("./feedback-button-
|
|
138
|
+
var I = (0, T.lazy)(() => import("./feedback-button-DhkM0S0C.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
|
|
139
139
|
let t = (0, w.c)(2), n;
|
|
140
140
|
return t[0] === e.children ? n = t[1] : (n = /* @__PURE__ */ (0, j.jsx)(O, {
|
|
141
141
|
FallbackComponent: R,
|
|
@@ -18,7 +18,7 @@ function x() {
|
|
|
18
18
|
return e.warn("Failed to get version from mount config"), null;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
var S = x() || "0.25.2-
|
|
21
|
+
var S = x() || "0.25.2-dev123", C = u(S), w = u(!0);
|
|
22
22
|
u(null);
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/core/wasm/state.ts
|
|
@@ -12,7 +12,7 @@ import { t as ct } from "./check-EDwSwP89.js";
|
|
|
12
12
|
import { A as lt, C as ut, M as dt, O as ft, S as pt, _ as mt, b as ht, c as gt, d as _t, g as vt, h as yt, i as bt, l as xt, m as St, n as Ct, p as wt, s as Tt, t as Et, u as Dt, v as Ot, y as kt } from "./select-BButFi-d.js";
|
|
13
13
|
import { $ as At, $t as jt, A as Mt, At as Nt, B as Pt, Bt as Ft, Ct as It, D as Lt, Dt as Rt, E as zt, Et as Bt, F as Vt, Ft as Ht, G as Ut, Gt as Wt, H as Gt, Ht as Kt, I as qt, It as Jt, J as Yt, Jt as Xt, Kt as Zt, L as Qt, Lt as $t, M as en, Mt as tn, N as nn, Nt as rn, O as an, Ot as on, P as sn, Pt as cn, Q as ln, Qt as un, R as dn, Rt as fn, S as pn, St as mn, T as hn, Tt as gn, U as _n, Ut as vn, V as yn, Vt as bn, W as xn, Wt as Sn, X as Cn, Xt as wn, Y as Tn, Yt as En, Z as Dn, Zt as On, _ as kn, _n as An, _t as jn, a as Mn, at as Nn, b as Pn, bt as Fn, cn as In, ct as Ln, d as Rn, dn as zn, dt as Bn, et as Vn, f as Hn, fn as Un, ft as Wn, gn as Gn, gt as Kn, h as qn, hn as Jn, ht as Yn, i as Xn, in as Zn, it as Qn, j as $n, jt as er, k as tr, kt as nr, l as rr, lt as ir, mn as ar, mt as or, n as sr, nn as cr, nt as lr, o as ur, on as dr, ot as fr, pn as pr, pt as mr, qt as hr, rn as gr, rt as _r, s as vr, sn as yr, st as br, t as xr, tn as Sr, tt as Cr, u as wr, un as Tr, vn as Er, vt as Dr, w as Or, wt as kr, x as Ar, xt as jr, y as Mr, yt as Nr, z as Pr, zt as Fr } from "./dropdown-menu-CP_qCYHC.js";
|
|
14
14
|
import { C as Ir, a as Lr, b as Rr, c as zr, d as Br, i as Vr, n as Hr, o as Ur, p as Wr, r as Gr, s as Kr, t as qr, x as Jr } from "./toDate-Dwcg_x_5.js";
|
|
15
|
-
import { n as Yr, t as Xr } from "./ErrorBoundary-
|
|
15
|
+
import { n as Yr, t as Xr } from "./ErrorBoundary-DwtvpxIv.js";
|
|
16
16
|
import { t as Zr } from "./clsx-CoeGtWvn.js";
|
|
17
17
|
import { t as Qr } from "./react-dom-DUmH0GXv.js";
|
|
18
18
|
import { t as $r } from "./jsx-runtime-3BD1kT0s.js";
|
|
@@ -2,7 +2,7 @@ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
|
|
|
2
2
|
import { t } from "./react-sHtZdjeP.js";
|
|
3
3
|
import { t as n } from "./react-dom-DUmH0GXv.js";
|
|
4
4
|
import { c as r, l as i, u as a } from "./data-grid-types-BH_r7g7l.js";
|
|
5
|
-
import { a as o, i as s, n as c, r as l } from "./glide-data-editor-
|
|
5
|
+
import { a as o, i as s, n as c, r as l } from "./glide-data-editor-TNcL0ZIF.js";
|
|
6
6
|
//#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_aca11a353ce3b112922852200b9c160f/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/data-grid-overlay-editor-style.js
|
|
7
7
|
var u = /* @__PURE__ */ e(t(), 1), d = /* @__PURE__ */ e(n(), 1), f = /*#__PURE__*/ o("div")({
|
|
8
8
|
name: "DataGridOverlayEditorStyle",
|
|
@@ -5,12 +5,12 @@ import { t as i } from "./compiler-runtime-CldRdSsv.js";
|
|
|
5
5
|
import { t as a } from "./copy-icon-Ft7t9bqz.js";
|
|
6
6
|
import { Ct as o, Ft as s, H as c, L as l, Lt as u, V as d, d as f, un as p } from "./cells-CuYwqnV8.js";
|
|
7
7
|
import { b as m } from "./select-BButFi-d.js";
|
|
8
|
-
import { n as h, t as ee } from "./globals-
|
|
8
|
+
import { n as h, t as ee } from "./globals-CwtFrEmN.js";
|
|
9
9
|
import { t as g } from "./jsx-runtime-3BD1kT0s.js";
|
|
10
10
|
import { C as _, _ as te, i as v } from "./useTheme-CRnjkku0.js";
|
|
11
11
|
import { a as ne, i as re, n as ie, r as ae } from "./dialog-CEBFZNyc.js";
|
|
12
12
|
import { t as oe } from "./useAsyncData-Deh5kszT.js";
|
|
13
|
-
import { t as se } from "./code-visibility-
|
|
13
|
+
import { t as se } from "./code-visibility-C5K6EQNt.js";
|
|
14
14
|
import { i as ce, n as le } from "./error-entries-zfHL6H60.js";
|
|
15
15
|
//#region src/components/ui/skeleton.tsx
|
|
16
16
|
var y = /* @__PURE__ */ e(r(), 1), b = i(), x = g(), ue = (e) => {
|
|
@@ -6,7 +6,7 @@ import { i as s, n as c, r as l } from "./copy-icon-Ft7t9bqz.js";
|
|
|
6
6
|
import { C as u, c as d, i as f, n as p, s as m, t as h, x as g } from "./select-BButFi-d.js";
|
|
7
7
|
import { d as _, h as v, i as y, l as b, n as x, o as S, s as C, t as w, u as T } from "./dropdown-menu-CP_qCYHC.js";
|
|
8
8
|
import { c as E, d as D, l as O, n as k, o as A, s as ee, t as j, u as te } from "./glide-utils-DJyqh0EM.js";
|
|
9
|
-
import { n as ne, t as re } from "./ErrorBoundary-
|
|
9
|
+
import { n as ne, t as re } from "./ErrorBoundary-DwtvpxIv.js";
|
|
10
10
|
import { t as M } from "./react-dom-DUmH0GXv.js";
|
|
11
11
|
import { t as N } from "./jsx-runtime-3BD1kT0s.js";
|
|
12
12
|
import { t as ie } from "./label-BDKF3Afc.js";
|
|
@@ -7062,7 +7062,7 @@ function rs(e, t, n, r, i) {
|
|
|
7062
7062
|
}
|
|
7063
7063
|
//#endregion
|
|
7064
7064
|
//#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_aca11a353ce3b112922852200b9c160f/node_modules/@glideapps/glide-data-grid/dist/esm/data-editor/data-editor.js
|
|
7065
|
-
var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-
|
|
7065
|
+
var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-rL_cgvYA.js")), ss = 0;
|
|
7066
7066
|
function cs(e) {
|
|
7067
7067
|
return (0, is.default)((0, as.default)((0, as.default)(e).filter((e) => e.span !== void 0).map((e) => (0, Za.default)((e.span?.[0] ?? 0) + 1, (e.span?.[1] ?? 0) + 1))));
|
|
7068
7068
|
}
|
|
@@ -9293,7 +9293,7 @@ function Vs(e, t, n, r, i) {
|
|
|
9293
9293
|
}
|
|
9294
9294
|
//#endregion
|
|
9295
9295
|
//#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_aca11a353ce3b112922852200b9c160f/node_modules/@glideapps/glide-data-grid/dist/esm/cells/number-cell.js
|
|
9296
|
-
var Hs = K.lazy(async () => await import("./number-overlay-editor-
|
|
9296
|
+
var Hs = K.lazy(async () => await import("./number-overlay-editor-ZgUJMA6H.js")), Us = {
|
|
9297
9297
|
getAccessibilityString: (e) => e.data?.toString() ?? "",
|
|
9298
9298
|
kind: W.Number,
|
|
9299
9299
|
needsHover: (e) => e.hoverEffect === !0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { h as e } from "./tooltip-BO1REbqs.js";
|
|
2
2
|
import { _ as t } from "./useTheme-CRnjkku0.js";
|
|
3
|
-
import { r as n } from "./code-visibility-
|
|
3
|
+
import { r as n } from "./code-visibility-C5K6EQNt.js";
|
|
4
4
|
var r = e("triangle-alert", [
|
|
5
5
|
["path", {
|
|
6
6
|
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
|
package/dist/main.js
CHANGED
|
@@ -7,7 +7,7 @@ import { C as w, F as T, G as E, I as D, J as O, K as k, L as A, P as j, R as M,
|
|
|
7
7
|
import { a as oe, d as se, f as ce, h as V, i as le, n as ue, o as de, r as fe, t as pe } from "./tooltip-BO1REbqs.js";
|
|
8
8
|
import { $ as me, $t as he, B as ge, Bt as _e, C as ve, Ct as ye, D as be, Dt as xe, Et as Se, F as Ce, G as we, Gt as Te, Ht as Ee, I as De, J as Oe, Jt as ke, Kt as Ae, L as je, O as Me, Ot as Ne, P as Pe, Pt as Fe, Q as Ie, Qt as Le, Rt as Re, S as ze, St as Be, T as Ve, Tt as He, U as Ue, W as We, Wt as Ge, bt as Ke, c as qe, cn as Je, ct as Ye, d as Xe, dn as Ze, dt as Qe, en as $e, f as et, fn as tt, ft as nt, g as rt, gt as it, h as at, hn as ot, k as st, l as ct, ln as lt, m as ut, mn as dt, n as ft, o as pt, on as mt, ot as ht, p as gt, q as _t, qt as vt, r as yt, rn as bt, rt as xt, sn as St, st as Ct, tn as wt, u as Tt, v as Et, w as Dt, wt as Ot, zt as kt } from "./cells-CuYwqnV8.js";
|
|
9
9
|
import { D as At, E as jt, O as Mt, S as Nt, T as Pt, _ as Ft, a as It, c as Lt, d as Rt, f as zt, g as Bt, h as Vt, i as Ht, l as Ut, m as Wt, n as Gt, o as Kt, p as qt, r as Jt, s as Yt, t as Xt, u as Zt, v as Qt, w as $t, x as en, y as tn } from "./spec-BwarBpUJ.js";
|
|
10
|
-
import { $t as nn, A as rn, At as an, B as on, Bt as sn, C as cn, Ct as ln, D as un, Dt as dn, E as fn, Et as pn, F as mn, Ft as hn, G as gn, Gt as _n, H as vn, Ht as yn, I as bn, It as xn, J as Sn, Jt as Cn, K as wn, Kt as Tn, L as En, Lt as Dn, M as On, Mt as kn, N as An, Nt as jn, O as Mn, Ot as Nn, P as Pn, Pt as Fn, Qt as In, R as Ln, Rt as Rn, S as zn, St as Bn, T as Vn, Tt as Hn, U as Un, Ut as Wn, V as Gn, Vt as Kn, W as qn, Wt as Jn, X as Yn, Xt as Xn, Y as Zn, Yt as Qn, Zt as $n, _ as er, _t as tr, an as nr, at as rr, b as ir, c as ar, cn as or, ct as sr, d as cr, dn as lr, dt as ur, en as dr, et as fr, f as pr, fn as mr, ft as hr, g as gr, gt as _r, h as vr, hn as yr, ht as br, in as xr, it as Sr, j as Cr, jt as wr, k as Tr, kt as Er, ln as Dr, lt as Or, m as kr, mn as Ar, mt as jr, nn as Mr, nt as Nr, ot as Pr, p as Fr, pn as Ir, pt as Lr, q as Rr, qt as zr, r as Br, rn as Vr, rt as Hr, sn as Ur, st as Wr, t as Gr, tn as Kr, tt as qr, u as Jr, un as Yr, ut as Xr, v as Zr, vt as Qr, w as $r, wt as ei, x as ti, y as ni, yt as ri, z as ii, zt as ai } from "./common-
|
|
10
|
+
import { $t as nn, A as rn, At as an, B as on, Bt as sn, C as cn, Ct as ln, D as un, Dt as dn, E as fn, Et as pn, F as mn, Ft as hn, G as gn, Gt as _n, H as vn, Ht as yn, I as bn, It as xn, J as Sn, Jt as Cn, K as wn, Kt as Tn, L as En, Lt as Dn, M as On, Mt as kn, N as An, Nt as jn, O as Mn, Ot as Nn, P as Pn, Pt as Fn, Qt as In, R as Ln, Rt as Rn, S as zn, St as Bn, T as Vn, Tt as Hn, U as Un, Ut as Wn, V as Gn, Vt as Kn, W as qn, Wt as Jn, X as Yn, Xt as Xn, Y as Zn, Yt as Qn, Zt as $n, _ as er, _t as tr, an as nr, at as rr, b as ir, c as ar, cn as or, ct as sr, d as cr, dn as lr, dt as ur, en as dr, et as fr, f as pr, fn as mr, ft as hr, g as gr, gt as _r, h as vr, hn as yr, ht as br, in as xr, it as Sr, j as Cr, jt as wr, k as Tr, kt as Er, ln as Dr, lt as Or, m as kr, mn as Ar, mt as jr, nn as Mr, nt as Nr, ot as Pr, p as Fr, pn as Ir, pt as Lr, q as Rr, qt as zr, r as Br, rn as Vr, rt as Hr, sn as Ur, st as Wr, t as Gr, tn as Kr, tt as qr, u as Jr, un as Yr, ut as Xr, v as Zr, vt as Qr, w as $r, wt as ei, x as ti, y as ni, yt as ri, z as ii, zt as ai } from "./common-CpPQFLxA.js";
|
|
11
11
|
import { c as oi, i as si, n as ci, o as li, t as ui } from "./useLifecycle-j7D9uD1o.js";
|
|
12
12
|
import { t as di } from "./check-EDwSwP89.js";
|
|
13
13
|
import { A as fi, C as pi, D as mi, E as hi, M as gi, O as _i, S as vi, T as yi, a as bi, b as xi, c as Si, i as Ci, k as wi, l as Ti, n as Ei, o as Di, r as Oi, s as ki, t as Ai, w as ji, x as Mi } from "./select-BButFi-d.js";
|
|
@@ -15,8 +15,8 @@ import { $ as Ni, C as Pi, Et as Fi, J as Ii, K as Li, R as Ri, S as zi, U as Bi
|
|
|
15
15
|
import { C as ua, S as da, T as fa, _ as pa, c as ma, d as ha, f as ga, g as _a, h as va, m as ya, u as ba, x as xa, y as Sa } from "./toDate-Dwcg_x_5.js";
|
|
16
16
|
import { a as Ca, c as wa, d as Ta, f as Ea, i as Da, l as Oa, n as ka, o as Aa, r as ja, s as Ma, t as Na } from "./process-output-C1GGFU6Q.js";
|
|
17
17
|
import { a as Pa, c as Fa, d as Ia, i as La, l as Ra, r as za, u as Ba } from "./glide-utils-DJyqh0EM.js";
|
|
18
|
-
import { n as Va, t as Ha } from "./ErrorBoundary-
|
|
19
|
-
import { n as Ua, t as Wa } from "./globals-
|
|
18
|
+
import { n as Va, t as Ha } from "./ErrorBoundary-DwtvpxIv.js";
|
|
19
|
+
import { n as Ua, t as Wa } from "./globals-CwtFrEmN.js";
|
|
20
20
|
import { t as Ga } from "./react-dom-DUmH0GXv.js";
|
|
21
21
|
import { t as Ka } from "./jsx-runtime-3BD1kT0s.js";
|
|
22
22
|
import { B as qa, C as H, Ct as Ja, D as Ya, E as Xa, F as U, G as Za, H as Qa, I as $a, L as eo, M as W, N as to, O as no, P as ro, Q as io, R as ao, S as G, St as oo, Tt as so, U as co, W as lo, Y as uo, Z as fo, _ as po, _t as mo, a as ho, b as go, bt as _o, c as vo, d as yo, f as bo, g as xo, h as So, ht as Co, i as wo, j as K, k as To, l as Eo, m as Do, n as Oo, o as ko, p as Ao, r as jo, s as Mo, u as No, ut as Po, v as Fo, vt as Io, w as Lo, wt as Ro, x as zo, xt as Bo, y as Vo, yt as Ho } from "./use-restore-focus-BEM7sFWl.js";
|
|
@@ -39,7 +39,7 @@ import { t as Ms } from "./useAsyncData-Deh5kszT.js";
|
|
|
39
39
|
import { i as Ns, n as Ps, r as Fs } from "./formats-DLtvJPnj.js";
|
|
40
40
|
import { M as Is, N as Ls } from "./vega-loader.browser-DNST6uVf.js";
|
|
41
41
|
import { a as Rs, n as zs } from "./loader-BQOfjTIJ.js";
|
|
42
|
-
import { c as Bs, d as Vs, i as Hs, l as Us, o as Ws, s as Gs, t as Ks, u as qs } from "./code-visibility-
|
|
42
|
+
import { c as Bs, d as Vs, i as Hs, l as Us, o as Ws, s as Gs, t as Ks, u as qs } from "./code-visibility-C5K6EQNt.js";
|
|
43
43
|
import { t as Js } from "./useDeepCompareMemoize-DXwzRINI.js";
|
|
44
44
|
import { t as Ys } from "./esm-D2gTsXEV.js";
|
|
45
45
|
//#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
|
|
@@ -10533,7 +10533,7 @@ function VC(e, t) {
|
|
|
10533
10533
|
}
|
|
10534
10534
|
//#endregion
|
|
10535
10535
|
//#region src/plugins/impl/DataEditorPlugin.tsx
|
|
10536
|
-
var HC = J.lazy(() => import("./glide-data-editor-
|
|
10536
|
+
var HC = J.lazy(() => import("./glide-data-editor-TNcL0ZIF.js").then((e) => e.t)), UC = wS("marimo-data-editor", { cssStyles: [qS] }).withData(W({
|
|
10537
10537
|
initialValue: W({ edits: G(W({
|
|
10538
10538
|
rowIdx: K(),
|
|
10539
10539
|
columnId: U(),
|
|
@@ -20251,7 +20251,7 @@ var DA = (e) => {
|
|
|
20251
20251
|
});
|
|
20252
20252
|
}
|
|
20253
20253
|
}, kA = (e) => {
|
|
20254
|
-
let t = (0, X.c)(
|
|
20254
|
+
let t = (0, X.c)(33), n = (0, J.useId)(), r;
|
|
20255
20255
|
t[0] === e.value ? r = t[1] : (r = AA(e.value), t[0] = e.value, t[1] = r);
|
|
20256
20256
|
let i = r, a = !e.debounce, o;
|
|
20257
20257
|
t[2] !== i || t[3] !== e.setValue || t[4] !== a ? (o = {
|
|
@@ -20261,31 +20261,39 @@ var DA = (e) => {
|
|
|
20261
20261
|
onChange: e.setValue
|
|
20262
20262
|
}, t[2] = i, t[3] = e.setValue, t[4] = a, t[5] = o) : o = t[5];
|
|
20263
20263
|
let { value: s, onChange: l } = Li(o), u;
|
|
20264
|
-
t[6]
|
|
20265
|
-
|
|
20266
|
-
|
|
20267
|
-
|
|
20268
|
-
|
|
20269
|
-
|
|
20270
|
-
|
|
20264
|
+
t[6] !== e.start || t[7] !== e.stop ? (u = (t) => ws(t, e.start ?? -Infinity, e.stop ?? Infinity), t[6] = e.start, t[7] = e.stop, t[8] = u) : u = t[8];
|
|
20265
|
+
let d = u, f;
|
|
20266
|
+
t[9] !== d || t[10] !== l || t[11] !== s ? (f = (e) => {
|
|
20267
|
+
let t = AA(e), n = t == null ? null : d(t);
|
|
20268
|
+
n !== s && l(n);
|
|
20269
|
+
}, t[9] = d, t[10] = l, t[11] = s, t[12] = f) : f = t[12];
|
|
20270
|
+
let p = f, m = e.label, h = n, g = e.fullWidth, _ = e.fullWidth && "w-full", v;
|
|
20271
|
+
t[13] === _ ? v = t[14] : (v = c("min-w-[3em]", _), t[13] = _, t[14] = v);
|
|
20272
|
+
let y = e.start ?? void 0, b = e.stop ?? void 0, x;
|
|
20273
|
+
t[15] !== d || t[16] !== s ? (x = s == null ? NaN : d(s), t[15] = d, t[16] = s, t[17] = x) : x = t[17];
|
|
20274
|
+
let S = e.label || "Number input", C;
|
|
20275
|
+
t[18] !== p || t[19] !== n || t[20] !== e.disabled || t[21] !== e.step || t[22] !== y || t[23] !== b || t[24] !== x || t[25] !== S || t[26] !== v ? (C = /* @__PURE__ */ (0, Y.jsx)(Hi, {
|
|
20271
20276
|
"data-testid": "marimo-plugin-number-input",
|
|
20272
|
-
className:
|
|
20273
|
-
minValue:
|
|
20274
|
-
maxValue:
|
|
20275
|
-
value:
|
|
20277
|
+
className: v,
|
|
20278
|
+
minValue: y,
|
|
20279
|
+
maxValue: b,
|
|
20280
|
+
value: x,
|
|
20276
20281
|
step: e.step,
|
|
20277
|
-
|
|
20282
|
+
commitBehavior: "validate",
|
|
20283
|
+
validationBehavior: "aria",
|
|
20284
|
+
isInvalid: !1,
|
|
20285
|
+
onChange: p,
|
|
20278
20286
|
id: n,
|
|
20279
|
-
"aria-label":
|
|
20287
|
+
"aria-label": S,
|
|
20280
20288
|
isDisabled: e.disabled
|
|
20281
|
-
}), t[
|
|
20282
|
-
let
|
|
20283
|
-
return t[
|
|
20284
|
-
label:
|
|
20285
|
-
controlId:
|
|
20286
|
-
fullWidth:
|
|
20287
|
-
children:
|
|
20288
|
-
}), t[
|
|
20289
|
+
}), t[18] = p, t[19] = n, t[20] = e.disabled, t[21] = e.step, t[22] = y, t[23] = b, t[24] = x, t[25] = S, t[26] = v, t[27] = C) : C = t[27];
|
|
20290
|
+
let w;
|
|
20291
|
+
return t[28] !== n || t[29] !== e.fullWidth || t[30] !== e.label || t[31] !== C ? (w = /* @__PURE__ */ (0, Y.jsx)(LS, {
|
|
20292
|
+
label: m,
|
|
20293
|
+
controlId: h,
|
|
20294
|
+
fullWidth: g,
|
|
20295
|
+
children: C
|
|
20296
|
+
}), t[28] = n, t[29] = e.fullWidth, t[30] = e.label, t[31] = C, t[32] = w) : w = t[32], w;
|
|
20289
20297
|
};
|
|
20290
20298
|
function AA(e) {
|
|
20291
20299
|
return e == null || Number.isNaN(e) ? null : e;
|
|
@@ -30099,7 +30107,7 @@ function OR(e) {
|
|
|
30099
30107
|
}
|
|
30100
30108
|
//#endregion
|
|
30101
30109
|
//#region src/components/editor/renderers/slides-layout/slides-layout.tsx
|
|
30102
|
-
var kR = J.lazy(() => import("./reveal-component-
|
|
30110
|
+
var kR = J.lazy(() => import("./reveal-component-CRHNdWDY.js")), AR = (e) => {
|
|
30103
30111
|
let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = ns(Sa), s = a === "read" || o, c = ns(gt) > 1, [l, u] = (0, J.useState)(null), d;
|
|
30104
30112
|
t[0] !== i || t[1] !== n ? (d = EP(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
|
|
30105
30113
|
let { slideCells: f, skippedIds: p, noOutputIds: m, slideTypes: h, startCellIndex: g } = d, _;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
|
|
2
2
|
import { t } from "./react-sHtZdjeP.js";
|
|
3
|
-
import { a as n } from "./glide-data-editor-
|
|
3
|
+
import { a as n } from "./glide-data-editor-TNcL0ZIF.js";
|
|
4
4
|
//#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_aca11a353ce3b112922852200b9c160f/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/private/number-overlay-editor-style.js
|
|
5
5
|
var r = /* @__PURE__ */ e(t()), i = /*#__PURE__*/ n("div")({
|
|
6
6
|
name: "NumberOverlayEditorStyle",
|
|
@@ -4,14 +4,14 @@ import { t as o } from "./react-sHtZdjeP.js";
|
|
|
4
4
|
import { t as s } from "./compiler-runtime-CldRdSsv.js";
|
|
5
5
|
import { h as c, t as l } from "./tooltip-BO1REbqs.js";
|
|
6
6
|
import { w as u } from "./cells-CuYwqnV8.js";
|
|
7
|
-
import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-
|
|
7
|
+
import { $ as d, Q as f, Z as p, an as m, i as h, l as g, ln as _, n as v, on as y, r as b, t as x, u as S } from "./common-CpPQFLxA.js";
|
|
8
8
|
import { M as C } from "./select-BButFi-d.js";
|
|
9
9
|
import { q as ee } from "./dropdown-menu-CP_qCYHC.js";
|
|
10
10
|
import { y as w } from "./toDate-Dwcg_x_5.js";
|
|
11
11
|
import { t as T } from "./jsx-runtime-3BD1kT0s.js";
|
|
12
12
|
import { q as E } from "./use-restore-focus-BEM7sFWl.js";
|
|
13
13
|
import { A as D, C as O, b as k } from "./useTheme-CRnjkku0.js";
|
|
14
|
-
import { a as A, n as te, t as ne } from "./code-visibility-
|
|
14
|
+
import { a as A, n as te, t as ne } from "./code-visibility-C5K6EQNt.js";
|
|
15
15
|
/* empty css */
|
|
16
16
|
var j = c("sticky-note", [["path", {
|
|
17
17
|
d: "M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { Provider } from "jotai";
|
|
11
11
|
import type React from "react";
|
|
12
12
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
13
|
+
import { requestId } from "@/__tests__/branded";
|
|
13
14
|
import { MockRequestClient } from "@/__mocks__/requests";
|
|
14
15
|
import { ModalProvider } from "@/components/modal/ImperativeModal";
|
|
15
16
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
@@ -129,7 +130,7 @@ describe("NotebookMenuDropdown", () => {
|
|
|
129
130
|
}));
|
|
130
131
|
invalidateDataSourceDiscovery();
|
|
131
132
|
vi.spyOn(DiscoverDataSources, "request").mockResolvedValue({
|
|
132
|
-
request_id: "request-id",
|
|
133
|
+
request_id: requestId("request-id"),
|
|
133
134
|
sources: [],
|
|
134
135
|
});
|
|
135
136
|
});
|
|
@@ -142,7 +143,7 @@ describe("NotebookMenuDropdown", () => {
|
|
|
142
143
|
|
|
143
144
|
it("shows detected databases in the add connection submenu", async () => {
|
|
144
145
|
vi.mocked(DiscoverDataSources.request).mockResolvedValue({
|
|
145
|
-
request_id: "request-id",
|
|
146
|
+
request_id: requestId("request-id"),
|
|
146
147
|
sources: [POSTGRES_SOURCE],
|
|
147
148
|
});
|
|
148
149
|
|
|
@@ -172,7 +173,7 @@ describe("NotebookMenuDropdown", () => {
|
|
|
172
173
|
|
|
173
174
|
it("shows detected storage in the add remote storage submenu", async () => {
|
|
174
175
|
vi.mocked(DiscoverDataSources.request).mockResolvedValue({
|
|
175
|
-
request_id: "request-id",
|
|
176
|
+
request_id: requestId("request-id"),
|
|
176
177
|
sources: [S3_SOURCE],
|
|
177
178
|
});
|
|
178
179
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { render, screen } from "@testing-library/react";
|
|
4
4
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { requestId } from "@/__tests__/branded";
|
|
5
6
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
6
7
|
import { DownloadStorage } from "@/core/storage/request-registry";
|
|
7
8
|
import { StorageFileViewer } from "../storage-file-viewer";
|
|
@@ -41,7 +42,7 @@ describe("StorageFileViewer", () => {
|
|
|
41
42
|
|
|
42
43
|
it("renders TOML from generic storage metadata as read-only TOML", async () => {
|
|
43
44
|
const request = vi.spyOn(DownloadStorage, "request").mockResolvedValue({
|
|
44
|
-
request_id: "request-id",
|
|
45
|
+
request_id: requestId("request-id"),
|
|
45
46
|
url: "https://example.com/pyproject.toml?signature=secret",
|
|
46
47
|
});
|
|
47
48
|
vi.stubGlobal(
|
|
@@ -8,6 +8,7 @@ import { EditorState, type Extension } from "@codemirror/state";
|
|
|
8
8
|
import { EditorView } from "@codemirror/view";
|
|
9
9
|
import { DuckDBDialect } from "@marimo-team/codemirror-sql/dialects";
|
|
10
10
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
11
|
+
import { requestId } from "@/__tests__/branded";
|
|
11
12
|
import type { CellId } from "@/core/cells/ids";
|
|
12
13
|
import type {
|
|
13
14
|
CompletionConfig,
|
|
@@ -1106,7 +1107,7 @@ describe("CustomSqlParser", () => {
|
|
|
1106
1107
|
const request = vi.spyOn(ValidateSQL, "request").mockResolvedValue({
|
|
1107
1108
|
error: null,
|
|
1108
1109
|
parse_result: { success: false, errors: [error] },
|
|
1109
|
-
request_id: "request-id",
|
|
1110
|
+
request_id: requestId("request-id"),
|
|
1110
1111
|
validate_result: null,
|
|
1111
1112
|
});
|
|
1112
1113
|
const state = EditorState.create({
|
|
@@ -1150,7 +1151,7 @@ describe("CustomSqlParser", () => {
|
|
|
1150
1151
|
vi.spyOn(ValidateSQL, "request").mockResolvedValue({
|
|
1151
1152
|
error: null,
|
|
1152
1153
|
parse_result: { success: false, errors: [error] },
|
|
1153
|
-
request_id: "request-id",
|
|
1154
|
+
request_id: requestId("request-id"),
|
|
1154
1155
|
validate_result: null,
|
|
1155
1156
|
});
|
|
1156
1157
|
const state = EditorState.create({
|
|
@@ -1194,7 +1195,7 @@ describe("CustomSqlParser", () => {
|
|
|
1194
1195
|
const request = vi.spyOn(ValidateSQL, "request").mockResolvedValue({
|
|
1195
1196
|
error: null,
|
|
1196
1197
|
parse_result: { success: false, errors: [error] },
|
|
1197
|
-
request_id: "request-id",
|
|
1198
|
+
request_id: requestId("request-id"),
|
|
1198
1199
|
validate_result: null,
|
|
1199
1200
|
});
|
|
1200
1201
|
const state = createNamedConnectionState({
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { requestId } from "@/__tests__/branded";
|
|
4
|
+
import type { DataSourceDiscoveryResult } from "@/core/kernel/messages";
|
|
3
5
|
import { connectionAtom } from "@/core/network/connection";
|
|
4
6
|
import { store } from "@/core/state/jotai";
|
|
5
7
|
import { ConnectionState } from "@/core/websocket/types";
|
|
@@ -41,7 +43,7 @@ describe("fetchDataSourceDiscovery", () => {
|
|
|
41
43
|
it("shares a single in-flight request across concurrent callers", async () => {
|
|
42
44
|
const request = vi
|
|
43
45
|
.spyOn(DiscoverDataSources, "request")
|
|
44
|
-
.mockResolvedValue({ request_id: "request-id", sources: [] });
|
|
46
|
+
.mockResolvedValue({ request_id: requestId("request-id"), sources: [] });
|
|
45
47
|
|
|
46
48
|
await Promise.all([
|
|
47
49
|
fetchDataSourceDiscovery(),
|
|
@@ -55,7 +57,7 @@ describe("fetchDataSourceDiscovery", () => {
|
|
|
55
57
|
it("re-runs discovery after the cache is invalidated", async () => {
|
|
56
58
|
const request = vi
|
|
57
59
|
.spyOn(DiscoverDataSources, "request")
|
|
58
|
-
.mockResolvedValue({ request_id: "request-id", sources: [] });
|
|
60
|
+
.mockResolvedValue({ request_id: requestId("request-id"), sources: [] });
|
|
59
61
|
|
|
60
62
|
await fetchDataSourceDiscovery();
|
|
61
63
|
invalidateDataSourceDiscovery();
|
|
@@ -68,7 +70,10 @@ describe("fetchDataSourceDiscovery", () => {
|
|
|
68
70
|
const request = vi
|
|
69
71
|
.spyOn(DiscoverDataSources, "request")
|
|
70
72
|
.mockRejectedValueOnce(new Error("boom"))
|
|
71
|
-
.mockResolvedValueOnce({
|
|
73
|
+
.mockResolvedValueOnce({
|
|
74
|
+
request_id: requestId("request-id"),
|
|
75
|
+
sources: [],
|
|
76
|
+
});
|
|
72
77
|
|
|
73
78
|
await expect(fetchDataSourceDiscovery()).rejects.toThrow("boom");
|
|
74
79
|
await expect(fetchDataSourceDiscovery()).resolves.toEqual([]);
|
|
@@ -77,16 +82,18 @@ describe("fetchDataSourceDiscovery", () => {
|
|
|
77
82
|
|
|
78
83
|
it("does not clear a newer cache entry when an invalidated request fails", async () => {
|
|
79
84
|
let rejectFirstRequest: ((error: Error) => void) | undefined;
|
|
80
|
-
const firstRequest = new Promise<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
85
|
+
const firstRequest = new Promise<DataSourceDiscoveryResult>(
|
|
86
|
+
(_resolve, reject) => {
|
|
87
|
+
rejectFirstRequest = reject;
|
|
88
|
+
},
|
|
89
|
+
);
|
|
86
90
|
const request = vi
|
|
87
91
|
.spyOn(DiscoverDataSources, "request")
|
|
88
92
|
.mockReturnValueOnce(firstRequest)
|
|
89
|
-
.mockResolvedValueOnce({
|
|
93
|
+
.mockResolvedValueOnce({
|
|
94
|
+
request_id: requestId("request-id"),
|
|
95
|
+
sources: [],
|
|
96
|
+
});
|
|
90
97
|
|
|
91
98
|
const staleResult = fetchDataSourceDiscovery().catch((error) => error);
|
|
92
99
|
await vi.waitFor(() => expect(request).toHaveBeenCalledTimes(1));
|
|
@@ -116,7 +123,7 @@ describe("fetchDataSourceDiscovery", () => {
|
|
|
116
123
|
}),
|
|
117
124
|
];
|
|
118
125
|
vi.spyOn(DiscoverDataSources, "request").mockResolvedValue({
|
|
119
|
-
request_id: "request-id",
|
|
126
|
+
request_id: requestId("request-id"),
|
|
120
127
|
sources,
|
|
121
128
|
});
|
|
122
129
|
|
|
@@ -7,7 +7,7 @@ import { throwNotImplemented } from "@/utils/functions";
|
|
|
7
7
|
import { Logger } from "@/utils/Logger";
|
|
8
8
|
import { generateUUID } from "@/utils/uuid";
|
|
9
9
|
import { initialNotebookState, notebookAtom } from "../cells/cells";
|
|
10
|
-
import type {
|
|
10
|
+
import type { ClientCommand } from "../kernel/messages";
|
|
11
11
|
import type { EditRequests, RunRequests } from "../network/types";
|
|
12
12
|
import { store as defaultStore } from "../state/jotai";
|
|
13
13
|
import { getMarimoExportContext } from "../static/export-context";
|
|
@@ -392,7 +392,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
392
392
|
// The kernel uses msgspec to parse control requests, which requires a 'type'
|
|
393
393
|
// field for discriminated union deserialization.
|
|
394
394
|
private async putControlRequest(
|
|
395
|
-
operation:
|
|
395
|
+
operation: ClientCommand,
|
|
396
396
|
session?: AppSession,
|
|
397
397
|
): Promise<void> {
|
|
398
398
|
session ??= await this.getActiveSession();
|
|
@@ -55,7 +55,7 @@ export type Capabilities =
|
|
|
55
55
|
export type CacheInfoFetched = NotificationMessageData<"cache-info">;
|
|
56
56
|
|
|
57
57
|
export type NotificationMessage = schemas["KnownUnions"]["notification"];
|
|
58
|
-
export type
|
|
58
|
+
export type ClientCommand = schemas["KnownUnions"]["command"];
|
|
59
59
|
|
|
60
60
|
export type NotificationMessageType = NotificationMessage["op"];
|
|
61
61
|
export interface NotificationPayload {
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { reloadSafe } from "@/utils/reload-safe";
|
|
|
11
11
|
import { generateUUID } from "@/utils/uuid";
|
|
12
12
|
import { createModuleWorker } from "@/utils/worker";
|
|
13
13
|
import { notebookIsRunningAtom } from "../cells/cells";
|
|
14
|
-
import type {
|
|
14
|
+
import type { ClientCommand } from "../kernel/messages";
|
|
15
15
|
import { getInitialAppMode } from "../mode";
|
|
16
16
|
import { API } from "../network/api";
|
|
17
17
|
import { withDevAssetUrl } from "../network/export-asset-url";
|
|
@@ -711,7 +711,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
711
711
|
public listStorageEntries = throwNotImplemented;
|
|
712
712
|
public downloadStorage = throwNotImplemented;
|
|
713
713
|
|
|
714
|
-
private async putControlRequest(operation:
|
|
714
|
+
private async putControlRequest(operation: ClientCommand) {
|
|
715
715
|
await this.rpc.proxy.request.bridge({
|
|
716
716
|
functionName: "put_control_request",
|
|
717
717
|
payload: operation,
|
|
@@ -3,7 +3,7 @@ import type { PyodideInterface } from "pyodide";
|
|
|
3
3
|
import type { WasmRuntimeConfig } from "../runtime-config";
|
|
4
4
|
import type { UserConfig } from "@/core/config/config-schema";
|
|
5
5
|
import type {
|
|
6
|
-
|
|
6
|
+
ClientCommand,
|
|
7
7
|
NotificationPayload,
|
|
8
8
|
} from "@/core/kernel/messages";
|
|
9
9
|
import type { JsonString } from "@/utils/json/base64";
|
|
@@ -74,7 +74,7 @@ export interface WasmController {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
export interface RawBridge {
|
|
77
|
-
put_control_request(operation:
|
|
77
|
+
put_control_request(operation: ClientCommand): Promise<string>;
|
|
78
78
|
put_input(input: string): Promise<string>;
|
|
79
79
|
code_complete(request: CodeCompletionRequest): Promise<string>;
|
|
80
80
|
read_code(): Promise<{ contents: string }>;
|
|
@@ -4,6 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { NumberField } from "@/components/ui/number-field";
|
|
5
5
|
import { useDebounceControlledState } from "@/hooks/useDebounce";
|
|
6
6
|
import { cn } from "@/utils/cn";
|
|
7
|
+
import { clamp } from "@/utils/math";
|
|
7
8
|
import type { IPlugin, IPluginProps, Setter } from "../types";
|
|
8
9
|
import { Labeled } from "./common/labeled";
|
|
9
10
|
|
|
@@ -65,8 +66,16 @@ const NumberComponent = (props: NumberComponentProps): JSX.Element => {
|
|
|
65
66
|
onChange: props.setValue,
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
const clampToRange = (n: number) =>
|
|
70
|
+
clamp(n, props.start ?? -Infinity, props.stop ?? Infinity);
|
|
71
|
+
|
|
68
72
|
const handleChange = (newValue: number) => {
|
|
69
|
-
|
|
73
|
+
const n = withoutNaN(newValue);
|
|
74
|
+
const next = n == null ? null : clampToRange(n);
|
|
75
|
+
// e.g. typing past `stop` while already at `stop`
|
|
76
|
+
if (next !== value) {
|
|
77
|
+
onChange(next);
|
|
78
|
+
}
|
|
70
79
|
};
|
|
71
80
|
|
|
72
81
|
return (
|
|
@@ -76,11 +85,19 @@ const NumberComponent = (props: NumberComponentProps): JSX.Element => {
|
|
|
76
85
|
className={cn("min-w-[3em]", props.fullWidth && "w-full")}
|
|
77
86
|
minValue={props.start ?? undefined}
|
|
78
87
|
maxValue={props.stop ?? undefined}
|
|
79
|
-
// This needs to be
|
|
88
|
+
// This needs to be `NaN` since `undefined` makes uncontrolled component
|
|
80
89
|
// and can lead to leaving the old value in forms (https://github.com/marimo-team/marimo/issues/7352)
|
|
81
90
|
// We out NaNs later
|
|
82
|
-
value={value
|
|
91
|
+
value={value == null ? Number.NaN : clampToRange(value)}
|
|
83
92
|
step={props.step}
|
|
93
|
+
// By default React Aria rounds every value to `start + n * step`, but
|
|
94
|
+
// `step` is only the stepper increment: users can enter any value in
|
|
95
|
+
// range (#9106). "validate" turns off that rounding (and the clamping,
|
|
96
|
+
// done above instead); its step validation is turned off so off-step
|
|
97
|
+
// values aren't flagged invalid or block `mo.ui.form` submission.
|
|
98
|
+
commitBehavior="validate"
|
|
99
|
+
validationBehavior="aria"
|
|
100
|
+
isInvalid={false}
|
|
84
101
|
onChange={handleChange}
|
|
85
102
|
id={id}
|
|
86
103
|
aria-label={props.label || "Number input"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { act, render } from "@testing-library/react";
|
|
3
|
+
import { act, fireEvent, render } from "@testing-library/react";
|
|
4
|
+
import { useState } from "react";
|
|
4
5
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
6
|
import type { z } from "zod";
|
|
6
7
|
import { initialModeAtom } from "@/core/mode";
|
|
@@ -474,4 +475,161 @@ describe("NumberPlugin", () => {
|
|
|
474
475
|
);
|
|
475
476
|
expect(numberField?.classList.contains("w-full")).toBe(true);
|
|
476
477
|
});
|
|
478
|
+
|
|
479
|
+
describe("does not snap values to step (#9106)", () => {
|
|
480
|
+
// Feeds `setValue` back into `value`, as the kernel round-trip does.
|
|
481
|
+
const renderNumber = (
|
|
482
|
+
initialValue: number,
|
|
483
|
+
data: Pick<z.infer<NumberPlugin["validator"]>, "start" | "stop" | "step">,
|
|
484
|
+
{ debounce = false } = {},
|
|
485
|
+
) => {
|
|
486
|
+
const plugin = new NumberPlugin();
|
|
487
|
+
const setValue = vi.fn();
|
|
488
|
+
const Harness = () => {
|
|
489
|
+
const [value, setState] = useState<number | null>(initialValue);
|
|
490
|
+
return plugin.render({
|
|
491
|
+
host: document.createElement("div"),
|
|
492
|
+
value,
|
|
493
|
+
setValue: (next) => {
|
|
494
|
+
setValue(next);
|
|
495
|
+
setState(next);
|
|
496
|
+
},
|
|
497
|
+
data: {
|
|
498
|
+
...data,
|
|
499
|
+
label: null,
|
|
500
|
+
debounce,
|
|
501
|
+
fullWidth: false,
|
|
502
|
+
},
|
|
503
|
+
functions: {},
|
|
504
|
+
});
|
|
505
|
+
};
|
|
506
|
+
const { getByRole } = render(<Harness />);
|
|
507
|
+
act(() => {
|
|
508
|
+
vi.advanceTimersByTime(0);
|
|
509
|
+
});
|
|
510
|
+
const input = getByRole("textbox", {
|
|
511
|
+
name: "Number input",
|
|
512
|
+
}) as HTMLInputElement;
|
|
513
|
+
return { input, setValue };
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const typeAndCommit = (input: HTMLInputElement, text: string) => {
|
|
517
|
+
act(() => {
|
|
518
|
+
input.focus();
|
|
519
|
+
});
|
|
520
|
+
fireEvent.change(input, { target: { value: text } });
|
|
521
|
+
act(() => {
|
|
522
|
+
input.blur();
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
it.each([
|
|
527
|
+
{ value: 2.23, start: 1.255_57, step: 0.001 },
|
|
528
|
+
{ value: 2.233_45, start: 1, step: 0.001 },
|
|
529
|
+
])(
|
|
530
|
+
"displays $value as-is with start=$start and step=$step",
|
|
531
|
+
({ value, start, step }) => {
|
|
532
|
+
const { input } = renderNumber(value, { start, stop: 20, step });
|
|
533
|
+
expect(input.value).toBe(String(value));
|
|
534
|
+
},
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
it.each([
|
|
538
|
+
{ typed: "2.3377", start: 1, step: 0.01 },
|
|
539
|
+
{ typed: "2.23111", start: 1.222, step: 0.01 },
|
|
540
|
+
])(
|
|
541
|
+
"keeps typed value $typed with start=$start and step=$step",
|
|
542
|
+
({ typed, start, step }) => {
|
|
543
|
+
const { input, setValue } = renderNumber(2.233_45, {
|
|
544
|
+
start,
|
|
545
|
+
stop: 20,
|
|
546
|
+
step,
|
|
547
|
+
});
|
|
548
|
+
typeAndCommit(input, typed);
|
|
549
|
+
expect(setValue).toHaveBeenLastCalledWith(Number(typed));
|
|
550
|
+
expect(input.value).toBe(typed);
|
|
551
|
+
expect(input.getAttribute("aria-invalid")).not.toBe("true");
|
|
552
|
+
// React Aria sets a custom validity on this text input in native mode,
|
|
553
|
+
// which would block `mo.ui.form` submission.
|
|
554
|
+
expect(input.validity.valid).toBe(true);
|
|
555
|
+
},
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
it("clamps typed values to start and stop", () => {
|
|
559
|
+
const { input, setValue } = renderNumber(5, {
|
|
560
|
+
start: 2,
|
|
561
|
+
stop: 10,
|
|
562
|
+
step: 1,
|
|
563
|
+
});
|
|
564
|
+
typeAndCommit(input, "25");
|
|
565
|
+
expect(setValue).toHaveBeenLastCalledWith(10);
|
|
566
|
+
expect(input.value).toBe("10");
|
|
567
|
+
typeAndCommit(input, "1");
|
|
568
|
+
expect(setValue).toHaveBeenLastCalledWith(2);
|
|
569
|
+
expect(input.value).toBe("2");
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
it("shows the bound when typing past a bound it is already at", () => {
|
|
573
|
+
const { input, setValue } = renderNumber(10, {
|
|
574
|
+
start: 2,
|
|
575
|
+
stop: 10,
|
|
576
|
+
step: 1,
|
|
577
|
+
});
|
|
578
|
+
typeAndCommit(input, "50");
|
|
579
|
+
expect(setValue).not.toHaveBeenCalled();
|
|
580
|
+
expect(input.value).toBe("10");
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it("increments and decrements by step", () => {
|
|
584
|
+
const { input, setValue } = renderNumber(5, {
|
|
585
|
+
start: 0,
|
|
586
|
+
stop: 10,
|
|
587
|
+
step: 0.5,
|
|
588
|
+
});
|
|
589
|
+
fireEvent.keyDown(input, { key: "ArrowUp" });
|
|
590
|
+
expect(setValue).toHaveBeenLastCalledWith(5.5);
|
|
591
|
+
expect(input.value).toBe("5.5");
|
|
592
|
+
fireEvent.keyDown(input, { key: "ArrowDown" });
|
|
593
|
+
expect(setValue).toHaveBeenLastCalledWith(5);
|
|
594
|
+
expect(input.value).toBe("5");
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it.each([
|
|
598
|
+
{ key: "ArrowUp", expected: 3 },
|
|
599
|
+
{ key: "ArrowDown", expected: 2 },
|
|
600
|
+
])(
|
|
601
|
+
"$key from an off-step value moves to the nearest step ($expected)",
|
|
602
|
+
({ key, expected }) => {
|
|
603
|
+
const { input, setValue } = renderNumber(2.23, {
|
|
604
|
+
start: 0,
|
|
605
|
+
stop: 10,
|
|
606
|
+
step: 1,
|
|
607
|
+
});
|
|
608
|
+
fireEvent.keyDown(input, { key });
|
|
609
|
+
expect(setValue).toHaveBeenLastCalledWith(expected);
|
|
610
|
+
expect(input.value).toBe(String(expected));
|
|
611
|
+
},
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
it.each([
|
|
615
|
+
{ typed: "2.3377", expected: 2.3377 },
|
|
616
|
+
{ typed: "50", expected: 20 },
|
|
617
|
+
])(
|
|
618
|
+
"commits typed $typed as $expected after the debounce delay",
|
|
619
|
+
({ typed, expected }) => {
|
|
620
|
+
const { input, setValue } = renderNumber(
|
|
621
|
+
2.233_45,
|
|
622
|
+
{ start: 1, stop: 20, step: 0.01 },
|
|
623
|
+
{ debounce: true },
|
|
624
|
+
);
|
|
625
|
+
typeAndCommit(input, typed);
|
|
626
|
+
expect(setValue).not.toHaveBeenCalled();
|
|
627
|
+
act(() => {
|
|
628
|
+
vi.advanceTimersByTime(200);
|
|
629
|
+
});
|
|
630
|
+
expect(setValue).toHaveBeenLastCalledWith(expected);
|
|
631
|
+
expect(input.value).toBe(String(expected));
|
|
632
|
+
},
|
|
633
|
+
);
|
|
634
|
+
});
|
|
477
635
|
});
|