@marimo-team/frontend 0.25.3-dev104 → 0.25.3-dev108

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 (112) hide show
  1. package/dist/assets/{CellStatus-DVrvejMC.js → CellStatus-_Aw9_foI.js} +1 -1
  2. package/dist/assets/{ConnectedDataExplorerComponent-Dft8R6l5.js → ConnectedDataExplorerComponent-BRgqbAsc.js} +1 -1
  3. package/dist/assets/{ErrorBoundary-0akNKvJm.js → ErrorBoundary-DxSzjvbx.js} +2 -2
  4. package/dist/assets/{JsonOutput-DeUmpc_f.js → JsonOutput-B7pGj79O.js} +2 -2
  5. package/dist/assets/{MarimoErrorOutput-BazxeAYV.js → MarimoErrorOutput-Bzo6Bkp5.js} +1 -1
  6. package/dist/assets/{RenderHTML-CbAdeual.js → RenderHTML-D6AC0IhC.js} +1 -1
  7. package/dist/assets/{RunButton-CjKwgCFU.js → RunButton-BjYsPiKa.js} +1 -1
  8. package/dist/assets/{add-cell-with-ai-BKVEws3J.js → add-cell-with-ai-DlpS2-wQ.js} +4 -4
  9. package/dist/assets/{add-connection-dialog-DS7LTz1T.js → add-connection-dialog-CyNAB_W2.js} +1 -1
  10. package/dist/assets/{agent-panel-B34QcdOK.js → agent-panel-_lzeDJ1g.js} +1 -1
  11. package/dist/assets/{ai-model-dropdown-DqFJCFVR.js → ai-model-dropdown-DSTTUxpi.js} +1 -1
  12. package/dist/assets/{app-config-button-CVh4UKi9.js → app-config-button-ChYKLsLO.js} +1 -1
  13. package/dist/assets/{blob-Bw0ZQoLx.js → blob-DTYOX-m5.js} +1 -1
  14. package/dist/assets/{cell-editor-DQ0io5Ye.js → cell-editor-Beg8ahPA.js} +2 -2
  15. package/dist/assets/{cell-link-DvOIu6A3.js → cell-link-D3rkqgbU.js} +1 -1
  16. package/dist/assets/{cells-Do-63MKT.js → cells-2HETnlvE.js} +5 -5
  17. package/dist/assets/{chat-display-DnkhBxdh.js → chat-display-0GIEXLvN.js} +1 -1
  18. package/dist/assets/{chat-panel-CN3qoX9G.js → chat-panel-BuWn4Z_F.js} +1 -1
  19. package/dist/assets/{chat-ui-B54K5qqr.js → chat-ui-X0s3vvdf.js} +1 -1
  20. package/dist/assets/{column-preview-DmxzHzaW.js → column-preview-yI7-INkZ.js} +1 -1
  21. package/dist/assets/{command-palette-CciCeRhy.js → command-palette-D6WLW1Ie.js} +1 -1
  22. package/dist/assets/{common-BCyx7t1i.js → common-DgXKwblm.js} +1 -1
  23. package/dist/assets/{components-CDvWXfXq.js → components-CuMhY4Sf.js} +1 -1
  24. package/dist/assets/{datasource-DieftweT.js → datasource-D9JMcEAP.js} +1 -1
  25. package/dist/assets/{dependency-graph-panel-IfcqTHgq.js → dependency-graph-panel-BVJWPCvw.js} +3 -3
  26. package/dist/assets/{documentation-panel-DeLCgVcq.js → documentation-panel--wI4XHso.js} +1 -1
  27. package/dist/assets/{download-BzfVCqUq.js → download-Dod42wfD.js} +1 -1
  28. package/dist/assets/{edit-page-HMyk4cWw.js → edit-page-EmacXgdB.js} +4 -4
  29. package/dist/assets/{error-entries-DjjWrbt4.js → error-entries-D00nWhWE.js} +1 -1
  30. package/dist/assets/{error-panel-CiG3JJA3.js → error-panel-CcN_1PWf.js} +1 -1
  31. package/dist/assets/{feedback-button-B8zVQEi6.js → feedback-button-ByGgqUsX.js} +1 -1
  32. package/dist/assets/feedback-button-tbWwJ_t6.js +1 -0
  33. package/dist/assets/{file-explorer-panel-BPD8Q0L-.js → file-explorer-panel-eTEqtMPW.js} +1 -1
  34. package/dist/assets/{file-name-input-CdkF9K3I.js → file-name-input-D5SfTNWh.js} +1 -1
  35. package/dist/assets/{floating-outline-TfDWJXBm.js → floating-outline-B-k3P_AO.js} +1 -1
  36. package/dist/assets/{gallery-page-BJpenPdQ.js → gallery-page-BzbMhDHi.js} +1 -1
  37. package/dist/assets/{glide-data-editor-DO15Nm-R.js → glide-data-editor-BMqhUrHI.js} +1 -1
  38. package/dist/assets/{home-page-mvqldGvD.js → home-page-BvA1BCmX.js} +1 -1
  39. package/dist/assets/{hooks-C4AJfqV0.js → hooks-CaRBg2ni.js} +1 -1
  40. package/dist/assets/{index-C2XzUsS7.js → index-hwaZTQ9l.js} +9 -9
  41. package/dist/assets/{layout-1kSh6fBF.js → layout-C-NAerIZ.js} +3 -3
  42. package/dist/assets/{logs-panel--QbHo7uS.js → logs-panel-B3T1GFBk.js} +1 -1
  43. package/dist/assets/{markdown-renderer-DJ7H8Rps.js → markdown-renderer-BhiTvxtL.js} +1 -1
  44. package/dist/assets/{name-cell-input-6Gd19S8T.js → name-cell-input-CgAObR6N.js} +1 -1
  45. package/dist/assets/{outline-panel-CjKvunvX.js → outline-panel-BhBb7Vqw.js} +1 -1
  46. package/dist/assets/{packages-panel-Gyrqi-MZ.js → packages-panel-Dz8rOIrh.js} +1 -1
  47. package/dist/assets/{panel-accordion-state-D49TNCLQ.js → panel-accordion-state-ZsUdpAYn.js} +1 -1
  48. package/dist/assets/{panels-DfbxoeGa.js → panels-B0lqLcI0.js} +1 -1
  49. package/dist/assets/{process-output-CgkoeA1-.js → process-output-CeOMwE17.js} +1 -1
  50. package/dist/assets/{readonly-code-display-BMbl_4BR.js → readonly-code-display-TvOC7ESE.js} +1 -1
  51. package/dist/assets/{readonly-python-code-BnPfpOJM.js → readonly-python-code-Cqkfdeyo.js} +1 -1
  52. package/dist/assets/{reveal-component-D84yAzG7.js → reveal-component-y06O6YuH.js} +1 -1
  53. package/dist/assets/{run-page-B10s8Pre.js → run-page-DHE6ET5K.js} +1 -1
  54. package/dist/assets/{runtime-details-state-Bkmgb59p.js → runtime-details-state-CKqJSfSR.js} +1 -1
  55. package/dist/assets/{scratchpad-panel-DtyjJ3yN.js → scratchpad-panel-BW_HfG5l.js} +1 -1
  56. package/dist/assets/{session-panel-Chaq1do8.js → session-panel-CdHdKUCF.js} +1 -1
  57. package/dist/assets/{snippets-panel-BaZmddOW.js → snippets-panel-DYLWOLYw.js} +1 -1
  58. package/dist/assets/{spec-uCpVvaAR.js → spec-DlH4Mp7d.js} +1 -1
  59. package/dist/assets/{state-Db73TZVD.js → state-DAqdiGqq.js} +1 -1
  60. package/dist/assets/{state-CqnCwHhY.js → state-DZN9vZ6z.js} +1 -1
  61. package/dist/assets/{tracing-C2vQMUI0.js → tracing-B0J2ctTm.js} +1 -1
  62. package/dist/assets/{tracing-panel-B4L2S2ac.js → tracing-panel-C1OCpoeE.js} +2 -2
  63. package/dist/assets/{tree-actions-JXDiioHK.js → tree-actions-sjBxIglc.js} +1 -1
  64. package/dist/assets/{useAddCell-CP3HIjGl.js → useAddCell-CaXnFGki.js} +1 -1
  65. package/dist/assets/{useCellActionButton-yi1_-emd.js → useCellActionButton-CJ90CMEj.js} +1 -1
  66. package/dist/assets/{useDeleteCell-BPLwyClM.js → useDeleteCell-D9N85822.js} +1 -1
  67. package/dist/assets/{useDependencyPanelTab-DmBiydXO.js → useDependencyPanelTab-CzAE0cm-.js} +1 -1
  68. package/dist/assets/{useNotebookActions-CfmgcJGx.js → useNotebookActions-CTKkktJB.js} +1 -1
  69. package/dist/assets/{useRunCells-jF-7tJkw.js → useRunCells-DGakx8hj.js} +1 -1
  70. package/dist/assets/{useSplitCell-B6zWL8Zf.js → useSplitCell-AK5BKPGM.js} +1 -1
  71. package/dist/index.html +21 -21
  72. package/package.json +2 -2
  73. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  74. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  75. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  76. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  77. package/src/components/data-table/charts/charts.tsx +5 -5
  78. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  79. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  80. package/src/components/dependency-graph/elements.ts +24 -21
  81. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  82. package/src/components/editor/output/ansi-reduce.ts +30 -23
  83. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
  84. package/src/core/ai/tools/base.ts +16 -7
  85. package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
  86. package/src/core/ai/tools/registry.ts +13 -8
  87. package/src/core/ai/tools/sample-tool.ts +6 -7
  88. package/src/core/cells/__tests__/session.test.ts +117 -36
  89. package/src/core/codemirror/__tests__/setup.test.ts +28 -28
  90. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  91. package/src/core/codemirror/language/extension.ts +8 -8
  92. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  93. package/src/core/codemirror/language/languages/python.ts +13 -7
  94. package/src/core/codemirror/language/languages/sql/sql.ts +9 -7
  95. package/src/core/codemirror/language/types.ts +7 -7
  96. package/src/core/codemirror/rtc/extension.ts +24 -12
  97. package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
  98. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  99. package/src/core/codemirror/utils.ts +1 -0
  100. package/src/core/host/__tests__/static.test.ts +167 -0
  101. package/src/core/host/backend.ts +10 -0
  102. package/src/core/host/static.ts +70 -0
  103. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  104. package/src/core/static/__tests__/files.test.ts +38 -10
  105. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  106. package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
  107. package/src/plugins/impl/DataTablePlugin.tsx +15 -18
  108. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -1
  109. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  110. package/src/plugins/impl/plotly/selection.ts +25 -19
  111. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  112. package/dist/assets/feedback-button-DQdMkSvR.js +0 -1
