@loword/loword-design-system 0.0.6 → 0.0.7

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 (51) hide show
  1. package/dist/components/Icon/LucideIcon.d.ts.map +1 -1
  2. package/dist/components/Icon/LucideIcon.js +9 -1
  3. package/dist/components/LDAnchor/AnchorBase.d.ts +24 -0
  4. package/dist/components/LDAnchor/AnchorBase.d.ts.map +1 -0
  5. package/dist/components/LDAnchor/AnchorBase.js +69 -0
  6. package/dist/components/LDAnchor/LDAnchor.d.ts +10 -0
  7. package/dist/components/LDAnchor/LDAnchor.d.ts.map +1 -0
  8. package/dist/components/LDAnchor/LDAnchor.js +14 -0
  9. package/dist/components/LDAutoComplete/AutoCompleteBase.d.ts +36 -0
  10. package/dist/components/LDAutoComplete/AutoCompleteBase.d.ts.map +1 -0
  11. package/dist/components/LDAutoComplete/AutoCompleteBase.js +175 -0
  12. package/dist/components/LDAutoComplete/LDAutoComplete.d.ts +19 -0
  13. package/dist/components/LDAutoComplete/LDAutoComplete.d.ts.map +1 -0
  14. package/dist/components/LDAutoComplete/LDAutoComplete.js +7 -0
  15. package/dist/components/LDEditor/EditorBase.js +1 -1
  16. package/dist/components/LDEditor/LDEditor.d.ts.map +1 -1
  17. package/dist/components/LDEditor/LDEditor.js +1 -1
  18. package/dist/components/LDFileUpload/FileUploadBase.d.ts +52 -0
  19. package/dist/components/LDFileUpload/FileUploadBase.d.ts.map +1 -0
  20. package/dist/components/LDFileUpload/FileUploadBase.js +186 -0
  21. package/dist/components/LDFileUpload/LDFileUpload.d.ts +16 -0
  22. package/dist/components/LDFileUpload/LDFileUpload.d.ts.map +1 -0
  23. package/dist/components/LDFileUpload/LDFileUpload.js +8 -0
  24. package/dist/components/LDFileUpload/LDFileUploadList.d.ts +17 -0
  25. package/dist/components/LDFileUpload/LDFileUploadList.d.ts.map +1 -0
  26. package/dist/components/LDFileUpload/LDFileUploadList.js +8 -0
  27. package/dist/components/LDFileUpload/LDImageUpload.d.ts +16 -0
  28. package/dist/components/LDFileUpload/LDImageUpload.d.ts.map +1 -0
  29. package/dist/components/LDFileUpload/LDImageUpload.js +8 -0
  30. package/dist/components/LDFileUpload/LDImageUploadList.d.ts +17 -0
  31. package/dist/components/LDFileUpload/LDImageUploadList.d.ts.map +1 -0
  32. package/dist/components/LDFileUpload/LDImageUploadList.js +8 -0
  33. package/dist/components/LDInput/LDInput.d.ts +2 -1
  34. package/dist/components/LDInput/LDInput.d.ts.map +1 -1
  35. package/dist/components/LDInput/LDInput.js +6 -6
  36. package/dist/constants/file.d.ts +1 -0
  37. package/dist/constants/file.d.ts.map +1 -1
  38. package/dist/constants/file.js +1 -0
  39. package/dist/index.css +239 -4
  40. package/dist/index.d.ts +8 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +10 -2
  43. package/dist/utils/file.d.ts +2 -0
  44. package/dist/utils/file.d.ts.map +1 -1
  45. package/dist/utils/file.js +35 -2
  46. package/package.json +1 -1
  47. package/src/styles/components/auto-complete.css +72 -0
  48. package/src/styles/components/index.css +1 -0
  49. package/dist/components/LDFileUpload/LDFileUploadBase.d.ts +0 -50
  50. package/dist/components/LDFileUpload/LDFileUploadBase.d.ts.map +0 -1
  51. package/dist/components/LDFileUpload/LDFileUploadBase.js +0 -102
