@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.
@@ -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?: string;
12
+ label: string;
13
13
  sx?: string;
14
14
  triggerType: FilterTriggerTypes;
15
15
  options: (Omit<FilterOptionProps, 'selected' | 'onClick'> | 'break')[];
16
16
  closeOnChange?: boolean;
17
- onChange?: (event: React.MouseEvent) => void;
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, onChange, }: FilterProps): React.JSX.Element;
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, onChange, }) => {
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 || options[0]?.value);
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 handleChange = (event) => {
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 (onChange)
44
- onChange(event);
63
+ if (optionOnChange)
64
+ optionOnChange(event);
45
65
  };
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}` });
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
- return (React.createElement(Option, { key: option.value, onClick: handleChange, selected: isSelected(option.value), ...option }));
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: options.find((option) => {
55
- if (typeof option === 'string' && option === 'break') {
56
- return false;
57
- }
58
- return isSelected(option.value);
59
- })?.label }),
60
- open && React.createElement(Container, { ref: optionsRef }, dropdownOptions)));
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-primary-blue-4);
214
+ background-color: var(--color-white);
169
215
  font-family: var(--font-inter);
170
216
 
171
- & > * {
172
- color: var(--color-primary-blue-2);
173
- fill: currentColor;
217
+ ${({ $labelIsDefault }) => !$labelIsDefault
218
+ ? `
219
+ & > * {
220
+ color: var(--color-primary-blue-2);
221
+ fill: currentColor;
174
222
 
175
- &:hover {
176
- color: var(--color-primary-blue-1);
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
- 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)))));
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: 164px;
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
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soul-refiner/design-system",
3
- "version": "0.2.72",
3
+ "version": "0.2.74",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
6
  "publishConfig": {