@papernote/ui 1.1.0 → 1.2.0

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.
Files changed (75) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +455 -455
  3. package/dist/components/CurrencyInput.d.ts +52 -0
  4. package/dist/components/CurrencyInput.d.ts.map +1 -0
  5. package/dist/components/DataTable.d.ts +3 -1
  6. package/dist/components/DataTable.d.ts.map +1 -1
  7. package/dist/components/Modal.d.ts.map +1 -1
  8. package/dist/components/Page.d.ts +2 -0
  9. package/dist/components/Page.d.ts.map +1 -1
  10. package/dist/components/PageLayout.d.ts +5 -1
  11. package/dist/components/PageLayout.d.ts.map +1 -1
  12. package/dist/components/index.d.ts +4 -0
  13. package/dist/components/index.d.ts.map +1 -1
  14. package/dist/index.d.ts +204 -4
  15. package/dist/index.esm.js +415 -88
  16. package/dist/index.esm.js.map +1 -1
  17. package/dist/index.js +413 -82
  18. package/dist/index.js.map +1 -1
  19. package/dist/styles.css +2877 -2675
  20. package/dist/utils/excelExport.d.ts +143 -0
  21. package/dist/utils/excelExport.d.ts.map +1 -0
  22. package/dist/utils/index.d.ts +2 -0
  23. package/dist/utils/index.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/AdminModal.css +49 -49
  26. package/src/components/CurrencyInput.stories.tsx +290 -0
  27. package/src/components/CurrencyInput.tsx +193 -0
  28. package/src/components/DataTable.tsx +78 -14
  29. package/src/components/Modal.stories.tsx +64 -0
  30. package/src/components/Modal.tsx +15 -2
  31. package/src/components/Page.stories.tsx +76 -0
  32. package/src/components/Page.tsx +35 -3
  33. package/src/components/PageLayout.stories.tsx +75 -0
  34. package/src/components/PageLayout.tsx +28 -9
  35. package/src/components/RoleManager.css +10 -10
  36. package/src/components/Spreadsheet.css +216 -216
  37. package/src/components/Spreadsheet.stories.tsx +362 -362
  38. package/src/components/Spreadsheet.tsx +351 -351
  39. package/src/components/SpreadsheetSimple.stories.tsx +27 -27
  40. package/src/components/Tabs.tsx +152 -152
  41. package/src/components/index.ts +5 -0
  42. package/src/styles/index.css +41 -4
  43. package/src/utils/excelExport.stories.tsx +535 -0
  44. package/src/utils/excelExport.ts +225 -0
  45. package/src/utils/index.ts +3 -0
  46. package/tailwind.config.js +253 -253
  47. package/dist/components/Button.stories.d.ts +0 -51
  48. package/dist/components/Button.stories.d.ts.map +0 -1
  49. package/dist/components/ChartVisualizationUI.d.ts +0 -21
  50. package/dist/components/ChartVisualizationUI.d.ts.map +0 -1
  51. package/dist/components/ChatUI.d.ts +0 -23
  52. package/dist/components/ChatUI.d.ts.map +0 -1
  53. package/dist/components/CommissionDashboardUI.d.ts +0 -25
  54. package/dist/components/CommissionDashboardUI.d.ts.map +0 -1
  55. package/dist/components/DataTable.stories.d.ts +0 -23
  56. package/dist/components/DataTable.stories.d.ts.map +0 -1
  57. package/dist/components/FormField.d.ts +0 -35
  58. package/dist/components/FormField.d.ts.map +0 -1
  59. package/dist/components/Input.stories.d.ts +0 -366
  60. package/dist/components/Input.stories.d.ts.map +0 -1
  61. package/dist/components/InsightsPanelUI.d.ts +0 -21
  62. package/dist/components/InsightsPanelUI.d.ts.map +0 -1
  63. package/dist/components/PaymentHistoryTimeline.d.ts +0 -34
  64. package/dist/components/PaymentHistoryTimeline.d.ts.map +0 -1
  65. package/dist/components/RelationshipManagerUI.d.ts +0 -60
  66. package/dist/components/RelationshipManagerUI.d.ts.map +0 -1
  67. package/dist/components/RoleManager.d.ts +0 -19
  68. package/dist/components/RoleManager.d.ts.map +0 -1
  69. package/dist/components/SplitCommissionBadge.d.ts +0 -18
  70. package/dist/components/SplitCommissionBadge.d.ts.map +0 -1
  71. package/dist/components/Spreadsheet.css +0 -216
  72. package/dist/components/__tests__/Button.test.d.ts +0 -2
  73. package/dist/components/__tests__/Button.test.d.ts.map +0 -1
  74. package/dist/components/__tests__/Input.test.d.ts +0 -2
  75. package/dist/components/__tests__/Input.test.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -2550,6 +2550,7 @@ const sizeClasses$4 = {
2550
2550
  };
2551
2551
  function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton = true, animation = 'scale', }) {
2552
2552
  const modalRef = React.useRef(null);
2553
+ const mouseDownOnBackdrop = React.useRef(false);
2553
2554
  const titleId = React.useId();
2554
2555
  // Handle escape key
2555
2556
  React.useEffect(() => {
@@ -2567,11 +2568,22 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
2567
2568
  document.body.style.overflow = 'unset';
2568
2569
  };
2569
2570
  }, [isOpen, onClose]);
