@cwellt_software/cwellt-reactjs-lib 1.0.8 → 1.0.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CwFileUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/control/input/file/CwFileUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,UAAU,QAAQ;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,iBAAiB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,YAAY,CAAC,eAAe,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,2CA2EvF"}
1
+ {"version":3,"file":"CwFileUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/control/input/file/CwFileUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,UAAU,QAAQ;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,iBAAiB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,YAAY,CAAC,eAAe,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,2CAmFvF"}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ interface CwFileUploadMultipleProps {
3
+ name?: string;
4
+ accept?: string;
5
+ multiple?: boolean;
6
+ maxFileSize?: number;
7
+ allowedTypes?: string[];
8
+ onSelect?: (files: FileList | null) => void;
9
+ onError?: (error: string) => void;
10
+ className?: string;
11
+ disabled?: boolean;
12
+ }
13
+ export declare function CwFileUploadMultiple(fileUploadProps: React.PropsWithChildren<CwFileUploadMultipleProps>): import("react/jsx-runtime").JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=CwFileUploadMultiple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CwFileUploadMultiple.d.ts","sourceRoot":"","sources":["../../../../../src/components/control/input/file/CwFileUploadMultiple.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAK7D,UAAU,yBAAyB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,KAAK,CAAC,iBAAiB,CAAC,yBAAyB,CAAC,2CAyRvG"}
package/dist/index.cjs.js CHANGED
@@ -423,7 +423,7 @@ function CwLoadingSmall(CwelltLoadingAppointements) {
423
423
  jsxRuntime.jsx("div", {})) }));
424
424
  }
425
425
 
426
- var styles$d = {"cw-generic-tooltip-content":"cw-generic-tooltip-module_cw-generic-tooltip-content__la-Si"};
426
+ var styles$e = {"cw-generic-tooltip-content":"cw-generic-tooltip-module_cw-generic-tooltip-content__la-Si"};
427
427
 
428
428
  // Constants moved outside to prevent recreation
429
429
  const margin = 16;
@@ -534,12 +534,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
534
534
  const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
535
535
  setIsVisible(true);
536
536
  }, showDelay);
537
- const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$d["cw-generic-tooltip-content"]);
537
+ const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$e["cw-generic-tooltip-content"]);
538
538
  // Memoize tooltip content creation
