@teamturing/react-kit 2.14.1 → 2.15.1

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.
Files changed (35) hide show
  1. package/dist/core/Avatar/index.d.ts +13 -0
  2. package/dist/core/Checkbox/index.d.ts +12 -0
  3. package/dist/core/Datagrid/DatagridBody.d.ts +6 -0
  4. package/dist/core/Datagrid/DatagridCell.d.ts +6 -0
  5. package/dist/core/Datagrid/DatagridHeader.d.ts +9 -0
  6. package/dist/core/Datagrid/DatagridRow.d.ts +7 -0
  7. package/dist/core/Datagrid/index.d.ts +15 -0
  8. package/dist/core/DescriptionList/index.d.ts +23 -0
  9. package/dist/core/GradientText/index.d.ts +3 -3
  10. package/dist/core/Grid/index.d.ts +2 -2
  11. package/dist/core/Pagination/index.d.ts +2 -2
  12. package/dist/core/Pill/index.d.ts +11 -3
  13. package/dist/core/Select/index.d.ts +300 -0
  14. package/dist/core/Spinner/index.d.ts +4 -4
  15. package/dist/core/Stack/index.d.ts +2 -2
  16. package/dist/hook/useRelocation.d.ts +18 -0
  17. package/dist/hook/useSafeLayoutEffect.d.ts +3 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +4369 -3699
  20. package/esm/core/Avatar/index.js +68 -0
  21. package/esm/core/Checkbox/index.js +169 -0
  22. package/esm/core/Datagrid/DatagridBody.js +16 -0
  23. package/esm/core/Datagrid/DatagridCell.js +13 -0
  24. package/esm/core/Datagrid/DatagridHeader.js +41 -0
  25. package/esm/core/Datagrid/DatagridRow.js +26 -0
  26. package/esm/core/Datagrid/index.js +56 -0
  27. package/esm/core/DescriptionList/index.js +70 -0
  28. package/esm/core/Pill/index.js +16 -5
  29. package/esm/core/Select/index.js +234 -0
  30. package/esm/core/TextInput/index.js +4 -4
  31. package/esm/core/Textarea/index.js +2 -2
  32. package/esm/hook/useRelocation.js +34 -0
  33. package/esm/hook/useSafeLayoutEffect.js +5 -0
  34. package/esm/index.js +7 -0
  35. package/package.json +2 -2
