@malloy-publisher/sdk 0.0.137 → 0.0.139
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/README.md +122 -1
- package/dist/ServerProvider-Bzid56gJ.cjs.js +1 -0
- package/dist/{ServerProvider-BGGK1ZQ_.es.js → ServerProvider-D-y63tG0.es.js} +550 -478
- package/dist/client/api.d.ts +144 -53
- package/dist/client/index.cjs.js +1 -1
- package/dist/client/index.es.js +22 -21
- package/dist/components/Notebook/Notebook.d.ts +4 -1
- package/dist/components/Notebook/NotebookCell.d.ts +2 -2
- package/dist/components/Notebook/types.d.ts +21 -0
- package/dist/components/filter/DimensionFilter.d.ts +43 -0
- package/dist/components/filter/index.d.ts +4 -0
- package/dist/components/filter/utils.d.ts +75 -0
- package/dist/components/index.d.ts +7 -6
- package/dist/components/styles.d.ts +3 -3
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/useDimensionFilters.d.ts +84 -0
- package/dist/hooks/useDimensionFiltersFromSpec.d.ts +52 -0
- package/dist/hooks/useDimensionFiltersQuery.d.ts +79 -0
- package/dist/hooks/useDimensionalFilterRangeData.d.ts +106 -0
- package/dist/index.cjs.js +141 -112
- package/dist/index.d.ts +3 -2
- package/dist/index.es.js +47903 -39798
- package/dist/sdk.css +1 -1
- package/package.json +16 -11
- package/src/components/Home/Home.tsx +15 -11
- package/src/components/Notebook/Notebook.tsx +391 -6
- package/src/components/Notebook/NotebookCell.tsx +2 -2
- package/src/components/Notebook/types.ts +24 -0
- package/src/components/Package/Connections.tsx +3 -6
- package/src/components/RenderedResult/RenderedResult.tsx +22 -3
- package/src/components/filter/DimensionFilter.tsx +738 -0
- package/src/components/filter/index.ts +20 -0
- package/src/components/filter/utils.ts +354 -0
- package/src/components/highlighter.ts +14 -6
- package/src/components/index.ts +7 -6
- package/src/hooks/index.ts +31 -0
- package/src/hooks/useDimensionFilters.ts +322 -0
- package/src/hooks/useDimensionFiltersFromSpec.ts +117 -0
- package/src/hooks/useDimensionFiltersQuery.ts +300 -0
- package/src/hooks/useDimensionalFilterRangeData.ts +758 -0
- package/src/index.ts +3 -2
- package/dist/ServerProvider-lXAaPKBb.cjs.js +0 -1
- package/dist/abap-BmBUA35e.es.js +0 -6
- package/dist/abap-Dwt2rH6y.cjs.js +0 -1
- package/dist/actionscript-3-mj8Uhnsc.cjs.js +0 -1
- package/dist/actionscript-3-zFUbzQa9.es.js +0 -6
- package/dist/ada-CBvPkFpZ.es.js +0 -6
- package/dist/ada-DZM58Vqs.cjs.js +0 -1
- package/dist/andromeeda-BXc5FOIb.cjs.js +0 -1
- package/dist/andromeeda-uXNdzNpk.es.js +0 -4
- package/dist/angular-html-B60m4jt-.cjs.js +0 -1
- package/dist/angular-html-D3aW1y6T.es.js +0 -32
- package/dist/angular-ts-Jud40GrY.es.js +0 -21
- package/dist/angular-ts-SIlYrqkG.cjs.js +0 -1
- package/dist/apache-CVNlsSDc.es.js +0 -6
- package/dist/apache-D7v5fxtZ.cjs.js +0 -1
- package/dist/apex-4hrAnw0a.cjs.js +0 -1
- package/dist/apex-DFk3KRB1.es.js +0 -6
- package/dist/apl-CKSaOFbt.cjs.js +0 -1
- package/dist/apl-pE3PRTDr.es.js +0 -16
- package/dist/applescript-CYMR_y0g.es.js +0 -6
- package/dist/applescript-Cnd3Dxju.cjs.js +0 -1
- package/dist/ara-4QmU5e04.es.js +0 -6
- package/dist/ara-BQ2aGbFQ.cjs.js +0 -1
- package/dist/asciidoc-C6nYvw8K.cjs.js +0 -1
- package/dist/asciidoc-v_1bjgUg.es.js +0 -6
- package/dist/asm-CQnBVCj-.cjs.js +0 -1
- package/dist/asm-RC0Yh-NZ.es.js +0 -6
- package/dist/astro-Be6fybGX.es.js +0 -16
- package/dist/astro-KhYkz6Xu.cjs.js +0 -1
- package/dist/aurora-x-BwoVEUWZ.es.js +0 -4
- package/dist/aurora-x-C5IpmIOG.cjs.js +0 -1
- package/dist/awk-DUx4h__E.cjs.js +0 -1
- package/dist/awk-gPH8MVMW.es.js +0 -6
- package/dist/ayu-dark-Cv7nTiif.cjs.js +0 -1
- package/dist/ayu-dark-CxPZkpb2.es.js +0 -4
- package/dist/ballerina-CXlzbmzl.cjs.js +0 -1
- package/dist/ballerina-kvLnRU_e.es.js +0 -6
- package/dist/bat-BHYy44sT.es.js +0 -6
- package/dist/bat-DlMT9sut.cjs.js +0 -1
- package/dist/beancount-CyyiuUzM.cjs.js +0 -1
- package/dist/beancount-D-MADTs_.es.js +0 -6
- package/dist/berry-B0EjuzrL.cjs.js +0 -1
- package/dist/berry-Ci9U0o4h.es.js +0 -6
- package/dist/bibtex-CX618D15.es.js +0 -6
- package/dist/bibtex-CfoG9xRq.cjs.js +0 -1
- package/dist/bicep-D6PH_9IY.cjs.js +0 -1
- package/dist/bicep-iuYiPopT.es.js +0 -6
- package/dist/blade-C0tMuk8f.cjs.js +0 -1
- package/dist/blade-DmXp5Zcz.es.js +0 -18
- package/dist/bsl-CfHcite8.cjs.js +0 -1
- package/dist/bsl-NPX_d-bb.es.js +0 -8
- package/dist/c-C4sXGJZM.cjs.js +0 -1
- package/dist/c-DASdrs7p.es.js +0 -6
- package/dist/cadence-BDALQi26.es.js +0 -6
- package/dist/cadence-Dq2CYzXG.cjs.js +0 -1
- package/dist/cairo-17kO8-kb.es.js +0 -8
- package/dist/cairo-CcKpJkyf.cjs.js +0 -1
- package/dist/catppuccin-frappe-BrTOiad2.es.js +0 -4
- package/dist/catppuccin-frappe-DXAedND3.cjs.js +0 -1
- package/dist/catppuccin-latte-D-dc_R4m.es.js +0 -4
- package/dist/catppuccin-latte-mwGw3-Ej.cjs.js +0 -1
- package/dist/catppuccin-macchiato-DN4jOp0G.es.js +0 -4
- package/dist/catppuccin-macchiato-cQCk9ADg.cjs.js +0 -1
- package/dist/catppuccin-mocha-B8yCE3-3.es.js +0 -4
- package/dist/catppuccin-mocha-ClSzDZSl.cjs.js +0 -1
- package/dist/clarity-CNgV2Ths.es.js +0 -6
- package/dist/clarity-ytMkUD5Q.cjs.js +0 -1
- package/dist/clojure-B_Wv414H.cjs.js +0 -1
- package/dist/clojure-CsKKFGwv.es.js +0 -6
- package/dist/cmake-Dr-A3iJx.es.js +0 -6
- package/dist/cmake-TBUaQXYY.cjs.js +0 -1
- package/dist/cobol-BzcJm6ie.es.js +0 -10
- package/dist/cobol-DXFNH4EH.cjs.js +0 -1
- package/dist/codeowners-Bt9yU6NX.es.js +0 -6
- package/dist/codeowners-QhPK6lIJ.cjs.js +0 -1
- package/dist/codeql-B7Q9tkDJ.cjs.js +0 -1
- package/dist/codeql-DBNTqJi1.es.js +0 -6
- package/dist/coffee-GRRSkgX1.cjs.js +0 -1
- package/dist/coffee-q2iaxUnQ.es.js +0 -8
- package/dist/common-lisp-Ced3ctK5.cjs.js +0 -1
- package/dist/common-lisp-r7ZEOG7T.es.js +0 -6
- package/dist/coq-BTRB4iqi.cjs.js +0 -1
- package/dist/coq-CB6Pv_W9.es.js +0 -6
- package/dist/cpp-CPOvHZqs.cjs.js +0 -1
- package/dist/cpp-CPQtoCcU.es.js +0 -18
- package/dist/crystal-BY_Cg265.es.js +0 -18
- package/dist/crystal-C6AG-iew.cjs.js +0 -1
- package/dist/csharp-CYWRhZ2R.es.js +0 -6
- package/dist/csharp-TKds-MhG.cjs.js +0 -1
- package/dist/css-B0kbn78J.cjs.js +0 -1
- package/dist/css-D1aVdRIU.es.js +0 -6
- package/dist/csv-BVJjiaC3.cjs.js +0 -1
- package/dist/csv-DvCncUGQ.es.js +0 -6
- package/dist/cue-BXMrmvay.es.js +0 -6
- package/dist/cue-Cz4J-rnd.cjs.js +0 -1
- package/dist/cypher-DTm5zNR1.es.js +0 -6
- package/dist/cypher-DuKTiyez.cjs.js +0 -1
- package/dist/d-BW9Wd7aK.cjs.js +0 -1
- package/dist/d-D6ZXmn3l.es.js +0 -6
- package/dist/dark-plus-Cd5emcYO.cjs.js +0 -1
- package/dist/dark-plus-pUHDTVV0.es.js +0 -4
- package/dist/dart-CWs-er6b.cjs.js +0 -1
- package/dist/dart-Dz59Is3F.es.js +0 -6
- package/dist/dax-CDxFL2Kb.cjs.js +0 -1
- package/dist/dax-DTVGzydb.es.js +0 -6
- package/dist/desktop-CFgo0jo7.cjs.js +0 -1
- package/dist/desktop-Db9vb-dl.es.js +0 -6
- package/dist/diff-BsEkKwI8.cjs.js +0 -1
- package/dist/diff-XmNrvgM1.es.js +0 -6
- package/dist/docker-DWH2onkn.es.js +0 -6
- package/dist/docker-hwiw4W8I.cjs.js +0 -1
- package/dist/dotenv-4337wvzu.es.js +0 -6
- package/dist/dotenv-CJ5o3G1C.cjs.js +0 -1
- package/dist/dracula-BNgwAJ-d.cjs.js +0 -1
- package/dist/dracula-BtZx2Kac.es.js +0 -4
- package/dist/dracula-soft-BHZ7sHFu.cjs.js +0 -1
- package/dist/dracula-soft-BKa-aqBv.es.js +0 -4
- package/dist/dream-maker-CvvfrJSx.es.js +0 -6
- package/dist/dream-maker-DBharE9Q.cjs.js +0 -1
- package/dist/edge-DI6_BHKG.es.js +0 -12
- package/dist/edge-i77KJtJz.cjs.js +0 -1
- package/dist/elixir-D00NoPSM.cjs.js +0 -1
- package/dist/elixir-ic9y5jcd.es.js +0 -8
- package/dist/elm-Bhj5Vf-e.cjs.js +0 -1
- package/dist/elm-DxnUqUaW.es.js +0 -8
- package/dist/emacs-lisp-BAefI874.es.js +0 -6
- package/dist/emacs-lisp-CDDyFsvQ.cjs.js +0 -1
- package/dist/erb-Cbj2YePa.es.js +0 -10
- package/dist/erb-Dybaw01v.cjs.js +0 -1
- package/dist/erlang-3VgdrQXV.cjs.js +0 -1
- package/dist/erlang-CmIiwF3I.es.js +0 -6
- package/dist/everforest-dark-DMCBqXCK.es.js +0 -4
- package/dist/everforest-dark-_sBMomR1.cjs.js +0 -1
- package/dist/everforest-light-BbXl82Em.es.js +0 -4
- package/dist/everforest-light-H0xoYxl0.cjs.js +0 -1
- package/dist/fennel-BvcDRFAV.cjs.js +0 -1
- package/dist/fennel-DNqkz9pE.es.js +0 -6
- package/dist/fish-CnamI0Ar.cjs.js +0 -1
- package/dist/fish-DIm72t2T.es.js +0 -6
- package/dist/fluent-BapTxJsC.es.js +0 -6
- package/dist/fluent-DFpT66K8.cjs.js +0 -1
- package/dist/fortran-fixed-form-DECY15PY.es.js +0 -8
- package/dist/fortran-fixed-form-u_RcUPMu.cjs.js +0 -1
- package/dist/fortran-free-form-CNDsBFUj.es.js +0 -6
- package/dist/fortran-free-form-IaGrWIda.cjs.js +0 -1
- package/dist/fsharp-B-aK2rr3.cjs.js +0 -1
- package/dist/fsharp-D2ZqviWP.es.js +0 -8
- package/dist/gdresource-BBAqNWe4.cjs.js +0 -1
- package/dist/gdresource-RIsK8sku.es.js +0 -10
- package/dist/gdscript-5N_43TPQ.cjs.js +0 -1
- package/dist/gdscript-D7aheHm-.es.js +0 -6
- package/dist/gdshader-BGJEsM2Z.es.js +0 -6
- package/dist/gdshader-Bl85Hrm5.cjs.js +0 -1
- package/dist/genie-C9gPjc6J.es.js +0 -6
- package/dist/genie-DGsxMAbQ.cjs.js +0 -1
- package/dist/gherkin-CVV6nEUH.cjs.js +0 -1
- package/dist/gherkin-bka1Exbx.es.js +0 -6
- package/dist/git-commit-BRJ1E4Bx.es.js +0 -8
- package/dist/git-commit-CwfgI4fD.cjs.js +0 -1
- package/dist/git-rebase-C3X7aMpn.es.js +0 -8
- package/dist/git-rebase-DUvbIQDw.cjs.js +0 -1
- package/dist/github-dark-BKL9xNgN.cjs.js +0 -1
- package/dist/github-dark-DenFmJkN.es.js +0 -4
- package/dist/github-dark-default-BJPUVz4H.es.js +0 -4
- package/dist/github-dark-default-Dsv5MuSi.cjs.js +0 -1
- package/dist/github-dark-dimmed-CtB9hz8U.cjs.js +0 -1
- package/dist/github-dark-dimmed-DUshB20C.es.js +0 -4
- package/dist/github-dark-high-contrast-BqZVM-jF.cjs.js +0 -1
- package/dist/github-dark-high-contrast-D3aGCnF8.es.js +0 -4
- package/dist/github-light-BFTOhCbz.cjs.js +0 -1
- package/dist/github-light-JYsPkUQd.es.js +0 -4
- package/dist/github-light-default-BZoWH9dH.cjs.js +0 -1
- package/dist/github-light-default-D99KPAby.es.js +0 -4
- package/dist/github-light-high-contrast-BbmZE-Mp.es.js +0 -4
- package/dist/github-light-high-contrast-Ks3kPGJU.cjs.js +0 -1
- package/dist/gleam-B4k9YFGD.es.js +0 -6
- package/dist/gleam-nR4mjrhK.cjs.js +0 -1
- package/dist/glimmer-js-C4MQf3Na.es.js +0 -14
- package/dist/glimmer-js-CNfyUqSb.cjs.js +0 -1
- package/dist/glimmer-ts-Bp7_dELi.cjs.js +0 -1
- package/dist/glimmer-ts-CoYpqZrZ.es.js +0 -14
- package/dist/glsl-BYTq1Tfl.es.js +0 -8
- package/dist/glsl-CIu1PL9X.cjs.js +0 -1
- package/dist/gnuplot-CurtDYoJ.cjs.js +0 -1
- package/dist/gnuplot-DnWoRZt-.es.js +0 -6
- package/dist/go-BErP6iv1.es.js +0 -6
- package/dist/go-CM9_GlwL.cjs.js +0 -1
- package/dist/graphql-BnnSMMC2.cjs.js +0 -1
- package/dist/graphql-g3nHRc0M.es.js +0 -14
- package/dist/groovy-BaVp9Il5.cjs.js +0 -1
- package/dist/groovy-IWs5-NIO.es.js +0 -6
- package/dist/hack-BVxH3fsq.cjs.js +0 -1
- package/dist/hack-wPAsyujS.es.js +0 -10
- package/dist/haml-4TJ757dz.es.js +0 -10
- package/dist/haml-vutdexHh.cjs.js +0 -1
- package/dist/handlebars-7GDLw__F.es.js +0 -14
- package/dist/handlebars-COmZnO8P.cjs.js +0 -1
- package/dist/haskell-CtlGos0K.es.js +0 -6
- package/dist/haskell-suhyCHEm.cjs.js +0 -1
- package/dist/haxe-BIQU1qHi.cjs.js +0 -1
- package/dist/haxe-CZZ33vZw.es.js +0 -6
- package/dist/hcl-6hOg9WP4.es.js +0 -6
- package/dist/hcl-CbQ1yCnz.cjs.js +0 -1
- package/dist/hjson-CgwED-oz.es.js +0 -6
- package/dist/hjson-Ddklb4QM.cjs.js +0 -1
- package/dist/hlsl-3-lv4gi7.es.js +0 -6
- package/dist/hlsl-B4NkiBfC.cjs.js +0 -1
- package/dist/houston-BDYrDoDW.es.js +0 -4
- package/dist/houston-T57H3gQZ.cjs.js +0 -1
- package/dist/html-Dc-Bg17s.cjs.js +0 -1
- package/dist/html-PSPajZka.es.js +0 -10
- package/dist/html-derivative-Brb3b4aI.es.js +0 -8
- package/dist/html-derivative-CY9mJeT0.cjs.js +0 -1
- package/dist/http-BrKsebcH.cjs.js +0 -1
- package/dist/http-CWBcr-Ch.es.js +0 -14
- package/dist/hxml-DLduiIv3.es.js +0 -8
- package/dist/hxml-DbGPHkY4.cjs.js +0 -1
- package/dist/hy-C2xHhR6I.es.js +0 -6
- package/dist/hy-DpyTdO3T.cjs.js +0 -1
- package/dist/imba-BEYqRZzB.es.js +0 -8
- package/dist/imba-CAIkF-GD.cjs.js +0 -1
- package/dist/ini-BUcvsX-U.es.js +0 -6
- package/dist/ini-CymULaw_.cjs.js +0 -1
- package/dist/java-B7odJ7Ap.es.js +0 -6
- package/dist/java-Bn1Lvoni.cjs.js +0 -1
- package/dist/javascript-Bnnicc83.cjs.js +0 -1
- package/dist/javascript-fa8UlHZE.es.js +0 -6
- package/dist/jinja-BoeZymy4.cjs.js +0 -1
- package/dist/jinja-DKLHYjK0.es.js +0 -11
- package/dist/jison-C0DlFEjB.cjs.js +0 -1
- package/dist/jison-CzPfUIvM.es.js +0 -8
- package/dist/json-71t8ZF9g.es.js +0 -6
- package/dist/json-y-J1j5EW.cjs.js +0 -1
- package/dist/json5-CzvlWgZ7.cjs.js +0 -1
- package/dist/json5-Z7F6rA6a.es.js +0 -6
- package/dist/jsonc-BnhWfmQw.cjs.js +0 -1
- package/dist/jsonc-Dphhs4m2.es.js +0 -6
- package/dist/jsonl-BbGkWPJz.cjs.js +0 -1
- package/dist/jsonl-D9jj92Gg.es.js +0 -6
- package/dist/jsonnet-Bn--UDZ1.cjs.js +0 -1
- package/dist/jsonnet-DEQ7IUoJ.es.js +0 -6
- package/dist/jssm-4CSVp8lc.cjs.js +0 -1
- package/dist/jssm-j74e88UX.es.js +0 -6
- package/dist/jsx-Bkesy5tT.es.js +0 -6
- package/dist/jsx-D8YwVp-7.cjs.js +0 -1
- package/dist/julia-B_r6juN7.es.js +0 -16
- package/dist/julia-DLxGoAlk.cjs.js +0 -1
- package/dist/kanagawa-dragon-BJZF7xDr.cjs.js +0 -1
- package/dist/kanagawa-dragon-CiKur4Hl.es.js +0 -4
- package/dist/kanagawa-lotus-BKu-smKu.es.js +0 -4
- package/dist/kanagawa-lotus-BhgzmRV4.cjs.js +0 -1
- package/dist/kanagawa-wave-BgJip59C.cjs.js +0 -1
- package/dist/kanagawa-wave-CQwozSzG.es.js +0 -4
- package/dist/kotlin-DCgZY7Ii.es.js +0 -6
- package/dist/kotlin-DDI6myF6.cjs.js +0 -1
- package/dist/kusto-Cw029H-v.es.js +0 -6
- package/dist/kusto-OZxALJZT.cjs.js +0 -1
- package/dist/laserwave--izBLY1I.cjs.js +0 -1
- package/dist/laserwave-6a00oqik.es.js +0 -4
- package/dist/latex-CXOK56Uv.cjs.js +0 -1
- package/dist/latex-GxBxlqbc.es.js +0 -8
- package/dist/lean-CYSet4vs.es.js +0 -6
- package/dist/lean-D1iY-35j.cjs.js +0 -1
- package/dist/less-DIaY7vQJ.cjs.js +0 -1
- package/dist/less-DQA4v-Nm.es.js +0 -6
- package/dist/light-plus-B5D0le0o.cjs.js +0 -1
- package/dist/light-plus-CZuVqSLX.es.js +0 -4
- package/dist/liquid-BYouVITI.cjs.js +0 -1
- package/dist/liquid-BxBkR-z5.es.js +0 -14
- package/dist/log-BIXUeBaj.cjs.js +0 -1
- package/dist/log-D2eRfqDn.es.js +0 -6
- package/dist/logo-B2d3b27P.cjs.js +0 -1
- package/dist/logo-QEAtGWZ9.es.js +0 -6
- package/dist/lua-B2_GGnC5.cjs.js +0 -1
- package/dist/lua-DeXVjwzF.es.js +0 -8
- package/dist/luau-BjYGiqID.es.js +0 -6
- package/dist/luau-CvqAeq4F.cjs.js +0 -1
- package/dist/make-BjuHP00g.es.js +0 -6
- package/dist/make-Oob5Z9Pk.cjs.js +0 -1
- package/dist/markdown-B6guhLWd.es.js +0 -6
- package/dist/markdown-BGBuj4LZ.cjs.js +0 -1
- package/dist/marko-CS7eEGs3.cjs.js +0 -1
- package/dist/marko-DwPYPpB3.es.js +0 -14
- package/dist/material-theme-D6KBX41T.es.js +0 -4
- package/dist/material-theme-Dj0-OyRN.cjs.js +0 -1
- package/dist/material-theme-darker-CkRroheE.es.js +0 -4
- package/dist/material-theme-darker-Dvfs29ir.cjs.js +0 -1
- package/dist/material-theme-lighter-BUBw43Yz.es.js +0 -4
- package/dist/material-theme-lighter-EU3ZGl_r.cjs.js +0 -1
- package/dist/material-theme-ocean-ClGX14Ja.es.js +0 -4
- package/dist/material-theme-ocean-px_3Pwqa.cjs.js +0 -1
- package/dist/material-theme-palenight-38jxvsGX.cjs.js +0 -1
- package/dist/material-theme-palenight-C1RVm8K1.es.js +0 -4
- package/dist/matlab-BpQlIJiw.es.js +0 -6
- package/dist/matlab-CbN2rF6P.cjs.js +0 -1
- package/dist/mdc-Bkl-bu_Z.cjs.js +0 -1
- package/dist/mdc-X4YjkufV.es.js +0 -12
- package/dist/mdx-Cl31h8mi.cjs.js +0 -1
- package/dist/mdx-DIoECIFU.es.js +0 -6
- package/dist/mermaid-BZ7WHNIe.es.js +0 -6
- package/dist/mermaid-CSogK_LM.cjs.js +0 -1
- package/dist/min-dark-C7ak0t6c.es.js +0 -4
- package/dist/min-dark-tt5o_I5e.cjs.js +0 -1
- package/dist/min-light-CKFxVcPp.es.js +0 -4
- package/dist/min-light-tmTHl_CQ.cjs.js +0 -1
- package/dist/mipsasm-BseoYJQp.cjs.js +0 -1
- package/dist/mipsasm-DusDYkFc.es.js +0 -6
- package/dist/mojo-CY9jaezJ.es.js +0 -6
- package/dist/mojo-D8QAG3Ze.cjs.js +0 -1
- package/dist/monokai-C1KBYcO0.es.js +0 -4
- package/dist/monokai-DMIxv6MM.cjs.js +0 -1
- package/dist/move-ChphFumd.es.js +0 -6
- package/dist/move-DaBrcjat.cjs.js +0 -1
- package/dist/narrat-Dz4d7OmN.es.js +0 -6
- package/dist/narrat-oOfAO4q8.cjs.js +0 -1
- package/dist/nextflow-BxJSKvPb.cjs.js +0 -1
- package/dist/nextflow-DW0Yq9a2.es.js +0 -6
- package/dist/nginx-ChI-VqNT.es.js +0 -8
- package/dist/nginx-LuyFICzP.cjs.js +0 -1
- package/dist/night-owl-BN78kThQ.cjs.js +0 -1
- package/dist/night-owl-Bm2rzalh.es.js +0 -4
- package/dist/nim-BiJA-5u7.es.js +0 -20
- package/dist/nim-DkC83hsN.cjs.js +0 -1
- package/dist/nix-Cg5uV_xg.es.js +0 -6
- package/dist/nix-DNME0Ea7.cjs.js +0 -1
- package/dist/nord-CC5OiUXg.es.js +0 -4
- package/dist/nord-Ca5AGUWc.cjs.js +0 -1
- package/dist/nushell-BfRnzRWn.es.js +0 -6
- package/dist/nushell-DI9Z3l3M.cjs.js +0 -1
- package/dist/objective-c-BGg9R27G.es.js +0 -6
- package/dist/objective-c-DVx8Rcni.cjs.js +0 -1
- package/dist/objective-cpp-CJ3y3V_5.es.js +0 -6
- package/dist/objective-cpp-s6XI7Jvk.cjs.js +0 -1
- package/dist/ocaml-BZLsfx_o.es.js +0 -6
- package/dist/ocaml-kUzDDUf2.cjs.js +0 -1
- package/dist/one-dark-pro-D7-kP8fv.es.js +0 -4
- package/dist/one-dark-pro-JOzzHStv.cjs.js +0 -1
- package/dist/one-light-020-h_lv.cjs.js +0 -1
- package/dist/one-light-D9sNaUtq.es.js +0 -4
- package/dist/pascal-D509_I72.cjs.js +0 -1
- package/dist/pascal-l2bqd7Dz.es.js +0 -6
- package/dist/perl-CkXYjL3t.es.js +0 -16
- package/dist/perl-DUnCLRB_.cjs.js +0 -1
- package/dist/php-D0k1sQr6.cjs.js +0 -1
- package/dist/php-q40Yjh5d.es.js +0 -18
- package/dist/plastic-CSTz3KZp.es.js +0 -4
- package/dist/plastic-r5piqq-S.cjs.js +0 -1
- package/dist/plsql-C_qH_YOK.cjs.js +0 -1
- package/dist/plsql-oVq_K_wH.es.js +0 -6
- package/dist/po-5jaeIyVd.es.js +0 -6
- package/dist/po-CBsLQIcu.cjs.js +0 -1
- package/dist/poimandres-BLP3NNjc.cjs.js +0 -1
- package/dist/poimandres-C-VADXHD.es.js +0 -4
- package/dist/polar-De-CDeYv.cjs.js +0 -1
- package/dist/polar-wcLp8ci7.es.js +0 -6
- package/dist/postcss-BZ3MNRIJ.es.js +0 -6
- package/dist/postcss-BtcsgaYj.cjs.js +0 -1
- package/dist/powerquery-B0rHn13V.cjs.js +0 -1
- package/dist/powerquery-CgRa2XRw.es.js +0 -6
- package/dist/powershell-Diwyv8Eh.es.js +0 -6
- package/dist/powershell-rCX2OYXT.cjs.js +0 -1
- package/dist/prisma-BaaUHYMp.cjs.js +0 -1
- package/dist/prisma-COL_v1x4.es.js +0 -6
- package/dist/prolog-CuvJOxqT.es.js +0 -6
- package/dist/prolog-DrXD2tGS.cjs.js +0 -1
- package/dist/proto-BtmQjBQu.cjs.js +0 -1
- package/dist/proto-o9HLmF90.es.js +0 -6
- package/dist/pug-Br4hpvIv.es.js +0 -12
- package/dist/pug-CFQMpTUe.cjs.js +0 -1
- package/dist/puppet-cIrXIuy8.cjs.js +0 -1
- package/dist/puppet-wpGOnQp5.es.js +0 -6
- package/dist/purescript-B_1NgE2N.es.js +0 -6
- package/dist/purescript-CX9QPs2N.cjs.js +0 -1
- package/dist/python-B9x3euv6.cjs.js +0 -1
- package/dist/python-xYxLFJY-.es.js +0 -6
- package/dist/qml-CzqrIM5W.cjs.js +0 -1
- package/dist/qml-D5gi21kK.es.js +0 -8
- package/dist/qmldir-BInDYbpo.es.js +0 -6
- package/dist/qmldir-DNF9H2ir.cjs.js +0 -1
- package/dist/qss-C744dLby.cjs.js +0 -1
- package/dist/qss-D-h4NdUG.es.js +0 -6
- package/dist/r-DgOc9oMe.cjs.js +0 -1
- package/dist/r-F-9I-ITZ.es.js +0 -6
- package/dist/racket-BoD1TBFT.es.js +0 -6
- package/dist/racket-Do9_vqnd.cjs.js +0 -1
- package/dist/raku-BW8wAUIz.cjs.js +0 -1
- package/dist/raku-IaYcw19m.es.js +0 -6
- package/dist/razor-Bt_t1YJb.es.js +0 -10
- package/dist/razor-COQhlwWF.cjs.js +0 -1
- package/dist/red-7y8PH7HH.es.js +0 -4
- package/dist/red-BQGOv1D5.cjs.js +0 -1
- package/dist/reg-CGWN_v-z.cjs.js +0 -1
- package/dist/reg-CMUdAgIP.es.js +0 -6
- package/dist/regexp-GiFkbxS-.es.js +0 -6
- package/dist/regexp-N7Z4hEeU.cjs.js +0 -1
- package/dist/rel-BYqA7mnV.cjs.js +0 -1
- package/dist/rel-BaRn3QX7.es.js +0 -6
- package/dist/riscv-B9V3SsvW.es.js +0 -6
- package/dist/riscv-ayQMUpo9.cjs.js +0 -1
- package/dist/rose-pine-DKEdv1Oe.cjs.js +0 -1
- package/dist/rose-pine-DhT-HZE9.es.js +0 -4
- package/dist/rose-pine-dawn-Bvt6DtVH.cjs.js +0 -1
- package/dist/rose-pine-dawn-DiCjL2i4.es.js +0 -4
- package/dist/rose-pine-moon-BNmGHlcn.es.js +0 -4
- package/dist/rose-pine-moon-cHuJy0Ng.cjs.js +0 -1
- package/dist/rst-BmKw97ch.es.js +0 -22
- package/dist/rst-Bq-h_T5U.cjs.js +0 -1
- package/dist/ruby-Bw5IEIKD.cjs.js +0 -1
- package/dist/ruby-cs7BSa_9.es.js +0 -30
- package/dist/rust-BnFKGEfa.cjs.js +0 -1
- package/dist/rust-Pc7DCsZD.es.js +0 -6
- package/dist/sas-BWKaSYkZ.cjs.js +0 -1
- package/dist/sas-DgvHx4mL.es.js +0 -8
- package/dist/sass-B9gYryDE.cjs.js +0 -1
- package/dist/sass-iCyS6eP9.es.js +0 -6
- package/dist/scala-C85dOwSU.cjs.js +0 -1
- package/dist/scala-Cly-fENF.es.js +0 -6
- package/dist/scheme-B_XUaARm.cjs.js +0 -1
- package/dist/scheme-Zi24oEYu.es.js +0 -6
- package/dist/scss-B_hSZppj.es.js +0 -8
- package/dist/scss-CV3c8_Y7.cjs.js +0 -1
- package/dist/sdbl-7Y5u0OW0.cjs.js +0 -1
- package/dist/sdbl-BBamrXFL.es.js +0 -6
- package/dist/shaderlab-CJ8U2E2w.cjs.js +0 -1
- package/dist/shaderlab-U9mqcu_f.es.js +0 -8
- package/dist/shellscript-3DYM9fut.cjs.js +0 -1
- package/dist/shellscript-Dn0-btNd.es.js +0 -6
- package/dist/shellsession-CbKmorC3.cjs.js +0 -1
- package/dist/shellsession-LvXGClmj.es.js +0 -8
- package/dist/slack-dark-akqwQ7ED.cjs.js +0 -1
- package/dist/slack-dark-i7wN4OET.es.js +0 -4
- package/dist/slack-ochin-BoQQWmTv.cjs.js +0 -1
- package/dist/slack-ochin-ndHf0LoP.es.js +0 -4
- package/dist/smalltalk-CCvytUuW.cjs.js +0 -1
- package/dist/smalltalk-Cns31tKw.es.js +0 -6
- package/dist/snazzy-light-BlSJXAu4.es.js +0 -4
- package/dist/snazzy-light-D_IwRieF.cjs.js +0 -1
- package/dist/solarized-dark-UTmkh7lw.es.js +0 -4
- package/dist/solarized-dark-gmm-WbDC.cjs.js +0 -1
- package/dist/solarized-light-BheCkDPT.es.js +0 -4
- package/dist/solarized-light-DzcxRSZP.cjs.js +0 -1
- package/dist/solidity-BG_k8fA_.es.js +0 -6
- package/dist/solidity-BcNcjFC4.cjs.js +0 -1
- package/dist/soy-B2d9ZydM.cjs.js +0 -1
- package/dist/soy-C0yEn39K.es.js +0 -8
- package/dist/sparql-CiBxIK0g.cjs.js +0 -1
- package/dist/sparql-CuZaxpno.es.js +0 -8
- package/dist/splunk-CTqDjQdo.es.js +0 -6
- package/dist/splunk-CzITjJj7.cjs.js +0 -1
- package/dist/sql-BqWZrLHB.cjs.js +0 -1
- package/dist/sql-DCkt643-.es.js +0 -6
- package/dist/ssh-config-DHHGll-v.es.js +0 -6
- package/dist/ssh-config-DUPeuEdB.cjs.js +0 -1
- package/dist/stata-B8m3qL-x.cjs.js +0 -1
- package/dist/stata-Dv81f34z.es.js +0 -8
- package/dist/stylus-ByHs6N-o.cjs.js +0 -1
- package/dist/stylus-n_9f0QQ5.es.js +0 -6
- package/dist/svelte-CfLoBBrI.cjs.js +0 -1
- package/dist/svelte-SoJd35Jr.es.js +0 -14
- package/dist/swift-BAWqNR8A.es.js +0 -6
- package/dist/swift-C5DnOriA.cjs.js +0 -1
- package/dist/synthwave-84-BBRLOmNT.cjs.js +0 -1
- package/dist/synthwave-84-NU3C_KFZ.es.js +0 -4
- package/dist/system-verilog-ClPLYLwh.cjs.js +0 -1
- package/dist/system-verilog-Cui-g-ut.es.js +0 -6
- package/dist/systemd-BASX0DlX.cjs.js +0 -1
- package/dist/systemd-CsKYQIQK.es.js +0 -6
- package/dist/talonscript-D2dGh8FO.es.js +0 -6
- package/dist/talonscript-DkCSnLHD.cjs.js +0 -1
- package/dist/tasl-BAQJK7KZ.cjs.js +0 -1
- package/dist/tasl-D3W8HMV6.es.js +0 -6
- package/dist/tcl-2y0Fuc4S.es.js +0 -6
- package/dist/tcl-CwJAYTvh.cjs.js +0 -1
- package/dist/templ-BSMv2wKZ.cjs.js +0 -1
- package/dist/templ-C7he2afp.es.js +0 -12
- package/dist/terraform-BGW6Oerf.es.js +0 -6
- package/dist/terraform-s-pzyVvp.cjs.js +0 -1
- package/dist/tex-B0y3cEZp.es.js +0 -8
- package/dist/tex-DwtFCA08.cjs.js +0 -1
- package/dist/tokyo-night-9T7_vGSy.cjs.js +0 -1
- package/dist/tokyo-night-LhP3hHhi.es.js +0 -4
- package/dist/toml-CQSfOn0e.es.js +0 -6
- package/dist/toml-CyMM7IXy.cjs.js +0 -1
- package/dist/ts-tags-C5-4VQhf.es.js +0 -41
- package/dist/ts-tags-MIr66hKK.cjs.js +0 -1
- package/dist/tsv-BtvSkaG0.es.js +0 -6
- package/dist/tsv-DqNGnuVj.cjs.js +0 -1
- package/dist/tsx-DiGsgWT8.es.js +0 -6
- package/dist/tsx-DpBRUnKC.cjs.js +0 -1
- package/dist/turtle-BJ2wmjPc.es.js +0 -6
- package/dist/turtle-DfO3eAsu.cjs.js +0 -1
- package/dist/twig-BzjoX4ZJ.cjs.js +0 -1
- package/dist/twig-OmkATFdv.es.js +0 -18
- package/dist/typescript-BqvpT6pB.cjs.js +0 -1
- package/dist/typescript-buWNZFwO.es.js +0 -6
- package/dist/typespec-P-ZVy8yC.cjs.js +0 -1
- package/dist/typespec-bLbdsxJL.es.js +0 -6
- package/dist/typst-BVh2IsT9.cjs.js +0 -1
- package/dist/typst-Y9_SmXTs.es.js +0 -6
- package/dist/v-BUlE9136.cjs.js +0 -1
- package/dist/v-wa8Orrdd.es.js +0 -6
- package/dist/vala-BIymb2K_.cjs.js +0 -1
- package/dist/vala-DRdriFr_.es.js +0 -6
- package/dist/vb-E2_-jk4M.es.js +0 -6
- package/dist/vb-IXOh8mqV.cjs.js +0 -1
- package/dist/verilog-B1iBoR5_.es.js +0 -6
- package/dist/verilog-BiglCqvO.cjs.js +0 -1
- package/dist/vesper-CJsaOsSM.es.js +0 -4
- package/dist/vesper-DqLWLxOu.cjs.js +0 -1
- package/dist/vhdl-CJUzuS2t.cjs.js +0 -1
- package/dist/vhdl-CRVaAhXk.es.js +0 -6
- package/dist/viml-B-zWOd7Z.es.js +0 -6
- package/dist/viml-B1nKLcgt.cjs.js +0 -1
- package/dist/vitesse-black-BoGvW84i.es.js +0 -4
- package/dist/vitesse-black-MF-1S1MG.cjs.js +0 -1
- package/dist/vitesse-dark-Cym-eLtO.es.js +0 -4
- package/dist/vitesse-dark-SIffJYSe.cjs.js +0 -1
- package/dist/vitesse-light-CcmG315c.es.js +0 -4
- package/dist/vitesse-light-U63SkYGT.cjs.js +0 -1
- package/dist/vue-DCwwWMGI.es.js +0 -31
- package/dist/vue-DYZqcRaZ.cjs.js +0 -1
- package/dist/vue-html-CdPbyrq1.cjs.js +0 -1
- package/dist/vue-html-sRE_Ny23.es.js +0 -10
- package/dist/vyper-CO9xUkIY.cjs.js +0 -1
- package/dist/vyper-DWutKXpa.es.js +0 -6
- package/dist/wasm-Bv5f0gKv.es.js +0 -6
- package/dist/wasm-CdIThIat.cjs.js +0 -1
- package/dist/wenyan-BMYnfus1.es.js +0 -6
- package/dist/wenyan-BSJ3fk7e.cjs.js +0 -1
- package/dist/wgsl-DnPoPGDU.es.js +0 -6
- package/dist/wgsl-d3zZE7ZN.cjs.js +0 -1
- package/dist/wikitext-BRCqXN2g.cjs.js +0 -1
- package/dist/wikitext-CntM04PE.es.js +0 -6
- package/dist/wolfram-C3rR92zj.cjs.js +0 -1
- package/dist/wolfram-Ws5qPlX9.es.js +0 -6
- package/dist/xml-BRLTD55J.cjs.js +0 -1
- package/dist/xml-Ch1q_kJp.es.js +0 -8
- package/dist/xsl-DyL8yqXw.es.js +0 -8
- package/dist/xsl-ETbYGV_-.cjs.js +0 -1
- package/dist/yaml-7DV6pRKj.cjs.js +0 -1
- package/dist/yaml-Bbg74JKr.es.js +0 -6
- package/dist/zenscript-BWMxwjeH.cjs.js +0 -1
- package/dist/zenscript-C0RKE4nU.es.js +0 -6
- package/dist/zig-D6SXBGNm.es.js +0 -6
- package/dist/zig-yAcNfpgW.cjs.js +0 -1
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
import Autocomplete from "@mui/material/Autocomplete";
|
|
2
|
+
import Box from "@mui/material/Box";
|
|
3
|
+
import CircularProgress from "@mui/material/CircularProgress";
|
|
4
|
+
import FormControl from "@mui/material/FormControl";
|
|
5
|
+
import InputLabel from "@mui/material/InputLabel";
|
|
6
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
7
|
+
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
|
8
|
+
import TextField from "@mui/material/TextField";
|
|
9
|
+
import Typography from "@mui/material/Typography";
|
|
10
|
+
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
|
|
11
|
+
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
|
12
|
+
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
|
13
|
+
import dayjs, { Dayjs } from "dayjs";
|
|
14
|
+
import utc from "dayjs/plugin/utc";
|
|
15
|
+
import { useEffect, useRef, useState } from "react";
|
|
16
|
+
import {
|
|
17
|
+
DimensionSpec,
|
|
18
|
+
DimensionValue,
|
|
19
|
+
} from "../../hooks/useDimensionalFilterRangeData";
|
|
20
|
+
import {
|
|
21
|
+
FilterSelection,
|
|
22
|
+
FilterValue,
|
|
23
|
+
FilterValuePrimitive,
|
|
24
|
+
MatchType,
|
|
25
|
+
} from "../../hooks/useDimensionFilters";
|
|
26
|
+
|
|
27
|
+
dayjs.extend(utc);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Type for the retrieval function used by Retrieval filter type
|
|
31
|
+
*/
|
|
32
|
+
export type RetrievalFunction = (
|
|
33
|
+
query: string,
|
|
34
|
+
spec: DimensionSpec,
|
|
35
|
+
) => Promise<DimensionValue[]>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Props for DimensionFilter component
|
|
39
|
+
*/
|
|
40
|
+
export interface DimensionFilterProps {
|
|
41
|
+
/** The dimension specification */
|
|
42
|
+
spec: DimensionSpec;
|
|
43
|
+
/** Available values for this dimension */
|
|
44
|
+
values: DimensionValue[];
|
|
45
|
+
/** Current filter selection (optional) */
|
|
46
|
+
selection?: FilterSelection | null;
|
|
47
|
+
/** Callback when filter changes */
|
|
48
|
+
onChange: (selection: FilterSelection | null) => void;
|
|
49
|
+
/** Retrieval function for semantic search (required for Retrieval filter type) */
|
|
50
|
+
retrievalFn?: RetrievalFunction;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get available match types based on filter type
|
|
55
|
+
*/
|
|
56
|
+
function getAvailableMatchTypes(
|
|
57
|
+
filterType: DimensionSpec["filterType"],
|
|
58
|
+
): MatchType[] {
|
|
59
|
+
switch (filterType) {
|
|
60
|
+
case "Star":
|
|
61
|
+
return ["Equals", "Contains"];
|
|
62
|
+
case "MinMax":
|
|
63
|
+
return ["Equals", "Less Than", "Greater Than", "Between"];
|
|
64
|
+
case "DateMinMax":
|
|
65
|
+
return ["Equals", "Before", "After", "Between"];
|
|
66
|
+
case "Retrieval":
|
|
67
|
+
return ["Concept Search"];
|
|
68
|
+
case "Boolean":
|
|
69
|
+
return ["Equals"];
|
|
70
|
+
case "NONE":
|
|
71
|
+
default:
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Determines if the filter type uses date values
|
|
78
|
+
*/
|
|
79
|
+
function isDateFilter(filterType: DimensionSpec["filterType"]): boolean {
|
|
80
|
+
return filterType === "DateMinMax";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Determines if the match type requires two values
|
|
85
|
+
*/
|
|
86
|
+
function requiresTwoValues(matchType: MatchType): boolean {
|
|
87
|
+
return matchType === "Between";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* DimensionFilter component - Renders appropriate filter UI based on dimension type
|
|
92
|
+
*
|
|
93
|
+
* This component dynamically renders the appropriate filter UI based on the dimension's
|
|
94
|
+
* filter type and selected match type. It supports:
|
|
95
|
+
* - Star filters: Dropdown selection or text search
|
|
96
|
+
* - MinMax filters: Numeric input with comparison operators
|
|
97
|
+
* - DateMinMax filters: Date pickers with date comparison operators
|
|
98
|
+
*
|
|
99
|
+
* @param props - Component props including spec, values, selection, and onChange callback
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```tsx
|
|
103
|
+
* <DimensionFilter
|
|
104
|
+
* spec={{ dimensionName: "category", filterType: "Star" }}
|
|
105
|
+
* values={categoryValues}
|
|
106
|
+
* selection={currentSelection}
|
|
107
|
+
* onChange={(selection) => updateFilter("category", selection)}
|
|
108
|
+
* />
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export function DimensionFilter({
|
|
112
|
+
spec,
|
|
113
|
+
values,
|
|
114
|
+
selection,
|
|
115
|
+
onChange,
|
|
116
|
+
retrievalFn,
|
|
117
|
+
}: DimensionFilterProps) {
|
|
118
|
+
// Default to "Between" for date filters, otherwise use first available match type
|
|
119
|
+
const getDefaultMatchType = () => {
|
|
120
|
+
if (selection?.matchType) return selection.matchType;
|
|
121
|
+
if (spec.filterType === "DateMinMax") return "Between";
|
|
122
|
+
return getAvailableMatchTypes(spec.filterType)[0] || "Equals";
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const [matchType, setMatchType] = useState<MatchType>(getDefaultMatchType());
|
|
126
|
+
const [value1, setValue1] = useState<FilterValue | "">(
|
|
127
|
+
selection?.value ?? "",
|
|
128
|
+
);
|
|
129
|
+
const [value2, setValue2] = useState<FilterValuePrimitive | "">(
|
|
130
|
+
selection?.value2 ?? "",
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// Retrieval state
|
|
134
|
+
const [retrievalOptions, setRetrievalOptions] = useState<DimensionValue[]>(
|
|
135
|
+
[],
|
|
136
|
+
);
|
|
137
|
+
const [retrievalLoading, setRetrievalLoading] = useState(false);
|
|
138
|
+
const [retrievalInputValue, setRetrievalInputValue] = useState("");
|
|
139
|
+
const [retrievalSearched, setRetrievalSearched] = useState(false);
|
|
140
|
+
const [retrievalFocused, setRetrievalFocused] = useState(false);
|
|
141
|
+
const pendingRequestRef = useRef<string | null>(null);
|
|
142
|
+
const isRequestInFlightRef = useRef(false);
|
|
143
|
+
|
|
144
|
+
// MinMax focus state for showing helper text
|
|
145
|
+
const [showMinMaxHelper, setShowMinMaxHelper] = useState(false);
|
|
146
|
+
|
|
147
|
+
// Effect to trigger retrieval
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
if (spec.filterType !== "Retrieval" || !retrievalFn) return;
|
|
150
|
+
|
|
151
|
+
const query = retrievalInputValue.trim();
|
|
152
|
+
if (query.length <= 2) {
|
|
153
|
+
setRetrievalOptions([]);
|
|
154
|
+
setRetrievalSearched(false);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const performRetrieval = async (searchQuery: string) => {
|
|
159
|
+
if (isRequestInFlightRef.current) {
|
|
160
|
+
pendingRequestRef.current = searchQuery;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
isRequestInFlightRef.current = true;
|
|
165
|
+
setRetrievalLoading(true);
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const results = await retrievalFn(searchQuery, spec);
|
|
169
|
+
setRetrievalOptions(results);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.error("Retrieval failed", e);
|
|
172
|
+
setRetrievalOptions([]);
|
|
173
|
+
} finally {
|
|
174
|
+
isRequestInFlightRef.current = false;
|
|
175
|
+
setRetrievalLoading(false);
|
|
176
|
+
setRetrievalSearched(true);
|
|
177
|
+
|
|
178
|
+
// Check pending
|
|
179
|
+
if (pendingRequestRef.current) {
|
|
180
|
+
const nextQuery = pendingRequestRef.current;
|
|
181
|
+
pendingRequestRef.current = null;
|
|
182
|
+
setTimeout(() => performRetrieval(nextQuery), 0);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Debounce
|
|
188
|
+
const timeoutId = setTimeout(() => {
|
|
189
|
+
performRetrieval(query);
|
|
190
|
+
}, 300);
|
|
191
|
+
|
|
192
|
+
return () => clearTimeout(timeoutId);
|
|
193
|
+
}, [retrievalInputValue, spec, retrievalFn]);
|
|
194
|
+
|
|
195
|
+
// Sync internal state with selection prop changes (e.g., when filter is cleared externally)
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (selection === null) {
|
|
198
|
+
// Clear internal state when selection is cleared externally
|
|
199
|
+
setValue1("");
|
|
200
|
+
setValue2("");
|
|
201
|
+
// Reset to default match type (Between for dates, first available for others)
|
|
202
|
+
setMatchType(
|
|
203
|
+
spec.filterType === "DateMinMax"
|
|
204
|
+
? "Between"
|
|
205
|
+
: getAvailableMatchTypes(spec.filterType)[0] || "Equals",
|
|
206
|
+
);
|
|
207
|
+
} else if (selection) {
|
|
208
|
+
// Update internal state when selection changes externally
|
|
209
|
+
setMatchType(selection.matchType);
|
|
210
|
+
// Use nullish coalescing to preserve false/0 values
|
|
211
|
+
setValue1(selection.value ?? "");
|
|
212
|
+
setValue2(selection.value2 ?? "");
|
|
213
|
+
}
|
|
214
|
+
}, [selection, spec.filterType]);
|
|
215
|
+
|
|
216
|
+
const availableMatchTypes = getAvailableMatchTypes(spec.filterType);
|
|
217
|
+
const isDate = isDateFilter(spec.filterType);
|
|
218
|
+
const needsTwoValues = requiresTwoValues(matchType);
|
|
219
|
+
|
|
220
|
+
// Extract min/max values for range filters (use UTC to avoid timezone shifts)
|
|
221
|
+
const minDate =
|
|
222
|
+
isDate && values.length >= 2 && values[0].value instanceof Date
|
|
223
|
+
? dayjs.utc(values[0].value)
|
|
224
|
+
: undefined;
|
|
225
|
+
const maxDate =
|
|
226
|
+
isDate && values.length >= 2 && values[1].value instanceof Date
|
|
227
|
+
? dayjs.utc(values[1].value)
|
|
228
|
+
: undefined;
|
|
229
|
+
|
|
230
|
+
// Extract min/max numbers for MinMax filters
|
|
231
|
+
const minNumber =
|
|
232
|
+
spec.filterType === "MinMax" &&
|
|
233
|
+
values.length >= 2 &&
|
|
234
|
+
typeof values[0].value === "number"
|
|
235
|
+
? values[0].value
|
|
236
|
+
: undefined;
|
|
237
|
+
const maxNumber =
|
|
238
|
+
spec.filterType === "MinMax" &&
|
|
239
|
+
values.length >= 2 &&
|
|
240
|
+
typeof values[1].value === "number"
|
|
241
|
+
? values[1].value
|
|
242
|
+
: undefined;
|
|
243
|
+
|
|
244
|
+
// Don't render if no match types available
|
|
245
|
+
if (availableMatchTypes.length === 0) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Handle match type change
|
|
250
|
+
const handleMatchTypeChange = (event: SelectChangeEvent<MatchType>) => {
|
|
251
|
+
const newMatchType = event.target.value as MatchType;
|
|
252
|
+
setMatchType(newMatchType);
|
|
253
|
+
|
|
254
|
+
// Clear value2 if not needed
|
|
255
|
+
if (!requiresTwoValues(newMatchType)) {
|
|
256
|
+
setValue2("");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Update selection
|
|
260
|
+
if (value1) {
|
|
261
|
+
onChange({
|
|
262
|
+
dimensionName: spec.dimensionName,
|
|
263
|
+
matchType: newMatchType,
|
|
264
|
+
value: value1,
|
|
265
|
+
...(requiresTwoValues(newMatchType) && value2 && { value2 }),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// Handle value change
|
|
271
|
+
const handleValueChange = (
|
|
272
|
+
newValue1: FilterValue | "" | null,
|
|
273
|
+
newValue2?: FilterValuePrimitive | "" | null,
|
|
274
|
+
) => {
|
|
275
|
+
setValue1(newValue1 ?? "");
|
|
276
|
+
if (newValue2 !== undefined) {
|
|
277
|
+
setValue2(newValue2 ?? "");
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// check for empty array (multi-select cleared)
|
|
281
|
+
const isEmptyArray = Array.isArray(newValue1) && newValue1.length === 0;
|
|
282
|
+
|
|
283
|
+
// Only call onChange if we have a valid value
|
|
284
|
+
if (
|
|
285
|
+
!isEmptyArray &&
|
|
286
|
+
newValue1 !== "" &&
|
|
287
|
+
newValue1 !== null &&
|
|
288
|
+
newValue1 !== undefined
|
|
289
|
+
) {
|
|
290
|
+
onChange({
|
|
291
|
+
dimensionName: spec.dimensionName,
|
|
292
|
+
matchType,
|
|
293
|
+
value: newValue1,
|
|
294
|
+
...(needsTwoValues && newValue2 && { value2: newValue2 }),
|
|
295
|
+
});
|
|
296
|
+
} else {
|
|
297
|
+
onChange(null);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Handle clear
|
|
302
|
+
const handleClear = () => {
|
|
303
|
+
setValue1("");
|
|
304
|
+
setValue2("");
|
|
305
|
+
onChange(null);
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
return (
|
|
309
|
+
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
|
|
310
|
+
{/* Dimension Name */}
|
|
311
|
+
<Box sx={{ fontWeight: 600, fontSize: "0.875rem" }}>
|
|
312
|
+
{spec.dimensionName}
|
|
313
|
+
</Box>
|
|
314
|
+
|
|
315
|
+
{/* Match Type Selector */}
|
|
316
|
+
{spec.filterType !== "Boolean" && (
|
|
317
|
+
<FormControl size="small" fullWidth>
|
|
318
|
+
<InputLabel>Match Type</InputLabel>
|
|
319
|
+
<Select
|
|
320
|
+
value={matchType}
|
|
321
|
+
label="Match Type"
|
|
322
|
+
onChange={handleMatchTypeChange}
|
|
323
|
+
>
|
|
324
|
+
{availableMatchTypes.map((type) => (
|
|
325
|
+
<MenuItem key={type} value={type}>
|
|
326
|
+
{type}
|
|
327
|
+
</MenuItem>
|
|
328
|
+
))}
|
|
329
|
+
</Select>
|
|
330
|
+
</FormControl>
|
|
331
|
+
)}
|
|
332
|
+
|
|
333
|
+
{/* Value Input - varies by filter type */}
|
|
334
|
+
{spec.filterType === "Star" && matchType === "Equals" && (
|
|
335
|
+
<Autocomplete
|
|
336
|
+
multiple
|
|
337
|
+
size="small"
|
|
338
|
+
options={values}
|
|
339
|
+
getOptionLabel={(option) => {
|
|
340
|
+
if (typeof option === "string") {
|
|
341
|
+
return option;
|
|
342
|
+
}
|
|
343
|
+
if (
|
|
344
|
+
typeof option === "object" &&
|
|
345
|
+
option !== null &&
|
|
346
|
+
"value" in option
|
|
347
|
+
) {
|
|
348
|
+
return String((option as DimensionValue).value);
|
|
349
|
+
}
|
|
350
|
+
return String(option);
|
|
351
|
+
}}
|
|
352
|
+
value={
|
|
353
|
+
Array.isArray(value1)
|
|
354
|
+
? value1.map(
|
|
355
|
+
(v: string) =>
|
|
356
|
+
values.find((opt) => opt.value === v) || v,
|
|
357
|
+
)
|
|
358
|
+
: value1
|
|
359
|
+
? [values.find((v) => v.value === value1) || value1]
|
|
360
|
+
: []
|
|
361
|
+
}
|
|
362
|
+
onChange={(_, newValue) => {
|
|
363
|
+
const newValues = newValue.map((item) => {
|
|
364
|
+
if (typeof item === "string") return item;
|
|
365
|
+
if (item && typeof item === "object" && "value" in item) {
|
|
366
|
+
return (item as DimensionValue).value;
|
|
367
|
+
}
|
|
368
|
+
return item;
|
|
369
|
+
}) as FilterValuePrimitive[];
|
|
370
|
+
handleValueChange(newValues);
|
|
371
|
+
}}
|
|
372
|
+
noOptionsText="No matches found"
|
|
373
|
+
renderInput={(params) => (
|
|
374
|
+
<TextField
|
|
375
|
+
{...params}
|
|
376
|
+
label="Values"
|
|
377
|
+
placeholder="Select values..."
|
|
378
|
+
/>
|
|
379
|
+
)}
|
|
380
|
+
freeSolo={!spec.values || spec.values.length === 0}
|
|
381
|
+
/>
|
|
382
|
+
)}
|
|
383
|
+
|
|
384
|
+
{spec.filterType === "Star" && matchType === "Contains" && (
|
|
385
|
+
<TextField
|
|
386
|
+
size="small"
|
|
387
|
+
label="Search Text"
|
|
388
|
+
value={value1}
|
|
389
|
+
onChange={(e) => handleValueChange(e.target.value)}
|
|
390
|
+
placeholder="Enter text to search..."
|
|
391
|
+
fullWidth
|
|
392
|
+
/>
|
|
393
|
+
)}
|
|
394
|
+
|
|
395
|
+
{spec.filterType === "Boolean" && (
|
|
396
|
+
<FormControl size="small" fullWidth>
|
|
397
|
+
<InputLabel>Value</InputLabel>
|
|
398
|
+
<Select
|
|
399
|
+
value={
|
|
400
|
+
value1 === true ? "true" : value1 === false ? "false" : ""
|
|
401
|
+
}
|
|
402
|
+
label="Value"
|
|
403
|
+
onChange={(e) => {
|
|
404
|
+
const val = e.target.value;
|
|
405
|
+
if (val === "true") handleValueChange(true);
|
|
406
|
+
else if (val === "false") handleValueChange(false);
|
|
407
|
+
else handleClear();
|
|
408
|
+
}}
|
|
409
|
+
>
|
|
410
|
+
<MenuItem value="">
|
|
411
|
+
<em>Blank</em>
|
|
412
|
+
</MenuItem>
|
|
413
|
+
<MenuItem value="true">True</MenuItem>
|
|
414
|
+
<MenuItem value="false">False</MenuItem>
|
|
415
|
+
</Select>
|
|
416
|
+
</FormControl>
|
|
417
|
+
)}
|
|
418
|
+
|
|
419
|
+
{spec.filterType === "Retrieval" && matchType === "Concept Search" && (
|
|
420
|
+
<Autocomplete
|
|
421
|
+
multiple
|
|
422
|
+
size="small"
|
|
423
|
+
options={retrievalOptions}
|
|
424
|
+
loading={retrievalLoading}
|
|
425
|
+
getOptionLabel={(option) => {
|
|
426
|
+
if (typeof option === "string") {
|
|
427
|
+
return option;
|
|
428
|
+
}
|
|
429
|
+
if (
|
|
430
|
+
typeof option === "object" &&
|
|
431
|
+
option !== null &&
|
|
432
|
+
"value" in option
|
|
433
|
+
) {
|
|
434
|
+
return String((option as DimensionValue).value);
|
|
435
|
+
}
|
|
436
|
+
return String(option);
|
|
437
|
+
}}
|
|
438
|
+
value={
|
|
439
|
+
Array.isArray(value1)
|
|
440
|
+
? value1.map((v: string) => {
|
|
441
|
+
const found = retrievalOptions.find(
|
|
442
|
+
(opt) => opt.value === v,
|
|
443
|
+
);
|
|
444
|
+
return found || { value: v };
|
|
445
|
+
})
|
|
446
|
+
: value1
|
|
447
|
+
? [{ value: value1 }]
|
|
448
|
+
: []
|
|
449
|
+
}
|
|
450
|
+
onInputChange={(_, newInputValue) => {
|
|
451
|
+
setRetrievalInputValue(newInputValue);
|
|
452
|
+
}}
|
|
453
|
+
onChange={(_, newValue) => {
|
|
454
|
+
const newValues = newValue.map((item) => {
|
|
455
|
+
if (typeof item === "string") return item;
|
|
456
|
+
if (item && typeof item === "object" && "value" in item) {
|
|
457
|
+
return (item as DimensionValue).value;
|
|
458
|
+
}
|
|
459
|
+
return item;
|
|
460
|
+
}) as FilterValuePrimitive[];
|
|
461
|
+
handleValueChange(newValues);
|
|
462
|
+
}}
|
|
463
|
+
noOptionsText={
|
|
464
|
+
retrievalInputValue.trim().length <= 2
|
|
465
|
+
? "Type at least 3 characters to search"
|
|
466
|
+
: "No matches found"
|
|
467
|
+
}
|
|
468
|
+
renderInput={(params) => (
|
|
469
|
+
<TextField
|
|
470
|
+
{...params}
|
|
471
|
+
label="Search Values"
|
|
472
|
+
placeholder="Type to search..."
|
|
473
|
+
onFocus={() => setRetrievalFocused(true)}
|
|
474
|
+
onBlur={() => setRetrievalFocused(false)}
|
|
475
|
+
helperText={
|
|
476
|
+
retrievalFocused &&
|
|
477
|
+
!retrievalLoading &&
|
|
478
|
+
retrievalSearched &&
|
|
479
|
+
retrievalOptions.length === 0
|
|
480
|
+
? "No matches found"
|
|
481
|
+
: undefined
|
|
482
|
+
}
|
|
483
|
+
InputProps={{
|
|
484
|
+
...params.InputProps,
|
|
485
|
+
endAdornment: (
|
|
486
|
+
<>
|
|
487
|
+
{retrievalLoading ? (
|
|
488
|
+
<CircularProgress color="inherit" size={20} />
|
|
489
|
+
) : null}
|
|
490
|
+
{params.InputProps.endAdornment}
|
|
491
|
+
</>
|
|
492
|
+
),
|
|
493
|
+
}}
|
|
494
|
+
/>
|
|
495
|
+
)}
|
|
496
|
+
freeSolo
|
|
497
|
+
filterOptions={(x) => x}
|
|
498
|
+
/>
|
|
499
|
+
)}
|
|
500
|
+
|
|
501
|
+
{spec.filterType === "MinMax" && !needsTwoValues && (
|
|
502
|
+
<TextField
|
|
503
|
+
size="small"
|
|
504
|
+
type="number"
|
|
505
|
+
label="Value"
|
|
506
|
+
value={value1}
|
|
507
|
+
onChange={(e) =>
|
|
508
|
+
handleValueChange(parseFloat(e.target.value) || "")
|
|
509
|
+
}
|
|
510
|
+
onFocus={() => setShowMinMaxHelper(true)}
|
|
511
|
+
onBlur={() => setShowMinMaxHelper(false)}
|
|
512
|
+
placeholder="Enter number..."
|
|
513
|
+
fullWidth
|
|
514
|
+
inputProps={{
|
|
515
|
+
min: minNumber,
|
|
516
|
+
max: maxNumber,
|
|
517
|
+
}}
|
|
518
|
+
helperText={
|
|
519
|
+
showMinMaxHelper &&
|
|
520
|
+
minNumber !== undefined &&
|
|
521
|
+
maxNumber !== undefined
|
|
522
|
+
? `Valid range: [${minNumber} - ${maxNumber}]`
|
|
523
|
+
: undefined
|
|
524
|
+
}
|
|
525
|
+
/>
|
|
526
|
+
)}
|
|
527
|
+
|
|
528
|
+
{spec.filterType === "MinMax" && needsTwoValues && (
|
|
529
|
+
<Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
|
|
530
|
+
<Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
|
|
531
|
+
<TextField
|
|
532
|
+
size="small"
|
|
533
|
+
type="number"
|
|
534
|
+
label="From"
|
|
535
|
+
value={value1}
|
|
536
|
+
onChange={(e) =>
|
|
537
|
+
handleValueChange(
|
|
538
|
+
parseFloat(e.target.value) || "",
|
|
539
|
+
value2,
|
|
540
|
+
)
|
|
541
|
+
}
|
|
542
|
+
onFocus={() => setShowMinMaxHelper(true)}
|
|
543
|
+
onBlur={() => setShowMinMaxHelper(false)}
|
|
544
|
+
placeholder="Min..."
|
|
545
|
+
fullWidth
|
|
546
|
+
inputProps={{
|
|
547
|
+
min: minNumber,
|
|
548
|
+
max: value2 || maxNumber,
|
|
549
|
+
}}
|
|
550
|
+
/>
|
|
551
|
+
<Box>to</Box>
|
|
552
|
+
<TextField
|
|
553
|
+
size="small"
|
|
554
|
+
type="number"
|
|
555
|
+
label="To"
|
|
556
|
+
value={value2}
|
|
557
|
+
onChange={(e) =>
|
|
558
|
+
handleValueChange(
|
|
559
|
+
value1,
|
|
560
|
+
parseFloat(e.target.value) || "",
|
|
561
|
+
)
|
|
562
|
+
}
|
|
563
|
+
onFocus={() => setShowMinMaxHelper(true)}
|
|
564
|
+
onBlur={() => setShowMinMaxHelper(false)}
|
|
565
|
+
placeholder="Max..."
|
|
566
|
+
fullWidth
|
|
567
|
+
inputProps={{
|
|
568
|
+
min: value1 || minNumber,
|
|
569
|
+
max: maxNumber,
|
|
570
|
+
}}
|
|
571
|
+
/>
|
|
572
|
+
</Box>
|
|
573
|
+
{showMinMaxHelper &&
|
|
574
|
+
minNumber !== undefined &&
|
|
575
|
+
maxNumber !== undefined && (
|
|
576
|
+
<Typography
|
|
577
|
+
variant="caption"
|
|
578
|
+
color="text.secondary"
|
|
579
|
+
sx={{ mt: -0.5, ml: 1.5 }}
|
|
580
|
+
>
|
|
581
|
+
Valid range: [{minNumber} - {maxNumber}]
|
|
582
|
+
</Typography>
|
|
583
|
+
)}
|
|
584
|
+
</Box>
|
|
585
|
+
)}
|
|
586
|
+
|
|
587
|
+
{isDate && !needsTwoValues && (
|
|
588
|
+
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
|
589
|
+
<DatePicker
|
|
590
|
+
label="Date"
|
|
591
|
+
value={value1 instanceof Date ? dayjs.utc(value1) : null}
|
|
592
|
+
onChange={(newValue: Dayjs | null) => {
|
|
593
|
+
// Only call onChange if value is null (cleared) or a valid date
|
|
594
|
+
if (newValue === null) {
|
|
595
|
+
handleValueChange(null);
|
|
596
|
+
} else if (newValue.isValid()) {
|
|
597
|
+
handleValueChange(newValue.utc().toDate());
|
|
598
|
+
}
|
|
599
|
+
// Invalid dates are ignored - don't update state
|
|
600
|
+
}}
|
|
601
|
+
timezone="UTC"
|
|
602
|
+
minDate={value1 instanceof Date ? undefined : minDate}
|
|
603
|
+
maxDate={value1 instanceof Date ? undefined : maxDate}
|
|
604
|
+
referenceDate={
|
|
605
|
+
matchType === "After" && minDate ? minDate : undefined
|
|
606
|
+
}
|
|
607
|
+
slotProps={{
|
|
608
|
+
textField: {
|
|
609
|
+
size: "small",
|
|
610
|
+
fullWidth: true,
|
|
611
|
+
sx: { minWidth: 150 },
|
|
612
|
+
onFocus: () => setShowMinMaxHelper(true),
|
|
613
|
+
onBlur: () => setShowMinMaxHelper(false),
|
|
614
|
+
helperText:
|
|
615
|
+
showMinMaxHelper && minDate && maxDate
|
|
616
|
+
? `Valid range: [${minDate.format("YYYY-MM-DD")} - ${maxDate.format("YYYY-MM-DD")}]`
|
|
617
|
+
: undefined,
|
|
618
|
+
},
|
|
619
|
+
openPickerButton: {
|
|
620
|
+
sx: { backgroundColor: "transparent" },
|
|
621
|
+
},
|
|
622
|
+
}}
|
|
623
|
+
/>
|
|
624
|
+
</LocalizationProvider>
|
|
625
|
+
)}
|
|
626
|
+
|
|
627
|
+
{isDate && needsTwoValues && (
|
|
628
|
+
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
|
629
|
+
<Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
|
|
630
|
+
<Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
|
|
631
|
+
<Box sx={{ flex: 1, minWidth: 0 }}>
|
|
632
|
+
<DatePicker
|
|
633
|
+
label="From"
|
|
634
|
+
value={
|
|
635
|
+
value1 instanceof Date ? dayjs.utc(value1) : null
|
|
636
|
+
}
|
|
637
|
+
onChange={(newValue: Dayjs | null) => {
|
|
638
|
+
// Only call onChange if value is null (cleared) or a valid date
|
|
639
|
+
if (newValue === null) {
|
|
640
|
+
handleValueChange(null, value2);
|
|
641
|
+
} else if (newValue.isValid()) {
|
|
642
|
+
handleValueChange(
|
|
643
|
+
newValue.utc().toDate(),
|
|
644
|
+
value2,
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
// Invalid dates are ignored - don't update state
|
|
648
|
+
}}
|
|
649
|
+
timezone="UTC"
|
|
650
|
+
minDate={
|
|
651
|
+
value1 instanceof Date ? undefined : minDate
|
|
652
|
+
}
|
|
653
|
+
maxDate={
|
|
654
|
+
value2 instanceof Date
|
|
655
|
+
? dayjs.utc(value2)
|
|
656
|
+
: value1 instanceof Date
|
|
657
|
+
? undefined
|
|
658
|
+
: maxDate
|
|
659
|
+
}
|
|
660
|
+
referenceDate={minDate}
|
|
661
|
+
slotProps={{
|
|
662
|
+
textField: {
|
|
663
|
+
size: "small",
|
|
664
|
+
fullWidth: true,
|
|
665
|
+
onFocus: () => setShowMinMaxHelper(true),
|
|
666
|
+
onBlur: () => setShowMinMaxHelper(false),
|
|
667
|
+
},
|
|
668
|
+
openPickerButton: {
|
|
669
|
+
sx: { backgroundColor: "transparent" },
|
|
670
|
+
},
|
|
671
|
+
}}
|
|
672
|
+
/>
|
|
673
|
+
</Box>
|
|
674
|
+
<Box>to</Box>
|
|
675
|
+
<Box sx={{ flex: 1, minWidth: 0 }}>
|
|
676
|
+
<DatePicker
|
|
677
|
+
label="To"
|
|
678
|
+
value={
|
|
679
|
+
value2 instanceof Date ? dayjs.utc(value2) : null
|
|
680
|
+
}
|
|
681
|
+
onChange={(newValue: Dayjs | null) => {
|
|
682
|
+
// Only call onChange if value is null (cleared) or a valid date
|
|
683
|
+
if (newValue === null) {
|
|
684
|
+
handleValueChange(value1, null);
|
|
685
|
+
} else if (newValue.isValid()) {
|
|
686
|
+
handleValueChange(
|
|
687
|
+
value1,
|
|
688
|
+
newValue.utc().toDate(),
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
// Invalid dates are ignored - don't update state
|
|
692
|
+
}}
|
|
693
|
+
timezone="UTC"
|
|
694
|
+
minDate={
|
|
695
|
+
value1 instanceof Date
|
|
696
|
+
? dayjs.utc(value1)
|
|
697
|
+
: value2 instanceof Date
|
|
698
|
+
? undefined
|
|
699
|
+
: minDate
|
|
700
|
+
}
|
|
701
|
+
maxDate={
|
|
702
|
+
value2 instanceof Date ? undefined : maxDate
|
|
703
|
+
}
|
|
704
|
+
referenceDate={
|
|
705
|
+
value1 instanceof Date
|
|
706
|
+
? dayjs.utc(value1)
|
|
707
|
+
: minDate
|
|
708
|
+
}
|
|
709
|
+
slotProps={{
|
|
710
|
+
textField: {
|
|
711
|
+
size: "small",
|
|
712
|
+
fullWidth: true,
|
|
713
|
+
onFocus: () => setShowMinMaxHelper(true),
|
|
714
|
+
onBlur: () => setShowMinMaxHelper(false),
|
|
715
|
+
},
|
|
716
|
+
openPickerButton: {
|
|
717
|
+
sx: { backgroundColor: "transparent" },
|
|
718
|
+
},
|
|
719
|
+
}}
|
|
720
|
+
/>
|
|
721
|
+
</Box>
|
|
722
|
+
</Box>
|
|
723
|
+
{showMinMaxHelper && minDate && maxDate && (
|
|
724
|
+
<Typography
|
|
725
|
+
variant="caption"
|
|
726
|
+
color="text.secondary"
|
|
727
|
+
sx={{ mt: -0.5, ml: 1.5 }}
|
|
728
|
+
>
|
|
729
|
+
Valid range: [{minDate.format("YYYY-MM-DD")} -{" "}
|
|
730
|
+
{maxDate.format("YYYY-MM-DD")}]
|
|
731
|
+
</Typography>
|
|
732
|
+
)}
|
|
733
|
+
</Box>
|
|
734
|
+
</LocalizationProvider>
|
|
735
|
+
)}
|
|
736
|
+
</Box>
|
|
737
|
+
);
|
|
738
|
+
}
|