mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Enhancement: Improved pill functionality and sizing.
This commit is contained in:
parent
0984ec9834
commit
8bc88112aa
1 changed files with 80 additions and 15 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import React, { cloneElement, isValidElement } from 'react';
|
||||
import React, { cloneElement, isValidElement, useRef } from 'react';
|
||||
import { Box, Flex, Pill, Tooltip, MultiSelect } from '@mantine/core';
|
||||
|
||||
/**
|
||||
|
|
@ -6,6 +6,8 @@ import { Box, Flex, Pill, Tooltip, MultiSelect } from '@mantine/core';
|
|||
* Recursively searches through React children to find and enhance MultiSelect
|
||||
*/
|
||||
const MultiSelectHeaderWrapper = ({ children }) => {
|
||||
const inputRef = useRef(null);
|
||||
|
||||
const enhanceMultiSelect = (element) => {
|
||||
if (!isValidElement(element)) {
|
||||
return element;
|
||||
|
|
@ -13,7 +15,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
|
||||
// Check if this element is a MultiSelect
|
||||
if (element.type === MultiSelect) {
|
||||
const { value = [], data = [], ...otherProps } = element.props;
|
||||
const { value = [], data = [], onChange, ...otherProps } = element.props;
|
||||
const selectedValues = Array.isArray(value) ? value : [];
|
||||
|
||||
if (selectedValues.length === 0) {
|
||||
|
|
@ -22,6 +24,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
...otherProps,
|
||||
value,
|
||||
data,
|
||||
onChange,
|
||||
styles: { pill: { display: 'none' } },
|
||||
});
|
||||
}
|
||||
|
|
@ -46,8 +49,42 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
</div>
|
||||
);
|
||||
|
||||
// Handle opening the dropdown when pill is clicked
|
||||
const handlePillClick = (e) => {
|
||||
// Check if the click is on the remove button (it has a data-attribute)
|
||||
if (e.target.closest('[data-disabled]') || e.target.closest('button')) {
|
||||
return; // Let the remove button handle it
|
||||
}
|
||||
e.stopPropagation();
|
||||
// Focus and click the input to open the dropdown
|
||||
if (inputRef.current) {
|
||||
const input = inputRef.current.querySelector('input');
|
||||
if (input) {
|
||||
input.focus();
|
||||
input.click();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle removing a single filter value
|
||||
const handleRemoveFirst = (e) => {
|
||||
e?.stopPropagation?.();
|
||||
if (onChange && selectedValues.length > 0) {
|
||||
const newValues = selectedValues.slice(1);
|
||||
onChange(newValues);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle clearing all filters
|
||||
const handleClearAll = (e) => {
|
||||
e?.stopPropagation?.();
|
||||
if (onChange) {
|
||||
onChange([]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box style={{ width: '100%', position: 'relative' }}>
|
||||
<Box ref={inputRef} style={{ width: '100%', position: 'relative' }}>
|
||||
<Tooltip label={tooltipContent} position="top" withArrow>
|
||||
<Flex
|
||||
gap={4}
|
||||
|
|
@ -55,7 +92,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
position: 'absolute',
|
||||
top: 4,
|
||||
left: 4,
|
||||
right: 30,
|
||||
right: 20,
|
||||
zIndex: 1,
|
||||
pointerEvents: 'none',
|
||||
overflow: 'hidden',
|
||||
|
|
@ -63,28 +100,55 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
>
|
||||
<Pill
|
||||
size="xs"
|
||||
withRemoveButton
|
||||
onRemove={handleRemoveFirst}
|
||||
onClick={handlePillClick}
|
||||
removeButtonProps={{
|
||||
onClick: handleRemoveFirst,
|
||||
style: { cursor: 'pointer' },
|
||||
}}
|
||||
style={{
|
||||
flex: '1 1 auto',
|
||||
flex: selectedValues.length > 1 ? '1 1 auto' : '0 1 auto',
|
||||
minWidth: 0,
|
||||
maxWidth:
|
||||
selectedValues.length > 1
|
||||
? 'calc(100% - 50px)'
|
||||
: 'calc(100% - 30px)',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'block',
|
||||
selectedValues.length > 1 ? 'calc(100% - 40px)' : '100%',
|
||||
pointerEvents: 'auto',
|
||||
}}
|
||||
>
|
||||
{firstLabel}
|
||||
<span
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
{firstLabel}
|
||||
</span>
|
||||
</Pill>
|
||||
{selectedValues.length > 1 && (
|
||||
<Pill
|
||||
size="xs"
|
||||
style={{ flexShrink: 0, pointerEvents: 'auto' }}
|
||||
withRemoveButton
|
||||
onRemove={handleClearAll}
|
||||
onClick={handlePillClick}
|
||||
removeButtonProps={{
|
||||
onClick: handleClearAll,
|
||||
style: { cursor: 'pointer' },
|
||||
}}
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
pointerEvents: 'auto',
|
||||
}}
|
||||
>
|
||||
+{selectedValues.length - 1}
|
||||
<span
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
+{selectedValues.length - 1}
|
||||
</span>
|
||||
</Pill>
|
||||
)}
|
||||
</Flex>
|
||||
|
|
@ -93,6 +157,7 @@ const MultiSelectHeaderWrapper = ({ children }) => {
|
|||
...otherProps,
|
||||
value,
|
||||
data,
|
||||
onChange,
|
||||
styles: { pill: { display: 'none' } },
|
||||
style: { width: '100%', ...otherProps.style },
|
||||
})}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue