@malloydata/malloy-explorer 0.0.294-dev250630221944 → 0.0.299-dev250804170242

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.gitmodules +3 -0
  2. package/@flowtypes/components/MalloyExplorerProvider.flow.js +3 -6
  3. package/README.md +7 -0
  4. package/dist/cjs/index.cjs +553 -356
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/esm/index.js +523 -326
  7. package/dist/esm/index.js.map +1 -1
  8. package/dist/malloy-explorer.css +2 -0
  9. package/dist/types/components/FieldToken.d.ts +5 -1
  10. package/dist/types/components/MalloyExplorerProvider.d.ts +3 -5
  11. package/dist/types/components/QueryPanel/AddMenu/AddAggregate.d.ts +1 -3
  12. package/dist/types/components/QueryPanel/AddMenu/AddEmptyNest.d.ts +1 -3
  13. package/dist/types/components/QueryPanel/AddMenu/AddGroupBy.d.ts +1 -3
  14. package/dist/types/components/QueryPanel/AddMenu/AddLimit.d.ts +1 -3
  15. package/dist/types/components/QueryPanel/AddMenu/AddMenu.d.ts +1 -3
  16. package/dist/types/components/QueryPanel/AddMenu/AddOrderBy.d.ts +1 -3
  17. package/dist/types/components/QueryPanel/AddMenu/AddView.d.ts +1 -3
  18. package/dist/types/components/QueryPanel/AddMenu/AddWhere.d.ts +0 -2
  19. package/dist/types/components/QueryPanel/AddMenu/ValueList.d.ts +2 -1
  20. package/dist/types/components/QueryPanel/Operations.d.ts +2 -3
  21. package/dist/types/components/QueryPanel/Parameters.d.ts +3 -3
  22. package/dist/types/components/QueryPanel/Query.d.ts +3 -4
  23. package/dist/types/components/QueryPanel/Source.d.ts +3 -3
  24. package/dist/types/components/QueryPanel/View.d.ts +2 -3
  25. package/dist/types/components/QueryPanel/ViewDefinition.d.ts +2 -3
  26. package/dist/types/components/QueryPanel/Visualization.d.ts +1 -2
  27. package/dist/types/components/QueryPanel/VizEditor/VizEditor.d.ts +1 -2
  28. package/dist/types/components/QueryPanel/VizEditor/VizEditorDialog.d.ts +1 -2
  29. package/dist/types/components/QueryPanel/VizEditor/VizEditorPopover.d.ts +1 -2
  30. package/dist/types/components/QueryPanel/VizEditor/styles.d.ts +3 -0
  31. package/dist/types/components/QueryPanel/VizEditor/utils.d.ts +3 -0
  32. package/dist/types/components/QueryPanel/operations/AggregateOperations.d.ts +3 -4
  33. package/dist/types/components/QueryPanel/operations/DrillOperations.d.ts +1 -2
  34. package/dist/types/components/QueryPanel/operations/FilterOperations.d.ts +2 -3
  35. package/dist/types/components/QueryPanel/operations/GroupByOperations.d.ts +2 -3
  36. package/dist/types/components/QueryPanel/operations/LimitOperation.d.ts +2 -3
  37. package/dist/types/components/QueryPanel/operations/NestOperation.d.ts +3 -5
  38. package/dist/types/components/QueryPanel/operations/OperationActionTitle.d.ts +0 -2
  39. package/dist/types/components/QueryPanel/operations/OrderByOperations.d.ts +2 -3
  40. package/dist/types/components/QueryPanel/operations/RenameDialog.d.ts +3 -4
  41. package/dist/types/components/QueryPanel/operations/SortableOperations.d.ts +3 -4
  42. package/dist/types/components/ResultPanel/ResultDisplay.d.ts +0 -4
  43. package/dist/types/components/SourcePanel/FieldGroupList.d.ts +3 -1
  44. package/dist/types/components/SourcePanel/FieldTokenWithActions.d.ts +3 -2
  45. package/dist/types/components/SourcePanel/SearchResultList.d.ts +3 -1
  46. package/dist/types/components/SourcePanel/hooks/useOperations.d.ts +0 -4
  47. package/dist/types/components/primitives/DropdownMenu.d.ts +1 -1
  48. package/dist/types/components/utils/axis.d.ts +10 -0
  49. package/dist/types/components/utils/icon.d.ts +3 -3
  50. package/dist/types/components/utils/segment.d.ts +1 -0
  51. package/dist/types/contexts/QueryEditorContext.d.ts +3 -14
  52. package/dist/types/hooks/useQueryBuilder.d.ts +2 -2
  53. package/dist/types/hooks/useQueryUpdate.d.ts +10 -0
  54. package/dist/types/hooks/useTopValues.d.ts +18 -0
  55. package/jest.config.ts +1 -1
  56. package/package.json +8 -6
  57. package/vite.config.mts +5 -0
package/dist/esm/index.js CHANGED
@@ -15,9 +15,8 @@ var __superGet = (cls, obj, key2) => __reflectGet(__getProtoOf(cls), key2, obj);
15
15
  var _a, _b, _captureMap, _compiled, _pattern, _nameMap, _strategy, __EmulatedRegExp_instances, execCore_fn, _c;
16
16
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
17
17
  import * as React from "react";
18
- import React__default, { useLayoutEffect, useEffect, useMemo, useState, useRef, createElement, useContext, useCallback, createContext, memo, useReducer } from "react";
19
- import * as QB from "@malloydata/malloy-query-builder";
20
- import { ASTArrowQueryDefinition, ASTArrowViewDefinition, ASTSegmentViewDefinition, ASTNestViewOperation, ASTRefinementViewDefinition, ASTFilterWithLiteralEquality, ASTAnnotation, ASTOrderByViewOperation, ASTGroupByViewOperation, ASTAggregateViewOperation, ASTLimitViewOperation, ASTTimeTruncationExpression, ASTFilterWithFilterString, ASTWhereViewOperation, ASTHavingViewOperation, ASTDrillViewOperation, ASTQuery } from "@malloydata/malloy-query-builder";
18
+ import React__default, { useLayoutEffect, useEffect, useMemo, createContext, useContext, useCallback, useState, useRef, createElement, memo, useReducer } from "react";
19
+ import { ASTQuery, ASTArrowQueryDefinition, ASTArrowViewDefinition, ASTSegmentViewDefinition, ASTNestViewOperation, ASTRefinementViewDefinition, ASTFilterWithLiteralEquality, ASTAnnotation, ASTOrderByViewOperation, ASTGroupByViewOperation, ASTAggregateViewOperation, ASTLimitViewOperation, ASTCalculateViewOperation, ASTTimeTruncationExpression, ASTFilterWithFilterString, ASTReferenceExpression, ASTWhereViewOperation, ASTHavingViewOperation, ASTDrillViewOperation, ASTReferenceQueryArrowSource } from "@malloydata/malloy-query-builder";
21
20
  import { Tag } from "@malloydata/malloy-tag";
22
21
  import { MalloyRenderer, isCoreVizPluginInstance } from "@malloydata/render";
23
22
  import { TemporalFilterExpression, BooleanFilterExpression, NumberFilterExpression, StringFilterExpression } from "@malloydata/malloy-filter";
@@ -3311,11 +3310,14 @@ var Root3$1 = Tooltip;
3311
3310
  var Trigger$4 = TooltipTrigger;
3312
3311
  var Portal$4 = TooltipPortal;
3313
3312
  var Content2$4 = TooltipContent;
