@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.
package/dist/esm/index.js CHANGED
@@ -20,7 +20,7 @@ import * as QB from "@malloydata/malloy-query-builder";
20
20
  import { ASTArrowQueryDefinition, ASTArrowViewDefinition, ASTSegmentViewDefinition, ASTNestViewOperation, ASTRefinementViewDefinition, ASTFilterWithLiteralEquality, ASTOrderByViewOperation, ASTGroupByViewOperation, ASTAggregateViewOperation, ASTLimitViewOperation, ASTTimeTruncationExpression, ASTFilterWithFilterString, ASTWhereViewOperation, ASTHavingViewOperation, ASTDrillViewOperation, ASTQuery } from "@malloydata/malloy-query-builder";
21
21
  import { Tag } from "@malloydata/malloy-tag";
22
22
  import { TemporalFilterExpression, BooleanFilterExpression, NumberFilterExpression, StringFilterExpression } from "@malloydata/malloy-filter";
23
- import "@malloydata/render/webcomponent";
23
+ import { MalloyRenderer } from "@malloydata/render";
24
24
  import * as ReactDOM from "react-dom";
25
25
  import ReactDOM__default, { unstable_batchedUpdates, createPortal } from "react-dom";
26
26
  function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
@@ -3781,6 +3781,7 @@ const SvgRadioChecked = (props2) => /* @__PURE__ */ React.createElement("svg", {
3781
3781
  const SvgRadioUnchecked = (props2) => /* @__PURE__ */ React.createElement("svg", { height: 16, viewBox: "0 0 16 16", width: 16, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React.createElement("circle", { cx: 8, cy: 8, r: 8, fill: "currentColor" }), /* @__PURE__ */ React.createElement("circle", { cx: 8, cy: 8, r: 7, fill: "#FFFFFF" }));
3782
3782
  const SvgWarning = (props2) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React.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" }));
3783
3783
  const SvgCheckCircle = (props2) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React.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" }));
3784
+ const SvgGear = (props2) => /* @__PURE__ */ React.createElement("svg", { fill: "none", height: 15, viewBox: "0 0 15 15", width: 15, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React.createElement("g", { clipRule: "evenodd", fill: "#151515", fillRule: "evenodd" }, /* @__PURE__ */ React.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.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" })));
3784
3785
  const SvgInfo = (props2) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React.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" }));
3785
3786
  const SvgError = (props2) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px", fill: "currentColor", ...props2 }, /* @__PURE__ */ React.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" }));
3786
3787
  const SvgRefresh = (props2) => /* @__PURE__ */ React.createElement("svg", { height: 20, viewBox: "0 0 20 20", width: 20, xmlns: "http://www.w3.org/2000/svg", ...props2 }, /* @__PURE__ */ React.createElement("g", { fill: "none", stroke: "currentColor" }, /* @__PURE__ */ React.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.createElement("path", { d: "m9.9 2 2.89 2.89-3 3.01" })));
@@ -3821,6 +3822,7 @@ const ICON_MAP = {
3821
3822
  radioUnchecked: SvgRadioUnchecked,
3822
3823
  warning: SvgWarning,
3823
3824
  check_circle: SvgCheckCircle,
3825
+ gear: SvgGear,
3824
3826
  info: SvgInfo,
3825
3827
  error: SvgError,
3826
3828
  refresh: SvgRefresh,
@@ -3855,6 +3857,7 @@ const ICON_MAP = {
3855
3857
  one_to_one: SvgTypeIconOneToOne,
3856
3858
  // Visualizations
3857
3859
  viz_bar_chart: SvgVizBarChart,
3860
+ viz_bar: SvgVizBarChart,
3858
3861
  viz_boolean: SvgVizBoolean,
3859
3862
  viz_bytes: SvgVizNumber,
3860
3863
  viz_cartesian_chart: SvgVizLine,
@@ -3864,6 +3867,7 @@ const ICON_MAP = {
3864
3867
  viz_image: SvgVizImage,
3865
3868
  viz_json: SvgVizJson,
3866
3869
  viz_line_chart: SvgVizLine,
3870
+ viz_line: SvgVizLine,
3867
3871
  viz_link: SvgVizLink,
3868
3872
  viz_list: SvgVizList,
3869
3873
  viz_list_detail: SvgVizListDetail,
@@ -26148,7 +26152,9 @@ function LiteralValue({
26148
26152
  });
26149
26153
  }
26150
26154
  }
26151
- const QUERY_RENDERERS = ["table", "bar_chart", "dashboard", "json", "line_chart", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map", "sparkline"];
26155
+ const RENDERER_PREFIX = "# ";
26156
+ const VIZ_RENDERERS = ["table", "bar", "dashboard", "json", "line", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map"];
26157
+ const QUERY_RENDERERS = ["table", "bar_chart", "dashboard", "json", "line_chart", "list", "list_detail", "point_map", "scatter_chart", "segment_map", "shape_map"];
26152
26158
  const ATOMIC_RENDERERS = ["number", "boolean", "currency", "image", "url", "percent", "text", "time"];
26153
26159
  const RENDERERS = [...QUERY_RENDERERS, ...ATOMIC_RENDERERS];
26154
26160
  function tagToRenderer(tag) {
@@ -26163,6 +26169,119 @@ function tagToRenderer(tag) {
26163
26169
  }
26164
26170
  return null;
26165
26171
  }
26172
+ function legacyToViz(name) {
26173
+ switch (name) {
26174
+ case "bar_chart":
26175
+ return "bar";
26176
+ case "line_chart":
26177
+ return "line";
26178
+ default:
26179
+ return name;
26180
+ }
26181
+ }
26182
+ const VISUALIZATION_OPTIONS = {
26183
+ table: null,
26184
+ bar: [{
26185
+ name: "title",
26186
+ label: "Title",
26187
+ type: "string",
26188
+ default: ""
26189
+ }, {
26190
+ name: "sub_title",
26191
+ label: "Subtitle",
26192
+ type: "string",
26193
+ default: ""
26194
+ }, {
26195
+ name: "stack",
26196
+ label: "Stack",
26197
+ type: "boolean",
26198
+ default: false
26199
+ }, {
26200
+ name: "size",
26201
+ label: "Size",
26202
+ type: "select",
26203
+ default: "fill",
26204
+ options: [{
26205
+ label: "Fill",
26206
+ value: "fill"
26207
+ }, {
26208
+ label: "Sparkline",
26209
+ value: "spark"
26210
+ }, {
26211
+ label: "X-Small",
26212
+ value: "xs"
26213
+ }, {
26214
+ label: "Small",
26215
+ value: "sm"
26216
+ }, {
26217
+ label: "Medium",
26218
+ value: "md"
26219
+ }, {
26220
+ label: "Large",
26221
+ value: "lg"
26222
+ }, {
26223
+ label: "X-Large",
26224
+ value: "xl"
26225
+ }, {
26226
+ label: "XX-Large",
26227
+ value: "2xl"
26228
+ }]
26229
+ }],
26230
+ dashboard: null,
26231
+ json: null,
26232
+ line: [{
26233
+ name: "title",
26234
+ label: "Title",
26235
+ type: "string",
26236
+ default: ""
26237
+ }, {
26238
+ name: "sub_title",
26239
+ label: "Subtitle",
26240
+ type: "string",
26241
+ default: ""
26242
+ }, {
26243
+ name: "zero_baseline",
26244
+ label: "Zero Baseline",
26245
+ type: "boolean",
26246
+ default: false
26247
+ }, {
26248
+ name: "size",
26249
+ label: "Size",
26250
+ type: "select",
26251
+ default: "md",
26252
+ options: [{
26253
+ label: "Fill",
26254
+ value: "fill"
26255
+ }, {
26256
+ label: "Sparkline",
26257
+ value: "spark"
26258
+ }, {
26259
+ label: "X-Small",
26260
+ value: "xs"
26261
+ }, {
26262
+ label: "Small",
26263
+ value: "sm"
26264
+ }, {
26265
+ label: "Medium",
26266
+ value: "md"
26267
+ }, {
26268
+ label: "Large",
26269
+ value: "lg"
26270
+ }, {
26271
+ label: "X-Large",
26272
+ value: "xl"
26273
+ }, {
26274
+ label: "XX-Large",
26275
+ value: "2xl"
26276
+ }]
26277
+ }],
26278
+ list: null,
26279
+ list_detail: null,
26280
+ point_map: null,
26281
+ scatter_chart: null,
26282
+ segment_map: null,
26283
+ shape_map: null
26284
+ };
26166
26285
  function atomicTypeToIcon(type) {
26167
26286
  return atomicTypeMap[type];
26168
26287
  }
@@ -30261,21 +30380,260 @@ const styles$r = {
30261
30380
  $$css: true
30262
30381
  }
30263
30382
  };
30383
+ function RendererPopover({
30384
+ rootQuery,
30385
+ viz,
30386
+ options,
30387
+ view,
30388
+ customStyle
30389
+ }) {
30390
+ const [open, setOpen] = useState(false);
30391
+ return /* @__PURE__ */ jsxs(Root2$2, {
30392
+ onOpenChange: (open2) => setOpen(open2),
30393
+ open,
30394
+ children: [/* @__PURE__ */ jsx(Trigger$2, {
30395
+ asChild: true,
30396
+ children: /* @__PURE__ */ jsx(Token, {
30397
+ icon: "gear",
30398
+ customStyle: {
30399
+ ...customStyle,
30400
+ ...dialogStyles$1.trigger
30401
+ }
30402
+ })
30403
+ }), /* @__PURE__ */ jsx(Portal$2, {
30404
+ children: /* @__PURE__ */ jsx(Content2$2, {
30405
+ align: "end",
30406
+ children: /* @__PURE__ */ jsx(RendererEditor, {
30407
+ rootQuery,
30408
+ view,
30409
+ viz,
30410
+ options,
30411
+ setOpen
30412
+ })
30413
+ })
30414
+ })]
30415
+ });
30416
+ }
30417
+ function RendererEditor({
30418
+ rootQuery,
30419
+ view,
30420
+ viz,
30421
+ options,
30422
+ setOpen
30423
+ }) {
30424
+ const {
30425
+ setQuery
30426
+ } = useContext(QueryEditorContext);
30427
+ const [current, setCurrent] = useState();
30428
+ useEffect(() => {
30429
+ const current2 = {};
30430
+ const currentTag = view.getTag(RENDERER_PREFIX);
30431
+ for (const option2 of options) {
30432
+ current2[option2.name] = currentTag.text("viz", option2.name) ?? option2.default.toString();
30433
+ }
30434
+ setCurrent(current2);
30435
+ }, [options, view, viz]);
30436
+ if (!current) {
30437
+ return null;
30438
+ }
30439
+ return /* @__PURE__ */ jsx("div", {
30440
+ ..._stylex.props(dialogStyles$1.content, fontStyles.body),
30441
+ children: /* @__PURE__ */ jsxs("div", {
30442
+ ...{
30443
+ className: "mlyqyf9gi mly78zum5 mlydt5ytf mly167g77z"
30444
+ },
30445
+ children: [/* @__PURE__ */ jsx("div", {
30446
+ ...{
30447
+ className: "mlyrvj5dj mly17bnpya mly167g77z"
30448
+ },
30449
+ children: options.map((option2) => option2.type === "boolean" ? /* @__PURE__ */ jsx(BooleanEditor, {
30450
+ option: option2,
30451
+ current,
30452
+ setCurrent
30453
+ }, option2.name) : option2.type === "string" ? /* @__PURE__ */ jsx(StringEditor$1, {
30454
+ option: option2,
30455
+ current,
30456
+ setCurrent
30457
+ }, option2.name) : (
30458
+ // option.type === 'select
30459
+ /* @__PURE__ */ jsx(SelectEditor, {
30460
+ option: option2,
30461
+ current,
30462
+ setCurrent
30463
+ }, option2.name)
30464
+ ))
30465
+ }), /* @__PURE__ */ jsxs("div", {
30466
+ ...{
30467
+ className: "mly78zum5 mly167g77z"
30468
+ },
30469
+ children: [/* @__PURE__ */ jsx(Button, {
30470
+ label: "Cancel",
30471
+ onClick: () => {
30472
+ setOpen(false);
30473
+ },
30474
+ customStyle: dialogStyles$1.editorCell
30475
+ }), /* @__PURE__ */ jsx(Button, {
30476
+ variant: "primary",
30477
+ label: "Apply",
30478
+ onClick: () => {
30479
+ if (!view.getTag(RENDERER_PREFIX).has("viz", viz)) {
30480
+ view.setTagProperty(["viz"], viz, RENDERER_PREFIX);
30481
+ }
30482
+ for (const option2 of options) {
30483
+ if (current[option2.name] !== option2.default.toString()) {
30484
+ view.setTagProperty(["viz", option2.name], current[option2.name], RENDERER_PREFIX);
30485
+ } else {
30486
+ view.removeTagProperty(["viz", option2.name], RENDERER_PREFIX);
30487
+ }
30488
+ }
30489
+ setQuery == null ? void 0 : setQuery(rootQuery.build());
30490
+ setOpen(false);
30491
+ },
30492
+ customStyle: dialogStyles$1.editorCell
30493
+ })]
30494
+ })]
30495
+ })
30496
+ });
30497
+ }
30498
+ function BooleanEditor({
30499
+ current,
30500
+ option: option2,
30501
+ setCurrent
30502
+ }) {
30503
+ return /* @__PURE__ */ jsxs(Fragment, {
30504
+ children: [/* @__PURE__ */ createElement("div", {
30505
+ ...{
30506
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30507
+ },
30508
+ key: option2.name
30509
+ }, /* @__PURE__ */ jsx("input", {
30510
+ type: "checkbox",
30511
+ checked: current[option2.name] === "true",
30512
+ onChange: ({
30513
+ target: {
30514
+ checked
30515
+ }
30516
+ }) => {
30517
+ setCurrent({
30518
+ ...current,
30519
+ [option2.name]: checked.toString()
30520
+ });
30521
+ }
30522
+ })), /* @__PURE__ */ jsx("label", {
30523
+ title: option2.description,
30524
+ children: option2.label
30525
+ }, `${option2.name}-label`)]
30526
+ });
30527
+ }
30528
+ function StringEditor$1({
30529
+ current,
30530
+ option: option2,
30531
+ setCurrent
30532
+ }) {
30533
+ return /* @__PURE__ */ jsxs(Fragment, {
30534
+ children: [/* @__PURE__ */ createElement("div", {
30535
+ ...{
30536
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30537
+ },
30538
+ key: `${option2.name}-label`
30539
+ }, /* @__PURE__ */ jsxs("label", {
30540
+ children: [option2.label, ":"]
30541
+ })), /* @__PURE__ */ jsx("input", {
30542
+ value: current[option2.name],
30543
+ onChange: ({
30544
+ target: {
30545
+ value
30546
+ }
30547
+ }) => {
30548
+ setCurrent({
30549
+ ...current,
30550
+ [option2.name]: value
30551
+ });
30552
+ }
30553
+ }, option2.name)]
30554
+ });
30555
+ }
30556
+ function SelectEditor({
30557
+ current,
30558
+ option: option2,
30559
+ setCurrent
30560
+ }) {
30561
+ return /* @__PURE__ */ jsxs(Fragment, {
30562
+ children: [/* @__PURE__ */ createElement("div", {
30563
+ ...{
30564
+ className: "mly78zum5 mly1lvf691 mly117nqv4"
30565
+ },
30566
+ key: `${option2.name}-label`
30567
+ }, /* @__PURE__ */ jsxs("label", {
30568
+ children: [option2.label, ":"]
30569
+ })), /* @__PURE__ */ jsx(SelectDropdown, {
30570
+ value: current[option2.name],
30571
+ options: option2.options,
30572
+ onChange: (value) => {
30573
+ setCurrent({
30574
+ ...current,
30575
+ [option2.name]: value
30576
+ });
30577
+ }
30578
+ }, option2.name)]
30579
+ });
30580
+ }
30581
+ const dialogStyles$1 = {
30582
+ trigger: {
30583
+ height: "mly1ktj5wk",
30584
+ $$css: true
30585
+ },
30586
+ content: {
30587
+ display: "mly78zum5",
30588
+ flexDirection: "mlydt5ytf",
30589
+ boxShadow: "mly5n1uv4",
30590
+ backgroundColor: "mly12peec7",
30591
+ borderRadius: "mlyur7f20",
30592
+ borderStartStartRadius: null,
30593
+ borderStartEndRadius: null,
30594
+ borderEndStartRadius: null,
30595
+ borderEndEndRadius: null,
30596
+ borderTopLeftRadius: null,
30597
+ borderTopRightRadius: null,
30598
+ borderBottomLeftRadius: null,
30599
+ borderBottomRightRadius: null,
30600
+ padding: "mlye8ttls",
30601
+ paddingInline: null,
30602
+ paddingStart: null,
30603
+ paddingLeft: null,
30604
+ paddingEnd: null,
30605
+ paddingRight: null,
30606
+ paddingBlock: null,
30607
+ paddingTop: null,
30608
+ paddingBottom: null,
30609
+ minWidth: "mlylm99nl",
30610
+ maxWidth: "mly1jkqq1h",
30611
+ gap: "mly167g77z",
30612
+ rowGap: null,
30613
+ columnGap: null,
30614
+ $$css: true
30615
+ },
30616
+ editorCell: {
30617
+ flexGrow: "mly1iyjqo2",
30618
+ $$css: true
30619
+ }
30620
+ };
30264
30621
  function Visualization$1({
30265
30622
  rootQuery,
30266
30623
  view
30267
30624
  }) {
30625
+ var _a2;
30268
30626
  const {
30269
30627
  setQuery
30270
30628
  } = useContext(QueryEditorContext);
30271
30629
  const currentTag = view.getTag();
30272
- const currentRenderer = tagToRenderer(currentTag) ?? "table";
30630
+ const rendererTag = view.getTag(RENDERER_PREFIX);
30631
+ const currentRenderer = ((_a2 = rendererTag.tag("viz")) == null ? void 0 : _a2.text()) ?? legacyToViz(tagToRenderer(currentTag) ?? "table");
30273
30632
  const setRenderer = (renderer) => {
30274
- view.removeTagProperty([currentRenderer]);
30275
- view.setTagProperty([renderer]);
30633
+ view.setTagProperty(["viz"], renderer, RENDERER_PREFIX);
30276
30634
  setQuery == null ? void 0 : setQuery(rootQuery.build());
30277
30635
  };
30278
- const vizes = QUERY_RENDERERS.map((viz) => ({
30636
+ const items = VIZ_RENDERERS.map((viz) => ({
30279
30637
  icon: /* @__PURE__ */ jsx(Icon, {
30280
30638
  name: `viz_${viz}`
30281
30639
  }),
@@ -30287,16 +30645,30 @@ function Visualization$1({
30287
30645
  customStyle: styles$q.first,
30288
30646
  icon: `viz_${currentRenderer}`,
30289
30647
  value: currentRenderer,
30290
- items: vizes,
30648
+ items,
30291
30649
  onChange: (viz) => setRenderer(viz)
30292
30650
  }, "first")];
30651
+ const options = VISUALIZATION_OPTIONS[currentRenderer];
30652
+ if (options) {
30653
+ tokens2.push(/* @__PURE__ */ jsx(RendererPopover, {
30654
+ viz: currentRenderer,
30655
+ options,
30656
+ view,
30657
+ rootQuery
30658
+ }, "menu"));
30659
+ }
30293
30660
  return /* @__PURE__ */ jsx(TokenGroup, {
30661
+ customStyle: styles$q.group,
30294
30662
  children: tokens2
30295
30663
  });
30296
30664
  }
30297
30665
  const styles$q = {
30666
+ group: {
30667
+ width: "mlyh8yej3",
30668
+ gridTemplateColumns: "mly52fmzj",
30669
+ $$css: true
30670
+ },
30298
30671
  first: {
30299
- flexGrow: "mly1iyjqo2",
30300
30672
  justifyContent: "mlylqzeqv",
30301
30673
  $$css: true
30302
30674
  }
@@ -31752,6 +32124,9 @@ function typeFromFilter(filter) {
31752
32124
  if (filter.operator === "null" && filter.not) {
31753
32125
  return "-null";
31754
32126
  }
32127
+ if (filter.operator === "before" && filter.not) {
32128
+ return "not_before";
32129
+ }
31755
32130
  return filter.operator;
31756
32131
  }
31757
32132
  function unitsFromFilter(filter, isDateTime) {
@@ -31805,6 +32180,9 @@ const DateTimeFilterCore = ({
31805
32180
  }, {
31806
32181
  value: "next",
31807
32182
  label: "next complete"
32183
+ }, {
32184
+ value: "not_before",
32185
+ label: "on or after"
31808
32186
  }, {
31809
32187
  value: "after",
31810
32188
  label: "after"
@@ -32166,6 +32544,12 @@ function dateTimeFilterChangeType(filter, type, units) {
32166
32544
  operator: type,
32167
32545
  before: fromMoment
32168
32546
  };
32547
+ case "not_before":
32548
+ return {
32549
+ operator: "before",
32550
+ before: fromMoment,
32551
+ not: true
32552
+ };
32169
32553
  case "in":
32170
32554
  return {
32171
32555
  operator: type,
@@ -33619,7 +34003,7 @@ const parsedToLabels = (parsed, filterString) => {
33619
34003
  const {
33620
34004
  not
33621
34005
  } = temporalClause;
33622
- op = `is${not ? " not" : ""} before`;
34006
+ op = not ? "is on or after" : "is before";
33623
34007
  value = displayTimeFromMoment(temporalClause.before);
33624
34008
  }
33625
34009
  break;
@@ -35664,42 +36048,48 @@ function RenderedResult({
35664
36048
  result,
35665
36049
  source
35666
36050
  }) {
35667
- const [renderer, setRenderer] = useState();
35668
36051
  const {
35669
36052
  onDrill,
35670
36053
  setQuery
35671
36054
  } = useContext(QueryEditorContext);
35672
- useEffect(() => {
35673
- const renderer2 = document.createElement("malloy-render");
35674
- renderer2.malloyResult = result;
35675
- renderer2.onDrill = ({
35676
- stableQuery,
35677
- stableDrillClauses
35678
- }) => {
35679
- if (onDrill) {
35680
- onDrill({
35681
- stableQuery,
35682
- stableDrillClauses
36055
+ const vizContainer = useRef(null);
36056
+ const viz = useMemo(() => {
36057
+ const renderer = new MalloyRenderer();
36058
+ const viz2 = renderer.createViz({
36059
+ onDrill: ({
36060
+ stableQuery,
36061
+ stableDrillClauses
36062
+ }) => {
36063
+ if (onDrill) {
36064
+ onDrill({
36065
+ stableQuery,
36066
+ stableDrillClauses
36067
+ });
36068
+ return;
36069
+ }
36070
+ const rootQuery = new ASTQuery({
36071
+ query: stableQuery,
36072
+ source
35683
36073
  });
35684
- return;
36074
+ setQuery == null ? void 0 : setQuery(rootQuery.build());
36075
+ },
36076
+ tableConfig: {
36077
+ enableDrill: true
35685
36078
  }
35686
- const rootQuery = new ASTQuery({
35687
- query: stableQuery,
35688
- source
35689
- });
35690
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35691
- };
35692
- renderer2.tableConfig = {
35693
- enableDrill: true
35694
- };
35695
- setRenderer(renderer2);
35696
- }, [onDrill, result, source, setQuery]);
35697
- if (renderer) {
35698
- return /* @__PURE__ */ jsx(DOMElement, {
35699
- element: renderer,
35700
- style: {
35701
- overflow: "hidden",
35702
- height: "100%"
36079
+ });
36080
+ return viz2;
36081
+ }, [onDrill, source, setQuery]);
36082
+ useEffect(() => {
36083
+ if (vizContainer.current && viz) {
36084
+ viz.setResult(result);
36085
+ viz.render(vizContainer.current);
36086
+ }
36087
+ }, [viz, result]);
36088
+ if (viz) {
36089
+ return /* @__PURE__ */ jsx("div", {
36090
+ ref: vizContainer,
36091
+ ...{
36092
+ className: "mly5yr21d mly1n2onr6 mly1ja2u2z mlyb3r6kr mlyh8yej3"
35703
36093
  }
35704
36094
  });
35705
36095
  } else {