539
539
  const tooltipContent = React.useMemo(() => {
540
540
  if (hide || !isVisible || !content)
541
541
  return null;
542
- return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$d["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, style: {
542
+ return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$e["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, style: {
543
543
  position: 'fixed',
544
544
  top: `${tooltipPosition.top}px`,
545
545
  left: `${tooltipPosition.left}px`,
@@ -554,7 +554,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
554
554
  clearTooltipTimeout();
555
555
  setIsVisible(false);
556
556
  }, [clearTooltipTimeout]);
557
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$d["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, children: [tooltipContent, children] }));
557
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$e["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, children: [tooltipContent, children] }));
558
558
  };
559
559
 
560
560
  // Reference for draggable modal
@@ -673,7 +673,7 @@ class CwModalIframe extends React__namespace.Component {
673
673
  }
674
674
  }
675
675
 
676
- var styles$c = {"cw-dialog-main":"cw-dialog-module_cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module_cw-dialog-button-close__9GRd8"};
676
+ var styles$d = {"cw-dialog-main":"cw-dialog-module_cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module_cw-dialog-button-close__9GRd8"};
677
677
 
678
678
  // Helper function to parse size values
679
679
  const parseSize = (size) => {
@@ -866,7 +866,7 @@ const CwDialog = props => {
866
866
  onClose();
867
867
  }
868
868
  }, [onClose]);
869
- const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$c["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
869
+ const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$d["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
870
870
  const content = React.useMemo(() => (jsxRuntime.jsx("section", { children: children })), [children]);
871
871
  const footer = React.useMemo(() => (jsxRuntime.jsx("footer", { children: customFooter || (jsxRuntime.jsx("button", { className: "cw-button-icon cwi-save", onClick: onSave })) })), [customFooter, onSave]);
872
872
  const resizeHandles = React.useMemo(() => size.autoHeight
@@ -895,7 +895,7 @@ const CwDialog = props => {
895
895
  : `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
896
896
  return { displayWidth, displayHeight };
897
897
  }, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
898
- return (open && (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$c["cw-dialog-main"], onClick: handleScrimClick, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
898
+ return (open && (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$d["cw-dialog-main"], onClick: handleScrimClick, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
899
899
  left: `${position.x}px`,
900
900
  top: `${position.y}px`,
901
901
  width: displayDimensions.displayWidth,
@@ -1058,7 +1058,7 @@ function CwButton({ text, variant = 'solid', color = 'primary', className = '',
1058
1058
  return (jsxRuntime.jsx("button", { type: "button", className: buttonClass, ...buttonProps, "data-color": color, children: variant === 'icon' ? null : (children ?? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [icon && jsxRuntime.jsx("span", { className: `cwi-icons cwi-${icon}` }), text && jsxRuntime.jsx("strong", { children: text })] }))) }));
1059
1059
  }
1060
1060
 
1061
- var styles$b = {"card":"cw-card-module_card__HJUT0","clickable":"cw-card-module_clickable__Y-V3X","disabled":"cw-card-module_disabled__0wHh1","loading":"cw-card-module_loading__-fzlx","content":"cw-card-module_content__ma9qy","headerContent":"cw-card-module_headerContent__x4Jfl","footerTags":"cw-card-module_footerTags__80sSW","loadingOverlay":"cw-card-module_loadingOverlay__8-zVV"};
1061
+ var styles$c = {"card":"cw-card-module_card__HJUT0","clickable":"cw-card-module_clickable__Y-V3X","disabled":"cw-card-module_disabled__0wHh1","loading":"cw-card-module_loading__-fzlx","content":"cw-card-module_content__ma9qy","headerContent":"cw-card-module_headerContent__x4Jfl","footerTags":"cw-card-module_footerTags__80sSW","loadingOverlay":"cw-card-module_loadingOverlay__8-zVV"};
1062
1062
 
1063
1063
  /**
1064
1064
  * CwCard - A simple card component for displaying content in a contained format
@@ -1082,11 +1082,11 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1082
1082
  // Construct class names using CSS modules
1083
1083
  const cardClassNames = [
1084
1084
  'cw-card',
1085
- styles$b.card,
1085
+ styles$c.card,
1086
1086
  className,
1087
- clickable ? styles$b.clickable : '',
1088
- disabled ? styles$b.disabled : '',
1089
- isLoading ? styles$b.loading : '',
1087
+ clickable ? styles$c.clickable : '',
1088
+ disabled ? styles$c.disabled : '',
1089
+ isLoading ? styles$c.loading : '',
1090
1090
  ].filter(Boolean).join(' ');
1091
1091
  // Handle click event when card is clickable
1092
1092
  const handleClick = () => {
@@ -1103,15 +1103,15 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1103
1103
  // Determine if footer should be rendered
1104
1104
  const hasFooter = hasChips || footer || (hasActions && direction === "row");
1105
1105
  // Actions component to reuse
1106
- const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$b.actions, children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1106
+ const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$c.actions, children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1107
1107
  return (jsxRuntime.jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && {
1108
1108
  role: 'button',
1109
1109
  tabIndex: 0,
1110
1110
  onClick: handleClick,
1111
- }), "data-variant": variant, "data-direction": direction, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$b.headerContent, "data-alignment": alignment, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), direction === "column" && ActionsComponent] })), jsxRuntime.jsx("div", { className: styles$b.content, children: children }), hasFooter && (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$b.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$b.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$b.footerContent, children: footer }))] })), direction === "row" && ActionsComponent, isLoading && (jsxRuntime.jsx("div", { className: styles$b.loadingOverlay, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1111
+ }), "data-variant": variant, "data-direction": direction, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$c.headerContent, "data-alignment": alignment, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), direction === "column" && ActionsComponent] })), jsxRuntime.jsx("div", { className: styles$c.content, children: children }), hasFooter && (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$c.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$c.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$c.footerContent, children: footer }))] })), direction === "row" && ActionsComponent, isLoading && (jsxRuntime.jsx("div", { className: styles$c.loadingOverlay, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1112
1112
  };
1113
1113
 
1114
- var styles$a = {"cardContainer":"cw-card-list-module_cardContainer__l3YEh","pagination":"cw-card-list-module_pagination__5Ay78","pageInfo":"cw-card-list-module_pageInfo__uiMel","emptyState":"cw-card-list-module_emptyState__RlqiS","sortControls":"cw-card-list-module_sortControls__mWgZA"};
1114
+ var styles$b = {"cardContainer":"cw-card-list-module_cardContainer__l3YEh","pagination":"cw-card-list-module_pagination__5Ay78","pageInfo":"cw-card-list-module_pageInfo__uiMel","emptyState":"cw-card-list-module_emptyState__RlqiS","sortControls":"cw-card-list-module_sortControls__mWgZA"};
1115
1115
 
1116
1116
  function CwCardList({ items, renderCard, pageSize = 10, className = '', layout = 'grid', defaultCardWidth = 320, cardGap = 16, isLoading = false, emptyState, sortOptions = [], defaultSortKey }) {
1117
1117
  const [currentPage, setCurrentPage] = React.useState(1);
@@ -1145,10 +1145,10 @@ function CwCardList({ items, renderCard, pageSize = 10, className = '', layout =
1145
1145
  '--card-width': `${defaultCardWidth}px`,
1146
1146
  '--card-gap': `${cardGap}px`
1147
1147
  };
1148
- return (jsxRuntime.jsxs("div", { className: `${className}`, children: [sortOptions.length > 0 && (jsxRuntime.jsxs("div", { className: styles$a.sortControls, children: [jsxRuntime.jsx("label", { htmlFor: "cardlist-sort-select", children: "Sort by:" }), jsxRuntime.jsx("select", { id: "cardlist-sort-select", value: sortKey, onChange: (e) => handleSortChange(e.target.value), className: styles$a.sortSelect, children: sortOptions.map(option => (jsxRuntime.jsx("option", { value: option.key, children: option.label }, option.key))) }), jsxRuntime.jsx("button", { onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'), className: `cw-button-icon ${sortDirection === 'asc' ? 'cwi-arrow-up' : 'cwi-arrow-down'}`, title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}` })] })), isLoading ? (jsxRuntime.jsx("div", { className: styles$a.loading, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$a.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$a.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx("div", { className: styles$a.cardWrapper, children: renderCard(item, index) }, index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$a.pagination, children: [jsxRuntime.jsx("button", { disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)), className: "cw-button-icon cwi-chevron-left" }), jsxRuntime.jsxs("span", { className: styles$a.pageInfo, children: [currentPage, " of ", totalPages] }), jsxRuntime.jsx("button", { disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), className: "cw-button-icon cwi-chevron-right" })] }))] }))] }));
1148
+ return (jsxRuntime.jsxs("div", { className: `${className}`, children: [sortOptions.length > 0 && (jsxRuntime.jsxs("div", { className: styles$b.sortControls, children: [jsxRuntime.jsx("label", { htmlFor: "cardlist-sort-select", children: "Sort by:" }), jsxRuntime.jsx("select", { id: "cardlist-sort-select", value: sortKey, onChange: (e) => handleSortChange(e.target.value), className: styles$b.sortSelect, children: sortOptions.map(option => (jsxRuntime.jsx("option", { value: option.key, children: option.label }, option.key))) }), jsxRuntime.jsx("button", { onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'), className: `cw-button-icon ${sortDirection === 'asc' ? 'cwi-arrow-up' : 'cwi-arrow-down'}`, title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}` })] })), isLoading ? (jsxRuntime.jsx("div", { className: styles$b.loading, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$b.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$b.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx("div", { className: styles$b.cardWrapper, children: renderCard(item, index) }, index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$b.pagination, children: [jsxRuntime.jsx("button", { disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)), className: "cw-button-icon cwi-chevron-left" }), jsxRuntime.jsxs("span", { className: styles$b.pageInfo, children: [currentPage, " of ", totalPages] }), jsxRuntime.jsx("button", { disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), className: "cw-button-icon cwi-chevron-right" })] }))] }))] }));
1149
1149
  }
1150
1150
 
1151
- var styles$9 = {"cw-accordion":"cw-accordion-module_cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module_cw-accordion-body__xlI8b"};
1151
+ var styles$a = {"cw-accordion":"cw-accordion-module_cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module_cw-accordion-body__xlI8b"};
1152
1152
 
1153
1153
  /**
1154
1154
  *
@@ -1165,7 +1165,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
1165
1165
  setVisible_accordionBody(!isVisible_accordionBody);
1166
1166
  };
1167
1167
  // #endregion
1168
- return (jsxRuntime.jsxs("div", { className: styles$9["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$9["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1168
+ return (jsxRuntime.jsxs("div", { className: styles$a["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$a["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1169
1169
  }
1170
1170
 
1171
1171
  /**
@@ -1370,7 +1370,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1370
1370
  } }), "of ", totalPages, jsxRuntime.jsx("button", { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, style: { marginLeft: "1rem" }, children: pageSizeOptions.map(size => (jsxRuntime.jsxs("option", { value: size, children: [size, " / page"] }, size))) })] }))] }));
1371
1371
  }
1372
1372
 
1373
- var styles$8 = {"cw-tabs":"cw-tabs-module_cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module_cw-tabs-content__HTp8d"};
1373
+ var styles$9 = {"cw-tabs":"cw-tabs-module_cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module_cw-tabs-content__HTp8d"};
1374
1374
 
1375
1375
  const TabIcon = ({ icon }) => {
1376
1376
  if (!icon)
@@ -1420,7 +1420,7 @@ function CwTabs(CwTabsProps) {
1420
1420
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
1421
1421
  ? { minWidth: CwTabsProps.tabsListWidth }
1422
1422
  : undefined;
1423
- return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, className: styles$8['cw-tabs'], style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$8['cw-tabs-content'], children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
1423
+ return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, className: styles$9['cw-tabs'], style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$9['cw-tabs-content'], children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
1424
1424
  }
1425
1425
 
1426
1426
  /**
@@ -1538,7 +1538,7 @@ const CwTableGrouped = props => {
1538
1538
  function CwFileUpload(fileUploadProps) {
1539
1539
  const [previewURL, setPreviewURL] = React.useState("");
1540
1540
  const [error, setError] = React.useState(null);
1541
- const [selectedFileName, setSelectedFileName] = React.useState("");
1541
+ const [_selectedFileName, setSelectedFileName] = React.useState("");
1542
1542
  const [_currentHexContent, setCurrentHexContent] = React.useState("");
1543
1543
  React.useEffect(() => {
1544
1544
  // If there is hexadecimal preview content, set the Preview URL
@@ -1550,36 +1550,185 @@ function CwFileUpload(fileUploadProps) {
1550
1550
  const file = event.target.files?.[0];
1551
1551
  setSelectedFileName(file?.name ?? "");
1552
1552
  if (file) {
1553
- if (!file.type.startsWith(fileUploadProps.accept)) {
1553
+ const allowedExts = fileUploadProps.accept.split(',').map(ext => ext.trim().replace('.', '').toLowerCase());
1554
+ const fileExt = file.name.split('.').pop()?.toLowerCase() ?? "";
1555
+ if (!allowedExts.includes(fileExt)) {
1554
1556
  setError(`Invalid file type. Only ${fileUploadProps.acceptString} files are allowed.`);
1555
1557
  setPreviewURL("");
1558
+ return;
1556
1559
  }
1557
- else {
1558
- setError(null);
1559
- const reader = new FileReader();
1560
- reader.onloadend = () => {
1561
- if (typeof reader.result === "string") {
1562
- const hexContent = arrayBufferToHex(reader.result);
1563
- setCurrentHexContent(hexContent);
1564
- setPreviewURL(reader.result);
1565
- setCurrentHexContent(arrayBufferToHex(reader.result));
1566
- // Llama a la función para guardar el contenido hexadecimal
1567
- fileUploadProps.onSaveHexContent(arrayBufferToHex(reader.result));
1568
- }
1560
+ setError(null);
1561
+ const reader = new FileReader();
1562
+ reader.onloadend = () => {
1563
+ if (typeof reader.result === "string") {
1564
+ const hexContent = arrayBufferToHex(reader.result);
1565
+ setCurrentHexContent(hexContent);
1566
+ setPreviewURL(reader.result);
1567
+ setCurrentHexContent(arrayBufferToHex(reader.result));
1568
+ // Call function to store hexadecimal content
1569
+ fileUploadProps.onSaveHexContent(arrayBufferToHex(reader.result));
1570
+ }
1571
+ };
1572
+ reader.readAsDataURL(file);
1573
+ }
1574
+ };
1575
+ // Function to convert the image buffer into hexadecimal content
1576
+ const arrayBufferToHex = (dataUrl) => {
1577
+ // Decodes the base64 of the URL data
1578
+ const base64 = dataUrl.split(",")[1];
1579
+ const binary = atob(base64);
1580
+ let hex = "";
1581
+ for (let i = 0; i < binary.length; i++) {
1582
+ hex += binary.charCodeAt(i).toString(16).padStart(2, "0");
1583
+ }
1584
+ return hex;
1585
+ };
1586
+ return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "row", children: [jsxRuntime.jsx("input", { className: "cw-button", type: "file", accept: fileUploadProps.accept, readOnly: true, placeholder: "No file selected...", onChange: handleFileChange }), previewURL && (jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsx("img", { src: previewURL, alt: "Preview", style: { maxWidth: "200px", maxHeight: "200px" } }) }))] }), error && jsxRuntime.jsx("div", { className: "row error", children: error }), jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsxs("label", { children: ["Please note: File/image has to be in ", fileUploadProps.acceptString, " format", fileUploadProps.sizeString && `, ${fileUploadProps.sizeString}`] }) })] }));
1587
+ }
1588
+
1589
+ var styles$8 = {"fileUploadContainer":"cw-file-upload-multiple-module_fileUploadContainer__liEc1","hiddenInput":"cw-file-upload-multiple-module_hiddenInput__TZBBI","uploadArea":"cw-file-upload-multiple-module_uploadArea__DdOhs","uploadAreaDisabled":"cw-file-upload-multiple-module_uploadAreaDisabled__VWeFX","uploadTitle":"cw-file-upload-multiple-module_uploadTitle__gjRk8","uploadSubtitle":"cw-file-upload-multiple-module_uploadSubtitle__Z0S5t","filesContainer":"cw-file-upload-multiple-module_filesContainer__g44PY","fileItem":"cw-file-upload-multiple-module_fileItem__w27Dg","fileIcon":"cw-file-upload-multiple-module_fileIcon__iJJUX","fileExtension":"cw-file-upload-multiple-module_fileExtension__vOuHv","fileInfo":"cw-file-upload-multiple-module_fileInfo__R5ZTv","fileName":"cw-file-upload-multiple-module_fileName__DjepK","fileSize":"cw-file-upload-multiple-module_fileSize__b8GSm","smallButton":"cw-file-upload-multiple-module_smallButton__siUAh"};
1590
+
1591
+ function CwFileUploadMultiple(fileUploadProps) {
1592
+ const fileInputRef = React.useRef(null);
1593
+ const [selectedFiles, setSelectedFiles] = React.useState([]);
1594
+ const getFileExtension = (filename) => {
1595
+ return filename.split('.').pop()?.toUpperCase() || '';
1596
+ };
1597
+ const validateFile = (file) => {
1598
+ // Validate the size of the file
1599
+ if (fileUploadProps.maxFileSize) {
1600
+ const fileSizeInMB = file.size / (1024 * 1024);
1601
+ if (fileSizeInMB > fileUploadProps.maxFileSize) {
1602
+ return {
1603
+ isValid: false,
1604
+ error: `File "${file.name}" is too large. Maximum size allowed is ${fileUploadProps.maxFileSize}MB.`
1605
+ };
1606
+ }
1607
+ }
1608
+ // Validate file type by extension (based in accept)
1609
+ if (fileUploadProps.accept) {
1610
+ const acceptedExtensions = fileUploadProps.accept.split(',').map(ext => ext.trim().toLowerCase());
1611
+ const fileExtension = '.' + file.name.split('.').pop()?.toLowerCase();
1612
+ const isExtensionValid = acceptedExtensions.some(ext => {
1613
+ if (ext.startsWith('.')) {
1614
+ return ext === fileExtension;
1615
+ }
1616
+ return false;
1617
+ });
1618
+ if (!isExtensionValid) {
1619
+ return {
1620
+ isValid: false,
1621
+ error: `File "${file.name}" has an invalid format. Allowed formats: ${fileUploadProps.accept}`
1569
1622
  };
1570
- reader.readAsDataURL(file);
1571
1623
  }
1572
1624
  }
1625
+ // Validate MIME type if specified
1626
+ if (fileUploadProps.allowedTypes && fileUploadProps.allowedTypes.length > 0) {
1627
+ const isMimeTypeValid = fileUploadProps.allowedTypes.includes(file.type);
1628
+ if (!isMimeTypeValid) {
1629
+ return {
1630
+ isValid: false,
1631
+ error: `File "${file.name}" has an invalid MIME type. Allowed types: ${fileUploadProps.allowedTypes.join(', ')}`
1632
+ };
1633
+ }
1634
+ }
1635
+ return { isValid: true };
1636
+ };
1637
+ const processFiles = (files, existingFiles = []) => {
1638
+ const fileArray = Array.from(files);
1639
+ const validFiles = [...existingFiles]; // Start with existing files
1640
+ const errors = [];
1641
+ for (const file of fileArray) {
1642
+ // Check if the file already exists (by name and size)
1643
+ const isDuplicate = existingFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
1644
+ if (isDuplicate) {
1645
+ errors.push(`File "${file.name}" is already selected.`);
1646
+ continue;
1647
+ }
1648
+ const validation = validateFile(file);
1649
+ if (!validation.isValid) {
1650
+ errors.push(validation.error);
1651
+ continue;
1652
+ }
1653
+ validFiles.push(file);
1654
+ }
1655
+ // Show errors if any
1656
+ if (errors.length > 0) {
1657
+ if (fileUploadProps.onError) {
1658
+ fileUploadProps.onError(errors.join('\n'));
1659
+ }
1660
+ else {
1661
+ console.error(errors.join('\n'));
1662
+ alert(errors.join('\n')); // Fallback if there is no onError
1663
+ }
1664
+ }
1665
+ // If not multiple, only take the first valid file (replace)
1666
+ if (!fileUploadProps.multiple && validFiles.length > 1) {
1667
+ return [validFiles[validFiles.length - 1]]; // Take the last file added
1668
+ }
1669
+ return validFiles;
1573
1670
  };
1574
- // Function to convert the image buffer into hexadecimal content
1575
- const arrayBufferToHex = (buffer) => {
1576
- const bytes = new Uint8Array(buffer.length);
1577
- for (let i = 0; i < buffer.length; i++) {
1578
- bytes[i] = buffer.charCodeAt(i);
1671
+ const updateFileInput = (files) => {
1672
+ // Create FileList with all files
1673
+ const dataTransfer = new DataTransfer();
1674
+ files.forEach(file => dataTransfer.items.add(file));
1675
+ if (fileInputRef.current) {
1676
+ fileInputRef.current.files = dataTransfer.files;
1677
+ }
1678
+ if (fileUploadProps.onSelect) {
1679
+ fileUploadProps.onSelect(dataTransfer.files);
1680
+ }
1681
+ };
1682
+ const handleFileSelect = (event) => {
1683
+ const files = event.target.files;
1684
+ if (files && files.length > 0) {
1685
+ const updatedFiles = processFiles(files, selectedFiles);
1686
+ if (updatedFiles.length > selectedFiles.length || !fileUploadProps.multiple) {
1687
+ setSelectedFiles(updatedFiles);
1688
+ updateFileInput(updatedFiles);
1689
+ }
1690
+ else {
1691
+ // Clear input if no new valid files were added
1692
+ if (fileInputRef.current) {
1693
+ fileInputRef.current.value = '';
1694
+ }
1695
+ }
1696
+ }
1697
+ };
1698
+ const removeFile = (indexToRemove) => {
1699
+ const newFiles = selectedFiles.filter((_, index) => index !== indexToRemove);
1700
+ setSelectedFiles(newFiles);
1701
+ updateFileInput(newFiles);
1702
+ };
1703
+ const removeAllFiles = () => {
1704
+ setSelectedFiles([]);
1705
+ if (fileInputRef.current) {
1706
+ fileInputRef.current.value = '';
1707
+ }
1708
+ if (fileUploadProps.onSelect) {
1709
+ fileUploadProps.onSelect(null);
1710
+ }
1711
+ };
1712
+ const handleButtonClick = () => {
1713
+ fileInputRef.current?.click();
1714
+ };
1715
+ const handleDragOver = (event) => {
1716
+ event.preventDefault();
1717
+ event.stopPropagation();
1718
+ };
1719
+ const handleDrop = (event) => {
1720
+ event.preventDefault();
1721
+ event.stopPropagation();
1722
+ const files = event.dataTransfer.files;
1723
+ if (files && files.length > 0) {
1724
+ const updatedFiles = processFiles(files, selectedFiles);
1725
+ if (updatedFiles.length > selectedFiles.length || !fileUploadProps.multiple) {
1726
+ setSelectedFiles(updatedFiles);
1727
+ updateFileInput(updatedFiles);
1728
+ }
1579
1729
  }
1580
- return globalThis.Buffer.from(bytes).toString("hex");
1581
1730
  };
1582
- return (jsxRuntime.jsxs("div", { children: [previewURL && (jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsx("img", { src: previewURL, alt: "Preview", style: { maxWidth: "200px", maxHeight: "200px" } }) })), jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsx("input", { type: "file", accept: fileUploadProps.accept, value: selectedFileName, readOnly: true, placeholder: "No file selected...", onChange: handleFileChange }) }), error && jsxRuntime.jsx("div", { className: "row error", children: error }), jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsxs("label", { children: ["Please note: File/image has to be in ", fileUploadProps.acceptString, " format", fileUploadProps.sizeString && `, ${fileUploadProps.sizeString}`] }) })] }));
1731
+ return (jsxRuntime.jsxs("div", { className: `${styles$8.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelect, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$8.hiddenInput }), selectedFiles.length === 0 ? (jsxRuntime.jsxs("div", { className: `${styles$8.uploadArea} ${fileUploadProps.disabled ? styles$8.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$8.uploadTitle}`, children: fileUploadProps.disabled ? 'Upload disabled' : 'Click to upload or drag and drop' }), jsxRuntime.jsxs("p", { className: `${styles$8.uploadSubtitle}`, children: [fileUploadProps.accept ? `Accepted files: ${fileUploadProps.accept}` : 'All file types accepted', !fileUploadProps.multiple && ' (Single file only)'] })] })) : (jsxRuntime.jsxs("div", { className: styles$8.filesContainer, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsxs("small", { className: styles$8.filesCount, children: [selectedFiles.length, " file", selectedFiles.length !== 1 ? 's' : '', " selected"] }), jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: "Clear all" })] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$8.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$8.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$8.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$8.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$8.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$8.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$8.smallButton })] }, index))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: "Add More Files", icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: "Change File", icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
1583
1732
  }
1584
1733
 
1585
1734
  function CwInput(CwInputProps) {
@@ -7543,6 +7692,7 @@ exports.CwDropdownFilter = CwDropdownFilter;
7543
7692
  exports.CwDropdownNavigation = CwDropdownNavigation;
7544
7693
  exports.CwExpandable = CwExpandable;
7545
7694
  exports.CwFileUpload = CwFileUpload;
7695
+ exports.CwFileUploadMultiple = CwFileUploadMultiple;
7546
7696
  exports.CwFindAirport = CwFindAirport;
7547
7697
  exports.CwFloatingButton = CwFloatingButton;
7548
7698
  exports.CwGenericTooltip = CwGenericTooltip;