@marimo-team/islands 0.25.3-dev42 → 0.25.3-dev46
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/{ErrorBoundary-Bb_hjI-F.js → ErrorBoundary-BWVs0-U9.js} +1 -1
- package/dist/{code-visibility-BseAT0Di.js → code-visibility-Dnpf43An.js} +1 -1
- package/dist/{common--apjoMvk.js → common-C6wfOJsp.js} +66 -67
- package/dist/{data-grid-overlay-editor-C2eZGIzb.js → data-grid-overlay-editor-CPTzwTJV.js} +1 -1
- package/dist/{feedback-button-Cy7x7fiM.js → feedback-button-B-CAcq1F.js} +2 -2
- package/dist/{glide-data-editor-CYonCTY5.js → glide-data-editor-DOh16wcn.js} +3 -3
- package/dist/{globals-W7yeDcvx.js → globals-C9VhYRAQ.js} +1 -1
- package/dist/main.js +6 -6
- package/dist/{number-overlay-editor-_5SNWHjp.js → number-overlay-editor-DDSvabGl.js} +1 -1
- package/dist/{reveal-component-DV1u0Sl1.js → reveal-component-5Vf1xGy3.js} +2 -2
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/data-table/__tests__/export-actions.test.tsx +88 -0
- package/src/components/data-table/export-actions.tsx +71 -45
package/package.json
CHANGED
|
@@ -914,6 +914,94 @@ describe("ExportActions dialog", () => {
|
|
|
914
914
|
expect(within(dialog).queryByRole("group")).not.toBeInTheDocument();
|
|
915
915
|
});
|
|
916
916
|
|
|
917
|
+
it("describes format options with their description and current settings", async () => {
|
|
918
|
+
renderExportActions({
|
|
919
|
+
getExportMetadata: vi.fn().mockResolvedValue(geometryMetadata),
|
|
920
|
+
});
|
|
921
|
+
await openDialog();
|
|
922
|
+
await screen.findByRole("button", { name: "GeoParquet options" });
|
|
923
|
+
|
|
924
|
+
for (const [label, description] of [
|
|
925
|
+
["CSV", "Comma-separated values Comma · UTF-8"],
|
|
926
|
+
["TSV", "Best for Excel and Google Sheets UTF-8"],
|
|
927
|
+
["JSON", "Raw JSON data Escapes non-ASCII"],
|
|
928
|
+
["GeoParquet", "Parquet with geometry and CRS metadata location"],
|
|
929
|
+
["GeoJSON", "Geometry in longitude and latitude location"],
|
|
930
|
+
]) {
|
|
931
|
+
expect(
|
|
932
|
+
screen.getByRole("button", { name: `${label} options` }),
|
|
933
|
+
).toHaveAccessibleDescription(description);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const csvOptions = screen.getByRole("button", { name: "CSV options" });
|
|
937
|
+
fireEvent.click(csvOptions);
|
|
938
|
+
fireEvent.change(screen.getByRole("combobox", { name: "Delimiter" }), {
|
|
939
|
+
target: { value: ";" },
|
|
940
|
+
});
|
|
941
|
+
expect(csvOptions).toHaveAccessibleDescription(
|
|
942
|
+
"Comma-separated values Semicolon · UTF-8",
|
|
943
|
+
);
|
|
944
|
+
fireEvent.click(csvOptions);
|
|
945
|
+
expect(csvOptions).toHaveAccessibleDescription(
|
|
946
|
+
"Comma-separated values Semicolon · UTF-8",
|
|
947
|
+
);
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
it.each([
|
|
951
|
+
["CSV", "Comma-separated values"],
|
|
952
|
+
["TSV", "Best for Excel and Google Sheets"],
|
|
953
|
+
["JSON", "Raw JSON data"],
|
|
954
|
+
["GeoParquet", "Parquet with geometry and CRS metadata"],
|
|
955
|
+
["GeoJSON", "Geometry in longitude and latitude"],
|
|
956
|
+
])(
|
|
957
|
+
"toggles %s options from the row label and description",
|
|
958
|
+
async (label, description) => {
|
|
959
|
+
renderExportActions({
|
|
960
|
+
getExportMetadata: vi.fn().mockResolvedValue(geometryMetadata),
|
|
961
|
+
});
|
|
962
|
+
await openDialog();
|
|
963
|
+
const toggle = await screen.findByRole("button", {
|
|
964
|
+
name: `${label} options`,
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
fireEvent.click(screen.getByText(label));
|
|
968
|
+
expect(toggle).toHaveAttribute("aria-expanded", "true");
|
|
969
|
+
expect(
|
|
970
|
+
screen.getByRole("group", { name: `${label} options` }),
|
|
971
|
+
).toBeInTheDocument();
|
|
972
|
+
|
|
973
|
+
fireEvent.click(screen.getByText(description));
|
|
974
|
+
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
|
975
|
+
expect(
|
|
976
|
+
screen.queryByRole("group", { name: `${label} options` }),
|
|
977
|
+
).not.toBeInTheDocument();
|
|
978
|
+
},
|
|
979
|
+
);
|
|
980
|
+
|
|
981
|
+
it("keeps download and copy independent of row expansion", async () => {
|
|
982
|
+
vi.stubGlobal(
|
|
983
|
+
"fetch",
|
|
984
|
+
vi.fn().mockResolvedValue({
|
|
985
|
+
ok: true,
|
|
986
|
+
text: vi.fn().mockResolvedValue("name,value\n"),
|
|
987
|
+
}),
|
|
988
|
+
);
|
|
989
|
+
renderExportActions();
|
|
990
|
+
await openDialog();
|
|
991
|
+
const toggle = screen.getByRole("button", { name: "CSV options" });
|
|
992
|
+
|
|
993
|
+
fireEvent.click(screen.getByRole("button", { name: "Download CSV" }));
|
|
994
|
+
await waitFor(() => expect(downloadByURL).toHaveBeenCalled());
|
|
995
|
+
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
|
996
|
+
|
|
997
|
+
fireEvent.click(screen.getByText("CSV"));
|
|
998
|
+
fireEvent.click(screen.getByRole("button", { name: "Copy CSV" }));
|
|
999
|
+
expect(toggle).toHaveAttribute("aria-expanded", "true");
|
|
1000
|
+
await waitFor(() => {
|
|
1001
|
+
expect(copyToClipboard).toHaveBeenCalledWith("name,value\n");
|
|
1002
|
+
});
|
|
1003
|
+
});
|
|
1004
|
+
|
|
917
1005
|
it("sends only changed CSV options with a download", async () => {
|
|
918
1006
|
renderExportActions();
|
|
919
1007
|
await openDialog();
|
|
@@ -761,7 +761,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
761
761
|
const expanded =
|
|
762
762
|
configurableFormat !== null &&
|
|
763
763
|
expandedFormat === configurableFormat;
|
|
764
|
+
const FormatHeader = configurableFormat ? "button" : "div";
|
|
764
765
|
const panelId = `export-options-${option.format}`;
|
|
766
|
+
const descriptionId = `${panelId}-description`;
|
|
767
|
+
const summaryId = `${panelId}-summary`;
|
|
765
768
|
const rowFailure =
|
|
766
769
|
failure?.action.format === option.format ? failure : null;
|
|
767
770
|
const summary =
|
|
@@ -802,55 +805,78 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
802
805
|
data-testid={`export-row-${option.format}`}
|
|
803
806
|
className={cn(expanded && "bg-muted/40")}
|
|
804
807
|
>
|
|
805
|
-
<div className="grid
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
808
|
+
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-center hover:bg-accent/50">
|
|
809
|
+
<FormatHeader
|
|
810
|
+
type={configurableFormat ? "button" : undefined}
|
|
811
|
+
className={cn(
|
|
812
|
+
"grid min-h-[60px] min-w-0 grid-cols-[28px_minmax(0,1fr)] items-center gap-x-1 py-2 pl-2.5 pr-1 text-left",
|
|
813
|
+
configurableFormat &&
|
|
814
|
+
"cursor-pointer focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
|
|
815
|
+
)}
|
|
816
|
+
aria-label={
|
|
817
|
+
configurableFormat ? `${optionLabel} options` : undefined
|
|
818
|
+
}
|
|
819
|
+
aria-describedby={
|
|
820
|
+
configurableFormat
|
|
821
|
+
? [descriptionId, summary && summaryId]
|
|
822
|
+
.filter(Boolean)
|
|
823
|
+
.join(" ")
|
|
824
|
+
: undefined
|
|
825
|
+
}
|
|
826
|
+
aria-expanded={configurableFormat ? expanded : undefined}
|
|
827
|
+
aria-controls={configurableFormat ? panelId : undefined}
|
|
828
|
+
onClick={
|
|
829
|
+
configurableFormat
|
|
830
|
+
? () => toggleExpanded(option.format)
|
|
831
|
+
: undefined
|
|
832
|
+
}
|
|
833
|
+
>
|
|
834
|
+
<span
|
|
835
|
+
aria-hidden={true}
|
|
836
|
+
className="inline-flex h-6 w-6 items-center justify-center"
|
|
815
837
|
>
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
838
|
+
{configurableFormat && (
|
|
839
|
+
<ChevronRightIcon
|
|
840
|
+
className={cn(
|
|
841
|
+
"h-4 w-4 text-muted-foreground transition-transform",
|
|
842
|
+
expanded && "rotate-90",
|
|
843
|
+
)}
|
|
844
|
+
/>
|
|
845
|
+
)}
|
|
846
|
+
</span>
|
|
847
|
+
<span className="flex min-w-0 items-center gap-3 pl-1">
|
|
848
|
+
<option.icon
|
|
849
|
+
aria-hidden={true}
|
|
850
|
+
data-testid={`export-format-icon-${option.format}`}
|
|
851
|
+
className="h-4 w-4 shrink-0 text-muted-foreground"
|
|
821
852
|
/>
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
<div className="flex min-w-0 items-center gap-3 pl-1">
|
|
827
|
-
<option.icon
|
|
828
|
-
aria-hidden={true}
|
|
829
|
-
data-testid={`export-format-icon-${option.format}`}
|
|
830
|
-
className="h-4 w-4 shrink-0 text-muted-foreground"
|
|
831
|
-
/>
|
|
832
|
-
<div className="grid min-w-0 gap-1">
|
|
833
|
-
<span className="flex min-w-0 items-baseline gap-x-2">
|
|
834
|
-
<span className="text-sm font-medium leading-tight">
|
|
835
|
-
{optionLabel}
|
|
836
|
-
</span>
|
|
837
|
-
{summary && (
|
|
838
|
-
<span
|
|
839
|
-
data-testid={`export-summary-${option.format}`}
|
|
840
|
-
className="min-w-0 truncate text-xs text-muted-foreground"
|
|
841
|
-
>
|
|
842
|
-
{summary}
|
|
853
|
+
<span className="grid min-w-0 gap-1">
|
|
854
|
+
<span className="flex min-w-0 items-baseline gap-x-2">
|
|
855
|
+
<span className="text-sm font-medium leading-tight">
|
|
856
|
+
{optionLabel}
|
|
843
857
|
</span>
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
858
|
+
{summary && (
|
|
859
|
+
<span
|
|
860
|
+
id={summaryId}
|
|
861
|
+
data-testid={`export-summary-${option.format}`}
|
|
862
|
+
className="min-w-0 truncate text-xs text-muted-foreground"
|
|
863
|
+
>
|
|
864
|
+
{summary}
|
|
865
|
+
</span>
|
|
866
|
+
)}
|
|
867
|
+
</span>
|
|
868
|
+
<span
|
|
869
|
+
id={descriptionId}
|
|
870
|
+
className="text-xs text-muted-foreground leading-tight"
|
|
871
|
+
>
|
|
872
|
+
{option.format === "parquet" && hasGeometry
|
|
873
|
+
? "Parquet with geometry and CRS metadata"
|
|
874
|
+
: option.description}
|
|
875
|
+
</span>
|
|
850
876
|
</span>
|
|
851
|
-
</
|
|
852
|
-
</
|
|
853
|
-
<div className="flex items-center gap-0.5">
|
|
877
|
+
</span>
|
|
878
|
+
</FormatHeader>
|
|
879
|
+
<div className="flex items-center gap-0.5 pr-2.5">
|
|
854
880
|
<Tooltip
|
|
855
881
|
content={
|
|
856
882
|
option.canDownload
|