@tipp/ui-quill-editor 1.1.2 → 1.2.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.
Files changed (116) hide show
  1. package/dist/editor.cjs.map +1 -1
  2. package/dist/editor.d.cts +2 -6
  3. package/dist/editor.d.ts +2 -6
  4. package/dist/editor.js +218 -3
  5. package/dist/editor.js.map +1 -1
  6. package/dist/read-card.cjs.map +1 -1
  7. package/dist/read-card.d.cts +1 -2
  8. package/dist/read-card.d.ts +1 -2
  9. package/dist/read-card.js +189 -3
  10. package/dist/read-card.js.map +1 -1
  11. package/dist/type.cjs +19 -0
  12. package/dist/type.cjs.map +1 -0
  13. package/dist/type.d.cts +7 -0
  14. package/dist/type.d.ts +7 -0
  15. package/dist/type.js +1 -0
  16. package/package.json +26 -6
  17. package/src/editor.tsx +1 -6
  18. package/src/read-card.tsx +1 -1
  19. package/src/type.ts +5 -0
  20. package/dist/chunk-4ULZXT3Z.js +0 -267
  21. package/dist/chunk-4ULZXT3Z.js.map +0 -1
  22. package/dist/chunk-5WZL7EM7.js +0 -272
  23. package/dist/chunk-5WZL7EM7.js.map +0 -1
  24. package/dist/chunk-63UMKKIY.js +0 -254
  25. package/dist/chunk-63UMKKIY.js.map +0 -1
  26. package/dist/chunk-6Z3DIHNP.js +0 -253
  27. package/dist/chunk-6Z3DIHNP.js.map +0 -1
  28. package/dist/chunk-7346KRGN.js +0 -224
  29. package/dist/chunk-7346KRGN.js.map +0 -1
  30. package/dist/chunk-ACJWK26B.js +0 -272
  31. package/dist/chunk-ACJWK26B.js.map +0 -1
  32. package/dist/chunk-AEDRFU3N.js +0 -273
  33. package/dist/chunk-AEDRFU3N.js.map +0 -1
  34. package/dist/chunk-CCOIRSYJ.js +0 -258
  35. package/dist/chunk-CCOIRSYJ.js.map +0 -1
  36. package/dist/chunk-EQCXRM42.js +0 -253
  37. package/dist/chunk-EQCXRM42.js.map +0 -1
  38. package/dist/chunk-EZ2MSXWD.js +0 -211
  39. package/dist/chunk-EZ2MSXWD.js.map +0 -1
  40. package/dist/chunk-FFENCIRE.js +0 -254
  41. package/dist/chunk-FFENCIRE.js.map +0 -1
  42. package/dist/chunk-HZN6OVD6.js +0 -253
  43. package/dist/chunk-HZN6OVD6.js.map +0 -1
  44. package/dist/chunk-ICAKLBT5.js +0 -253
  45. package/dist/chunk-ICAKLBT5.js.map +0 -1
  46. package/dist/chunk-IIBNGFLN.mjs +0 -273
  47. package/dist/chunk-IIBNGFLN.mjs.map +0 -1
  48. package/dist/chunk-IWRASGLB.js +0 -215
  49. package/dist/chunk-IWRASGLB.js.map +0 -1
  50. package/dist/chunk-K4Q6PRQ3.js +0 -272
  51. package/dist/chunk-K4Q6PRQ3.js.map +0 -1
  52. package/dist/chunk-KBRYMAW4.js +0 -254
  53. package/dist/chunk-KBRYMAW4.js.map +0 -1
  54. package/dist/chunk-KLFBBLJB.js +0 -212
  55. package/dist/chunk-KLFBBLJB.js.map +0 -1
  56. package/dist/chunk-KYAHTSA6.js +0 -253
  57. package/dist/chunk-KYAHTSA6.js.map +0 -1
  58. package/dist/chunk-MX3IDKDT.js +0 -215
  59. package/dist/chunk-MX3IDKDT.js.map +0 -1
  60. package/dist/chunk-NFVMYQC2.js +0 -215
  61. package/dist/chunk-NFVMYQC2.js.map +0 -1
  62. package/dist/chunk-NQOX4TPA.js +0 -258
  63. package/dist/chunk-NQOX4TPA.js.map +0 -1
  64. package/dist/chunk-OLRR6W3N.js +0 -272
  65. package/dist/chunk-OLRR6W3N.js.map +0 -1
  66. package/dist/chunk-PSI2XOKW.js +0 -272
  67. package/dist/chunk-PSI2XOKW.js.map +0 -1
  68. package/dist/chunk-PWBZK7KO.js +0 -272
  69. package/dist/chunk-PWBZK7KO.js.map +0 -1
  70. package/dist/chunk-QAD3RXYR.js +0 -253
  71. package/dist/chunk-QAD3RXYR.js.map +0 -1
  72. package/dist/chunk-QC5RGGRB.js +0 -224
  73. package/dist/chunk-QC5RGGRB.js.map +0 -1
  74. package/dist/chunk-QGCFWTOT.js +0 -253
  75. package/dist/chunk-QGCFWTOT.js.map +0 -1
  76. package/dist/chunk-QVPYAKUW.js +0 -253
  77. package/dist/chunk-QVPYAKUW.js.map +0 -1
  78. package/dist/chunk-RC5DDS52.js +0 -272
  79. package/dist/chunk-RC5DDS52.js.map +0 -1
  80. package/dist/chunk-RVTX55MD.js +0 -215
  81. package/dist/chunk-RVTX55MD.js.map +0 -1
  82. package/dist/chunk-UE5CSHOY.js +0 -211
  83. package/dist/chunk-UE5CSHOY.js.map +0 -1
  84. package/dist/chunk-VWJC7GOO.js +0 -253
  85. package/dist/chunk-VWJC7GOO.js.map +0 -1
  86. package/dist/chunk-WITVYZYX.js +0 -211
  87. package/dist/chunk-WITVYZYX.js.map +0 -1
  88. package/dist/chunk-WQQTLSPU.js +0 -253
  89. package/dist/chunk-WQQTLSPU.js.map +0 -1
  90. package/dist/chunk-WZQACNB7.js +0 -215
  91. package/dist/chunk-WZQACNB7.js.map +0 -1
  92. package/dist/chunk-X5ODDFPU.js +0 -272
  93. package/dist/chunk-X5ODDFPU.js.map +0 -1
  94. package/dist/chunk-XFOLCHPG.js +0 -257
  95. package/dist/chunk-XFOLCHPG.js.map +0 -1
  96. package/dist/chunk-XO4BXXHE.js +0 -258
  97. package/dist/chunk-XO4BXXHE.js.map +0 -1
  98. package/dist/chunk-Y7747DJG.js +0 -195
  99. package/dist/chunk-Y7747DJG.js.map +0 -1
  100. package/dist/chunk-Z7OJPAOK.js +0 -211
  101. package/dist/chunk-Z7OJPAOK.js.map +0 -1
  102. package/dist/chunk-ZJXLAGSA.js +0 -213
  103. package/dist/chunk-ZJXLAGSA.js.map +0 -1
  104. package/dist/editor.d.mts +0 -30
  105. package/dist/editor.mjs +0 -7
  106. package/dist/index.cjs +0 -477
  107. package/dist/index.cjs.map +0 -1
  108. package/dist/index.d.cts +0 -4
  109. package/dist/index.d.mts +0 -3
  110. package/dist/index.d.ts +0 -4
  111. package/dist/index.js +0 -13
  112. package/dist/index.js.map +0 -1
  113. package/dist/index.mjs +0 -7
  114. package/dist/index.mjs.map +0 -1
  115. package/src/index.tsx +0 -2
  116. /package/dist/{editor.mjs.map → type.js.map} +0 -0