@@ -0,0 +1,234 @@
1
+ import { forwardRef, useState } from 'react';
2
+ import SvgChevronDown from '../../packages/icons/esm/ChevronDown.js';
3
+ import { r as reactIsExports } from '../../node_modules/react-is/index.js';
4
+ import styled, { css } from 'styled-components';
5
+ import useProvidedOrCreatedRef from '../../hook/useProvidedOrCreatedRef.js';
6
+ import { forcePixelValue } from '../../utils/forcePixelValue.js';
7
+ import { isFunction } from '../../utils/isFunction.js';
8
+ import { isNullable } from '../../utils/isNullable.js';
9
+ import StyledIcon from '../StyledIcon/index.js';
10
+ import View from '../View/index.js';
11
+ import { j as jsxRuntimeExports } from '../../node_modules/react/jsx-runtime.js';
12
+
13
+ const Select = ({
14
+ children,
15
+ disabled,
16
+ validationStatus,
17
+ leadingVisual: LeadingVisual,
18
+ placeholder = '옵션 선택',
19
+ ...props
20
+ }, ref) => {
21
+ const PLACEHOLDER_VALUE = '';
22
+ const selectRef = useProvidedOrCreatedRef(ref);
23
+ const [isValueEmpty, setIsValueEmpty] = useState(isNullable(props.value) || props.value === PLACEHOLDER_VALUE);
24
+ const focusSelect = () => {
25
+ selectRef.current?.focus();
26
+ };
27
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(SelectWrapper, {
28
+ disabled: disabled,
29
+ onClick: focusSelect,
30
+ hasLeadingVisual: !isNullable(LeadingVisual),
31
+ validationStatus: validationStatus,
32
+ isValueEmpty: isValueEmpty,
33
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx(View, {
34
+ sx: {
35
+ 'flexShrink': 0,
36
+ 'fontSize': 'xxs',
37
+ 'fontWeight': 'medium',
38
+ 'color': 'text/neutral',
39
+ '& > svg': {
40
+ display: 'block',
41
+ width: 20,
42
+ height: 20,
43
+ color: 'icon/neutral/bold'
44
+ }
45
+ },
46
+ children: typeof LeadingVisual !== 'string' && reactIsExports.isValidElementType(LeadingVisual) ? /*#__PURE__*/jsxRuntimeExports.jsx(LeadingVisual, {}) : LeadingVisual
47
+ }), /*#__PURE__*/jsxRuntimeExports.jsxs(BaseSelect, {
48
+ ref: e => {
49
+ isFunction(ref) ? ref(e) : null;
50
+ selectRef.current = e;
51
+ },
52
+ placeholder: placeholder,
53
+ disabled: disabled,
54
+ ...props,
55
+ onChange: e => {
56
+ props.onChange?.(e);
57
+ if (!e.defaultPrevented) {
58
+ if (e.target.value === PLACEHOLDER_VALUE) {
59
+ setIsValueEmpty(true);
60
+ } else {
61
+ setIsValueEmpty(false);
62
+ }
63
+ }
64
+ },
65
+ children: [/*#__PURE__*/jsxRuntimeExports.jsx("option", {
66
+ label: placeholder,
67
+ value: PLACEHOLDER_VALUE
68
+ }), children]
69
+ }), /*#__PURE__*/jsxRuntimeExports.jsx(StyledIcon, {
70
+ sx: {
71
+ position: 'absolute',
72
+ top: '50%',
73
+ transform: 'translateY(-50%)',
74
+ right: 5,
75
+ pointerEvents: 'none'
76
+ },
77
+ icon: SvgChevronDown,
78
+ color: disabled ? 'icon/disabled' : 'icon/neutral/bolder',
79
+ size: 16
80
+ })]
81
+ });
82
+ };
83
+ const SelectWrapper = styled.div`
84
+ position: relative;
85
+ width: ${forcePixelValue('100%')};
86
+ border-width: ${forcePixelValue(1)};
87
+ border-style: solid;
88
+ border-radius: ${({
89
+ theme
90
+ }) => forcePixelValue(theme.radii.xs)};
91
+ border-color: ${({
92
+ theme
93
+ }) => theme.colors['border/input']};
94
+ background-color: ${({
95
+ theme
96
+ }) => theme.colors['bg/input']};
97
+ display: inline-flex;
98
+ align-items: center;
99
+
100
+ font-size: ${({
101
+ theme
102
+ }) => forcePixelValue(theme.fontSizes.xs)};
103
+ font-weight: ${({
104
+ theme
105
+ }) => theme.fontWeights.medium};
106
+ line-height: ${({
107
+ theme
108
+ }) => theme.lineHeights[2]};
109
+ color: ${({
110
+ theme
111
+ }) => theme.colors['text/neutral/subtle']};
112
+
113
+ /**
114
+ * placeholder style
115
+ */
116
+ ${({
117
+ theme,
118
+ isValueEmpty
119
+ }) => isValueEmpty ? css`
120
+ color: ${theme.colors['text/neutral/subtlest']};
121
+ ` : null}
122
+
123
+ &:after {
124
+ content: '';
125
+ position: absolute;
126
+ top: ${forcePixelValue(-1)};
127
+ right: ${forcePixelValue(-1)};
128
+ bottom: ${forcePixelValue(-1)};
129
+ left: ${forcePixelValue(-1)};
130
+
131
+ border: ${forcePixelValue(2)} solid transparent;
132
+ border-radius: ${({
133
+ theme
134
+ }) => forcePixelValue(theme.radii.xs)};
135
+ pointer-events: none;
136
+ }
137
+
138
+ ${props => props.validationStatus !== 'error' && !props.disabled && css`
139
+ &:hover:not(:focus-within) {
140
+ &:after {
141
+ border-color: ${({
142
+ theme
143
+ }) => theme.colors['border/hovered']};
144
+ }
145
+ }
146
+ `}
147
+
148
+ ${props => props.validationStatus === 'error' && css`
149
+ &:after {
150
+ border-color: ${({
151
+ theme
152
+ }) => theme.colors['border/danger']};
153
+ }
154
+ `}
155
+
156
+ ${props => props.validationStatus !== 'error' && css`
157
+ &:focus-within {
158
+ &:after {
159
+ border-color: ${({
160
+ theme
161
+ }) => theme.colors['border/focused']};
162
+ }
163
+ }
164
+ `}
165
+
166
+ ${props => props.disabled && css`
167
+ border-color: ${props.theme.colors['border/input']};
168
+ background-color: ${props.theme.colors['bg/disabled']};
169
+ color: ${props.theme.colors['text/disabled']};
170
+
171
+ select::placeholder {
172
+ color: ${props.theme.colors['text/disabled']};
173
+ }
174
+
175
+ select {
176
+ cursor: not-allowed;
177
+ }
178
+ `};
179
+
180
+ ${props => props.hasLeadingVisual && css`
181
+ padding-left: ${forcePixelValue(props.theme.space[5])};
182
+ select {
183
+ padding-left: ${forcePixelValue(props.theme.space[3])};
184
+ }
185
+ `}
186
+
187
+ transition: background-color 100ms;
188
+ &:after {
189
+ transition: border-color 100ms;
190
+ }
191
+ `;
192
+ const UnstyledSelect = styled.select`
193
+ font-size: inherit;
194
+ font-weight: inherit;
195
+ line-height: inherit;
196
+ font-family: inherit;
197
+ border-radius: inherit;
198
+ color: inherit;
199
+ transition: inherit;
200
+
201
+ border: 0;
202
+ background-color: transparent;
203
+ width: 100%;
204
+ &:focus {
205
+ outline: 0;
206
+ }
207
+
208
+ appearance: none;
209
+ -webkit-appearance: none;
210
+ -moz-appearance: none;
211
+ `;
212
+ const BaseSelect = styled(UnstyledSelect)`
213
+ padding-top: ${({
214
+ theme
215
+ }) => forcePixelValue(theme.space['4'])};
216
+ padding-right: ${({
217
+ theme
218
+ }) => forcePixelValue(theme.space['12'])};
219
+ padding-bottom: ${({
220
+ theme
221
+ }) => forcePixelValue(theme.space['4'])};
222
+ padding-left: ${({
223
+ theme
224
+ }) => forcePixelValue(theme.space['5'])};
225
+
226
+ white-space: pre;
227
+ text-overflow: ellipsis;
228
+ `;
229
+ const SelectOption = styled.option``;
230
+ var index = Object.assign( /*#__PURE__*/forwardRef(Select), {
231
+ Option: SelectOption
232
+ });
233
+
234
+ export { index as default };
@@ -38,8 +38,8 @@ const TextInput = /*#__PURE__*/forwardRef(({
38
38
  'color': color['text/neutral'],
39
39
  '& > svg': {
40
40
  display: 'block',
41
- width: 24,
42
- height: 24,
41
+ width: 20,
42
+ height: 20,
43
43
  color: color['icon/neutral/bold']
44
44
  }
45
45
  },
@@ -81,7 +81,7 @@ const TextInputWrapper = styled.div`
81
81
  border-style: solid;
82
82
  border-radius: ${({
83
83
  theme
84
- }) => forcePixelValue(theme.radii.s)};
84
+ }) => forcePixelValue(theme.radii.xs)};
85
85
  border-color: ${({
86
86
  theme
87
87
  }) => theme.colors['border/input']};
@@ -121,7 +121,7 @@ const TextInputWrapper = styled.div`
121
121
  border: ${forcePixelValue(2)} solid transparent;
122
122
  border-radius: ${({
123
123
  theme
124
- }) => forcePixelValue(theme.radii.s)};
124
+ }) => forcePixelValue(theme.radii.xs)};
125
125
  pointer-events: none;