@@ -29,10 +29,12 @@ describe("getAxisEncoding", () => {
29
29
  aggregate: "sum",
30
30
  timeUnit: undefined,
31
31
  },
32
- { binned: true, step: 10 },
33
- COUNT_FIELD,
34
- true,
35
- ChartType.BAR,
32
+ {
33
+ binValues: { binned: true, step: 10 },
34
+ label: COUNT_FIELD,
35
+ stack: true,
36
+ chartType: ChartType.BAR,
37
+ },
36
38
  );
37
39
 
38
40
  expect(result).toEqual({
@@ -52,10 +54,12 @@ describe("getAxisEncoding", () => {
52
54
  aggregate: "mean",
53
55
  timeUnit: undefined,
54
56
  },
55
- undefined,
56
- "Average Price",
57
- false,
58
- ChartType.BAR,
57
+ {
58
+ binValues: undefined,
59
+ label: "Average Price",
60
+ stack: false,
61
+ chartType: ChartType.BAR,
62
+ },
59
63
  );
60
64
 
61
65
  expect(result).toEqual({
@@ -79,10 +83,12 @@ describe("getAxisEncoding", () => {
79
83
  aggregate: NONE_VALUE,
80
84
  timeUnit,
81
85
  },
82
- undefined,
83
- "Date",
84
- undefined,
85
- ChartType.LINE,
86
+ {
87
+ binValues: undefined,
88
+ label: "Date",
89
+ stack: undefined,
90
+ chartType: ChartType.LINE,
91
+ },
86
92
  );
87
93
 
88
94
  expect(result).toEqual({
@@ -105,10 +111,12 @@ describe("getAxisEncoding", () => {
105
111
  aggregate: NONE_VALUE,
106
112
  timeUnit: undefined,
107
113
  },
108
- undefined,
109
- "Category",
110
- true,
111
- ChartType.BAR,
114
+ {
115
+ binValues: undefined,
116
+ label: "Category",
117
+ stack: true,
118
+ chartType: ChartType.BAR,
119
+ },
112
120
  );
113
121
 
114
122
  expect(result).toEqual({
@@ -129,10 +137,12 @@ describe("getAxisEncoding", () => {
129
137
  aggregate: "sum",
130
138
  timeUnit: undefined,
131
139
  },
132
- undefined,
133
- "Value",
134
- false,
135
- ChartType.BAR,
140
+ {
141
+ binValues: undefined,
142
+ label: "Value",
143
+ stack: false,
144
+ chartType: ChartType.BAR,
145
+ },
136
146
  );
137
147
 
138
148
  expect((result as { bin?: unknown }).bin).toBeUndefined();
@@ -146,10 +156,12 @@ describe("getAxisEncoding", () => {
146
156
  aggregate: "sum",
147
157
  timeUnit: undefined,
148
158
  },
149
- undefined,
150
- undefined,
151
- false,
152
- ChartType.BAR,
159
+ {
160
+ binValues: undefined,
161
+ label: undefined,
162
+ stack: false,
163
+ chartType: ChartType.BAR,
164
+ },
153
165
  );
154
166
 
155
167
  expect((result as { title?: string }).title).toBeUndefined();
@@ -164,10 +176,12 @@ describe("getAxisEncoding", () => {
164
176
  aggregate: agg,
165
177
  timeUnit: undefined,
166
178
  },
167
- undefined,
168
- "Value",
169
- false,
170
- ChartType.BAR,
179
+ {
180
+ binValues: undefined,
181
+ label: "Value",
182
+ stack: false,
183
+ chartType: ChartType.BAR,
184
+ },
171
185
  );
172
186
 
173
187
  const expectedAggregate = (result as { aggregate?: string }).aggregate;
@@ -189,10 +203,12 @@ describe("getAxisEncoding", () => {
189
203
  aggregate: agg,
190
204
  timeUnit: undefined,
191
205
  },
192
- undefined,
193
- "Date",
194
- false,
195
- ChartType.BAR,
206
+ {
207
+ binValues: undefined,
208
+ label: "Date",
209
+ stack: false,
210
+ chartType: ChartType.BAR,
211
+ },
196
212
  );
197
213
 
198
214
  const expectedAggregate = (result as { aggregate?: string }).aggregate;
@@ -209,10 +225,12 @@ describe("getAxisEncoding", () => {
209
225
  sort: sort as "ascending" | "descending",
210
226
  aggregate: NONE_VALUE,
211
227
  },
212
- undefined,
213
- "Value",
214
- false,
215
- ChartType.BAR,
228
+ {
229
+ binValues: undefined,
230
+ label: "Value",
231
+ stack: false,
232
+ chartType: ChartType.BAR,
233
+ },
216
234
  );
217
235
 
218
236
  const expectedSort = (result as { sort?: string }).sort;
@@ -1009,10 +1027,12 @@ describe("Special character escaping in specs", () => {
1009
1027
  aggregate: "sum",
1010
1028
  timeUnit: undefined,
1011
1029
  },
1012
- undefined,
1013
- "Value",
1014
- false,
1015
- ChartType.BAR,
1030
+ {
1031
+ binValues: undefined,
1032
+ label: "Value",
1033
+ stack: false,
1034
+ chartType: ChartType.BAR,
1035
+ },
1016
1036
  );
1017
1037
 
1018
1038
  invariant("field" in result, "field should be defined");
@@ -1027,10 +1047,12 @@ describe("Special character escaping in specs", () => {
1027
1047
  aggregate: "mean",
1028
1048
  timeUnit: undefined,
1029
1049
  },
1030
- undefined,
1031
- "Data",
1032
- false,
1033
- ChartType.BAR,
1050
+ {
1051
+ binValues: undefined,
1052
+ label: "Data",
1053
+ stack: false,
1054
+ chartType: ChartType.BAR,
1055
+ },
1034
1056
  );
1035
1057
 
1036
1058
  invariant("field" in result, "field should be defined");
@@ -1045,10 +1067,12 @@ describe("Special character escaping in specs", () => {
1045
1067
  aggregate: NONE_VALUE,
1046
1068
  timeUnit: "yearmonth",
1047
1069
  },
1048
- undefined,
1049
- "Timestamp",
1050
- false,
1051
- ChartType.LINE,
1070
+ {
1071
+ binValues: undefined,
1072
+ label: "Timestamp",
1073
+ stack: false,
1074
+ chartType: ChartType.LINE,
1075
+ },
1052
1076
  );
1053
1077
 
1054
1078
  invariant("field" in result, "field should be defined");
@@ -1063,10 +1087,12 @@ describe("Special character escaping in specs", () => {
1063
1087
  aggregate: "sum",
1064
1088
  timeUnit: undefined,
1065
1089
  },
1066
- undefined,
1067
- "Result",
1068
- false,
1069
- ChartType.BAR,
1090
+ {
1091
+ binValues: undefined,
1092
+ label: "Result",
1093
+ stack: false,
1094
+ chartType: ChartType.BAR,
1095
+ },
1070
1096
  );
1071
1097
 
1072
1098
  invariant("field" in result, "field should be defined");
@@ -51,13 +51,19 @@ export type ErrorMessage = TypedString<"ErrorMessage">;
51
51
  export const X_AXIS_REQUIRED = "X-axis column is required" as ErrorMessage;
52
52
  export const Y_AXIS_REQUIRED = "Y-axis column is required" as ErrorMessage;
53
53
 
54
- export function createSpecWithoutData(
55
- chartType: ChartType,
56
- formValues: ChartSchemaType,
57
- theme: ResolvedTheme,
58
- width: number | "container",
59
- height: number,
60
- ): TopLevelSpec | ErrorMessage {
54
+ export function createSpecWithoutData({
55
+ chartType,
56
+ formValues,
57
+ theme,
58
+ width,
59
+ height,
60
+ }: {
61
+ chartType: ChartType;
62
+ formValues: ChartSchemaType;
63
+ theme: ResolvedTheme;
64
+ width: number | "container";
65
+ height: number;
66
+ }): TopLevelSpec | ErrorMessage {
61
67
  const {
62
68
  xColumn,
63
69
  yColumn,
@@ -85,27 +91,25 @@ export function createSpecWithoutData(
85
91
  const yEncodingKey = "y";
86
92
 
87
93
  // Create encodings
88
- const xEncoding = getAxisEncoding(
89
- xColumn,
90
- formValues.xAxis?.bin,
91
- getFieldLabel(formValues.xAxis?.label),
92
- colorByColumn?.field && horizontal ? stacking : undefined,
94
+ const xEncoding = getAxisEncoding(xColumn, {
95
+ binValues: formValues.xAxis?.bin,
96
+ label: getFieldLabel(formValues.xAxis?.label),
97
+ stack: colorByColumn?.field && horizontal ? stacking : undefined,
93
98
  chartType,
94
- );
99
+ });
95
100
 
96
101
  let defaultYAggregation: ValidAggregationFn = DEFAULT_AGGREGATION;
97
102
  if (yColumn?.selectedDataType === "string") {
98
103
  defaultYAggregation = "count";
99
104
  }
100
105
 
101
- const yEncoding = getAxisEncoding(
102
- yColumn,
103
- formValues.yAxis?.bin,
104
- getFieldLabel(formValues.yAxis?.label),
105
- colorByColumn?.field && !horizontal ? stacking : undefined,
106
+ const yEncoding = getAxisEncoding(yColumn, {
107
+ binValues: formValues.yAxis?.bin,
108
+ label: getFieldLabel(formValues.yAxis?.label),
109
+ stack: colorByColumn?.field && !horizontal ? stacking : undefined,
106
110
  chartType,
107
- defaultYAggregation,
108
- );
111
+ defaultAggregate: defaultYAggregation,
112
+ });
109
113
 
110
114
  const rowFacet = facet?.row.field
111
115
  ? getFacetEncoding(facet.row, chartType)
@@ -115,14 +119,14 @@ export function createSpecWithoutData(
115
119
  : undefined;
116
120
 
117
121
  const colorByEncoding = getColorEncoding(chartType, formValues);
118
- const baseSpec = getBaseSpec(
122
+ const baseSpec = getBaseSpec({
119
123
  chartType,
120
124
  formValues,
121
125
  theme,
122
126
  width,
123
127
  height,
124
128
  title,
125
- );
129
+ });
126
130
  const baseEncoding: Encoding<Field> = {
127
131
  [xEncodingKey]: horizontal ? yEncoding : xEncoding,
128
132
  [yEncodingKey]: horizontal ? xEncoding : yEncoding,
@@ -160,11 +164,19 @@ export function augmentSpecWithData(
160
164
 
161
165
  export function getAxisEncoding(
162
166
  column: NonNullable<z.infer<typeof AxisSchema>>,
163
- binValues: z.infer<typeof BinSchema> | undefined,
164
- label: string | undefined,
165
- stack: boolean | undefined,
166
- chartType: ChartType,
167
- defaultAggregate?: ValidAggregationFn,
167
+ {
168
+ binValues,
169
+ label,
170
+ stack,
171
+ chartType,
172
+ defaultAggregate,
173
+ }: {
174
+ binValues: z.infer<typeof BinSchema> | undefined;
175
+ label: string | undefined;
176
+ stack: boolean | undefined;
177
+ chartType: ChartType;
178
+ defaultAggregate?: ValidAggregationFn;
179
+ },
168
180
  ): PositionDef<string> {
169
181
  const selectedDataType = column.selectedDataType || "string";
170
182
 
@@ -236,13 +248,12 @@ function getPieChartSpec(
236
248
  return "Size by column is required" as ErrorMessage;
237
249
  }
238
250
 
239
- const thetaEncoding: PolarDef<string> = getAxisEncoding(
240
- yColumn,
241
- formValues.xAxis?.bin,
242
- getFieldLabel(formValues.xAxis?.label),
243
- undefined,
244
- ChartType.PIE,
245
- );
251
+ const thetaEncoding: PolarDef<string> = getAxisEncoding(yColumn, {
252
+ binValues: formValues.xAxis?.bin,
253
+ label: getFieldLabel(formValues.xAxis?.label),
254
+ stack: undefined,
255
+ chartType: ChartType.PIE,
256
+ });
246
257
 
247
258
  const colorEncoding: ColorDef<string> = {
248
259
  field: escapeFieldName(colorByColumn.field),
@@ -252,7 +263,14 @@ function getPieChartSpec(
252
263
  };
253
264
 
254
265
  return {
255
- ...getBaseSpec(ChartType.PIE, formValues, theme, width, height, title),
266
+ ...getBaseSpec({
267
+ chartType: ChartType.PIE,
268
+ formValues,
269
+ theme,
270
+ width,
271
+ height,
272
+ title,
273
+ }),
256
274
  mark: {
257
275
  type: convertChartTypeToMark(ChartType.PIE),
258
276
  innerRadius: formValues.style?.innerRadius,
@@ -270,14 +288,21 @@ function getPieChartSpec(
270
288
  };
271
289
  }
272
290
 
273
- function getBaseSpec(
274
- chartType: ChartType,
275
- formValues: ChartSchemaType,
276
- theme: ResolvedTheme,
277
- width: number | "container",
278
- height: number,
279
- title?: string,
280
- ): BaseSpec {
291
+ function getBaseSpec({
292
+ chartType,
293
+ formValues,
294
+ theme,
295
+ width,
296
+ height,
297
+ title,
298
+ }: {
299
+ chartType: ChartType;
300
+ formValues: ChartSchemaType;
301
+ theme: ResolvedTheme;
302
+ width: number | "container";
303
+ height: number;
304
+ title?: string;
305
+ }): BaseSpec {
281
306
  let gridLines = formValues.style?.gridLines ?? false;
282
307
  // Scatter charts have grid lines by default
283
308
  if (chartType === ChartType.SCATTER) {
@@ -387,13 +387,13 @@ export const ChartPanel: React.FC<{
387
387
  // deeply partial, but the form always starts from complete defaults.
388
388
  const formValues = useWatch({ control: form.control }) as ChartSchemaType;
389
389
 
390
- const specWithoutData = createSpecWithoutData(
391
- selectedChartType,
390
+ const specWithoutData = createSpecWithoutData({
391
+ chartType: selectedChartType,
392
392
  formValues,
393
393
  theme,
394
- "container",
395
- CHART_HEIGHT,
396
- );
394
+ width: "container",
395
+ height: CHART_HEIGHT,
396
+ });
397
397
 
398
398
  // Prevent unnecessary re-renders of the chart
399
399
  const memoizedChart = useMemo(() => {
@@ -119,16 +119,16 @@ export class ColumnChartSpecModel<T> {
119
119
  private columnBinValues = new Map<ColumnName, BinValues>();
120
120
  private columnValueCounts = new Map<ColumnName, ValueCounts>();
121
121
 
122
- public static readonly EMPTY = new ColumnChartSpecModel(
123
- [],
124
- new Map(),
125
- {},
126
- {},
127
- {},
128
- {
122
+ public static readonly EMPTY = new ColumnChartSpecModel({
123
+ data: [],
124
+ fieldTypes: new Map(),
125
+ stats: {},
126
+ binValues: {},
127
+ valueCounts: {},
128
+ opts: {
129
129
  includeCharts: false,
130
130
  },
131
- );
131
+ });
132
132
 
133
133
  private dataSpec: TopLevelSpec["data"];
134
134
 
@@ -144,16 +144,23 @@ export class ColumnChartSpecModel<T> {
144
144
  includeCharts: boolean;
145
145
  };
146
146
 
147
- public constructor(
148
- data: T[] | string,
149
- fieldTypes: FieldTypes,
150
- stats: Record<ColumnName, Partial<ColumnHeaderStats>>,
151
- binValues: Record<ColumnName, BinValues>,
152
- valueCounts: Record<ColumnName, ValueCounts>,
147
+ public constructor({
148
+ data,
149
+ fieldTypes,
150
+ stats,
151
+ binValues,
152
+ valueCounts,
153
+ opts,
154
+ }: {
155
+ data: T[] | string;
156
+ fieldTypes: FieldTypes;
157
+ stats: Record<ColumnName, Partial<ColumnHeaderStats>>;
158
+ binValues: Record<ColumnName, BinValues>;
159
+ valueCounts: Record<ColumnName, ValueCounts>;
153
160
  opts: {
154
161
  includeCharts: boolean;
155
- },
156
- ) {
162
+ };
163
+ }) {
157
164
  this.fieldTypes = fieldTypes;
158
165
  this.stats = stats;
159
166
  this.binValues = binValues;
@@ -85,13 +85,13 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
85
85
 
86
86
  // oxlint-disable-next-line react/hook-use-state
87
87
  const [initial] = useState(() => {
88
- const elements = elementsBuilder.createElements(
88
+ const elements = elementsBuilder.createElements({
89
89
  cellIds,
90
90
  cellAtoms,
91
91
  variables,
92
- settings.hidePureMarkdown,
93
- settings.hideReusableFunctions,
94
- );
92
+ hidePureMarkdown: settings.hidePureMarkdown,
93
+ hideReusableFunctions: settings.hideReusableFunctions,
94
+ });
95
95
  return layoutElements({
96
96
  nodes: withExpansion(elements.nodes, expandedIds),
97
97
  edges: elements.edges,
@@ -163,13 +163,13 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
163
163
 
164
164
  // Rebuild + re-layout when the graph inputs or the expand/collapse set change.
165
165
  useEffect(() => {
166
- const elements = elementsBuilder.createElements(
166
+ const elements = elementsBuilder.createElements({
167
167
  cellIds,
168
168
  cellAtoms,
169
169
  variables,
170
- settings.hidePureMarkdown,
171
- settings.hideReusableFunctions,
172
- );
170
+ hidePureMarkdown: settings.hidePureMarkdown,
171
+ hideReusableFunctions: settings.hideReusableFunctions,
172
+ });
173
173
  syncChanges({
174
174
  nodes: withExpansion(elements.nodes, expandedIds),
175
175
  edges: elements.edges,
@@ -42,6 +42,14 @@ export interface NodeData {
42
42
  }
43
43
  export type CustomNodeProps = NodeProps<NodeData>;
44
44
 
45
+ interface CreateElementsOptions {
46
+ cellIds: CellId[];
47
+ cellAtoms: Atom<CellData>[];
48
+ variables: Variables;
49
+ hidePureMarkdown: boolean;
50
+ hideReusableFunctions: boolean;
51
+ }
52
+
45
53
  const LINE_HEIGHT = 11; // matches TinyCode.css
46
54
 
47
55
  export function getNodeHeight(linesOfCode: number) {
@@ -176,13 +184,10 @@ export function computeDefsByCell(
176
184
  }
177
185
 
178
186
  interface ElementsBuilder {
179
- createElements: (
180
- cellIds: CellId[],
181
- cellAtoms: Atom<CellData>[],
182
- variables: Variables,
183
- hidePureMarkdown: boolean,
184
- hideReusableFunctions: boolean,
185
- ) => { nodes: Node<NodeData>[]; edges: Edge[] };
187
+ createElements: (options: CreateElementsOptions) => {
188
+ nodes: Node<NodeData>[];
189
+ edges: Edge[];
190
+ };
186
191
  }
187
192
 
188
193
  export class VerticalElementsBuilder implements ElementsBuilder {
@@ -225,13 +230,11 @@ export class VerticalElementsBuilder implements ElementsBuilder {
225
230
  };
226
231
  }
227
232
 
228
- public createElements(
229
- cellIds: CellId[],
230
- cellAtoms: Atom<CellData>[],
231
- variables: Variables,
232
- _hidePureMarkdown: boolean,
233
- _hideReusableFunctions: boolean,
234
- ) {
233
+ public createElements({
234
+ cellIds,
235
+ cellAtoms,
236
+ variables,
237
+ }: CreateElementsOptions) {
235
238
  let prevY = 0;
236
239
  const nodes: Node<NodeData>[] = [];
237
240
  const edges: Edge[] = [];
@@ -311,13 +314,13 @@ export class TreeElementsBuilder implements ElementsBuilder {
311
314
  };
312
315
  }
313
316
 
314
- public createElements(
315
- cellIds: CellId[],
316
- cellAtoms: Atom<CellData>[],
317
- variables: Variables,
318
- hidePureMarkdown: boolean,
319
- hideReusableFunctions: boolean,
320
- ) {
317
+ public createElements({
318
+ cellIds,
319
+ cellAtoms,
320
+ variables,
321
+ hidePureMarkdown,
322
+ hideReusableFunctions,
323
+ }: CreateElementsOptions) {
321
324
  const nodes: Node<NodeData>[] = [];
322
325
 
323
326
  const cellRuntime = getNotebook().cellRuntime;
@@ -7,10 +7,12 @@ import { boundingBox, placeIslands } from "../layout";
7
7
 
8
8
  function node(
9
9
  id: string,
10
- x: number,
11
- y: number,
12
- width: number,
13
- height: number,
10
+ {
11
+ x,
12
+ y,
13
+ width,
14
+ height,
15
+ }: { x: number; y: number; width: number; height: number },
14
16
  ): Node<NodeData> {
15
17
  return {
16
18
  id,
@@ -28,8 +30,8 @@ describe("boundingBox", () => {
28
30
 
29
31
  it("spans position + size across nodes", () => {
30
32
  const box = boundingBox([
31
- node("a", 0, 0, 50, 50),
32
- node("b", 10, 20, 100, 40),
33
+ node("a", { x: 0, y: 0, width: 50, height: 50 }),
34
+ node("b", { x: 10, y: 20, width: 100, height: 40 }),
33
35
  ]);
34
36
  expect(box).toEqual({ minX: 0, minY: 0, maxX: 110, maxY: 60 });
35
37
  });
@@ -52,12 +54,17 @@ describe("boundingBox", () => {
52
54
 
53
55
  describe("placeIslands", () => {
54
56
  it("returns nothing when there are no islands", () => {
55
- expect(placeIslands([], [node("a", 0, 0, 100, 100)])).toEqual([]);
57
+ expect(
58
+ placeIslands([], [node("a", { x: 0, y: 0, width: 100, height: 100 })]),
59
+ ).toEqual([]);
56
60
  });
57
61
 
58
62
  it("stacks islands in a column to the right of the placed graph", () => {
59
- const placed = [node("main", 0, 0, 200, 300)];
60
- const islands = [node("i0", 0, 0, 90, 40), node("i1", 0, 0, 90, 40)];
63
+ const placed = [node("main", { x: 0, y: 0, width: 200, height: 300 })];
64
+ const islands = [
65
+ node("i0", { x: 0, y: 0, width: 90, height: 40 }),
66
+ node("i1", { x: 0, y: 0, width: 90, height: 40 }),
67
+ ];
61
68
  const result = placeIslands(islands, placed);
62
69
  // startX = maxX(200) + margin(40) = 240; startY = minY(0).
63
70
  expect(result[0].position).toEqual({ x: 240, y: 0 });
@@ -66,9 +73,9 @@ describe("placeIslands", () => {
66
73
  });
67
74
 
68
75
  it("wraps into a new column when the column gets too tall", () => {
69
- const placed = [node("main", 0, 0, 200, 300)];
76
+ const placed = [node("main", { x: 0, y: 0, width: 200, height: 300 })];
70
77
  const islands = Array.from({ length: 10 }, (_, i) =>
71
- node(`i${i}`, 0, 0, 90, 40),
78
+ node(`i${i}`, { x: 0, y: 0, width: 90, height: 40 }),
72
79
  );
73
80
  const result = placeIslands(islands, placed);
74
81
  const firstColumnX = result[0].position.x;