3314
- const QueryEditorContext = /* @__PURE__ */ React.createContext({});
3313
+ const QueryEditorContext = /* @__PURE__ */ React.createContext({
3314
+ setQuery: () => {
3315
+ }
3316
+ });
3315
3317
  function useQueryBuilder(source, query) {
3316
3318
  return useMemo(() => {
3317
3319
  if (source) {
3318
- return new QB.ASTQuery({
3320
+ return new ASTQuery({
3319
3321
  query,
3320
3322
  source
3321
3323
  });
@@ -3399,10 +3401,29 @@ const findNestView = (currentView, remainingPath) => {
3399
3401
  }
3400
3402
  return null;
3401
3403
  };
3404
+ const UpdateQueryContext = /* @__PURE__ */ createContext({
3405
+ updateQuery: () => {
3406
+ console.warn("Missing <MalloyExplorerProvider>");
3407
+ }
3408
+ });
3409
+ function useUpdateQuery() {
3410
+ const {
3411
+ updateQuery
3412
+ } = useContext(UpdateQueryContext);
3413
+ return updateQuery;
3414
+ }
3415
+ const TopValuesContext = /* @__PURE__ */ createContext({});
3416
+ function useTopValues() {
3417
+ const {
3418
+ topValues
3419
+ } = useContext(TopValuesContext);
3420
+ return topValues;
3421
+ }
3402
3422
  function MalloyExplorerProvider({
3403
3423
  source,
3404
3424
  query,
3405
- onQueryChange,
3425
+ onQueryChange = () => {
3426
+ },
3406
3427
  focusedNestViewPath,
3407
3428
  onFocusedNestViewPathChange,
3408
3429
  children,
@@ -3410,20 +3431,32 @@ function MalloyExplorerProvider({
3410
3431
  onDrill
3411
3432
  }) {
3412
3433
  const rootQuery = useQueryBuilder(source, query);
3434
+ const updateQuery = useCallback(() => {
3435
+ onQueryChange == null ? void 0 : onQueryChange(rootQuery == null ? void 0 : rootQuery.build());
3436
+ }, [onQueryChange, rootQuery]);
3413
3437
  return /* @__PURE__ */ jsx(TooltipProvider, {
3414
3438
  children: /* @__PURE__ */ jsx(MalloyQueryFocusProvider, {
3415
3439
  rootQuery,
3416
3440
  focusedNestViewPath,
3417
3441
  onFocusedNestViewPathChange,
3418
- children: /* @__PURE__ */ jsx(QueryEditorContext.Provider, {
3442
+ children: /* @__PURE__ */ jsx(UpdateQueryContext.Provider, {
3419
3443
  value: {
3420
- source,
3421
- rootQuery,
3422
- setQuery: onQueryChange,
3423
- topValues,
3424
- onDrill
3444
+ updateQuery
3425
3445
  },
3426
- children
3446
+ children: /* @__PURE__ */ jsx(TopValuesContext.Provider, {
3447
+ value: {
3448
+ topValues
3449
+ },
3450
+ children: /* @__PURE__ */ jsx(QueryEditorContext.Provider, {
3451
+ value: {
3452
+ source,
3453
+ rootQuery,
3454
+ setQuery: onQueryChange,
3455
+ onDrill
3456
+ },
3457
+ children
3458
+ })
3459
+ })
3427
3460
  })
3428
3461
  })
3429
3462
  });
@@ -7992,16 +8025,14 @@ function SelectorToken({
7992
8025
  onValueChange: handleValueChange,
7993
8026
  required: true,
7994
8027
  children: [/* @__PURE__ */ jsxs(Trigger$3, {
7995
- ..._stylex.props(tokenStyles.main, styles$H.selectTrigger, tokenColorVariants[color], tokenSizeVariants[size2], fontStyles.body, tokenStyles.label, customStyle),
8028
+ ..._stylex.props(tokenStyles.main, styles$H.selectTrigger, tokenColorVariants[color], tokenSizeVariants[size2], customStyle),
7996
8029
  children: [icon && /* @__PURE__ */ jsx(Icon, {
7997
8030
  name: icon,
7998
8031
  customStyle: tokenStyles.icon
7999
8032
  }), /* @__PURE__ */ jsx(Value$1, {
8000
8033
  asChild: true,
8001
8034
  children: /* @__PURE__ */ jsx("div", {
8002
- ...{
8003
- className: "mlyb3r6kr mlylyipyv"
8004
- },
8035
+ ..._stylex.props(fontStyles.body, tokenStyles.label),
8005
8036
  children: label
8006
8037
  })
8007
8038
  })]
@@ -8030,17 +8061,15 @@ function SelectorToken({
8030
8061
  }, 10);
8031
8062
  }
8032
8063
  }
8033
- }), /* @__PURE__ */ jsx(ScrollableArea, {
8034
- children: /* @__PURE__ */ jsx(Group$1, {
8035
- ...{
8036
- className: "mly78zum5 mlydt5ytf mlyuyqlj2 mlyfawy5m mly195vfkc"
8037
- },
8038
- children: filteredItems.map((item) => /* @__PURE__ */ jsx(SelectItem, {
8039
- value: item.value,
8040
- selectedValue: value,
8041
- children: item.label
8042
- }, item.value))
8043
- })
8064
+ }), /* @__PURE__ */ jsx(Group$1, {
8065
+ ...{
8066
+ className: "mly78zum5 mlydt5ytf mlyuyqlj2 mlyfawy5m mly195vfkc mlyysyzu8"
8067
+ },
8068
+ children: filteredItems.map((item) => /* @__PURE__ */ jsx(SelectItem, {
8069
+ value: item.value,
8070
+ selectedValue: value,
8071
+ children: item.label
8072
+ }, item.value))
8044
8073
  })]
8045
8074
  })
8046
8075
  })
@@ -25990,9 +26019,9 @@ function QueryActionBar({
25990
26019
  children: [/* @__PURE__ */ jsx(Button, {
25991
26020
  onClick: () => {
25992
26021
  focusMainView();
25993
- setQuery == null ? void 0 : setQuery(void 0);
26022
+ setQuery(void 0);
25994
26023
  },
25995
- isDisabled: !rootQuery || (rootQuery == null ? void 0 : rootQuery.isEmpty()),
26024
+ isDisabled: !rootQuery || rootQuery.isEmpty(),
25996
26025
  label: "Clear",
25997
26026
  variant: "flat",
25998
26027
  size: "compact"
@@ -26202,6 +26231,7 @@ function fieldToIcon(field) {
26202
26231
  break;
26203
26232
  case "dimension":
26204
26233
  case "measure":
26234
+ case "calculate":
26205
26235
  icon = atomicTypeToIcon(field.type.kind);
26206
26236
  break;
26207
26237
  case "join":
@@ -26213,8 +26243,7 @@ function fieldToIcon(field) {
26213
26243
  function relationshipToIcon(relationship) {
26214
26244
  return relationshipMap[relationship];
26215
26245
  }
26216
- function viewToVisualizationIcon(view) {
26217
- const currentTag = view.getTag();
26246
+ function tagToVisualization(currentTag) {
26218
26247
  const currentRenderer = tagToRenderer(currentTag) ?? "table";
26219
26248
  return `viz_${currentRenderer}`;
26220
26249
  }
@@ -26234,6 +26263,7 @@ const fieldKindMap = {
26234
26263
  view: "purple",
26235
26264
  dimension: "cyan",
26236
26265
  measure: "green",
26266
+ calculate: "green",
26237
26267
  join: void 0
26238
26268
  };
26239
26269
  const relationshipMap = {
@@ -26243,6 +26273,7 @@ const relationshipMap = {
26243
26273
  };
26244
26274
  function FieldToken({
26245
26275
  field,
26276
+ additionalSiblings,
26246
26277
  hoverActions,
26247
26278
  hoverActionsVisible,
26248
26279
  ...props2
@@ -26267,7 +26298,7 @@ function FieldToken({
26267
26298
  color: fieldKindToColor(field.kind),
26268
26299
  icon: fieldToIcon(field),
26269
26300
  ...props2
26270
- }), hoverActions && /* @__PURE__ */ jsx("div", {
26301
+ }), additionalSiblings, hoverActions && /* @__PURE__ */ jsx("div", {
26271
26302
  ...{
26272
26303
  className: "mly1vsucm1 mly2lah0s"
26273
26304
  },
@@ -26289,19 +26320,22 @@ function DrillOperations({
26289
26320
  ...{
26290
26321
  className: "mly78zum5 mlydt5ytf mly1jnr06f"
26291
26322
  },
26292
- children: drills.map((drill, key2) => /* @__PURE__ */ jsxs(TokenGroup, {
26293
- color: "cyan",
26294
- customStyle: localStyles.tokenGroup,
26295
- children: [/* @__PURE__ */ jsx(FieldToken, {
26296
- field: drill.filter.fieldReference.getFieldInfo()
26297
- }), /* @__PURE__ */ jsx(Token, {
26298
- label: "="
26299
- }), drill.filter instanceof ASTFilterWithLiteralEquality ? /* @__PURE__ */ jsx(LiteralValue, {
26300
- value: drill.filter.value.node
26301
- }) : /* @__PURE__ */ jsx(Token, {
26302
- label: drill.filter.filterString
26303
- })]
26304
- }, key2))
26323
+ children: drills.map((drill, key2) => {
26324
+ const field = drill.filter.expression.getFieldInfo();
26325
+ return field ? /* @__PURE__ */ jsxs(TokenGroup, {
26326
+ color: "cyan",
26327
+ customStyle: localStyles.tokenGroup,
26328
+ children: [/* @__PURE__ */ jsx(FieldToken, {
26329
+ field
26330
+ }), /* @__PURE__ */ jsx(Token, {
26331
+ label: "="
26332
+ }), drill.filter instanceof ASTFilterWithLiteralEquality ? /* @__PURE__ */ jsx(LiteralValue, {
26333
+ value: drill.filter.value.node
26334
+ }) : /* @__PURE__ */ jsx(Token, {
26335
+ label: drill.filter.filterString
26336
+ })]
26337
+ }, key2) : null;
26338
+ })
26305
26339
  })]
26306
26340
  });
26307
26341
  }
@@ -30600,6 +30634,12 @@ const styles$s = {
30600
30634
  justifyContent: "mly1rfj78v",
30601
30635
  $$css: true
30602
30636
  },
30637
+ nest: {
30638
+ gridColumn: "mly623te4",
30639
+ gridColumnStart: null,
30640
+ gridColumnEnd: null,
30641
+ $$css: true
30642
+ },
30603
30643
  heading: {
30604
30644
  gridColumn: "mly623te4",
30605
30645
  gridColumnStart: null,
@@ -31112,6 +31152,20 @@ const colorVariants = {
31112
31152
  $$css: true
31113
31153
  }
31114
31154
  };
31155
+ function setAtPath(current, path, value) {
31156
+ const newCurrent = {
31157
+ ...current
31158
+ };
31159
+ let target = newCurrent;
31160
+ for (let i2 = 0; i2 < path.length - 1; i2++) {
31161
+ if (typeof target[path[i2]] !== "object") {
31162
+ target[path[i2]] = {};
31163
+ }
31164
+ target = target[path[i2]];
31165
+ }
31166
+ target[path[path.length - 1]] = value;
31167
+ return newCurrent;
31168
+ }
31115
31169
  function OneOfEditor({
31116
31170
  view,
31117
31171
  name,
@@ -31157,6 +31211,15 @@ function OneOfEditor({
31157
31211
  current,
31158
31212
  option: subOption
31159
31213
  }, key2);
31214
+ case "object":
31215
+ return /* @__PURE__ */ jsx(OneOfObjectEditor, {
31216
+ view,
31217
+ name,
31218
+ path,
31219
+ updateCurrent,
31220
+ current,
31221
+ option: subOption
31222
+ }, key2);
31160
31223
  }
31161
31224
  return null;
31162
31225
  })]
@@ -31266,7 +31329,7 @@ function OneOfNumberEditor({
31266
31329
  valueAsNumber
31267
31330
  }
31268
31331
  }) => {
31269
- setValue(value);
31332
+ setValue(valueAsNumber);
31270
31333
  updateCurrent(path, valueAsNumber);
31271
31334
  },
31272
31335
  ..._stylex.props(styles$s.input)
@@ -31305,6 +31368,48 @@ function OneOfArrayEditor({
31305
31368
  }), /* @__PURE__ */ jsx("div", {})]
31306
31369
  });
31307
31370
  }
31371
+ function OneOfObjectEditor({
31372
+ path,
31373
+ current,
31374
+ option: option2,
31375
+ updateCurrent,
31376
+ view
31377
+ }) {
31378
+ const isObject2 = current != null && typeof current === "object" && !Array.isArray(current);
31379
+ const [objectValue, setObjectValue] = useState(isObject2 ? current : {});
31380
+ return /* @__PURE__ */ jsxs(Fragment, {
31381
+ children: [/* @__PURE__ */ jsx("div", {
31382
+ ..._stylex.props(styles$s.left),
31383
+ children: /* @__PURE__ */ jsx("input", {
31384
+ type: "radio",
31385
+ checked: isObject2,
31386
+ onChange: ({
31387
+ target: {
31388
+ checked
31389
+ }
31390
+ }) => {
31391
+ if (checked) {
31392
+ updateCurrent(path, objectValue);
31393
+ }
31394
+ }
31395
+ })
31396
+ }), /* @__PURE__ */ jsx("div", {
31397
+ ..._stylex.props(styles$s.nest, styles$s.editorGrid),
31398
+ children: /* @__PURE__ */ jsx(ObjectEditor, {
31399
+ current: objectValue,
31400
+ updateCurrent: (path2, value) => {
31401
+ const [_2, ...subPath] = path2;
31402
+ setObjectValue(setAtPath(objectValue, subPath, value));
31403
+ updateCurrent(path2, value);
31404
+ },
31405
+ view,
31406
+ name: "",
31407
+ path,
31408
+ option: option2
31409
+ })
31410
+ })]
31411
+ });
31412
+ }
31308
31413
  function ArrayEditor({
31309
31414
  name,
31310
31415
  path,
@@ -31335,6 +31440,7 @@ function NumberEditor$1({
31335
31440
  option: option2,
31336
31441
  updateCurrent
31337
31442
  }) {
31443
+ const [value, setValue] = React.useState(current ?? option2.minimum);
31338
31444
  return /* @__PURE__ */ jsxs(Fragment, {
31339
31445
  children: [/* @__PURE__ */ jsx("div", {
31340
31446
  ..._stylex.props(styles$s.left, styles$s.label),
@@ -31342,7 +31448,7 @@ function NumberEditor$1({
31342
31448
  children: [option2.title ?? name, ":"]
31343
31449
  })
31344
31450
  }), /* @__PURE__ */ jsx("input", {
31345
- value: current,
31451
+ value,
31346
31452
  type: "number",
31347
31453
  min: option2.minimum,
31348
31454
  max: option2.maximum,
@@ -31351,6 +31457,7 @@ function NumberEditor$1({
31351
31457
  valueAsNumber
31352
31458
  }
31353
31459
  }) => {
31460
+ setValue(valueAsNumber);
31354
31461
  updateCurrent(path, valueAsNumber);
31355
31462
  },
31356
31463
  ..._stylex.props(styles$s.input)
@@ -31549,11 +31656,12 @@ function ObjectEditor({
31549
31656
  option: option2,
31550
31657
  updateCurrent
31551
31658
  }) {
31552
- const [isExpanded, setIsExpanded] = useState(path.length === 0);
31659
+ const [isExpanded, setIsExpanded] = useState(path.length === 0 || !name);
31553
31660
  return /* @__PURE__ */ jsxs(Fragment, {
31554
31661
  children: [name ? /* @__PURE__ */ jsxs(Fragment, {
31555
31662
  children: [/* @__PURE__ */ jsxs("div", {
31556
31663
  ..._stylex.props(styles$s.label, styles$s.heading),
31664
+ onClick: () => setIsExpanded(!isExpanded),
31557
31665
  children: [/* @__PURE__ */ jsx("label", {
31558
31666
  children: option2.title ?? name
31559
31667
  }), option2.description ? /* @__PURE__ */ jsx(InfoHover, {
@@ -31645,31 +31753,20 @@ function ObjectEditor({
31645
31753
  });
31646
31754
  }
31647
31755
  function VizEditor({
31648
- rootQuery,
31649
31756
  view,
31650
31757
  plugin,
31651
31758
  setOpen
31652
31759
  }) {
31653
- const {
31654
- setQuery
31655
- } = useContext(QueryEditorContext);
31760
+ const updateQuery = useUpdateQuery();
31656
31761
  const [current, setCurrent] = useState(plugin.getSettings());
31657
- console.info("RendererEditor current settings:", current);
31658
31762
  const schema = plugin.getSchema();
31659
31763
  const updateCurrent = (path, value) => {
31660
- const newCurrent = {
31661
- ...current
31662
- };
31663
- let target = newCurrent;
31664
- for (let i2 = 0; i2 < path.length - 1; i2++) {
31665
- if (!(path[i2] in target)) {
31666
- target[path[i2]] = {};
31667
- }
31668
- target = target[path[i2]];
31669
- }
31670
- target[path[path.length - 1]] = value;
31764
+ const newCurrent = setAtPath(current, path, value);
31671
31765
  setCurrent(newCurrent);
31672
31766
  };
31767
+ React.useEffect(() => {
31768
+ console.info("RendererEditor current settings:", current);
31769
+ }, [current]);
31673
31770
  return /* @__PURE__ */ jsxs("div", {
31674
31771
  ..._stylex.props(styles$s.editor),
31675
31772
  children: [/* @__PURE__ */ jsx("div", {
@@ -31704,7 +31801,7 @@ function VizEditor({
31704
31801
  view.getOrAddAnnotations().add(new ASTAnnotation({
31705
31802
  value
31706
31803
  }));
31707
- setQuery == null ? void 0 : setQuery(rootQuery.build());
31804
+ updateQuery();
31708
31805
  setOpen(false);
31709
31806
  },
31710
31807
  customStyle: styles$s.editorCell
@@ -31917,7 +32014,6 @@ const dialogStyles = {
31917
32014
  }
31918
32015
  };
31919
32016
  function VizEditorDialog({
31920
- rootQuery,
31921
32017
  plugin,
31922
32018
  view,
31923
32019
  customStyle,
@@ -31947,7 +32043,6 @@ function VizEditorDialog({
31947
32043
  ..._stylex.props(dialogStyles.displayNone),
31948
32044
  children: "Edit visualization parameters"
31949
32045
  }), /* @__PURE__ */ jsx(VizEditor, {
31950
- rootQuery,
31951
32046
  view,
31952
32047
  plugin,
31953
32048
  setOpen
@@ -31966,26 +32061,27 @@ const styles$p = {
31966
32061
  }
31967
32062
  };
31968
32063
  function Visualization$1({
31969
- rootQuery,
31970
32064
  view
31971
32065
  }) {
31972
- const {
31973
- setQuery
31974
- } = useContext(QueryEditorContext);
32066
+ const updateQuery = useUpdateQuery();
31975
32067
  const renderer = useMemo(() => new MalloyRenderer(), []);
31976
32068
  const [currentRenderer, setCurrentRenderer] = useState("table");
31977
32069
  const [plugin, setPlugin] = useState();
32070
+ const [error, setError] = useState("");
31978
32071
  const [open, setOpen] = useState(false);
32072
+ const tag = view.getTag().toString();
31979
32073
  useEffect(() => {
31980
32074
  var _a2;
32075
+ setError("");
31981
32076
  const viz = renderer.createViz({
31982
- onError: (error) => {
31983
- console.error("Malloy render error", error);
32077
+ onError: (error2) => {
32078
+ console.error("Malloy render error", error2);
32079
+ setError(error2.message);
31984
32080
  }
31985
32081
  });
31986
32082
  viz.setResult({
31987
32083
  schema: view.definition.getOutputSchema(),
31988
- annotations: view.getTag().toString().split("\n").map((value) => ({
32084
+ annotations: tag.split("\n").map((value) => ({
31989
32085
  value
31990
32086
  })),
31991
32087
  connection_name: ""
@@ -31993,20 +32089,26 @@ function Visualization$1({
31993
32089
  const metadata = viz.getMetadata();
31994
32090
  if (metadata) {
31995
32091
  const plugin2 = viz.getActivePlugin(metadata.getRootField().key);
31996
- if (plugin2 && isCoreVizPluginInstance(plugin2)) {
31997
- setCurrentRenderer(plugin2.name);
31998
- setPlugin(plugin2);
32092
+ if (plugin2) {
32093
+ if (isCoreVizPluginInstance(plugin2)) {
32094
+ setCurrentRenderer(plugin2.name);
32095
+ setPlugin(plugin2);
32096
+ return;
32097
+ }
32098
+ if (plugin2.name === "error") {
32099
+ setError(plugin2.getMetadata().message);
32100
+ }
31999
32101
  }
32000
- } else {
32001
- const currentTag = view.getTag();
32002
- const rendererTag = view.getTag(RENDERER_PREFIX);
32003
- const currentRenderer2 = ((_a2 = rendererTag.tag("viz")) == null ? void 0 : _a2.text()) ?? legacyToViz(tagToRenderer(currentTag) ?? "table");
32004
- setCurrentRenderer(currentRenderer2);
32005
32102
  }
32006
- }, [renderer, view]);
32103
+ const currentTag = view.getTag();
32104
+ const rendererTag = view.getTag(RENDERER_PREFIX);
32105
+ const currentRenderer2 = ((_a2 = rendererTag.tag("viz")) == null ? void 0 : _a2.text()) ?? legacyToViz(tagToRenderer(currentTag) ?? "table");
32106
+ setCurrentRenderer(currentRenderer2);
32107
+ setPlugin(void 0);
32108
+ }, [renderer, view, tag]);
32007
32109
  const updateViz = (renderer2) => {
32008
32110
  view.setTagProperty(["viz"], renderer2, RENDERER_PREFIX);
32009
- setQuery == null ? void 0 : setQuery(rootQuery.build());
32111
+ updateQuery();
32010
32112
  };
32011
32113
  const items = VIZ_RENDERERS.map((viz) => ({
32012
32114
  icon: /* @__PURE__ */ jsx(Icon, {
@@ -32031,6 +32133,13 @@ function Visualization$1({
32031
32133
  tooltip: "Edit Settings..."
32032
32134
  }, "gear"));
32033
32135
  }
32136
+ if (error) {
32137
+ tokens2.push(/* @__PURE__ */ jsx(Token, {
32138
+ icon: "warning",
32139
+ tooltip: error,
32140
+ customStyle: styles$o.trigger
32141
+ }));
32142
+ }
32034
32143
  return /* @__PURE__ */ jsxs(Fragment, {
32035
32144
  children: [/* @__PURE__ */ jsx(TokenGroup, {
32036
32145
  customStyle: styles$o.group,
@@ -32038,7 +32147,6 @@ function Visualization$1({
32038
32147
  }), /* @__PURE__ */ jsx(VizEditorDialog, {
32039
32148
  open,
32040
32149
  setOpen,
32041
- rootQuery,
32042
32150
  plugin,
32043
32151
  view
32044
32152
  })]
@@ -32181,9 +32289,7 @@ function TopValuesTable({
32181
32289
  field,
32182
32290
  path
32183
32291
  }) {
32184
- const {
32185
- topValues
32186
- } = useContext(QueryEditorContext);
32292
+ const topValues = useTopValues();
32187
32293
  const fieldPath = [...path, field.name].join(".");
32188
32294
  const fieldTopValues = topValues == null ? void 0 : topValues.find((entry) => entry.fieldName === fieldPath);
32189
32295
  if (!fieldTopValues) {
@@ -32556,9 +32662,7 @@ function BooleanFilterCore({
32556
32662
  });
32557
32663
  }
32558
32664
  function useSearch(searchTerm, fieldPath) {
32559
- const {
32560
- topValues
32561
- } = useContext(QueryEditorContext);
32665
+ const topValues = useTopValues();
32562
32666
  if (topValues && searchTerm) {
32563
32667
  let searchValues = topValues;
32564
32668
  if (fieldPath) {
@@ -32600,7 +32704,8 @@ function ValueList({
32600
32704
  fieldPath,
32601
32705
  ref,
32602
32706
  customStyle,
32603
- showPath = true
32707
+ showPath = true,
32708
+ hideNoMatchMessage = false
32604
32709
  }) {
32605
32710
  const {
32606
32711
  searchResults
@@ -32622,7 +32727,7 @@ function ValueList({
32622
32727
  },
32623
32728
  children: value.fieldName
32624
32729
  }) : null]
32625
- }, value.fieldName + ":" + value.fieldValue)) : search ? /* @__PURE__ */ jsx("div", {
32730
+ }, value.fieldName + ":" + value.fieldValue)) : search && !hideNoMatchMessage ? /* @__PURE__ */ jsx("div", {
32626
32731
  ..._stylex.props(addMenuStyles.item),
32627
32732
  "data-disabled": "true",
32628
32733
  children: "No matching values"
@@ -32817,7 +32922,8 @@ const StringFilterCore = ({
32817
32922
  },
32818
32923
  customStyle: styles$i.valueList,
32819
32924
  showPath: false,
32820
- filter: (value) => !currentFilter.values.includes(value)
32925
+ filter: (value) => !currentFilter.values.includes(value),
32926
+ hideNoMatchMessage: true
32821
32927
  })
32822
32928
  })]
32823
32929
  }) : currentFilter.operator === "~" ? /* @__PURE__ */ jsx(StringEditor, {
@@ -33958,6 +34064,42 @@ const styles$g = {
33958
34064
  $$css: true
33959
34065
  }
33960
34066
  };
34067
+ const getPrimaryAxis = (view) => {
34068
+ const schema = view.getOutputSchema();
34069
+ return getPrimaryAxisFromSchema(schema);
34070
+ };
34071
+ const getPrimaryAxisFromSchema = (schema) => {
34072
+ let primaryAxisField = void 0;
34073
+ primaryAxisField = findAxisFieldByAnnotation(schema.fields) || findAxisFieldByType(schema.fields) || findDefaultAxisField(schema.fields);
34074
+ return primaryAxisField;
34075
+ };
34076
+ const findAxisFieldByAnnotation = (fields) => {
34077
+ return fields.find((field) => {
34078
+ if (field.kind === "dimension" && field.annotations && field.annotations.find((annotation) => annotation.value === "# x")) {
34079
+ return true;
34080
+ }
34081
+ return false;
34082
+ });
34083
+ };
34084
+ const findAxisFieldByType = (fields) => {
34085
+ return fields.find((field) => {
34086
+ if (field.kind === "dimension") {
34087
+ const dimension = field;
34088
+ if (dimension.type.kind === "date_type" || dimension.type.kind === "timestamp_type") {
34089
+ return true;
34090
+ }
34091
+ }
34092
+ return false;
34093
+ });
34094
+ };
34095
+ const findDefaultAxisField = (fields) => {
34096
+ return fields.find((field) => {
34097
+ if (field.kind === "dimension") {
34098
+ return true;
34099
+ }
34100
+ return false;
34101
+ });
34102
+ };
33961
34103
  function toFullName(path, name) {
33962
34104
  return [...path || [], name].join(".");
33963
34105
  }
@@ -34036,6 +34178,34 @@ function addGroupBy(view, field, path) {
34036
34178
  segment.addTimestampGroupBy(field.name, path, "second");
34037
34179
  } else {
34038
34180
  segment.addGroupBy(field.name, path, rename);
34181
+ recomputePartitionByAndPrimaryAxis(segment);
34182
+ }
34183
+ }
34184
+ function recomputePartitionByAndPrimaryAxis(segment) {
34185
+ var _a2;
34186
+ const primaryAxis = getPrimaryAxisFromSchema(segment.getOutputSchema());
34187
+ const groupBys = segment.operations.items.filter((op) => op.kind === "group_by");
34188
+ const movingAverages = segment.operations.items.filter((op) => op.kind === "calculate" && op.expression.kind === "moving_average");
34189
+ const canSmooth = primaryAxis !== null && (primaryAxis == null ? void 0 : primaryAxis.kind) === "dimension" && (primaryAxis.type.kind === "timestamp_type" || primaryAxis.type.kind === "date_type");
34190
+ if (!canSmooth) {
34191
+ movingAverages.forEach((operation) => {
34192
+ operation.delete();
34193
+ segment.addAggregate(operation.getFieldInfo().name);
34194
+ });
34195
+ } else {
34196
+ const nonPrimaryGroupByNames = groupBys.filter((gb) => gb.name !== primaryAxis.name);
34197
+ movingAverages.forEach((operation) => {
34198
+ operation.expression.edit();
34199
+ operation.expression.setPartitionFields(nonPrimaryGroupByNames.map((gb) => gb.field.getReference()).filter((ref) => !!ref));
34200
+ });
34201
+ const primaryTimeAxisOperation = groupBys.find((gb) => gb.name === primaryAxis.name);
34202
+ if (primaryTimeAxisOperation) {
34203
+ const expression = (_a2 = primaryTimeAxisOperation.field) == null ? void 0 : _a2.expression;
34204
+ if (expression && expression.kind === "time_truncation") {
34205
+ const truncationExpression = primaryTimeAxisOperation.field.expression;
34206
+ truncationExpression.truncation = "day";
34207
+ }
34208
+ }
34039
34209
  }
34040
34210
  }
34041
34211
  function addAggregate(view, field, path) {
@@ -34147,16 +34317,13 @@ function OperationActionTitle({
34147
34317
  });
34148
34318
  }
34149
34319
  function RenameDialog({
34150
- rootQuery,
34151
34320
  view,
34152
34321
  target,
34153
34322
  open,
34154
34323
  setOpen
34155
34324
  }) {
34156
34325
  const [name, setName] = useState("");
34157
- const {
34158
- setQuery
34159
- } = useContext(QueryEditorContext);
34326
+ const updateQuery = useUpdateQuery();
34160
34327
  useEffect(() => {
34161
34328
  if (target) {
34162
34329
  setName(target.name);
@@ -34166,8 +34333,9 @@ function RenameDialog({
34166
34333
  return null;
34167
34334
  }
34168
34335
  const onRename = () => {
34336
+ target.edit();
34169
34337
  target.name = name;
34170
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
34338
+ updateQuery();
34171
34339
  setOpen(false);
34172
34340
  };
34173
34341
  const {
@@ -34230,15 +34398,12 @@ function RenameDialog({
34230
34398
  });
34231
34399
  }
34232
34400
  function SortableOperations({
34233
- rootQuery,
34234
34401
  segment,
34235
34402
  view,
34236
34403
  operations,
34237
34404
  kind
34238
34405
  }) {
34239
- const {
34240
- setQuery
34241
- } = useContext(QueryEditorContext);
34406
+ const updateQuery = useUpdateQuery();
34242
34407
  const sensors = useSensors(useSensor(PointerSensor));
34243
34408
  const items = useMemo(() => {
34244
34409
  return operations.map((operation) => ({
@@ -34260,7 +34425,7 @@ function SortableOperations({
34260
34425
  const oldIndex = names.indexOf(active.id);
34261
34426
  const newIndex = names.indexOf(over.id);
34262
34427
  segment.reorderFields(arrayMove(names, oldIndex, newIndex));
34263
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34428
+ updateQuery();
34264
34429
  }
34265
34430
  }
34266
34431
  const {
@@ -34272,7 +34437,7 @@ function SortableOperations({
34272
34437
  types: ["dimension"],
34273
34438
  onClick: (field, path) => {
34274
34439
  addGroupBy(view, field, path);
34275
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34440
+ updateQuery();
34276
34441
  }
34277
34442
  } : {
34278
34443
  title: "aggregate",
@@ -34280,12 +34445,11 @@ function SortableOperations({
34280
34445
  types: ["measure"],
34281
34446
  onClick: (field, path) => {
34282
34447
  addAggregate(view, field, path);
34283
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34448
+ updateQuery();
34284
34449
  }
34285
34450
  };
34286
34451
  return /* @__PURE__ */ jsxs("div", {
34287
34452
  children: [/* @__PURE__ */ jsx(OperationActionTitle, {
34288
- rootQuery,
34289
34453
  view,
34290
34454
  fields,
34291
34455
  ...props2
@@ -34298,7 +34462,6 @@ function SortableOperations({
34298
34462
  children: /* @__PURE__ */ jsx(SortableContext, {
34299
34463
  items,
34300
34464
  children: items.map((item) => /* @__PURE__ */ jsx(SortableOperation, {
34301
- rootQuery,
34302
34465
  id: item.id,
34303
34466
  color: kind === "group_by" ? "cyan" : "green",
34304
34467
  view,
@@ -34311,18 +34474,16 @@ function SortableOperations({
34311
34474
  }
34312
34475
  const NULL_PATH = [];
34313
34476
  function SortableOperation({
34314
- rootQuery,
34315
34477
  id,
34316
34478
  view,
34317
34479
  operation,
34318
34480
  color
34319
34481
  }) {
34320
34482
  var _a2;
34321
- const {
34322
- setQuery
34323
- } = useContext(QueryEditorContext);
34483
+ const updateQuery = useUpdateQuery();
34324
34484
  const fieldInfo = operation.getFieldInfo();
34325
- const path = ((_a2 = operation.field.getReference()) == null ? void 0 : _a2.path) ?? NULL_PATH;
34485
+ const field = operation instanceof ASTCalculateViewOperation ? null : operation.field;
34486
+ const path = operation instanceof ASTCalculateViewOperation ? operation.expression.node.field_reference.path ?? NULL_PATH : ((_a2 = operation.field.getReference()) == null ? void 0 : _a2.path) ?? NULL_PATH;
34326
34487
  const {
34327
34488
  attributes,
34328
34489
  listeners,
@@ -34342,6 +34503,18 @@ function SortableOperation({
34342
34503
  transform: CSS$1.Transform.toString(transform2),
34343
34504
  transition
34344
34505
  };
34506
+ const primaryAxis = useMemo(() => {
34507
+ return getPrimaryAxis(view);
34508
+ }, [view]);
34509
+ const canSmooth = operation.kind === "aggregate" && primaryAxis !== null && (primaryAxis == null ? void 0 : primaryAxis.kind) === "dimension" && (primaryAxis.type.kind === "timestamp_type" || primaryAxis.type.kind === "date_type");
34510
+ const enableSmoothing = useCallback((operation2) => {
34511
+ if (!canSmooth) {
34512
+ return;
34513
+ }
34514
+ operation2.convertToCalculateMovingAverage(operation2.name + "_smoothed", 7);
34515
+ recomputePartitionByAndPrimaryAxis(view.getOrAddDefaultSegment());
34516
+ updateQuery();
34517
+ }, [canSmooth, updateQuery, view]);
34345
34518
  const hoverActions = useMemo(() => {
34346
34519
  return /* @__PURE__ */ jsxs(Fragment, {
34347
34520
  children: [/* @__PURE__ */ jsx(DropdownMenu, {
@@ -34352,7 +34525,14 @@ function SortableOperation({
34352
34525
  tooltip: "More Actions"
34353
34526
  }),
34354
34527
  onOpenChange: setHoverActionsVisible,
34355
- children: [/* @__PURE__ */ jsx(DropdownMenuItem, {
34528
+ children: [canSmooth ? /* @__PURE__ */ jsx(DropdownMenuItem, {
34529
+ label: "Add smoothing",
34530
+ onClick: () => {
34531
+ if (operation instanceof ASTAggregateViewOperation) {
34532
+ enableSmoothing(operation);
34533
+ }
34534
+ }
34535
+ }, "smoothing") : null, /* @__PURE__ */ jsx(DropdownMenuItem, {
34356
34536
  label: "Rename",
34357
34537
  onClick: () => {
34358
34538
  setRenameTarget(operation);
@@ -34362,12 +34542,21 @@ function SortableOperation({
34362
34542
  }, [...path, fieldInfo.name].join(".")), /* @__PURE__ */ jsx(ClearButton, {
34363
34543
  onClick: () => {
34364
34544
  operation.delete();
34365
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
34545
+ recomputePartitionByAndPrimaryAxis(view.getOrAddDefaultSegment());
34546
+ updateQuery();
34366
34547
  }
34367
34548
  })]
34368
34549
  });
34369
- }, [fieldInfo, operation, path, rootQuery, setQuery]);
34370
- const granular = granularityMenuItems(fieldInfo, operation.field);
34550
+ }, [canSmooth, enableSmoothing, fieldInfo.name, operation, path, updateQuery, view]);
34551
+ const hasSmoothedField = useMemo(() => {
34552
+ return view.getOrAddDefaultSegment().operations.items.some((operation2) => {
34553
+ return operation2.kind === "calculate";
34554
+ });
34555
+ }, [view]);
34556
+ const granular = granularityMenuItems(fieldInfo, field);
34557
+ if (hasSmoothedField && granular && operation.name === (primaryAxis == null ? void 0 : primaryAxis.name)) {
34558
+ granular.options = granular.options.filter((option2) => option2.value === "day");
34559
+ }
34371
34560
  let icon = "orderBy";
34372
34561
  if (fieldInfo.kind === "dimension" || fieldInfo.kind === "measure") {
34373
34562
  icon = atomicTypeToIcon(fieldInfo.type.kind);
@@ -34376,26 +34565,41 @@ function SortableOperation({
34376
34565
  id,
34377
34566
  ref: setNodeRef,
34378
34567
  style,
34379
- children: [granular ? /* @__PURE__ */ jsxs(TokenGroup, {
34380
- customStyle: customStyles.tokenGroup,
34381
- children: [/* @__PURE__ */ jsx(Token, {
34382
- color,
34383
- icon,
34384
- label: fieldInfo.name,
34385
- dragProps: {
34386
- attributes,
34387
- listeners
34568
+ children: [field && granular ? /* @__PURE__ */ jsxs("div", {
34569
+ ...{
34570
+ 0: {
34571
+ className: "mly78zum5 mly6s0dn4 mly1nhvcw1 mly1jnr06f mly11ogjb6 mly1g9of4s"
34572
+ },
34573
+ 1: {
34574
+ className: "mly78zum5 mly6s0dn4 mly1nhvcw1 mly1jnr06f mly1ae5hkt"
34388
34575
  }
34389
- }), /* @__PURE__ */ jsx(SelectorToken, {
34390
- color,
34391
- value: granular.value,
34392
- onChange: (granulation) => {
34393
- if (operation.field.expression instanceof ASTTimeTruncationExpression) operation.field.expression.truncation = granulation;
34394
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34576
+ }[!!hoverActionsVisible << 0],
34577
+ children: [/* @__PURE__ */ jsxs(TokenGroup, {
34578
+ customStyle: customStyles.tokenGroup,
34579
+ children: [/* @__PURE__ */ jsx(Token, {
34580
+ color,
34581
+ icon,
34582
+ label: fieldInfo.name,
34583
+ dragProps: {
34584
+ attributes,
34585
+ listeners
34586
+ }
34587
+ }), /* @__PURE__ */ jsx(SelectorToken, {
34588
+ color,
34589
+ value: granular.value,
34590
+ onChange: (granulation) => {
34591
+ if (field.expression instanceof ASTTimeTruncationExpression) field.expression.truncation = granulation;
34592
+ updateQuery();
34593
+ },
34594
+ items: granular.options
34595
+ })]
34596
+ }), hoverActions && /* @__PURE__ */ jsx("div", {
34597
+ ...{
34598
+ className: "mly2b4tyj mly2lah0s"
34395
34599
  },
34396
- items: granular.options
34600
+ children: hoverActions
34397
34601
  })]
34398
- }) : /* @__PURE__ */ jsx(FieldToken, {
34602
+ }) : operation instanceof ASTCalculateViewOperation ? /* @__PURE__ */ jsx(FieldToken, {
34399
34603
  field: fieldInfo,
34400
34604
  color,
34401
34605
  hoverActionsVisible,
@@ -34412,9 +34616,67 @@ function SortableOperation({
34412
34616
  dragProps: {
34413
34617
  attributes,
34414
34618
  listeners
34415
- }
34619
+ },
34620
+ additionalSiblings: /* @__PURE__ */ jsx(SelectorToken, {
34621
+ color,
34622
+ value: "" + (operation.expression.node.rows_preceding ?? 7),
34623
+ onChange: (value) => {
34624
+ if (value === "1") {
34625
+ view.getOrAddDefaultSegment().operations.add(new ASTAggregateViewOperation({
34626
+ kind: "aggregate",
34627
+ field: {
34628
+ expression: {
34629
+ kind: "field_reference",
34630
+ name: operation.expression.node.field_reference.name
34631
+ }
34632
+ }
34633
+ }));
34634
+ operation.delete();
34635
+ updateQuery();
34636
+ } else {
34637
+ operation.expression.edit();
34638
+ operation.expression.rowsPreceding = parseInt(value, 10);
34639
+ updateQuery();
34640
+ }
34641
+ },
34642
+ items: [{
34643
+ label: "7d",
34644
+ value: "7"
34645
+ }, {
34646
+ label: "14d",
34647
+ value: "14"
34648
+ }, {
34649
+ label: "28d",
34650
+ value: "28"
34651
+ }, {
34652
+ label: "30d",
34653
+ value: "30"
34654
+ }, {
34655
+ label: "Remove smoothing",
34656
+ value: "1"
34657
+ }]
34658
+ })
34659
+ }) : /* @__PURE__ */ jsx(Fragment, {
34660
+ children: /* @__PURE__ */ jsx(FieldToken, {
34661
+ field: fieldInfo,
34662
+ color,
34663
+ hoverActionsVisible,
34664
+ hoverActions,
34665
+ tooltip: /* @__PURE__ */ jsx(FieldHoverCard, {
34666
+ field: fieldInfo,
34667
+ path
34668
+ }),
34669
+ tooltipProps: {
34670
+ side: "right",
34671
+ align: "start",
34672
+ alignOffset: 28
34673
+ },
34674
+ dragProps: {
34675
+ attributes,
34676
+ listeners
34677
+ }
34678
+ })
34416
34679
  }), /* @__PURE__ */ jsx(RenameDialog, {
34417
- rootQuery,
34418
34680
  view,
34419
34681
  target: renameTarget,
34420
34682
  open: renameOpen,
@@ -34425,7 +34687,7 @@ function SortableOperation({
34425
34687
  const DateGranulation = ["day", "week", "month", "quarter", "year"];
34426
34688
  const TimestampGranulation = ["second", "minute", "hour", "day", "week", "month", "quarter", "year"];
34427
34689
  function granularityMenuItems(fieldInfo, field) {
34428
- if (fieldInfo.kind !== "dimension" || !(field.expression instanceof ASTTimeTruncationExpression)) {
34690
+ if (!field || fieldInfo.kind !== "dimension" || !(field.expression instanceof ASTTimeTruncationExpression)) {
34429
34691
  return null;
34430
34692
  }
34431
34693
  if (fieldInfo.type.kind === "timestamp_type") {
@@ -34455,13 +34717,11 @@ const customStyles = {
34455
34717
  }
34456
34718
  };
34457
34719
  function GroupByOperations({
34458
- rootQuery,
34459
34720
  segment,
34460
34721
  view,
34461
34722
  groupBys
34462
34723
  }) {
34463
34724
  return /* @__PURE__ */ jsx(SortableOperations, {
34464
- rootQuery,
34465
34725
  segment,
34466
34726
  view,
34467
34727
  operations: groupBys,
@@ -34704,12 +34964,9 @@ function displayTimeFromMoment(momentObj) {
34704
34964
  return momentObj.moment;
34705
34965
  }
34706
34966
  function FilterOperations({
34707
- rootQuery,
34708
34967
  filters
34709
34968
  }) {
34710
- const {
34711
- setQuery
34712
- } = useContext(QueryEditorContext);
34969
+ const updateQuery = useUpdateQuery();
34713
34970
  if (filters.length === 0) {
34714
34971
  return null;
34715
34972
  }
@@ -34725,13 +34982,12 @@ function FilterOperations({
34725
34982
  children: ["Invalid filter", /* @__PURE__ */ jsx(ClearButton, {
34726
34983
  onClick: () => {
34727
34984
  filterOperation.delete();
34728
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34985
+ updateQuery();
34729
34986
  }
34730
34987
  })]
34731
34988
  }),
34732
34989
  children: /* @__PURE__ */ jsx(SingleFilterOperation, {
34733
- filterOperation,
34734
- rootQuery
34990
+ filterOperation
34735
34991
  })
34736
34992
  }, key2);
34737
34993
  })
@@ -34739,41 +34995,42 @@ function FilterOperations({
34739
34995
  });
34740
34996
  }
34741
34997
  function SingleFilterOperation({
34742
- rootQuery,
34743
34998
  filterOperation
34744
34999
  }) {
34745
- const {
34746
- setQuery
34747
- } = useContext(QueryEditorContext);
35000
+ const updateQuery = useUpdateQuery();
34748
35001
  const setFilter = useCallback((filter2) => {
34749
35002
  if (filterOperation.filter instanceof ASTFilterWithFilterString) {
34750
35003
  filterOperation.filter.setFilter(filter2);
34751
35004
  }
34752
- setQuery == null ? void 0 : setQuery(rootQuery.build());
34753
- }, [filterOperation.filter, rootQuery, setQuery]);
34754
- if (!(filterOperation.filter instanceof ASTFilterWithFilterString)) {
35005
+ updateQuery();
35006
+ }, [filterOperation.filter, updateQuery]);
35007
+ const {
35008
+ filter
35009
+ } = filterOperation;
35010
+ if (!(filter instanceof ASTFilterWithFilterString)) {
34755
35011
  return null;
34756
35012
  }
34757
35013
  const {
34758
- fieldReference,
35014
+ expression,
34759
35015
  filterString
34760
- } = filterOperation.filter;
34761
- const filter = filterOperation.filter.getFilter();
34762
- const fieldInfo = fieldReference.getFieldInfo();
34763
- if (fieldInfo.kind !== "dimension" && fieldInfo.kind !== "measure") {
34764
- throw new Error(`Invalid filter field kind: ${fieldInfo.kind}`);
35016
+ } = filter;
35017
+ if (!(expression instanceof ASTReferenceExpression)) {
35018
+ return null;
34765
35019
  }
35020
+ const fieldInfo = filter.getFieldInfo();
35021
+ const parsedFilter = filter.getFilter();
35022
+ const path = expression.path ?? [];
34766
35023
  const {
34767
35024
  op,
34768
35025
  value
34769
- } = parsedToLabels(filter, filterString);
35026
+ } = parsedToLabels(parsedFilter, filterString);
34770
35027
  const label = `${fieldInfo.name} ${op} ${value}`;
34771
35028
  return /* @__PURE__ */ jsxs("div", {
34772
35029
  ..._stylex.props(hoverStyles.main),
34773
35030
  children: [/* @__PURE__ */ jsx(FilterPopover, {
34774
35031
  fieldInfo,
34775
- path: fieldReference.path ?? [],
34776
- filter,
35032
+ path,
35033
+ filter: parsedFilter,
34777
35034
  setFilter,
34778
35035
  trigger: /* @__PURE__ */ jsx(Token, {
34779
35036
  icon: "filter",
@@ -34790,19 +35047,16 @@ function SingleFilterOperation({
34790
35047
  children: /* @__PURE__ */ jsx(ClearButton, {
34791
35048
  onClick: () => {
34792
35049
  filterOperation.delete();
34793
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35050
+ updateQuery();
34794
35051
  }
34795
35052
  })
34796
35053
  })]
34797
35054
  });
34798
35055
  }
34799
35056
  function LimitOperation({
34800
- rootQuery,
34801
35057
  limit
34802
35058
  }) {
34803
- const {
34804
- setQuery
34805
- } = useContext(QueryEditorContext);
35059
+ const updateQuery = useUpdateQuery();
34806
35060
  if (!limit) {
34807
35061
  return null;
34808
35062
  }
@@ -34817,7 +35071,7 @@ function LimitOperation({
34817
35071
  value: limit.limit,
34818
35072
  onChange: (value) => {
34819
35073
  limit.limit = value;
34820
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35074
+ updateQuery();
34821
35075
  },
34822
35076
  errorMessage: limit.limit < 0 ? "Limit must be positive" : void 0
34823
35077
  }), /* @__PURE__ */ jsx("div", {
@@ -34825,7 +35079,7 @@ function LimitOperation({
34825
35079
  children: /* @__PURE__ */ jsx(ClearButton, {
34826
35080
  onClick: () => {
34827
35081
  limit.delete();
34828
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35082
+ updateQuery();
34829
35083
  }
34830
35084
  })
34831
35085
  })]
@@ -34833,13 +35087,11 @@ function LimitOperation({
34833
35087
  });
34834
35088
  }
34835
35089
  function AggregateOperations({
34836
- rootQuery,
34837
35090
  segment,
34838
35091
  view,
34839
35092
  aggregates
34840
35093
  }) {
34841
35094
  return /* @__PURE__ */ jsx(SortableOperations, {
34842
- rootQuery,
34843
35095
  segment,
34844
35096
  view,
34845
35097
  operations: aggregates,
@@ -34847,12 +35099,9 @@ function AggregateOperations({
34847
35099
  });
34848
35100
  }
34849
35101
  function OrderByOperations({
34850
- rootQuery,
34851
35102
  orderBys
34852
35103
  }) {
34853
- const {
34854
- setQuery
34855
- } = useContext(QueryEditorContext);
35104
+ const updateQuery = useUpdateQuery();
34856
35105
  if (orderBys.length === 0) {
34857
35106
  return null;
34858
35107
  }
@@ -34892,7 +35141,7 @@ function OrderByOperations({
34892
35141
  value: orderBy.direction ?? "asc",
34893
35142
  onChange: (direction) => {
34894
35143
  orderBy.direction = direction;
34895
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35144
+ updateQuery();
34896
35145
  }
34897
35146
  })]
34898
35147
  }), /* @__PURE__ */ jsx("div", {
@@ -34900,7 +35149,7 @@ function OrderByOperations({
34900
35149
  children: /* @__PURE__ */ jsx(ClearButton, {
34901
35150
  onClick: () => {
34902
35151
  orderBy.delete();
34903
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35152
+ updateQuery();
34904
35153
  }
34905
35154
  })
34906
35155
  })]
@@ -34910,7 +35159,6 @@ function OrderByOperations({
34910
35159
  });
34911
35160
  }
34912
35161
  function View({
34913
- rootQuery,
34914
35162
  view
34915
35163
  }) {
34916
35164
  return /* @__PURE__ */ jsxs("div", {
@@ -34920,10 +35168,8 @@ function View({
34920
35168
  gap: 8
34921
35169
  },
34922
35170
  children: [/* @__PURE__ */ jsx(Visualization$1, {
34923
- rootQuery,
34924
35171
  view
34925
35172
  }), /* @__PURE__ */ jsx(ViewDefinition, {
34926
- rootQuery,
34927
35173
  view,
34928
35174
  viewDef: view.definition
34929
35175
  })]
@@ -34988,12 +35234,9 @@ const styles$f = {
34988
35234
  }
34989
35235
  };
34990
35236
  function AddLimit({
34991
- rootQuery,
34992
35237
  view
34993
35238
  }) {
34994
- const {
34995
- setQuery
34996
- } = useContext(QueryEditorContext);
35239
+ const updateQuery = useUpdateQuery();
34997
35240
  const segment = getSegmentIfPresent(view);
34998
35241
  const hasLimit = segment ? segmentHasLimit(segment) : false;
34999
35242
  return /* @__PURE__ */ jsx(AddItem, {
@@ -35005,17 +35248,14 @@ function AddLimit({
35005
35248
  onClick: () => {
35006
35249
  const segment2 = view.getOrAddDefaultSegment();
35007
35250
  segment2.setLimit(10);
35008
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35251
+ updateQuery();
35009
35252
  }
35010
35253
  });
35011
35254
  }
35012
35255
  function AddEmptyNest({
35013
- rootQuery,
35014
35256
  view
35015
35257
  }) {
35016
- const {
35017
- setQuery
35018
- } = useContext(QueryEditorContext);
35258
+ const updateQuery = useUpdateQuery();
35019
35259
  return /* @__PURE__ */ jsx(AddItem, {
35020
35260
  icon: /* @__PURE__ */ jsx(Icon, {
35021
35261
  name: "nest"
@@ -35025,7 +35265,7 @@ function AddEmptyNest({
35025
35265
  const segment = view.getOrAddDefaultSegment();
35026
35266
  const nestNo = segmentNestNo(segment, `Nest`);
35027
35267
  segment.addEmptyNest(nestNo > 1 ? `Nest ${nestNo}` : `Nest`);
35028
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35268
+ updateQuery();
35029
35269
  }
35030
35270
  });
35031
35271
  }
@@ -35057,13 +35297,10 @@ const styles$e = {
35057
35297
  }
35058
35298
  };
35059
35299
  function AddOrderBy({
35060
- rootQuery,
35061
35300
  view,
35062
35301
  search
35063
35302
  }) {
35064
- const {
35065
- setQuery
35066
- } = useContext(QueryEditorContext);
35303
+ const updateQuery = useUpdateQuery();
35067
35304
  const outputSchemaFields = view.getOutputSchema().fields;
35068
35305
  const segment = getSegmentIfPresent(view);
35069
35306
  const fields = useMemo(() => outputSchemaFields.filter((field) => field.kind === "dimension").filter((field) => ORDERABLE_TYPES$1.includes(field.type.kind)).filter((field) => segment ? !segmentHasOrderBy(segment, field.name) : true), [outputSchemaFields, segment]);
@@ -35075,7 +35312,7 @@ function AddOrderBy({
35075
35312
  types: ["dimension"],
35076
35313
  onAddOperation: (field) => {
35077
35314
  addOrderBy(view, field);
35078
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35315
+ updateQuery();
35079
35316
  },
35080
35317
  disabledMessage: "There must be at least one field in the output to order by.",
35081
35318
  search
@@ -35083,13 +35320,10 @@ function AddOrderBy({
35083
35320
  }
35084
35321
  const ORDERABLE_TYPES$1 = ["string_type", "number_type", "boolean_type", "date_type", "timestamp_type"];
35085
35322
  function AddGroupBy({
35086
- rootQuery,
35087
35323
  view,
35088
35324
  search
35089
35325
  }) {
35090
- const {
35091
- setQuery
35092
- } = useContext(QueryEditorContext);
35326
+ const updateQuery = useUpdateQuery();
35093
35327
  const {
35094
35328
  fields
35095
35329
  } = getInputSchemaFromViewParent(view);
@@ -35106,19 +35340,16 @@ function AddGroupBy({
35106
35340
  filter,
35107
35341
  onAddOperation: (field, path) => {
35108
35342
  addGroupBy(view, field, path);
35109
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35343
+ updateQuery();
35110
35344
  },
35111
35345
  search
35112
35346
  });
35113
35347
  }
35114
35348
  function AddAggregate({
35115
- rootQuery,
35116
35349
  view,
35117
35350
  search
35118
35351
  }) {
35119
- const {
35120
- setQuery
35121
- } = useContext(QueryEditorContext);
35352
+ const updateQuery = useUpdateQuery();
35122
35353
  const {
35123
35354
  fields
35124
35355
  } = getInputSchemaFromViewParent(view);
@@ -35135,7 +35366,7 @@ function AddAggregate({
35135
35366
  filter,
35136
35367
  onAddOperation: (field, path) => {
35137
35368
  addAggregate(view, field, path);
35138
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35369
+ updateQuery();
35139
35370
  },
35140
35371
  search
35141
35372
  });
@@ -35144,10 +35375,7 @@ function AddWhere({
35144
35375
  view,
35145
35376
  search
35146
35377
  }) {
35147
- const {
35148
- rootQuery,
35149
- setQuery
35150
- } = React.useContext(QueryEditorContext);
35378
+ const updateQuery = useUpdateQuery();
35151
35379
  const {
35152
35380
  fields
35153
35381
  } = getInputSchemaFromViewParent(view);
@@ -35161,7 +35389,7 @@ function AddWhere({
35161
35389
  onAddOperation: (field, path, filter) => {
35162
35390
  if (filter && (field.kind === "dimension" || field.kind === "measure")) {
35163
35391
  addFilter(view, field, path, filter);
35164
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
35392
+ updateQuery();
35165
35393
  }
35166
35394
  },
35167
35395
  isFilterOperation: true,
@@ -35170,15 +35398,18 @@ function AddWhere({
35170
35398
  }
35171
35399
  const FILTERABLE_TYPES$1 = /* @__PURE__ */ new Set(["string_type", "boolean_type", "number_type", "date_type", "timestamp_type"]);
35172
35400
  function AddView({
35173
- rootQuery,
35174
35401
  view,
35175
35402
  search
35176
35403
  }) {
35177
35404
  const {
35178
- setQuery
35405
+ rootQuery
35179
35406
  } = useContext(QueryEditorContext);
35407
+ const updateQuery = useUpdateQuery();
35180
35408
  const allFields = getInputSchemaFromViewParent(view).fields;
35181
35409
  const fields = useMemo(() => allFields.filter((field) => field.kind === "view" && !isIndexView(field)), [allFields]);
35410
+ if (!rootQuery) {
35411
+ return null;
35412
+ }
35182
35413
  return /* @__PURE__ */ jsx(AddFieldItem, {
35183
35414
  label: "Add view",
35184
35415
  icon: "view",
@@ -35192,20 +35423,17 @@ function AddView({
35192
35423
  } else {
35193
35424
  addNest(view, field);
35194
35425
  }
35195
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35426
+ updateQuery();
35196
35427
  },
35197
35428
  search
35198
35429
  });
35199
35430
  }
35200
35431
  function AddMenu({
35201
- rootQuery,
35202
35432
  view
35203
35433
  }) {
35204
35434
  const [open, setOpen] = useState(false);
35205
35435
  const [active, setActive] = useState("");
35206
- const {
35207
- setQuery
35208
- } = useContext(QueryEditorContext);
35436
+ const updateQuery = useUpdateQuery();
35209
35437
  const [search, setSearch] = useState("");
35210
35438
  const segment = getSegmentIfPresent(view);
35211
35439
  const toggleActive = (toggle) => {
@@ -35269,7 +35497,7 @@ function AddMenu({
35269
35497
  } else {
35270
35498
  addNest(view, field);
35271
35499
  }
35272
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35500
+ updateQuery();
35273
35501
  },
35274
35502
  search
35275
35503
  }), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx(ValueList, {
@@ -35285,7 +35513,7 @@ function AddMenu({
35285
35513
  values: [value.fieldValue ?? "∅"]
35286
35514
  }
35287
35515
  });
35288
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35516
+ updateQuery();
35289
35517
  }
35290
35518
  })]
35291
35519
  }) : /* @__PURE__ */ jsxs("div", {
@@ -35322,7 +35550,6 @@ function AddMenu({
35322
35550
  onClick: () => toggleActive("view"),
35323
35551
  open: active === "view"
35324
35552
  }), /* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsx(AddLimit, {
35325
- rootQuery,
35326
35553
  view
35327
35554
  }), /* @__PURE__ */ jsx(AddItem, {
35328
35555
  icon: /* @__PURE__ */ jsx(Icon, {
@@ -35332,7 +35559,6 @@ function AddMenu({
35332
35559
  onClick: () => toggleActive("order_by"),
35333
35560
  open: active === "order_by"
35334
35561
  }), /* @__PURE__ */ jsx(AddEmptyNest, {
35335
- rootQuery,
35336
35562
  view
35337
35563
  })]
35338
35564
  }), /* @__PURE__ */ jsxs("div", {
@@ -35341,23 +35567,18 @@ function AddMenu({
35341
35567
  overflowY: "auto"
35342
35568
  },
35343
35569
  children: [active === "group_by" && /* @__PURE__ */ jsx(AddGroupBy, {
35344
- rootQuery,
35345
35570
  view,
35346
35571
  search
35347
35572
  }), active === "aggregate" && /* @__PURE__ */ jsx(AddAggregate, {
35348
- rootQuery,
35349
35573
  view,
35350
35574
  search
35351
35575
  }), active === "where" && /* @__PURE__ */ jsx(AddWhere, {
35352
- rootQuery,
35353
35576
  view,
35354
35577
  search
35355
35578
  }), active === "view" && /* @__PURE__ */ jsx(AddView, {
35356
- rootQuery,
35357
35579
  view,
35358
35580
  search
35359
35581
  }), active === "order_by" && /* @__PURE__ */ jsx(AddOrderBy, {
35360
- rootQuery,
35361
35582
  view,
35362
35583
  search
35363
35584
  })]
@@ -35403,7 +35624,6 @@ function FocusableView({
35403
35624
  });
35404
35625
  }
35405
35626
  function NestOperations({
35406
- rootQuery,
35407
35627
  view,
35408
35628
  nests
35409
35629
  }) {
@@ -35413,20 +35633,16 @@ function NestOperations({
35413
35633
  return /* @__PURE__ */ jsx("div", {
35414
35634
  ..._stylex.props(styles$u.tokenContainer),
35415
35635
  children: nests.map((nest) => /* @__PURE__ */ jsx(NestOperation, {
35416
- rootQuery,
35417
35636
  view,
35418
35637
  nest
35419
35638
  }, nest.name))
35420
35639
  });
35421
35640
  }
35422
35641
  function NestOperation({
35423
- rootQuery,
35424
35642
  view,
35425
35643
  nest
35426
35644
  }) {
35427
- const {
35428
- setQuery
35429
- } = useContext(QueryEditorContext);
35645
+ const updateQuery = useUpdateQuery();
35430
35646
  const [renameOpen, setRenameOpen] = useState(false);
35431
35647
  const parentNestViewPath = useContext(NestViewPathContext);
35432
35648
  const {
@@ -35447,7 +35663,7 @@ function NestOperation({
35447
35663
  onClick: () => {
35448
35664
  focusNestView([...parentNestViewPath]);
35449
35665
  nest2.delete();
35450
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35666
+ updateQuery();
35451
35667
  }
35452
35668
  }), /* @__PURE__ */ jsx(DropdownMenuItem, {
35453
35669
  label: "Rename",
@@ -35456,7 +35672,6 @@ function NestOperation({
35456
35672
  }
35457
35673
  })]
35458
35674
  }), /* @__PURE__ */ jsx(AddMenu, {
35459
- rootQuery,
35460
35675
  view: nest2.view
35461
35676
  })]
35462
35677
  });
@@ -35468,17 +35683,15 @@ function NestOperation({
35468
35683
  },
35469
35684
  children: [/* @__PURE__ */ jsx(CollapsiblePanel, {
35470
35685
  title: nest.name,
35471
- icon: viewToVisualizationIcon(nest.view),
35686
+ icon: tagToVisualization(nest.view.getTag()),
35472
35687
  defaultOpen: true,
35473
35688
  controls: getControls(nest),
35474
35689
  collapsedControls: getControls(nest),
35475
35690
  isFocused: isNestViewFocused([...parentNestViewPath, nest.name]),
35476
35691
  children: /* @__PURE__ */ jsx(View, {
35477
- rootQuery,
35478
35692
  view: nest.view
35479
35693
  })
35480
35694
  }), /* @__PURE__ */ jsx(RenameDialog, {
35481
- rootQuery,
35482
35695
  view,
35483
35696
  target: nest,
35484
35697
  open: renameOpen,
@@ -35488,7 +35701,6 @@ function NestOperation({
35488
35701
  });
35489
35702
  }
35490
35703
  function Operations({
35491
- rootQuery,
35492
35704
  view,
35493
35705
  viewDef
35494
35706
  }) {
@@ -35506,7 +35718,7 @@ function Operations({
35506
35718
  segment.operations.items.forEach((operation) => {
35507
35719
  if (operation instanceof ASTGroupByViewOperation) {
35508
35720
  groupBys.push(operation);
35509
- } else if (operation instanceof ASTAggregateViewOperation) {
35721
+ } else if (operation instanceof ASTAggregateViewOperation || operation instanceof ASTCalculateViewOperation) {
35510
35722
  aggregates.push(operation);
35511
35723
  } else if (operation instanceof ASTWhereViewOperation) {
35512
35724
  filters.push(operation);
@@ -35527,66 +35739,53 @@ function Operations({
35527
35739
  className: "mly1tpqehw mly10lvyaf"
35528
35740
  },
35529
35741
  children: [/* @__PURE__ */ jsx(GroupByOperations, {
35530
- rootQuery,
35531
35742
  segment,
35532
35743
  view,
35533
35744
  groupBys
35534
35745
  }), /* @__PURE__ */ jsx(AggregateOperations, {
35535
- rootQuery,
35536
35746
  segment,
35537
35747
  view,
35538
35748
  aggregates
35539
35749
  }), /* @__PURE__ */ jsx(DrillOperations, {
35540
- rootQuery,
35541
35750
  drills
35542
35751
  }), /* @__PURE__ */ jsx(FilterOperations, {
35543
- rootQuery,
35544
35752
  filters
35545
35753
  }), /* @__PURE__ */ jsx(OrderByOperations, {
35546
- rootQuery,
35547
35754
  orderBys
35548
35755
  }), /* @__PURE__ */ jsx(NestOperations, {
35549
- rootQuery,
35550
35756
  view,
35551
35757
  nests
35552
35758
  }), /* @__PURE__ */ jsx(LimitOperation, {
35553
- rootQuery,
35554
35759
  limit
35555
35760
  })]
35556
35761
  });
35557
35762
  }
35558
35763
  function ViewDefinition({
35559
- rootQuery,
35560
35764
  view,
35561
35765
  viewDef
35562
35766
  }) {
35563
35767
  if (viewDef instanceof ASTArrowViewDefinition) {
35564
35768
  return /* @__PURE__ */ jsx(ViewDefinition, {
35565
- rootQuery,
35566
35769
  view,
35567
35770
  viewDef: viewDef.view
35568
35771
  });
35569
35772
  } else if (viewDef instanceof ASTRefinementViewDefinition) {
35570
35773
  return /* @__PURE__ */ jsxs("div", {
35571
35774
  children: [/* @__PURE__ */ jsx(ViewDefinition, {
35572
- rootQuery,
35573
35775
  view,
35574
35776
  viewDef: viewDef.base
35575
35777
  }), /* @__PURE__ */ jsx(ViewDefinition, {
35576
- rootQuery,
35577
35778
  view,
35578
35779
  viewDef: viewDef.refinement
35579
35780
  })]
35580
35781
  });
35581
35782
  } else if (viewDef instanceof ASTSegmentViewDefinition) {
35582
35783
  return /* @__PURE__ */ jsx(Operations, {
35583
- rootQuery,
35584
35784
  view,
35585
35785
  viewDef
35586
35786
  });
35587
35787
  } else {
35588
35788
  return /* @__PURE__ */ jsx(CollapsingView, {
35589
- rootQuery,
35590
35789
  viewDef
35591
35790
  });
35592
35791
  }
@@ -35655,14 +35854,21 @@ const styles$c = {
35655
35854
  }
35656
35855
  };
35657
35856
  function Query({
35658
- rootQuery,
35659
- query,
35660
- setQuery
35857
+ definition
35661
35858
  }) {
35662
35859
  const {
35663
35860
  focusMainView,
35664
35861
  isMainViewFocused
35665
35862
  } = useQueryFocus();
35863
+ const {
35864
+ rootQuery,
35865
+ setQuery
35866
+ } = useContext(QueryEditorContext);
35867
+ const updateQuery = useUpdateQuery();
35868
+ if (!rootQuery) {
35869
+ return null;
35870
+ }
35871
+ const isEmpty = rootQuery.isEmpty();
35666
35872
  return /* @__PURE__ */ jsx(FocusableView, {
35667
35873
  children: /* @__PURE__ */ jsxs(CollapsiblePanel, {
35668
35874
  title: "Main query",
@@ -35681,44 +35887,41 @@ function Query({
35681
35887
  label: "Clear query",
35682
35888
  onClick: () => {
35683
35889
  focusMainView();
35684
- setQuery == null ? void 0 : setQuery(void 0);
35890
+ setQuery(void 0);
35685
35891
  },
35686
- disabled: rootQuery.isEmpty()
35892
+ disabled: isEmpty
35687
35893
  }), /* @__PURE__ */ jsx(DropdownMenuItem, {
35688
35894
  icon: "nest",
35689
35895
  label: "Nest query",
35690
35896
  onClick: () => {
35691
- if (rootQuery.definition instanceof ASTArrowQueryDefinition) {
35692
- rootQuery.definition.view.convertToNest("Nest");
35897
+ if (definition instanceof ASTArrowQueryDefinition) {
35898
+ definition.view.convertToNest("Nest");
35693
35899
  }
35694
- setQuery == null ? void 0 : setQuery(rootQuery.build());
35900
+ updateQuery();
35695
35901
  },
35696
- disabled: rootQuery.isEmpty() || !(rootQuery.definition instanceof ASTArrowQueryDefinition)
35902
+ disabled: isEmpty || !(definition instanceof ASTArrowQueryDefinition)
35697
35903
  })]
35698
35904
  }) : /* @__PURE__ */ jsx(Fragment, {})
35699
- }), query.definition instanceof ASTArrowQueryDefinition ? /* @__PURE__ */ jsx(AddMenu, {
35700
- rootQuery,
35701
- view: query.definition
35905
+ }), definition instanceof ASTArrowQueryDefinition ? /* @__PURE__ */ jsx(AddMenu, {
35906
+ view: definition
35702
35907
  }) : null]
35703
35908
  }),
35704
35909
  collapsedControls: /* @__PURE__ */ jsx(Icon, {
35705
- name: viewToVisualizationIcon(query)
35910
+ name: tagToVisualization(rootQuery.getTag())
35706
35911
  }),
35707
- children: [query.definition instanceof ASTArrowQueryDefinition ? /* @__PURE__ */ jsxs("div", {
35912
+ children: [definition instanceof ASTArrowQueryDefinition ? /* @__PURE__ */ jsxs("div", {
35708
35913
  style: {
35709
35914
  display: "flex",
35710
35915
  flexDirection: "column",
35711
35916
  gap: 8
35712
35917
  },
35713
- children: [!query.isEmpty() && /* @__PURE__ */ jsx(Visualization$1, {
35714
- rootQuery,
35715
- view: query
35918
+ children: [!isEmpty && /* @__PURE__ */ jsx(Visualization$1, {
35919
+ view: rootQuery
35716
35920
  }), /* @__PURE__ */ jsx(ViewDefinition, {
35717
- rootQuery,
35718
- view: query.definition,
35719
- viewDef: query.definition.view
35921
+ view: definition,
35922
+ viewDef: definition.view
35720
35923
  })]
35721
- }) : null, query.isEmpty() ? /* @__PURE__ */ jsx("div", {
35924
+ }) : null, isEmpty ? /* @__PURE__ */ jsx("div", {
35722
35925
  ...{
35723
35926
  className: "mly78zum5 mlyl56j7k mly6s0dn4 mlyng8ra"
35724
35927
  },
@@ -35740,9 +35943,9 @@ function Query({
35740
35943
  });
35741
35944
  }
35742
35945
  function Source({
35743
- rootQuery
35946
+ definition
35744
35947
  }) {
35745
- if (rootQuery.definition instanceof ASTArrowQueryDefinition) {
35948
+ if (definition instanceof ASTArrowQueryDefinition) {
35746
35949
  return /* @__PURE__ */ jsx("div", {
35747
35950
  ..._stylex.props(styles$u.queryCard, styles$b.content),
35748
35951
  children: /* @__PURE__ */ jsxs("div", {
@@ -35753,7 +35956,7 @@ function Source({
35753
35956
  ...{
35754
35957
  className: "mlyb3r6kr mlylyipyv mly117nqv4"
35755
35958
  },
35756
- children: rootQuery.definition.as.ArrowQueryDefinition().source.as.ReferenceQueryArrowSource().name
35959
+ children: definition.source.getSourceInfo().name
35757
35960
  })]
35758
35961
  })
35759
35962
  });
@@ -36090,13 +36293,13 @@ function LiteralValueEditor({
36090
36293
  }
36091
36294
  }
36092
36295
  function Parameters({
36093
- rootQuery
36296
+ definition
36094
36297
  }) {
36095
- const {
36096
- setQuery
36097
- } = useContext(QueryEditorContext);
36098
- if (rootQuery.definition instanceof ASTArrowQueryDefinition) {
36099
- const source = rootQuery.definition.as.ArrowQueryDefinition().source.as.ReferenceQueryArrowSource();
36298
+ const updateQuery = useUpdateQuery();
36299
+ if (definition instanceof ASTArrowQueryDefinition && definition.source instanceof ASTReferenceQueryArrowSource) {
36300
+ const {
36301
+ source
36302
+ } = definition;
36100
36303
  const sourceParameters = source.getSourceParameters();
36101
36304
  if (!sourceParameters || sourceParameters.length === 0) {
36102
36305
  return null;
@@ -36119,7 +36322,7 @@ function Parameters({
36119
36322
  value: ((_a2 = source.tryGetParameter(parameter.name)) == null ? void 0 : _a2.parameter.value) ?? parameter.default_value,
36120
36323
  setValue: (value) => {
36121
36324
  source.setParameter(parameter.name, value);
36122
- setQuery == null ? void 0 : setQuery(rootQuery.build());
36325
+ updateQuery();
36123
36326
  }
36124
36327
  })]
36125
36328
  }, parameter.name);
@@ -36137,23 +36340,23 @@ const styles$9 = {
36137
36340
  };
36138
36341
  function QueryEditor() {
36139
36342
  const {
36140
- rootQuery,
36141
- setQuery
36343
+ rootQuery
36142
36344
  } = useContext(QueryEditorContext);
36143
36345
  if (!rootQuery) {
36144
36346
  console.error("Missing <MalloyExplorerProvider>");
36145
36347
  return null;
36146
36348
  }
36349
+ const {
36350
+ definition
36351
+ } = rootQuery;
36147
36352
  return /* @__PURE__ */ jsxs("div", {
36148
36353
  ..._stylex.props(fontStyles.body, styles$8.main),
36149
36354
  children: [/* @__PURE__ */ jsx(Source, {
36150
- rootQuery
36355
+ definition
36151
36356
  }), /* @__PURE__ */ jsx(Parameters, {
36152
- rootQuery
36357
+ definition
36153
36358
  }), /* @__PURE__ */ jsx(Query, {
36154
- rootQuery,
36155
- query: rootQuery,
36156
- setQuery
36359
+ definition
36157
36360
  })]
36158
36361
  });
36159
36362
  }
@@ -36684,22 +36887,19 @@ function RenderedResult({
36684
36887
  const viz = useMemo(() => {
36685
36888
  const renderer = new MalloyRenderer();
36686
36889
  const viz2 = renderer.createViz({
36687
- onDrill: ({
36688
- stableQuery,
36689
- stableDrillClauses
36690
- }) => {
36890
+ onDrill: (drillData) => {
36691
36891
  if (onDrill) {
36692
- onDrill({
36693
- stableQuery,
36694
- stableDrillClauses
36695
- });
36892
+ onDrill(drillData);
36696
36893
  return;
36697
36894
  }
36895
+ const {
36896
+ stableQuery
36897
+ } = drillData;
36698
36898
  const rootQuery = new ASTQuery({
36699
36899
  query: stableQuery,
36700
36900
  source
36701
36901
  });
36702
- setQuery == null ? void 0 : setQuery(rootQuery.build());
36902
+ setQuery(rootQuery.build());
36703
36903
  },
36704
36904
  tableConfig: {
36705
36905
  enableDrill: true
@@ -37280,27 +37480,21 @@ function useOperations(view, field, path) {
37280
37480
  return "";
37281
37481
  }, [matchingFieldItem, view, path, field.name, fullName]);
37282
37482
  return {
37283
- isGroupByAllowed: !groupByDisabledReason,
37284
37483
  groupByDisabledReason,
37285
- isAggregateAllowed: !aggregateDisabledReason,
37286
37484
  aggregateDisabledReason,
37287
- isFilterAllowed: !filterDisabledReason,
37288
37485
  filterDisabledReason,
37289
- isOrderByAllowed: !orderByDisabledReason,
37290
37486
  orderByDisabledReason
37291
37487
  };
37292
37488
  }
37293
37489
  const FILTERABLE_TYPES = ["string_type", "boolean_type", "number_type", "date_type", "timestamp_type"];
37294
37490
  const ORDERABLE_TYPES = ["string_type", "number_type", "boolean_type", "date_type", "timestamp_type"];
37295
37491
  function FieldTokenWithActions({
37492
+ rootQuery,
37296
37493
  field,
37297
37494
  path,
37298
37495
  viewDef
37299
37496
  }) {
37300
- const {
37301
- rootQuery,
37302
- setQuery
37303
- } = React__default.useContext(QueryEditorContext);
37497
+ const updateQuery = useUpdateQuery();
37304
37498
  const {
37305
37499
  focusedNestView
37306
37500
  } = useQueryFocus();
@@ -37324,19 +37518,19 @@ function FieldTokenWithActions({
37324
37518
  } else if (operation === "filter" && !filterDisabledReason && filter) {
37325
37519
  addFilter(view, field, path, filter);
37326
37520
  }
37327
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
37521
+ updateQuery();
37328
37522
  }
37329
37523
  };
37330
37524
  const handleSetView = () => {
37331
- if (field.kind === "view" && (rootQuery == null ? void 0 : rootQuery.isEmpty())) {
37332
- rootQuery == null ? void 0 : rootQuery.setView(field.name);
37333
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
37525
+ if (field.kind === "view" && rootQuery.isEmpty()) {
37526
+ rootQuery.setView(field.name);
37527
+ updateQuery();
37334
37528
  }
37335
37529
  };
37336
37530
  const handleAddView = () => {
37337
37531
  if (field.kind === "view") {
37338
37532
  addNest(view, field);
37339
- setQuery == null ? void 0 : setQuery(rootQuery == null ? void 0 : rootQuery.build());
37533
+ updateQuery();
37340
37534
  }
37341
37535
  };
37342
37536
  return /* @__PURE__ */ jsx(FieldToken, {
@@ -37344,9 +37538,9 @@ function FieldTokenWithActions({
37344
37538
  hoverActions: field.kind === "view" ? /* @__PURE__ */ jsxs(Fragment, {
37345
37539
  children: [/* @__PURE__ */ jsx(ActionButton, {
37346
37540
  icon: "insert",
37347
- disabled: !(rootQuery == null ? void 0 : rootQuery.isEmpty()),
37541
+ disabled: !rootQuery.isEmpty(),
37348
37542
  onClick: handleSetView,
37349
- tooltip: !(rootQuery == null ? void 0 : rootQuery.isEmpty()) ? "Can only add a view to an empty query." : "Add view",
37543
+ tooltip: !rootQuery.isEmpty() ? "Can only add a view to an empty query." : "Add view",
37350
37544
  onTooltipOpenChange: setIsTooltipOpen
37351
37545
  }), /* @__PURE__ */ jsx(ActionButton, {
37352
37546
  icon: "nest",
@@ -37412,7 +37606,7 @@ function FieldTokenWithActions({
37412
37606
  })]
37413
37607
  }) : null,
37414
37608
  onClick: field.kind === "dimension" && !groupByDisabledReason ? () => handleAddOperationAction("groupBy") : field.kind === "measure" && !aggregateDisabledReason ? () => handleAddOperationAction("aggregate") : field.kind === "view" ? () => {
37415
- if (rootQuery == null ? void 0 : rootQuery.isEmpty()) {
37609
+ if (rootQuery.isEmpty()) {
37416
37610
  handleSetView();
37417
37611
  } else {
37418
37612
  handleAddView();
@@ -37456,6 +37650,7 @@ function ActionButton({
37456
37650
  }
37457
37651
  const FIELD_KIND_ORDER = ["dimension", "measure", "view"];
37458
37652
  function SearchResultList({
37653
+ rootQuery,
37459
37654
  source,
37460
37655
  items
37461
37656
  }) {
@@ -37465,10 +37660,7 @@ function SearchResultList({
37465
37660
  items: groupFieldItemsByPath(source, group.items)
37466
37661
  }));
37467
37662
  }, [source, items]);
37468
- const {
37469
- rootQuery
37470
- } = React.useContext(QueryEditorContext);
37471
- const viewDef = rootQuery == null ? void 0 : rootQuery.definition;
37663
+ const viewDef = rootQuery.definition;
37472
37664
  if (!(viewDef instanceof ASTArrowQueryDefinition)) {
37473
37665
  return null;
37474
37666
  }
@@ -37505,6 +37697,7 @@ function SearchResultList({
37505
37697
  field,
37506
37698
  path
37507
37699
  }) => /* @__PURE__ */ jsx(FieldTokenWithActions, {
37700
+ rootQuery,
37508
37701
  field,
37509
37702
  path,
37510
37703
  viewDef
@@ -37531,6 +37724,7 @@ const getSublabelFromPath = (source, path) => {
37531
37724
  return path.length > 0 ? `joined to ${[...path.slice(0, -1), source.name].join(" > ")}` : void 0;
37532
37725
  };
37533
37726
  function FieldGroupList({
37727
+ rootQuery,
37534
37728
  source,
37535
37729
  fieldItems,
37536
37730
  fieldGroupType
@@ -37550,10 +37744,7 @@ function FieldGroupList({
37550
37744
  group
37551
37745
  }) => group === fieldGroupType)) == null ? void 0 : _a2.items) ?? [];
37552
37746
  }, [fieldGroupsByKindByPath, fieldGroupType]);
37553
- const {
37554
- rootQuery
37555
- } = React.useContext(QueryEditorContext);
37556
- const viewDef = rootQuery == null ? void 0 : rootQuery.definition;
37747
+ const viewDef = rootQuery.definition;
37557
37748
  if (!(viewDef instanceof ASTArrowQueryDefinition)) {
37558
37749
  return null;
37559
37750
  }
@@ -37570,6 +37761,7 @@ function FieldGroupList({
37570
37761
  field,
37571
37762
  path
37572
37763
  }) => /* @__PURE__ */ jsx(FieldTokenWithActions, {
37764
+ rootQuery,
37573
37765
  field,
37574
37766
  path,
37575
37767
  viewDef
@@ -37582,7 +37774,8 @@ function SourcePanel({
37582
37774
  onRefresh
37583
37775
  }) {
37584
37776
  const {
37585
- source
37777
+ source,
37778
+ rootQuery
37586
37779
  } = React.useContext(QueryEditorContext);
37587
37780
  const [searchQuery, setSearchQuery] = React.useState("");
37588
37781
  const {
@@ -37605,7 +37798,7 @@ function SourcePanel({
37605
37798
  return [];
37606
37799
  }, [fieldItems, searchQuery]);
37607
37800
  const isSearchActive = !!searchQuery;
37608
- if (!source) {
37801
+ if (!source || !rootQuery) {
37609
37802
  return null;
37610
37803
  }
37611
37804
  return /* @__PURE__ */ jsxs("div", {
@@ -37660,6 +37853,7 @@ function SourcePanel({
37660
37853
  className: "mly78zum5 mlydt5ytf mlyysyzu8 mly1iyjqo2"
37661
37854
  },
37662
37855
  children: isSearchActive ? /* @__PURE__ */ jsx(SearchResultList, {
37856
+ rootQuery,
37663
37857
  source,
37664
37858
  items: searchResultItems
37665
37859
  }) : /* @__PURE__ */ jsxs(AccordionList, {
@@ -37676,6 +37870,7 @@ function SourcePanel({
37676
37870
  color: "cyan"
37677
37871
  }),
37678
37872
  children: /* @__PURE__ */ jsx(FieldGroupList, {
37873
+ rootQuery,
37679
37874
  source,
37680
37875
  fieldItems,
37681
37876
  fieldGroupType: "dimension"
@@ -37692,6 +37887,7 @@ function SourcePanel({
37692
37887
  color: "green"
37693
37888
  }),
37694
37889
  children: /* @__PURE__ */ jsx(FieldGroupList, {
37890
+ rootQuery,
37695
37891
  source,
37696
37892
  fieldItems,
37697
37893
  fieldGroupType: "measure"
@@ -37708,6 +37904,7 @@ function SourcePanel({
37708
37904
  color: "purple"
37709
37905
  }),
37710
37906
  children: /* @__PURE__ */ jsx(FieldGroupList, {
37907
+ rootQuery,
37711
37908
  source,
37712
37909
  fieldItems,
37713
37910
  fieldGroupType: "view"