@teamturing/react-kit 2.52.1 → 2.53.0

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.
@@ -4,7 +4,7 @@ type Props = {
4
4
  variant?: 'neutral' | 'danger';
5
5
  leadingVisual?: ElementType | ReactNode;
6
6
  trailingVisual?: ElementType | ReactNode;
7
- description?: string;
7
+ description?: ReactNode;
8
8
  descriptionLayout?: 'inline' | 'block';
9
9
  disabled?: boolean;
10
10
  selected?: boolean;
@@ -0,0 +1,25 @@
1
+ import { HTMLProps } from 'react';
2
+ import { SxProp } from '../../utils/styled-system';
3
+ type Props = {
4
+ file: File | Blob;
5
+ variant?: 'default' | 'thumbnail';
6
+ /**
7
+ * 비활성화 상태를 정의합니다.
8
+ */
9
+ disabled?: boolean;
10
+ /**
11
+ * 로딩 상태를 정의합니다.
12
+ */
13
+ loading?: boolean;
14
+ /**
15
+ *
16
+ */
17
+ validationStatus?: 'error' | undefined;
18
+ /**
19
+ * 시각적인 후행 부분에 상호작용할 요소를 정의합니다.
20
+ */
21
+ trailingAction?: React.ReactElement<HTMLProps<HTMLButtonElement>>;
22
+ } & SxProp;
23
+ declare const FileItem: ({ file, variant, disabled, loading, validationStatus, trailingAction, ...props }: Props) => import("react/jsx-runtime").JSX.Element;
24
+ export default FileItem;
25
+ export type { Props as FileItemProps };
package/dist/index.d.ts CHANGED
@@ -37,6 +37,8 @@ export { default as Drawer } from './core/Drawer';
37
37
  export type { DrawerProps, UnstyledDrawerHeaderProps, UnstyledDrawerBodyProps, UnstyledDrawerFooterProps, DrawerHeaderProps, DrawerHeaderIconButtonProps, DrawerBodyProps, DrawerFooterProps, } from './core/Drawer';
38
38
  export { default as EmptyState } from './core/EmptyState';
39
39
  export type { EmptyStateProps } from './core/EmptyState';
40
+ export { default as FileItem } from './core/FileItem';
41
+ export type { FileItemProps } from './core/FileItem';
40
42
  export { default as Flash } from './core/Flash';
41
43
  export type { FlashProps } from './core/Flash';
42
44
  export { default as FormControl } from './core/FormControl';
package/dist/index.js CHANGED
@@ -4716,6 +4716,219 @@ const BaseEmptyState = styled__default.default.div`
4716
4716
  ${sx}
4717
4717
  `;
4718
4718
 
4719
+ const FileItem = ({
4720
+ file,
4721
+ variant = 'default',
4722
+ disabled,
4723
+ loading,
4724
+ validationStatus,
4725
+ trailingAction,
4726
+ ...props
4727
+ }) => {
4728
+ const fileType = file.type.match('image/*') ? 'image' : file.type.match('video/*') ? 'video' : 'whatever';
4729
+ const fileName = 'name' in file ? file.name : '';
4730
+ const FileIcon = fileType === 'image' ? icons.PictureIcon : fileType === 'video' ? icons.VideoIcon : icons.DocumentIcon;
4731
+ const [objectUrl, setObjectUrl] = React.useState('');
4732
+ React.useEffect(() => {
4733
+ setObjectUrl(URL.createObjectURL(file));
4734
+ return () => {
4735
+ URL.revokeObjectURL(objectUrl);
4736
+ };
4737
+ }, []);
4738
+ return /*#__PURE__*/jsxRuntime.jsx(BaseFile, {
4739
+ variant: variant,
4740
+ disabled: disabled,
4741
+ loading: disabled,
4742
+ validationStatus: validationStatus,
4743
+ trailingAction: trailingAction,
4744
+ ...props,
4745
+ children: variant === 'default' ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
4746
+ children: [/*#__PURE__*/jsxRuntime.jsx(FileIcon, {}), /*#__PURE__*/jsxRuntime.jsx("span", {
4747
+ children: fileName
4748
+ }), validationStatus === 'error' ? /*#__PURE__*/jsxRuntime.jsx(StyledIcon, {
4749
+ icon: icons.ExclamationPointInCircleIcon,
4750
+ size: 24,
4751
+ color: 'icon/danger'
4752
+ }) : loading ? /*#__PURE__*/jsxRuntime.jsx(Spinner, {
4753
+ width: 24,
4754
+ height: 24
4755
+ }) : null, trailingAction]
4756
+ }) : variant === 'thumbnail' ? /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
4757
+ children: [fileType === 'image' ? /*#__PURE__*/jsxRuntime.jsx("img", {
4758
+ src: objectUrl
4759
+ }) : fileType === 'video' ? /*#__PURE__*/jsxRuntime.jsxs("div", {
4760
+ className: 'file__thumbnail__video',
4761
+ children: [/*#__PURE__*/jsxRuntime.jsx("video", {
4762
+ src: objectUrl
4763
+ }), /*#__PURE__*/jsxRuntime.jsx(icons.VideoIcon, {})]
4764
+ }) : /*#__PURE__*/jsxRuntime.jsx("div", {
4765
+ className: 'file__thumbnail__whatever',
4766
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.DocumentIcon, {})
4767
+ }), validationStatus === 'error' || loading ? /*#__PURE__*/jsxRuntime.jsx("div", {
4768
+ className: 'file__thumbnail__cover',
4769
+ children: validationStatus === 'error' ? /*#__PURE__*/jsxRuntime.jsx(StyledIcon, {
4770
+ icon: icons.ExclamationPointInCircleIcon,
4771
+ size: 24,
4772
+ color: 'icon/danger'
4773
+ }) : loading ? /*#__PURE__*/jsxRuntime.jsx(Spinner, {
4774
+ width: 24,
4775
+ height: 24
4776
+ }) : null
4777
+ }) : null, trailingAction]
4778
+ }) : null
4779
+ });
4780
+ };
4781
+ const BaseFile = styled__default.default.div({
4782
+ position: 'relative'
4783
+ }, ({
4784
+ theme,
4785
+ disabled
4786
+ }) => variant({
4787
+ prop: 'variant',
4788
+ variants: {
4789
+ default: {
4790
+ 'backgroundColor': theme.colors['bg/neutral'],
4791
+ 'borderRadius': theme.radii.xs,
4792
+ 'width': '100%',
4793
+ 'height': utils.forcePixelValue(48),
4794
+ 'py': 1,
4795
+ 'pr': 2,
4796
+ 'pl': 4,
4797
+ 'display': 'flex',
4798
+ 'columnGap': 2,
4799
+ 'alignItems': 'center',
4800
+ '& > svg': {
4801
+ width: 24,
4802
+ height: 24,
4803
+ color: theme.colors['icon/neutral/bold']
4804
+ },
4805
+ '& > span': {
4806
+ flex: 1,
4807
+ fontSize: theme.fontSizes.xs,
4808
+ fontWeight: theme.fontWeights.medium,
4809
+ lineHeight: theme.lineHeights[2],
4810
+ overflow: 'hidden',
4811
+ textOverflow: 'ellipsis',
4812
+ whiteSpace: 'nowrap',
4813
+ color: theme.colors['text/neutral/subtle']
4814
+ },
4815
+ ...(disabled ? {
4816
+ '& > svg': {
4817
+ color: theme.colors['icon/disabled']
4818
+ },
4819
+ '& span': {
4820
+ color: theme.colors['text/disabled']
4821
+ }
4822
+ } : {})
4823
+ },
4824
+ thumbnail: {
4825
+ 'display': 'flex',
4826
+ 'alignItems': 'center',
4827
+ 'justifyContent': 'center',
4828
+ 'width': utils.forcePixelValue(160),
4829
+ 'maxWidth': utils.forcePixelValue(160),
4830
+ 'aspectRatio': '16 / 9',
4831
+ 'backgroundColor': theme.colors['bg/neutral'],
4832
+ 'overflow': 'hidden',
4833
+ 'borderRadius': 'xs',
4834
+ '&:after': {
4835
+ content: '""',
4836
+ position: 'absolute',
4837
+ top: utils.forcePixelValue(0),
4838
+ right: utils.forcePixelValue(0),
4839
+ bottom: utils.forcePixelValue(0),
4840
+ left: utils.forcePixelValue(0),
4841
+ borderWidth: 1,
4842
+ borderColor: theme.colors['border/neutral'],
4843
+ borderStyle: 'solid',
4844
+ borderRadius: 'xs',
4845
+ pointerEvents: 'none'
4846
+ },
4847
+ '& > .file__thumbnail__cover': {
4848
+ position: 'absolute',
4849
+ top: 0,
4850
+ left: 0,
4851
+ right: 0,
4852
+ bottom: 0,
4853
+ display: 'flex',
4854
+ justifyContent: 'center',
4855
+ alignItems: 'center',
4856
+ pointerEvents: 'none',
4857
+ backgroundColor: 'bg/neutral'
4858
+ },
4859
+ '& > img': {
4860
+ width: '100%',
4861
+ height: '100%',
4862
+ objectFit: 'cover'
4863
+ },
4864
+ '& > .file__thumbnail__video': {
4865
+ position: 'relative',
4866
+ width: '100%',
4867
+ height: '100%',
4868
+ backgroundColor: 'transparent',
4869
+ display: 'flex',
4870
+ alignItems: 'center',
4871
+ justifyContent: 'center',
4872
+ svg: {
4873
+ position: 'absolute',
4874
+ top: '50%',
4875
+ left: '50%',
4876
+ transform: 'translate(-50%, -50%)',
4877
+ width: 24,
4878
+ height: 24,
4879
+ color: 'icon/primary'
4880
+ },
4881
+ video: {
4882
+ width: '100%'
4883
+ }
4884
+ },
4885
+ '& > .file__thumbnail__whatever': {
4886
+ width: '100%',
4887
+ height: '100%',
4888
+ backgroundColor: 'bg/neutral',
4889
+ display: 'flex',
4890
+ alignItems: 'center',
4891
+ justifyContent: 'center',
4892
+ svg: {
4893
+ width: 24,
4894
+ height: 24,
4895
+ color: 'icon/neutral/bold'
4896
+ }
4897
+ },
4898
+ '& > button': {
4899
+ position: 'absolute',
4900
+ top: 0,
4901
+ right: 0
4902
+ },
4903
+ ...(disabled ? {} : {})
4904
+ }
4905
+ }
4906
+ }), ({
4907
+ theme,
4908
+ variant: propVariant
4909
+ }) => variant({
4910
+ prop: 'validationStatus',
4911
+ variants: {
4912
+ error: {
4913
+ ...(propVariant === 'thumbnail' ? {
4914
+ '&:after': {
4915
+ content: '""',
4916
+ position: 'absolute',
4917
+ top: utils.forcePixelValue(0),
4918
+ right: utils.forcePixelValue(0),
4919
+ bottom: utils.forcePixelValue(0),
4920
+ left: utils.forcePixelValue(0),
4921
+ borderWidth: 2,
4922
+ borderColor: theme.colors['border/danger'],
4923
+ borderStyle: 'solid',
4924
+ borderRadius: 'xs',
4925
+ pointerEvents: 'none'
4926
+ }
4927
+ } : {})
4928
+ }
4929
+ }
4930
+ }), sx);
4931
+
4719
4932
  const Flash = ({
4720
4933
  variant = 'neutral',
4721
4934
  icon: Icon = variant === 'danger' ? icons.WarningIcon : variant === 'assist' ? icons.TwinkleIcon : variant === 'accent' ? icons.InfoInCircleIcon : icons.InfoInCircleIcon,
@@ -7986,6 +8199,7 @@ exports.Dialog = index$8;
7986
8199
  exports.Drawer = index$7;
7987
8200
  exports.EmptyState = EmptyState;
7988
8201
  exports.EnigmaUI = index;
8202
+ exports.FileItem = FileItem;
7989
8203
  exports.Flash = index$6;
7990
8204
  exports.FormControl = index$5;
7991
8205
  exports.GradientText = GradientText;
@@ -0,0 +1,225 @@
1
+ import { ExclamationPointInCircleIcon, VideoIcon, DocumentIcon, PictureIcon } from '@teamturing/icons';
2
+ import { forcePixelValue } from '@teamturing/utils';
3
+ import { useState, useEffect } from 'react';
4
+ import styled from 'styled-components';
5
+ import '../../node_modules/styled-system/dist/index.esm.js';
6
+ import { sx } from '../../utils/styled-system/index.js';
7
+ import Spinner from '../Spinner/index.js';
8
+ import StyledIcon from '../StyledIcon/index.js';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import { variant } from '../../node_modules/@styled-system/variant/dist/index.esm.js';
11
+
12
+ const FileItem = ({
13
+ file,
14
+ variant = 'default',
15
+ disabled,
16
+ loading,
17
+ validationStatus,
18
+ trailingAction,
19
+ ...props
20
+ }) => {
21
+ const fileType = file.type.match('image/*') ? 'image' : file.type.match('video/*') ? 'video' : 'whatever';
22
+ const fileName = 'name' in file ? file.name : '';
23
+ const FileIcon = fileType === 'image' ? PictureIcon : fileType === 'video' ? VideoIcon : DocumentIcon;
24
+ const [objectUrl, setObjectUrl] = useState('');
25
+ useEffect(() => {
26
+ setObjectUrl(URL.createObjectURL(file));
27
+ return () => {
28
+ URL.revokeObjectURL(objectUrl);
29
+ };
30
+ }, []);
31
+ return /*#__PURE__*/jsx(BaseFile, {
32
+ variant: variant,
33
+ disabled: disabled,
34
+ loading: disabled,
35
+ validationStatus: validationStatus,
36
+ trailingAction: trailingAction,
37
+ ...props,
38
+ children: variant === 'default' ? /*#__PURE__*/jsxs(Fragment, {
39
+ children: [/*#__PURE__*/jsx(FileIcon, {}), /*#__PURE__*/jsx("span", {
40
+ children: fileName
41
+ }), validationStatus === 'error' ? /*#__PURE__*/jsx(StyledIcon, {
42
+ icon: ExclamationPointInCircleIcon,
43
+ size: 24,
44
+ color: 'icon/danger'
45
+ }) : loading ? /*#__PURE__*/jsx(Spinner, {
46
+ width: 24,
47
+ height: 24
48
+ }) : null, trailingAction]
49
+ }) : variant === 'thumbnail' ? /*#__PURE__*/jsxs(Fragment, {
50
+ children: [fileType === 'image' ? /*#__PURE__*/jsx("img", {
51
+ src: objectUrl
52
+ }) : fileType === 'video' ? /*#__PURE__*/jsxs("div", {
53
+ className: 'file__thumbnail__video',
54
+ children: [/*#__PURE__*/jsx("video", {
55
+ src: objectUrl
56
+ }), /*#__PURE__*/jsx(VideoIcon, {})]
57
+ }) : /*#__PURE__*/jsx("div", {
58
+ className: 'file__thumbnail__whatever',
59
+ children: /*#__PURE__*/jsx(DocumentIcon, {})
60
+ }), validationStatus === 'error' || loading ? /*#__PURE__*/jsx("div", {
61
+ className: 'file__thumbnail__cover',
62
+ children: validationStatus === 'error' ? /*#__PURE__*/jsx(StyledIcon, {
63
+ icon: ExclamationPointInCircleIcon,
64
+ size: 24,
65
+ color: 'icon/danger'
66
+ }) : loading ? /*#__PURE__*/jsx(Spinner, {
67
+ width: 24,
68
+ height: 24
69
+ }) : null
70
+ }) : null, trailingAction]
71
+ }) : null
72
+ });
73
+ };
74
+ const BaseFile = styled.div({
75
+ position: 'relative'
76
+ }, ({
77
+ theme,
78
+ disabled
79
+ }) => variant({
80
+ prop: 'variant',
81
+ variants: {
82
+ default: {
83
+ 'backgroundColor': theme.colors['bg/neutral'],
84
+ 'borderRadius': theme.radii.xs,
85
+ 'width': '100%',
86
+ 'height': forcePixelValue(48),
87
+ 'py': 1,
88
+ 'pr': 2,
89
+ 'pl': 4,
90
+ 'display': 'flex',
91
+ 'columnGap': 2,
92
+ 'alignItems': 'center',
93
+ '& > svg': {
94
+ width: 24,
95
+ height: 24,
96
+ color: theme.colors['icon/neutral/bold']
97
+ },
98
+ '& > span': {
99
+ flex: 1,
100
+ fontSize: theme.fontSizes.xs,
101
+ fontWeight: theme.fontWeights.medium,
102
+ lineHeight: theme.lineHeights[2],
103
+ overflow: 'hidden',
104
+ textOverflow: 'ellipsis',
105
+ whiteSpace: 'nowrap',
106
+ color: theme.colors['text/neutral/subtle']
107
+ },
108
+ ...(disabled ? {
109
+ '& > svg': {
110
+ color: theme.colors['icon/disabled']
111
+ },
112
+ '& span': {
113
+ color: theme.colors['text/disabled']
114
+ }
115
+ } : {})
116
+ },
117
+ thumbnail: {
118
+ 'display': 'flex',
119
+ 'alignItems': 'center',
120
+ 'justifyContent': 'center',
121
+ 'width': forcePixelValue(160),
122
+ 'maxWidth': forcePixelValue(160),
123
+ 'aspectRatio': '16 / 9',
124
+ 'backgroundColor': theme.colors['bg/neutral'],
125
+ 'overflow': 'hidden',
126
+ 'borderRadius': 'xs',
127
+ '&:after': {
128
+ content: '""',
129
+ position: 'absolute',
130
+ top: forcePixelValue(0),
131
+ right: forcePixelValue(0),
132
+ bottom: forcePixelValue(0),
133
+ left: forcePixelValue(0),
134
+ borderWidth: 1,
135
+ borderColor: theme.colors['border/neutral'],
136
+ borderStyle: 'solid',
137
+ borderRadius: 'xs',
138
+ pointerEvents: 'none'
139
+ },
140
+ '& > .file__thumbnail__cover': {
141
+ position: 'absolute',
142
+ top: 0,
143
+ left: 0,
144
+ right: 0,
145
+ bottom: 0,
146
+ display: 'flex',
147
+ justifyContent: 'center',
148
+ alignItems: 'center',
149
+ pointerEvents: 'none',
150
+ backgroundColor: 'bg/neutral'
151
+ },
152
+ '& > img': {
153
+ width: '100%',
154
+ height: '100%',
155
+ objectFit: 'cover'
156
+ },
157
+ '& > .file__thumbnail__video': {
158
+ position: 'relative',
159
+ width: '100%',
160
+ height: '100%',
161
+ backgroundColor: 'transparent',
162
+ display: 'flex',
163
+ alignItems: 'center',
164
+ justifyContent: 'center',
165
+ svg: {
166
+ position: 'absolute',
167
+ top: '50%',
168
+ left: '50%',
169
+ transform: 'translate(-50%, -50%)',
170
+ width: 24,
171
+ height: 24,
172
+ color: 'icon/primary'
173
+ },
174
+ video: {
175
+ width: '100%'
176
+ }
177
+ },
178
+ '& > .file__thumbnail__whatever': {
179
+ width: '100%',
180
+ height: '100%',
181
+ backgroundColor: 'bg/neutral',
182
+ display: 'flex',
183
+ alignItems: 'center',
184
+ justifyContent: 'center',
185
+ svg: {
186
+ width: 24,
187
+ height: 24,
188
+ color: 'icon/neutral/bold'
189
+ }
190
+ },
191
+ '& > button': {
192
+ position: 'absolute',
193
+ top: 0,
194
+ right: 0
195
+ },
196
+ ...(disabled ? {} : {})
197
+ }
198
+ }
199
+ }), ({
200
+ theme,
201
+ variant: propVariant
202
+ }) => variant({
203
+ prop: 'validationStatus',
204
+ variants: {
205
+ error: {
206
+ ...(propVariant === 'thumbnail' ? {
207
+ '&:after': {
208
+ content: '""',
209
+ position: 'absolute',
210
+ top: forcePixelValue(0),
211
+ right: forcePixelValue(0),
212
+ bottom: forcePixelValue(0),
213
+ left: forcePixelValue(0),
214
+ borderWidth: 2,
215
+ borderColor: theme.colors['border/danger'],
216
+ borderStyle: 'solid',
217
+ borderRadius: 'xs',
218
+ pointerEvents: 'none'
219
+ }
220
+ } : {})
221
+ }
222
+ }
223
+ }), sx);
224
+
225
+ export { FileItem as default };
package/esm/index.js CHANGED
@@ -16,6 +16,7 @@ export { default as DescriptionList } from './core/DescriptionList/index.js';
16
16
  export { default as Dialog } from './core/Dialog/index.js';
17
17
  export { default as Drawer } from './core/Drawer/index.js';
18
18
  export { default as EmptyState } from './core/EmptyState/index.js';
19
+ export { default as FileItem } from './core/FileItem/index.js';
19
20
  export { default as Flash } from './core/Flash/index.js';
20
21
  export { default as FormControl } from './core/FormControl/index.js';
21
22
  export { default as GradientText } from './core/GradientText/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamturing/react-kit",
3
- "version": "2.52.1",
3
+ "version": "2.53.0",
4
4
  "description": "React components, hooks for create teamturing web application",
5
5
  "author": "Sungchang Park <psch300@gmail.com> (https://github.com/psch300)",
6
6
  "homepage": "https://github.com/weareteamturing/bombe#readme",
@@ -66,5 +66,5 @@
66
66
  "react-textarea-autosize": "^8.5.3",
67
67
  "styled-system": "^5.1.5"
68
68
  },
69
- "gitHead": "bc2a674fefa2e1fe34a21754ed2283a04273f0cc"
69
+ "gitHead": "abcc2cc8d11799d8c8895282864db9a41b34bb57"
70
70
  }