126
126
  }
127
127
 
@@ -33,7 +33,7 @@ const TextareaWrapper = styled.div`
33
33
  border-style: solid;
34
34
  border-radius: ${({
35
35
  theme
36
- }) => forcePixelValue(theme.radii.s)};
36
+ }) => forcePixelValue(theme.radii.xs)};
37
37
  border-color: ${({
38
38
  theme
39
39
  }) => theme.colors['border/input']};
@@ -88,7 +88,7 @@ const TextareaWrapper = styled.div`
88
88
  border: ${forcePixelValue(2)} solid transparent;
89
89
  border-radius: ${({
90
90
  theme
91
- }) => forcePixelValue(theme.radii.s)};
91
+ }) => forcePixelValue(theme.radii.xs)};
92
92
  pointer-events: none;
93
93
  }
94
94
 
@@ -0,0 +1,34 @@
1
+ import { Children, isValidElement } from 'react';
2
+
3
+ /**
4
+ * `children`의 컴포넌트들을 시각적으로 재배치하기 위한 훅입니다.
5
+ */
6
+ const useRelocation = ({
7
+ children,
8
+ config
9
+ }) => {
10
+ const keys = Object.keys(config);
11
+ const values = Object.values(config);
12
+ const relocatableElementsObject = {};
13
+ const restElements = [];
14
+ Children.map(children, child => {
15
+ if (! /*#__PURE__*/isValidElement(child)) return;
16
+ const index = values.findIndex(value => child.type === value);
17
+ const isRelocatableComponent = index !== -1;
18
+ const relocationKey = keys[index];
19
+ const isDuplicatedComponent = relocatableElementsObject[relocationKey];
20
+ if (!isRelocatableComponent) {
21
+ restElements.push(child);
22
+ return;
23
+ }
24
+ if (isDuplicatedComponent) {
25
+ return;
26
+ }
27
+ if (isRelocatableComponent) {
28
+ relocatableElementsObject[relocationKey] = child;
29
+ }
30
+ });
31
+ return [relocatableElementsObject, restElements];
32
+ };
33
+
34
+ export { useRelocation as default };
@@ -0,0 +1,5 @@
1
+ import { useLayoutEffect, useEffect } from 'react';
2
+
3
+ const useSafeLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? useLayoutEffect : useEffect;
4
+
5
+ export { useSafeLayoutEffect as default };
package/esm/index.js CHANGED
@@ -1,6 +1,10 @@
1
+ export { default as Avatar } from './core/Avatar/index.js';
1
2
  export { default as Breadcrumbs } from './core/Breadcrumbs/index.js';