@@ -0,0 +1,186 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, useContext, useState, } from 'react';
4
+ import cn from '../../utils/cn.js';
5
+ import { FILE_EXTENSIONS } from '../../constants/file.js';
6
+ import LDButton from '../LDButton/LDButton.js';
7
+ import LDCarousel from '../LDCarousel/LDCarousel.js';
8
+ import { fileToBase64, getFileIcon, getFileSizeUnit, isImage, validAllowedExtesions, validFileSize, validImageSize, } from '../../utils/file.js';
9
+ import LDToast from '../LDToast/LDToast.js';
10
+ import { renderIcon } from '../../utils/renderIcon.js';
11
+ const FileUploadContext = createContext(null);
12
+ export const useFileUploadContext = () => {
13
+ const fileUploadContext = useContext(FileUploadContext);
14
+ if (!fileUploadContext) {
15
+ throw new Error('LDFileUploadBase 하위 컴포넌트는 Root 내부에서 사용해야 합니다.');
16
+ }
17
+ return fileUploadContext;
18
+ };
19
+ const Root = ({ recommendedSize, maxSize, allowedExtensions, maxFileCount, fileList, setFileList, onChangeFile, onDeleteFile, className, children, }) => {
20
+ return (_jsx(FileUploadContext.Provider, { value: {
21
+ recommendedSize,
22
+ maxSize,
23
+ allowedExtensions,
24
+ maxFileCount,
25
+ fileList,
26
+ setFileList,
27
+ onChangeFile,
28
+ onDeleteFile,
29
+ }, children: _jsx("div", { className: cn('w-full', className), children: children }) }));
30
+ };
31
+ const Input = ({ type = 'default', label = '파일 선택', ...props }) => {
32
+ const { allowedExtensions, maxSize, fileList, setFileList, maxFileCount, onChangeFile, } = useFileUploadContext();
33
+ const getFileError = async (file) => {
34
+ if (!validAllowedExtesions(file, allowedExtensions)) {
35
+ const allowed = allowedExtensions
36
+ .map((item) => FILE_EXTENSIONS[item].toUpperCase())
37
+ .join(', ');
38
+ return `지원하지 않는 파일 형식입니다. ${allowed} 파일만 업로드 가능합니다.`;
39
+ }
40
+ if (!validFileSize(file, maxSize)) {
41
+ return `파일 크기가 너무 큽니다. ${getFileSizeUnit(maxSize)} 이하 파일을 선택해주세요.`;
42
+ }
43
+ if (isImage(file.name) && !(await validImageSize(file))) {
44
+ return '이미지 해상도가 너무 큽니다. 더 작은 크기의 이미지를 선택해주세요.';
45
+ }
46
+ return null;
47
+ };
48
+ const handleFile = async (e) => {
49
+ const files = e.target.files;
50
+ if (!files)
51
+ return;
52
+ if (fileList.length + files.length > maxFileCount) {
53
+ LDToast.error(`최대 ${maxFileCount}개까지 업로드할 수 있습니다.`);
54
+ return;
55
+ }
56
+ for (const file of files) {
57
+ const error = await getFileError(file);
58
+ if (error) {
59
+ LDToast.error(error);
60
+ return;
61
+ }
62
+ }
63
+ const newFiles = [];
64
+ for (const file of files) {
65
+ try {
66
+ const data = await fileToBase64(file);
67
+ newFiles.push(data);
68
+ }
69
+ catch (error) {
70
+ if (error instanceof Error) {
71
+ LDToast.error(error.message);
72
+ return;
73
+ }
74
+ LDToast.error('파일 업로드 중 문제가 발생했습니다. 잠시후 다시 시도해주세요.');
75
+ return;
76
+ }
77
+ }
78
+ const newList = [...fileList, ...newFiles];
79
+ setFileList(newList);
80
+ await onChangeFile(newList);
81
+ };
82
+ const fileInput = (_jsx("input", { type: "file", multiple: maxFileCount > 1, onClick: (e) => (e.currentTarget.value = ''), onChange: (e) => handleFile(e), className: "sr-only" }));
83
+ if (type === 'image') {
84
+ return (_jsxs("label", { className: cn('border-3 border-dotted rounded-xl border-neutral100 bg-neutral50 text-neutral500', 'size-21 flex justify-center items-center ld-transition', 'hover:bg-neutral-100 hover:border-neutral200 hover:cursor-pointer hover:text-neutral600', props.className), children: [renderIcon('images', 'size-6'), fileInput] }));
85
+ }
86
+ return (_jsxs(LDButton, { as: "label", ...props, children: [label, fileInput] }));
87
+ };
88
+ const CardList = (props) => {
89
+ const { fileList, setFileList, allowedExtensions, maxSize, onChangeFile, onDeleteFile, } = useFileUploadContext();
90
+ const [hoveredList, setHoveredList] = useState(new Array(fileList.length).fill(false));
91
+ const handleFile = async (e, idx) => {
92
+ const files = e.target.files;
93
+ if (!files)
94
+ return;
95
+ const file = files[0];
96
+ if (!file)
97
+ return;
98
+ if (!validAllowedExtesions(file, allowedExtensions)) {
99
+ const allowed = allowedExtensions
100
+ .map((item) => FILE_EXTENSIONS[item].toUpperCase())
101
+ .join(', ');
102
+ LDToast.error(`지원하지 않는 파일 형식입니다. ${allowed} 파일만 업로드 가능합니다.`);
103
+ return;
104
+ }
105
+ if (!validFileSize(file, maxSize)) {
106
+ LDToast.error(`파일 크기가 너무 큽니다. ${getFileSizeUnit(maxSize)} 이하 파일을 선택해주세요.`);
107
+ return;
108
+ }
109
+ if (isImage(file.name) && !(await validImageSize(file))) {
110
+ LDToast.error('이미지 해상도가 너무 큽니다. 더 작은 크기의 이미지를 선택해주세요.');
111
+ return;
112
+ }
113
+ try {
114
+ const data = await fileToBase64(file);
115
+ const newList = fileList.map((item, i) => (i === idx ? data : item));
116
+ setFileList(newList);
117
+ await onChangeFile(newList);
118
+ }
119
+ catch (error) {
120
+ if (error instanceof Error) {
121
+ LDToast.error(error.message);
122
+ return;
123
+ }
124
+ LDToast.error('파일 업로드 중 문제가 발생했습니다. 잠시후 다시 시도해주세요.');
125
+ }
126
+ };
127
+ const handleDeleteFile = async (idx) => {
128
+ const target = fileList[idx];
129
+ if (!target)
130
+ return;
131
+ try {
132
+ const result = await onDeleteFile(target);
133
+ if (result) {
134
+ const newList = fileList.filter((_, i) => i !== idx);
135
+ setFileList(newList);
136
+ await onChangeFile(newList);
137
+ }
138
+ }
139
+ catch {
140
+ LDToast.error('파일 삭제 중 문제가 발생했습니다. 잠시후 다시 시도해주세요.');
141
+ }
142
+ };
143
+ if (props.type === 'image') {
144
+ const cards = fileList.map((file, idx) => (_jsxs("label", { className: "relative block size-21 overflow-hidden rounded-[21px] hover:cursor-pointer", onMouseOver: () => {
145
+ setHoveredList((prev) => {
146
+ const next = [...prev];
147
+ next[idx] = true;
148
+ return next;
149
+ });
150
+ }, onMouseOut: () => {
151
+ setHoveredList((prev) => {
152
+ const next = [...prev];
153
+ next[idx] = false;
154
+ return next;
155
+ });
156
+ }, children: [_jsx("img", { src: file?.src, alt: file?.fileName, className: "size-full object-cover" }), _jsx("input", { type: "file", onClick: (e) => (e.currentTarget.value = ''), onChange: (e) => handleFile(e, idx), className: "sr-only" }), _jsx(LDButton, { onClick: async (e) => {
157
+ e.preventDefault();
158
+ e.stopPropagation();
159
+ await handleDeleteFile(idx);
160
+ }, variant: "ghost", leftIcon: "trash2", color: "neutral", className: cn('text-neutral700 absolute top-2 right-2 rounded-sm bg-neutral-100 px-0 flex justify-center items-center min-w-0 h-5 w-5 ld-transition', hoveredList[idx] ? 'opacity-100' : 'opacity-0') })] }, `${file.fileName}_${idx}`)));
161
+ if (fileList.length <= 1) {
162
+ return (_jsx("div", { className: cn('flex flex-row gap-sm', props.className), children: cards }));
163
+ }
164
+ return (_jsx(LDCarousel, { className: props.className, slideSize: "auto", gap: 8, showArrows: false, showDots: false, slides: cards }));
165
+ }
166
+ return (_jsx("div", { className: "flex flex-col gap-sm w-full", children: fileList.map((file, idx) => (_jsxs("label", { className: "w-full flex flex-row justify-between items-center px-4 py-3 bg-neutral50 rounded-lg hover:cursor-pointer", children: [_jsxs("div", { className: "flex flex-row items-center gap-sm", children: [_jsx("div", { className: "size-15 overflow-hidden rounded-lg", children: _jsx("div", { className: "flex size-full items-center justify-center text-neutral500 bg-white", children: isImage(file.fileName) ? (_jsx("img", { src: file?.src, alt: file?.fileName, className: "size-full object-cover" })) : (renderIcon(getFileIcon(file.fileName), 'size-8')) }) }), _jsx("div", { className: "text-neutral700 display16", children: file.fileName })] }), _jsx("input", { type: "file", onClick: (e) => (e.currentTarget.value = ''), onChange: (e) => handleFile(e, idx), className: "sr-only" }), _jsx(LDButton, { onClick: async (e) => {
167
+ e.stopPropagation();
168
+ await handleDeleteFile(idx);
169
+ }, variant: "ghost", leftIcon: "trash2", size: "large", color: "neutral", className: "text-neutral500 rounded-sm bg-white px-0 flex justify-center items-center min-w-0 h-10 w-10 ld-transition" })] }, `${file.fileName}_${idx}`))) }));
170
+ };
171
+ const Description = ({ className }) => {
172
+ const { recommendedSize, maxSize, allowedExtensions, maxFileCount } = useFileUploadContext();
173
+ const recommendedSizeText = recommendedSize &&
174
+ `권장 사이즈 ${recommendedSize.width}x${recommendedSize.height}, `;
175
+ const requiredText = `최대 크기 ${getFileSizeUnit(maxSize)}`;
176
+ const extensionsText = ` (${allowedExtensions.map((item) => FILE_EXTENSIONS[item]).join(', ')})`;
177
+ const countText = maxFileCount > 1 ? `, 최대 ${maxFileCount}개` : '';
178
+ return (_jsxs("p", { className: cn('display12 text-neutral400 semibold', className), children: [recommendedSizeText, requiredText, extensionsText, countText] }));
179
+ };
180
+ export const FileUploadBase = {
181
+ Root,
182
+ Input,
183
+ CardList,
184
+ Description,
185
+ };
186
+ export default FileUploadBase;
@@ -0,0 +1,16 @@
1
+ import { TMimeType } from '../../constants/file.js';
2
+ import { IFile } from '../../utils/file.js';
3
+ interface ILDFileUploadProps {
4
+ recommendedSize?: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ maxSize: number;
9
+ allowedExtensions: TMimeType[];
10
+ onChangeFile: (files: IFile[]) => void | Promise<void>;
11
+ onDeleteFile: (file: IFile) => Promise<boolean>;
12
+ isExistDescription?: boolean;
13
+ }
14
+ declare const LDFileUpload: (props: ILDFileUploadProps) => import("react/jsx-runtime").JSX.Element;
15
+ export default LDFileUpload;
16
+ //# sourceMappingURL=LDFileUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDFileUpload.d.ts","sourceRoot":"","sources":["../../../src/components/LDFileUpload/LDFileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGzC,UAAU,kBAAkB;IAC1B,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,SAAS,EAAE,CAAC;IAC/B,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,YAAY,GAAI,OAAO,kBAAkB,4CAuB9C,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import FileUploadBase from '../../components/LDFileUpload/FileUploadBase.js';
3
+ import { useState } from 'react';
4
+ const LDFileUpload = (props) => {
5
+ const [fileList, setFileList] = useState([]);
6
+ return (_jsxs(FileUploadBase.Root, { fileList: fileList, setFileList: setFileList, maxSize: props.maxSize, allowedExtensions: props.allowedExtensions, recommendedSize: props.recommendedSize ?? { width: 1200, height: 800 }, maxFileCount: 1, onChangeFile: props.onChangeFile, onDeleteFile: props.onDeleteFile, className: "flex flex-col gap-sm ld-transition", children: [fileList[0]?.src ? (_jsx(FileUploadBase.CardList, {})) : (_jsx(FileUploadBase.Input, { className: "w-fit" })), props.isExistDescription && _jsx(FileUploadBase.Description, {})] }));
7
+ };
8
+ export default LDFileUpload;
@@ -0,0 +1,17 @@
1
+ import { TMimeType } from '../../constants/file.js';
2
+ import { IFile } from '../../utils/file.js';
3
+ interface ILDFileUploadListProps {
4
+ recommendedSize?: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ maxSize: number;
9
+ allowedExtensions: TMimeType[];
10
+ maxFileCount: number;
11
+ onChangeFile: (files: IFile[]) => void | Promise<void>;
12
+ onDeleteFile: (file: IFile) => Promise<boolean>;
13
+ isExistDescription?: boolean;
14
+ }
15
+ declare const LDFileUploadList: (props: ILDFileUploadListProps) => import("react/jsx-runtime").JSX.Element;
16
+ export default LDFileUploadList;
17
+ //# sourceMappingURL=LDFileUploadList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDFileUploadList.d.ts","sourceRoot":"","sources":["../../../src/components/LDFileUpload/LDFileUploadList.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGzC,UAAU,sBAAsB;IAC9B,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,SAAS,EAAE,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,sBAAsB,4CAwBtD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import FileUploadBase from '../../components/LDFileUpload/FileUploadBase.js';
3
+ import { useState } from 'react';
4
+ const LDFileUploadList = (props) => {
5
+ const [fileList, setFileList] = useState([]);
6
+ return (_jsxs(FileUploadBase.Root, { fileList: fileList, setFileList: setFileList, maxSize: props.maxSize, allowedExtensions: props.allowedExtensions, recommendedSize: props.recommendedSize ?? { width: 1200, height: 800 }, maxFileCount: props.maxFileCount, onChangeFile: props.onChangeFile, onDeleteFile: props.onDeleteFile, className: "flex flex-col gap-sm ld-transition", children: [fileList.length < props.maxFileCount && (_jsx(FileUploadBase.Input, { className: "w-fit" })), props.isExistDescription && _jsx(FileUploadBase.Description, {}), _jsx("div", { className: "flex flex-row gap-sm", children: fileList.length > 0 && _jsx(FileUploadBase.CardList, {}) })] }));
7
+ };
8
+ export default LDFileUploadList;
@@ -0,0 +1,16 @@
1
+ import { TMimeType } from '../../constants/file.js';
2
+ import { IFile } from '../../utils/file.js';
3
+ interface ILDImageUploadProps {
4
+ recommendedSize?: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ maxSize: number;
9
+ allowedExtensions: TMimeType[];
10
+ onChangeFile: (files: IFile[]) => void | Promise<void>;
11
+ onDeleteFile: (file: IFile) => Promise<boolean>;
12
+ isExistDescription?: boolean;
13
+ }
14
+ declare const LDImageUpload: (props: ILDImageUploadProps) => import("react/jsx-runtime").JSX.Element;
15
+ export default LDImageUpload;
16
+ //# sourceMappingURL=LDImageUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDImageUpload.d.ts","sourceRoot":"","sources":["../../../src/components/LDFileUpload/LDImageUpload.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGzC,UAAU,mBAAmB;IAC3B,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,SAAS,EAAE,CAAC;IAC/B,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,aAAa,GAAI,OAAO,mBAAmB,4CAuBhD,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import FileUploadBase from '../../components/LDFileUpload/FileUploadBase.js';
3
+ import { useState } from 'react';
4
+ const LDImageUpload = (props) => {
5
+ const [fileList, setFileList] = useState([]);
6
+ return (_jsxs(FileUploadBase.Root, { fileList: fileList, setFileList: setFileList, maxSize: props.maxSize, allowedExtensions: props.allowedExtensions, recommendedSize: props.recommendedSize ?? { width: 1200, height: 800 }, maxFileCount: 1, onChangeFile: props.onChangeFile, onDeleteFile: props.onDeleteFile, className: "flex flex-col gap-sm ld-transition", children: [fileList[0]?.src ? (_jsx(FileUploadBase.CardList, { type: "image" })) : (_jsx(FileUploadBase.Input, { type: "image" })), props.isExistDescription && _jsx(FileUploadBase.Description, {})] }));
7
+ };
8
+ export default LDImageUpload;
@@ -0,0 +1,17 @@
1
+ import { TMimeType } from '../../constants/file.js';
2
+ import { IFile } from '../../utils/file.js';
3
+ interface ILDImageUploadListProps {
4
+ recommendedSize?: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ maxSize: number;
9
+ allowedExtensions: TMimeType[];
10
+ maxFileCount: number;
11
+ onChangeFile: (files: IFile[]) => void | Promise<void>;
12
+ onDeleteFile: (file: IFile) => Promise<boolean>;
13
+ isExistDescription?: boolean;
14
+ }
15
+ declare const LDImageUploadList: (props: ILDImageUploadListProps) => import("react/jsx-runtime").JSX.Element;
16
+ export default LDImageUploadList;
17
+ //# sourceMappingURL=LDImageUploadList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDImageUploadList.d.ts","sourceRoot":"","sources":["../../../src/components/LDFileUpload/LDImageUploadList.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGzC,UAAU,uBAAuB;IAC/B,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,SAAS,EAAE,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,iBAAiB,GAAI,OAAO,uBAAuB,4CAwBxD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import FileUploadBase from '../../components/LDFileUpload/FileUploadBase.js';
3
+ import { useState } from 'react';
4
+ const LDImageUploadList = (props) => {
5
+ const [fileList, setFileList] = useState([]);
6
+ return (_jsxs(FileUploadBase.Root, { fileList: fileList, setFileList: setFileList, maxSize: props.maxSize, allowedExtensions: props.allowedExtensions, recommendedSize: props.recommendedSize ?? { width: 1200, height: 800 }, maxFileCount: props.maxFileCount, onChangeFile: props.onChangeFile, onDeleteFile: props.onDeleteFile, className: "flex flex-col gap-sm ld-transition", children: [_jsxs("div", { className: "flex flex-row gap-sm", children: [fileList.length > 0 && _jsx(FileUploadBase.CardList, { type: "image" }), fileList.length < props.maxFileCount && (_jsx(FileUploadBase.Input, { type: "image" }))] }), props.isExistDescription && _jsx(FileUploadBase.Description, {})] }));
7
+ };
8
+ export default LDImageUploadList;
@@ -1,7 +1,8 @@
1
1
  import { type InputHTMLAttributes, type ReactNode, type Ref } from 'react';
