@malloydata/malloy-explorer 0.0.285-dev250530165648 → 0.0.285-dev250611150446

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.
@@ -20,7 +20,7 @@ const React = require("react");
20
20
  const QB = require("@malloydata/malloy-query-builder");
21
21
  const malloyTag = require("@malloydata/malloy-tag");
22
22
  const malloyFilter = require("@malloydata/malloy-filter");
23
- require("@malloydata/render/webcomponent");
23
+ const render = require("@malloydata/render");
24
24
  const ReactDOM = require("react-dom");
25
25
  function _interopNamespaceDefault(e) {
26
26
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -3799,6 +3799,7 @@ const SvgRadioChecked = (props2) => /* @__PURE__ */ React__namespace.createEleme
3799
3799
  const SvgRadioUnchecked = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { height: 16, viewBox: "0 0 16 16", width: 16, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React__namespace.createElement("circle", { cx: 8, cy: 8, r: 8, fill: "currentColor" }), /* @__PURE__ */ React__namespace.createElement("circle", { cx: 8, cy: 8, r: 7, fill: "#FFFFFF" }));
3800
3800
  const SvgWarning = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React__namespace.createElement("path", { d: "m40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z" }));
3801
3801
  const SvgCheckCircle = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React__namespace.createElement("path", { d: "m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" }));
3802
+ const SvgGear = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { fill: "none", height: 15, viewBox: "0 0 15 15", width: 15, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React__namespace.createElement("g", { clipRule: "evenodd", fill: "#151515", fillRule: "evenodd" }, /* @__PURE__ */ React__namespace.createElement("path", { d: "m10 7.50001c0 1.38072-1.11928 2.49999-2.49999 2.49999s-2.5-1.11927-2.5-2.49999c0-1.38071 1.11929-2.5 2.5-2.5s2.49999 1.11929 2.49999 2.5zm-.99999 0c0 .82843-.67157 1.5-1.5 1.5-.82842 0-1.5-.67157-1.5-1.5 0-.82842.67158-1.5 1.5-1.5.82843 0 1.5.67158 1.5 1.5z" }), /* @__PURE__ */ React__namespace.createElement("path", { d: "m8.92908 3.05724c-.34403-1.52302-2.5141-1.52302-2.85813 0-.07078.31333-.43034.46227-.70195.29076-1.3202-.83367-2.85467.7008-2.021 2.021.17151.27161.02257.63117-.29076.70195-1.52302.34403-1.52302 2.5141 0 2.85813.31333.07077.46227.43034.29076.70195-.83367 1.32017.7008 2.85467 2.021 2.02097.27161-.1715.63117-.0225.70195.2908.34403 1.523 2.5141 1.523 2.85813 0 .07077-.3133.43034-.4623.70195-.2908 1.32017.8337 2.85467-.7008 2.02097-2.02097-.1715-.27161-.0225-.63118.2908-.70195 1.523-.34403 1.523-2.5141 0-2.85813-.3133-.07078-.4623-.43034-.2908-.70195.8337-1.3202-.7008-2.85467-2.02097-2.021-.27161.17151-.63118.02257-.70195-.29076zm-1.8827.22034c.1092-.48347.79806-.48347.90727 0 .22296.98707 1.35568 1.45625 2.21135.91595.419-.26464.9061.22246.6415.64154-.5403.85562-.0711 1.98834.916 2.21131.4834.1092.4834.79806 0 .90727-.9871.22296-1.4563 1.35568-.916 2.21135.2646.419-.2225.9061-.6415.6415-.85567-.5403-1.98839-.0711-2.21135.916-.10921.4834-.79807.4834-.90727 0-.22297-.9871-1.35569-1.4563-2.21131-.916-.41908.2646-.90618-.2225-.64154-.6415.5403-.85567.07112-1.98839-.91595-2.21135-.48347-.10921-.48347-.79807 0-.90727.98707-.22297 1.45625-1.35569.91595-2.21131-.26464-.41908.22246-.90618.64154-.64154.85562.5403 1.98834.07112 2.21131-.91595z" })));
3802
3803
  const SvgInfo = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z" }));
