@cwellt_software/cwellt-reactjs-lib 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +586 -213
- package/dist/index.css +2 -2
- package/dist/index.d.ts +205 -5
- package/dist/index.es.js +585 -214
- package/dist/src/common/hooks/useDropdownPortal.d.ts +86 -0
- package/dist/src/common/hooks/useDropdownPortal.d.ts.map +1 -0
- package/dist/src/components/control/action/search/CwSearch.d.ts +22 -0
- package/dist/src/components/control/action/search/CwSearch.d.ts.map +1 -1
- package/dist/src/components/control/choice/multi-filter/CwMultiFilter.d.ts.map +1 -1
- package/dist/src/components/control/choice/option/CwOption.d.ts +3 -1
- package/dist/src/components/control/choice/option/CwOption.d.ts.map +1 -1
- package/dist/src/components/control/choice/select/CwDropdown.d.ts +56 -0
- package/dist/src/components/control/choice/select/CwDropdown.d.ts.map +1 -0
- package/dist/src/components/control/choice/select/CwSelect.d.ts.map +1 -1
- package/dist/src/components/control/choice/tag-selector/CwTagSelector.d.ts +68 -0
- package/dist/src/components/control/choice/tag-selector/CwTagSelector.d.ts.map +1 -0
- package/dist/src/components/control/input/new-dates/CwDatePickerTemporal.d.ts +48 -0
- package/dist/src/components/control/input/new-dates/CwDatePickerTemporal.d.ts.map +1 -0
- package/dist/src/components/control/input/new-dates/datePickerHelpers.d.ts +20 -0
- package/dist/src/components/control/input/new-dates/datePickerHelpers.d.ts.map +1 -0
- package/dist/src/components/control/input/new-dates/usePickerPopup.d.ts +7 -8
- package/dist/src/components/control/input/new-dates/usePickerPopup.d.ts.map +1 -1
- package/dist/src/components/custom/find-airport/CwFindAirportComp.d.ts +36 -1
- package/dist/src/components/custom/find-airport/CwFindAirportComp.d.ts.map +1 -1
- package/dist/src/components/custom/find-crewmember/CwFindCrewmemberComp.d.ts +26 -0
- package/dist/src/components/custom/find-crewmember/CwFindCrewmemberComp.d.ts.map +1 -1
- package/dist/src/components/display/data/table/CwTable.d.ts.map +1 -1
- package/dist/src/components/display/data/table-serverside/CwTableServerSide.d.ts +2 -1
- package/dist/src/components/display/data/table-serverside/CwTableServerSide.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
- package/dist/src/playground/pages/DatePickerTemporalPage.d.ts +3 -0
- package/dist/src/playground/pages/DatePickerTemporalPage.d.ts.map +1 -0
- package/dist/src/playground/pages/SelectorsPage.d.ts +3 -0
- package/dist/src/playground/pages/SelectorsPage.d.ts.map +1 -0
- package/dist/test/components/control/input/new-dates/datePickerHelpers.test.d.ts +2 -0
- package/dist/test/components/control/input/new-dates/datePickerHelpers.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -652,7 +652,7 @@ function CwLoadingSmall(CwelltLoadingAppointements) {
|
|
|
652
652
|
return (jsxRuntime.jsx("div", { children: CwelltLoadingAppointements.isLoading === true ? (jsxRuntime.jsx("div", { className: "cw-loading-container", children: jsxRuntime.jsx("div", { className: "cw-loading" }) })) : (jsxRuntime.jsx("div", {})) }));
|
|
653
653
|
}
|
|
654
654
|
|
|
655
|
-
var styles$
|
|
655
|
+
var styles$q = {"cw-generic-tooltip-content":"cw-generic-tooltip-module__cw-generic-tooltip-content__la-Si","cw-generic-tooltip":"cw-generic-tooltip-module__cw-generic-tooltip__Ij76M"};
|
|
656
656
|
|
|
657
657
|
// Constants moved outside to prevent recreation
|
|
658
658
|
const margin$1 = 16;
|
|
@@ -775,12 +775,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
|
|
|
775
775
|
const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
|
|
776
776
|
setIsVisible(true);
|
|
777
777
|
}, showDelay);
|
|
778
|
-
const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$
|
|
778
|
+
const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$q["cw-generic-tooltip-content"]);
|
|
779
779
|
// Memoize tooltip content creation
|
|
780
780
|
const tooltipContent = React.useMemo(() => {
|
|
781
781
|
if (hide || !isVisible || !content)
|
|
782
782
|
return null;
|
|
783
|
-
return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$
|
|
783
|
+
return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$q["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
|
|
784
784
|
position: 'fixed',
|
|
785
785
|
top: `${tooltipPosition.top}px`,
|
|
786
786
|
left: `${tooltipPosition.left}px`,
|
|
@@ -795,10 +795,10 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
|
|
|
795
795
|
clearTooltipTimeout();
|
|
796
796
|
setIsVisible(false);
|
|
797
797
|
}, [clearTooltipTimeout]);
|
|
798
|
-
return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$
|
|
798
|
+
return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$q["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
|
|
799
799
|
};
|
|
800
800
|
|
|
801
|
-
var styles$
|
|
801
|
+
var styles$p = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
|
|
802
802
|
|
|
803
803
|
// Constants
|
|
804
804
|
const margin = 16;
|
|
@@ -1013,7 +1013,7 @@ const CwTooltipManager = () => {
|
|
|
1013
1013
|
if (!state.isVisible || !state.content) {
|
|
1014
1014
|
return null;
|
|
1015
1015
|
}
|
|
1016
|
-
return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$
|
|
1016
|
+
return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$p["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, style: {
|
|
1017
1017
|
top: `${tooltipPosition.top}px`,
|
|
1018
1018
|
left: `${tooltipPosition.left}px`,
|
|
1019
1019
|
opacity: (isPositioned && !isMeasuring) ? 1 : 0,
|
|
@@ -1081,7 +1081,7 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
|
|
|
1081
1081
|
React.useEffect(() => {
|
|
1082
1082
|
ensureTooltipManager();
|
|
1083
1083
|
}, []);
|
|
1084
|
-
return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$
|
|
1084
|
+
return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$p["cw-tooltip"], children: children }));
|
|
1085
1085
|
};
|
|
1086
1086
|
|
|
1087
1087
|
function CwButton({ text, variant = 'solid', color = 'primary', className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }) {
|
|
@@ -1134,7 +1134,7 @@ function CwModal(custModalProps) {
|
|
|
1134
1134
|
return (jsxRuntime.jsx("div", { children: custModalProps.modalState && (jsxRuntime.jsxs("div", { className: custModalProps.classNameModalOverlay + " cwelltModalOverlay", children: [jsxRuntime.jsx("div", { className: "cwelltModalOverlayBg", onClick: custModalProps.onCloseModal }), jsxRuntime.jsx(Draggable, { disabled: isModalDisabled, axis: "both", nodeRef: draggableRef, children: jsxRuntime.jsxs("div", { className: custModalProps.classNameModal + " cwelltContainerModal", ref: draggableRef, style: widthModalDef !== "40em" ? modalStyle.widthCustomStyle : modalStyle.widthDefStyle, children: [jsxRuntime.jsxs("div", { className: "cwelltModalHeader", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: [jsxRuntime.jsx("div", { className: "cwelltModalTitle", children: custModalProps.titleModal }), jsxRuntime.jsx("button", { className: "cwelltBtnCloseModal", onClick: custModalProps.onCloseModal, children: jsxRuntime.jsx("span", { className: "cwelltCloseIcon" }) })] }), jsxRuntime.jsx("div", { className: "cwelltModalBody", children: jsxRuntime.jsx("div", { className: "cwelltContainerModalBody", style: { position: "relative" }, children: custModalProps.children }) }), isHide === false ? (jsxRuntime.jsx("footer", { className: "legacy-modal-footer", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: custModalProps.onSaveModal, form: custModalProps.formSaveModal, hidden: custModalProps.HideBtnModal, type: custModalProps.HtmlSubmitModal }) })) : (jsxRuntime.jsx("div", { style: { display: "none" } }))] }) })] })) }));
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
1137
|
-
var styles$
|
|
1137
|
+
var styles$o = {"overlayPositioned":"CwConfirmationPopup-module__overlayPositioned__11qYB","popup":"CwConfirmationPopup-module__popup__ahPjM","message":"CwConfirmationPopup-module__message__MnNL4","buttons":"CwConfirmationPopup-module__buttons__fGYYE","button":"CwConfirmationPopup-module__button__ugYQE","confirmButton":"CwConfirmationPopup-module__confirmButton__rTP4S","cancelButton":"CwConfirmationPopup-module__cancelButton__Ry694"};
|
|
1138
1138
|
|
|
1139
1139
|
function CwConfirmationPopup(props) {
|
|
1140
1140
|
const { isOpen, onConfirm, onCancel, message = "Are you sure you want to proceed?", confirmText = "Confirm", cancelText = "Cancel", placement = 'bottom', children } = props;
|
|
@@ -1198,15 +1198,15 @@ function CwConfirmationPopup(props) {
|
|
|
1198
1198
|
onCancel();
|
|
1199
1199
|
}
|
|
1200
1200
|
};
|
|
1201
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$
|
|
1201
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$o.overlayPositioned, onClick: handleOverlayClick, children: jsxRuntime.jsxs("div", { ref: popupRef, className: styles$o.popup, style: {
|
|
1202
1202
|
position: 'absolute',
|
|
1203
1203
|
top: `${position.top}px`,
|
|
1204
1204
|
left: `${position.left}px`,
|
|
1205
1205
|
transform: 'none'
|
|
1206
|
-
}, children: [jsxRuntime.jsx("p", { className: styles$
|
|
1206
|
+
}, children: [jsxRuntime.jsx("p", { className: styles$o.message, children: message }), jsxRuntime.jsxs("div", { className: styles$o.buttons, children: [jsxRuntime.jsx("button", { className: `${styles$o.button} ${styles$o.confirmButton}`, onClick: onConfirm, children: confirmText }), jsxRuntime.jsx("button", { className: `${styles$o.button} ${styles$o.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
|
|
1207
1207
|
}
|
|
1208
1208
|
|
|
1209
|
-
var styles$
|
|
1209
|
+
var styles$n = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
|
|
1210
1210
|
|
|
1211
1211
|
// Helper function to parse size values
|
|
1212
1212
|
const parseSize = (size) => {
|
|
@@ -1479,7 +1479,7 @@ const CwDialog = props => {
|
|
|
1479
1479
|
}
|
|
1480
1480
|
}
|
|
1481
1481
|
}, [open]);
|
|
1482
|
-
const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$
|
|
1482
|
+
const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$n["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
|
|
1483
1483
|
const content = React.useMemo(() => (jsxRuntime.jsx("section", { children: children })), [children]);
|
|
1484
1484
|
const footer = React.useMemo(() => (jsxRuntime.jsx("footer", { children: customFooter || (jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: onSave, tooltipPosition: "top", disabled: disableSave, "data-testid": "cw-dialog-save" })) })), [customFooter, onSave, disableSave]);
|
|
1485
1485
|
const resizeHandles = React.useMemo(() => size.autoHeight
|
|
@@ -1506,7 +1506,7 @@ const CwDialog = props => {
|
|
|
1506
1506
|
: `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
|
|
1507
1507
|
return { displayWidth, displayHeight };
|
|
1508
1508
|
}, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
|
|
1509
|
-
const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$
|
|
1509
|
+
const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$n["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
|
|
1510
1510
|
left: `${position.x}px`,
|
|
1511
1511
|
top: `${position.y}px`,
|
|
1512
1512
|
width: displayDimensions.displayWidth,
|
|
@@ -1709,7 +1709,7 @@ function CwAlign(props) {
|
|
|
1709
1709
|
}, children: props.children }));
|
|
1710
1710
|
}
|
|
1711
1711
|
|
|
1712
|
-
var styles$
|
|
1712
|
+
var styles$m = {"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"};
|
|
1713
1713
|
|
|
1714
1714
|
/**
|
|
1715
1715
|
* CwCard - A simple card component for displaying content in a contained format
|
|
@@ -1733,11 +1733,11 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
|
|
|
1733
1733
|
// Construct class names using CSS modules
|
|
1734
1734
|
const cardClassNames = [
|
|
1735
1735
|
'cw-card',
|
|
1736
|
-
styles$
|
|
1736
|
+
styles$m.card,
|
|
1737
1737
|
className,
|
|
1738
|
-
clickable ? styles$
|
|
1739
|
-
disabled ? styles$
|
|
1740
|
-
isLoading ? styles$
|
|
1738
|
+
clickable ? styles$m.clickable : '',
|
|
1739
|
+
disabled ? styles$m.disabled : '',
|
|
1740
|
+
isLoading ? styles$m.loading : '',
|
|
1741
1741
|
].filter(Boolean).join(' ');
|
|
1742
1742
|
// Handle click event when card is clickable
|
|
1743
1743
|
const handleClick = () => {
|
|
@@ -1754,15 +1754,15 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
|
|
|
1754
1754
|
// Determine if footer should be rendered
|
|
1755
1755
|
const hasFooter = hasChips || footer || (hasActions && direction === "row");
|
|
1756
1756
|
// Actions component to reuse
|
|
1757
|
-
const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$
|
|
1757
|
+
const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$m.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;
|
|
1758
1758
|
return (jsxRuntime.jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && {
|
|
1759
1759
|
role: 'button',
|
|
1760
1760
|
tabIndex: 0,
|
|
1761
1761
|
onClick: handleClick,
|
|
1762
|
-
}), "data-variant": variant, "data-direction": direction, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$
|
|
1762
|
+
}), "data-variant": variant, "data-direction": direction, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$m.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$m.content, children: children }), hasFooter && (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$m.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$m.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$m.footerContent, children: footer }))] })), direction === "row" && ActionsComponent, isLoading && (jsxRuntime.jsx("div", { className: styles$m.loadingOverlay, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
|
|
1763
1763
|
};
|
|
1764
1764
|
|
|
1765
|
-
var styles$
|
|
1765
|
+
var styles$l = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","loading":"cw-card-list-module__loading__cYpND","emptyState":"cw-card-list-module__emptyState__RlqiS","sortControls":"cw-card-list-module__sortControls__mWgZA"};
|
|
1766
1766
|
|
|
1767
1767
|
function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', defaultCardWidth = 320, cardGap = 16, isLoading = false, emptyState, sortOptions = [], defaultSortKey, ...htmlProps }) {
|
|
1768
1768
|
const [currentPage, setCurrentPage] = React.useState(1);
|
|
@@ -1796,10 +1796,10 @@ function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', default
|
|
|
1796
1796
|
'--card-width': `${defaultCardWidth}px`,
|
|
1797
1797
|
'--card-gap': `${cardGap}px`
|
|
1798
1798
|
};
|
|
1799
|
-
return (jsxRuntime.jsxs("div", { ...htmlProps, children: [sortOptions.length > 0 && (jsxRuntime.jsxs("div", { className: styles$
|
|
1799
|
+
return (jsxRuntime.jsxs("div", { ...htmlProps, children: [sortOptions.length > 0 && (jsxRuntime.jsxs("div", { className: styles$l.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$l.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$l.loading, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$l.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$l.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx("div", { className: styles$l.cardWrapper, children: renderCard(item, index) }, index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$l.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$l.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" })] }))] }))] }));
|
|
1800
1800
|
}
|
|
1801
1801
|
|
|
1802
|
-
var styles$
|
|
1802
|
+
var styles$k = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
|
|
1803
1803
|
|
|
1804
1804
|
/**
|
|
1805
1805
|
*
|
|
@@ -1816,7 +1816,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
|
|
|
1816
1816
|
setVisible_accordionBody(!isVisible_accordionBody);
|
|
1817
1817
|
};
|
|
1818
1818
|
// #endregion
|
|
1819
|
-
return (jsxRuntime.jsxs("div", { className: styles$
|
|
1819
|
+
return (jsxRuntime.jsxs("div", { className: styles$k["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$k["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
|
|
1820
1820
|
}
|
|
1821
1821
|
|
|
1822
1822
|
/**
|
|
@@ -2020,15 +2020,6 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2020
2020
|
window.addEventListener("mousemove", onMouseMove);
|
|
2021
2021
|
window.addEventListener("mouseup", onMouseUp);
|
|
2022
2022
|
};
|
|
2023
|
-
const scrollContainerStyle = React.useMemo(() => {
|
|
2024
|
-
if (stickyHeader || scrollHeight) {
|
|
2025
|
-
return {
|
|
2026
|
-
maxHeight: scrollHeight ?? 300,
|
|
2027
|
-
overflowY: "auto"
|
|
2028
|
-
};
|
|
2029
|
-
}
|
|
2030
|
-
return {}; // no height or scroll
|
|
2031
|
-
}, [stickyHeader, scrollHeight]);
|
|
2032
2023
|
const getColSpan = () => columns.length + (expandedRowRender ? 1 : 0);
|
|
2033
2024
|
const hasClassNameRow = (item) => {
|
|
2034
2025
|
return typeof item === "object" && item !== null && "classNameRow" in item;
|
|
@@ -2057,23 +2048,21 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2057
2048
|
: "cwi-chevron-right"}` }) })), columns.map(col => (jsxRuntime.jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex] ?? "") : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsxRuntime.jsx("tr", { className: "cw-table-row-expanded", children: jsxRuntime.jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
|
|
2058
2049
|
});
|
|
2059
2050
|
};
|
|
2060
|
-
return (jsxRuntime.jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container ${classNameContainer ?? ""}`, style:
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
? "sortable"
|
|
2074
|
-
:
|
|
2075
|
-
? "sortable-asc"
|
|
2076
|
-
: "sortable-desc" }))] }), jsxRuntime.jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderTableBody() })] }) }), pagination && data.length > pageSizeOptions[0] && (jsxRuntime.jsxs("footer", { className: "cw-table-pagination", children: [jsxRuntime.jsxs("div", { className: "cw-table-pagination-size", children: [jsxRuntime.jsx(CwIcon, { iconId: "list" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsxRuntime.jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }), jsxRuntime.jsxs("div", { className: "cw-table-pagination-nav", children: [jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left-double" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left" }), jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", value: currentPage, onChange: (e) => {
|
|
2051
|
+
return (jsxRuntime.jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container${stickyHeader || scrollHeight ? " cw-table-scroll" : ""} ${classNameContainer ?? ""}`, style: { ...(scrollHeight ? { "--table-height": typeof scrollHeight === "number" ? `${scrollHeight}px` : scrollHeight } : {}), ...style }, children: [jsxRuntime.jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [expandedRowRender && jsxRuntime.jsx("th", {}), columns.map(col => (jsxRuntime.jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${sortConfig.key === col.dataIndex
|
|
2052
|
+
? sortConfig.direction
|
|
2053
|
+
: ""}`.trim(), style: {
|
|
2054
|
+
cursor: col.sortable ? "pointer" : "default",
|
|
2055
|
+
userSelect: "none",
|
|
2056
|
+
width: columnWidths[col.key] ?? col.width,
|
|
2057
|
+
...((col.width || columnWidths[col.key]) && {
|
|
2058
|
+
minWidth: 50,
|
|
2059
|
+
maxWidth: columnWidths[col.key] ?? col.width
|
|
2060
|
+
}),
|
|
2061
|
+
}, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsx("span", { children: col.title }), col.sortable && col.dataIndex && (jsxRuntime.jsx(CwIcon, { style: { fontSize: "1.25em" }, iconId: sortConfig.key !== col.dataIndex
|
|
2062
|
+
? "sortable"
|
|
2063
|
+
: sortConfig.direction === "asc"
|
|
2064
|
+
? "sortable-asc"
|
|
2065
|
+
: "sortable-desc" }))] }), jsxRuntime.jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderTableBody() })] }), pagination && data.length > pageSizeOptions[0] && (jsxRuntime.jsxs("footer", { className: "cw-table-pagination", children: [jsxRuntime.jsxs("div", { className: "cw-table-pagination-size", children: [jsxRuntime.jsx(CwIcon, { iconId: "list" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsxRuntime.jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }), jsxRuntime.jsxs("div", { className: "cw-table-pagination-nav", children: [jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left-double" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left" }), jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", value: currentPage, onChange: (e) => {
|
|
2077
2066
|
const value = parseInt(e.target.value, 10);
|
|
2078
2067
|
if (!isNaN(value))
|
|
2079
2068
|
handlePageChange(value);
|
|
@@ -2085,7 +2074,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2085
2074
|
}, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages === 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages === 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
|
|
2086
2075
|
}
|
|
2087
2076
|
|
|
2088
|
-
var styles$
|
|
2077
|
+
var styles$j = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","skeletonRow":"cw-sortable-table-module__skeletonRow__vyD0M","skeleton":"cw-sortable-table-module__skeleton__QGXAD","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
|
|
2089
2078
|
|
|
2090
2079
|
/**
|
|
2091
2080
|
* Hook that provides state management for CwSortableTable.
|
|
@@ -2148,9 +2137,9 @@ function useSortableTable(initialItems) {
|
|
|
2148
2137
|
}
|
|
2149
2138
|
|
|
2150
2139
|
// ─── Drop indicator row ───────────────────────────────────────────────────────
|
|
2151
|
-
const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$
|
|
2140
|
+
const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$j.dropIndicator, "aria-hidden": true, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", {}) }) }));
|
|
2152
2141
|
// ─── Loading skeleton ─────────────────────────────────────────────────────────
|
|
2153
|
-
const LoadingRows = ({ colSpan }) => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsxRuntime.jsx("tr", { className: styles$
|
|
2142
|
+
const LoadingRows = ({ colSpan }) => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsxRuntime.jsx("tr", { className: styles$j.skeletonRow, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", { className: styles$j.skeleton }) }) }, i))) }));
|
|
2154
2143
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
2155
2144
|
/**
|
|
2156
2145
|
* CwSortableTable
|
|
@@ -2237,11 +2226,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2237
2226
|
return items.map((item, index) => {
|
|
2238
2227
|
const key = item[rowKey];
|
|
2239
2228
|
const isDragging = draggedItem?.[rowKey] === key;
|
|
2240
|
-
return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$
|
|
2229
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$j.dragging : "", children: [showHandle && (jsxRuntime.jsx("td", { className: "cw-table-col-action", children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsxRuntime.jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
|
|
2241
2230
|
});
|
|
2242
2231
|
};
|
|
2243
2232
|
// ── Render ──────────────────────────────────────────────────────────────
|
|
2244
|
-
return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxRuntime.jsxs("footer", { className: styles$
|
|
2233
|
+
return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxRuntime.jsxs("footer", { className: styles$j.saveBar, children: [jsxRuntime.jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsxRuntime.jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
|
|
2245
2234
|
}
|
|
2246
2235
|
|
|
2247
2236
|
/**
|
|
@@ -2297,7 +2286,7 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2297
2286
|
*
|
|
2298
2287
|
* @returns React component
|
|
2299
2288
|
*/
|
|
2300
|
-
function CwTableServerSide({ columns, data, totalItems, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection, onChange, serverState, }) {
|
|
2289
|
+
function CwTableServerSide({ columns, data, totalItems, pagination = false, pageSizeOptions = [5, 10, 20, 50], pageLabel = "page", expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection, onChange, serverState, }) {
|
|
2301
2290
|
const [internalState, setInternalState] = React.useState({
|
|
2302
2291
|
page: 1,
|
|
2303
2292
|
pageSize: pageSizeOptions[0],
|
|
@@ -2446,10 +2435,10 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
|
|
|
2446
2435
|
if (isNaN(value) || value < 1 || value > totalPages) {
|
|
2447
2436
|
handlePageChange(1);
|
|
2448
2437
|
}
|
|
2449
|
-
}, min: 1, max: totalPages }), jsxRuntime.jsxs("span", { children: ["of ", totalPages] }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: state.pageSize, onChange: handleItemsPerPageChange, children: pageSizeOptions.map((size) => (jsxRuntime.
|
|
2438
|
+
}, min: 1, max: totalPages }), jsxRuntime.jsxs("span", { children: ["of ", totalPages] }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: state.pageSize, onChange: handleItemsPerPageChange, children: pageSizeOptions.map((size) => (jsxRuntime.jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }))] }));
|
|
2450
2439
|
}
|
|
2451
2440
|
|
|
2452
|
-
var styles$
|
|
2441
|
+
var styles$i = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
|
|
2453
2442
|
|
|
2454
2443
|
const TabIcon = ({ icon }) => {
|
|
2455
2444
|
if (!icon)
|
|
@@ -2499,7 +2488,7 @@ function CwTabs(CwTabsProps) {
|
|
|
2499
2488
|
const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
|
|
2500
2489
|
? { minWidth: CwTabsProps.tabsListWidth }
|
|
2501
2490
|
: undefined;
|
|
2502
|
-
return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$
|
|
2491
|
+
return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$i['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", 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, "data-tab-key": tab.key, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsxRuntime.jsx("span", { className: styles$i['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$i['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
|
|
2503
2492
|
}
|
|
2504
2493
|
|
|
2505
2494
|
/**
|
|
@@ -2523,10 +2512,10 @@ const CwExpandable = ({ briefing, onToggle, onOpen, onClose, children, ...detail
|
|
|
2523
2512
|
onClose?.(ev);
|
|
2524
2513
|
});
|
|
2525
2514
|
}, [onClose, onOpen, onToggle]);
|
|
2526
|
-
return (jsxRuntime.
|
|
2515
|
+
return (jsxRuntime.jsxs("details", { ref: myRef, ...detailsProps, className: "cw-expandable", children: [jsxRuntime.jsx("summary", { children: briefing }), children && jsxRuntime.jsx("section", { children: children })] }));
|
|
2527
2516
|
};
|
|
2528
2517
|
|
|
2529
|
-
var styles$
|
|
2518
|
+
var styles$h = {"cw-master-detail":"cw-master-detail-module__cw-master-detail__O8-FA","resizer":"cw-master-detail-module__resizer__hvGhL","detail":"cw-master-detail-module__detail__BG4Dm","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
|
|
2530
2519
|
|
|
2531
2520
|
const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, detailContent, emptyDetail, searchPlaceholder = 'Search...', onSearch, masterHeader, masterFooter, masterWidth: initialWidth = 320, minMasterWidth = 240, maxMasterWidth = 500, resizable = true, showSearch = true, }) => {
|
|
2532
2521
|
const [masterWidth, setMasterWidth] = React.useState(initialWidth);
|
|
@@ -2562,10 +2551,10 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
|
|
|
2562
2551
|
document.body.style.userSelect = '';
|
|
2563
2552
|
};
|
|
2564
2553
|
}, [isResizing, minMasterWidth, maxMasterWidth]);
|
|
2565
|
-
const rootClassName = [styles$
|
|
2566
|
-
return (jsxRuntime.jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxRuntime.jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsxRuntime.jsx("search", { children: jsxRuntime.jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsxRuntime.jsx("header", { children: masterHeader })), jsxRuntime.jsx("ul", { children: items.map((item) => (jsxRuntime.jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$
|
|
2554
|
+
const rootClassName = [styles$h['cw-master-detail'], className].filter(Boolean).join(' ');
|
|
2555
|
+
return (jsxRuntime.jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxRuntime.jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsxRuntime.jsx("search", { children: jsxRuntime.jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsxRuntime.jsx("header", { children: masterHeader })), jsxRuntime.jsx("ul", { children: items.map((item) => (jsxRuntime.jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$h.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsxRuntime.jsx("section", { className: styles$h.detail, children: selectedKey && detailContent
|
|
2567
2556
|
? detailContent
|
|
2568
|
-
: (jsxRuntime.jsx("div", { className: styles$
|
|
2557
|
+
: (jsxRuntime.jsx("div", { className: styles$h['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
|
|
2569
2558
|
};
|
|
2570
2559
|
|
|
2571
2560
|
/**
|
|
@@ -2589,7 +2578,7 @@ const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "
|
|
|
2589
2578
|
: emptyValue })] }, item.key))) }));
|
|
2590
2579
|
};
|
|
2591
2580
|
|
|
2592
|
-
var styles$
|
|
2581
|
+
var styles$g = {"sortableList":"cw-sortable-list-module__sortableList__PyLO-","sortableItem":"cw-sortable-list-module__sortableItem__FAnn2","readOnly":"cw-sortable-list-module__readOnly__r7GcH","dragging":"cw-sortable-list-module__dragging__MD715","moved":"cw-sortable-list-module__moved__sE6-N","expandedContent":"cw-sortable-list-module__expandedContent__Kocna","sortableHandle":"cw-sortable-list-module__sortableHandle__HvYBK","sortableContent":"cw-sortable-list-module__sortableContent__C6JhR","sortableTitle":"cw-sortable-list-module__sortableTitle__EgWXr","sortableExtraContent":"cw-sortable-list-module__sortableExtraContent__s4LSv","sortableActions":"cw-sortable-list-module__sortableActions__gwQOU","dropIndicator":"cw-sortable-list-module__dropIndicator__MNSF-","emptyMessage":"cw-sortable-list-module__emptyMessage__gMpaL"};
|
|
2593
2582
|
|
|
2594
2583
|
function CwSortableList({ items, onReorder, renderItem, className = '', movedItems = new Set(), emptyMessage = "No elements to show", readOnly = false, maxHeight = "300px", }) {
|
|
2595
2584
|
const [draggedItem, setDraggedItem] = React.useState(null);
|
|
@@ -2652,15 +2641,15 @@ function CwSortableList({ items, onReorder, renderItem, className = '', movedIte
|
|
|
2652
2641
|
}
|
|
2653
2642
|
};
|
|
2654
2643
|
if (items.length === 0) {
|
|
2655
|
-
return (jsxRuntime.jsx("div", { className: `${styles$
|
|
2644
|
+
return (jsxRuntime.jsx("div", { className: `${styles$g.sortableList} ${styles$g.emptyState} ${className}`, children: jsxRuntime.jsx("div", { className: styles$g.emptyMessage, children: emptyMessage }) }));
|
|
2656
2645
|
}
|
|
2657
|
-
return (jsxRuntime.jsx("div", { className: `${styles$
|
|
2646
|
+
return (jsxRuntime.jsx("div", { className: `${styles$g.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
|
|
2658
2647
|
const { title, extraContent, actions, showHandle = true, expandedContent } = renderItem(item);
|
|
2659
2648
|
const isDragging = draggedItem?.id === item.id;
|
|
2660
2649
|
const isMoved = movedItems.has(item.id);
|
|
2661
2650
|
const canExpand = Boolean(expandedContent);
|
|
2662
2651
|
const isExpanded = expandedItems.has(item.id);
|
|
2663
|
-
return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$
|
|
2652
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$g.dropIndicator }), jsxRuntime.jsxs("div", { className: `${styles$g.sortableItem} ${isDragging ? styles$g.dragging : ''} ${isMoved ? styles$g.moved : ''} ${readOnly ? styles$g.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxRuntime.jsxs("header", { children: [canExpand ? (jsxRuntime.jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsxRuntime.jsx("div", { className: styles$g.sortableHandle, children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxRuntime.jsxs("div", { className: styles$g.sortableContent, children: [jsxRuntime.jsx("div", { className: styles$g.sortableTitle, children: title }), extraContent && jsxRuntime.jsx("div", { className: styles$g.sortableExtraContent, children: extraContent })] }), jsxRuntime.jsx("div", { className: styles$g.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsxRuntime.jsx("div", { className: styles$g.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsxRuntime.jsx("div", { className: styles$g.dropIndicator }))] }, item.id));
|
|
2664
2653
|
}) }));
|
|
2665
2654
|
}
|
|
2666
2655
|
|
|
@@ -2837,7 +2826,7 @@ function CwFileUpload(fileUploadProps) {
|
|
|
2837
2826
|
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}`] }) })] }));
|
|
2838
2827
|
}
|
|
2839
2828
|
|
|
2840
|
-
var styles$
|
|
2829
|
+
var styles$f = {"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"};
|
|
2841
2830
|
|
|
2842
2831
|
const DEFAULT_LABELS = {
|
|
2843
2832
|
uploadDisabled: 'Upload disabled',
|
|
@@ -3004,12 +2993,12 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
3004
2993
|
}
|
|
3005
2994
|
}
|
|
3006
2995
|
};
|
|
3007
|
-
return (jsxRuntime.jsxs("div", { className: `${styles$
|
|
2996
|
+
return (jsxRuntime.jsxs("div", { className: `${styles$f.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$f.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxRuntime.jsxs("div", { className: `${styles$f.uploadArea} ${fileUploadProps.disabled ? styles$f.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$f.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxRuntime.jsxs("p", { className: `${styles$f.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxRuntime.jsxs("div", { className: styles$f.filesContainer, children: [jsxRuntime.jsxs("div", { className: styles$f.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$f.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$f.fileExtension, children: getFileExtension(existingFile) })] }), jsxRuntime.jsx("div", { className: styles$f.fileInfo, children: jsxRuntime.jsx("p", { className: styles$f.fileName, children: existingFile }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
|
|
3008
2997
|
setExistingFile(undefined);
|
|
3009
2998
|
if (fileUploadProps.onSelect) {
|
|
3010
2999
|
fileUploadProps.onSelect(null);
|
|
3011
3000
|
}
|
|
3012
|
-
}, disabled: fileUploadProps.disabled, className: styles$
|
|
3001
|
+
}, disabled: fileUploadProps.disabled, className: styles$f.smallButton })] }), jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxRuntime.jsxs("div", { className: styles$f.filesContainer, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsx("small", { className: styles$f.filesCount, children: labels.filesSelected(selectedFiles.length) }), jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll })] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$f.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$f.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$f.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$f.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$f.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$f.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$f.smallButton })] }, index))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
|
|
3013
3002
|
}
|
|
3014
3003
|
|
|
3015
3004
|
function CwInput(CwInputProps) {
|
|
@@ -3050,7 +3039,7 @@ function CwDigit(props) {
|
|
|
3050
3039
|
return (jsxRuntime.jsx("div", { className: "cw-input-text", children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsx("input", { type: "number", ...inputProps }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] }) }));
|
|
3051
3040
|
}
|
|
3052
3041
|
|
|
3053
|
-
var styles$
|
|
3042
|
+
var styles$e = {"colorPreview":"cw-color-picker-module__colorPreview__ylJcD","hueBar":"cw-color-picker-module__hueBar__bFhyC","hueBarSlider":"cw-color-picker-module__hueBarSlider__D53IV","colorPickerInteractiveArea":"cw-color-picker-module__colorPickerInteractiveArea__KZFR1","colorArea":"cw-color-picker-module__colorArea__xgpSE","colorAreaOverlay":"cw-color-picker-module__colorAreaOverlay__pmgOc","hueBackground":"cw-color-picker-module__hueBackground__Mks78","whiteGradient":"cw-color-picker-module__whiteGradient__Bt-fU","blackGradient":"cw-color-picker-module__blackGradient__VnEKJ","colorAreaCursor":"cw-color-picker-module__colorAreaCursor__lotg3"};
|
|
3054
3043
|
|
|
3055
3044
|
const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }) => {
|
|
3056
3045
|
const [rgb, setRgb] = React.useState({ r: 255, g: 255, b: 255 });
|
|
@@ -3253,13 +3242,13 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
|
|
|
3253
3242
|
// Calculate background color for the main area based on current hue
|
|
3254
3243
|
const hueColor = hsvToRgb(hsv.h, 100, 100);
|
|
3255
3244
|
const hueHex = rgbToHex(hueColor.r, hueColor.g, hueColor.b);
|
|
3256
|
-
return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$
|
|
3245
|
+
return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$e.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsxRuntime.jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsxRuntime.jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsxRuntime.jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxRuntime.jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "R:" }), jsxRuntime.jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "G:" }), jsxRuntime.jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "B:" }), jsxRuntime.jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxRuntime.jsxs("div", { className: styles$e.colorPickerInteractiveArea, children: [jsxRuntime.jsx("div", { className: styles$e.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsxRuntime.jsx("div", { className: styles$e.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxRuntime.jsxs("div", { className: styles$e.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxRuntime.jsxs("div", { className: styles$e.colorAreaOverlay, children: [jsxRuntime.jsx("div", { className: styles$e.hueBackground, style: { backgroundColor: hueHex } }), jsxRuntime.jsx("div", { className: styles$e.whiteGradient }), jsxRuntime.jsx("div", { className: styles$e.blackGradient })] }), jsxRuntime.jsx("div", { className: styles$e.colorAreaCursor, style: {
|
|
3257
3246
|
left: `${hsv.s}%`,
|
|
3258
3247
|
top: `${100 - hsv.v}%`
|
|
3259
3248
|
} })] })] })] }));
|
|
3260
3249
|
};
|
|
3261
3250
|
|
|
3262
|
-
var styles$
|
|
3251
|
+
var styles$d = {"container":"cw-input-color-module__container__x7gpk","selectColor":"cw-input-color-module__selectColor__DTo3V","disabled":"cw-input-color-module__disabled__O1fK5","readOnly":"cw-input-color-module__readOnly__HL-Bz","colorDropdown":"cw-input-color-module__colorDropdown__pX2bc"};
|
|
3263
3252
|
|
|
3264
3253
|
const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
|
|
3265
3254
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
@@ -3392,11 +3381,11 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
|
|
|
3392
3381
|
break;
|
|
3393
3382
|
}
|
|
3394
3383
|
};
|
|
3395
|
-
return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$
|
|
3384
|
+
return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$d.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$d.selectColor} ${disabled ? styles$d.disabled : ''} ${readOnly ? styles$d.readOnly : ''}`, style: {
|
|
3396
3385
|
width,
|
|
3397
3386
|
height,
|
|
3398
3387
|
backgroundColor: value,
|
|
3399
|
-
}, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$
|
|
3388
|
+
}, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$d.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsxRuntime.jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
|
|
3400
3389
|
};
|
|
3401
3390
|
|
|
3402
3391
|
/**
|
|
@@ -4037,7 +4026,7 @@ const CwImageArea = React.forwardRef((props, ref) => {
|
|
|
4037
4026
|
});
|
|
4038
4027
|
CwImageArea.displayName = "CwImageArea";
|
|
4039
4028
|
|
|
4040
|
-
var styles$
|
|
4029
|
+
var styles$c = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
|
|
4041
4030
|
|
|
4042
4031
|
/**
|
|
4043
4032
|
* This class represents a week where days can be selected or unselected
|
|
@@ -4177,15 +4166,15 @@ const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
|
|
|
4177
4166
|
setSelectedDays(newWeekdays);
|
|
4178
4167
|
onChange?.(newWeekdays.toString());
|
|
4179
4168
|
};
|
|
4180
|
-
return (jsxRuntime.jsx("div", { className: styles$
|
|
4169
|
+
return (jsxRuntime.jsx("div", { className: styles$c["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
|
|
4181
4170
|
};
|
|
4182
4171
|
|
|
4183
|
-
var styles$
|
|
4172
|
+
var styles$b = {"check-container":"cw-check-module__check-container__4nscZ","checkbox-group-container":"cw-check-module__checkbox-group-container__WMNbG"};
|
|
4184
4173
|
|
|
4185
4174
|
function CwCheck(props) {
|
|
4186
4175
|
const { labelProps, labelText, iconProps, alignment = "row", className, ...inputProps } = props;
|
|
4187
4176
|
const displayText = labelText || labelProps?.text;
|
|
4188
|
-
return (jsxRuntime.jsx("div", { className: `cw-check ${styles$
|
|
4177
|
+
return (jsxRuntime.jsx("div", { className: `cw-check ${styles$b["check-container"]}${className ? ` ${className}` : ''}`, children: jsxRuntime.jsxs("label", { "data-direction": alignment, children: [jsxRuntime.jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxRuntime.jsxs("span", { className: "cw-icon-text", children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), displayText] }))] }) }));
|
|
4189
4178
|
}
|
|
4190
4179
|
|
|
4191
4180
|
function CwCheckbox(CwCheckboxProps) {
|
|
@@ -4217,7 +4206,7 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, alignProps
|
|
|
4217
4206
|
: [];
|
|
4218
4207
|
const flexDirection = alignProps?.flexDirection ?? "row";
|
|
4219
4208
|
const dataDirection = { 'data-direction': flexDirection };
|
|
4220
|
-
return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$
|
|
4209
|
+
return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$b["checkbox-group-container"]}${className ? ` ${className}` : ''}`, ...dataDirection, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: `${optionsAlignment === "row" ? "cw-flex-column cw-gap-small" : "cw-flex-row cw-flex-wrap"}`, children: options.map((option) => (jsxRuntime.jsx(CwCheck, { labelText: option.label, checked: value.includes(option.value), disabled: disabled || option.disabled, alignment: optionsAlignment, onChange: (e) => handleChange(option.value, e.target.checked) }, option.value))) })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
|
|
4221
4210
|
}
|
|
4222
4211
|
|
|
4223
4212
|
function CwToggle(props) {
|
|
@@ -4235,13 +4224,16 @@ function CwToggle(props) {
|
|
|
4235
4224
|
* @example
|
|
4236
4225
|
* <CwSelect>
|
|
4237
4226
|
* <CwOption>A</CwOption>
|
|
4238
|
-
* <CwOption>
|
|
4227
|
+
* <CwOption color="#4a90d9">Blue option</CwOption>
|
|
4239
4228
|
* <CwOption>C</CwOption>
|
|
4240
4229
|
* </CwSelect>
|
|
4241
4230
|
*/
|
|
4242
4231
|
function CwOption(props) {
|
|
4243
|
-
const { text, ...optionProps } = props;
|
|
4244
|
-
|
|
4232
|
+
const { text, color, style, ...optionProps } = props;
|
|
4233
|
+
const mergedStyle = color
|
|
4234
|
+
? { ...style, backgroundColor: color, color: getContrastColor(color) }
|
|
4235
|
+
: style;
|
|
4236
|
+
return (jsxRuntime.jsx("option", { className: "cw-option", style: mergedStyle, ...optionProps, children: optionProps.children ?? text }));
|
|
4245
4237
|
}
|
|
4246
4238
|
|
|
4247
4239
|
/**
|
|
@@ -4275,7 +4267,248 @@ function CwSelect(props) {
|
|
|
4275
4267
|
: [];
|
|
4276
4268
|
const flexDirection = alignProps?.flexDirection ?? "row";
|
|
4277
4269
|
const dataDirection = { 'data-direction': flexDirection };
|
|
4278
|
-
|
|
4270
|
+
const { backgroundColor, color: textColor, ...wrapperStyle } = style ?? {};
|
|
4271
|
+
return (jsxRuntime.jsxs("div", { className: `cw-select${className ? ` ${className}` : ''}`, ...dataDirection, style: wrapperStyle, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: selectProps.required === true ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-gap-small cw-flex-grow", children: [jsxRuntime.jsxs("select", { ...selectProps, style: backgroundColor ? { backgroundColor, color: textColor } : undefined, children: [placeholder && jsxRuntime.jsx(CwOption, { value: "", children: placeholder }), children] }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
// ─── Default strategy: below anchor, match width, flip above if needed ────────
|
|
4275
|
+
function defaultPositionStrategy(anchorRect, panelRect) {
|
|
4276
|
+
const panelH = panelRect?.height ?? 200;
|
|
4277
|
+
const spaceBelow = window.innerHeight - anchorRect.bottom;
|
|
4278
|
+
const top = spaceBelow >= panelH + 4
|
|
4279
|
+
? anchorRect.bottom + 4
|
|
4280
|
+
: Math.max(4, anchorRect.top - panelH);
|
|
4281
|
+
const width = anchorRect.width;
|
|
4282
|
+
const left = Math.max(4, Math.min(anchorRect.left, window.innerWidth - width - 4));
|
|
4283
|
+
return { top, left, width };
|
|
4284
|
+
}
|
|
4285
|
+
// ─── Hook ─────────────────────────────────────────────────────────────────────
|
|
4286
|
+
/**
|
|
4287
|
+
* Generic portal-based dropdown panel hook.
|
|
4288
|
+
*
|
|
4289
|
+
* Renders the panel as a direct child of `<body>` via `createPortal` so it
|
|
4290
|
+
* escapes any `overflow: hidden/auto` ancestor (dialogs, tabs, cards, etc.).
|
|
4291
|
+
* Positions the panel with `position: fixed` computed from the anchor element's
|
|
4292
|
+
* `getBoundingClientRect()`, and repositions on scroll and resize.
|
|
4293
|
+
*
|
|
4294
|
+
* The fix pattern is the same as {@link usePickerPopup} used by `CwDatePicker`.
|
|
4295
|
+
*
|
|
4296
|
+
* > **Future migration note:** Once the project's minimum browser baseline
|
|
4297
|
+
* > reaches Firefox 147 / Safari 26 (CSS Anchor Positioning — Baseline 2026),
|
|
4298
|
+
* > this hook can be replaced with `popover="manual"` + CSS `anchor()` with
|
|
4299
|
+
* > zero JS positioning.
|
|
4300
|
+
*
|
|
4301
|
+
* @example
|
|
4302
|
+
* ```tsx
|
|
4303
|
+
* const wrapperRef = useRef<HTMLDivElement>(null);
|
|
4304
|
+
* const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
4305
|
+
* anchorRef: wrapperRef,
|
|
4306
|
+
* isOpen,
|
|
4307
|
+
* onClose: () => setIsOpen(false),
|
|
4308
|
+
* });
|
|
4309
|
+
*
|
|
4310
|
+
* return (
|
|
4311
|
+
* <div ref={wrapperRef}>
|
|
4312
|
+
* <input ... />
|
|
4313
|
+
* {renderPanel(
|
|
4314
|
+
* <div ref={panelRef} style={panelStyle} className={styles.dropdown}>
|
|
4315
|
+
* {options}
|
|
4316
|
+
* </div>
|
|
4317
|
+
* )}
|
|
4318
|
+
* </div>
|
|
4319
|
+
* );
|
|
4320
|
+
* ```
|
|
4321
|
+
*/
|
|
4322
|
+
function useDropdownPortal({ anchorRef, isOpen, onClose, positionStrategy = defaultPositionStrategy, }) {
|
|
4323
|
+
const panelRef = React.useRef(null);
|
|
4324
|
+
const [style, setStyle] = React.useState({
|
|
4325
|
+
position: "fixed",
|
|
4326
|
+
top: 0,
|
|
4327
|
+
left: 0,
|
|
4328
|
+
width: "auto",
|
|
4329
|
+
zIndex: 1000,
|
|
4330
|
+
right: "auto",
|
|
4331
|
+
marginLeft: 0,
|
|
4332
|
+
});
|
|
4333
|
+
const reposition = React.useCallback(() => {
|
|
4334
|
+
const anchor = anchorRef.current;
|
|
4335
|
+
if (!anchor)
|
|
4336
|
+
return;
|
|
4337
|
+
const anchorRect = anchor.getBoundingClientRect();
|
|
4338
|
+
const panelRect = panelRef.current?.getBoundingClientRect() ?? null;
|
|
4339
|
+
const { top, left, width } = positionStrategy(anchorRect, panelRect);
|
|
4340
|
+
setStyle({
|
|
4341
|
+
position: "fixed",
|
|
4342
|
+
top,
|
|
4343
|
+
left,
|
|
4344
|
+
width: width ?? "auto",
|
|
4345
|
+
zIndex: 1000,
|
|
4346
|
+
right: "auto",
|
|
4347
|
+
marginLeft: 0,
|
|
4348
|
+
});
|
|
4349
|
+
}, [anchorRef, positionStrategy]);
|
|
4350
|
+
// Reposition when opened; re-measure after first paint to get real panel size
|
|
4351
|
+
React.useEffect(() => {
|
|
4352
|
+
if (!isOpen)
|
|
4353
|
+
return;
|
|
4354
|
+
reposition();
|
|
4355
|
+
const raf = requestAnimationFrame(reposition);
|
|
4356
|
+
const handleUpdate = () => reposition();
|
|
4357
|
+
window.addEventListener("resize", handleUpdate);
|
|
4358
|
+
// Capture phase catches scroll on all scrollable ancestors
|
|
4359
|
+
window.addEventListener("scroll", handleUpdate, true);
|
|
4360
|
+
return () => {
|
|
4361
|
+
cancelAnimationFrame(raf);
|
|
4362
|
+
window.removeEventListener("resize", handleUpdate);
|
|
4363
|
+
window.removeEventListener("scroll", handleUpdate, true);
|
|
4364
|
+
};
|
|
4365
|
+
}, [isOpen, reposition]);
|
|
4366
|
+
// Close when the anchor scrolls out of view in any overflow container
|
|
4367
|
+
React.useEffect(() => {
|
|
4368
|
+
if (!isOpen)
|
|
4369
|
+
return;
|
|
4370
|
+
const anchor = anchorRef.current;
|
|
4371
|
+
if (!anchor)
|
|
4372
|
+
return;
|
|
4373
|
+
const observer = new IntersectionObserver(([entry]) => { if (!entry.isIntersecting)
|
|
4374
|
+
onClose(); }, { threshold: 0 });
|
|
4375
|
+
observer.observe(anchor);
|
|
4376
|
+
return () => observer.disconnect();
|
|
4377
|
+
}, [isOpen, anchorRef, onClose]);
|
|
4378
|
+
// Close on outside click (anchor + panel are both considered "inside")
|
|
4379
|
+
React.useEffect(() => {
|
|
4380
|
+
if (!isOpen)
|
|
4381
|
+
return;
|
|
4382
|
+
const handleMouseDown = (e) => {
|
|
4383
|
+
const target = e.target;
|
|
4384
|
+
if (anchorRef.current?.contains(target) || panelRef.current?.contains(target))
|
|
4385
|
+
return;
|
|
4386
|
+
onClose();
|
|
4387
|
+
};
|
|
4388
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4389
|
+
return () => document.removeEventListener("mousedown", handleMouseDown);
|
|
4390
|
+
}, [isOpen, onClose, anchorRef, panelRef]);
|
|
4391
|
+
const renderPanel = React.useCallback((children) => {
|
|
4392
|
+
if (!isOpen)
|
|
4393
|
+
return null;
|
|
4394
|
+
return reactDom.createPortal(children, document.body);
|
|
4395
|
+
}, [isOpen]);
|
|
4396
|
+
return { panelRef, panelStyle: style, renderPanel };
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
var dropdownStyles = {"dropdown":"cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-choice-dropdown-module__optionFocused__BYMxj","optionSelected":"cw-choice-dropdown-module__optionSelected__Lt8Xg","optionDisabled":"cw-choice-dropdown-module__optionDisabled__n3scM","searchBox":"cw-choice-dropdown-module__searchBox__0gox7","searchInput":"cw-choice-dropdown-module__searchInput__G5oRs","emptyState":"cw-choice-dropdown-module__emptyState__HO0Y7","colorCircle":"cw-choice-dropdown-module__colorCircle__x7mI9"};
|
|
4400
|
+
|
|
4401
|
+
/**
|
|
4402
|
+
* Custom dropdown component with colour-coded options, optional search filter, and full
|
|
4403
|
+
* keyboard navigation (↑ ↓ Enter Esc Tab).
|
|
4404
|
+
*
|
|
4405
|
+
* Use `CwDropdown` instead of the native `<select>` when options need colour indicators or
|
|
4406
|
+
* when inline search filtering is required.
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* <CwDropdown
|
|
4410
|
+
* options={[{ value: 'a', label: 'Option A', color: '#1976D2' }]}
|
|
4411
|
+
* value={selected}
|
|
4412
|
+
* onChange={setSelected}
|
|
4413
|
+
* labelProps={{ text: 'My Label' }}
|
|
4414
|
+
* />
|
|
4415
|
+
*/
|
|
4416
|
+
function CwDropdown({ options, value, onChange, labelProps, alignProps, placeholder = "Select...", allowSearch = false, disabled = false, required = false, feedback, className, style, ...otherProps }) {
|
|
4417
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
4418
|
+
const [searchText, setSearchText] = React.useState("");
|
|
4419
|
+
const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
|
|
4420
|
+
const containerRef = React.useRef(null);
|
|
4421
|
+
const wrapperRef = React.useRef(null);
|
|
4422
|
+
const inputRef = React.useRef(null);
|
|
4423
|
+
const highlightedItemRef = React.useRef(null);
|
|
4424
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
4425
|
+
anchorRef: wrapperRef,
|
|
4426
|
+
isOpen,
|
|
4427
|
+
onClose: () => { setIsOpen(false); setSearchText(""); setHighlightedIndex(-1); },
|
|
4428
|
+
});
|
|
4429
|
+
const selectedOption = options.find(opt => opt.value === value);
|
|
4430
|
+
// Filter options based on search
|
|
4431
|
+
const filteredOptions = searchText
|
|
4432
|
+
? options.filter(opt => opt.label.toLowerCase().includes(searchText.toLowerCase()))
|
|
4433
|
+
: options;
|
|
4434
|
+
// Feedback handling
|
|
4435
|
+
const feedbackMessages = feedback
|
|
4436
|
+
? Array.isArray(feedback) ? feedback : [feedback]
|
|
4437
|
+
: [];
|
|
4438
|
+
// Scroll highlighted item into view
|
|
4439
|
+
React.useEffect(() => {
|
|
4440
|
+
if (isOpen && highlightedItemRef.current) {
|
|
4441
|
+
highlightedItemRef.current.scrollIntoView({
|
|
4442
|
+
block: "nearest",
|
|
4443
|
+
behavior: "smooth",
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
}, [highlightedIndex, isOpen]);
|
|
4447
|
+
const handleTriggerClick = React.useCallback(() => {
|
|
4448
|
+
if (!disabled) {
|
|
4449
|
+
setIsOpen(!isOpen);
|
|
4450
|
+
setHighlightedIndex(-1);
|
|
4451
|
+
if (!isOpen && allowSearch) {
|
|
4452
|
+
setTimeout(() => inputRef.current?.focus(), 0);
|
|
4453
|
+
}
|
|
4454
|
+
}
|
|
4455
|
+
}, [isOpen, disabled, allowSearch]);
|
|
4456
|
+
const handleOptionSelect = React.useCallback((optionValue) => {
|
|
4457
|
+
const selected = options.find(opt => opt.value === optionValue);
|
|
4458
|
+
if (selected && !selected.disabled) {
|
|
4459
|
+
onChange?.(optionValue);
|
|
4460
|
+
setIsOpen(false);
|
|
4461
|
+
setSearchText("");
|
|
4462
|
+
setHighlightedIndex(-1);
|
|
4463
|
+
}
|
|
4464
|
+
}, [options, onChange]);
|
|
4465
|
+
const handleSearchChange = React.useCallback((e) => {
|
|
4466
|
+
setSearchText(e.target.value);
|
|
4467
|
+
setHighlightedIndex(-1);
|
|
4468
|
+
}, []);
|
|
4469
|
+
const handleKeyDown = React.useCallback((e) => {
|
|
4470
|
+
if (!isOpen) {
|
|
4471
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
4472
|
+
e.preventDefault();
|
|
4473
|
+
setIsOpen(true);
|
|
4474
|
+
}
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
switch (e.key) {
|
|
4478
|
+
case "ArrowDown":
|
|
4479
|
+
e.preventDefault();
|
|
4480
|
+
setHighlightedIndex(prev => prev < filteredOptions.length - 1 ? prev + 1 : 0);
|
|
4481
|
+
break;
|
|
4482
|
+
case "ArrowUp":
|
|
4483
|
+
e.preventDefault();
|
|
4484
|
+
setHighlightedIndex(prev => prev > 0 ? prev - 1 : filteredOptions.length - 1);
|
|
4485
|
+
break;
|
|
4486
|
+
case "Enter":
|
|
4487
|
+
e.preventDefault();
|
|
4488
|
+
if (highlightedIndex >= 0 && highlightedIndex < filteredOptions.length) {
|
|
4489
|
+
handleOptionSelect(filteredOptions[highlightedIndex].value);
|
|
4490
|
+
}
|
|
4491
|
+
break;
|
|
4492
|
+
case "Escape":
|
|
4493
|
+
e.preventDefault();
|
|
4494
|
+
setIsOpen(false);
|
|
4495
|
+
setSearchText("");
|
|
4496
|
+
setHighlightedIndex(-1);
|
|
4497
|
+
break;
|
|
4498
|
+
case "Tab":
|
|
4499
|
+
setIsOpen(false);
|
|
4500
|
+
setSearchText("");
|
|
4501
|
+
setHighlightedIndex(-1);
|
|
4502
|
+
break;
|
|
4503
|
+
}
|
|
4504
|
+
}, [isOpen, highlightedIndex, filteredOptions, handleOptionSelect]);
|
|
4505
|
+
const flexDirection = alignProps?.flexDirection ?? "row";
|
|
4506
|
+
return (jsxRuntime.jsxs("div", { ref: containerRef, className: `cw-dropdown${className ? ` ${className}` : ""}`, "data-direction": flexDirection, style: style, ...otherProps, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("button", { type: "button", className: "cw-dropdown-trigger", onClick: handleTriggerClick, onKeyDown: handleKeyDown, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": selectedOption?.label || placeholder, children: jsxRuntime.jsx("div", { className: "cw-dropdown-trigger-content", children: selectedOption ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [selectedOption.color && (jsxRuntime.jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: selectedOption.color } })), jsxRuntime.jsx("span", { children: selectedOption.label })] })) : (jsxRuntime.jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }) }), jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", paddingRight: "0.5rem", flexShrink: 0, cursor: disabled ? "not-allowed" : "pointer" }, onClick: handleTriggerClick, children: jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small" }) }), renderPanel(jsxRuntime.jsxs("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsxRuntime.jsx("div", { className: dropdownStyles.searchBox, children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: dropdownStyles.searchInput, autoComplete: "off" }) })), jsxRuntime.jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxRuntime.jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
|
|
4507
|
+
dropdownStyles.option,
|
|
4508
|
+
value === option.value ? dropdownStyles.optionSelected : "",
|
|
4509
|
+
highlightedIndex === index ? dropdownStyles.optionFocused : "",
|
|
4510
|
+
option.disabled ? dropdownStyles.optionDisabled : "",
|
|
4511
|
+
].filter(Boolean).join(" "), onClick: () => !option.disabled && handleOptionSelect(option.value), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": value === option.value, "aria-disabled": option.disabled, children: [option.color && (jsxRuntime.jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: option.color } })), jsxRuntime.jsx("span", { children: option.label })] }, option.value)))) : (jsxRuntime.jsx("li", { className: dropdownStyles.emptyState, children: "No options available" })) })] }))] })] }), feedbackMessages.map((item, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": item.type, children: item.message }, index)))] }));
|
|
4279
4512
|
}
|
|
4280
4513
|
|
|
4281
4514
|
function CwDropdownFilter(props) {
|
|
@@ -4288,7 +4521,7 @@ function CwDropdownFilter(props) {
|
|
|
4288
4521
|
return (jsxRuntime.jsxs("div", { id: props.IdContent, className: containerClassName, children: [props.children, isVisible && (jsxRuntime.jsx("nav", { className: "cw-dropdown-menu", style: inlineStyles, onMouseLeave: props.onMouseLeave, id: props.idDropDownFilter, role: "menu", children: jsxRuntime.jsx("ul", { role: "none", children: props.DataSourceDropDownItem?.map((item) => (jsxRuntime.jsx("li", { id: item.IdDropDown_filter, role: "menuitem", children: item.dropDownFilter_desc }, item.IdDropDown_filter))) }) }))] }));
|
|
4289
4522
|
}
|
|
4290
4523
|
|
|
4291
|
-
var styles$
|
|
4524
|
+
var styles$a = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
|
|
4292
4525
|
|
|
4293
4526
|
/**
|
|
4294
4527
|
* Button that toggles a floating panel with arbitrary children.
|
|
@@ -4335,7 +4568,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
|
|
|
4335
4568
|
}
|
|
4336
4569
|
panel.togglePopover();
|
|
4337
4570
|
}, [placement]);
|
|
4338
|
-
return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$
|
|
4571
|
+
return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$a.container, children: [jsxRuntime.jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsxRuntime.jsx("div", { ref: panelCallbackRef, className: `${styles$a.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
|
|
4339
4572
|
}
|
|
4340
4573
|
|
|
4341
4574
|
function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor, onPrimaryColor) {
|
|
@@ -4353,13 +4586,13 @@ function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor
|
|
|
4353
4586
|
return result;
|
|
4354
4587
|
}
|
|
4355
4588
|
|
|
4356
|
-
var styles$
|
|
4589
|
+
var styles$9 = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
|
|
4357
4590
|
|
|
4358
4591
|
const CwMultiFilterTag = props => {
|
|
4359
4592
|
const { ID, Name, Value, Category, Removable, PrimaryColor, Selectable, Selected } = props;
|
|
4360
4593
|
const backgroundColor = `rgb(${PrimaryColor.r},${PrimaryColor.g},${PrimaryColor.b})`;
|
|
4361
4594
|
const isOutlineMode = Selected && !Removable;
|
|
4362
|
-
return (jsxRuntime.jsx("li", { className: styles$
|
|
4595
|
+
return (jsxRuntime.jsx("li", { className: styles$9["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
|
|
4363
4596
|
if (Selectable)
|
|
4364
4597
|
props.OnSelect?.(props);
|
|
4365
4598
|
}, children: jsxRuntime.jsx(CwChip, { label: Name, colorScheme: "custom", customColor: backgroundColor, variant: isOutlineMode ? "outline" : "soft", closable: Removable, onClose: () => props.OnRemove?.(props),
|
|
@@ -4369,7 +4602,7 @@ const CwMultiFilterTag = props => {
|
|
|
4369
4602
|
} : undefined }) }));
|
|
4370
4603
|
};
|
|
4371
4604
|
|
|
4372
|
-
var styles$
|
|
4605
|
+
var styles$8 = {"cw-multi-filter-catalog-container":"cw-multi-filter-module__cw-multi-filter-catalog-container__S3nsq","cw-multi-filter":"cw-multi-filter-module__cw-multi-filter__zipBK","category-selected":"cw-multi-filter-module__category-selected__eYbes","cw-multi-filter-search":"cw-multi-filter-module__cw-multi-filter-search__eyHr0 cw-choice-input-box-module__inputBox__gHY9d"};
|
|
4373
4606
|
|
|
4374
4607
|
/**
|
|
4375
4608
|
* A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
|
|
@@ -4517,19 +4750,14 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4517
4750
|
const [selectedCategory, setSelectedCategory] = React.useState("All");
|
|
4518
4751
|
const componentRef = React.useRef(null);
|
|
4519
4752
|
const inputRef = React.useRef(null);
|
|
4753
|
+
const wrapperRef = React.useRef(null);
|
|
4754
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
4755
|
+
anchorRef: wrapperRef,
|
|
4756
|
+
isOpen: isPanelOpen,
|
|
4757
|
+
onClose: () => { setIsPanelOpen(false); setFilteredTags(getUnselectedAll()); setSelectedCategory("All"); setInputTextValue(""); },
|
|
4758
|
+
});
|
|
4520
4759
|
React.useEffect(() => {
|
|
4521
|
-
|
|
4522
|
-
if (componentRef.current && !componentRef.current.contains(event.target)) {
|
|
4523
|
-
setIsPanelOpen(false);
|
|
4524
|
-
setFilteredTags(new Set());
|
|
4525
|
-
setSelectedCategory("All");
|
|
4526
|
-
setInputTextValue("");
|
|
4527
|
-
}
|
|
4528
|
-
}
|
|
4529
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
4530
|
-
return () => {
|
|
4531
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
4532
|
-
};
|
|
4760
|
+
// Outside-click is now handled by useDropdownPortal
|
|
4533
4761
|
}, []);
|
|
4534
4762
|
const categoriesMappedToTags = () => {
|
|
4535
4763
|
const categoriesMap = new Map();
|
|
@@ -4540,9 +4768,10 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4540
4768
|
});
|
|
4541
4769
|
return categoriesMap;
|
|
4542
4770
|
};
|
|
4771
|
+
const getUnselectedAll = (excluded = selectedTags) => new Set(Array.from(allTags).filter(tag => !Array.from(excluded).some(t => t.ID === tag.ID)));
|
|
4543
4772
|
const handleClickCategory = (category) => {
|
|
4544
4773
|
setSelectedCategory(category);
|
|
4545
|
-
setFilteredTags(category
|
|
4774
|
+
setFilteredTags(category !== "All" ? (categoriesMappedToTags().get(category) ?? new Set()) : getUnselectedAll());
|
|
4546
4775
|
};
|
|
4547
4776
|
const rgbAString = (r, g, b) => {
|
|
4548
4777
|
return `rgb(${r}, ${g}, ${b})`;
|
|
@@ -4574,7 +4803,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4574
4803
|
setFilteredTags(new Set(newFilterTags));
|
|
4575
4804
|
}
|
|
4576
4805
|
else {
|
|
4577
|
-
setFilteredTags(
|
|
4806
|
+
setFilteredTags(getUnselectedAll());
|
|
4578
4807
|
}
|
|
4579
4808
|
};
|
|
4580
4809
|
const addTag = (newTag) => {
|
|
@@ -4588,7 +4817,13 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4588
4817
|
const updatedTags = new Set(selectedTags).add(newTag);
|
|
4589
4818
|
onChangeSelectedTags(updatedTags);
|
|
4590
4819
|
setInputTextValue("");
|
|
4591
|
-
|
|
4820
|
+
setFilteredTags(selectedCategory === "All" ? getUnselectedAll(updatedTags) : prev => {
|
|
4821
|
+
const next = new Set(prev);
|
|
4822
|
+
const toRemove = Array.from(next).find(t => t.ID === newTag.ID);
|
|
4823
|
+
if (toRemove)
|
|
4824
|
+
next.delete(toRemove);
|
|
4825
|
+
return next;
|
|
4826
|
+
});
|
|
4592
4827
|
}
|
|
4593
4828
|
};
|
|
4594
4829
|
const removeTag = (id) => {
|
|
@@ -4612,9 +4847,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4612
4847
|
inputRef.current?.focus();
|
|
4613
4848
|
}
|
|
4614
4849
|
};
|
|
4615
|
-
return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, className: `${styles$
|
|
4850
|
+
return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, className: `${styles$8["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
|
|
4616
4851
|
e.preventDefault();
|
|
4617
|
-
}, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, className: styles$
|
|
4852
|
+
}, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$8["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxRuntime.jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (React.createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsxRuntime.jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
|
|
4618
4853
|
switch (e.key) {
|
|
4619
4854
|
case "Enter":
|
|
4620
4855
|
case "Tab": {
|
|
@@ -4641,21 +4876,10 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4641
4876
|
break;
|
|
4642
4877
|
}
|
|
4643
4878
|
}
|
|
4644
|
-
} })] }), selectedTags.size > 0
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
? {
|
|
4649
|
-
backgroundColor: getColor(category).primary,
|
|
4650
|
-
color: getColor(category).onPrimary,
|
|
4651
|
-
outline: "2px solid " + getColor(category).onPrimary,
|
|
4652
|
-
outlineOffset: "-2px",
|
|
4653
|
-
fontWeight: 400
|
|
4654
|
-
}
|
|
4655
|
-
: {
|
|
4656
|
-
backgroundColor: getColor(category).primary,
|
|
4657
|
-
color: getColor(category).onPrimary,
|
|
4658
|
-
}, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsxRuntime.jsx("ul", { children: Array.from(filteredTags)
|
|
4879
|
+
} })] }), selectedTags.size > 0 && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxRuntime.jsxs("section", { ref: panelRef, className: styles$8["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxRuntime.jsxs("nav", { children: [jsxRuntime.jsx("button", { className: selectedCategory === "All" ? styles$8["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsxRuntime.jsx("button", { className: selectedCategory === category ? styles$8["category-selected"] : undefined, style: {
|
|
4880
|
+
backgroundColor: getColor(category).primary,
|
|
4881
|
+
color: getColor(category).onPrimary,
|
|
4882
|
+
}, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsxRuntime.jsx("ul", { children: Array.from(filteredTags)
|
|
4659
4883
|
.sort((a, b) => {
|
|
4660
4884
|
const input = inputTextValue.trim().toLowerCase();
|
|
4661
4885
|
const aName = a.Name.trim().toLowerCase();
|
|
@@ -4675,9 +4899,148 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4675
4899
|
removeTag(props.ID);
|
|
4676
4900
|
else
|
|
4677
4901
|
addTag(props);
|
|
4678
|
-
} }, props.ID))) })] })] }));
|
|
4902
|
+
} }, props.ID))) })] }))] }));
|
|
4679
4903
|
};
|
|
4680
4904
|
|
|
4905
|
+
var styles$7 = {"container":"cw-tag-selector-module__container__-do8i","inputBox":"cw-tag-selector-module__inputBox__3NGz9 cw-choice-input-box-module__inputBox__gHY9d","disabled":"cw-tag-selector-module__disabled__vbud9 cw-choice-input-box-module__disabled__TFAnC","dropdown":"cw-tag-selector-module__dropdown__X6Dob cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-tag-selector-module__option__2UQ7g cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-tag-selector-module__optionFocused__8-lv8 cw-choice-dropdown-module__optionFocused__BYMxj","optionDot":"cw-tag-selector-module__optionDot__CdFlG cw-choice-dropdown-module__colorCircle__x7mI9","selectAll":"cw-tag-selector-module__selectAll__HyvMA"};
|
|
4906
|
+
|
|
4907
|
+
/**
|
|
4908
|
+
* Multi-select input with chip tags and searchable dropdown.
|
|
4909
|
+
* Works like a Kendo MultiSelect: selected items appear as removable chips
|
|
4910
|
+
* inside the input area, and a filtered dropdown lets the user pick more.
|
|
4911
|
+
*
|
|
4912
|
+
* @example
|
|
4913
|
+
* ```tsx
|
|
4914
|
+
* const options = [
|
|
4915
|
+
* { value: "1", label: "Alpha" },
|
|
4916
|
+
* { value: "2", label: "Bravo" },
|
|
4917
|
+
* { value: "3", label: "Charlie" },
|
|
4918
|
+
* ];
|
|
4919
|
+
* const [selected, setSelected] = useState<string[]>([]);
|
|
4920
|
+
*
|
|
4921
|
+
* <CwTagSelector
|
|
4922
|
+
* labelProps={{ text: "Tags" }}
|
|
4923
|
+
* options={options}
|
|
4924
|
+
* value={selected}
|
|
4925
|
+
* onChange={setSelected}
|
|
4926
|
+
* placeholder="Select items…"
|
|
4927
|
+
* />
|
|
4928
|
+
* ```
|
|
4929
|
+
*/
|
|
4930
|
+
function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, alignProps, placeholder = "Select…", disabled = false, showSelectAll = false, feedback, className, style, }) {
|
|
4931
|
+
const [search, setSearch] = React.useState("");
|
|
4932
|
+
const [open, setOpen] = React.useState(false);
|
|
4933
|
+
const [focusedIndex, setFocusedIndex] = React.useState(-1);
|
|
4934
|
+
const containerRef = React.useRef(null);
|
|
4935
|
+
const inputBoxRef = React.useRef(null);
|
|
4936
|
+
const inputRef = React.useRef(null);
|
|
4937
|
+
const listRef = React.useRef(null);
|
|
4938
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
4939
|
+
anchorRef: inputBoxRef,
|
|
4940
|
+
isOpen: open,
|
|
4941
|
+
onClose: () => { setOpen(false); setFocusedIndex(-1); },
|
|
4942
|
+
});
|
|
4943
|
+
const selectedSet = React.useMemo(() => new Set(value), [value]);
|
|
4944
|
+
const filtered = React.useMemo(() => {
|
|
4945
|
+
if (!search)
|
|
4946
|
+
return options.filter(o => !selectedSet.has(o.value));
|
|
4947
|
+
const lower = search.toLowerCase();
|
|
4948
|
+
return options.filter(o => !selectedSet.has(o.value) && o.label.toLowerCase().includes(lower));
|
|
4949
|
+
}, [options, selectedSet, search]);
|
|
4950
|
+
const selectedOptions = React.useMemo(() => value.map(v => options.find(o => o.value === v)).filter(Boolean), [value, options]);
|
|
4951
|
+
const handleSelect = React.useCallback((optionValue) => {
|
|
4952
|
+
onChange([...value, optionValue]);
|
|
4953
|
+
setSearch("");
|
|
4954
|
+
setFocusedIndex(-1);
|
|
4955
|
+
inputRef.current?.focus();
|
|
4956
|
+
}, [value, onChange]);
|
|
4957
|
+
const handleRemove = React.useCallback((optionValue) => {
|
|
4958
|
+
onChange(value.filter(v => v !== optionValue));
|
|
4959
|
+
inputRef.current?.focus();
|
|
4960
|
+
}, [value, onChange]);
|
|
4961
|
+
const allSelected = options.length > 0 && options.every(o => selectedSet.has(o.value));
|
|
4962
|
+
const handleToggleAll = React.useCallback(() => {
|
|
4963
|
+
if (allSelected) {
|
|
4964
|
+
onChange([]);
|
|
4965
|
+
}
|
|
4966
|
+
else {
|
|
4967
|
+
onChange(options.map(o => o.value));
|
|
4968
|
+
}
|
|
4969
|
+
setSearch("");
|
|
4970
|
+
setFocusedIndex(-1);
|
|
4971
|
+
inputRef.current?.focus();
|
|
4972
|
+
}, [allSelected, options, onChange]);
|
|
4973
|
+
const handleInputChange = React.useCallback((e) => {
|
|
4974
|
+
setSearch(e.currentTarget.value);
|
|
4975
|
+
if (!open)
|
|
4976
|
+
setOpen(true);
|
|
4977
|
+
setFocusedIndex(-1);
|
|
4978
|
+
}, [open]);
|
|
4979
|
+
const handleInputFocus = React.useCallback(() => {
|
|
4980
|
+
if (!disabled)
|
|
4981
|
+
setOpen(true);
|
|
4982
|
+
}, [disabled]);
|
|
4983
|
+
const handleKeyDown = React.useCallback((e) => {
|
|
4984
|
+
if (e.key === "Backspace" && !search && value.length > 0) {
|
|
4985
|
+
onChange(value.slice(0, -1));
|
|
4986
|
+
return;
|
|
4987
|
+
}
|
|
4988
|
+
if (e.key === "Escape") {
|
|
4989
|
+
setOpen(false);
|
|
4990
|
+
setFocusedIndex(-1);
|
|
4991
|
+
return;
|
|
4992
|
+
}
|
|
4993
|
+
if (e.key === "Enter") {
|
|
4994
|
+
e.preventDefault();
|
|
4995
|
+
if (focusedIndex >= 0 && focusedIndex < filtered.length) {
|
|
4996
|
+
handleSelect(filtered[focusedIndex].value);
|
|
4997
|
+
}
|
|
4998
|
+
else if (search.trim().length > 0 && filtered.length > 0) {
|
|
4999
|
+
const lower = search.trim().toLowerCase();
|
|
5000
|
+
const match = filtered.find(o => o.label.trim().toLowerCase() === lower) ??
|
|
5001
|
+
filtered.find(o => o.label.trim().toLowerCase().startsWith(lower)) ??
|
|
5002
|
+
filtered[0];
|
|
5003
|
+
if (match)
|
|
5004
|
+
handleSelect(match.value);
|
|
5005
|
+
}
|
|
5006
|
+
else if (!open) {
|
|
5007
|
+
setOpen(true);
|
|
5008
|
+
setFocusedIndex(0);
|
|
5009
|
+
}
|
|
5010
|
+
return;
|
|
5011
|
+
}
|
|
5012
|
+
if (!open) {
|
|
5013
|
+
if (e.key === "ArrowDown") {
|
|
5014
|
+
setOpen(true);
|
|
5015
|
+
setFocusedIndex(0);
|
|
5016
|
+
e.preventDefault();
|
|
5017
|
+
}
|
|
5018
|
+
return;
|
|
5019
|
+
}
|
|
5020
|
+
if (e.key === "ArrowDown") {
|
|
5021
|
+
e.preventDefault();
|
|
5022
|
+
setFocusedIndex(prev => (prev < filtered.length - 1 ? prev + 1 : prev));
|
|
5023
|
+
}
|
|
5024
|
+
else if (e.key === "ArrowUp") {
|
|
5025
|
+
e.preventDefault();
|
|
5026
|
+
setFocusedIndex(prev => (prev > 0 ? prev - 1 : 0));
|
|
5027
|
+
}
|
|
5028
|
+
}, [open, search, value, filtered, focusedIndex, onChange, handleSelect]);
|
|
5029
|
+
// Scroll focused item into view
|
|
5030
|
+
React.useEffect(() => {
|
|
5031
|
+
if (focusedIndex >= 0 && listRef.current) {
|
|
5032
|
+
const item = listRef.current.children[focusedIndex];
|
|
5033
|
+
item?.scrollIntoView({ block: "nearest" });
|
|
5034
|
+
}
|
|
5035
|
+
}, [focusedIndex]);
|
|
5036
|
+
// Close on outside click — now handled by useDropdownPortal
|
|
5037
|
+
// Keeping containerRef for any other potential use
|
|
5038
|
+
const direction = alignProps?.flexDirection ?? "row";
|
|
5039
|
+
const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
|
|
5040
|
+
return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$7.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: `${styles$7.inputBox}${disabled ? ` ${styles$7.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
|
|
5041
|
+
inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$7.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$7.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$7.option}${idx === focusedIndex ? ` ${styles$7.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$7.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
|
|
5042
|
+
}
|
|
5043
|
+
|
|
4681
5044
|
var styles$6 = {"tree-container":"cw-tree-view-module__tree-container__NN-HJ","tree-wrapper":"cw-tree-view-module__tree-wrapper__keBZI","tree-item":"cw-tree-view-module__tree-item__prE9N","tree-node":"cw-tree-view-module__tree-node__wfro9","selected":"cw-tree-view-module__selected__XJQ0w","non-selectable":"cw-tree-view-module__non-selectable__YuPSx","tree-children":"cw-tree-view-module__tree-children__ji8CZ","empty-state":"cw-tree-view-module__empty-state__yvRjo","tree-label":"cw-tree-view-module__tree-label__ss3Nf","tree-spacer":"cw-tree-view-module__tree-spacer__E9Ud2"};
|
|
4682
5045
|
|
|
4683
5046
|
function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId: initialSelectedId = null }) {
|
|
@@ -4784,12 +5147,30 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
|
|
|
4784
5147
|
return (jsxRuntime.jsxs("div", { className: `cw-tree-view ${styles$6["tree-container"]}`, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsxRuntime.jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsxRuntime.jsx("div", { className: styles$6["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxRuntime.jsxs("div", { className: styles$6["empty-state"], children: [jsxRuntime.jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
|
|
4785
5148
|
}
|
|
4786
5149
|
|
|
5150
|
+
/**
|
|
5151
|
+
* Text input with a live-filtered suggestion dropdown backed by a local `CwSelectList` array.
|
|
5152
|
+
* Use `CwFindAirport` or `CwFindCrewmember` for API-backed search inputs.
|
|
5153
|
+
*
|
|
5154
|
+
* @example
|
|
5155
|
+
* <CwSearchInput
|
|
5156
|
+
* selectList={myItems}
|
|
5157
|
+
* handleChange={(id) => console.log('selected', id)}
|
|
5158
|
+
* labelProps={{ text: 'Employee' }}
|
|
5159
|
+
* placeholder="Search by name…"
|
|
5160
|
+
* />
|
|
5161
|
+
*/
|
|
4787
5162
|
function CwSearchInput(optionsProps) {
|
|
4788
5163
|
const [searchText, setSearchText] = React.useState("");
|
|
4789
5164
|
const [filteredOptions, setFilteredOptions] = React.useState([]);
|
|
4790
5165
|
const [_selectedOption, setSelectedOption] = React.useState(null);
|
|
4791
5166
|
const [showDropdown, setShowDropdown] = React.useState(false);
|
|
4792
5167
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
5168
|
+
const wrapperRef = React.useRef(null);
|
|
5169
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
5170
|
+
anchorRef: wrapperRef,
|
|
5171
|
+
isOpen: showDropdown && filteredOptions.length > 0,
|
|
5172
|
+
onClose: () => setShowDropdown(false),
|
|
5173
|
+
});
|
|
4793
5174
|
// Extract props
|
|
4794
5175
|
const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, ...otherProps } = optionsProps;
|
|
4795
5176
|
// Get direction for data attribute
|
|
@@ -4840,9 +5221,8 @@ function CwSearchInput(optionsProps) {
|
|
|
4840
5221
|
}
|
|
4841
5222
|
};
|
|
4842
5223
|
const handleInputBlur = () => {
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
}, 150);
|
|
5224
|
+
// Dropdown is closed by useDropdownPortal's outside-click handler.
|
|
5225
|
+
// Blur alone must not close it — clicking an option would lose focus before the click fires.
|
|
4846
5226
|
};
|
|
4847
5227
|
const handleOptionSelect = (option) => {
|
|
4848
5228
|
setSearchText(option.description);
|
|
@@ -4860,7 +5240,7 @@ function CwSearchInput(optionsProps) {
|
|
|
4860
5240
|
handleChange("");
|
|
4861
5241
|
}
|
|
4862
5242
|
};
|
|
4863
|
-
return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, id: id, ...otherProps, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", children: [jsxRuntime.jsx("input", { type: "text", value: searchText, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled }), isLoading && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsxRuntime.jsx(CwIcon, { ...iconProps }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] })] }),
|
|
5243
|
+
return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, id: id, ...otherProps, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("input", { type: "text", value: searchText, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled }), isLoading && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsxRuntime.jsx(CwIcon, { ...iconProps }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, children: jsxRuntime.jsx("ul", { children: filteredOptions.map((option) => (jsxRuntime.jsx("li", { className: dropdownStyles.option, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
|
|
4864
5244
|
}
|
|
4865
5245
|
|
|
4866
5246
|
var styles$5 = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
|
|
@@ -5117,81 +5497,49 @@ var styles$4 = {"pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","
|
|
|
5117
5497
|
/**
|
|
5118
5498
|
* Renders a picker popup in a portal so it escapes overflow containers.
|
|
5119
5499
|
* Positions itself relative to the anchor element.
|
|
5500
|
+
*
|
|
5501
|
+
* Thin wrapper around {@link useDropdownPortal} that adds directional
|
|
5502
|
+
* preference logic ("left-bottom", "right-top", etc.) for calendar popups.
|
|
5503
|
+
* The public API is unchanged — existing callers (`CwDatePicker`, etc.) need
|
|
5504
|
+
* no modifications.
|
|
5120
5505
|
*/
|
|
5121
5506
|
function usePickerPopup({ anchorRef, isOpen, onClose, position = "left-bottom" }) {
|
|
5122
|
-
const
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
const anchor = anchorRef.current;
|
|
5126
|
-
const popup = popupRef.current;
|
|
5127
|
-
if (!anchor || !popup)
|
|
5128
|
-
return;
|
|
5129
|
-
const rect = anchor.getBoundingClientRect();
|
|
5130
|
-
const popupRect = popup.getBoundingClientRect();
|
|
5131
|
-
// Determine vertical placement
|
|
5507
|
+
const pickerStrategy = React.useCallback((anchorRect, panelRect) => {
|
|
5508
|
+
const popupH = panelRect?.height ?? 300;
|
|
5509
|
+
const popupW = panelRect?.width ?? 300;
|
|
5132
5510
|
const preferTop = position.includes("top");
|
|
5133
|
-
const spaceBelow = window.innerHeight -
|
|
5134
|
-
const spaceAbove =
|
|
5135
|
-
const popupH = popupRect.height || 300; // fallback for first render
|
|
5511
|
+
const spaceBelow = window.innerHeight - anchorRect.bottom;
|
|
5512
|
+
const spaceAbove = anchorRect.top;
|
|
5136
5513
|
let top;
|
|
5137
5514
|
if (preferTop && spaceAbove >= popupH) {
|
|
5138
|
-
top =
|
|
5515
|
+
top = anchorRect.top - popupH;
|
|
5139
5516
|
}
|
|
5140
5517
|
else if (!preferTop && spaceBelow >= popupH + 4) {
|
|
5141
|
-
top =
|
|
5518
|
+
top = anchorRect.bottom + 4;
|
|
5142
5519
|
}
|
|
5143
5520
|
else {
|
|
5144
|
-
|
|
5145
|
-
top = spaceBelow >= popupH + 4 ? rect.bottom + 4 : rect.top - popupH;
|
|
5521
|
+
top = spaceBelow >= popupH + 4 ? anchorRect.bottom + 4 : anchorRect.top - popupH;
|
|
5146
5522
|
}
|
|
5147
|
-
// Determine horizontal placement
|
|
5148
5523
|
let left;
|
|
5149
5524
|
if (position.includes("right")) {
|
|
5150
|
-
left =
|
|
5525
|
+
left = anchorRect.right - popupW;
|
|
5151
5526
|
}
|
|
5152
5527
|
else {
|
|
5153
|
-
left =
|
|
5528
|
+
left = anchorRect.left;
|
|
5154
5529
|
}
|
|
5155
|
-
|
|
5156
|
-
left = Math.max(4, Math.min(left, window.innerWidth - (popupRect.width || 200) - 4));
|
|
5530
|
+
left = Math.max(4, Math.min(left, window.innerWidth - popupW - 4));
|
|
5157
5531
|
top = Math.max(4, top);
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
window.addEventListener("scroll", handleUpdate, true); // capture phase catches all scrollable ancestors
|
|
5170
|
-
return () => {
|
|
5171
|
-
window.removeEventListener("resize", handleUpdate);
|
|
5172
|
-
window.removeEventListener("scroll", handleUpdate, true);
|
|
5173
|
-
};
|
|
5174
|
-
}, [isOpen, reposition]);
|
|
5175
|
-
// Close on outside click — checks both anchor and popup
|
|
5176
|
-
React.useEffect(() => {
|
|
5177
|
-
if (!isOpen)
|
|
5178
|
-
return;
|
|
5179
|
-
const handleMouseDown = (e) => {
|
|
5180
|
-
const target = e.target;
|
|
5181
|
-
if (anchorRef.current?.contains(target) ||
|
|
5182
|
-
popupRef.current?.contains(target))
|
|
5183
|
-
return;
|
|
5184
|
-
onClose();
|
|
5185
|
-
};
|
|
5186
|
-
document.addEventListener("mousedown", handleMouseDown);
|
|
5187
|
-
return () => document.removeEventListener("mousedown", handleMouseDown);
|
|
5188
|
-
}, [isOpen, onClose, anchorRef]);
|
|
5189
|
-
const renderPopup = React.useCallback((children) => {
|
|
5190
|
-
if (!isOpen)
|
|
5191
|
-
return null;
|
|
5192
|
-
return reactDom.createPortal(children, document.body);
|
|
5193
|
-
}, [isOpen]);
|
|
5194
|
-
return { popupRef, popupStyle: style, renderPopup };
|
|
5532
|
+
// No width override — the calendar has its own intrinsic size
|
|
5533
|
+
return { top, left };
|
|
5534
|
+
}, [position]);
|
|
5535
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
5536
|
+
anchorRef,
|
|
5537
|
+
isOpen,
|
|
5538
|
+
onClose,
|
|
5539
|
+
positionStrategy: pickerStrategy,
|
|
5540
|
+
});
|
|
5541
|
+
// Expose original API names so CwDatePicker needs zero changes
|
|
5542
|
+
return { popupRef: panelRef, popupStyle: panelStyle, renderPopup: renderPanel };
|
|
5195
5543
|
}
|
|
5196
5544
|
|
|
5197
5545
|
function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabledMatcher, defaultMonth, labelProps, alignProps, placeholder = "Select a date", displayFormat = "dd.MM.yyyy", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showTodayButton = false, locale: locale$1 = locale.enGB, todayLabel = "Today", feedback, }) {
|
|
@@ -9192,6 +9540,24 @@ const SuperScheduler = ({ id, state, header, rows, events, pinnedOrderCategory,
|
|
|
9192
9540
|
}, children: "Clear pinned" }) })] })), jsxRuntime.jsx(Scheduler, { id: `${id}-notPinned`, state: { ...state, isHeaderVisible: !isFirstVisible }, header: header, rows: notPinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: unPinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: PinRowHeader, rowHeightRem: rowHeightRem })] }));
|
|
9193
9541
|
};
|
|
9194
9542
|
|
|
9543
|
+
/**
|
|
9544
|
+
* API-backed airport search input for WinOps.
|
|
9545
|
+
*
|
|
9546
|
+
* Fetches matching airports from the WinOps backend as the user types (debounced).
|
|
9547
|
+
* Renders results in a shared `cw-choice-dropdown` styled panel with keyboard navigation.
|
|
9548
|
+
* Supports pre-selecting an airport by `value` (AptKey) and customising the displayed text
|
|
9549
|
+
* format via `displayMode`.
|
|
9550
|
+
*
|
|
9551
|
+
* Requires a running WinOps backend — set `cblConfig` to its base URL.
|
|
9552
|
+
*
|
|
9553
|
+
* @example
|
|
9554
|
+
* <CwFindAirport
|
|
9555
|
+
* cblConfig="https://localhost:44300"
|
|
9556
|
+
* handleChange={(key) => setAirportKey(key)}
|
|
9557
|
+
* labelProps={{ text: 'Departure Airport' }}
|
|
9558
|
+
* displayMode="iata-only"
|
|
9559
|
+
* />
|
|
9560
|
+
*/
|
|
9195
9561
|
const CwFindAirport = ({ handleChange, searchType = "OnlyDatabase", placeHolder = "Search airport…", required = false, cblConfig, className = "", value, disabled = false, displayMode, initialDisplayText, labelProps, alignProps, width }) => {
|
|
9196
9562
|
// State
|
|
9197
9563
|
const [inputValue, setInputValue] = React.useState("");
|
|
@@ -9204,8 +9570,13 @@ const CwFindAirport = ({ handleChange, searchType = "OnlyDatabase", placeHolder
|
|
|
9204
9570
|
const [tooltipText, setTooltipText] = React.useState("");
|
|
9205
9571
|
// Refs
|
|
9206
9572
|
const inputRef = React.useRef(null);
|
|
9207
|
-
const
|
|
9573
|
+
const wrapperRef = React.useRef(null);
|
|
9208
9574
|
const searchTimeoutRef = React.useRef();
|
|
9575
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
9576
|
+
anchorRef: wrapperRef,
|
|
9577
|
+
isOpen: showDropdown && options.length > 0,
|
|
9578
|
+
onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
|
|
9579
|
+
});
|
|
9209
9580
|
// Utility function to extract ICAO from DisplayAirportText
|
|
9210
9581
|
const extractIcao = React.useCallback((displayText) => {
|
|
9211
9582
|
const match = displayText.match(/^([A-Z]{4})\(/);
|
|
@@ -9382,19 +9753,7 @@ const CwFindAirport = ({ handleChange, searchType = "OnlyDatabase", placeHolder
|
|
|
9382
9753
|
break;
|
|
9383
9754
|
}
|
|
9384
9755
|
};
|
|
9385
|
-
// Handle clicks outside dropdown
|
|
9386
|
-
React.useEffect(() => {
|
|
9387
|
-
const handleClickOutside = (event) => {
|
|
9388
|
-
if (dropdownRef.current &&
|
|
9389
|
-
!dropdownRef.current.contains(event.target) &&
|
|
9390
|
-
!inputRef.current?.contains(event.target)) {
|
|
9391
|
-
setShowDropdown(false);
|
|
9392
|
-
setHighlightedIndex(-1);
|
|
9393
|
-
}
|
|
9394
|
-
};
|
|
9395
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
9396
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
9397
|
-
}, []);
|
|
9756
|
+
// Handle clicks outside dropdown — now handled by useDropdownPortal
|
|
9398
9757
|
// Load initial value
|
|
9399
9758
|
React.useEffect(() => {
|
|
9400
9759
|
if (value && value !== 0 && value !== -1) {
|
|
@@ -9436,9 +9795,25 @@ const CwFindAirport = ({ handleChange, searchType = "OnlyDatabase", placeHolder
|
|
|
9436
9795
|
return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className}`, style: {
|
|
9437
9796
|
...(width ? { width } : {}),
|
|
9438
9797
|
...(labelProps?.labelWidth ? { '--label-width': labelProps.labelWidth } : {})
|
|
9439
|
-
}, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected airport", variant: "icon", icon: "close", color: "neutral" })) : (jsxRuntime.jsx(CwIcon, { iconId: "control-tower" })) })] })] }),
|
|
9798
|
+
}, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected airport", variant: "icon", icon: "close", color: "neutral" })) : (jsxRuntime.jsx(CwIcon, { iconId: "control-tower" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: options.map((option, index) => (jsxRuntime.jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
|
|
9440
9799
|
};
|
|
9441
9800
|
|
|
9801
|
+
/**
|
|
9802
|
+
* API-backed crewmember search input for WinOps.
|
|
9803
|
+
*
|
|
9804
|
+
* Fetches matching crewmembers from the WinOps backend as the user types (debounced).
|
|
9805
|
+
* Renders results in a shared `cw-choice-dropdown` styled panel with keyboard navigation.
|
|
9806
|
+
* Supports pre-selecting a crewmember by numeric `value` (ID).
|
|
9807
|
+
*
|
|
9808
|
+
* Requires a running WinOps backend — set `cblConfig` to its base URL.
|
|
9809
|
+
*
|
|
9810
|
+
* @example
|
|
9811
|
+
* <CwFindCrewmember
|
|
9812
|
+
* cblConfig="https://localhost:44300"
|
|
9813
|
+
* handleChange={(id) => setCrewId(id)}
|
|
9814
|
+
* labelProps={{ text: 'Crew Member' }}
|
|
9815
|
+
* />
|
|
9816
|
+
*/
|
|
9442
9817
|
const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", required = false, cblConfig, className = "", value, disabled = false, initialDisplayText, labelProps, alignProps, width }) => {
|
|
9443
9818
|
const [inputValue, setInputValue] = React.useState("");
|
|
9444
9819
|
const [options, setOptions] = React.useState([]);
|
|
@@ -9449,8 +9824,13 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
|
|
|
9449
9824
|
const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
|
|
9450
9825
|
const [tooltipText, setTooltipText] = React.useState("");
|
|
9451
9826
|
const inputRef = React.useRef(null);
|
|
9452
|
-
const
|
|
9827
|
+
const wrapperRef = React.useRef(null);
|
|
9453
9828
|
const searchTimeoutRef = React.useRef();
|
|
9829
|
+
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
9830
|
+
anchorRef: wrapperRef,
|
|
9831
|
+
isOpen: showDropdown && options.length > 0,
|
|
9832
|
+
onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
|
|
9833
|
+
});
|
|
9454
9834
|
const getDisplayText = React.useCallback((crew) => {
|
|
9455
9835
|
return `${crew.threeLetterCode} - ${crew.lastName} ${crew.firstName}`;
|
|
9456
9836
|
}, []);
|
|
@@ -9552,16 +9932,7 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
|
|
|
9552
9932
|
}
|
|
9553
9933
|
};
|
|
9554
9934
|
React.useEffect(() => {
|
|
9555
|
-
|
|
9556
|
-
if (dropdownRef.current &&
|
|
9557
|
-
!dropdownRef.current.contains(event.target) &&
|
|
9558
|
-
!inputRef.current?.contains(event.target)) {
|
|
9559
|
-
setShowDropdown(false);
|
|
9560
|
-
setHighlightedIndex(-1);
|
|
9561
|
-
}
|
|
9562
|
-
};
|
|
9563
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
9564
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
9935
|
+
// Outside-click is now handled by useDropdownPortal
|
|
9565
9936
|
}, []);
|
|
9566
9937
|
React.useEffect(() => {
|
|
9567
9938
|
if (value && value !== 0 && value !== -1) {
|
|
@@ -9600,7 +9971,7 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
|
|
|
9600
9971
|
return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className}`, style: {
|
|
9601
9972
|
...(width ? { width } : {}),
|
|
9602
9973
|
...(labelProps?.labelWidth ? { '--label-width': labelProps.labelWidth } : {})
|
|
9603
|
-
}, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsxRuntime.jsx(CwIcon, { iconId: "person" })) })] })] }),
|
|
9974
|
+
}, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsxRuntime.jsx(CwIcon, { iconId: "person" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: options.map((option, index) => (jsxRuntime.jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
|
|
9604
9975
|
};
|
|
9605
9976
|
|
|
9606
9977
|
exports.CblDragAndDrop = CblDragAndDrop;
|
|
@@ -9628,6 +9999,7 @@ exports.CwDialog = CwDialog;
|
|
|
9628
9999
|
exports.CwDialogManager = CwDialogManager;
|
|
9629
10000
|
exports.CwDigit = CwDigit;
|
|
9630
10001
|
exports.CwDisplayMessage = CwDisplayMessage;
|
|
10002
|
+
exports.CwDropdown = CwDropdown;
|
|
9631
10003
|
exports.CwDropdownFilter = CwDropdownFilter;
|
|
9632
10004
|
exports.CwExpandable = CwExpandable;
|
|
9633
10005
|
exports.CwFileUpload = CwFileUpload;
|
|
@@ -9679,6 +10051,7 @@ exports.CwTable = CwTable;
|
|
|
9679
10051
|
exports.CwTableGrouped = CwTableGrouped;
|
|
9680
10052
|
exports.CwTableServerSide = CwTableServerSide;
|
|
9681
10053
|
exports.CwTabs = CwTabs;
|
|
10054
|
+
exports.CwTagSelector = CwTagSelector;
|
|
9682
10055
|
exports.CwTextArea = CwTextArea;
|
|
9683
10056
|
exports.CwTime = CwTime;
|
|
9684
10057
|
exports.CwTimePicker = CwTimePicker;
|