@@ -1,254 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
- var __hasOwnProp = Object.prototype.hasOwnProperty;
4
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __spreadValues = (a, b) => {
7
- for (var prop in b || (b = {}))
8
- if (__hasOwnProp.call(b, prop))
9
- __defNormalProp(a, prop, b[prop]);
10
- if (__getOwnPropSymbols)
11
- for (var prop of __getOwnPropSymbols(b)) {
12
- if (__propIsEnum.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- }
15
- return a;
16
- };
17
- var __objRest = (source, exclude) => {
18
- var target = {};
19
- for (var prop in source)
20
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
21
- target[prop] = source[prop];
22
- if (source != null && __getOwnPropSymbols)
23
- for (var prop of __getOwnPropSymbols(source)) {
24
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
25
- target[prop] = source[prop];
26
- }
27
- return target;
28
- };
29
- var __async = (__this, __arguments, generator) => {
30
- return new Promise((resolve, reject) => {
31
- var fulfilled = (value) => {
32
- try {
33
- step(generator.next(value));
34
- } catch (e) {
35
- reject(e);
36
- }
37
- };
38
- var rejected = (value) => {
39
- try {
40
- step(generator.throw(value));
41
- } catch (e) {
42
- reject(e);
43
- }
44
- };
45
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
46
- step((generator = generator.apply(__this, __arguments)).next());
47
- });
48
- };
49
-
50
- // src/editor.tsx
51
- import { forwardRef, useCallback, useRef, useState } from "react";
52
- import {
53
- Box,
54
- Button,
55
- Flex,
56
- Grid,
57
- Link,
58
- Separator,
59
- TextField,
60
- Typo,
61
- Link2Icon,
62
- toast,
63
- FileIcon
64
- } from "@tipp/ui";
65
- import ReactQuill from "react-quill";
66
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
67
- var Editor = forwardRef(
68
- (props, ref) => {
69
- const _a = props, {
70
- defaultAttachedFiles,
71
- defaultTitle,
72
- defaultValue,
73
- onClickSave,
74
- uploadFile,
75
- deleteFile,
76
- isLoading,
77
- SecondaryButton,
78
- clearEditor
79
- } = _a, quillProps = __objRest(_a, [
80
- "defaultAttachedFiles",
81
- "defaultTitle",
82
- "defaultValue",
83
- "onClickSave",
84
- "uploadFile",
85
- "deleteFile",
86
- "isLoading",
87
- "SecondaryButton",
88
- "clearEditor"
89
- ]);
90
- const defaultRef = useRef(null);
91
- const editorRef = ref || defaultRef;
92
- const [attachedFiles, setAttachedFiles] = useState(
93
- defaultAttachedFiles || []
94
- );
95
- const [fileDeleteLoading, setFileDeleteLoading] = useState(/* @__PURE__ */ new Set());
96
- const [title, setTitle] = useState(defaultTitle || "");
97
- const [content, setContent] = useState(defaultValue || "");
98
- console.log({ content });
99
- const handleOnChangeContent = useCallback((value) => {
100
- setContent(value);
101
- }, []);
102
- const handleButtonClick = useCallback(() => {
103
- let input = document.createElement("input");
104
- input.type = "file";
105
- input.onchange = (event) => __async(void 0, null, function* () {
106
- var _a2;
107
- const file = (_a2 = event.target.files) == null ? void 0 : _a2[0];
108
- if (!file) {
109
- toast.error("\uD30C\uC77C\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.");
110
- return;
111
- }
112
- const fileName = file.name;
113
- const attachment = yield uploadFile == null ? void 0 : uploadFile(file, `hr-notes/${fileName}`);
114
- if (attachment) {
115
- setAttachedFiles((prev) => [...prev, attachment]);
116
- }
117
- input = null;
118
- });
119
- input.click();
120
- }, [uploadFile]);
121
- const handleDeleteFile = useCallback(
122
- (fileUrl) => __async(void 0, null, function* () {
123
- try {
124
- setFileDeleteLoading((p) => p.add(fileUrl));
125
- yield deleteFile == null ? void 0 : deleteFile(fileUrl);
126
- setAttachedFiles(
127
- (currentFiles) => currentFiles.filter((item) => item.url !== fileUrl)
128
- );
129
- } catch (err) {
130
- toast.error("\uD30C\uC77C \uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
131
- } finally {
132
- setFileDeleteLoading((p) => {
133
- p.delete(fileUrl);
134
- return p;
135
- });
136
- }
137
- }),
138
- [deleteFile]
139
- );
140
- const renderAttachedFiles = useCallback(() => {
141
- return /* @__PURE__ */ jsx(Box, { width: "100%", children: attachedFiles.map((file) => {
142
- return /* @__PURE__ */ jsxs(Fragment, { children: [
143
- /* @__PURE__ */ jsx(Separator, { size: "4" }),
144
- /* @__PURE__ */ jsxs(
145
- Flex,
146
- {
147
- align: "center",
148
- justify: "between",
149
- p: "4",
150
- width: "100%",
151
- children: [
152
- /* @__PURE__ */ jsx(Link, { href: file.url, size: "2", children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "3", children: [
153
- /* @__PURE__ */ jsx(FileIcon, {}),
154
- file.fileName
155
- ] }) }),
156
- /* @__PURE__ */ jsx(
157
- Button,
158
- {
159
- loading: fileDeleteLoading.has(file.url),
160
- onClick: () => {
161
- void handleDeleteFile(file.url);
162
- },
163
- variant: "ghost",
164
- children: "\uCCA8\uBD80 \uD30C\uC77C \uC0AD\uC81C"
165
- }
166
- )
167
- ]
168
- },
169
- `${file.url}_${file.fileName}`
170
- )
171
- ] });
172
- }) });
173
- }, [attachedFiles, fileDeleteLoading, handleDeleteFile]);
174
- const handleOnChangeTitle = useCallback((e) => {
175
- setTitle(e.target.value);
176
- }, []);
177
- const clearEditorState = useCallback(() => {
178
- setContent("");
179
- setAttachedFiles([]);
180
- setTitle("");
181
- }, []);
182
- const handleSaveClick = useCallback(() => {
183
- onClickSave == null ? void 0 : onClickSave({
184
- title,
185
- content,
186
- files: attachedFiles
187
- });
188
- }, [onClickSave, title, content, attachedFiles]);
189
- if (props.clearEditor) {
190
- props.clearEditor.current = clearEditorState;
191
- }
192
- return /* @__PURE__ */ jsxs("div", { className: "tipp-ql-wrapper", children: [
193
- /* @__PURE__ */ jsxs(
194
- Grid,
195
- {
196
- align: "center",
197
- columns: "auto auto 1fr",
198
- gap: "2",
199
- height: "42px",
200
- pl: "2",
201
- pr: "3",
202
- width: "100%",
203
- children: [
204
- /* @__PURE__ */ jsx(Box, { pl: "3", pr: "3", children: /* @__PURE__ */ jsx(Typo, { children: "\uC81C\uBAA9" }) }),
205
- /* @__PURE__ */ jsx(Separator, { orientation: "vertical", style: { height: "100%" } }),
206
- /* @__PURE__ */ jsx(
207
- TextField.Root,
208
- {
209
- className: "editor-title-text-field",
210
- onChange: handleOnChangeTitle,
211
- placeholder: "\uC81C\uBAA9\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694",
212
- value: title
213
- }
214
- )
215
- ]
216
- }
217
- ),
218
- /* @__PURE__ */ jsx(
219
- ReactQuill,
220
- __spreadValues({
221
- className: "tipp-ql-editor write-mode",
222
- onChange: handleOnChangeContent,
223
- ref: editorRef,
224
- theme: "snow",
225
- value: content
226
- }, quillProps)
227
- ),
228
- renderAttachedFiles(),
229
- /* @__PURE__ */ jsx(Separator, { size: "4" }),
230
- /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "between", p: "2", pl: "4", pr: "4", width: "100%", children: [
231
- /* @__PURE__ */ jsx(
232
- Button,
233
- {
234
- color: "gray",
235
- onClick: handleButtonClick,
236
- variant: "transparent",
237
- children: /* @__PURE__ */ jsx(Link2Icon, { height: 20, width: 20 })
238
- }
239
- ),
240
- /* @__PURE__ */ jsxs(Flex, { gap: "2", children: [
241
- clearEditor ? /* @__PURE__ */ jsx(Button, { color: "gray", onClick: clearEditorState, variant: "outline", children: "\uCD08\uAE30\uD654" }) : null,
242
- SecondaryButton ? SecondaryButton : null,
243
- /* @__PURE__ */ jsx(Button, { disabled: isLoading, onClick: handleSaveClick, children: "\uC800\uC7A5" })
244
- ] })
245
- ] })
246
- ] });
247
- }
248
- );
249
- Editor.displayName = "TIPP-Quill-Editor";
250
-
251
- export {
252
- Editor
253
- };
254
- //# sourceMappingURL=chunk-FFENCIRE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/editor.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Flex,\n Grid,\n Link,\n Separator,\n TextField,\n Typo,\n Link2Icon,\n toast,\n FileIcon,\n} from '@tipp/ui';\nimport type { ReactQuillProps } from 'react-quill';\nimport ReactQuill from 'react-quill';\n\nexport interface Attachment {\n fileName: string;\n url: string;\n}\n\nexport interface TippEditorProps extends ReactQuillProps {\n defaultTitle?: string;\n defaultValue?: string;\n defaultAttachedFiles?: Attachment[];\n /** 저장하기 버튼 클릭 시 실행 */\n onClickSave?: (values: {\n title: string;\n content: string;\n files: Attachment[];\n }) => void;\n /** 파일 업로드 버튼 클릭 시 실행 */\n uploadFile?: (\n file: File,\n destination: string\n ) => Promise<Attachment | undefined>;\n deleteFile?: (fileUrl: string) => Promise<void>;\n /** 외부에서 Editor를 빈 상태로 초기화 시켜야 할 때 사용 */\n clearEditor?: React.MutableRefObject<(() => void) | undefined>;\n /** 초기화 버튼말고 다른 버튼 추가시 */\n SecondaryButton?: React.ReactNode;\n /** true인 경우 저장하기 버튼이 비활성 화 됨. 연타 방지 */\n isLoading?: boolean;\n}\n\nexport const Editor = forwardRef<ReactQuill, TippEditorProps>(\n (props, ref): React.ReactNode => {\n const {\n defaultAttachedFiles,\n defaultTitle,\n defaultValue,\n onClickSave,\n uploadFile,\n deleteFile,\n isLoading,\n SecondaryButton,\n clearEditor,\n ...quillProps\n } = props;\n const defaultRef = useRef<ReactQuill>(null);\n const editorRef = ref || defaultRef;\n const [attachedFiles, setAttachedFiles] = useState<Attachment[]>(\n defaultAttachedFiles || []\n );\n const [fileDeleteLoading, setFileDeleteLoading] = useState(new Set());\n\n const [title, setTitle] = useState(defaultTitle || '');\n const [content, setContent] = useState(defaultValue || '');\n\n console.log({ content });\n const handleOnChangeContent = useCallback((value: string) => {\n setContent(value);\n }, []);\n\n const handleButtonClick = useCallback(() => {\n let input: HTMLInputElement | null = document.createElement('input');\n input.type = 'file';\n input.onchange = async (event) => {\n const file = (event.target as HTMLInputElement).files?.[0];\n if (!file) {\n // console.log('DEBUG: no file');\n toast.error('파일을 선택해주세요.');\n return;\n }\n\n const fileName = file.name;\n const attachment = await uploadFile?.(file, `hr-notes/${fileName}`);\n if (attachment) {\n setAttachedFiles((prev) => [...prev, attachment]);\n }\n input = null;\n };\n input.click();\n }, [uploadFile]);\n\n const handleDeleteFile = useCallback(\n async (fileUrl: string) => {\n try {\n setFileDeleteLoading((p) => p.add(fileUrl));\n await deleteFile?.(fileUrl);\n setAttachedFiles((currentFiles) =>\n currentFiles.filter((item) => item.url !== fileUrl)\n );\n } catch (err) {\n toast.error('파일 삭제에 실패했습니다.');\n } finally {\n setFileDeleteLoading((p) => {\n p.delete(fileUrl);\n return p;\n });\n }\n },\n [deleteFile]\n );\n\n const renderAttachedFiles = useCallback(() => {\n return (\n <Box width=\"100%\">\n {attachedFiles.map((file) => {\n return (\n <>\n <Separator size=\"4\" />\n <Flex\n align=\"center\"\n justify=\"between\"\n key={`${file.url}_${file.fileName}`}\n p=\"4\"\n width=\"100%\"\n >\n <Link href={file.url} size=\"2\">\n <Flex align=\"center\" gap=\"3\">\n <FileIcon />\n {file.fileName}\n </Flex>\n </Link>\n <Button\n loading={fileDeleteLoading.has(file.url)}\n onClick={() => {\n void handleDeleteFile(file.url);\n }}\n variant=\"ghost\"\n >\n 첨부 파일 삭제\n </Button>\n </Flex>\n </>\n );\n })}\n </Box>\n );\n }, [attachedFiles, fileDeleteLoading, handleDeleteFile]);\n\n const handleOnChangeTitle = useCallback<\n React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>\n >((e) => {\n setTitle(e.target.value);\n }, []);\n\n const clearEditorState = useCallback(() => {\n setContent('');\n setAttachedFiles([]);\n setTitle('');\n }, []);\n\n const handleSaveClick = useCallback(() => {\n onClickSave?.({\n title,\n content,\n files: attachedFiles,\n });\n }, [onClickSave, title, content, attachedFiles]);\n\n if (props.clearEditor) {\n props.clearEditor.current = clearEditorState;\n }\n\n return (\n <div className=\"tipp-ql-wrapper\">\n {/* 제목 입력창 */}\n <Grid\n align=\"center\"\n columns=\"auto auto 1fr\"\n gap=\"2\"\n height=\"42px\"\n pl=\"2\"\n pr=\"3\"\n width=\"100%\"\n >\n <Box pl=\"3\" pr=\"3\">\n <Typo>제목</Typo>\n </Box>\n <Separator orientation=\"vertical\" style={{ height: '100%' }} />\n <TextField.Root\n className=\"editor-title-text-field\"\n onChange={handleOnChangeTitle}\n placeholder=\"제목을 입력해주세요\"\n value={title}\n />\n </Grid>\n <ReactQuill\n className=\"tipp-ql-editor write-mode\"\n onChange={handleOnChangeContent}\n ref={editorRef}\n theme=\"snow\"\n value={content}\n {...quillProps}\n />\n {renderAttachedFiles()}\n <Separator size=\"4\" />\n <Flex align=\"center\" justify=\"between\" p=\"2\" pl=\"4\" pr=\"4\" width=\"100%\">\n <Button\n color=\"gray\"\n onClick={handleButtonClick}\n variant=\"transparent\"\n >\n <Link2Icon height={20} width={20} />\n </Button>\n\n <Flex gap=\"2\">\n {clearEditor ? (\n <Button color=\"gray\" onClick={clearEditorState} variant=\"outline\">\n 초기화\n </Button>\n ) : null}\n {SecondaryButton ? SecondaryButton : null}\n <Button disabled={isLoading} onClick={handleSaveClick}>\n 저장\n </Button>\n </Flex>\n </Flex>\n </div>\n );\n }\n);\n\nEditor.displayName = 'TIPP-Quill-Editor';\n"],"mappings":"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","names":["_a"]}
@@ -1,253 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
- var __hasOwnProp = Object.prototype.hasOwnProperty;
4
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __spreadValues = (a, b) => {
7
- for (var prop in b || (b = {}))
8
- if (__hasOwnProp.call(b, prop))
9
- __defNormalProp(a, prop, b[prop]);
10
- if (__getOwnPropSymbols)
11
- for (var prop of __getOwnPropSymbols(b)) {
12
- if (__propIsEnum.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- }
15
- return a;
16
- };
17
- var __objRest = (source, exclude) => {
18
- var target = {};
19
- for (var prop in source)
20
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
21
- target[prop] = source[prop];
22
- if (source != null && __getOwnPropSymbols)
23
- for (var prop of __getOwnPropSymbols(source)) {
24
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
25
- target[prop] = source[prop];
26
- }
27
- return target;
28
- };
29
- var __async = (__this, __arguments, generator) => {
30
- return new Promise((resolve, reject) => {
31
- var fulfilled = (value) => {
32
- try {
33
- step(generator.next(value));
34
- } catch (e) {
35
- reject(e);
36
- }
37
- };
38
- var rejected = (value) => {
39
- try {
40
- step(generator.throw(value));
41
- } catch (e) {
42
- reject(e);
43
- }
44
- };
45
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
46
- step((generator = generator.apply(__this, __arguments)).next());
47
- });
48
- };
49
-
50
- // src/editor.tsx
51
- import { forwardRef, useCallback, useRef, useState } from "react";
52
- import {
53
- Box,
54
- Button,
55
- Flex,
56
- Grid,
57
- Link,
58
- Separator,
59
- TextField,
60
- Typo,
61
- Link2Icon,
62
- toast,
63
- FileIcon
64
- } from "@tipp/ui";
65
- import ReactQuill from "react-quill";
66
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
67
- var Editor = forwardRef(
68
- (props, ref) => {
69
- const _a = props, {
70
- defaultAttachedFiles,
71
- defaultTitle,
72
- defaultValue,
73
- onClickSave,
74
- uploadFile,
75
- deleteFile,
76
- isLoading,
77
- SecondaryButton,
78
- clearEditor
79
- } = _a, quillProps = __objRest(_a, [
80
- "defaultAttachedFiles",
81
- "defaultTitle",
82
- "defaultValue",
83
- "onClickSave",
84
- "uploadFile",
85
- "deleteFile",
86
- "isLoading",
87
- "SecondaryButton",
88
- "clearEditor"
89
- ]);
90
- const defaultRef = useRef(null);
91
- const editorRef = ref || defaultRef;
92
- const [attachedFiles, setAttachedFiles] = useState(
93
- defaultAttachedFiles || []
94
- );
95
- const [title, setTitle] = useState(defaultTitle || "");
96
- const [content, setContent] = useState(defaultValue || "");
97
- const handleOnChangeContent = useCallback((value) => {
98
- setContent(value);
99
- }, []);
100
- const handleButtonClick = useCallback(() => {
101
- let input = document.createElement("input");
102
- input.type = "file";
103
- input.onchange = (event) => __async(void 0, null, function* () {
104
- var _a2;
105
- const file = (_a2 = event.target.files) == null ? void 0 : _a2[0];
106
- if (!file) {
107
- toast.error("\uD30C\uC77C\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.");
108
- return;
109
- }
110
- const fileName = file.name;
111
- const attachment = yield uploadFile == null ? void 0 : uploadFile(file, `hr-notes/${fileName}`);
112
- if (attachment) {
113
- setAttachedFiles((prev) => [...prev, attachment]);
114
- }
115
- input = null;
116
- });
117
- input.click();
118
- }, [uploadFile]);
119
- const [fileDeleteLoading, setFileDeleteLoading] = useState(/* @__PURE__ */ new Set());
120
- const handleDeleteFile = useCallback(
121
- (fileUrl) => __async(void 0, null, function* () {
122
- try {
123
- setFileDeleteLoading((p) => p.add(fileUrl));
124
- yield deleteFile == null ? void 0 : deleteFile(fileUrl);
125
- setAttachedFiles(
126
- (currentFiles) => currentFiles.filter((item) => item.url !== fileUrl)
127
- );
128
- } catch (err) {
129
- toast.error("\uD30C\uC77C \uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
130
- } finally {
131
- setFileDeleteLoading((p) => {
132
- p.delete(fileUrl);
133
- return p;
134
- });
135
- }
136
- }),
137
- [deleteFile]
138
- );
139
- const renderAttachedFiles = useCallback(() => {
140
- return /* @__PURE__ */ jsx(Box, { width: "100%", children: attachedFiles == null ? void 0 : attachedFiles.map((file) => {
141
- return /* @__PURE__ */ jsxs(Fragment, { children: [
142
- /* @__PURE__ */ jsx(Separator, { size: "4" }),
143
- /* @__PURE__ */ jsxs(
144
- Flex,
145
- {
146
- align: "center",
147
- justify: "between",
148
- p: "4",
149
- width: "100%",
150
- children: [
151
- /* @__PURE__ */ jsx(Link, { href: file.url, size: "2", children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "3", children: [
152
- /* @__PURE__ */ jsx(FileIcon, {}),
153
- file.fileName
154
- ] }) }),
155
- /* @__PURE__ */ jsx(
156
- Button,
157
- {
158
- loading: fileDeleteLoading.has(file.url),
159
- onClick: () => {
160
- void handleDeleteFile(file.url);
161
- },
162
- variant: "ghost",
163
- children: "\uCCA8\uBD80 \uD30C\uC77C \uC0AD\uC81C"
164
- }
165
- )
166
- ]
167
- },
168
- `${file.url}_${file.fileName}`
169
- )
170
- ] });
171
- }) });
172
- }, [attachedFiles, fileDeleteLoading, handleDeleteFile]);
173
- const handleOnChangeTitle = useCallback((e) => {
174
- setTitle(e.target.value);
175
- }, []);
176
- const clearEditorState = useCallback(() => {
177
- setContent("");
178
- setAttachedFiles([]);
179
- setTitle("");
180
- }, []);
181
- const handleSaveClick = useCallback(() => {
182
- onClickSave == null ? void 0 : onClickSave({
183
- title,
184
- content,
185
- files: attachedFiles
186
- });
187
- }, [onClickSave, title, content, attachedFiles]);
188
- if (props.clearEditor) {
189
- props.clearEditor.current = clearEditorState;
190
- }
191
- return /* @__PURE__ */ jsxs("div", { className: "tipp-ql-wrapper", children: [
192
- /* @__PURE__ */ jsxs(
193
- Grid,
194
- {
195
- align: "center",
196
- columns: "auto 1fr auto auto",
197
- gap: "2",
198
- height: "42px",
199
- pl: "2",
200
- pr: "3",
201
- width: "100%",
202
- children: [
203
- /* @__PURE__ */ jsx(Box, { pl: "3", pr: "3", children: /* @__PURE__ */ jsx(Typo, { children: "\uC81C\uBAA9" }) }),
204
- /* @__PURE__ */ jsx(Separator, { orientation: "vertical", style: { height: "100%" } }),
205
- /* @__PURE__ */ jsx(
206
- TextField.Root,
207
- {
208
- className: "editor-title-text-field",
209
- onChange: handleOnChangeTitle,
210
- placeholder: "\uC81C\uBAA9\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694",
211
- value: title
212
- }
213
- )
214
- ]
215
- }
216
- ),
217
- /* @__PURE__ */ jsx(
218
- ReactQuill,
219
- __spreadValues({
220
- className: "tipp-ql-editor write-mode",
221
- onChange: handleOnChangeContent,
222
- ref: editorRef,
223
- theme: "snow",
224
- value: content
225
- }, quillProps)
226
- ),
227
- renderAttachedFiles(),
228
- /* @__PURE__ */ jsx(Separator, { size: "4" }),
229
- /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "between", p: "2", pl: "4", pr: "4", width: "100%", children: [
230
- /* @__PURE__ */ jsx(
231
- Button,
232
- {
233
- color: "gray",
234
- onClick: handleButtonClick,
235
- variant: "transparent",
236
- children: /* @__PURE__ */ jsx(Link2Icon, { height: 20, width: 20 })
237
- }
238
- ),
239
- /* @__PURE__ */ jsxs(Flex, { gap: "2", children: [
240
- clearEditor ? /* @__PURE__ */ jsx(Button, { color: "gray", onClick: clearEditorState, variant: "outline", children: "\uCD08\uAE30\uD654" }) : null,
241
- SecondaryButton ? SecondaryButton : null,
242
- /* @__PURE__ */ jsx(Button, { disabled: isLoading, onClick: handleSaveClick, children: "\uC800\uC7A5" })
243
- ] })
244
- ] })
245
- ] });
246
- }
247
- );
248
- Editor.displayName = "TIPP-Quill-Editor";
249
-
250
- export {
251
- Editor
252
- };
253
- //# sourceMappingURL=chunk-HZN6OVD6.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/editor.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Flex,\n Grid,\n Link,\n Separator,\n TextField,\n Typo,\n Link2Icon,\n toast,\n FileIcon,\n} from '@tipp/ui';\nimport type { ReactQuillProps } from 'react-quill';\nimport ReactQuill from 'react-quill';\n\ninterface Attachment {\n fileName: string;\n url: string;\n}\n\nexport interface TippEditorProps extends ReactQuillProps {\n defaultTitle?: string;\n defaultValue?: string;\n defaultAttachedFiles?: Attachment[];\n /** 저장하기 버튼 클릭 시 실행 */\n onClickSave?: (values: {\n title: string;\n content: string;\n files: Attachment[];\n }) => void;\n /** 파일 업로드 버튼 클릭 시 실행 */\n uploadFile?: (\n file: File,\n destination: string\n ) => Promise<Attachment | undefined>;\n deleteFile?: (fileUrl: string) => Promise<void>;\n /** 외부에서 Editor를 빈 상태로 초기화 시켜야 할 때 사용 */\n clearEditor?: React.MutableRefObject<(() => void) | undefined>;\n /** 초기화 버튼말고 다른 버튼 추가시 */\n SecondaryButton?: React.ReactNode;\n /** true인 경우 저장하기 버튼이 비활성 화 됨. 연타 방지 */\n isLoading?: boolean;\n}\n\nexport const Editor = forwardRef<ReactQuill, TippEditorProps>(\n (props, ref): React.ReactNode => {\n const {\n defaultAttachedFiles,\n defaultTitle,\n defaultValue,\n onClickSave,\n uploadFile,\n deleteFile,\n isLoading,\n SecondaryButton,\n clearEditor,\n ...quillProps\n } = props;\n const defaultRef = useRef<ReactQuill>(null);\n const editorRef = ref || defaultRef;\n const [attachedFiles, setAttachedFiles] = useState<Attachment[]>(\n defaultAttachedFiles || []\n );\n\n const [title, setTitle] = useState(defaultTitle || '');\n const [content, setContent] = useState(defaultValue || '');\n\n const handleOnChangeContent = useCallback((value: string) => {\n setContent(value);\n }, []);\n\n const handleButtonClick = useCallback(() => {\n let input: HTMLInputElement | null = document.createElement('input');\n input.type = 'file';\n input.onchange = async (event) => {\n const file = (event.target as HTMLInputElement).files?.[0];\n if (!file) {\n // console.log('DEBUG: no file');\n toast.error('파일을 선택해주세요.');\n return;\n }\n\n const fileName = file.name;\n const attachment = await uploadFile?.(file, `hr-notes/${fileName}`);\n if (attachment) {\n setAttachedFiles((prev) => [...prev, attachment]);\n }\n input = null;\n };\n input.click();\n }, [uploadFile]);\n\n const [fileDeleteLoading, setFileDeleteLoading] = useState(new Set());\n\n const handleDeleteFile = useCallback(\n async (fileUrl: string) => {\n try {\n setFileDeleteLoading((p) => p.add(fileUrl));\n await deleteFile?.(fileUrl);\n setAttachedFiles((currentFiles) =>\n currentFiles.filter((item) => item.url !== fileUrl)\n );\n } catch (err) {\n // console.log(`DEBUG: error is ${err}`);\n toast.error('파일 삭제에 실패했습니다.');\n } finally {\n setFileDeleteLoading((p) => {\n p.delete(fileUrl);\n return p;\n });\n }\n },\n [deleteFile]\n );\n\n const renderAttachedFiles = useCallback(() => {\n return (\n <Box width=\"100%\">\n {attachedFiles?.map((file) => {\n return (\n <>\n <Separator size=\"4\" />\n <Flex\n align=\"center\"\n justify=\"between\"\n key={`${file.url}_${file.fileName}`}\n p=\"4\"\n width=\"100%\"\n >\n <Link href={file.url} size=\"2\">\n <Flex align=\"center\" gap=\"3\">\n <FileIcon />\n {file.fileName}\n </Flex>\n </Link>\n <Button\n loading={fileDeleteLoading.has(file.url)}\n onClick={() => {\n void handleDeleteFile(file.url);\n }}\n variant=\"ghost\"\n >\n 첨부 파일 삭제\n </Button>\n </Flex>\n </>\n );\n })}\n </Box>\n );\n }, [attachedFiles, fileDeleteLoading, handleDeleteFile]);\n\n const handleOnChangeTitle = useCallback<\n React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>\n >((e) => {\n setTitle(e.target.value);\n }, []);\n\n const clearEditorState = useCallback(() => {\n setContent('');\n setAttachedFiles([]);\n setTitle('');\n }, []);\n\n const handleSaveClick = useCallback(() => {\n onClickSave?.({\n title,\n content,\n files: attachedFiles,\n });\n }, [onClickSave, title, content, attachedFiles]);\n\n if (props.clearEditor) {\n props.clearEditor.current = clearEditorState;\n }\n\n return (\n <div className=\"tipp-ql-wrapper\">\n <Grid\n align=\"center\"\n columns=\"auto 1fr auto auto\"\n gap=\"2\"\n height=\"42px\"\n pl=\"2\"\n pr=\"3\"\n width=\"100%\"\n >\n <Box pl=\"3\" pr=\"3\">\n <Typo>제목</Typo>\n </Box>\n <Separator orientation=\"vertical\" style={{ height: '100%' }} />\n <TextField.Root\n className=\"editor-title-text-field\"\n onChange={handleOnChangeTitle}\n placeholder=\"제목을 입력해주세요\"\n value={title}\n />\n </Grid>\n <ReactQuill\n className=\"tipp-ql-editor write-mode\"\n onChange={handleOnChangeContent}\n ref={editorRef}\n theme=\"snow\"\n value={content}\n {...quillProps}\n />\n {renderAttachedFiles()}\n <Separator size=\"4\" />\n <Flex align=\"center\" justify=\"between\" p=\"2\" pl=\"4\" pr=\"4\" width=\"100%\">\n <Button\n color=\"gray\"\n onClick={handleButtonClick}\n variant=\"transparent\"\n >\n <Link2Icon height={20} width={20} />\n </Button>\n\n <Flex gap=\"2\">\n {clearEditor ? (\n <Button color=\"gray\" onClick={clearEditorState} variant=\"outline\">\n 초기화\n </Button>\n ) : null}\n {SecondaryButton ? SecondaryButton : null}\n <Button disabled={isLoading} onClick={handleSaveClick}>\n 저장\n </Button>\n </Flex>\n </Flex>\n </div>\n );\n }\n);\n\nEditor.displayName = 'TIPP-Quill-Editor';\n"],"mappings":"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","names":["_a"]}