2
2
  type InputVariant = 'filled' | 'outline' | 'ghost';
3
3
  type InputColor = 'neutral' | 'point' | 'danger';
4
- type InputSize = 'xSmall' | 'small' | 'medium' | 'large' | 'big' | 'xLarge';
4
+ export type InputSize = 'xSmall' | 'small' | 'medium' | 'large' | 'big' | 'xLarge';
5
+ export declare const inputSizeClasses: Record<InputSize, string>;
5
6
  export declare const iconSizes: Record<InputSize, number>;
6
7
  export interface LDInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'color' | 'size'> {
7
8
  /** 입력 필드 스타일 유형 */
@@ -1 +1 @@
1
- {"version":3,"file":"LDInput.d.ts","sourceRoot":"","sources":["../../../src/components/LDInput/LDInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAMf,KAAK,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AACnD,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjD,KAAK,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAqD5E,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAO/C,CAAC;AAGF,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,OAAO,GAAG,MAAM,CACjB;IACC,mBAAmB;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,YAAY;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uBAAuB;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,mBAAmB;IACnB,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAED,QAAA,MAAM,OAAO,GAAI,kHAad,YAAY,4CAuEd,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"LDInput.d.ts","sourceRoot":"","sources":["../../../src/components/LDInput/LDInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAMf,KAAK,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AACnD,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AAmCb,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOtD,CAAC;AAWF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAO/C,CAAC;AAGF,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,OAAO,GAAG,MAAM,CACjB;IACC,mBAAmB;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,YAAY;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uBAAuB;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,mBAAmB;IACnB,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAED,QAAA,MAAM,OAAO,GAAI,kHAad,YAAY,4CAuEd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -11,9 +11,9 @@ const variantColorClasses = {
11
11
  danger: 'bg-tintRed text-neutral900 outline-2 outline-red500',
12
12
  },
13
13
  outline: {
14
- neutral: 'bg-transparent text-neutral900 border border-mono200 focus:border-lb500',
15
- point: 'bg-transparent text-neutral900 border border-mono200 focus:border-lb500',
16
- danger: 'bg-transparent text-neutral900 border border-danger100 focus:border-red500',
14
+ neutral: 'bg-transparent text-neutral900 border-2 border-mono200 focus:border-lb500',
15
+ point: 'bg-transparent text-neutral900 border-2 border-mono200 focus:border-lb500',
16
+ danger: 'bg-transparent text-neutral900 border-2 border-danger100 focus:border-red500',
17
17
  },
18
18
  ghost: {
19
19
  neutral: 'bg-transparent text-neutral900 outline-2 outline-transparent hover:bg-mono50 focus:bg-mono100 focus:outline-lb500',
@@ -23,10 +23,10 @@ const variantColorClasses = {
23
23
  };
24
24
  const disabledVariantClasses = {
25
25
  filled: 'bg-mono100 text-mono400',
26
- outline: 'bg-transparent text-mono400 border border-mono200',
26
+ outline: 'bg-transparent text-mono400 border-2 border-mono200',
27
27
  ghost: 'bg-transparent text-mono400',
28
28
  };
29
- const sizeClasses = {
29
+ export const inputSizeClasses = {
30
30
  xSmall: 'input-2xs',
31
31
  small: 'input-xs',
32
32
  medium: 'input-sm',
@@ -65,7 +65,7 @@ const LDInput = ({ variant, color = 'neutral', size, showPasswordToggle = false,
65
65
  const fieldClassName = cn('w-full bold placeholder-mono400 ld-transition outline-none', variant &&
66
66
  (disabled
67
67
  ? disabledVariantClasses[variant]
68
- : variantColorClasses[variant][color]), size && !height && sizeClasses[size], height && 'h-full', disabled && 'cursor-not-allowed', 'read-only:cursor-not-allowed', resolvedRightAddon && size && addonRightPaddingClasses[size], className);
68
+ : variantColorClasses[variant][color]), size && !height && inputSizeClasses[size], height && 'h-full', disabled && 'cursor-not-allowed', 'read-only:cursor-not-allowed', resolvedRightAddon && size && addonRightPaddingClasses[size], className);
69
69
  return (_jsxs(InputBase.Root, { block: block, style: rootStyle, children: [_jsx(InputBase.Field, { ref: ref, type: resolvedType, disabled: disabled, className: fieldClassName, style: fieldStyle, ...props }), resolvedRightAddon && (_jsx(InputBase.Addon, { position: "right", className: "right-2.5 text-neutral40", children: resolvedRightAddon }))] }));
70
70
  };
71
71
  export default LDInput;
@@ -9,6 +9,7 @@ export declare const MAX_IMAGE_SIZE: {
9
9
  };
10
10
  /** MIME 타입 → 확장자 매핑 */
11
11
  export declare const FILE_EXTENSIONS: {
12
+ readonly 'image/avif': "avif";
12
13
  readonly 'image/apng': "apng";
13
14
  readonly 'image/bmp': "bmp";
14
15
  readonly 'image/gif': "gif";
@@ -1 +1 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/constants/file.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,uBAAuB;AACvB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;CAyBlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,eAAe,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC;AAEjE,2BAA2B;AAC3B,eAAO,MAAM,0BAA0B,EAAE,SAAS,EAQjD,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,gBAAgB,QAAwB,CAAC"}
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/constants/file.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,uBAAuB;AACvB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;CA0BlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,eAAe,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC;AAEjE,2BAA2B;AAC3B,eAAO,MAAM,0BAA0B,EAAE,SAAS,EAQjD,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,gBAAgB,QAAwB,CAAC"}
@@ -9,6 +9,7 @@ export const MAX_IMAGE_SIZE = {
9
9
  };
10
10
  /** MIME 타입 → 확장자 매핑 */
11
11
  export const FILE_EXTENSIONS = {
12
+ 'image/avif': 'avif',
12
13
  'image/apng': 'apng',
13
14
  'image/bmp': 'bmp',
14
15
  'image/gif': 'gif',