@marimo-team/islands 0.22.1-dev4 → 0.22.1-dev6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.22.1-dev4",
3
+ "version": "0.22.1-dev6",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -21,6 +21,7 @@ interface TableBottomBarProps<TData> {
21
21
  getRowIds?: GetRowIds;
22
22
  showPageSizeSelector?: boolean;
23
23
  tableLoading?: boolean;
24
+ part?: string;
24
25
  }
25
26
 
26
27
  export const TableBottomBar = <TData,>({
@@ -32,6 +33,7 @@ export const TableBottomBar = <TData,>({
32
33
  getRowIds,
33
34
  showPageSizeSelector,
34
35
  tableLoading,
36
+ part,
35
37
  }: TableBottomBarProps<TData>) => {
36
38
  const { locale } = useLocale();
37
39
  const handleSelectAllRows = (value: boolean) => {
@@ -143,7 +145,10 @@ export const TableBottomBar = <TData,>({
143
145
  };
144
146
 
145
147
  return (
146
- <div className="flex lg:grid lg:grid-cols-[1fr_auto_1fr] items-center shrink-0 pt-1">
148
+ <div
149
+ part={part}
150
+ className="flex lg:grid lg:grid-cols-[1fr_auto_1fr] items-center shrink-0 pt-1"
151
+ >
147
152
  <div className="flex flex-col text-sm text-muted-foreground px-2 shrink-0">
148
153
  <div className="flex items-center gap-1">{renderTotal()}</div>
149
154
  <CellSelectionStats table={table} className="lg:hidden" />
@@ -13,7 +13,7 @@ import {
13
13
  XIcon,
14
14
  } from "lucide-react";
15
15
  import type { JSX } from "react";
16
- import React, { useMemo, useState } from "react";
16
+ import React, { useMemo, useRef, useState } from "react";
17
17
  import { type UseFormReturn, useForm } from "react-hook-form";
18
18
  import useResizeObserver from "use-resize-observer";
19
19
  import { PythonIcon } from "@/components/editor/cell/code/icons";
@@ -61,6 +61,7 @@ export interface TablePanelProps {
61
61
  totalRows: number | TooManyRows;
62
62
  columns: number;
63
63
  displayHeader: boolean;
64
+ onCloseChartBuilder?: () => void;
64
65
  getDataUrl?: GetDataUrl;
65
66
  fieldTypes?: FieldTypesWithExternalType | null;
66
67
  }
@@ -74,12 +75,33 @@ export const TablePanel: React.FC<TablePanelProps> = ({
74
75
  getDataUrl,
75
76
  fieldTypes,
76
77
  displayHeader,
78
+ onCloseChartBuilder,
77
79
  }) => {
78
80
  const [tabsMap, saveTabsMap] = useAtom(tabsStorageAtom);
79
81
  const tabs = cellId ? (tabsMap.get(cellId) ?? []) : [];
80
82
 
81
- const [tabNum, setTabNum] = useState(0);
82
83
  const [selectedTab, setSelectedTab] = useState(DEFAULT_TAB_NAME);
84
+ const [tabCounter, setTabCounter] = useState(tabs.length);
85
+ const prevDisplayHeader = useRef(displayHeader);
86
+
87
+ // Auto-create a default chart tab when chart builder opens with no tabs
88
+ if (
89
+ displayHeader &&
90
+ !prevDisplayHeader.current &&
91
+ tabs.length === 0 &&
92
+ cellId
93
+ ) {
94
+ prevDisplayHeader.current = displayHeader;
95
+ const tabName = getChartTabName(0, NEW_CHART_TYPE);
96
+ const newTabs = new Map(tabsMap);
97
+ newTabs.set(cellId, [
98
+ { tabName, chartType: NEW_CHART_TYPE, config: getChartDefaults() },
99
+ ]);
100
+ saveTabsMap(newTabs);
101
+ setTabCounter(1);
102
+ setSelectedTab(tabName);
103
+ }
104
+ prevDisplayHeader.current = displayHeader;
83
105
 
84
106
  if (!displayHeader || (tabs.length === 0 && !displayHeader)) {
85
107
  return dataTable;
@@ -89,7 +111,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
89
111
  if (!cellId) {
90
112
  return;
91
113
  }
92
- const tabName = getChartTabName(tabNum, NEW_CHART_TYPE);
114
+ const tabName = getChartTabName(tabCounter, NEW_CHART_TYPE);
93
115
 
94
116
  const newTabs = new Map(tabsMap);
95
117
  newTabs.set(cellId, [
@@ -102,7 +124,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
102
124
  ]);
103
125
 
104
126
  saveTabsMap(newTabs);
105
- setTabNum(tabNum + 1);
127
+ setTabCounter(tabCounter + 1);
106
128
  setSelectedTab(tabName);
107
129
  };
108
130
 
@@ -110,14 +132,21 @@ export const TablePanel: React.FC<TablePanelProps> = ({
110
132
  if (!cellId) {
111
133
  return;
112
134
  }
135
+ const deletedIndex = tabs.findIndex((tab) => tab.tabName === tabName);
136
+ const remaining = tabs.filter((tab) => tab.tabName !== tabName);
113
137
  const newTabs = new Map(tabsMap);
114
- newTabs.set(
115
- cellId,
116
- tabs.filter((tab) => tab.tabName !== tabName),
117
- );
138
+ newTabs.set(cellId, remaining);
118
139
  saveTabsMap(newTabs);
119
- setSelectedTab(DEFAULT_TAB_NAME);
120
- setTabNum(tabNum - 1);
140
+
141
+ if (remaining.length === 0) {
142
+ onCloseChartBuilder?.();
143
+ } else if (tabName === selectedTab) {
144
+ if (deletedIndex < remaining.length) {
145
+ setSelectedTab(remaining[deletedIndex].tabName);
146
+ } else {
147
+ setSelectedTab(remaining[remaining.length - 1].tabName);
148
+ }
149
+ }
121
150
  };
122
151
 
123
152
  const saveTabChart = ({
@@ -178,7 +207,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
178
207
 
179
208
  return (
180
209
  <Tabs value={selectedTab} className="-mt-1">
181
- <TabsList>
210
+ <TabsList part="table-tabs">
182
211
  <TabsTrigger
183
212
  className="text-xs"
184
213
  value={DEFAULT_TAB_NAME}
@@ -283,7 +283,10 @@ const DataTableInternal = <TData,>({
283
283
  <div className={cn(wrapperClassName, "flex flex-col space-y-1")}>
284
284
  <FilterPills filters={filters} table={table} />
285
285
  <CellSelectionProvider>
286
- <div className={cn(className || "rounded-md border overflow-hidden")}>
286
+ <div
287
+ part="table-wrapper"
288
+ className={cn(className || "rounded-md border overflow-hidden")}
289
+ >
287
290
  <TableTopBar
288
291
  enableSearch={enableSearch}
289
292
  searchQuery={searchQuery}
@@ -313,6 +316,7 @@ const DataTableInternal = <TData,>({
313
316
  </Table>
314
317
  </div>
315
318
  <TableBottomBar
319
+ part="table-footer"
316
320
  totalColumns={totalColumns}
317
321
  pagination={pagination}
318
322
  selection={selection}
@@ -24,7 +24,10 @@ export const LoadingTable = ({
24
24
 
25
25
  return (
26
26
  <div className={cn(wrapperClassName, "flex flex-col space-y-2")}>
27
- <div className={cn(className || "rounded-md border")}>
27
+ <div
28
+ part="table-wrapper"
29
+ className={cn(className || "rounded-md border")}
30
+ >
28
31
  <Table>
29
32
  <TableHeader>
30
33
  {Array.from({ length: 1 }).map((_, i) => (
@@ -98,9 +98,30 @@
98
98
 
99
99
  /* Special case for particular components */
100
100
 
101
- .output-area:has(> .output > marimo-ui-element > marimo-table) {
101
+ .output-area:has(
102
+ > .output:only-child > marimo-ui-element:only-child > marimo-table
103
+ ) {
104
+ padding: 0 0 5px;
102
105
  max-height: none;
103
106
  overflow: hidden;
107
+
108
+ /* Flush table: remove border and configure edge padding via CSS variable */
109
+ --marimo-table-edge-padding: 0.75rem;
110
+
111
+ marimo-table::part(table-tabs) {
112
+ margin-top: 0.25rem;
113
+ border: none;
114
+ border-radius: 0;
115
+ }
116
+
117
+ marimo-table::part(table-wrapper) {
118
+ border: none;
119
+ border-radius: 0;
120
+ }
121
+
122
+ marimo-table::part(table-footer) {
123
+ padding-inline: 0.25rem;
124
+ }
104
125
  }
105
126
 
106
127
  & > :first-child {
package/src/css/table.css CHANGED
@@ -1,5 +1,22 @@
1
1
  @reference "../css/globals.css";
2
2
 
3
+ /* Edge padding for flush tables (--marimo-table-edge-padding inherits through shadow DOM) */
4
+ [part="table-wrapper"] th:first-child {
5
+ padding-left: var(--marimo-table-edge-padding, 0.5rem);
6
+ }
7
+
8
+ [part="table-wrapper"] th:last-child {
9
+ padding-right: var(--marimo-table-edge-padding, 0.5rem);
10
+ }
11
+
12
+ [part="table-wrapper"] td:first-child {
13
+ padding-left: var(--marimo-table-edge-padding, 0.375rem);
14
+ }
15
+
16
+ [part="table-wrapper"] td:last-child {
17
+ padding-right: var(--marimo-table-edge-padding, 0.375rem);
18
+ }
19
+
3
20
  .markdown table,
4
21
  table.dataframe {
5
22
  display: block;
@@ -763,6 +763,7 @@ export const LoadingDataTableComponent = memo(
763
763
  {props.showChartBuilder ? (
764
764
  <TablePanel
765
765
  displayHeader={displayHeader}
766
+ onCloseChartBuilder={() => setDisplayHeader(false)}
766
767
  data={data?.rows || []}
767
768
  columns={props.totalColumns}
768
769
  totalRows={props.totalRows}