sag_components 2.0.0-beta305 → 2.0.0-beta307
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.esm.js +155 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +155 -16
- package/dist/index.js.map +1 -1
- package/dist/types/components/OverlayDropdown/OverlayDropdown.style.d.ts +2 -0
- package/dist/types/components/SearchInput/SearchInput.stories.d.ts +27 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -3796,11 +3796,14 @@ const SearchInput$1 = props => {
|
|
|
3796
3796
|
position = 'left',
|
|
3797
3797
|
iconColor = '#212121',
|
|
3798
3798
|
onTyping = () => {},
|
|
3799
|
+
onClear = () => {},
|
|
3800
|
+
clearTrigger,
|
|
3799
3801
|
className
|
|
3800
3802
|
} = props;
|
|
3801
3803
|
|
|
3802
3804
|
// Use internal state for uncontrolled mode
|
|
3803
3805
|
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
3806
|
+
const previousValueRef = useRef(defaultValue);
|
|
3804
3807
|
|
|
3805
3808
|
// Determine if component is controlled
|
|
3806
3809
|
const isControlled = controlledValue !== undefined;
|
|
@@ -3812,12 +3815,33 @@ const SearchInput$1 = props => {
|
|
|
3812
3815
|
setInternalValue(defaultValue);
|
|
3813
3816
|
}
|
|
3814
3817
|
}, [defaultValue, isControlled]);
|
|
3818
|
+
|
|
3819
|
+
// Clear the input when clearTrigger changes (external clear trigger)
|
|
3820
|
+
useEffect(() => {
|
|
3821
|
+
if (clearTrigger !== undefined) {
|
|
3822
|
+
setInternalValue('');
|
|
3823
|
+
}
|
|
3824
|
+
}, [clearTrigger]);
|
|
3815
3825
|
const handleInputChange = e => {
|
|
3826
|
+
const newValue = e.target.value;
|
|
3827
|
+
|
|
3828
|
+
// Detect native clear button click (value was non-empty, now empty, via input event)
|
|
3829
|
+
if (previousValueRef.current && newValue === '') {
|
|
3830
|
+
onClear();
|
|
3831
|
+
}
|
|
3832
|
+
previousValueRef.current = newValue;
|
|
3816
3833
|
if (!isControlled) {
|
|
3817
|
-
setInternalValue(
|
|
3834
|
+
setInternalValue(newValue);
|
|
3818
3835
|
}
|
|
3819
3836
|
onTyping(e);
|
|
3820
3837
|
};
|
|
3838
|
+
|
|
3839
|
+
// Handle the 'search' event which fires when native clear button is clicked
|
|
3840
|
+
const handleSearch = e => {
|
|
3841
|
+
if (e.target.value === '') {
|
|
3842
|
+
onClear();
|
|
3843
|
+
}
|
|
3844
|
+
};
|
|
3821
3845
|
return /*#__PURE__*/React$1.createElement(TextFieldContainer, {
|
|
3822
3846
|
className: className,
|
|
3823
3847
|
width: width
|
|
@@ -3832,6 +3856,7 @@ const SearchInput$1 = props => {
|
|
|
3832
3856
|
height: height,
|
|
3833
3857
|
placeholder: placeholder,
|
|
3834
3858
|
onChange: handleInputChange,
|
|
3859
|
+
onSearch: handleSearch,
|
|
3835
3860
|
position: position
|
|
3836
3861
|
}));
|
|
3837
3862
|
};
|
|
@@ -37714,8 +37739,16 @@ const SearchInput = styled.input`
|
|
|
37714
37739
|
}
|
|
37715
37740
|
`;
|
|
37716
37741
|
const ListWrapper = styled.div`
|
|
37717
|
-
max-height: ${props =>
|
|
37718
|
-
|
|
37742
|
+
max-height: ${props => {
|
|
37743
|
+
const maxH = parseInt(props.maxHeight) || 400;
|
|
37744
|
+
const actualH = (props.actualHeight || maxH) + 16;
|
|
37745
|
+
return actualH < maxH ? `${actualH}px` : props.maxHeight;
|
|
37746
|
+
}};
|
|
37747
|
+
overflow-y: ${props => {
|
|
37748
|
+
const maxH = parseInt(props.maxHeight) || 400;
|
|
37749
|
+
const actualH = (props.actualHeight || maxH) + 16;
|
|
37750
|
+
return actualH < maxH ? 'hidden' : 'auto';
|
|
37751
|
+
}};
|
|
37719
37752
|
position: relative;
|
|
37720
37753
|
`;
|
|
37721
37754
|
const CheckboxGroup = styled.div`
|
|
@@ -37760,6 +37793,7 @@ const CheckboxLabel = styled.label`
|
|
|
37760
37793
|
color: #212121;
|
|
37761
37794
|
cursor: pointer;
|
|
37762
37795
|
flex-shrink: 0;
|
|
37796
|
+
box-sizing: border-box;
|
|
37763
37797
|
|
|
37764
37798
|
&:hover {
|
|
37765
37799
|
background-color: #E6F0F0;
|
|
@@ -37832,7 +37866,7 @@ const FilterPop = props => {
|
|
|
37832
37866
|
selectedAttributes: propSelectedAttributes = {},
|
|
37833
37867
|
showSearch = true,
|
|
37834
37868
|
searchPlaceholder = "Search...",
|
|
37835
|
-
itemHeight =
|
|
37869
|
+
itemHeight = 40,
|
|
37836
37870
|
overscan = 5,
|
|
37837
37871
|
hasActiveFilter = false // NEW: Indicates if this column has an active filter
|
|
37838
37872
|
} = props;
|
|
@@ -37921,16 +37955,18 @@ const FilterPop = props => {
|
|
|
37921
37955
|
offsetY
|
|
37922
37956
|
} = useMemo(() => {
|
|
37923
37957
|
const containerHeight = parseInt(maxHeight) || 400;
|
|
37924
|
-
const
|
|
37925
|
-
const
|
|
37958
|
+
const gap = 8;
|
|
37959
|
+
const itemWithGap = itemHeight + gap;
|
|
37960
|
+
const startIndex = Math.max(0, Math.floor(scrollTop / itemWithGap) - overscan);
|
|
37961
|
+
const endIndex = Math.min(sortedList.length, Math.ceil((scrollTop + containerHeight) / itemWithGap) + overscan);
|
|
37926
37962
|
const visible = sortedList.slice(startIndex, endIndex).map((item, idx) => ({
|
|
37927
37963
|
...item,
|
|
37928
37964
|
index: startIndex + idx
|
|
37929
37965
|
}));
|
|
37930
37966
|
return {
|
|
37931
37967
|
visibleItems: visible,
|
|
37932
|
-
totalHeight:
|
|
37933
|
-
offsetY: startIndex *
|
|
37968
|
+
totalHeight: sortedList.length * itemHeight + Math.max(0, sortedList.length - 1) * gap,
|
|
37969
|
+
offsetY: startIndex * itemWithGap
|
|
37934
37970
|
};
|
|
37935
37971
|
}, [sortedList, scrollTop, itemHeight, overscan, maxHeight]);
|
|
37936
37972
|
const areAllNonAllItemsSelected = function () {
|
|
@@ -38130,7 +38166,8 @@ const FilterPop = props => {
|
|
|
38130
38166
|
}), /*#__PURE__*/React$1.createElement(ListWrapper, {
|
|
38131
38167
|
ref: scrollContainerRef,
|
|
38132
38168
|
onScroll: handleScroll,
|
|
38133
|
-
maxHeight: maxHeight
|
|
38169
|
+
maxHeight: maxHeight,
|
|
38170
|
+
actualHeight: totalHeight
|
|
38134
38171
|
}, sortedList.length === 1 ? /*#__PURE__*/React$1.createElement(NoResultsMessage, null, "No items match your search") : /*#__PURE__*/React$1.createElement("div", {
|
|
38135
38172
|
style: {
|
|
38136
38173
|
height: `${totalHeight}px`,
|
|
@@ -40982,10 +41019,12 @@ const TableHeader = ({
|
|
|
40982
41019
|
const debouncedFilterState = useDebounce(filterState, debounceDelay);
|
|
40983
41020
|
const iconRefs = useRef({});
|
|
40984
41021
|
const popupRef = useRef(null);
|
|
41022
|
+
const prevResetKeyRef = useRef(resetFiltersKey);
|
|
40985
41023
|
|
|
40986
|
-
// Reset internal state when resetFiltersKey changes
|
|
41024
|
+
// Reset internal state when resetFiltersKey changes (not when columns change)
|
|
40987
41025
|
useEffect(() => {
|
|
40988
|
-
|
|
41026
|
+
// Only run reset when resetFiltersKey actually changed
|
|
41027
|
+
if (resetFiltersKey !== prevResetKeyRef.current && resetFiltersKey > 0) {
|
|
40989
41028
|
const resetSelections = {};
|
|
40990
41029
|
columns.forEach(column => {
|
|
40991
41030
|
if (column.filter && column.filterOptions) {
|
|
@@ -41007,6 +41046,7 @@ const TableHeader = ({
|
|
|
41007
41046
|
setVisibleFilterPopWrapper(null);
|
|
41008
41047
|
setVisibleSortPopWrapper(null);
|
|
41009
41048
|
}
|
|
41049
|
+
prevResetKeyRef.current = resetFiltersKey;
|
|
41010
41050
|
}, [resetFiltersKey, columns]);
|
|
41011
41051
|
|
|
41012
41052
|
// Track if we've already initialized from saved state
|
|
@@ -57679,6 +57719,21 @@ function ModalDrawer(_ref) {
|
|
|
57679
57719
|
}, "\xD7"), children));
|
|
57680
57720
|
}
|
|
57681
57721
|
|
|
57722
|
+
// Keyframes for rolling/marquee animation
|
|
57723
|
+
const scrollTextAnimation = keyframes`
|
|
57724
|
+
0% {
|
|
57725
|
+
transform: translateX(0);
|
|
57726
|
+
}
|
|
57727
|
+
10% {
|
|
57728
|
+
transform: translateX(0);
|
|
57729
|
+
}
|
|
57730
|
+
90% {
|
|
57731
|
+
transform: translateX(var(--scroll-distance, -30%));
|
|
57732
|
+
}
|
|
57733
|
+
100% {
|
|
57734
|
+
transform: translateX(var(--scroll-distance, -30%));
|
|
57735
|
+
}
|
|
57736
|
+
`;
|
|
57682
57737
|
const scrollableStyles = `
|
|
57683
57738
|
&::-webkit-scrollbar {
|
|
57684
57739
|
height: 8px;
|
|
@@ -57697,6 +57752,9 @@ const scrollableStyles = `
|
|
|
57697
57752
|
`;
|
|
57698
57753
|
const TooltipWrapper = styled(Tooltip$2)`
|
|
57699
57754
|
width: 100%;
|
|
57755
|
+
.tooltip-wrapper {
|
|
57756
|
+
width: 100%;
|
|
57757
|
+
}
|
|
57700
57758
|
`;
|
|
57701
57759
|
const DropdownContainer = styled.div`
|
|
57702
57760
|
position: relative;
|
|
@@ -57794,6 +57852,41 @@ const Wrapper = styled.div`
|
|
|
57794
57852
|
align-items: center;
|
|
57795
57853
|
width: 100%;
|
|
57796
57854
|
`;
|
|
57855
|
+
|
|
57856
|
+
// Wrapper for scrollable truncated text
|
|
57857
|
+
const ScrollableTextWrapper = styled.div`
|
|
57858
|
+
flex: 1;
|
|
57859
|
+
display: flex;
|
|
57860
|
+
align-items: center;
|
|
57861
|
+
min-width: 0;
|
|
57862
|
+
overflow: hidden;
|
|
57863
|
+
position: relative;
|
|
57864
|
+
`;
|
|
57865
|
+
|
|
57866
|
+
// Inner text that scrolls when truncated
|
|
57867
|
+
const ScrollableTextInner = styled.span`
|
|
57868
|
+
display: inline-block;
|
|
57869
|
+
white-space: nowrap;
|
|
57870
|
+
line-height: 21px;
|
|
57871
|
+
font-family: "Poppins", sans-serif;
|
|
57872
|
+
font-size: 14px;
|
|
57873
|
+
font-weight: 400;
|
|
57874
|
+
color: ${props => props.color || 'inherit'};
|
|
57875
|
+
max-width: 100%;
|
|
57876
|
+
|
|
57877
|
+
/* Default state: show ellipsis */
|
|
57878
|
+
overflow: hidden;
|
|
57879
|
+
text-overflow: ellipsis;
|
|
57880
|
+
|
|
57881
|
+
${props => props.$isTruncated && css`
|
|
57882
|
+
${ScrollableTextWrapper}:hover & {
|
|
57883
|
+
/* On hover: remove ellipsis and start animation */
|
|
57884
|
+
overflow: visible;
|
|
57885
|
+
text-overflow: clip;
|
|
57886
|
+
animation: ${scrollTextAnimation} ${props.$animationDuration || 3}s linear infinite;
|
|
57887
|
+
}
|
|
57888
|
+
`}
|
|
57889
|
+
`;
|
|
57797
57890
|
const TruncatedText = styled.span`
|
|
57798
57891
|
flex: 1;
|
|
57799
57892
|
min-width: 0;
|
|
@@ -58110,7 +58203,54 @@ OverlayTemplateDialog.propTypes = {
|
|
|
58110
58203
|
buttonHoverColor: PropTypes.string
|
|
58111
58204
|
};
|
|
58112
58205
|
|
|
58113
|
-
|
|
58206
|
+
// Component for scrolling truncated text on hover
|
|
58207
|
+
const ScrollingText = _ref => {
|
|
58208
|
+
let {
|
|
58209
|
+
children,
|
|
58210
|
+
color
|
|
58211
|
+
} = _ref;
|
|
58212
|
+
const wrapperRef = useRef(null);
|
|
58213
|
+
const textRef = useRef(null);
|
|
58214
|
+
const [isTruncated, setIsTruncated] = useState(false);
|
|
58215
|
+
const [scrollDistance, setScrollDistance] = useState(0);
|
|
58216
|
+
const [animationDuration, setAnimationDuration] = useState(3);
|
|
58217
|
+
const checkTruncation = useCallback(() => {
|
|
58218
|
+
if (wrapperRef.current && textRef.current) {
|
|
58219
|
+
const wrapperWidth = wrapperRef.current.offsetWidth;
|
|
58220
|
+
const textWidth = textRef.current.scrollWidth;
|
|
58221
|
+
const isOverflowing = textWidth > wrapperWidth;
|
|
58222
|
+
setIsTruncated(isOverflowing);
|
|
58223
|
+
if (isOverflowing) {
|
|
58224
|
+
// Calculate how much we need to scroll (extra width + small padding)
|
|
58225
|
+
const extraWidth = textWidth - wrapperWidth + 20;
|
|
58226
|
+
setScrollDistance(-extraWidth);
|
|
58227
|
+
|
|
58228
|
+
// Calculate animation duration based on text length (roughly 50px per second)
|
|
58229
|
+
const duration = Math.max(2, Math.min(8, extraWidth / 50));
|
|
58230
|
+
setAnimationDuration(duration);
|
|
58231
|
+
}
|
|
58232
|
+
}
|
|
58233
|
+
}, []);
|
|
58234
|
+
useEffect(() => {
|
|
58235
|
+
checkTruncation();
|
|
58236
|
+
|
|
58237
|
+
// Recheck on window resize
|
|
58238
|
+
window.addEventListener('resize', checkTruncation);
|
|
58239
|
+
return () => window.removeEventListener('resize', checkTruncation);
|
|
58240
|
+
}, [children, checkTruncation]);
|
|
58241
|
+
return /*#__PURE__*/React$1.createElement(ScrollableTextWrapper, {
|
|
58242
|
+
ref: wrapperRef
|
|
58243
|
+
}, /*#__PURE__*/React$1.createElement(ScrollableTextInner, {
|
|
58244
|
+
ref: textRef,
|
|
58245
|
+
color: color,
|
|
58246
|
+
$isTruncated: isTruncated,
|
|
58247
|
+
$animationDuration: animationDuration,
|
|
58248
|
+
style: {
|
|
58249
|
+
'--scroll-distance': `${scrollDistance}px`
|
|
58250
|
+
}
|
|
58251
|
+
}, children));
|
|
58252
|
+
};
|
|
58253
|
+
const OverlayDropdown = _ref2 => {
|
|
58114
58254
|
let {
|
|
58115
58255
|
data = [],
|
|
58116
58256
|
value,
|
|
@@ -58136,7 +58276,7 @@ const OverlayDropdown = _ref => {
|
|
|
58136
58276
|
height = "auto",
|
|
58137
58277
|
margin = "8px",
|
|
58138
58278
|
...props
|
|
58139
|
-
} =
|
|
58279
|
+
} = _ref2;
|
|
58140
58280
|
const [open, setOpen] = useState(false);
|
|
58141
58281
|
const [hoveredText, setHoveredText] = useState(null);
|
|
58142
58282
|
const [templateDialog, setTemplateDialog] = useState(null);
|
|
@@ -58423,9 +58563,8 @@ const OverlayDropdown = _ref => {
|
|
|
58423
58563
|
}
|
|
58424
58564
|
}
|
|
58425
58565
|
}
|
|
58426
|
-
}, /*#__PURE__*/React$1.createElement(
|
|
58427
|
-
|
|
58428
|
-
onMouseLeave: () => setHoveredText(null)
|
|
58566
|
+
}, /*#__PURE__*/React$1.createElement(ScrollingText, {
|
|
58567
|
+
color: item.value === value ? '#fff' : '#212121'
|
|
58429
58568
|
}, displayText), iconToShow);
|
|
58430
58569
|
})))), templateDialog && /*#__PURE__*/React$1.createElement(OverlayTemplateDialog, {
|
|
58431
58570
|
open: true,
|