@soul-refiner/design-system 0.2.72 → 0.2.74
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/components/input/filter/filter.d.ts +6 -4
- package/dist/components/input/filter/filter.js +84 -29
- package/dist/components/input/filter/filter_option.d.ts +5 -1
- package/dist/components/input/filter/filter_option.js +18 -6
- package/dist/components/surfaces/post/post.d.ts +1 -1
- package/dist/components/surfaces/post/post.js +10 -2
- package/package.json +1 -1
|
@@ -6,18 +6,20 @@ import { FilterOptionProps } from './filter_option';
|
|
|
6
6
|
type FilterTriggerTypes = 'outlined' | 'pill' | 'labeled' | 'avatar' | 'text';
|
|
7
7
|
export interface FilterProps {
|
|
8
8
|
closeOnBlur?: boolean;
|
|
9
|
-
defaultValue?: string;
|
|
9
|
+
defaultValue?: string | string[];
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
graphic?: React.ReactElement;
|
|
12
|
-
label
|
|
12
|
+
label: string;
|
|
13
13
|
sx?: string;
|
|
14
14
|
triggerType: FilterTriggerTypes;
|
|
15
15
|
options: (Omit<FilterOptionProps, 'selected' | 'onClick'> | 'break')[];
|
|
16
16
|
closeOnChange?: boolean;
|
|
17
|
-
|
|
17
|
+
optionOnChange?: (event: React.MouseEvent) => void;
|
|
18
|
+
checkbox?: boolean;
|
|
19
|
+
applyOnClick?: (event: React.MouseEvent) => void;
|
|
18
20
|
}
|
|
19
21
|
declare const Filter: {
|
|
20
|
-
({ closeOnBlur, disabled, graphic, label, sx, triggerType, options, defaultValue, closeOnChange,
|
|
22
|
+
({ closeOnBlur, disabled, graphic, label, sx, triggerType, options, defaultValue, closeOnChange, optionOnChange, checkbox, applyOnClick, }: FilterProps): React.JSX.Element;
|
|
21
23
|
Trigger: {
|
|
22
24
|
({ disabled, graphic, label, onClick, open, type, value, }: FilterTriggerProps): React.JSX.Element;
|
|
23
25
|
displayName: string;
|
|
@@ -1,20 +1,40 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled, { css } from 'styled-components';
|
|
4
|
-
import { P } from '../../';
|
|
4
|
+
import { Box, Button, 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,
|
|
8
|
+
const Filter = ({ closeOnBlur = true, disabled, graphic, label, sx, triggerType, options, defaultValue = '', closeOnChange = true, optionOnChange, checkbox, applyOnClick, }) => {
|
|
9
|
+
const multiple = !!checkbox;
|
|
9
10
|
const wrapperRef = React.useRef(null);
|
|
10
11
|
const optionsRef = React.useRef(null);
|
|
11
12
|
const [open, setOpen] = React.useState(false);
|
|
12
|
-
const [selected, setSelected] = React.useState(defaultValue
|
|
13
|
+
const [selected, setSelected] = React.useState(() => defaultValue ? defaultValue : multiple ? [] : '');
|
|
14
|
+
const [filterLabel, setFilterLabel] = React.useState('');
|
|
13
15
|
React.useEffect(() => {
|
|
14
16
|
if (disabled) {
|
|
15
17
|
setOpen(false);
|
|
16
18
|
}
|
|
17
19
|
}, [disabled]);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
if (open) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!selected.length) {
|
|
25
|
+
setFilterLabel(label);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// not using selected[0] since it is required to show the first
|
|
29
|
+
const firstSelected = options.find((option) => typeof option !== 'string' && isSelected(option.value));
|
|
30
|
+
if (typeof selected === 'string') {
|
|
31
|
+
setFilterLabel(firstSelected.label);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
setFilterLabel(selected.length > 1
|
|
35
|
+
? `${firstSelected.label} +${selected.length - 1}`
|
|
36
|
+
: firstSelected.label);
|
|
37
|
+
}, [selected, options, open]);
|
|
18
38
|
const handleOpen = () => {
|
|
19
39
|
if (disabled) {
|
|
20
40
|
return;
|
|
@@ -28,7 +48,7 @@ const Filter = ({ closeOnBlur = true, disabled, graphic, label, sx, triggerType,
|
|
|
28
48
|
setOpen(false);
|
|
29
49
|
}
|
|
30
50
|
};
|
|
31
|
-
const
|
|
51
|
+
const handleChangeSingle = (event) => {
|
|
32
52
|
event.stopPropagation();
|
|
33
53
|
const value = event.target.getAttribute('data-value') ?? '';
|
|
34
54
|
if (selected !== value) {
|
|
@@ -37,27 +57,52 @@ const Filter = ({ closeOnBlur = true, disabled, graphic, label, sx, triggerType,
|
|
|
37
57
|
else {
|
|
38
58
|
setSelected('');
|
|
39
59
|
}
|
|
40
|
-
if (closeOnChange) {
|
|
60
|
+
if (closeOnChange && !applyOnClick) {
|
|
41
61
|
setOpen(false);
|
|
42
62
|
}
|
|
43
|
-
if (
|
|
44
|
-
|
|
63
|
+
if (optionOnChange)
|
|
64
|
+
optionOnChange(event);
|
|
45
65
|
};
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
const handleChangeMultiple = (event) => {
|
|
67
|
+
event.stopPropagation();
|
|
68
|
+
const value = event.target.getAttribute('data-value') ?? '';
|
|
69
|
+
if (Array.isArray(selected) && selected.includes(value)) {
|
|
70
|
+
setSelected((prev) => prev.filter((item) => item !== value));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
setSelected((prev) => [value, ...prev]);
|
|
74
|
+
}
|
|
75
|
+
if (closeOnChange && !applyOnClick) {
|
|
76
|
+
setOpen(false);
|
|
50
77
|
}
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
if (optionOnChange)
|
|
79
|
+
optionOnChange(event);
|
|
80
|
+
};
|
|
81
|
+
const handleChange = multiple ? handleChangeMultiple : handleChangeSingle;
|
|
82
|
+
const isSelected = (value) => multiple ? selected.includes(value) : value === selected;
|
|
83
|
+
const dropdownOptions = [
|
|
84
|
+
...options.map((option, index) => {
|
|
85
|
+
if (typeof option === 'string' && option === 'break') {
|
|
86
|
+
return React.createElement(Spacer, { key: `${React.useId()}-spacer-${index}` });
|
|
87
|
+
}
|
|
88
|
+
return (React.createElement(Option, { key: option.value, onClick: handleChange, selected: isSelected(option.value), checkbox: checkbox, radio: !multiple && triggerType === 'pill', showClose: index === 0 && triggerType === 'pill', onClose: () => setOpen(false), ...option }));
|
|
89
|
+
}),
|
|
90
|
+
triggerType === 'pill' && React.createElement(Spacer, { key: `spacer-${options.length}` }),
|
|
91
|
+
];
|
|
53
92
|
return (React.createElement(Wrapper, { "$sx": sx, tabIndex: 0, ref: wrapperRef, onBlurCapture: handleBlur },
|
|
54
|
-
React.createElement(FilterTrigger, { disabled: disabled, graphic: graphic, label: label, onClick: handleOpen, open: open, type: triggerType, value:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
93
|
+
React.createElement(FilterTrigger, { disabled: disabled, graphic: graphic, label: label, onClick: handleOpen, open: open, type: triggerType, value: filterLabel }),
|
|
94
|
+
open && (React.createElement(Container, { ref: optionsRef },
|
|
95
|
+
React.createElement(React.Fragment, null,
|
|
96
|
+
dropdownOptions,
|
|
97
|
+
triggerType === 'pill' && (React.createElement(Box, { "$display": "flex", "$dir": "row", "$align": "center", "$justify": "flex-end", "$gap": 8, sx: "margin-top: 8px; padding-right: 8px; padding-bottom: 8px" },
|
|
98
|
+
React.createElement(Button, { onClick: () => {
|
|
99
|
+
setSelected(multiple ? [] : '');
|
|
100
|
+
setOpen(false);
|
|
101
|
+
}, size: "small", type: "text" }, "Reset"),
|
|
102
|
+
React.createElement(Button, { onClick: (event) => {
|
|
103
|
+
applyOnClick && applyOnClick(event);
|
|
104
|
+
setOpen(false);
|
|
105
|
+
}, size: "small", type: "primary" }, "Apply"))))))));
|
|
61
106
|
};
|
|
62
107
|
const Wrapper = styled.div `
|
|
63
108
|
position: relative;
|
|
@@ -98,7 +143,7 @@ const wrapperProps = {
|
|
|
98
143
|
};
|
|
99
144
|
const FilterTrigger = ({ disabled, graphic, label, onClick, open, type, value, }) => {
|
|
100
145
|
if (type === 'pill') {
|
|
101
|
-
return (React.createElement(Pill, { disabled: disabled, onClick: onClick, ...wrapperProps },
|
|
146
|
+
return (React.createElement(Pill, { disabled: disabled, onClick: onClick, "$labelIsDefault": value === label, ...wrapperProps },
|
|
102
147
|
graphic,
|
|
103
148
|
React.createElement(P, { ...textProps }, value),
|
|
104
149
|
!graphic && (open ? React.createElement(ChevronUp, null) : React.createElement(ChevronDown, null))));
|
|
@@ -164,18 +209,28 @@ const Outlined = styled.button `
|
|
|
164
209
|
const Pill = styled.button `
|
|
165
210
|
${sharedStyles}
|
|
166
211
|
${Styles.flex}
|
|
212
|
+
border: 1px solid var(--color-grey-8);
|
|
167
213
|
border-radius: 24px;
|
|
168
|
-
background-color: var(--color-
|
|
214
|
+
background-color: var(--color-white);
|
|
169
215
|
font-family: var(--font-inter);
|
|
170
216
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
217
|
+
${({ $labelIsDefault }) => !$labelIsDefault
|
|
218
|
+
? `
|
|
219
|
+
& > * {
|
|
220
|
+
color: var(--color-primary-blue-2);
|
|
221
|
+
fill: currentColor;
|
|
174
222
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
223
|
+
&:hover {
|
|
224
|
+
color: var(--color-primary-blue-1);
|
|
225
|
+
background-color: var(--color-primary-blue-4);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
&:hover {
|
|
230
|
+
background-color: var(--color-primary-blue-4);
|
|
231
|
+
}
|
|
232
|
+
`
|
|
233
|
+
: ''}
|
|
179
234
|
`;
|
|
180
235
|
const Labeled = styled.button `
|
|
181
236
|
${sharedStyles}
|
|
@@ -6,9 +6,13 @@ export interface FilterOptionProps {
|
|
|
6
6
|
selected: boolean;
|
|
7
7
|
sx?: string;
|
|
8
8
|
value: string;
|
|
9
|
+
checkbox?: boolean;
|
|
10
|
+
radio?: boolean;
|
|
11
|
+
showClose?: boolean;
|
|
12
|
+
onClose?: () => void;
|
|
9
13
|
}
|
|
10
14
|
declare const Option: {
|
|
11
|
-
({ label, onClick, selected, sx, value }: FilterOptionProps): React.JSX.Element;
|
|
15
|
+
({ label, onClick, selected, sx, value, checkbox, radio, showClose, onClose, }: FilterOptionProps): React.JSX.Element;
|
|
12
16
|
displayName: string;
|
|
13
17
|
};
|
|
14
18
|
export interface FilterSpacerProps {
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import { Box, P } from '../..';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import { Box, P, Checkbox, Radio } from '../..';
|
|
5
|
+
import { Close } from '../../../icons';
|
|
6
|
+
const Option = ({ label, onClick, selected, sx, value, checkbox, radio = false, showClose = false, onClose, }) => {
|
|
7
|
+
return (React.createElement(OptionWrapper, { "data-value": value, onClick: onClick, "$selected": selected, "$sx": sx, "$hasCheckbox": !!checkbox },
|
|
8
|
+
checkbox && React.createElement(Checkbox, { selected: selected }),
|
|
9
|
+
radio && React.createElement(Radio, { checked: selected, value: value }),
|
|
10
|
+
React.createElement(Box, { "$dir": "column", "$display": "flex" }, label && (React.createElement(P, { "$color": "grey-4", "$fontSize": 14, "$lineHeight": 20, "$mediumBold": true, "$textClampLines": 1 }, label))),
|
|
11
|
+
showClose && (React.createElement(Close, { sx: "margin-left: auto; pointer-events: auto !important;", size: 16, onClick: (event) => {
|
|
12
|
+
event.stopPropagation();
|
|
13
|
+
onClose && onClose();
|
|
14
|
+
} }))));
|
|
8
15
|
};
|
|
9
16
|
Option.displayName = 'Filter.Option';
|
|
10
17
|
const OptionWrapper = styled.div `
|
|
@@ -15,13 +22,13 @@ const OptionWrapper = styled.div `
|
|
|
15
22
|
display: flex;
|
|
16
23
|
align-items: center;
|
|
17
24
|
gap: 8px;
|
|
18
|
-
min-width:
|
|
25
|
+
min-width: 217px;
|
|
19
26
|
|
|
20
27
|
& > * {
|
|
21
28
|
pointer-events: none;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
${({ $selected }) => {
|
|
31
|
+
${({ $selected, $hasCheckbox }) => {
|
|
25
32
|
if ($selected) {
|
|
26
33
|
return `
|
|
27
34
|
background-color: var(--color-grey-9);
|
|
@@ -29,6 +36,11 @@ const OptionWrapper = styled.div `
|
|
|
29
36
|
background-color: var(--color-grey-8);
|
|
30
37
|
}`;
|
|
31
38
|
}
|
|
39
|
+
if ($hasCheckbox) {
|
|
40
|
+
return `&:hover {
|
|
41
|
+
background-color: var(--color-grey-10);
|
|
42
|
+
}`;
|
|
43
|
+
}
|
|
32
44
|
return `
|
|
33
45
|
&:hover {
|
|
34
46
|
background-color: var(--color-grey-10);
|
|
@@ -14,4 +14,4 @@ export interface PostProps extends React.PropsWithChildren {
|
|
|
14
14
|
isPaywalled?: boolean;
|
|
15
15
|
onJoin?: () => void;
|
|
16
16
|
}
|
|
17
|
-
export declare const Post: ({ actions, author, authorActive, authorHref, authorImage, content, createdDate, dropdown, id, images, isPaywalled, onJoin, }: PostProps) => React.JSX.Element;
|
|
17
|
+
export declare const Post: ({ actions, author, authorActive, authorHref, authorImage, children, content, createdDate, dropdown, hasComments, id, images, isPaywalled, onJoin, }: PostProps) => React.JSX.Element;
|
|
@@ -6,9 +6,10 @@ import { Button } from '../../actions/button';
|
|
|
6
6
|
import { Avatar } from '../../iconography/avatar';
|
|
7
7
|
import { Lock } from '../../../icons';
|
|
8
8
|
import { abbrTimeBeforeDate } from './helpers';
|
|
9
|
-
export const Post = ({ actions, author, authorActive, authorHref, authorImage, content, createdDate, dropdown, id, images, isPaywalled = false, onJoin, }) => {
|
|
9
|
+
export const Post = ({ actions, author, authorActive, authorHref, authorImage, children, content, createdDate, dropdown, hasComments, id, images, isPaywalled = false, onJoin, }) => {
|
|
10
10
|
const componentId = React.useId();
|
|
11
11
|
const _actions = React.Children.toArray(actions);
|
|
12
|
+
const _comments = React.Children.toArray(children);
|
|
12
13
|
const subtitle = abbrTimeBeforeDate(new Date(createdDate));
|
|
13
14
|
return (React.createElement(Wrapper, { id: id },
|
|
14
15
|
React.createElement(Header, null,
|
|
@@ -29,7 +30,8 @@ export const Post = ({ actions, author, authorActive, authorHref, authorImage, c
|
|
|
29
30
|
React.createElement("br", null),
|
|
30
31
|
"to unlock this post"),
|
|
31
32
|
React.createElement(Button, { onClick: onJoin, size: "small", sx: "width: 213px;", type: "outlined" }, "Join now"))),
|
|
32
|
-
!!_actions.length && (React.createElement(ActionsWrapper, null, !isPaywalled && _actions))
|
|
33
|
+
!!_actions.length && (React.createElement(ActionsWrapper, null, !isPaywalled && _actions)),
|
|
34
|
+
hasComments && !!_comments.length && (React.createElement(CommentWrapper, null, _comments))));
|
|
33
35
|
};
|
|
34
36
|
const Wrapper = styled.div `
|
|
35
37
|
position: relative;
|
|
@@ -118,3 +120,9 @@ const ActionsWrapper = styled.div `
|
|
|
118
120
|
align-items: center;
|
|
119
121
|
padding: 24px;
|
|
120
122
|
`;
|
|
123
|
+
const CommentWrapper = styled.div `
|
|
124
|
+
padding: 24px;
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-flow: column nowrap;
|
|
127
|
+
gap: 24px;
|
|
128
|
+
`;
|