@soul-refiner/design-system 0.2.67 → 0.2.69

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 extends React.PropsWithChildren {
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
- value: string;
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, children, disabled, graphic, label, sx, triggerType, value, }: FilterProps): React.JSX.Element;
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;
@@ -27,6 +30,6 @@ export interface FilterTriggerProps {
27
30
  onClick?: (event: React.MouseEvent) => void;
28
31
  open: boolean;
29
32
  type: FilterTriggerTypes;
30
- value: string;
33
+ value?: string;
31
34
  }
32
35
  export { Filter };
@@ -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
- const Filter = ({ closeOnBlur = true, children, disabled, graphic, label, sx, triggerType, value, }) => {
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,36 @@ 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 }, children)));
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)));
32
61
  };
33
62
  const Wrapper = styled.div `
34
63
  position: relative;
@@ -41,6 +70,18 @@ const Container = styled.div `
41
70
  width: max-content;
42
71
  z-index: 100;
43
72
  outline: none;
73
+ box-shadow: var(--elevation-2);
74
+ background-color: var(--color-white);
75
+ cursor: pointer;
76
+ border-radius: 8px;
77
+
78
+ & > div:first-of-type {
79
+ border-radius: 8px 8px 0px 0px;
80
+ }
81
+
82
+ & > div:last-of-type {
83
+ border-radius: 0px 0px 8px 8px;
84
+ }
44
85
  `;
45
86
  /********************************************************
46
87
  * Triggers
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soul-refiner/design-system",
3
- "version": "0.2.67",
3
+ "version": "0.2.69",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
6
  "publishConfig": {