@soul-refiner/design-system 0.2.67 → 0.2.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { FilterOptionProps } from './filter_option';
|
|
2
3
|
/********************************************************
|
|
3
4
|
* Filter
|
|
4
5
|
*/
|
|
5
6
|
type FilterTriggerTypes = 'outlined' | 'pill' | 'labeled' | 'avatar' | 'text';
|
|
6
|
-
export interface FilterProps
|
|
7
|
+
export interface FilterProps {
|
|
7
8
|
closeOnBlur?: boolean;
|
|
8
9
|
defaultValue?: string;
|
|
9
10
|
disabled?: boolean;
|
|
@@ -11,10 +12,12 @@ export interface FilterProps extends React.PropsWithChildren {
|
|
|
11
12
|
label?: string;
|
|
12
13
|
sx?: string;
|
|
13
14
|
triggerType: FilterTriggerTypes;
|
|
14
|
-
|
|
15
|
+
options: (Omit<FilterOptionProps, 'selected' | 'onClick'> | 'break')[];
|
|
16
|
+
closeOnChange?: boolean;
|
|
17
|
+
onChange?: (event: React.MouseEvent) => void;
|
|
15
18
|
}
|
|
16
19
|
declare const Filter: {
|
|
17
|
-
({ closeOnBlur,
|
|
20
|
+
({ closeOnBlur, disabled, graphic, label, sx, triggerType, options, defaultValue, closeOnChange, onChange, }: FilterProps): React.JSX.Element;
|
|
18
21
|
Trigger: {
|
|
19
22
|
({ disabled, graphic, label, onClick, open, type, value, }: FilterTriggerProps): React.JSX.Element;
|
|
20
23
|
displayName: string;
|
|
@@ -4,10 +4,12 @@ import styled, { css } from 'styled-components';
|
|
|
4
4
|
import { P } from '../../';
|
|
5
5
|
import { ChevronDown, ChevronUp } from '../../../icons';
|
|
6
6
|
import { Styles } from '../../../common';
|
|
7
|
-
|
|
7
|
+
import { Spacer, Option } from './filter_option';
|
|
8
|
+
const Filter = ({ closeOnBlur = true, disabled, graphic, label, sx, triggerType, options, defaultValue, closeOnChange = true, onChange, }) => {
|
|
8
9
|
const wrapperRef = React.useRef(null);
|
|
9
10
|
const optionsRef = React.useRef(null);
|
|
10
11
|
const [open, setOpen] = React.useState(false);
|
|
12
|
+
const [selected, setSelected] = React.useState(defaultValue || options[0]?.value);
|
|
11
13
|
React.useEffect(() => {
|
|
12
14
|
if (disabled) {
|
|
13
15
|
setOpen(false);
|
|
@@ -26,9 +28,31 @@ const Filter = ({ closeOnBlur = true, children, disabled, graphic, label, sx, tr
|
|
|
26
28
|
setOpen(false);
|
|
27
29
|
}
|
|
28
30
|
};
|
|
31
|
+
const handleChange = (event) => {
|
|
32
|
+
event.stopPropagation();
|
|
33
|
+
const value = event.target.getAttribute('data-value') ?? '';
|
|
34
|
+
if (selected !== value) {
|
|
35
|
+
setSelected(value);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
setSelected('');
|
|
39
|
+
}
|
|
40
|
+
if (closeOnChange) {
|
|
41
|
+
setOpen(false);
|
|
42
|
+
}
|
|
43
|
+
if (onChange)
|
|
44
|
+
onChange(event);
|
|
45
|
+
};
|
|
46
|
+
const isSelected = (value) => value === selected;
|
|
47
|
+
const dropdownOptions = options.map((option, index) => {
|
|
48
|
+
if (typeof option === 'string' && option === 'break') {
|
|
49
|
+
return React.createElement(Spacer, { key: `${React.useId()}-spacer-${index}` });
|
|
50
|
+
}
|
|
51
|
+
return (React.createElement(Option, { key: option.value, onClick: handleChange, selected: isSelected(option.value), ...option }));
|
|
52
|
+
});
|
|
29
53
|
return (React.createElement(Wrapper, { "$sx": sx, tabIndex: 0, ref: wrapperRef, onBlurCapture: handleBlur },
|
|
30
|
-
React.createElement(FilterTrigger, { disabled: disabled, graphic: graphic, label: label, onClick: handleOpen, open: open, type: triggerType, value: value }),
|
|
31
|
-
open && React.createElement(Container, { ref: optionsRef },
|
|
54
|
+
React.createElement(FilterTrigger, { disabled: disabled, graphic: graphic, label: label, onClick: handleOpen, open: open, type: triggerType, value: options.find((option) => isSelected(option.value)).label }),
|
|
55
|
+
open && React.createElement(Container, { ref: optionsRef }, dropdownOptions)));
|
|
32
56
|
};
|
|
33
57
|
const Wrapper = styled.div `
|
|
34
58
|
position: relative;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface FilterOptionProps {
|
|
3
|
+
color?: string;
|
|
4
|
+
label: string;
|
|
5
|
+
onClick?: (event: React.MouseEvent<HTMLDivElement>) => void | undefined;
|
|
6
|
+
selected: boolean;
|
|
7
|
+
sx?: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
declare const Option: {
|
|
11
|
+
({ label, onClick, selected, sx, value }: FilterOptionProps): React.JSX.Element;
|
|
12
|
+
displayName: string;
|
|
13
|
+
};
|
|
14
|
+
export interface FilterSpacerProps {
|
|
15
|
+
sx?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const Spacer: {
|
|
18
|
+
({ sx }: FilterSpacerProps): React.JSX.Element;
|
|
19
|
+
displayName: string;
|
|
20
|
+
};
|
|
21
|
+
export { Option };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { Box, P } from '../..';
|
|
5
|
+
const Option = ({ label, onClick, selected, sx, value }) => {
|
|
6
|
+
return (React.createElement(OptionWrapper, { "data-value": value, onClick: onClick, "$selected": selected, "$sx": sx },
|
|
7
|
+
React.createElement(Box, { "$dir": "column", "$display": "flex" }, label && (React.createElement(P, { "$color": "grey-4", "$fontSize": 14, "$lineHeight": 20, "$mediumBold": true, "$textClampLines": 1 }, label)))));
|
|
8
|
+
};
|
|
9
|
+
Option.displayName = 'Filter.Option';
|
|
10
|
+
const OptionWrapper = styled.div `
|
|
11
|
+
position: relative;
|
|
12
|
+
z-index: 1;
|
|
13
|
+
padding: 12px 16px;
|
|
14
|
+
user-select: none;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: 8px;
|
|
18
|
+
min-width: 164px;
|
|
19
|
+
|
|
20
|
+
& > * {
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
${({ $selected }) => {
|
|
25
|
+
if ($selected) {
|
|
26
|
+
return `
|
|
27
|
+
background-color: var(--color-grey-9);
|
|
28
|
+
&:active {
|
|
29
|
+
background-color: var(--color-grey-8);
|
|
30
|
+
}`;
|
|
31
|
+
}
|
|
32
|
+
return `
|
|
33
|
+
&:hover {
|
|
34
|
+
background-color: var(--color-grey-10);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&:active {
|
|
38
|
+
background-color: var(--color-grey-8);
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
}}
|
|
42
|
+
${({ $sx }) => ($sx ? $sx : '')}
|
|
43
|
+
`;
|
|
44
|
+
export const Spacer = ({ sx }) => {
|
|
45
|
+
return React.createElement(SpacerWrapper, { "$sx": sx });
|
|
46
|
+
};
|
|
47
|
+
Spacer.displayName = 'Filter.Spacer';
|
|
48
|
+
const SpacerWrapper = styled.div `
|
|
49
|
+
width: 100%;
|
|
50
|
+
height: 1px;
|
|
51
|
+
background-color: var(--color-grey-8);
|
|
52
|
+
|
|
53
|
+
&:hover {
|
|
54
|
+
appearance: none;
|
|
55
|
+
}
|
|
56
|
+
${({ $sx }) => ($sx ? $sx : '')}
|
|
57
|
+
`;
|
|
58
|
+
export { Option };
|