2570
- // Handle click outside
2571
- const handleBackdropClick = (e) => {
2571
+ // Track if mousedown originated on the backdrop
2572
+ const handleBackdropMouseDown = (e) => {
2572
2573
  if (e.target === e.currentTarget) {
2574
+ mouseDownOnBackdrop.current = true;
2575
+ }
2576
+ else {
2577
+ mouseDownOnBackdrop.current = false;
2578
+ }
2579
+ };
2580
+ // Handle click outside - only close if both mousedown and click happened on backdrop
2581
+ const handleBackdropClick = (e) => {
2582
+ if (e.target === e.currentTarget && mouseDownOnBackdrop.current) {
2573
2583
  onClose();
2574
2584
  }
2585
+ // Reset the flag after handling click
2586
+ mouseDownOnBackdrop.current = false;
2575
2587
  };
2576
2588
  const getAnimationClass = () => {
2577
2589
  switch (animation) {
@@ -2591,7 +2603,7 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
2591
2603
  };
2592
2604
  if (!isOpen)
2593
2605
  return null;
2594
- return (jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onClick: handleBackdropClick, children: jsxRuntime.jsxs("div", { ref: modalRef, className: `${sizeClasses$4[size]} w-full bg-white bg-subtle-grain rounded-xl shadow-2xl border border-paper-200 ${getAnimationClass()}`, role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsxRuntime.jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsxRuntime.jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) }))] }), jsxRuntime.jsx("div", { className: "px-6 py-4", children: children })] }) }));
2606
+ return (jsxRuntime.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onMouseDown: handleBackdropMouseDown, onClick: handleBackdropClick, children: jsxRuntime.jsxs("div", { ref: modalRef, className: `${sizeClasses$4[size]} w-full bg-white bg-subtle-grain rounded-xl shadow-2xl border border-paper-200 ${getAnimationClass()}`, role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsxRuntime.jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsxRuntime.jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) }))] }), jsxRuntime.jsx("div", { className: "px-6 py-4", children: children })] }) }));
2595
2607
  }
2596
2608
  function ModalFooter({ children }) {
2597
2609
  return (jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-3 px-6 py-4 border-t border-paper-200 bg-paper-50", children: children }));
@@ -5976,19 +5988,19 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
5976
5988
  spacing: orientation === 'vertical' ? 'mt-8' : 'mt-8',
5977
5989
  },
5978
5990
  };
5979
- return (jsxRuntime.jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsxRuntime.jsx("div", { className: `
5980
- flex ${orientation === 'vertical' ? 'flex-col' : ''}
5991
+ return (jsxRuntime.jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsxRuntime.jsx("div", { className: `
5992
+ flex ${orientation === 'vertical' ? 'flex-col' : ''}
5981
5993
  ${variant === 'underline'
5982
5994
  ? orientation === 'vertical'
5983
5995
  ? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
5984
5996
  : `border-b border-paper-200 ${sizeClasses[size].gap}`
5985
- : `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
5986
- ${sizeClasses[size].minWidth}
5997
+ : `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
5998
+ ${sizeClasses[size].minWidth}
5987
5999
  `, role: "tablist", children: tabs.map((tab) => {
5988
6000
  const isActive = activeTab === tab.id;
5989
- return (jsxRuntime.jsxs("button", { role: "tab", "aria-selected": isActive, "aria-controls": `panel-${tab.id}`, disabled: tab.disabled, onClick: () => !tab.disabled && handleTabChange(tab.id), className: `
5990
- flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
5991
- ${orientation === 'vertical' ? 'w-full justify-start' : ''}
6001
+ return (jsxRuntime.jsxs("button", { role: "tab", "aria-selected": isActive, "aria-controls": `panel-${tab.id}`, disabled: tab.disabled, onClick: () => !tab.disabled && handleTabChange(tab.id), className: `
6002
+ flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
6003
+ ${orientation === 'vertical' ? 'w-full justify-start' : ''}
5992
6004
  ${variant === 'underline'
5993
6005
  ? isActive
5994
6006
  ? orientation === 'vertical'
@@ -5999,8 +6011,8 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
5999
6011
  : 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
6000
6012
  : isActive
6001
6013
  ? 'bg-white text-accent-900 rounded-md shadow-xs'
6002
- : 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
6003
- ${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
6014
+ : 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
6015
+ ${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
6004
6016
  `, children: [tab.icon && jsxRuntime.jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: tab.icon }), jsxRuntime.jsx("span", { children: tab.label })] }, tab.id));
6005
6017
  }) }), jsxRuntime.jsx("div", { className: `${orientation === 'vertical' ? 'flex-1' : sizeClasses[size].spacing}`, children: tabs.map((tab) => (jsxRuntime.jsx("div", { id: `panel-${tab.id}`, role: "tabpanel", "aria-labelledby": tab.id, hidden: activeTab !== tab.id, className: activeTab === tab.id ? 'animate-fade-in' : '', children: activeTab === tab.id && tab.content }, tab.id))) })] }));
6006
6018
  }
