@hexclave/dashboard-ui-components 1.0.36 → 1.0.38

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.
@@ -4,8 +4,8 @@ import * as class_variance_authority_types0 from "class-variance-authority/types
4
4
 
5
5
  //#region src/components/button.d.ts
6
6
  declare const designButtonVariants: (props?: ({
7
- variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "plain" | null | undefined;
8
- size?: "icon" | "default" | "sm" | "lg" | null | undefined;
7
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "plain" | null | undefined;
8
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
9
9
  } & class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  type DesignOriginalButtonProps = {
11
11
  asChild?: boolean;
@@ -36,8 +36,8 @@ declare const DesignButton: React.FC<{
36
36
  } & {
37
37
  asChild?: boolean;
38
38
  } & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
39
- variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "plain" | null | undefined;
40
- size?: "icon" | "default" | "sm" | "lg" | null | undefined;
39
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "plain" | null | undefined;
40
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
41
41
  } & class_variance_authority_types0.ClassProp) | undefined) => string> & {
42
42
  ref?: React.Ref<HTMLButtonElement> | undefined;
43
43
  }>;
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { DownloadSimpleIcon } from "@phosphor-icons/react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import React, { useCallback, useEffect, useMemo, useState } from "react";
5
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { DesignButton } from "../button.js";
7
7
  import { formatGridDate, resolveColumnValue } from "./state.js";
8
8
  import { DesignDialog } from "../dialog.js";
