@marimo-team/islands 0.23.16-dev25 → 0.23.16-dev28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -22,17 +22,17 @@ import { _ as Functions, c as useEventListener, f as composeRefs, g as Logger, h
22
22
  import { t as require_react } from "./react-DA-nE2FX.js";
23
23
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
24
24
  import { n as Copy, r as toast, t as copyToClipboard } from "./copy-DNq8q3zw.js";
25
- import { $ as notebookOutline, A as ChevronDownIcon, Bn as Eye, Bt as DATA_TYPE_ICON, C as Accordion, Cn as selectAtom, Ct as PathBuilder, D as BorderAllIcon, Dn as Item$1, E as AccordionTrigger, En as Content2, Ft as repl, G as hasRunAnyCellAtom, Gn as CircleAlert, H as renderHTML, Hn as Database, Ht as require_client, I as base64ToDataView, In as LoaderCircle, It as SQLParser, Jt as requestClientAtom, K as cellIdsAtom, Kn as Braces, Kt as convertStatsName, Ln as Layers, Lt as MarkdownParser, Mn as Table2, Mt as jotaiJsonStorage, Nn as PaintRoller, On as Root2$1, Ot as DeferredRequestRegistry, Q as notebookAtom, Qt as shouldHidePublishedCell, R as dataViewToBase64, Rn as Info, Sn as atomWithStorage, T as AccordionItem, U as getMarimoExportContext, Un as Columns2, V as safeExtractSetUIElementMessageBuffers, W as hasTrustedExportContext, X as hasOnlyOneCellAtom, Xt as isUninstantiated, Y as getCellNames, Yt as useRequestClient, Z as initialNotebookState, Zt as publishedCellClasses, _n as OBJECT_ID_ATTR, _t as isInternalCellName, a as useCellFocusActions, at as createCell, bt as customPythonLanguageSupport, dn as parseInitialValue, dt as headingToIdentifier, et as numColumnsAtom, f as isOutputEmpty, gn as findCellId, gt as getValidName, hn as UIElementId, i as LazyAnyLanguageCodeMirror, jn as Trash2, kn as Trigger2, kt as generateUUID, ln as parseAttrValue, lt as outputIsLoading, n as Spinner, nt as useCellActions, o as useLastFocusedCellId, on as NotebookScopedLocalStorage, p as useExpandedConsoleOutput, pn as HTMLCellId, q as createActions, qt as getRequestClient, rt as useCellIds, s as maybeAddAltairImport, tt as reducer, un as parseDataset, ut as outputIsStale, vn as RANDOM_ID_ATTR, vt as normalizeName, w as AccordionContent, wt as Paths, xn as atomWithReducer, xt as MarkdownLanguageAdapter, yn as jsonParseWithSpecialChar, yt as Checkbox, zn as FileText, zt as PluralWords, __tla as __tla_0 } from "./html-to-image-27MFfyOf.js";
25
+ import { $ as notebookOutline, A as ChevronDownIcon, Bn as Eye, Bt as DATA_TYPE_ICON, C as Accordion, Cn as selectAtom, Ct as PathBuilder, D as BorderAllIcon, Dn as Item$1, E as AccordionTrigger, En as Content2, Ft as repl, G as hasRunAnyCellAtom, Gn as CircleAlert, H as renderHTML, Hn as Database, Ht as require_client, I as base64ToDataView, In as LoaderCircle, It as SQLParser, Jt as requestClientAtom, K as cellIdsAtom, Kn as Braces, Kt as convertStatsName, Ln as Layers, Lt as MarkdownParser, Mn as Table2, Mt as jotaiJsonStorage, Nn as PaintRoller, On as Root2$1, Ot as DeferredRequestRegistry, Q as notebookAtom, Qt as shouldHidePublishedCell, R as dataViewToBase64, Rn as Info, Sn as atomWithStorage, T as AccordionItem, U as getMarimoExportContext, Un as Columns2, V as safeExtractSetUIElementMessageBuffers, W as hasTrustedExportContext, X as hasOnlyOneCellAtom, Xt as isUninstantiated, Y as getCellNames, Yt as useRequestClient, Z as initialNotebookState, Zt as publishedCellClasses, _n as OBJECT_ID_ATTR, _t as isInternalCellName, a as useCellFocusActions, at as createCell, bt as customPythonLanguageSupport, dn as parseInitialValue, dt as headingToIdentifier, et as numColumnsAtom, f as isOutputEmpty, gn as findCellId, gt as getValidName, hn as UIElementId, i as LazyAnyLanguageCodeMirror, jn as Trash2, kn as Trigger2, kt as generateUUID, ln as parseAttrValue, lt as outputIsLoading, n as Spinner, nt as useCellActions, o as useLastFocusedCellId, on as NotebookScopedLocalStorage, p as useExpandedConsoleOutput, pn as HTMLCellId, q as createActions, qt as getRequestClient, rt as useCellIds, s as maybeAddAltairImport, tt as reducer, un as parseDataset, ut as outputIsStale, vn as RANDOM_ID_ATTR, vt as normalizeName, w as AccordionContent, wt as Paths, xn as atomWithReducer, xt as MarkdownLanguageAdapter, yn as jsonParseWithSpecialChar, yt as Checkbox, zn as FileText, zt as PluralWords, __tla as __tla_0 } from "./html-to-image-Bza3T2dl.js";
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-B9WoXK1R.js";
27
27
  import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-DIlxLFXG.js";
28
28
  import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS$1, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-CQKL_D3i.js";
29
- import { $ as smartMatch, $t as HtmlOutput, A as LoadingState, At as loadTableAndRawData, B as useInternalStateWithSync, Bt as dateToLocalISODateTime, C as Progress, Ct as renderCellValue, D as ColumnPreviewContainer, Dt as useIntersectionObserver, E as ColumnName, Et as DelayMount, F as ContextMenu, Ft as toFieldTypes, G as Combobox, Gt as TabsTrigger, H as CompactChipRow, Ht as Tabs, I as ContextMenuContent, It as getMimeValues, J as CommandEmpty, Jt as ChartLoadingState, K as ComboboxItem, Kt as ChartErrorState, L as ContextMenuItem, Lt as isNullishFilter, M as prettifyRowCount, Mt as INDEX_COLUMN_NAME, N as getColumnCountForDisplay, Nt as SELECT_COLUMN_ID, O as EmptyState, Ot as usePrevious$1, P as getUserColumnVisibilityCounts, Pt as TOO_MANY_ROWS, Q as CommandSeparator, Qt as Kbd, R as ContextMenuSeparator, Rt as Maps, S as downloadHTMLAsImage, St as inferFieldTypes, T as downloadSizeLimitAtom, Tt as ColumnChartSpecModel, U as DatePicker, Ut as TabsContent, V as useSelectList, Vt as dateToLocalISOTime, W as DateRangePicker, Wt as TabsList, X as CommandItem, Xt as useOverflowDetection, Y as CommandInput, Yt as LazyVegaEmbed, Z as CommandList, Zt as RenderTextWithLinks, _ as InstallPackageButton, _n as ChevronsDownUp, _t as TableHead, an as $fae977aafc393c5c$export$6b862160d295c8e, at as isCellAwareAtom, b as downloadByURL, bt as NAMELESS_COLUMN_PREFIX, cn as Funnel, ct as Toggle, d as RadioGroup, dn as Ellipsis, en as EmotionCacheProvider, et as ContextAwarePanelItem, f as RadioGroupItem, fn as Download, ft as Fill, g as DataTable, gn as ChevronsLeft, gt as TableCell, h as OutputRenderer, hn as ChevronsRight, ht as TableBody, in as $fae977aafc393c5c$export$588937bcd60ade55, it as contextAwarePanelType, j as prettifyRowColumnCount, jt as loadTableData, k as ErrorState, kt as getPageIndexForRow, l as Slide, ln as EyeOff, m as OutputArea, mn as ChevronsUpDown, mt as Table, n as marimoVersionAtom, nn as hasFunctionProperty, nt as contextAwarePanelOpen, on as TextWrap, ot as SlotNames, p as JsonOutput, pn as Code, pt as Provider$1, q as Command, qt as ChartInfoState, r as showCodeInRunModeAtom, rn as isRecord, rt as contextAwarePanelOwner, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as GripHorizontal, st as slotsController, t as useNotebookCodeAvailable, tn as safeLocale, tt as PANEL_TYPES, u as Switch, v as ADD_PRINTING_CLASS, vn as ChevronLeft, vt as TableHeader, w as Filenames, wt as ColumnChartContext, x as downloadExportedFile, xt as generateColumns, y as downloadBlob, yn as ArrowDownWideNarrow, yt as TableRow, z as ContextMenuTrigger, zt as dateToLocalISODate, __tla as __tla_2 } from "./code-visibility-Btz9Lj-7.js";
29
+ import { $ as smartMatch, $t as HtmlOutput, A as LoadingState, At as loadTableAndRawData, B as useInternalStateWithSync, Bt as dateToLocalISODateTime, C as Progress, Ct as renderCellValue, D as ColumnPreviewContainer, Dt as useIntersectionObserver, E as ColumnName, Et as DelayMount, F as ContextMenu, Ft as toFieldTypes, G as Combobox, Gt as TabsTrigger, H as CompactChipRow, Ht as Tabs, I as ContextMenuContent, It as getMimeValues, J as CommandEmpty, Jt as ChartLoadingState, K as ComboboxItem, Kt as ChartErrorState, L as ContextMenuItem, Lt as isNullishFilter, M as prettifyRowCount, Mt as INDEX_COLUMN_NAME, N as getColumnCountForDisplay, Nt as SELECT_COLUMN_ID, O as EmptyState, Ot as usePrevious$1, P as getUserColumnVisibilityCounts, Pt as TOO_MANY_ROWS, Q as CommandSeparator, Qt as Kbd, R as ContextMenuSeparator, Rt as Maps, S as downloadHTMLAsImage, St as inferFieldTypes, T as downloadSizeLimitAtom, Tt as ColumnChartSpecModel, U as DatePicker, Ut as TabsContent, V as useSelectList, Vt as dateToLocalISOTime, W as DateRangePicker, Wt as TabsList, X as CommandItem, Xt as useOverflowDetection, Y as CommandInput, Yt as LazyVegaEmbed, Z as CommandList, Zt as RenderTextWithLinks, _ as InstallPackageButton, _n as ChevronsDownUp, _t as TableHead, an as $fae977aafc393c5c$export$6b862160d295c8e, at as isCellAwareAtom, b as downloadByURL, bt as NAMELESS_COLUMN_PREFIX, cn as Funnel, ct as Toggle, d as RadioGroup, dn as Ellipsis, en as EmotionCacheProvider, et as ContextAwarePanelItem, f as RadioGroupItem, fn as Download, ft as Fill, g as DataTable, gn as ChevronsLeft, gt as TableCell, h as OutputRenderer, hn as ChevronsRight, ht as TableBody, in as $fae977aafc393c5c$export$588937bcd60ade55, it as contextAwarePanelType, j as prettifyRowColumnCount, jt as loadTableData, k as ErrorState, kt as getPageIndexForRow, l as Slide, ln as EyeOff, m as OutputArea, mn as ChevronsUpDown, mt as Table, n as marimoVersionAtom, nn as hasFunctionProperty, nt as contextAwarePanelOpen, on as TextWrap, ot as SlotNames, p as JsonOutput, pn as Code, pt as Provider$1, q as Command, qt as ChartInfoState, r as showCodeInRunModeAtom, rn as isRecord, rt as contextAwarePanelOwner, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as GripHorizontal, st as slotsController, t as useNotebookCodeAvailable, tn as safeLocale, tt as PANEL_TYPES, u as Switch, v as ADD_PRINTING_CLASS, vn as ChevronLeft, vt as TableHeader, w as Filenames, wt as ColumnChartContext, x as downloadExportedFile, xt as generateColumns, y as downloadBlob, yn as ArrowDownWideNarrow, yt as TableRow, z as ContextMenuTrigger, zt as dateToLocalISODate, __tla as __tla_2 } from "./code-visibility-CTlBHNhq.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CMJGqBaY.js";
31
31
  import { t as Check } from "./check-DP7U0H0G.js";
32
32
  import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-DIy9NAmg.js";
33
33
  import { B as $64fa3d84918910a7$export$4d86445c2cf5e3, C as DropdownMenuTrigger, Ft as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, It as $3ef42575df84b30b$export$9d1611c77c2fe928, W as $64fa3d84918910a7$export$df3a06d6289f983e, Wt as $ff5963eb1fccf552$export$e08e3b67e392101e, X as useDebouncedCallback, Y as useDebounceControlledState, a as NumberField, d as roundToFractionDigits, f as DropdownMenu, g as DropdownMenuLabel, gn as ChevronRight, h as DropdownMenuItem, hn as Circle, i as OnBlurredInput, l as prettyNumber, m as DropdownMenuGroup, n as DebouncedNumberInput, o as maxFractionDigitsForSteps, ot as $f7dceffc5ad7768b$export$4e328f61c538687f, p as DropdownMenuContent, pt as $6179b936705e76d3$export$ae780daf29e6d456, r as Input, st as $701a24aa0da5b062$export$ea18c227d4417cc3, t as DebouncedInput, u as prettyScientificNumber, v as DropdownMenuSeparator, xt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, y as DropdownMenuShortcut, z as $64fa3d84918910a7$export$29f1550f4b0d4415 } from "./input-C5K4VBvB.js";
34
34
  import { S as isWasm, _ as initialModeAtom, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as getInitialAppMode, m as require_cuid2, u as getStaticVirtualFiles, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-CqhBWjvO.js";
35
- import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Square, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-BpssYna4.js";
35
+ import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Square, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-pCEXvnhG.js";
36
36
  import { n as Trash, r as Pencil, t as BulkEdit } from "./types-DicH9Oi0.js";
37
37
  import { n as require_prop_types, r as Plus, t as ErrorBoundary } from "./ErrorBoundary-DhLqwSWA.js";
38
38
  import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
@@ -9009,7 +9009,7 @@ let __tla = Promise.all([
9009
9009
  };
9010
9010
  }
9011
9011
  };
9012
- var LazyChatbot = import_react.lazy(() => import("./chat-ui-BMBk8I78.js").then((e) => ({
9012
+ var LazyChatbot = import_react.lazy(() => import("./chat-ui-DuPGKU9z.js").then((e) => ({
9013
9013
  default: e.Chatbot
9014
9014
  }))), messageSchema = array(object({
9015
9015
  id: string(),
@@ -38147,7 +38147,7 @@ ${c}
38147
38147
  function _temp2$2(e) {
38148
38148
  e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
38149
38149
  }
38150
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-ByqpHkkW.js"));
38150
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-CAfix0fI.js"));
38151
38151
  const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
38152
38152
  var _a5;
38153
38153
  let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
@@ -1,6 +1,6 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
3
- import { ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-27MFfyOf.js";
3
+ import { ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-Bza3T2dl.js";
4
4
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
5
5
  import { t as Strings } from "./strings-DIy9NAmg.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
@@ -6,10 +6,10 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
6
6
  import { c as useEventListener, g as Logger, h as cn, m as Events, t as Button } from "./button-BSm8IXRU.js";
7
7
  import { t as require_react } from "./react-DA-nE2FX.js";
8
8
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
9
- import { ut as outputIsStale } from "./html-to-image-27MFfyOf.js";
9
+ import { ut as outputIsStale } from "./html-to-image-Bza3T2dl.js";
10
10
  import "./chunk-5FQGJX7Z-B9WoXK1R.js";
11
11
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
12
- import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, dt as PanelResizeHandle, i as DEFAULT_DECK_TRANSITION, l as Slide, ln as EyeOff, lt as Panel, o as DEFAULT_SLIDE_TYPE, pn as Code, t as useNotebookCodeAvailable, un as Expand, ut as PanelGroup } from "./code-visibility-Btz9Lj-7.js";
12
+ import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, dt as PanelResizeHandle, i as DEFAULT_DECK_TRANSITION, l as Slide, ln as EyeOff, lt as Panel, o as DEFAULT_SLIDE_TYPE, pn as Code, t as useNotebookCodeAvailable, un as Expand, ut as PanelGroup } from "./code-visibility-CTlBHNhq.js";
13
13
  import { R as ChevronDown } from "./strings-DIy9NAmg.js";
14
14
  import { X as useDebouncedCallback } from "./input-C5K4VBvB.js";
15
15
  import { v as kioskModeAtom } from "./toDate-CqhBWjvO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.16-dev25",
3
+ "version": "0.23.16-dev28",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -109,9 +109,10 @@ exports[`ColumnChartSpecModel > file URL handling > should handle arrow data 1`]
109
109
  "type": "temporal",
110
110
  },
111
111
  "y": {
112
- "aggregate": "max",
113
- "axis": null,
114
- "type": "quantitative",
112
+ "value": 0,
113
+ },
114
+ "y2": {
115
+ "value": 100,
115
116
  },
116
117
  },
117
118
  "mark": {
@@ -222,9 +223,10 @@ exports[`ColumnChartSpecModel > should expect bin values to be used for number a
222
223
  "field": "bin_end_extended",
223
224
  },
224
225
  "y": {
225
- "aggregate": "max",
226
- "axis": null,
227
- "type": "quantitative",
226
+ "value": 0,
227
+ },
228
+ "y2": {
229
+ "value": 30,
228
230
  },
229
231
  },
230
232
  "mark": {
@@ -486,9 +488,10 @@ exports[`ColumnChartSpecModel > should handle datetime bin values 1`] = `
486
488
  "type": "ordinal",
487
489
  },
488
490
  "y": {
489
- "aggregate": "max",
490
- "axis": null,
491
- "type": "quantitative",
491
+ "value": 0,
492
+ },
493
+ "y2": {
494
+ "value": 30,
492
495
  },
493
496
  },
494
497
  "mark": {
@@ -633,6 +636,152 @@ exports[`ColumnChartSpecModel > should handle string value counts 1`] = `
633
636
  }
634
637
  `;
635
638
 
639
+ exports[`ColumnChartSpecModel > should render a null bar for all-null temporal columns 1`] = `
640
+ {
641
+ "background": "transparent",
642
+ "config": {
643
+ "axis": {
644
+ "domain": false,
645
+ },
646
+ "view": {
647
+ "stroke": "transparent",
648
+ },
649
+ },
650
+ "data": {
651
+ "name": "bin_values",
652
+ "values": [
653
+ {
654
+ "bin_end": null,
655
+ "bin_start": null,
656
+ "count": 12,
657
+ },
658
+ ],
659
+ },
660
+ "height": 30,
661
+ "layer": [
662
+ {
663
+ "encoding": {
664
+ "x": {
665
+ "axis": null,
666
+ "field": "bin_start",
667
+ "type": "nominal",
668
+ },
669
+ "y": {
670
+ "axis": null,
671
+ "field": "count",
672
+ "type": "quantitative",
673
+ },
674
+ },
675
+ "mark": {
676
+ "color": "#cc4e00",
677
+ "type": "bar",
678
+ },
679
+ },
680
+ {
681
+ "encoding": {
682
+ "tooltip": [
683
+ {
684
+ "field": "count",
685
+ "format": ",d",
686
+ "title": "nulls",
687
+ "type": "quantitative",
688
+ },
689
+ ],
690
+ "x": {
691
+ "axis": null,
692
+ "field": "bin_start",
693
+ "type": "nominal",
694
+ },
695
+ "y": {
696
+ "value": 0,
697
+ },
698
+ "y2": {
699
+ "value": 30,
700
+ },
701
+ },
702
+ "mark": {
703
+ "opacity": 0,
704
+ "type": "bar",
705
+ },
706
+ },
707
+ ],
708
+ "width": 70,
709
+ }
710
+ `;
711
+
712
+ exports[`ColumnChartSpecModel > should render only a null bar for all-null numeric columns 1`] = `
713
+ {
714
+ "background": "transparent",
715
+ "config": {
716
+ "axis": {
717
+ "domain": false,
718
+ },
719
+ "view": {
720
+ "stroke": "transparent",
721
+ },
722
+ },
723
+ "data": {
724
+ "name": "bin_values",
725
+ "values": [
726
+ {
727
+ "bin_end": null,
728
+ "bin_start": null,
729
+ "count": 12,
730
+ },
731
+ ],
732
+ },
733
+ "height": 30,
734
+ "layer": [
735
+ {
736
+ "encoding": {
737
+ "x": {
738
+ "axis": null,
739
+ "field": "bin_start",
740
+ "type": "nominal",
741
+ },
742
+ "y": {
743
+ "axis": null,
744
+ "field": "count",
745
+ "type": "quantitative",
746
+ },
747
+ },
748
+ "mark": {
749
+ "color": "#cc4e00",
750
+ "type": "bar",
751
+ },
752
+ },
753
+ {
754
+ "encoding": {
755
+ "tooltip": [
756
+ {
757
+ "field": "count",
758
+ "format": ",d",
759
+ "title": "nulls",
760
+ "type": "quantitative",
761
+ },
762
+ ],
763
+ "x": {
764
+ "axis": null,
765
+ "field": "bin_start",
766
+ "type": "nominal",
767
+ },
768
+ "y": {
769
+ "value": 0,
770
+ },
771
+ "y2": {
772
+ "value": 30,
773
+ },
774
+ },
775
+ "mark": {
776
+ "opacity": 0,
777
+ "type": "bar",
778
+ },
779
+ },
780
+ ],
781
+ "width": 70,
782
+ }
783
+ `;
784
+
636
785
  exports[`ColumnChartSpecModel > snapshot with legacy data spec > array 1`] = `
637
786
  {
638
787
  "background": "transparent",
@@ -700,9 +849,10 @@ exports[`ColumnChartSpecModel > snapshot with legacy data spec > array 1`] = `
700
849
  "type": "quantitative",
701
850
  },
702
851
  "y": {
703
- "aggregate": "max",
704
- "axis": null,
705
- "type": "quantitative",
852
+ "value": 0,
853
+ },
854
+ "y2": {
855
+ "value": 100,
706
856
  },
707
857
  },
708
858
  "mark": {
@@ -788,9 +938,10 @@ exports[`ColumnChartSpecModel > snapshot with legacy data spec > csv data 1`] =
788
938
  "type": "quantitative",
789
939
  },
790
940
  "y": {
791
- "aggregate": "max",
792
- "axis": null,
793
- "type": "quantitative",
941
+ "value": 0,
942
+ },
943
+ "y2": {
944
+ "value": 100,
794
945
  },
795
946
  },
796
947
  "mark": {
@@ -876,9 +1027,10 @@ exports[`ColumnChartSpecModel > snapshot with legacy data spec > csv string 1`]
876
1027
  "type": "quantitative",
877
1028
  },
878
1029
  "y": {
879
- "aggregate": "max",
880
- "axis": null,
881
- "type": "quantitative",
1030
+ "value": 0,
1031
+ },
1032
+ "y2": {
1033
+ "value": 100,
882
1034
  },
883
1035
  },
884
1036
  "mark": {
@@ -988,9 +1140,10 @@ exports[`ColumnChartSpecModel > snapshot with legacy data spec > url data 1`] =
988
1140
  "type": "temporal",
989
1141
  },
990
1142
  "y": {
991
- "aggregate": "max",
992
- "axis": null,
993
- "type": "quantitative",
1143
+ "value": 0,
1144
+ },
1145
+ "y2": {
1146
+ "value": 100,
994
1147
  },
995
1148
  },
996
1149
  "mark": {
@@ -178,6 +178,104 @@ describe("ColumnChartSpecModel", () => {
178
178
  expect(summary2.spec?.data?.values).toEqual(mockBinValues.integer);
179
179
  });
180
180
 
181
+ it("should render only a null bar for all-null numeric columns", () => {
182
+ const allNullStats: Record<ColumnName, Partial<ColumnHeaderStats>> = {
183
+ number: { nulls: 12, total: 12 },
184
+ };
185
+ const allNullBins: Record<ColumnName, BinValues> = {
186
+ number: [],
187
+ };
188
+ const model = new ColumnChartSpecModel(
189
+ [],
190
+ mockFieldTypes,
191
+ allNullStats,
192
+ allNullBins,
193
+ {},
194
+ { includeCharts: true },
195
+ );
196
+ const summary = model.getHeaderSummary("number");
197
+ expect(summary.spec).toBeDefined();
198
+ // @ts-expect-error hconcat should be available
199
+ expect(summary.spec?.hconcat).toBeUndefined();
200
+ // @ts-expect-error data.values should be available
201
+ expect(summary.spec?.data?.values).toEqual([
202
+ { bin_start: null, bin_end: null, count: 12 },
203
+ ]);
204
+ // Full-width null-only chart (not the thin hconcat null strip)
205
+ expect(summary.spec?.width).toBe(70);
206
+ // Full-height tooltip hit area uses pixel y/y2 (no aggregate:max)
207
+ // @ts-expect-error layer should be available
208
+ expect(summary.spec?.layer?.[1]?.encoding?.y).toEqual({ value: 0 });
209
+ // @ts-expect-error layer should be available
210
+ expect(summary.spec?.layer?.[1]?.encoding?.y2).toEqual({ value: 30 });
211
+ expect(summary.spec).toMatchSnapshot();
212
+ });
213
+
214
+ it("should ignore NaN bins and not mutate stored bin values", () => {
215
+ const nanOnlyBins: Record<ColumnName, BinValues> = {
216
+ number: [
217
+ { bin_start: Number.NaN, bin_end: 0.1, count: 0 },
218
+ { bin_start: Number.NaN, bin_end: 1, count: 0 },
219
+ ],
220
+ };
221
+ const stats: Record<ColumnName, Partial<ColumnHeaderStats>> = {
222
+ number: { nulls: 12, total: 12 },
223
+ };
224
+ const model = new ColumnChartSpecModel(
225
+ [],
226
+ mockFieldTypes,
227
+ stats,
228
+ nanOnlyBins,
229
+ {},
230
+ { includeCharts: true },
231
+ );
232
+ const first = model.getHeaderSummary("number");
233
+ const second = model.getHeaderSummary("number");
234
+ // All NaN bins are invalid → null-only chart
235
+ // @ts-expect-error hconcat should be available
236
+ expect(first.spec?.hconcat).toBeUndefined();
237
+ expect(first.spec?.width).toBe(70);
238
+ // Stored bins must not grow across getHeaderSummary calls
239
+ expect(nanOnlyBins.number).toHaveLength(2);
240
+ expect(second.spec).toEqual(first.spec);
241
+ });
242
+
243
+ it("should render a null bar for all-null temporal columns", () => {
244
+ const model = new ColumnChartSpecModel(
245
+ [],
246
+ mockFieldTypes,
247
+ { datetime: { nulls: 12, total: 12 } },
248
+ { datetime: [] },
249
+ {},
250
+ { includeCharts: true },
251
+ );
252
+ const summary = model.getHeaderSummary("datetime");
253
+ expect(summary.spec).toBeDefined();
254
+ // @ts-expect-error data.values
255
+ expect(summary.spec?.data?.values).toEqual([
256
+ { bin_start: null, bin_end: null, count: 12 },
257
+ ]);
258
+ expect(summary.spec?.width).toBe(70);
259
+ // Same full-height hover hit area as numeric all-null charts
260
+ // @ts-expect-error layer should be available
261
+ expect(summary.spec?.layer?.[1]?.encoding?.y).toEqual({ value: 0 });
262
+ // @ts-expect-error layer should be available
263
+ expect(summary.spec?.layer?.[1]?.encoding?.y2).toEqual({ value: 30 });
264
+ expect(summary.spec).toMatchSnapshot();
265
+ });
266
+
267
+ it("should return null when numeric bins are empty and there are no nulls", () => {
268
+ const model = new ColumnChartSpecModel(
269
+ [],
270
+ mockFieldTypes,
271
+ { number: { min: 0, max: 1 } },
272
+ { number: [] },
273
+ {},
274
+ { includeCharts: true },
275
+ );
276
+ expect(model.getHeaderSummary("number").spec).toBeNull();
277
+ });
278
+
181
279
  it("should handle datetime bin values", () => {
182
280
  const model = new ColumnChartSpecModel(
183
281
  [],
@@ -191,7 +289,10 @@ describe("ColumnChartSpecModel", () => {
191
289
  const summary = model.getHeaderSummary("datetime");
192
290
  expect(summary.spec).toBeDefined();
193
291
  // @ts-expect-error data.values should be available
194
- expect(summary.spec?.data?.values).toEqual(mockBinValues.datetime);
292
+ expect(summary.spec?.data?.values).toEqual([
293
+ ...mockBinValues.datetime,
294
+ { bin_start: null, bin_end: null, count: 10 },
295
+ ]);
195
296
 
196
297
  expect(summary.spec).toMatchSnapshot();
197
298