@@ -6928,8 +6940,35 @@ const TwoColumnContent = ({ sidebar, children, className = '', }) => {
6928
6940
  * </PageLayout>
6929
6941
  * ```
6930
6942
  */
6931
- const Page = ({ children, maxWidth: _maxWidth = '7xl', className = '', padding: _padding = 'normal' }) => {
6932
- return (jsxRuntime.jsx("div", { className: "min-h-screen bg-paper-100", children: jsxRuntime.jsx("div", { className: `notebook-page notebook-margin notebook-ruled ${className}`, children: children }) }));
6943
+ const Page = ({ children, maxWidth = '7xl', className = '', padding = 'normal', fixed = false }) => {
6944
+ // Max width classes
6945
+ const maxWidthClasses = {
6946
+ '4xl': 'max-w-4xl',
6947
+ '5xl': 'max-w-5xl',
6948
+ '6xl': 'max-w-6xl',
6949
+ '7xl': 'max-w-7xl',
6950
+ 'full': 'max-w-full',
6951
+ };
6952
+ // Padding classes - responsive (fixed left/top, responsive right/bottom) vs all fixed
6953
+ const paddingClasses = {
6954
+ none: fixed ? 'p-0' : 'pt-0 pl-0 pr-0 pb-0',
6955
+ sm: fixed ? 'p-4' : 'pt-4 pl-4 pr-4 pb-4 sm:pr-6 md:pr-8 sm:pb-6 md:pb-8',
6956
+ normal: fixed ? 'pt-12 pl-20 pr-16 pb-12' : 'pt-12 pl-20 pr-4 pb-4 sm:pr-8 md:pr-12 lg:pr-16 sm:pb-8 md:pb-12 lg:pb-16',
6957
+ lg: fixed ? 'pt-16 pl-24 pr-20 pb-16' : 'pt-16 pl-24 pr-6 pb-6 sm:pr-12 md:pr-16 lg:pr-20 sm:pb-12 md:pb-16 lg:pb-20',
6958
+ };
6959
+ // Margin classes - responsive (fixed left/top, responsive right/bottom) vs all fixed
6960
+ const marginClasses = fixed
6961
+ ? 'mt-4 ml-4 mr-4 mb-4'
6962
+ : 'mt-4 ml-4 mr-4 mb-4 sm:mr-6 md:mr-8 lg:mr-auto sm:mb-6 md:mb-8';
6963
+ return (jsxRuntime.jsx("div", { className: "min-h-screen bg-paper-100", children: jsxRuntime.jsx("div", { className: `
6964
+ bg-white bg-subtle-grain rounded-sm shadow-lg border-l-4 border-paper-300
6965
+ min-h-[calc(100vh-2rem)] relative
6966
+ notebook-margin notebook-ruled
6967
+ ${maxWidthClasses[maxWidth]}
6968
+ ${paddingClasses[padding]}
6969
+ ${marginClasses}
6970
+ ${className}
6971
+ `.trim().replace(/\s+/g, ' '), children: children }) }));
6933
6972
  };
6934
6973
 
6935
6974
  /**
@@ -7264,7 +7303,7 @@ function getColumnStyle(column, dynamicWidth) {
7264
7303
  * />
7265
7304
  * ```
7266
7305
  */
7267
- function DataTable({ data, columns, loading = false, error = null, emptyMessage = 'No data available', loadingRows = 5, className = '', onSortChange, currentSort = null, onEdit, onDelete, actions = [], onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
7306
+ function DataTable({ data, columns, loading = false, error = null, emptyMessage = 'No data available', loadingRows = 5, className = '', onSortChange, currentSort = null, onEdit, onDelete, actions = [], enableContextMenu = true, onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
7268
7307
  // Visual customization props
7269
7308
  striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, highlightedRowId, bordered = false, borderColor = 'border-paper-200', disableHover = false, hiddenColumns = [], headerClassName = '', renderEmptyState: customRenderEmptyState, resizable = false, onColumnResize, reorderable = false, onColumnReorder, virtualized = false, virtualHeight = '600px', virtualRowHeight = 60, }) {
7270
7309
  // Column resizing state
@@ -7281,6 +7320,12 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
7281
7320
  const tableContainerRef = React.useRef(null);
7282
7321
  // Row hover state (for coordinating primary + secondary row highlighting)
7283
7322
  const [hoveredRowKey, setHoveredRowKey] = React.useState(null);
7323
+ // Context menu state
7324
+ const [contextMenuState, setContextMenuState] = React.useState({
7325
+ isOpen: false,
7326
+ position: { x: 0, y: 0 },
7327
+ item: null,
7328
+ });
7284
7329
  // Filter columns based on hiddenColumns
7285
7330
  const baseVisibleColumns = columns.filter(col => !hiddenColumns.includes(String(col.key)));
7286
7331
  // Initialize column order on mount or when columns change
@@ -7503,6 +7548,28 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
7503
7548
  });
7504
7549
  }
7505
7550
  const allActions = [...builtInActions, ...actions];
7551
+ // Convert actions to menu items for context menu
7552
+ const convertActionsToMenuItems = (item) => {
7553
+ const visibleActions = allActions.filter(action => !action.show || action.show(item));
7554
+ return visibleActions.map((action, idx) => {
7555
+ let iconElement = null;
7556
+ if (action.icon) {
7557
+ if (React.isValidElement(action.icon)) {
7558
+ iconElement = action.icon;
7559
+ }
7560
+ else {
7561
+ iconElement = React.createElement(action.icon, { className: 'h-4 w-4' });
7562
+ }
7563
+ }
7564
+ return {
7565
+ id: `action-${idx}`,
7566
+ label: action.label,
7567
+ icon: iconElement,
7568
+ onClick: () => action.onClick(item),
7569
+ danger: action.variant === 'danger',
7570
+ };
7571
+ });
7572
+ };
7506
7573
  // Selection state management
7507
7574
  const [internalSelectedRows, setInternalSelectedRows] = React.useState(new Set());
7508
7575
  // Expansion state management
@@ -7660,7 +7727,19 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
7660
7727
  // Hover state for row pair (primary + secondary)
7661
7728
  const isHovered = hoveredRowKey === rowKey;
7662
7729
  const hoverClass = disableHover ? '' : (isHovered ? 'bg-paper-100' : '');
7663
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("tr", { className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item), onDoubleClick: () => {
7730
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("tr", { className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item), onContextMenu: (e) => {
7731
+ if (enableContextMenu && allActions.length > 0) {
7732
+ e.preventDefault();
7733
+ e.stopPropagation();
7734
+ const x = e.clientX;
7735
+ const y = e.clientY;
7736
+ setContextMenuState({
7737
+ isOpen: true,
7738
+ position: { x, y },
7739
+ item,
7740
+ });
7741
+ }
7742
+ }, onDoubleClick: () => {
7664
7743
  // Priority 1: If there's an onEdit handler (legacy), trigger it
7665
7744
  if (onEdit) {
7666
7745
  onEdit(item);
@@ -7816,10 +7895,9 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
7816
7895
  }, children: jsxRuntime.jsx("div", { className: "absolute right-0 top-0 bottom-0 w-1 bg-paper-300 group-hover:bg-accent-400 transition-colors" }) }))] }, columnKey));
7817
7896
  })] }) }), jsxRuntime.jsx("tbody", { className: "bg-white table-loading transition-opacity duration-200", children: loading && data.length === 0 ? (renderLoadingSkeleton()) : data.length === 0 ? (renderEmptyStateContent()) : (renderDataRows()) })] })] }));
7818
7897
  // Wrap in scrollable container if virtualized
7819
- if (virtualized) {
7820
- return (jsxRuntime.jsx("div", { ref: tableContainerRef, onScroll: handleScroll, style: { height: virtualHeight, overflow: 'auto' }, className: "rounded-lg", children: tableContent }));
7821
- }
7822
- return tableContent;
7898
+ const finalContent = virtualized ? (jsxRuntime.jsx("div", { ref: tableContainerRef, onScroll: handleScroll, style: { height: virtualHeight, overflow: 'auto' }, className: "rounded-lg", children: tableContent })) : tableContent;
7899
+ // Render with context menu
7900
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [finalContent, contextMenuState.isOpen && contextMenuState.item && (jsxRuntime.jsx(Menu, { items: convertActionsToMenuItems(contextMenuState.item), position: contextMenuState.position, onClose: () => setContextMenuState({ isOpen: false, position: { x: 0, y: 0 }, item: null }) }))] }));
7823
7901
  }