@@ -17,7 +17,7 @@ function DataGridExportDialog({ open, onOpenChange, rows, columns, exportFilenam
17
17
  const hasServerExport = exportOptions?.fetchRows != null;
18
18
  const resolvedFields = useMemo(() => exportOptions?.fields ?? buildColumnExportFields(columns), [exportOptions?.fields, columns]);
19
19
  const [format, setFormat] = useState("csv");
20
- const [scope, setScope] = useState("all");
20
+ const [scope, setScope] = useState(exportOptions?.defaultScope ?? "all");
21
21
  const [fields, setFields] = useState(resolvedFields);
22
22
  const [isExporting, setIsExporting] = useState(false);
23
23
  const [progress, setProgress] = useState(idleExportProgress);
@@ -25,6 +25,12 @@ function DataGridExportDialog({ open, onOpenChange, rows, columns, exportFilenam
25
25
  useEffect(() => {
26
26
  if (!isExporting) setFields(resolvedFields);
27
27
  }, [isExporting, resolvedFields]);
28
+ const defaultScope = exportOptions?.defaultScope ?? "all";
29
+ const wasOpenRef = useRef(false);
30
+ useEffect(() => {
31
+ if (open && !wasOpenRef.current) setScope(defaultScope);
32
+ wasOpenRef.current = open;
33
+ }, [open, defaultScope]);
28
34
  exportOptions?.entityName;
29
35
  const entityNamePlural = exportOptions?.entityNamePlural ?? "rows";
30
36
  const filenamePrefix = exportOptions?.filenamePrefix ?? exportFilename;
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid-export-dialog.js","names":[],"sources":["../../../../src/components/data-grid/data-grid-export-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { DownloadSimpleIcon } from \"@phosphor-icons/react\";\nimport React, { useCallback, useEffect, useMemo, useState } from \"react\";\n\nimport { DesignButton } from \"../button\";\nimport { DesignDialog } from \"../dialog\";\nimport { formatGridDate, resolveColumnValue } from \"./state\";\nimport type {\n DataGridColumnDef,\n DataGridExportField,\n DataGridExportFormat,\n DataGridExportOptions,\n DataGridExportScope,\n} from \"./types\";\n\ntype ExportProgress = {\n phase: \"idle\" | \"fetching\" | \"generating\" | \"complete\";\n fetched: number;\n};\n\ntype ExportCellValue = string | number | boolean | null | undefined;\ntype ExportTable = {\n csvHeaders: string[];\n jsonKeys: string[];\n rows: ExportCellValue[][];\n};\n\ntype DataGridExportDialogProps<TRow> = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n rows: readonly TRow[];\n columns: readonly DataGridColumnDef<TRow>[];\n exportFilename: string;\n exportOptions?: DataGridExportOptions<TRow>;\n};\n\nconst idleExportProgress: ExportProgress = {\n phase: \"idle\",\n fetched: 0,\n};\nconst exportCompletionDisplayMs = 800;\n\nexport function DataGridExportDialog<TRow>({\n open,\n onOpenChange,\n rows,\n columns,\n exportFilename,\n exportOptions,\n}: DataGridExportDialogProps<TRow>) {\n const hasServerExport = exportOptions?.fetchRows != null;\n const resolvedFields = useMemo(\n () => exportOptions?.fields ?? buildColumnExportFields(columns),\n [exportOptions?.fields, columns],\n );\n const [format, setFormat] = useState<DataGridExportFormat>(\"csv\");\n const [scope, setScope] = useState<DataGridExportScope>(\"all\");\n const [fields, setFields] = useState<readonly DataGridExportField<TRow>[]>(resolvedFields);\n const [isExporting, setIsExporting] = useState(false);\n const [progress, setProgress] = useState<ExportProgress>(idleExportProgress);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n useEffect(() => {\n if (!isExporting) {\n setFields(resolvedFields);\n }\n }, [isExporting, resolvedFields]);\n\n const entityName = exportOptions?.entityName ?? \"row\";\n const entityNamePlural = exportOptions?.entityNamePlural ?? \"rows\";\n const filenamePrefix = exportOptions?.filenamePrefix ?? exportFilename;\n const title = exportOptions?.title ?? \"Export data\";\n const description = exportOptions?.description ?? (\n hasServerExport\n ? \"Configure and download data from this table\"\n : \"Configure and download the rows currently loaded in this table\"\n );\n const allScopeLabel = exportOptions?.allScopeLabel ?? `Export all ${entityNamePlural} in the project`;\n const filteredScopeLabel = exportOptions?.filteredScopeLabel ?? `Export only filtered/searched ${entityNamePlural}`;\n const progressSubjectLabel = exportOptions?.progressSubjectLabel ?? entityNamePlural;\n const progressTitle = progress.phase === \"complete\" ? \"Export complete\" : `Exporting ${progressSubjectLabel}`;\n const fetchExportRows = exportOptions?.fetchRows;\n\n const closeDialog = useCallback(() => {\n onOpenChange(false);\n setErrorMessage(null);\n }, [onOpenChange]);\n\n const handleOpenChange = useCallback((nextOpen: boolean) => {\n if (isExporting && !nextOpen) {\n return;\n }\n if (nextOpen) {\n onOpenChange(true);\n } else {\n closeDialog();\n }\n }, [closeDialog, isExporting, onOpenChange]);\n\n const toggleField = useCallback((key: string) => {\n setFields((prev) =>\n prev.map((field) =>\n field.key === key ? { ...field, enabled: !field.enabled } : field\n )\n );\n }, []);\n\n const selectAllFields = useCallback(() => {\n setFields((prev) => prev.map((field) => ({ ...field, enabled: true })));\n }, []);\n\n const deselectAllFields = useCallback(() => {\n setFields((prev) => prev.map((field) => ({ ...field, enabled: false })));\n }, []);\n\n const fetchRows = useCallback(async () => {\n if (fetchExportRows != null) {\n return await fetchExportRows({\n scope,\n onProgress: (fetched) => setProgress({ phase: \"fetching\", fetched }),\n });\n }\n\n setProgress({ phase: \"fetching\", fetched: rows.length });\n return rows;\n }, [fetchExportRows, rows, scope]);\n\n const handleExport = async () => {\n const enabledFields = fields.filter((field) => field.enabled);\n if (enabledFields.length === 0) {\n setErrorMessage(\"Select at least one field to export.\");\n return;\n }\n\n setErrorMessage(null);\n setIsExporting(true);\n setProgress({ phase: \"fetching\", fetched: 0 });\n try {\n const exportRows = await fetchRows();\n\n if (exportRows.length === 0) {\n setErrorMessage(\n exportOptions?.emptyExportDescription\n ?? `There are no ${entityNamePlural} to export.`,\n );\n setIsExporting(false);\n setProgress(idleExportProgress);\n return;\n }\n\n setProgress({ phase: \"generating\", fetched: exportRows.length });\n const transformedData = buildExportTable(exportRows, enabledFields);\n\n if (format === \"csv\") {\n exportToCsv(transformedData, filenamePrefix);\n } else {\n exportToJson(transformedData, filenamePrefix);\n }\n\n setProgress({ phase: \"complete\", fetched: exportRows.length });\n await new Promise<void>((resolve) => setTimeout(resolve, exportCompletionDisplayMs));\n closeDialog();\n } catch {\n setErrorMessage(\"Something went wrong while exporting. Please try again.\");\n } finally {\n setIsExporting(false);\n setProgress(idleExportProgress);\n }\n };\n\n return (\n <DesignDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={isExporting ? progressTitle : title}\n description={isExporting ? `Preparing export for ${progressSubjectLabel}.` : description}\n size=\"2xl\"\n variant=\"plain\"\n headerClassName={isExporting ? \"sr-only\" : undefined}\n hideTopCloseButton={isExporting}\n >\n {isExporting ? (\n <ExportProgressContent\n progress={progress}\n format={format}\n subjectLabel={progressSubjectLabel}\n />\n ) : (\n <div className=\"space-y-6\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor={`${filenamePrefix}-export-format`}>\n Export Format\n </label>\n <select\n id={`${filenamePrefix}-export-format`}\n value={format}\n onChange={(event) => setFormat(event.currentTarget.value === \"json\" ? \"json\" : \"csv\")}\n className=\"h-9 w-full rounded-md border border-input bg-white px-3 text-sm dark:bg-background\"\n >\n <option value=\"csv\">CSV (Comma-separated values)</option>\n <option value=\"json\">JSON (JavaScript Object Notation)</option>\n </select>\n </div>\n\n {hasServerExport ? (\n <fieldset className=\"space-y-2\">\n <legend className=\"text-sm font-medium\">Export Scope</legend>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n name={`${filenamePrefix}-export-scope`}\n value=\"all\"\n checked={scope === \"all\"}\n onChange={() => setScope(\"all\")}\n />\n <span>{allScopeLabel}</span>\n </label>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n name={`${filenamePrefix}-export-scope`}\n value=\"filtered\"\n checked={scope === \"filtered\"}\n onChange={() => setScope(\"filtered\")}\n />\n <span>{filteredScopeLabel}</span>\n </label>\n </fieldset>\n ) : null}\n\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <label className=\"text-sm font-medium\">Fields to Export</label>\n <div className=\"flex gap-2\">\n <DesignButton type=\"button\" variant=\"ghost\" size=\"sm\" onClick={selectAllFields} className=\"h-7 text-xs\">\n Select All\n </DesignButton>\n <DesignButton type=\"button\" variant=\"ghost\" size=\"sm\" onClick={deselectAllFields} className=\"h-7 text-xs\">\n Deselect All\n </DesignButton>\n </div>\n </div>\n <div className=\"grid max-h-[300px] grid-cols-1 gap-3 overflow-y-auto rounded-lg border border-border p-4 sm:grid-cols-2\">\n {fields.map((field) => (\n <label key={field.key} className=\"flex cursor-pointer items-center gap-2 text-sm font-normal\">\n <input\n type=\"checkbox\"\n checked={field.enabled}\n onChange={() => toggleField(field.key)}\n />\n <span>{field.label}</span>\n </label>\n ))}\n </div>\n </div>\n\n {errorMessage != null ? (\n <div className=\"rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <div className=\"font-medium\">{exportOptions?.emptyExportTitle ?? \"Export unavailable\"}</div>\n <div>{errorMessage}</div>\n </div>\n ) : null}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <DesignButton variant=\"outline\" onClick={closeDialog}>\n Cancel\n </DesignButton>\n <DesignButton onClick={handleExport}>\n <DownloadSimpleIcon className=\"mr-2 h-4 w-4\" />\n Export {titleCase(entityNamePlural)}\n </DesignButton>\n </div>\n </div>\n )}\n </DesignDialog>\n );\n}\n\nfunction ExportProgressContent(props: {\n progress: ExportProgress;\n format: DataGridExportFormat;\n subjectLabel: string;\n}) {\n const { progress, format, subjectLabel } = props;\n const fileLabel = format.toUpperCase();\n const isComplete = progress.phase === \"complete\";\n const title = isComplete ? \"Export complete\" : `Exporting ${subjectLabel}`;\n const description = isComplete\n ? `Your ${fileLabel} is ready and the download should begin automatically.`\n : `Your ${fileLabel} is being prepared from matching ${subjectLabel}.`;\n const statusLabel = progress.phase === \"complete\"\n ? \"Download ready\"\n : progress.phase === \"generating\"\n ? `Preparing ${fileLabel}`\n : `Fetching ${subjectLabel}`;\n const countLabel = `${progress.fetched.toLocaleString()} ${isComplete ? \"exported\" : \"fetched\"}`;\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-1\">\n <h2 className=\"text-base font-semibold leading-snug\">{title}</h2>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border border-border bg-muted/35 p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-4 text-sm\">\n <span className=\"font-medium text-foreground\">{statusLabel}</span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {countLabel}\n </span>\n </div>\n <div className=\"relative h-2 overflow-hidden rounded-full bg-foreground/10\">\n {isComplete ? (\n <div className=\"h-full w-full rounded-full bg-emerald-500/80\" />\n ) : (\n <div className=\"data-grid-export-progress-shimmer absolute inset-y-0 left-0 w-2/5 rounded-full bg-gradient-to-r from-transparent via-foreground/65 to-transparent\" />\n )}\n </div>\n </div>\n\n <div className=\"rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200\">\n Do not reload this page until the export finishes. The download will start automatically.\n </div>\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <DesignButton variant=\"outline\" disabled>\n Cancel\n </DesignButton>\n </div>\n </div>\n );\n}\n\nfunction buildColumnExportFields<TRow>(\n columns: readonly DataGridColumnDef<TRow>[],\n): readonly DataGridExportField<TRow>[] {\n const fields: DataGridExportField<TRow>[] = [];\n\n for (const column of columns) {\n const label = typeof column.header === \"string\" ? column.header.trim() : column.id;\n if (label.length === 0) {\n continue;\n }\n\n fields.push({\n key: column.id,\n label,\n enabled: true,\n getValue: (row) => formatColumnExportValue(column, row),\n });\n }\n\n return fields;\n}\n\nfunction formatColumnExportValue<TRow>(\n column: DataGridColumnDef<TRow>,\n row: TRow,\n): unknown {\n const value = resolveColumnValue(column, row);\n if (column.formatValue != null) {\n return column.formatValue(value, row);\n }\n if (column.type === \"date\" || column.type === \"dateTime\") {\n return formatGridDate(value, \"absolute\", {\n parseValue: column.parseValue,\n dateFormat: column.dateFormat,\n }).display ?? \"\";\n }\n return value;\n}\n\nfunction buildExportTable<TRow>(\n rows: readonly TRow[],\n enabledFields: readonly DataGridExportField<TRow>[],\n): ExportTable {\n return {\n csvHeaders: enabledFields.map((field) => field.label),\n jsonKeys: buildJsonKeys(enabledFields),\n rows: rows.map((row) => enabledFields.map((field) => toExportCellValue(field.getValue(row)))),\n };\n}\n\nfunction buildJsonKeys<TRow>(\n fields: readonly DataGridExportField<TRow>[],\n): string[] {\n const labelCounts = new Map<string, number>();\n for (const field of fields) {\n labelCounts.set(field.label, (labelCounts.get(field.label) ?? 0) + 1);\n }\n\n const usedKeys = new Map<string, true>();\n const keys: string[] = [];\n for (const field of fields) {\n const baseKey = labelCounts.get(field.label) === 1 ? field.label : `${field.label} (${field.key})`;\n let key = baseKey;\n let suffix = 2;\n while (usedKeys.has(key)) {\n key = `${baseKey} ${suffix}`;\n suffix++;\n }\n usedKeys.set(key, true);\n keys.push(key);\n }\n\n return keys;\n}\n\nfunction toExportCellValue(value: unknown): ExportCellValue {\n if (value == null) {\n return \"\";\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === \"object\") {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\nfunction exportToCsv(data: ExportTable, filenamePrefix: string) {\n const csvContent = \"\\uFEFF\" + [\n data.csvHeaders.map(escapeCsvCell).join(\",\"),\n ...data.rows.map((row) => row.map(escapeCsvCell).join(\",\")),\n ].join(\"\\n\");\n downloadFile(csvContent, `${buildExportFilename(filenamePrefix)}.csv`, \"text/csv;charset=utf-8;\");\n}\n\nfunction escapeCsvCell(value: ExportCellValue): string {\n const rawText = String(value ?? \"\");\n const text = typeof value === \"string\" && /^[=+\\-@\\t\\r]/.test(rawText.trimStart()) ? `'${rawText}` : rawText;\n if (text.includes(\",\") || text.includes('\"') || text.includes(\"\\n\") || text.includes(\"\\r\")) {\n return `\"${text.replace(/\"/g, '\"\"')}\"`;\n }\n return text;\n}\n\nfunction exportToJson(data: ExportTable, filenamePrefix: string) {\n const rows = data.rows.map((row) => {\n const jsonRow: Record<string, ExportCellValue> = {};\n for (let i = 0; i < data.jsonKeys.length; i++) {\n jsonRow[data.jsonKeys[i]] = row[i] ?? \"\";\n }\n return jsonRow;\n });\n const jsonString = JSON.stringify(rows, null, 2);\n downloadFile(jsonString, `${buildExportFilename(filenamePrefix)}.json`, \"application/json\");\n}\n\nfunction downloadFile(content: string, filename: string, type: string) {\n const blob = new Blob([content], { type });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n try {\n link.click();\n } finally {\n link.remove();\n URL.revokeObjectURL(url);\n }\n}\n\nfunction buildExportFilename(prefix: string) {\n return `${prefix}-${new Date().toISOString().split(\"T\")[0]}`;\n}\n\nfunction titleCase(value: string) {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"data-grid-export-dialog.js","names":[],"sources":["../../../../src/components/data-grid/data-grid-export-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { DownloadSimpleIcon } from \"@phosphor-icons/react\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { DesignButton } from \"../button\";\nimport { DesignDialog } from \"../dialog\";\nimport { formatGridDate, resolveColumnValue } from \"./state\";\nimport type {\n DataGridColumnDef,\n DataGridExportField,\n DataGridExportFormat,\n DataGridExportOptions,\n DataGridExportScope,\n} from \"./types\";\n\ntype ExportProgress = {\n phase: \"idle\" | \"fetching\" | \"generating\" | \"complete\";\n fetched: number;\n};\n\ntype ExportCellValue = string | number | boolean | null | undefined;\ntype ExportTable = {\n csvHeaders: string[];\n jsonKeys: string[];\n rows: ExportCellValue[][];\n};\n\ntype DataGridExportDialogProps<TRow> = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n rows: readonly TRow[];\n columns: readonly DataGridColumnDef<TRow>[];\n exportFilename: string;\n exportOptions?: DataGridExportOptions<TRow>;\n};\n\nconst idleExportProgress: ExportProgress = {\n phase: \"idle\",\n fetched: 0,\n};\nconst exportCompletionDisplayMs = 800;\n\nexport function DataGridExportDialog<TRow>({\n open,\n onOpenChange,\n rows,\n columns,\n exportFilename,\n exportOptions,\n}: DataGridExportDialogProps<TRow>) {\n const hasServerExport = exportOptions?.fetchRows != null;\n const resolvedFields = useMemo(\n () => exportOptions?.fields ?? buildColumnExportFields(columns),\n [exportOptions?.fields, columns],\n );\n const [format, setFormat] = useState<DataGridExportFormat>(\"csv\");\n const [scope, setScope] = useState<DataGridExportScope>(exportOptions?.defaultScope ?? \"all\");\n const [fields, setFields] = useState<readonly DataGridExportField<TRow>[]>(resolvedFields);\n const [isExporting, setIsExporting] = useState(false);\n const [progress, setProgress] = useState<ExportProgress>(idleExportProgress);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n useEffect(() => {\n if (!isExporting) {\n setFields(resolvedFields);\n }\n }, [isExporting, resolvedFields]);\n\n // Reset the scope to its default each time the dialog opens. The dialog stays\n // mounted between opens, so without this the scope would retain whatever the\n // user last picked instead of honoring `defaultScope` on every open. We track\n // the previous `open` value with a ref so the reset only fires on a genuine\n // closed->open transition -- not on every render that flips other state (e.g.\n // `isExporting` going false after a failed/empty export would otherwise wipe\n // the user's current selection while the dialog is still open).\n const defaultScope = exportOptions?.defaultScope ?? \"all\";\n const wasOpenRef = useRef(false);\n useEffect(() => {\n if (open && !wasOpenRef.current) {\n setScope(defaultScope);\n }\n wasOpenRef.current = open;\n }, [open, defaultScope]);\n\n const entityName = exportOptions?.entityName ?? \"row\";\n const entityNamePlural = exportOptions?.entityNamePlural ?? \"rows\";\n const filenamePrefix = exportOptions?.filenamePrefix ?? exportFilename;\n const title = exportOptions?.title ?? \"Export data\";\n const description = exportOptions?.description ?? (\n hasServerExport\n ? \"Configure and download data from this table\"\n : \"Configure and download the rows currently loaded in this table\"\n );\n const allScopeLabel = exportOptions?.allScopeLabel ?? `Export all ${entityNamePlural} in the project`;\n const filteredScopeLabel = exportOptions?.filteredScopeLabel ?? `Export only filtered/searched ${entityNamePlural}`;\n const progressSubjectLabel = exportOptions?.progressSubjectLabel ?? entityNamePlural;\n const progressTitle = progress.phase === \"complete\" ? \"Export complete\" : `Exporting ${progressSubjectLabel}`;\n const fetchExportRows = exportOptions?.fetchRows;\n\n const closeDialog = useCallback(() => {\n onOpenChange(false);\n setErrorMessage(null);\n }, [onOpenChange]);\n\n const handleOpenChange = useCallback((nextOpen: boolean) => {\n if (isExporting && !nextOpen) {\n return;\n }\n if (nextOpen) {\n onOpenChange(true);\n } else {\n closeDialog();\n }\n }, [closeDialog, isExporting, onOpenChange]);\n\n const toggleField = useCallback((key: string) => {\n setFields((prev) =>\n prev.map((field) =>\n field.key === key ? { ...field, enabled: !field.enabled } : field\n )\n );\n }, []);\n\n const selectAllFields = useCallback(() => {\n setFields((prev) => prev.map((field) => ({ ...field, enabled: true })));\n }, []);\n\n const deselectAllFields = useCallback(() => {\n setFields((prev) => prev.map((field) => ({ ...field, enabled: false })));\n }, []);\n\n const fetchRows = useCallback(async () => {\n if (fetchExportRows != null) {\n return await fetchExportRows({\n scope,\n onProgress: (fetched) => setProgress({ phase: \"fetching\", fetched }),\n });\n }\n\n setProgress({ phase: \"fetching\", fetched: rows.length });\n return rows;\n }, [fetchExportRows, rows, scope]);\n\n const handleExport = async () => {\n const enabledFields = fields.filter((field) => field.enabled);\n if (enabledFields.length === 0) {\n setErrorMessage(\"Select at least one field to export.\");\n return;\n }\n\n setErrorMessage(null);\n setIsExporting(true);\n setProgress({ phase: \"fetching\", fetched: 0 });\n try {\n const exportRows = await fetchRows();\n\n if (exportRows.length === 0) {\n setErrorMessage(\n exportOptions?.emptyExportDescription\n ?? `There are no ${entityNamePlural} to export.`,\n );\n setIsExporting(false);\n setProgress(idleExportProgress);\n return;\n }\n\n setProgress({ phase: \"generating\", fetched: exportRows.length });\n const transformedData = buildExportTable(exportRows, enabledFields);\n\n if (format === \"csv\") {\n exportToCsv(transformedData, filenamePrefix);\n } else {\n exportToJson(transformedData, filenamePrefix);\n }\n\n setProgress({ phase: \"complete\", fetched: exportRows.length });\n await new Promise<void>((resolve) => setTimeout(resolve, exportCompletionDisplayMs));\n closeDialog();\n } catch {\n setErrorMessage(\"Something went wrong while exporting. Please try again.\");\n } finally {\n setIsExporting(false);\n setProgress(idleExportProgress);\n }\n };\n\n return (\n <DesignDialog\n open={open}\n onOpenChange={handleOpenChange}\n title={isExporting ? progressTitle : title}\n description={isExporting ? `Preparing export for ${progressSubjectLabel}.` : description}\n size=\"2xl\"\n variant=\"plain\"\n headerClassName={isExporting ? \"sr-only\" : undefined}\n hideTopCloseButton={isExporting}\n >\n {isExporting ? (\n <ExportProgressContent\n progress={progress}\n format={format}\n subjectLabel={progressSubjectLabel}\n />\n ) : (\n <div className=\"space-y-6\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor={`${filenamePrefix}-export-format`}>\n Export Format\n </label>\n <select\n id={`${filenamePrefix}-export-format`}\n value={format}\n onChange={(event) => setFormat(event.currentTarget.value === \"json\" ? \"json\" : \"csv\")}\n className=\"h-9 w-full rounded-md border border-input bg-white px-3 text-sm dark:bg-background\"\n >\n <option value=\"csv\">CSV (Comma-separated values)</option>\n <option value=\"json\">JSON (JavaScript Object Notation)</option>\n </select>\n </div>\n\n {hasServerExport ? (\n <fieldset className=\"space-y-2\">\n <legend className=\"text-sm font-medium\">Export Scope</legend>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n name={`${filenamePrefix}-export-scope`}\n value=\"all\"\n checked={scope === \"all\"}\n onChange={() => setScope(\"all\")}\n />\n <span>{allScopeLabel}</span>\n </label>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n name={`${filenamePrefix}-export-scope`}\n value=\"filtered\"\n checked={scope === \"filtered\"}\n onChange={() => setScope(\"filtered\")}\n />\n <span>{filteredScopeLabel}</span>\n </label>\n </fieldset>\n ) : null}\n\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <label className=\"text-sm font-medium\">Fields to Export</label>\n <div className=\"flex gap-2\">\n <DesignButton type=\"button\" variant=\"ghost\" size=\"sm\" onClick={selectAllFields} className=\"h-7 text-xs\">\n Select All\n </DesignButton>\n <DesignButton type=\"button\" variant=\"ghost\" size=\"sm\" onClick={deselectAllFields} className=\"h-7 text-xs\">\n Deselect All\n </DesignButton>\n </div>\n </div>\n <div className=\"grid max-h-[300px] grid-cols-1 gap-3 overflow-y-auto rounded-lg border border-border p-4 sm:grid-cols-2\">\n {fields.map((field) => (\n <label key={field.key} className=\"flex cursor-pointer items-center gap-2 text-sm font-normal\">\n <input\n type=\"checkbox\"\n checked={field.enabled}\n onChange={() => toggleField(field.key)}\n />\n <span>{field.label}</span>\n </label>\n ))}\n </div>\n </div>\n\n {errorMessage != null ? (\n <div className=\"rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <div className=\"font-medium\">{exportOptions?.emptyExportTitle ?? \"Export unavailable\"}</div>\n <div>{errorMessage}</div>\n </div>\n ) : null}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <DesignButton variant=\"outline\" onClick={closeDialog}>\n Cancel\n </DesignButton>\n <DesignButton onClick={handleExport}>\n <DownloadSimpleIcon className=\"mr-2 h-4 w-4\" />\n Export {titleCase(entityNamePlural)}\n </DesignButton>\n </div>\n </div>\n )}\n </DesignDialog>\n );\n}\n\nfunction ExportProgressContent(props: {\n progress: ExportProgress;\n format: DataGridExportFormat;\n subjectLabel: string;\n}) {\n const { progress, format, subjectLabel } = props;\n const fileLabel = format.toUpperCase();\n const isComplete = progress.phase === \"complete\";\n const title = isComplete ? \"Export complete\" : `Exporting ${subjectLabel}`;\n const description = isComplete\n ? `Your ${fileLabel} is ready and the download should begin automatically.`\n : `Your ${fileLabel} is being prepared from matching ${subjectLabel}.`;\n const statusLabel = progress.phase === \"complete\"\n ? \"Download ready\"\n : progress.phase === \"generating\"\n ? `Preparing ${fileLabel}`\n : `Fetching ${subjectLabel}`;\n const countLabel = `${progress.fetched.toLocaleString()} ${isComplete ? \"exported\" : \"fetched\"}`;\n\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-1\">\n <h2 className=\"text-base font-semibold leading-snug\">{title}</h2>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border border-border bg-muted/35 p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-4 text-sm\">\n <span className=\"font-medium text-foreground\">{statusLabel}</span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {countLabel}\n </span>\n </div>\n <div className=\"relative h-2 overflow-hidden rounded-full bg-foreground/10\">\n {isComplete ? (\n <div className=\"h-full w-full rounded-full bg-emerald-500/80\" />\n ) : (\n <div className=\"data-grid-export-progress-shimmer absolute inset-y-0 left-0 w-2/5 rounded-full bg-gradient-to-r from-transparent via-foreground/65 to-transparent\" />\n )}\n </div>\n </div>\n\n <div className=\"rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200\">\n Do not reload this page until the export finishes. The download will start automatically.\n </div>\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <DesignButton variant=\"outline\" disabled>\n Cancel\n </DesignButton>\n </div>\n </div>\n );\n}\n\nfunction buildColumnExportFields<TRow>(\n columns: readonly DataGridColumnDef<TRow>[],\n): readonly DataGridExportField<TRow>[] {\n const fields: DataGridExportField<TRow>[] = [];\n\n for (const column of columns) {\n const label = typeof column.header === \"string\" ? column.header.trim() : column.id;\n if (label.length === 0) {\n continue;\n }\n\n fields.push({\n key: column.id,\n label,\n enabled: true,\n getValue: (row) => formatColumnExportValue(column, row),\n });\n }\n\n return fields;\n}\n\nfunction formatColumnExportValue<TRow>(\n column: DataGridColumnDef<TRow>,\n row: TRow,\n): unknown {\n const value = resolveColumnValue(column, row);\n if (column.formatValue != null) {\n return column.formatValue(value, row);\n }\n if (column.type === \"date\" || column.type === \"dateTime\") {\n return formatGridDate(value, \"absolute\", {\n parseValue: column.parseValue,\n dateFormat: column.dateFormat,\n }).display ?? \"\";\n }\n return value;\n}\n\nfunction buildExportTable<TRow>(\n rows: readonly TRow[],\n enabledFields: readonly DataGridExportField<TRow>[],\n): ExportTable {\n return {\n csvHeaders: enabledFields.map((field) => field.label),\n jsonKeys: buildJsonKeys(enabledFields),\n rows: rows.map((row) => enabledFields.map((field) => toExportCellValue(field.getValue(row)))),\n };\n}\n\nfunction buildJsonKeys<TRow>(\n fields: readonly DataGridExportField<TRow>[],\n): string[] {\n const labelCounts = new Map<string, number>();\n for (const field of fields) {\n labelCounts.set(field.label, (labelCounts.get(field.label) ?? 0) + 1);\n }\n\n const usedKeys = new Map<string, true>();\n const keys: string[] = [];\n for (const field of fields) {\n const baseKey = labelCounts.get(field.label) === 1 ? field.label : `${field.label} (${field.key})`;\n let key = baseKey;\n let suffix = 2;\n while (usedKeys.has(key)) {\n key = `${baseKey} ${suffix}`;\n suffix++;\n }\n usedKeys.set(key, true);\n keys.push(key);\n }\n\n return keys;\n}\n\nfunction toExportCellValue(value: unknown): ExportCellValue {\n if (value == null) {\n return \"\";\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === \"object\") {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\nfunction exportToCsv(data: ExportTable, filenamePrefix: string) {\n const csvContent = \"\\uFEFF\" + [\n data.csvHeaders.map(escapeCsvCell).join(\",\"),\n ...data.rows.map((row) => row.map(escapeCsvCell).join(\",\")),\n ].join(\"\\n\");\n downloadFile(csvContent, `${buildExportFilename(filenamePrefix)}.csv`, \"text/csv;charset=utf-8;\");\n}\n\nfunction escapeCsvCell(value: ExportCellValue): string {\n const rawText = String(value ?? \"\");\n const text = typeof value === \"string\" && /^[=+\\-@\\t\\r]/.test(rawText.trimStart()) ? `'${rawText}` : rawText;\n if (text.includes(\",\") || text.includes('\"') || text.includes(\"\\n\") || text.includes(\"\\r\")) {\n return `\"${text.replace(/\"/g, '\"\"')}\"`;\n }\n return text;\n}\n\nfunction exportToJson(data: ExportTable, filenamePrefix: string) {\n const rows = data.rows.map((row) => {\n const jsonRow: Record<string, ExportCellValue> = {};\n for (let i = 0; i < data.jsonKeys.length; i++) {\n jsonRow[data.jsonKeys[i]] = row[i] ?? \"\";\n }\n return jsonRow;\n });\n const jsonString = JSON.stringify(rows, null, 2);\n downloadFile(jsonString, `${buildExportFilename(filenamePrefix)}.json`, \"application/json\");\n}\n\nfunction downloadFile(content: string, filename: string, type: string) {\n const blob = new Blob([content], { type });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n try {\n link.click();\n } finally {\n link.remove();\n URL.revokeObjectURL(url);\n }\n}\n\nfunction buildExportFilename(prefix: string) {\n return `${prefix}-${new Date().toISOString().split(\"T\")[0]}`;\n}\n\nfunction titleCase(value: string) {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n"],"mappings":"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"}
@@ -173,7 +173,8 @@ type DataGridExportOptions<TRow> = {
173
173
  emptyExportDescription?: string;
174
174
  allScopeLabel?: ReactNode;
175
175
  filteredScopeLabel?: ReactNode;
176
- progressSubjectLabel?: string;
176
+ progressSubjectLabel?: string; /** Which export scope is selected by default when the dialog opens. Defaults to `"all"`. */
177
+ defaultScope?: DataGridExportScope;
177
178
  };
178
179
  type DataGridCallbacks<TRow> = {
179
180
  onRowClick?: (row: TRow, rowId: RowId, event: React.MouseEvent) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/components/data-grid/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/components/data-grid/types.ts"],"mappings":";;;;;KAKY,KAAA;AAAA,KAGA,kBAAA;AAAA,KASA,mBAAA;AAAA,KAEA,iBAAA;;AAXZ;;KAgBY,mBAAA;;;AAPZ;KAYY,kBAAA;EACV,QAAA,IAAY,IAAA,EAAM,IAAA;EAClB,QAAA,IAAY,IAAA,EAAM,IAAA;AAAA;AAZpB;AAAA,KAgBY,mBAAA;EACV,GAAA,EAAK,IAAA;EACL,KAAA,EAAO,KAAA;EACP,QAAA;EACA,KAAA;EACA,QAAA;EACA,UAAA;EAjB6B;;AAK/B;EAgBE,WAAA,EAAa,mBAAA;AAAA;;KAIH,qBAAA;EACV,QAAA;EACA,SAAA,EAAW,iBAAA,CAAkB,IAAA;EAC7B,QAAA;EACA,SAAA;AAAA;;KAIU,iBAAA;EAtBA,yCAwBV,EAAA,UAxB6B;EA2B7B,MAAA,aAAmB,GAAA,EAAK,qBAAA,CAAsB,IAAA,MAAU,SAAA;EAzBjD;;EA6BP,QAAA,SAAiB,IAAA,KAAS,GAAA,EAAK,IAAA,eArBC;EAwBhC,UAAA,IAAc,GAAA,EAAK,mBAAA,CAAoB,IAAA,MAAU,SAAA,EAjCjD;EAqCA,KAAA,WApCA;EAsCA,QAAA,WArCA;EAuCA,QAAA;EArCA;;EAwCA,IAAA;EAGA,QAAA;EACA,SAAA;EACA,QAAA,YApCU;EAsCV,GAAA,GAAM,iBAAA;EAGN,KAAA,GAAQ,mBAAA,EAvCoB;EAyC5B,IAAA,GAAO,kBAAA,EA1CP;EA4CA,YAAA,YAAwB,oBAAA;EA3Cb;;;;;EAmDX,YAAA;EA7CU;;EAkDV,cAAA,IAAkB,CAAA,WAAY,CAAA;EA7CgB;;EAgD9C,WAAA,IAAe,KAAA,WAAgB,GAAA,EAAK,IAAA;EA5CnB;;;;EAmDjB,UAAA,IAAc,KAAA,cAAmB,IAAA,SA9B3B;EAgCN,UAAA,GAAa,kBAAA,EA3BN;EA+BP,WAAA,IAAe,GAAA,EAAK,mBAAA,CAAoB,IAAA,GAAO,KAAA,EAAO,KAAA,CAAM,UAAA,WAbxB;EAepC,iBAAA,IAAqB,GAAA,EAAK,mBAAA,CAAoB,IAAA,GAAO,KAAA,EAAO,KAAA,CAAM,UAAA;AAAA;AAAA,KAGxD,oBAAA;EACV,KAAA;EACA,KAAA;AAAA;AAAA,KAIU,gBAAA;EACV,QAAA;EACA,SAAA;AAAA;AAAA,KAEU,iBAAA,YAA6B,gBAAA;AAAA,KAG7B,qBAAA;AAAA,KAEA,sBAAA;EACV,WAAA,EAAa,WAAA,CAAY,KAAA,GAlFqB;EAoF9C,QAAA,EAAU,KAAA;AAAA;AAAA,KAIA,wBAAA,GAA2B,MAAA;AAAA,KAE3B,qBAAA;EACV,IAAA;EACA,KAAA;AAAA;;KAKU,sBAAA;;KAGA,0BAAA;AAAA,KAEA,uBAAA;EACV,SAAA;EACA,QAAA;AAAA;AAAA,KAIU,aAAA;EACV,OAAA,EAAS,iBAAA;EACT,gBAAA,EAAkB,wBAAA;EAClB,YAAA,EAAc,MAAA;EACd,aAAA,EAAe,qBAAA;EACf,WAAA;EACA,UAAA,EAAY,uBAAA;EACZ,SAAA,EAAW,sBAAA;EArFJ;;;EAyFP,WAAA,EAAa,mBAAA;EA1Eb;;;;;;EAiFA,WAAA;AAAA;;KAKU,mBAAA;EACV,OAAA,EAAS,iBAAA;EACT,UAAA,EAAY,uBAAA;EAxEZ;;;;EA6EA,WAAA,UA7E4D;EA+E5D,MAAA;AAAA;;KAIU,mBAAA;EACV,IAAA,EAAM,IAAA,IAlFsD;EAoF5D,aAAA,WApFqD;EAsFrD,UAAA,YAtF4E;EAwF5E,OAAA;AAAA;;;;KAMU,kBAAA,UACV,MAAA,EAAQ,mBAAA,KACL,cAAA,CAAe,mBAAA,CAAoB,IAAA;AAAA,KAG5B,oBAAA;AAAA,KAEA,mBAAA;AAAA,KAEA,mBAAA;EACV,GAAA;EACA,KAAA;EACA,OAAA;EACA,QAAA,GAAW,GAAA,EAAK,IAAA;AAAA;AAAA,KAGN,yBAAA;EACV,KAAA,EAAO,mBAAA;EACP,UAAA,GAAa,OAAA;AAAA;AAAA,KAGH,qBAAA;EACV,KAAA;EACA,WAAA,GAAc,SAAA;EACd,UAAA;EACA,gBAAA;EACA,cAAA;EACA,MAAA,YAAkB,mBAAA,CAAoB,IAAA;EACtC,SAAA,IAAa,OAAA,EAAS,yBAAA,KAA8B,OAAA,UAAiB,IAAA;EACrE,gBAAA;EACA,sBAAA;EACA,aAAA,GAAgB,SAAA;EAChB,kBAAA,GAAqB,SAAA;EACrB,oBAAA,WA1GA;EA4GA,YAAA,GAAe,mBAAA;AAAA;AAAA,KAIL,iBAAA;EACV,UAAA,IAAc,GAAA,EAAK,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,CAAM,UAAA;EACpD,gBAAA,IAAoB,GAAA,EAAK,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,CAAM,UAAA;EAC1D,WAAA,IAAe,GAAA,EAAK,IAAA,EAAM,QAAA,UAAkB,KAAA,WAAgB,KAAA,EAAO,KAAA,CAAM,UAAA;EA/GpC;;AAEvC;;;;;AAOA;EA+GE,iBAAA,IAAqB,WAAA,EAAa,WAAA,CAAY,KAAA,GAAQ,YAAA,EAAc,IAAA;EACpE,YAAA,IAAgB,KAAA,EAAO,iBAAA;EACvB,cAAA,IAAkB,QAAA,UAAkB,KAAA;EACpC,wBAAA,IAA4B,KAAA,EAAO,wBAAA;AAAA;AAAA,KAIzB,aAAA;4BAEV,OAAA,WAAkB,iBAAA,CAAkB,IAAA;EArHA;AAEtC;EAwHE,IAAA,WAAe,IAAA;EAEf,QAAA,GAAW,GAAA,EAAK,IAAA,KAAS,KAAA,EAxHjB;EA0HR,aAAA,WAtHuB;EAwHvB,SAAA,YAvHS;EAyHT,YAAA,YAvHc;EA2Hd,OAAA,YAxHY;EA0HZ,aAAA,YArHa;EAuHb,UAAA;EAGA,KAAA,EAAO,aAAA;EACP,QAAA,EAAU,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,cAAA,CAAe,aAAA;EArIrC;;;EA2IT,cAAA,6BAzIc;EA2Id,aAAA,GAAgB,qBAAA,EA1ID;EA4If,SAAA;EA1IA;;;;;;;;;AAiBF;EAsIE,SAAA;;;;;EAKA,kBAAA,WAzIY;EA2IZ,YAAA,WApIA;EAsIA,QAAA,WAtIM;EAwIN,SAAA;EApI6B;;;;;EA0I7B,UAAA,YAvIA;EAyIA,SAAA;AAAA,IAGE,iBAAA,CAAkB,IAAA;EAxIb,yEA2IP,OAAA,aAAoB,GAAA,EAAK,sBAAA,CAAuB,IAAA,MAAU,SAAA;EArIhD;;;;;EA2IV,YAAA,GAAe,SAAA,KAAc,GAAA,EAAK,sBAAA,CAAuB,IAAA,MAAU,SAAA,GAzIhE;EA2IH,UAAA,GAAa,SAAA,EA3II;EA6IjB,YAAA,GAAe,SAAA,EA9IP;EAgJR,MAAA,aAAmB,GAAA,EAAK,qBAAA,CAAsB,IAAA,MAAU,SAAA,GA/IrD;EAiJH,WAAA,GAAc,SAAA,KAAc,GAAA,EAAK,qBAAA,CAAsB,IAAA,MAAU,SAAA,GAjJ3B;EAoJtC,cAAA;EApJ0C;AAG5C;EAoJE,aAAA,GAAgB,qBAAA,CAAsB,IAAA;EAEtC,OAAA,GAAU,OAAA,CAAQ,eAAA;EAElB,SAAA;AAAA;AAAA,KAIU,sBAAA;EACV,KAAA,EAAO,aAAA;EACP,QAAA,EAAU,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,cAAA,CAAe,aAAA;EAC9C,OAAA,WAAkB,iBAAA,CAAkB,IAAA;EACpC,cAAA,WAAyB,iBAAA,CAAkB,IAAA;EAC3C,aAAA;EACA,gBAAA;EACA,OAAA,EAAS,eAAA,EA/JqB;EAiK9B,SAAA;AAAA;AAAA,KAGU,qBAAA;EACV,KAAA,EAAO,aAAA;EACP,aAAA;EACA,eAAA;EACA,gBAAA;EACA,cAAA,EAAgB,sBAAA;EAChB,OAAA,EAAS,eAAA;AAAA;AAAA,KAIC,eAAA;EAEV,iBAAA;EACA,OAAA;EACA,MAAA;EACA,OAAA;EAEA,OAAA;EACA,OAAA;EACA,YAAA;EAEA,UAAA;EACA,kBAAA;EACA,kBAAA;EAEA,YAAA,GAAe,KAAA;EAEf,WAAA;EACA,MAAA,GAAS,IAAA,UAAc,KAAA;EAEvB,MAAA;EACA,OAAA;EACA,WAAA;EAEA,SAAA;EACA,YAAA;EAEA,OAAA;EACA,QAAA;EACA,MAAA;EAEA,OAAA;EACA,QAAA;EACA,KAAA;EACA,UAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexclave/dashboard-ui-components",
3
- "version": "1.0.36",
3
+ "version": "1.0.38",
4
4
  "repository": "https://github.com/hexclave/hexclave",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -50,8 +50,8 @@
50
50
  "@tanstack/react-table": "^8.21.3",
51
51
  "@tanstack/react-virtual": "^3.13.0",
52
52
  "class-variance-authority": "^0.7.0",
53
- "@hexclave/ui": "1.0.36",
54
- "@hexclave/shared": "1.0.36"
53
+ "@hexclave/shared": "1.0.38",
54
+ "@hexclave/ui": "1.0.38"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/react": "^19.0.0",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { DownloadSimpleIcon } from "@phosphor-icons/react";
4
- import React, { useCallback, useEffect, useMemo, useState } from "react";
4
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
5
 
6
6
  import { DesignButton } from "../button";
7
7
  import { DesignDialog } from "../dialog";
@@ -55,7 +55,7 @@ export function DataGridExportDialog<TRow>({
55
55
  [exportOptions?.fields, columns],
56
56
  );
57
57
  const [format, setFormat] = useState<DataGridExportFormat>("csv");
58
- const [scope, setScope] = useState<DataGridExportScope>("all");
58
+ const [scope, setScope] = useState<DataGridExportScope>(exportOptions?.defaultScope ?? "all");
59
59
  const [fields, setFields] = useState<readonly DataGridExportField<TRow>[]>(resolvedFields);
60
60
  const [isExporting, setIsExporting] = useState(false);
61
61
  const [progress, setProgress] = useState<ExportProgress>(idleExportProgress);
@@ -67,6 +67,22 @@ export function DataGridExportDialog<TRow>({
67
67
  }
68
68
  }, [isExporting, resolvedFields]);
69
69
 
70
+ // Reset the scope to its default each time the dialog opens. The dialog stays
71
+ // mounted between opens, so without this the scope would retain whatever the
72
+ // user last picked instead of honoring `defaultScope` on every open. We track
73
+ // the previous `open` value with a ref so the reset only fires on a genuine
74
+ // closed->open transition -- not on every render that flips other state (e.g.
75
+ // `isExporting` going false after a failed/empty export would otherwise wipe
76
+ // the user's current selection while the dialog is still open).
77
+ const defaultScope = exportOptions?.defaultScope ?? "all";
78
+ const wasOpenRef = useRef(false);
79
+ useEffect(() => {
80
+ if (open && !wasOpenRef.current) {
81
+ setScope(defaultScope);
82
+ }
83
+ wasOpenRef.current = open;
84
+ }, [open, defaultScope]);
85
+
70
86
  const entityName = exportOptions?.entityName ?? "row";
71
87
  const entityNamePlural = exportOptions?.entityNamePlural ?? "rows";
72
88
  const filenamePrefix = exportOptions?.filenamePrefix ?? exportFilename;
@@ -251,6 +251,8 @@ export type DataGridExportOptions<TRow> = {
251
251
  allScopeLabel?: ReactNode;
252
252
  filteredScopeLabel?: ReactNode;
253
253
  progressSubjectLabel?: string;
254
+ /** Which export scope is selected by default when the dialog opens. Defaults to `"all"`. */
255
+ defaultScope?: DataGridExportScope;
254
256
  };
255
257
 
256
258
  // ─── Callbacks ───────────────────────────────────────────────────────