@pagamio/frontend-commons-lib 0.8.365 → 0.8.366
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.
|
@@ -31,7 +31,7 @@ const FilterComponent = ({ filters, selectedFilters, showApplyFilterButton = tru
|
|
|
31
31
|
resetFilters();
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
-
return (_jsxs(FilterWrapper, { isNarrow: isNarrow, children: [_jsxs("div", { className: "flex flex-1 flex-wrap items-center gap-2 min-w-0", children: [showSearch && (_jsxs("div", { className: "relative w-full sm:flex-1 sm:min-w-[200px] sm:max-w-[340px] min-w-0", children: [_jsx(IconSearch, { size: 16, className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: searctInputPlaceHolder, value: searchQuery, onChange: onSearch, onKeyDown: handleSearchKeyDown, "aria-label": "Search", className: cn('h-9 w-full rounded-md border border-border bg-background pl-9 pr-3 text-sm text-foreground', 'placeholder:text-muted-foreground', 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50') })] })), filters.map((filter) => {
|
|
34
|
+
return (_jsxs(FilterWrapper, { isNarrow: isNarrow, allowOverflowVisible: Boolean(children), children: [_jsxs("div", { className: "flex flex-1 flex-wrap items-center gap-2 min-w-0", children: [showSearch && (_jsxs("div", { className: "relative w-full sm:flex-1 sm:min-w-[200px] sm:max-w-[340px] min-w-0", children: [_jsx(IconSearch, { size: 16, className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { type: "text", placeholder: searctInputPlaceHolder, value: searchQuery, onChange: onSearch, onKeyDown: handleSearchKeyDown, "aria-label": "Search", className: cn('h-9 w-full rounded-md border border-border bg-background pl-9 pr-3 text-sm text-foreground', 'placeholder:text-muted-foreground', 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', 'disabled:cursor-not-allowed disabled:opacity-50') })] })), filters.map((filter) => {
|
|
35
35
|
const { name, type, options } = filter;
|
|
36
36
|
const value = selectedFilters[name];
|
|
37
37
|
const renderFilterInput = () => {
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
interface FilterWrapperProps {
|
|
3
3
|
isNarrow: boolean;
|
|
4
4
|
children: React.ReactNode;
|
|
5
|
+
allowOverflowVisible?: boolean;
|
|
5
6
|
}
|
|
6
|
-
declare const FilterWrapper: ({ isNarrow, children }: FilterWrapperProps) => React.JSX.Element;
|
|
7
|
+
declare const FilterWrapper: ({ isNarrow, children, allowOverflowVisible }: FilterWrapperProps) => React.JSX.Element;
|
|
7
8
|
export default FilterWrapper;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
const FilterWrapper = ({ isNarrow, children }) => {
|
|
2
|
+
const FilterWrapper = ({ isNarrow, children, allowOverflowVisible = false }) => {
|
|
3
3
|
return (
|
|
4
|
-
// `min-w-0` so this card can shrink inside a flex/grid parent
|
|
5
|
-
// `overflow-hidden` so
|
|
6
|
-
|
|
4
|
+
// `min-w-0` so this card can shrink inside a flex/grid parent.
|
|
5
|
+
// Most toolbars keep `overflow-hidden` so oversized rows do not punch out,
|
|
6
|
+
// but some controls (like export popovers) need to render beyond the card.
|
|
7
|
+
_jsx("div", { className: `bg-card shadow-xl rounded-lg p-4 mb-2 min-w-0 ${allowOverflowVisible ? 'overflow-visible' : 'overflow-hidden'}`, children: _jsx("div", { className: isNarrow
|
|
7
8
|
? 'flex flex-col w-full gap-3'
|
|
8
9
|
: // `flex-wrap` lets the filter pills drop onto a second row instead of
|
|
9
10
|
// overflowing the toolbar; each child group is set to `min-w-0` via its own
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Stack } from '@mantine/core';
|
|
3
3
|
import { Checkbox, Label, TextInput } from 'flowbite-react';
|
|
4
4
|
import { HiMail } from 'react-icons/hi';
|
|
5
5
|
import { useEffect, useRef, useState } from 'react';
|
|
6
|
-
|
|
7
|
-
// Modal handles its own open/close + backdrop click)
|
|
8
|
-
import { Modal, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components';
|
|
6
|
+
import { Button, Modal, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components';
|
|
9
7
|
import { exportToCsv, exportToPdf, exportToXlsx, generateExportAsFile, sendExportEmail } from './exportUtils';
|
|
10
8
|
const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, extraOptions = [], pdfOptions, xlsxOptions, csvOptions, exportAll = false, fetchData, asyncExport, enableEmailExport = false, emailExportApiUrl, onEmailExportSuccess, onEmailExportError, }) => {
|
|
11
9
|
const [exportType, setExportType] = useState(null);
|
|
@@ -19,10 +17,10 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
19
17
|
const [showEmailModal, setShowEmailModal] = useState(false);
|
|
20
18
|
const [pendingExportData, setPendingExportData] = useState(null);
|
|
21
19
|
const [pendingEmailFormat, setPendingEmailFormat] = useState(null);
|
|
22
|
-
const
|
|
20
|
+
const containerRef = useRef(null);
|
|
23
21
|
useEffect(() => {
|
|
24
22
|
const handleClickOutside = (event) => {
|
|
25
|
-
if (
|
|
23
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
26
24
|
setExportType(null);
|
|
27
25
|
}
|
|
28
26
|
};
|
|
@@ -181,30 +179,23 @@ const ExportDropdown = ({ data, columns, containerClassName, buttonClassName, ex
|
|
|
181
179
|
};
|
|
182
180
|
// Show popover when exportType is set and Select is closed
|
|
183
181
|
const popoverOpened = exportType !== null && !selectOpen;
|
|
184
|
-
const
|
|
182
|
+
const continueLabel = isExporting
|
|
185
183
|
? exportProgress && exportProgress.total > exportProgress.fetched
|
|
186
184
|
? `Fetching ${exportProgress.fetched}/${exportProgress.total}...`
|
|
187
185
|
: isEmailExport
|
|
188
186
|
? 'Preparing...'
|
|
189
187
|
: 'Exporting...'
|
|
190
188
|
: 'Continue';
|
|
191
|
-
return (_jsxs("div", { className: `w-40 ${containerClassName ?? ''}`, children: [_jsxs(Select, { value: exportType ?? 'none', open: selectOpen, onOpenChange: setSelectOpen, onValueChange: (value) => handleExportChange(value === 'none' ? null : value), children: [_jsx(SelectTrigger, { className: `w-full ${buttonClassName ?? ''}`, children: _jsx(SelectValue, { placeholder: "Export Data" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "none", children: _jsx("span", { className: "text-muted-foreground", children: "Export Data As" }) }, "reset"), exportOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))), extraOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value)))] })] }, "export-dropdown"), _jsxs(
|
|
192
|
-
|
|
193
|
-
onClick: handleContinue,
|
|
194
|
-
disabled: getIncludedColumns().length === 0 || isExporting,
|
|
195
|
-
loading: isExporting,
|
|
196
|
-
}, secondaryButton: {
|
|
197
|
-
label: 'Cancel',
|
|
198
|
-
onClick: () => setExportType(null),
|
|
199
|
-
disabled: isExporting,
|
|
200
|
-
variant: 'outline',
|
|
201
|
-
}, children: [_jsx("div", { className: "text-sm text-muted-foreground pb-3", children: "Uncheck to exclude column from export" }), _jsxs("div", { className: "mb-4 p-3 bg-muted rounded-md", children: [_jsxs("div", { className: "flex items-center gap-x-2", children: [_jsx(Checkbox, { id: "export-all-data", checked: exportAllData, onChange: (event) => setExportAllData(event.currentTarget.checked), className: "checked:!bg-primary checked:!border-primary-50" }), _jsx("label", { htmlFor: "export-all-data", className: "text-sm font-medium", children: "Export all data" })] }), _jsx("p", { className: "text-xs text-muted-foreground mt-1 ml-6", children: shouldQueueAsync
|
|
202
|
-
? 'This dataset is large - it will be prepared in the background and and appear in export history.'
|
|
189
|
+
return (_jsxs("div", { ref: containerRef, className: `relative w-40 ${containerClassName ?? ''}`, children: [_jsxs(Select, { value: exportType ?? 'none', open: selectOpen, onOpenChange: setSelectOpen, onValueChange: (value) => handleExportChange(value === 'none' ? null : value), children: [_jsx(SelectTrigger, { className: `w-full ${buttonClassName ?? ''}`, children: _jsx(SelectValue, { placeholder: "Export Data" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "none", children: _jsx("span", { className: "text-muted-foreground", children: "Export Data As" }) }, "reset"), exportOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))), extraOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value)))] })] }, "export-dropdown"), popoverOpened && (_jsxs("div", { className: "absolute left-0 top-full z-50 mt-2 w-64 rounded-md bg-background p-4 shadow-lg", children: [_jsx("div", { className: "pb-3 text-sm text-muted-foreground", children: "Uncheck to exclude column from export" }), _jsxs("div", { className: "mb-4 rounded-md bg-muted p-3", children: [_jsxs("div", { className: "flex items-center gap-x-2", children: [_jsx(Checkbox, { id: "export-all-data", checked: exportAllData, onChange: (event) => setExportAllData(event.currentTarget.checked), className: "checked:!bg-primary checked:!border-primary" }), _jsx(Label, { htmlFor: "export-all-data", className: "text-sm font-medium", children: "Export all data" })] }), _jsx("p", { className: "ml-6 mt-1 text-xs text-muted-foreground", children: shouldQueueAsync
|
|
190
|
+
? 'This dataset is large — it will be prepared in the background and appear in export history.'
|
|
203
191
|
: 'This will fetch all records for the table' })] }), _jsx(Stack, { children: columns.map((col) => {
|
|
204
192
|
if (col.accessorKey !== 'action') {
|
|
205
193
|
return (_jsxs("div", { className: "flex items-center gap-x-2", children: [_jsx(Checkbox, { id: col.accessorKey, checked: !excludedColumns.includes(col.accessorKey), onChange: (event) => handleCheckboxChange(col.accessorKey, !event.currentTarget.checked), className: "checked:!bg-primary checked:!border-primary" }), _jsx(Label, { htmlFor: col.accessorKey, children: col.header })] }, col.accessorKey));
|
|
206
194
|
}
|
|
207
|
-
|
|
195
|
+
return null;
|
|
196
|
+
}) }), _jsx(Button, { variant: "primary", className: `mt-4 flex w-full items-center justify-center rounded-md px-4 py-2 text-white ${getIncludedColumns().length === 0 || isExporting
|
|
197
|
+
? 'cursor-not-allowed bg-gray-300'
|
|
198
|
+
: 'bg-primary hover:bg-primary/90'}`, onClick: handleContinue, disabled: getIncludedColumns().length === 0 || isExporting, children: isExporting ? (_jsxs(_Fragment, { children: [_jsxs("svg", { className: "-ml-1 mr-2 h-4 w-4 animate-spin text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), continueLabel] })) : ('Continue') })] })), _jsx(Modal, { isOpen: showEmailModal, onClose: handleEmailModalClose, title: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(HiMail, { className: "w-5 h-5 text-primary" }), _jsx("span", { children: "Send Export via Email" })] }), size: "md", primaryButton: {
|
|
208
199
|
label: 'Send Email',
|
|
209
200
|
onClick: () => {
|
|
210
201
|
handleEmailModalSubmit().catch((error) => {
|
package/lib/styles.css
CHANGED
|
@@ -815,6 +815,9 @@ video {
|
|
|
815
815
|
.top-\[57\%\] {
|
|
816
816
|
top: 57%;
|
|
817
817
|
}
|
|
818
|
+
.top-full {
|
|
819
|
+
top: 100%;
|
|
820
|
+
}
|
|
818
821
|
.\!z-\[1000\] {
|
|
819
822
|
z-index: 1000 !important;
|
|
820
823
|
}
|
|
@@ -971,6 +974,9 @@ video {
|
|
|
971
974
|
.-mb-px {
|
|
972
975
|
margin-bottom: -1px;
|
|
973
976
|
}
|
|
977
|
+
.-ml-1 {
|
|
978
|
+
margin-left: -0.25rem;
|
|
979
|
+
}
|
|
974
980
|
.-mt-2 {
|
|
975
981
|
margin-top: -0.5rem;
|
|
976
982
|
}
|
|
@@ -1973,6 +1979,9 @@ video {
|
|
|
1973
1979
|
.overflow-hidden {
|
|
1974
1980
|
overflow: hidden;
|
|
1975
1981
|
}
|
|
1982
|
+
.overflow-visible {
|
|
1983
|
+
overflow: visible;
|
|
1984
|
+
}
|
|
1976
1985
|
.overflow-x-auto {
|
|
1977
1986
|
overflow-x: auto;
|
|
1978
1987
|
}
|
|
@@ -4254,10 +4263,6 @@ video {
|
|
|
4254
4263
|
.checked\:\!border-primary:checked {
|
|
4255
4264
|
border-color: hsl(var(--primary)) !important;
|
|
4256
4265
|
}
|
|
4257
|
-
.checked\:\!border-primary-50:checked {
|
|
4258
|
-
--tw-border-opacity: 1 !important;
|
|
4259
|
-
border-color: rgb(237 234 244 / var(--tw-border-opacity, 1)) !important;
|
|
4260
|
-
}
|
|
4261
4266
|
.checked\:border-transparent:checked {
|
|
4262
4267
|
border-color: transparent;
|
|
4263
4268
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagamio/frontend-commons-lib",
|
|
3
3
|
"description": "Pagamio library for Frontend reusable components like the form engine and table container",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.366",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"provenance": false
|