7824
7902
 
7825
7903
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -11631,12 +11709,12 @@ var bessel$1 = {};
11631
11709
 
11632
11710
  /* bessel.js (C) 2013-present SheetJS -- http://sheetjs.com */
11633
11711
 
11634
- (function (exports) {
11712
+ (function (exports$1) {
11635
11713
  (function (factory) {
11636
11714
  /*jshint ignore:start */
11637
11715
  if(typeof DO_NOT_EXPORT_BESSEL === 'undefined') {
11638
11716
  {
11639
- factory(exports);
11717
+ factory(exports$1);
11640
11718
  }
11641
11719
  } else {
11642
11720
  factory({});
@@ -11870,7 +11948,7 @@ var bessel$1 = {};
11870
11948
 
11871
11949
  var jstat = {exports: {}};
11872
11950
 
11873
- (function (module, exports) {
11951
+ (function (module, exports$1) {
11874
11952
  (function (window, factory) {
11875
11953
  {
11876
11954
  module.exports = factory();
@@ -30527,7 +30605,7 @@ var hasRequiredScheduler_production;
30527
30605
  function requireScheduler_production () {
30528
30606
  if (hasRequiredScheduler_production) return scheduler_production;
30529
30607
  hasRequiredScheduler_production = 1;
30530
- (function (exports) {
30608
+ (function (exports$1) {
30531
30609
  function push(heap, node) {
30532
30610
  var index = heap.length;
30533
30611
  heap.push(node);
@@ -30576,16 +30654,16 @@ function requireScheduler_production () {
30576
30654
  var diff = a.sortIndex - b.sortIndex;
30577
30655
  return 0 !== diff ? diff : a.id - b.id;
30578
30656
  }
30579
- exports.unstable_now = void 0;
30657
+ exports$1.unstable_now = void 0;
30580
30658
  if ("object" === typeof performance && "function" === typeof performance.now) {
30581
30659
  var localPerformance = performance;
30582
- exports.unstable_now = function () {
30660
+ exports$1.unstable_now = function () {
30583
30661
  return localPerformance.now();
30584
30662
  };
30585
30663
  } else {
30586
30664
  var localDate = Date,
30587
30665
  initialTime = localDate.now();
30588
- exports.unstable_now = function () {
30666
+ exports$1.unstable_now = function () {
30589
30667
  return localDate.now() - initialTime;
30590
30668
  };
30591
30669
  }
@@ -30633,14 +30711,14 @@ function requireScheduler_production () {
30633
30711
  function shouldYieldToHost() {
30634
30712
  return needsPaint
30635
30713
  ? true
30636
- : exports.unstable_now() - startTime < frameInterval
30714
+ : exports$1.unstable_now() - startTime < frameInterval
30637
30715
  ? false
30638
30716
  : true;
30639
30717
  }
30640
30718
  function performWorkUntilDeadline() {
30641
30719
  needsPaint = false;
30642
30720
  if (isMessageLoopRunning) {
30643
- var currentTime = exports.unstable_now();
30721
+ var currentTime = exports$1.unstable_now();
30644
30722
  startTime = currentTime;
30645
30723
  var hasMoreWork = true;
30646
30724
  try {
@@ -30670,7 +30748,7 @@ function requireScheduler_production () {
30670
30748
  var continuationCallback = callback(
30671
30749
  currentTask.expirationTime <= currentTime
30672
30750
  );
30673
- currentTime = exports.unstable_now();
30751
+ currentTime = exports$1.unstable_now();
30674
30752
  if ("function" === typeof continuationCallback) {
30675
30753
  currentTask.callback = continuationCallback;
30676
30754
  advanceTimers(currentTime);
@@ -30726,29 +30804,29 @@ function requireScheduler_production () {
30726
30804
  };
30727
30805
  function requestHostTimeout(callback, ms) {
30728
30806
  taskTimeoutID = localSetTimeout(function () {
30729
- callback(exports.unstable_now());
30807
+ callback(exports$1.unstable_now());
30730
30808
  }, ms);
30731
30809
  }
30732
- exports.unstable_IdlePriority = 5;
30733
- exports.unstable_ImmediatePriority = 1;
30734
- exports.unstable_LowPriority = 4;
30735
- exports.unstable_NormalPriority = 3;
30736
- exports.unstable_Profiling = null;
30737
- exports.unstable_UserBlockingPriority = 2;
30738
- exports.unstable_cancelCallback = function (task) {
30810
+ exports$1.unstable_IdlePriority = 5;
30811
+ exports$1.unstable_ImmediatePriority = 1;
30812
+ exports$1.unstable_LowPriority = 4;
30813
+ exports$1.unstable_NormalPriority = 3;
30814
+ exports$1.unstable_Profiling = null;
30815
+ exports$1.unstable_UserBlockingPriority = 2;
30816
+ exports$1.unstable_cancelCallback = function (task) {
30739
30817
  task.callback = null;
30740
30818
  };
30741
- exports.unstable_forceFrameRate = function (fps) {
30819
+ exports$1.unstable_forceFrameRate = function (fps) {
30742
30820
  0 > fps || 125 < fps
30743
30821
  ? console.error(
30744
30822
  "forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"
30745
30823
  )
30746
30824
  : (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);
30747
30825
  };
30748
- exports.unstable_getCurrentPriorityLevel = function () {
30826
+ exports$1.unstable_getCurrentPriorityLevel = function () {
30749
30827
  return currentPriorityLevel;
30750
30828
  };
30751
- exports.unstable_next = function (eventHandler) {
30829
+ exports$1.unstable_next = function (eventHandler) {
30752
30830
  switch (currentPriorityLevel) {
30753
30831
  case 1:
30754
30832
  case 2:
@@ -30766,10 +30844,10 @@ function requireScheduler_production () {
30766
30844
  currentPriorityLevel = previousPriorityLevel;
30767
30845
  }
30768
30846
  };
30769
- exports.unstable_requestPaint = function () {
30847
+ exports$1.unstable_requestPaint = function () {
30770
30848
  needsPaint = true;
30771
30849
  };
30772
- exports.unstable_runWithPriority = function (priorityLevel, eventHandler) {
30850
+ exports$1.unstable_runWithPriority = function (priorityLevel, eventHandler) {
30773
30851
  switch (priorityLevel) {
30774
30852
  case 1:
30775
30853
  case 2:
@@ -30788,12 +30866,12 @@ function requireScheduler_production () {
30788
30866
  currentPriorityLevel = previousPriorityLevel;
30789
30867
  }
30790
30868
  };
30791
- exports.unstable_scheduleCallback = function (
30869
+ exports$1.unstable_scheduleCallback = function (
30792
30870
  priorityLevel,
30793
30871
  callback,
30794
30872
  options
30795
30873
  ) {
30796
- var currentTime = exports.unstable_now();
30874
+ var currentTime = exports$1.unstable_now();
30797
30875
  "object" === typeof options && null !== options
30798
30876
  ? ((options = options.delay),
30799
30877
  (options =
@@ -30844,8 +30922,8 @@ function requireScheduler_production () {
30844
30922
  ((isMessageLoopRunning = true), schedulePerformWorkUntilDeadline())));
30845
30923
  return priorityLevel;
30846
30924
  };
30847
- exports.unstable_shouldYield = shouldYieldToHost;
30848
- exports.unstable_wrapCallback = function (callback) {
30925
+ exports$1.unstable_shouldYield = shouldYieldToHost;
30926
+ exports$1.unstable_wrapCallback = function (callback) {
30849
30927
  var parentPriorityLevel = currentPriorityLevel;
30850
30928
  return function () {
30851
30929
  var previousPriorityLevel = currentPriorityLevel;
@@ -30878,13 +30956,13 @@ var hasRequiredScheduler_development;
30878
30956
  function requireScheduler_development () {
30879
30957
  if (hasRequiredScheduler_development) return scheduler_development;
30880
30958
  hasRequiredScheduler_development = 1;
30881
- (function (exports) {
30959
+ (function (exports$1) {
30882
30960
  "production" !== process.env.NODE_ENV &&
30883
30961
  (function () {
30884
30962
  function performWorkUntilDeadline() {
30885
30963
  needsPaint = false;
30886
30964
  if (isMessageLoopRunning) {
30887
- var currentTime = exports.unstable_now();
30965
+ var currentTime = exports$1.unstable_now();
30888
30966
  startTime = currentTime;
30889
30967
  var hasMoreWork = true;
30890
30968
  try {
@@ -30915,7 +30993,7 @@ function requireScheduler_development () {
30915
30993
  var continuationCallback = callback(
30916
30994
  currentTask.expirationTime <= currentTime
30917
30995
  );
30918
- currentTime = exports.unstable_now();
30996
+ currentTime = exports$1.unstable_now();
30919
30997
  if ("function" === typeof continuationCallback) {
30920
30998
  currentTask.callback = continuationCallback;
30921
30999
  advanceTimers(currentTime);
@@ -31036,32 +31114,32 @@ function requireScheduler_development () {
31036
31114
  function shouldYieldToHost() {
31037
31115
  return needsPaint
31038
31116
  ? true
31039
- : exports.unstable_now() - startTime < frameInterval
31117
+ : exports$1.unstable_now() - startTime < frameInterval
31040
31118
  ? false
31041
31119
  : true;
31042
31120
  }
31043
31121
  function requestHostTimeout(callback, ms) {
31044
31122
  taskTimeoutID = localSetTimeout(function () {
31045
- callback(exports.unstable_now());
31123
+ callback(exports$1.unstable_now());
31046
31124
  }, ms);
31047
31125
  }
31048
31126
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
31049
31127
  "function" ===
31050
31128
  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
31051
31129
  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
31052
- exports.unstable_now = void 0;
31130
+ exports$1.unstable_now = void 0;
31053
31131
  if (
31054
31132
  "object" === typeof performance &&
31055
31133
  "function" === typeof performance.now
31056
31134
  ) {
31057
31135
  var localPerformance = performance;
31058
- exports.unstable_now = function () {
31136
+ exports$1.unstable_now = function () {
31059
31137
  return localPerformance.now();
31060
31138
  };
31061
31139
  } else {
31062
31140
  var localDate = Date,
31063
31141
  initialTime = localDate.now();
31064
- exports.unstable_now = function () {
31142
+ exports$1.unstable_now = function () {
31065
31143
  return localDate.now() - initialTime;
31066
31144
  };
31067
31145
  }
@@ -31098,26 +31176,26 @@ function requireScheduler_development () {
31098
31176
  schedulePerformWorkUntilDeadline = function () {
31099
31177
  localSetTimeout(performWorkUntilDeadline, 0);
31100
31178
  };
31101
- exports.unstable_IdlePriority = 5;
31102
- exports.unstable_ImmediatePriority = 1;
31103
- exports.unstable_LowPriority = 4;
31104
- exports.unstable_NormalPriority = 3;
31105
- exports.unstable_Profiling = null;
31106
- exports.unstable_UserBlockingPriority = 2;
31107
- exports.unstable_cancelCallback = function (task) {
31179
+ exports$1.unstable_IdlePriority = 5;
31180
+ exports$1.unstable_ImmediatePriority = 1;
31181
+ exports$1.unstable_LowPriority = 4;
31182
+ exports$1.unstable_NormalPriority = 3;
31183
+ exports$1.unstable_Profiling = null;
31184
+ exports$1.unstable_UserBlockingPriority = 2;
31185
+ exports$1.unstable_cancelCallback = function (task) {
31108
31186
  task.callback = null;
31109
31187
  };
31110
- exports.unstable_forceFrameRate = function (fps) {
31188
+ exports$1.unstable_forceFrameRate = function (fps) {
31111
31189
  0 > fps || 125 < fps
31112
31190
  ? console.error(
31113
31191
  "forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"
31114
31192
  )
31115
31193
  : (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);
31116
31194
  };
31117
- exports.unstable_getCurrentPriorityLevel = function () {
31195
+ exports$1.unstable_getCurrentPriorityLevel = function () {
31118
31196
  return currentPriorityLevel;
31119
31197
  };
31120
- exports.unstable_next = function (eventHandler) {
31198
+ exports$1.unstable_next = function (eventHandler) {
31121
31199
  switch (currentPriorityLevel) {
31122
31200
  case 1:
31123
31201
  case 2:
@@ -31135,10 +31213,10 @@ function requireScheduler_development () {
31135
31213
  currentPriorityLevel = previousPriorityLevel;
31136
31214
  }
31137
31215
  };
31138
- exports.unstable_requestPaint = function () {
31216
+ exports$1.unstable_requestPaint = function () {
31139
31217
  needsPaint = true;
31140
31218
  };
31141
- exports.unstable_runWithPriority = function (priorityLevel, eventHandler) {
31219
+ exports$1.unstable_runWithPriority = function (priorityLevel, eventHandler) {
31142
31220
  switch (priorityLevel) {
31143
31221
  case 1:
31144
31222
  case 2:
@@ -31157,12 +31235,12 @@ function requireScheduler_development () {
31157
31235
  currentPriorityLevel = previousPriorityLevel;
31158
31236
  }
31159
31237
  };
31160
- exports.unstable_scheduleCallback = function (
31238
+ exports$1.unstable_scheduleCallback = function (
31161
31239
  priorityLevel,
31162
31240
  callback,
31163
31241
  options
31164
31242
  ) {
31165
- var currentTime = exports.unstable_now();
31243
+ var currentTime = exports$1.unstable_now();
31166
31244
  "object" === typeof options && null !== options
31167
31245
  ? ((options = options.delay),
31168
31246
  (options =
@@ -31214,8 +31292,8 @@ function requireScheduler_development () {
31214
31292
  schedulePerformWorkUntilDeadline())));
31215
31293
  return priorityLevel;
31216
31294
  };
31217
- exports.unstable_shouldYield = shouldYieldToHost;
31218
- exports.unstable_wrapCallback = function (callback) {
31295
+ exports$1.unstable_shouldYield = shouldYieldToHost;
31296
+ exports$1.unstable_wrapCallback = function (callback) {
31219
31297
  var parentPriorityLevel = currentPriorityLevel;
31220
31298
  return function () {
31221
31299
  var previousPriorityLevel = currentPriorityLevel;
@@ -35476,8 +35554,8 @@ return CRC32;
35476
35554
  })();
35477
35555
  /* [MS-CFB] v20171201 */
35478
35556
  var CFB = /*#__PURE__*/(function _CFB(){
35479
- var exports = {};
35480
- exports.version = '1.2.1';
35557
+ var exports$1 = {};
35558
+ exports$1.version = '1.2.1';
35481
35559
  /* [MS-CFB] 2.6.4 */
35482
35560
  function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
35483
35561
  var L = l.split("/"), R = r.split("/");
@@ -37149,12 +37227,12 @@ function cfb_mov(cfb/*:CFBContainer*/, old_name/*:string*/, new_name/*:string*/)
37149
37227
 
37150
37228
  function cfb_gc(cfb/*:CFBContainer*/)/*:void*/ { rebuild_cfb(cfb, true); }
37151
37229
 
37152
- exports.find = find;
37153
- exports.read = read;
37154
- exports.parse = parse;
37155
- exports.write = write;
37156
- exports.writeFile = write_file;
37157
- exports.utils = {
37230
+ exports$1.find = find;
37231
+ exports$1.read = read;
37232
+ exports$1.parse = parse;
37233
+ exports$1.write = write;
37234
+ exports$1.writeFile = write_file;
37235
+ exports$1.utils = {
37158
37236
  cfb_new: cfb_new,
37159
37237
  cfb_add: cfb_add,
37160
37238
  cfb_del: cfb_del,
@@ -37170,7 +37248,7 @@ exports.utils = {
37170
37248
  consts: consts
37171
37249
  };
37172
37250
 
37173
- return exports;
37251
+ return exports$1;
37174
37252
  })();
37175
37253
 
37176
37254
  /* normalize data for blob ctor */
@@ -58633,6 +58711,137 @@ function CurrencyDisplay({ amount, currency = 'USD', locale = 'en-US', className
58633
58711
  return (jsxRuntime.jsx("span", { className: combinedClasses, title: `${currency} ${safeAmount.toFixed(precision)}`, children: displayValue }));
58634
58712
  }
58635
58713
 
58714
+ /**
58715
+ * CurrencyInput - Specialized input for monetary values
58716
+ *
58717
+ * Automatically formats currency values with proper symbols and thousands separators.
58718
+ * Handles parsing and validation of numeric currency input.
58719
+ *
58720
+ * @example Basic usage
58721
+ * ```tsx
58722
+ * <CurrencyInput
58723
+ * label="Price"
58724
+ * value={price}
58725
+ * onChange={setPrice}
58726
+ * currency="USD"
58727
+ * />
58728
+ * ```
58729
+ *
58730
+ * @example With validation
58731
+ * ```tsx
58732
+ * <CurrencyInput
58733
+ * label="Budget"
58734
+ * value={budget}
58735
+ * onChange={setBudget}
58736
+ * min={0}
58737
+ * max={10000}
58738
+ * validationState={budget > 10000 ? 'error' : null}
58739
+ * validationMessage={budget > 10000 ? 'Exceeds maximum budget' : ''}
58740
+ * />
58741
+ * ```
58742
+ */
58743
+ const CurrencyInput = React.forwardRef(({ value, onChange, currency = 'USD', locale = 'en-US', precision = 2, allowNegative = false, min, max, onBlur, onFocus, ...props }, ref) => {
58744
+ const [displayValue, setDisplayValue] = React.useState('');
58745
+ const [isFocused, setIsFocused] = React.useState(false);
58746
+ // Get currency symbol
58747
+ const getCurrencySymbol = () => {
58748
+ const formatter = new Intl.NumberFormat(locale, {
58749
+ style: 'currency',
58750
+ currency,
58751
+ });
58752
+ const parts = formatter.formatToParts(0);
58753
+ const symbolPart = parts.find(part => part.type === 'currency');
58754
+ return symbolPart?.value || '$';
58755
+ };
58756
+ const currencySymbol = getCurrencySymbol();
58757
+ // Format number as currency
58758
+ const formatCurrency = (num) => {
58759
+ const formatter = new Intl.NumberFormat(locale, {
58760
+ minimumFractionDigits: isFocused ? 0 : precision,
58761
+ maximumFractionDigits: precision,
58762
+ });
58763
+ return formatter.format(num);
58764
+ };
58765
+ // Parse display value to number
58766
+ const parseValue = (str) => {
58767
+ if (!str || str === '')
58768
+ return null;
58769
+ // Remove all non-numeric characters except decimal point and minus sign
58770
+ let cleaned = str.replace(/[^\d.-]/g, '');
58771
+ // Handle multiple decimal points
58772
+ const parts = cleaned.split('.');
58773
+ if (parts.length > 2) {
58774
+ cleaned = parts[0] + '.' + parts.slice(1).join('');
58775
+ }
58776
+ // Handle multiple minus signs (keep only first)
58777
+ const minusCount = (cleaned.match(/-/g) || []).length;
58778
+ if (minusCount > 1) {
58779
+ const hasLeadingMinus = cleaned.startsWith('-');
58780
+ cleaned = cleaned.replace(/-/g, '');
58781
+ if (hasLeadingMinus)
58782
+ cleaned = '-' + cleaned;
58783
+ }
58784
+ // Parse to float
58785
+ const num = parseFloat(cleaned);
58786
+ if (isNaN(num))
58787
+ return null;
58788
+ // Apply precision
58789
+ return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
58790
+ };
58791
+ // Update display value when external value changes
58792
+ React.useEffect(() => {
58793
+ if (value === undefined || value === null || value === '') {
58794
+ setDisplayValue('');
58795
+ }
58796
+ else {
58797
+ const numValue = typeof value === 'string' ? parseFloat(value) : value;
58798
+ if (!isNaN(numValue)) {
58799
+ setDisplayValue(formatCurrency(numValue));
58800
+ }
58801
+ }
58802
+ }, [value, isFocused]);
58803
+ const handleChange = (e) => {
58804
+ const inputValue = e.target.value;
58805
+ setDisplayValue(inputValue);
58806
+ const numValue = parseValue(inputValue);
58807
+ // Validate constraints
58808
+ if (numValue !== null) {
58809
+ if (!allowNegative && numValue < 0)
58810
+ return;
58811
+ if (min !== undefined && numValue < min)
58812
+ return;
58813
+ if (max !== undefined && numValue > max)
58814
+ return;
58815
+ }
58816
+ onChange?.(numValue);
58817
+ };
58818
+ const handleFocus = (e) => {
58819
+ setIsFocused(true);
58820
+ // Remove formatting when focused for easier editing
58821
+ if (value !== undefined && value !== null && value !== '') {
58822
+ const numValue = typeof value === 'string' ? parseFloat(value) : value;
58823
+ if (!isNaN(numValue)) {
58824
+ setDisplayValue(numValue.toString());
58825
+ }
58826
+ }
58827
+ onFocus?.(e);
58828
+ };
58829
+ const handleBlur = (e) => {
58830
+ setIsFocused(false);
58831
+ // Reformat on blur
58832
+ const numValue = parseValue(displayValue);
58833
+ if (numValue !== null) {
58834
+ setDisplayValue(formatCurrency(numValue));
58835
+ }
58836
+ else if (displayValue === '') {
58837
+ setDisplayValue('');
58838
+ }
58839
+ onBlur?.(e);
58840
+ };
58841
+ return (jsxRuntime.jsx(Input, { ref: ref, type: "text", value: displayValue, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, prefix: currencySymbol, ...props }));
58842
+ });
58843
+ CurrencyInput.displayName = 'CurrencyInput';
58844
+
58636
58845
  const formatOptions = {
58637
58846
  short: {
58638
58847
  year: 'numeric',
@@ -59543,8 +59752,19 @@ const AppLayout = ({ children, toolbarSections = [], className = '', showToolbar
59543
59752
  * </Layout>
59544
59753
  * ```
59545
59754
  */
59546
- function PageLayout({ title, description, children, className = '', headerContent }) {
59547
- return (jsxRuntime.jsxs(Page, { children: [headerContent, jsxRuntime.jsxs("div", { className: `p-6 max-w-7xl mx-auto pb-20 ${className}`, children: [jsxRuntime.jsxs("div", { className: "mb-8", children: [jsxRuntime.jsx("h1", { className: "text-3xl font-bold text-ink-900 mb-2", children: title }), description && (jsxRuntime.jsx("p", { className: "text-ink-600", children: description }))] }), children] })] }));
59755
+ function PageLayout({ title, description, children, className = '', headerContent, maxWidth = '7xl', fixed = false }) {
59756
+ // Responsive padding classes - fixed left/top, responsive right/bottom
59757
+ const paddingClasses = fixed
59758
+ ? 'p-6 pb-20'
59759
+ : 'pt-6 pl-6 pr-2 pb-8 sm:pr-4 md:pr-6 sm:pb-12 md:pb-16 lg:pb-20';
59760
+ const maxWidthClasses = {
59761
+ '4xl': 'max-w-4xl',
59762
+ '5xl': 'max-w-5xl',
59763
+ '6xl': 'max-w-6xl',
59764
+ '7xl': 'max-w-7xl',
59765
+ 'full': 'max-w-full',
59766
+ };
59767
+ return (jsxRuntime.jsxs(Page, { padding: "none", maxWidth: maxWidth, fixed: fixed, children: [headerContent, jsxRuntime.jsxs("div", { className: `${paddingClasses} ${maxWidthClasses[maxWidth]} mx-auto ${className}`, children: [jsxRuntime.jsxs("div", { className: "mb-8", children: [jsxRuntime.jsx("h1", { className: "text-3xl font-bold text-ink-900 mb-2", children: title }), description && (jsxRuntime.jsx("p", { className: "text-ink-600", children: description }))] }), children] })] }));
59548
59768
  }
59549
59769
 
59550
59770
  const sizeClasses = {
@@ -59916,6 +60136,113 @@ function loadColumnOrder(tableId) {
59916
60136
  }
59917
60137
  }
59918
60138
 
60139
+ /**
60140
+ * Export data to Excel file
60141
+ *
60142
+ * A standalone utility for exporting any data array to Excel format.
60143
+ * Works independently of the Spreadsheet component.
60144
+ *
60145
+ * **Features:**
60146
+ * - Export arrays of objects to Excel
60147
+ * - Custom column headers and ordering
60148
+ * - Value formatting with custom functions
60149
+ * - Multi-sheet support
60150
+ * - Automatic type handling
60151
+ *
60152
+ * @example
60153
+ * ```typescript
60154
+ * // Simple export - uses object keys as headers
60155
+ * const data = [
60156
+ * { id: 1, name: 'Product A', price: 29.99 },
60157
+ * { id: 2, name: 'Product B', price: 49.99 },
60158
+ * ];
60159
+ * exportToExcel({ data, filename: 'products.xlsx' });
60160
+ *
60161
+ * // Custom columns with formatting
60162
+ * exportToExcel({
60163
+ * data: users,
60164
+ * filename: 'users.xlsx',
60165
+ * columns: [
60166
+ * { key: 'id', label: 'ID' },
60167
+ * { key: 'name', label: 'Full Name' },
60168
+ * { key: 'email', label: 'Email Address' },
60169
+ * { key: 'createdAt', label: 'Joined', format: (date) => new Date(date).toLocaleDateString() },
60170
+ * { key: 'isActive', label: 'Status', format: (active) => active ? 'Active' : 'Inactive' },
60171
+ * ],
60172
+ * });
60173
+ *
60174
+ * // Multi-sheet export
60175
+ * const wb = utils.book_new();
60176
+ * exportToExcel({ data: products, sheetName: 'Products', workbook: wb });
60177
+ * exportToExcel({ data: orders, sheetName: 'Orders', workbook: wb });
60178
+ * writeFile(wb, 'multi-sheet.xlsx');
60179
+ * ```
60180
+ *
60181
+ * @param options - Export configuration options
60182
+ * @returns WorkBook if workbook option provided, otherwise void (auto-downloads)
60183
+ */
60184
+ function exportToExcel({ data, filename = 'export.xlsx', sheetName = 'Sheet1', columns, includeHeaders = true, workbook, }) {
60185
+ if (!data || data.length === 0) {
60186
+ throw new Error('No data provided for export');
60187
+ }
60188
+ let worksheetData;
60189
+ if (columns) {
60190
+ // Use custom columns with specific ordering and formatting
60191
+ const headers = columns.map((col) => col.label);
60192
+ const rows = data.map((row) => columns.map((col) => {
60193
+ const value = row[col.key];
60194
+ return col.format ? col.format(value) : value ?? '';
60195
+ }));
60196
+ worksheetData = includeHeaders ? [headers, ...rows] : rows;
60197
+ }
60198
+ else {
60199
+ // Auto-generate from object keys
60200
+ if (includeHeaders) {
60201
+ const headers = Object.keys(data[0]);
60202
+ const rows = data.map((row) => headers.map((key) => row[key] ?? ''));
60203
+ worksheetData = [headers, ...rows];
60204
+ }
60205
+ else {
60206
+ const headers = Object.keys(data[0]);
60207
+ worksheetData = data.map((row) => headers.map((key) => row[key] ?? ''));
60208
+ }
60209
+ }
60210
+ const worksheet = utils.aoa_to_sheet(worksheetData);
60211
+ // If workbook provided, add sheet and return (for multi-sheet exports)
60212
+ if (workbook) {
60213
+ utils.book_append_sheet(workbook, worksheet, sheetName);
60214
+ return workbook;
60215
+ }
60216
+ // Otherwise, create workbook and download
60217
+ const newWorkbook = utils.book_new();
60218
+ utils.book_append_sheet(newWorkbook, worksheet, sheetName);
60219
+ writeFileSync(newWorkbook, filename);
60220
+ }
60221
+ function exportDataTableToExcel({ data, columns, filename = 'export.xlsx', sheetName = 'Sheet1', }) {
60222
+ const excelColumns = columns.map((col) => ({
60223
+ key: col.key,
60224
+ label: col.header,
60225
+ }));
60226
+ exportToExcel({
60227
+ data,
60228
+ columns: excelColumns,
60229
+ filename,
60230
+ sheetName,
60231
+ });
60232
+ }
60233
+ function createMultiSheetExcel({ filename, sheets }) {
60234
+ const workbook = utils.book_new();
60235
+ sheets.forEach((sheet) => {
60236
+ exportToExcel({
60237
+ data: sheet.data,
60238
+ sheetName: sheet.name,
60239
+ columns: sheet.columns,
60240
+ workbook,
60241
+ });
60242
+ });
60243
+ writeFileSync(workbook, filename);
60244
+ }
60245
+
59919
60246
  function useColumnResize(options = {}) {
59920
60247
  const { tableId, persist = false } = options;
59921
60248
  const [columnWidths, setColumnWidths] = React.useState({});
@@ -60066,6 +60393,7 @@ exports.ConfirmDialog = ConfirmDialog;
60066
60393
  exports.ContextMenu = ContextMenu;
60067
60394
  exports.ControlBar = ControlBar;
60068
60395
  exports.CurrencyDisplay = CurrencyDisplay;
60396
+ exports.CurrencyInput = CurrencyInput;
60069
60397
  exports.Dashboard = Dashboard;
60070
60398
  exports.DashboardContent = DashboardContent;
60071
60399
  exports.DashboardHeader = DashboardHeader;
@@ -60169,8 +60497,11 @@ exports.addWarningMessage = addWarningMessage;
60169
60497
  exports.calculateColumnWidth = calculateColumnWidth;
60170
60498
  exports.createActionsSection = createActionsSection;
60171
60499
  exports.createFiltersSection = createFiltersSection;
60500
+ exports.createMultiSheetExcel = createMultiSheetExcel;
60172
60501
  exports.createPageControlsSection = createPageControlsSection;
60173
60502
  exports.createQueryDetailsSection = createQueryDetailsSection;
60503
+ exports.exportDataTableToExcel = exportDataTableToExcel;
60504
+ exports.exportToExcel = exportToExcel;
60174
60505
  exports.formatStatisticValue = formatStatisticValue;
60175
60506
  exports.formatStatistics = formatStatistics;
60176
60507
  exports.loadColumnOrder = loadColumnOrder;