3803
3804
  const SvgError = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React__namespace.createElement("path", { d: "M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240ZM330-120 120-330v-300l210-210h300l210 210v300L630-120H330Zm34-80h232l164-164v-232L596-760H364L200-596v232l164 164Zm116-280Z" }));
3804
3805
  const SvgRefresh = (props2) => /* @__PURE__ */ React__namespace.createElement("svg", { height: 20, viewBox: "0 0 20 20", width: 20, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React__namespace.createElement("g", { fill: "none", stroke: "currentColor" }, /* @__PURE__ */ React__namespace.createElement("path", { d: "m17.08 11.15c.01.16.02.32.02.49 0 3.89-3.16 7.05-7.05 7.05-3.89-.01-7.05-3.16-7.05-7.06 0-3.89 3.16-7.05 7.05-7.05.85 0 1.66.15 2.41.42", strokeWidth: 1.1 }), /* @__PURE__ */ React__namespace.createElement("path", { d: "m9.9 2 2.89 2.89-3 3.01" })));
@@ -3839,6 +3840,7 @@ const ICON_MAP = {
3839
3840
  radioUnchecked: SvgRadioUnchecked,
3840
3841
  warning: SvgWarning,
3841
3842
  check_circle: SvgCheckCircle,
3843
+ gear: SvgGear,
3842
3844
  info: SvgInfo,
3843
3845
  error: SvgError,
3844
3846
  refresh: SvgRefresh,
@@ -3873,6 +3875,7 @@ const ICON_MAP = {
3873
3875
  one_to_one: SvgTypeIconOneToOne,
3874
3876
  // Visualizations
3875
3877
  viz_bar_chart: SvgVizBarChart,
3878
+ viz_bar: SvgVizBarChart,
3876
3879
  viz_boolean: SvgVizBoolean,
3877
3880
  viz_bytes: SvgVizNumber,
3878
3881
  viz_cartesian_chart: SvgVizLine,
@@ -3882,6 +3885,7 @@ const ICON_MAP = {
3882
3885
  viz_image: SvgVizImage,
3883
3886
  viz_json: SvgVizJson,
3884
3887
  viz_line_chart: SvgVizLine,
3888
+ viz_line: SvgVizLine,
3885
3889
  viz_link: SvgVizLink,
3886
3890
  viz_list: SvgVizList,
3887
3891
  viz_list_detail: SvgVizListDetail,
@@ -26166,7 +26170,9 @@ function LiteralValue({
26166
26170
  });
26167
26171
  }
26168
26172
  }
26169
- const QUERY_RENDERERS = ["table", "bar_chart", "dashboard", "json", "line_chart", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map", "sparkline"];
26173
+ const RENDERER_PREFIX = "# ";
26174
+ const VIZ_RENDERERS = ["table", "bar", "dashboard", "json", "line", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map"];
26175
+ const QUERY_RENDERERS = ["table", "bar_chart", "dashboard", "json", "line_chart", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map"];
26170
26176
  const ATOMIC_RENDERERS = ["number", "boolean", "currency", "image", "url", "percent", "text", "time"];
26171
26177
  const RENDERERS = [...QUERY_RENDERERS, ...ATOMIC_RENDERERS];
26172
26178
  function tagToRenderer(tag) {
@@ -26181,6 +26187,119 @@ function tagToRenderer(tag) {
26181
26187
  }
26182
26188
  return null;
26183
26189
  }
26190
+ function legacyToViz(name) {
26191
+ switch (name) {
26192
+ case "bar_chart":
26193
+ return "bar";
26194
+ case "line_chart":
26195
+ return "line";
26196
+ default:
26197
+ return name;
26198
+ }
26199
+ }
26200
+ const VISUALIZATION_OPTIONS = {
26201
+ table: null,
26202
+ bar: [{
26203
+ name: "title",
26204
+ label: "Title",
26205
+ type: "string",
26206
+ default: ""
26207
+ }, {
26208
+ name: "sub_title",
26209
+ label: "Subtitle",
26210
+ type: "string",
26211
+ default: ""
26212
+ }, {
26213
+ name: "stack",
26214
+ label: "Stack",
26215
+ type: "boolean",
26216
+ default: false
26217
+ }, {
26218
+ name: "size",
26219
+ label: "Size",
26220
+ type: "select",
26221
+ default: "fill",
26222
+ options: [{
26223
+ label: "Fill",
26224
+ value: "fill"
26225
+ }, {
26226
+ label: "Sparkline",
26227
+ value: "spark"
26228
+ }, {
26229
+ label: "X-Small",
26230
+ value: "xs"
26231
+ }, {
26232
+ label: "Small",
26233
+ value: "sm"
26234
+ }, {
26235
+ label: "Medium",
26236
+ value: "md"
26237
+ }, {
26238
+ label: "Large",
26239
+ value: "lg"
26240
+ }, {
26241
+ label: "X-Large",
26242
+ value: "xl"
26243
+ }, {
26244
+ label: "XX-Large",
26245
+ value: "2xl"
26246
+ }]
26247
+ }],
26248
+ dashboard: null,
26249
+ json: null,
26250
+ line: [{
26251
+ name: "title",
26252
+ label: "Title",
26253
+ type: "string",
26254
+ default: ""
26255
+ }, {
26256
+ name: "sub_title",
26257
+ label: "Subtitle",
26258
+ type: "string",
26259
+ default: ""
26260
+ }, {
26261
+ name: "zero_baseline",
26262
+ label: "Zero Baseline",
26263
+ type: "boolean",
26264
+ default: false
26265
+ }, {
26266
+ name: "size",
26267
+ label: "Size",
26268
+ type: "select",
26269
+ default: "md",
26270
+ options: [{
26271
+ label: "Fill",
26272
+ value: "fill"
26273
+ }, {
26274
+ label: "Sparkline",
26275
+ value: "spark"
26276
+ }, {
26277
+ label: "X-Small",
26278
+ value: "xs"
26279
+ }, {
26280
+ label: "Small",
26281
+ value: "sm"
26282
+ }, {
26283
+ label: "Medium",
26284
+ value: "md"
26285
+ }, {
26286
+ label: "Large",
26287
+ value: "lg"
26288
+ }, {
26289
+ label: "X-Large",
26290
+ value: "xl"
26291
+ }, {
26292
+ label: "XX-Large",
26293
+ value: "2xl"
26294
+ }]
26295
+ }],
26296
+ list: null,
26297
+ list_detail: null,
26298
+ point_map: null,
26299
+ scatter_chart: null,
26300
+ segment_map: null,
26301
+ shape_map: null
26302
+ };
26184
26303
  function atomicTypeToIcon(type) {
26185
26304
  return atomicTypeMap[type];
26186
26305
  }
@@ -30279,21 +30398,260 @@ const styles$r = {
30279
30398
  $$css: true
30280
30399
  }
30281
30400
  };
30401
+ function RendererPopover({
30402
+ rootQuery,
30403
+ viz,
30404
+ options,
30405
+ view,
30406
+ customStyle
30407
+ }) {
30408
+ const [open, setOpen] = React.useState(false);
30409
+ return /* @__PURE__ */ jsxRuntime.jsxs(Root2$2, {
30410
+ onOpenChange: (open2) => setOpen(open2),
30411
+ open,
30412
+ children: [/* @__PURE__ */ jsxRuntime.jsx(Trigger$2, {
30413
+ asChild: true,
30414
+ children: /* @__PURE__ */ jsxRuntime.jsx(Token, {
30415
+ icon: "gear",
30416
+ customStyle: {
30417
+ ...customStyle,
30418
+ ...dialogStyles$1.trigger
30419
+ }
30420
+ })
30421
+ }), /* @__PURE__ */ jsxRuntime.jsx(Portal$2, {
30422
+ children: /* @__PURE__ */ jsxRuntime.jsx(Content2$2, {
30423
+ align: "end",
30424
+ children: /* @__PURE__ */ jsxRuntime.jsx(RendererEditor, {
30425
+ rootQuery,
30426
+ view,
30427
+ viz,
30428
+ options,
30429
+ setOpen
30430
+ })
30431
+ })
30432
+ })]
30433
+ });
30434
+ }
30435
+ function RendererEditor({
30436
+ rootQuery,
30437
+ view,
30438
+ viz,
30439
+ options,
30440
+ setOpen
30441
+ }) {
30442
+ const {
30443
+ setQuery
30444
+ } = React.useContext(QueryEditorContext);
30445
+ const [current, setCurrent] = React.useState();
30446
+ React.useEffect(() => {
30447
+ const current2 = {};
30448
+ const currentTag = view.getTag(RENDERER_PREFIX);
30449
+ for (const option2 of options) {
30450
+ current2[option2.name] = currentTag.text("viz", option2.name) ?? option2.default.toString();
30451
+ }
30452
+ setCurrent(current2);
30453
+ }, [options, view, viz]);
30454
+ if (!current) {
30455
+ return null;
30456
+ }
30457
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
30458
+ ..._stylex.props(dialogStyles$1.content, fontStyles.body),
30459
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", {
30460
+ ...{
30461
+ className: "mlyqyf9gi mly78zum5 mlydt5ytf mly167g77z"
30462
+ },
30463
+ children: [/* @__PURE__ */ jsxRuntime.jsx("div", {
30464
+ ...{
30465
+ className: "mlyrvj5dj mly17bnpya mly167g77z"
30466
+ },
30467
+ children: options.map((option2) => option2.type === "boolean" ? /* @__PURE__ */ jsxRuntime.jsx(BooleanEditor, {
30468
+ option: option2,
30469
+ current,
30470
+ setCurrent
30471
+ }, option2.name) : option2.type === "string" ? /* @__PURE__ */ jsxRuntime.jsx(StringEditor$1, {
30472
+ option: option2,
30473
+ current,
30474
+ setCurrent
30475
+ }, option2.name) : (
30476
+ // option.type === 'select
30477
+ /* @__PURE__ */ jsxRuntime.jsx(SelectEditor, {
30478
+ option: option2,
30479
+ current,
30480
+ setCurrent
30481
+ }, option2.name)
30482
+ ))
30483
+ }), /* @__PURE__ */ jsxRuntime.jsxs("div", {
30484
+ ...{
30485
+ className: "mly78zum5 mly167g77z"
30486
+ },
30487
+ children: [/* @__PURE__ */ jsxRuntime.jsx(Button, {
30488
+ label: "Cancel",
30489
+ onClick: () => {
30490
+ setOpen(false);
30491
+ },
30492
+ customStyle: dialogStyles$1.editorCell
30493
+ }), /* @__PURE__ */ jsxRuntime.jsx(Button, {
30494
+ variant: "primary",
30495
+ label: "Apply",
30496
+ onClick: () => {
30497
+ if (!view.getTag(RENDERER_PREFIX).has("viz", viz)) {
30498
+ view.setTagProperty(["viz"], viz, RENDERER_PREFIX);
30499
+ }
30500
+ for (const option2 of options) {
30501
+ if (current[option2.name] !== option2.default.toString()) {
30502
+ view.setTagProperty(["viz", option2.name], current[option2.name], RENDERER_PREFIX);
30503
+ } else {
30504
+ view.removeTagProperty(["viz", option2.name], RENDERER_PREFIX);
30505
+ }
30506
+ }
30507
+ setQuery == null ? void 0 : setQuery(rootQuery.build());
30508
+ setOpen(false);
30509
+ },
30510
+ customStyle: dialogStyles$1.editorCell
30511
+ })]
30512
+ })]
30513
+ })
30514
+ });
30515
+ }
30516
+ function BooleanEditor({
30517
+ current,
30518
+ option: option2,
30519
+ setCurrent
30520
+ }) {
30521
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
30522
+ children: [/* @__PURE__ */ React.createElement("div", {
30523
+ ...{
30524
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30525
+ },
30526
+ key: option2.name
30527
+ }, /* @__PURE__ */ jsxRuntime.jsx("input", {
30528
+ type: "checkbox",
30529
+ checked: current[option2.name] === "true",
30530
+ onChange: ({
30531
+ target: {
30532
+ checked
30533
+ }
30534
+ }) => {
30535
+ setCurrent({
30536
+ ...current,
30537
+ [option2.name]: checked.toString()
30538
+ });
30539
+ }
30540
+ })), /* @__PURE__ */ jsxRuntime.jsx("label", {
30541
+ title: option2.description,
30542
+ children: option2.label
30543
+ }, `${option2.name}-label`)]
30544
+ });
30545
+ }
30546
+ function StringEditor$1({
30547
+ current,
30548
+ option: option2,
30549
+ setCurrent
30550
+ }) {
30551
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
30552
+ children: [/* @__PURE__ */ React.createElement("div", {
30553
+ ...{
30554
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30555
+ },
30556
+ key: `${option2.name}-label`
30557
+ }, /* @__PURE__ */ jsxRuntime.jsxs("label", {
30558
+ children: [option2.label, ":"]
30559
+ })), /* @__PURE__ */ jsxRuntime.jsx("input", {
30560
+ value: current[option2.name],
30561
+ onChange: ({
30562
+ target: {
30563
+ value
30564
+ }
30565
+ }) => {
30566
+ setCurrent({
30567
+ ...current,
30568
+ [option2.name]: value
30569
+ });
30570
+ }
30571
+ }, option2.name)]
30572
+ });
30573
+ }
30574
+ function SelectEditor({
30575
+ current,
30576
+ option: option2,
30577
+ setCurrent
30578
+ }) {
30579
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
30580
+ children: [/* @__PURE__ */ React.createElement("div", {
30581
+ ...{
30582
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30583
+ },
30584
+ key: `${option2.name}-label`
30585
+ }, /* @__PURE__ */ jsxRuntime.jsxs("label", {
30586
+ children: [option2.label, ":"]
30587
+ })), /* @__PURE__ */ jsxRuntime.jsx(SelectDropdown, {
30588
+ value: current[option2.name],
30589
+ options: option2.options,
30590
+ onChange: (value) => {
30591
+ setCurrent({
30592
+ ...current,
30593
+ [option2.name]: value
30594
+ });
30595
+ }
30596
+ }, option2.name)]
30597
+ });
30598
+ }
30599
+ const dialogStyles$1 = {
30600
+ trigger: {
30601
+ height: "mly1ktj5wk",
30602
+ $$css: true
30603
+ },
30604
+ content: {
30605
+ display: "mly78zum5",
30606
+ flexDirection: "mlydt5ytf",
30607
+ boxShadow: "mly5n1uv4",
30608
+ backgroundColor: "mly12peec7",
30609
+ borderRadius: "mlyur7f20",
30610
+ borderStartStartRadius: null,
30611
+ borderStartEndRadius: null,
30612
+ borderEndStartRadius: null,
30613
+ borderEndEndRadius: null,
30614
+ borderTopLeftRadius: null,
30615
+ borderTopRightRadius: null,
30616
+ borderBottomLeftRadius: null,
30617
+ borderBottomRightRadius: null,
30618
+ padding: "mlye8ttls",
30619
+ paddingInline: null,
30620
+ paddingStart: null,
30621
+ paddingLeft: null,
30622
+ paddingEnd: null,
30623
+ paddingRight: null,
30624
+ paddingBlock: null,
30625
+ paddingTop: null,
30626
+ paddingBottom: null,
30627
+ minWidth: "mlylm99nl",
30628
+ maxWidth: "mly1jkqq1h",
30629
+ gap: "mly167g77z",
30630
+ rowGap: null,
30631
+ columnGap: null,
30632
+ $$css: true
30633
+ },
30634
+ editorCell: {
30635
+ flexGrow: "mly1iyjqo2",
30636
+ $$css: true
30637
+ }
30638
+ };
30282
30639
  function Visualization$1({
30283
30640
  rootQuery,
30284
30641
  view
30285
30642
  }) {
30643
+ var _a2;
30286
30644
  const {
30287
30645
  setQuery
30288
30646
  } = React.useContext(QueryEditorContext);
30289
30647
  const currentTag = view.getTag();
30290
- const currentRenderer = tagToRenderer(currentTag) ?? "table";
30648
+ const rendererTag = view.getTag(RENDERER_PREFIX);
30649
+ const currentRenderer = ((_a2 = rendererTag.tag("viz")) == null ? void 0 : _a2.text()) ?? legacyToViz(tagToRenderer(currentTag) ?? "table");
30291
30650
  const setRenderer = (renderer) => {
30292
- view.removeTagProperty([currentRenderer]);
30293
- view.setTagProperty([renderer]);
30651
+ view.setTagProperty(["viz"], renderer, RENDERER_PREFIX);
30294
30652
  setQuery == null ? void 0 : setQuery(rootQuery.build());
30295
30653
  };
30296
- const vizes = QUERY_RENDERERS.map((viz) => ({
30654
+ const items = VIZ_RENDERERS.map((viz) => ({
30297
30655
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
30298
30656
  name: `viz_${viz}`
30299
30657
  }),
@@ -30305,16 +30663,30 @@ function Visualization$1({
30305
30663
  customStyle: styles$q.first,
30306
30664
  icon: `viz_${currentRenderer}`,
30307
30665
  value: currentRenderer,
30308
- items: vizes,
30666
+ items,
30309
30667
  onChange: (viz) => setRenderer(viz)
30310
30668
  }, "first")];
30669
+ const options = VISUALIZATION_OPTIONS[currentRenderer];
30670
+ if (options) {
30671
+ tokens2.push(/* @__PURE__ */ jsxRuntime.jsx(RendererPopover, {
30672
+ viz: currentRenderer,
30673
+ options,
30674
+ view,
30675
+ rootQuery
30676
+ }, "menu"));
30677
+ }
30311
30678
  return /* @__PURE__ */ jsxRuntime.jsx(TokenGroup, {
30679
+ customStyle: styles$q.group,
30312
30680
  children: tokens2
30313
30681
  });
30314
30682
  }
30315
30683
  const styles$q = {
30684
+ group: {
30685
+ width: "mlyh8yej3",
30686
+ gridTemplateColumns: "mly52fmzj",
30687
+ $$css: true
30688
+ },
30316
30689
  first: {
30317
- flexGrow: "mly1iyjqo2",
30318
30690
  justifyContent: "mlylqzeqv",
30319
30691
  $$css: true
30320
30692
  }
@@ -31770,6 +32142,9 @@ function typeFromFilter(filter) {
31770
32142
  if (filter.operator === "null" && filter.not) {
31771
32143
  return "-null";
31772
32144
  }
32145
+ if (filter.operator === "before" && filter.not) {
32146
+ return "not_before";
32147
+ }
31773
32148
  return filter.operator;
31774
32149
  }
31775
32150
  function unitsFromFilter(filter, isDateTime) {
@@ -31823,6 +32198,9 @@ const DateTimeFilterCore = ({
31823
32198
  }, {
31824
32199
  value: "next",
31825
32200
  label: "next complete"
32201
+ }, {
32202
+ value: "not_before",
32203
+ label: "on or after"
31826
32204
  }, {
31827
32205
  value: "after",
31828
32206
  label: "after"
@@ -32184,6 +32562,12 @@ function dateTimeFilterChangeType(filter, type, units) {
32184
32562
  operator: type,
32185
32563
  before: fromMoment
32186
32564
  };
32565
+ case "not_before":
32566
+ return {
32567
+ operator: "before",
32568
+ before: fromMoment,
32569
+ not: true
32570
+ };
32187
32571
  case "in":
32188
32572
  return {
32189
32573
  operator: type,
@@ -33637,7 +34021,7 @@ const parsedToLabels = (parsed, filterString) => {
33637
34021
  const {
33638
34022
  not
33639
34023
  } = temporalClause;
33640
- op = `is${not ? " not" : ""} before`;
34024
+ op = not ? "is on or after" : "is before";
33641
34025
  value = displayTimeFromMoment(temporalClause.before);
33642
34026
  }
33643
34027
  break;
@@ -35682,42 +36066,48 @@ function RenderedResult({
35682
36066
  result,
35683
36067
  source
35684
36068
  }) {
35685
- const [renderer, setRenderer] = React.useState();
35686
36069
  const {
35687
36070
  onDrill,
35688
36071
  setQuery
35689
36072
  } = React.useContext(QueryEditorContext);
35690
- React.useEffect(() => {
35691
- const renderer2 = document.createElement("malloy-render");
35692
- renderer2.malloyResult = result;
35693
- renderer2.onDrill = ({
35694
- stableQuery,
35695
- stableDrillClauses
35696
- }) => {
35697
- if (onDrill) {
35698
- onDrill({
35699
- stableQuery,
35700
- stableDrillClauses
36073
+ const vizContainer = React.useRef(null);
36074
+ const viz = React.useMemo(() => {
36075
+ const renderer = new render.MalloyRenderer();
36076
+ const viz2 = renderer.createViz({
36077
+ onDrill: ({
36078
+ stableQuery,
36079
+ stableDrillClauses
36080
+ }) => {
36081
+ if (onDrill) {
36082
+ onDrill({
36083
+ stableQuery,
36084
+ stableDrillClauses
36085
+ });
36086
+ return;
36087
+ }
36088
+ const rootQuery = new QB.ASTQuery({
36089
+ query: stableQuery,
36090
+ source
35701
36091
  });
35702
- return;
36092
+ setQuery == null ? void 0 : setQuery(rootQuery.build());
36093
+ },
36094
+ tableConfig: {
36095
+ enableDrill: true
35703
36096
  }
35704
- const rootQuery = new QB.ASTQuery({
35705
- query: stableQuery,
35706
- source
35707
- });
35708
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35709
- };
35710
- renderer2.tableConfig = {
35711
- enableDrill: true
35712
- };
35713
- setRenderer(renderer2);
35714
- }, [onDrill, result, source, setQuery]);
35715
- if (renderer) {
35716
- return /* @__PURE__ */ jsxRuntime.jsx(DOMElement, {
35717
- element: renderer,
35718
- style: {
35719
- overflow: "hidden",
35720
- height: "100%"
36097
+ });
36098
+ return viz2;
36099
+ }, [onDrill, source, setQuery]);
36100
+ React.useEffect(() => {
36101
+ if (vizContainer.current && viz) {
36102
+ viz.setResult(result);
36103
+ viz.render(vizContainer.current);
36104
+ }
36105
+ }, [viz, result]);
36106
+ if (viz) {
36107
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
36108
+ ref: vizContainer,
36109
+ ...{
36110
+ className: "mly5yr21d mly1n2onr6 mly1ja2u2z mlyb3r6kr mlyh8yej3"
35721
36111
  }
35722
36112
  });
35723
36113
  } else {