2
3
  export { default as Button } from './core/Button/index.js';
4
+ export { default as Checkbox } from './core/Checkbox/index.js';
3
5
  export { default as Chip } from './core/Chip/index.js';
6
+ export { default as Datagrid } from './core/Datagrid/index.js';
7
+ export { default as DescriptionList } from './core/DescriptionList/index.js';
4
8
  export { default as Dialog } from './core/Dialog/index.js';
5
9
  export { default as DialogHandler } from './core/DialogHandler/index.js';
6
10
  export { default as GradientText } from './core/GradientText/index.js';
@@ -15,6 +19,7 @@ export { default as Overlay } from './core/Overlay/index.js';
15
19
  export { default as OverlayPopper } from './core/OverlayPopper/index.js';
16
20
  export { default as Pagination } from './core/Pagination/index.js';
17
21
  export { default as Pill } from './core/Pill/index.js';
22
+ export { default as Select } from './core/Select/index.js';
18
23
  export { default as Space } from './core/Space/index.js';
19
24
  export { default as Spinner } from './core/Spinner/index.js';
20
25
  export { default as Stack } from './core/Stack/index.js';
@@ -36,7 +41,9 @@ export { default as useFocusZone } from './hook/useFocusZone.js';
36
41
  export { default as useMediaQuery } from './hook/useMediaQuery.js';
37
42
  export { default as useOutsideClick } from './hook/useOutsideClick.js';
38
43
  export { default as useProvidedOrCreatedRef } from './hook/useProvidedOrCreatedRef.js';
44
+ export { default as useRelocation } from './hook/useRelocation.js';
39
45
  export { default as useResize } from './hook/useResize.js';
46
+ export { default as useSafeLayoutEffect } from './hook/useSafeLayoutEffect.js';
40
47
  export { default as useToggleHandler } from './hook/useToggleHandler.js';
41
48
  export { default as theme } from './theme/index.js';
42
49
  export { lineClamp, sx, textDecoration, whiteSpace, wordBreak } from './utils/styled-system/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamturing/react-kit",
3
- "version": "2.14.1",
3
+ "version": "2.15.1",
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",
@@ -62,5 +62,5 @@
62
62
  "react-is": "^18.2.0",
63
63
  "styled-system": "^5.1.5"
64
64
  },
65
- "gitHead": "60a452ea4bddbf4b7256820dd694b0479fbbad52"
65
+ "gitHead": "4dd8a356f2d54ce591d4f7b988f92b8098c500ef"
66
66
  }