@tipp/ui-quill-editor 1.4.47 → 2.0.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.
- package/dist/{chunk-B2YNOJG7.js → chunk-6W7GMBAM.js} +1 -1
- package/dist/chunk-6W7GMBAM.js.map +1 -0
- package/dist/{chunk-AYPEDHDL.js → chunk-WH3MP2R3.js} +1 -1
- package/dist/editor.cjs +4 -4
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.d.cts +2 -2
- package/dist/editor.d.ts +2 -2
- package/dist/editor.js +4 -4
- package/dist/editor.js.map +1 -1
- package/dist/html-container.cjs.map +1 -1
- package/dist/html-container.js +2 -2
- package/dist/index.css +580 -599
- package/dist/index.css.map +1 -0
- package/dist/read-card.cjs +1 -2
- package/dist/read-card.cjs.map +1 -1
- package/dist/read-card.d.cts +1 -1
- package/dist/read-card.d.ts +1 -1
- package/dist/read-card.js +3 -4
- package/dist/read-card.js.map +1 -1
- package/package.json +8 -8
- package/src/editor.tsx +3 -4
- package/src/html-container.tsx +1 -1
- package/src/read-card.tsx +1 -1
- package/dist/chunk-B2YNOJG7.js.map +0 -1
- /package/dist/{chunk-AYPEDHDL.js.map → chunk-WH3MP2R3.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/html-container.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\n\ninterface QuillHtmlOutputContainerProps {\n html: string;\n className?: string;\n}\n\nconst QuillHtmlOutputContainer = forwardRef<\n HTMLDivElement,\n QuillHtmlOutputContainerProps\n>(({ html, className }, ref): React.ReactNode => {\n return (\n <div className=\"ql-snow ql-container read-mode\">\n <div\n className={`ql-editor ${className || ''}`}\n dangerouslySetInnerHTML={{ __html: html }}\n ref={ref}\n />\n </div>\n );\n});\n\nQuillHtmlOutputContainer.displayName = 'QuillHtmlOutputContainer';\n\nexport default QuillHtmlOutputContainer;\n"],"mappings":";AAAA,SAAgB,kBAAkB;AAa5B;AANN,IAAM,2BAA2B,WAG/B,CAAC,EAAE,MAAM,UAAU,GAAG,QAAyB;AAC/C,SACE,oBAAC,SAAI,WAAU,kCACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,aAAa,aAAa,EAAE;AAAA,MACvC,yBAAyB,EAAE,QAAQ,KAAK;AAAA,MACxC;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;AAED,yBAAyB,cAAc;AAEvC,IAAO,yBAAQ;","names":[]}
|
package/dist/editor.cjs
CHANGED
|
@@ -81,7 +81,7 @@ __export(editor_exports, {
|
|
|
81
81
|
module.exports = __toCommonJS(editor_exports);
|
|
82
82
|
var import_react = require("react");
|
|
83
83
|
var import_ui = require("@tipp/ui");
|
|
84
|
-
var
|
|
84
|
+
var import_react_quill_new = __toESM(require("react-quill-new"), 1);
|
|
85
85
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
86
86
|
var Editor = (0, import_react.forwardRef)(
|
|
87
87
|
(props, ref) => {
|
|
@@ -126,7 +126,7 @@ var Editor = (0, import_react.forwardRef)(
|
|
|
126
126
|
const handleButtonClick = (0, import_react.useCallback)(() => {
|
|
127
127
|
let input = document.createElement("input");
|
|
128
128
|
input.type = "file";
|
|
129
|
-
input.onchange = (event) => __async(
|
|
129
|
+
input.onchange = (event) => __async(null, null, function* () {
|
|
130
130
|
var _a2;
|
|
131
131
|
const file = (_a2 = event.target.files) == null ? void 0 : _a2[0];
|
|
132
132
|
if (!file) {
|
|
@@ -143,7 +143,7 @@ var Editor = (0, import_react.forwardRef)(
|
|
|
143
143
|
input.click();
|
|
144
144
|
}, [uploadFile]);
|
|
145
145
|
const handleDeleteFile = (0, import_react.useCallback)(
|
|
146
|
-
(fileUrl) => __async(
|
|
146
|
+
(fileUrl) => __async(null, null, function* () {
|
|
147
147
|
try {
|
|
148
148
|
setFileDeleteLoading((p) => p.add(fileUrl));
|
|
149
149
|
yield deleteFile == null ? void 0 : deleteFile(fileUrl);
|
|
@@ -250,7 +250,7 @@ var Editor = (0, import_react.forwardRef)(
|
|
|
250
250
|
}
|
|
251
251
|
),
|
|
252
252
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
253
|
-
|
|
253
|
+
import_react_quill_new.default,
|
|
254
254
|
__spreadValues({
|
|
255
255
|
className: "tipp-ql-editor write-mode",
|
|
256
256
|
onChange: handleOnChangeContent,
|
package/dist/editor.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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';\nimport type { Attachment } from './type';\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 minHeight?: string;\n maxHeight?: string;\n height?: string;\n}\n\nexport const Editor = forwardRef<ReactQuill, TippEditorProps>(\n (props, ref): React.ReactElement => {\n const {\n defaultAttachedFiles,\n defaultTitle,\n defaultValue,\n onClickSave,\n uploadFile,\n deleteFile,\n isLoading,\n SecondaryButton,\n clearEditor,\n minHeight,\n maxHeight,\n height,\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 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 const cssVariables = {\n '--max-height': maxHeight,\n '--min-height': minHeight,\n '--height': height || '100%',\n } as React.CSSProperties;\n\n return (\n <div\n className=\"tipp-ql-wrapper\"\n style={{\n ...cssVariables,\n }}\n >\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","ReactQuill"]}
|
|
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 ReactQuill from 'react-quill-new';\nimport type { Attachment } from './type';\n\nexport interface TippEditorProps extends ReactQuill.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 minHeight?: string;\n maxHeight?: string;\n height?: string;\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 minHeight,\n maxHeight,\n height,\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 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 const cssVariables = {\n '--max-height': maxHeight,\n '--min-height': minHeight,\n '--height': height || '100%',\n } as React.CSSProperties;\n\n return (\n <div\n className=\"tipp-ql-wrapper\"\n style={{\n ...cssVariables,\n }}\n >\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","ReactQuill"]}
|
package/dist/editor.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import ReactQuill
|
|
2
|
+
import ReactQuill from 'react-quill-new';
|
|
3
3
|
import { Attachment } from './type.cjs';
|
|
4
4
|
|
|
5
|
-
interface TippEditorProps extends ReactQuillProps {
|
|
5
|
+
interface TippEditorProps extends ReactQuill.ReactQuillProps {
|
|
6
6
|
defaultTitle?: string;
|
|
7
7
|
defaultValue?: string;
|
|
8
8
|
defaultAttachedFiles?: Attachment[];
|
package/dist/editor.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import ReactQuill
|
|
2
|
+
import ReactQuill from 'react-quill-new';
|
|
3
3
|
import { Attachment } from './type.js';
|
|
4
4
|
|
|
5
|
-
interface TippEditorProps extends ReactQuillProps {
|
|
5
|
+
interface TippEditorProps extends ReactQuill.ReactQuillProps {
|
|
6
6
|
defaultTitle?: string;
|
|
7
7
|
defaultValue?: string;
|
|
8
8
|
defaultAttachedFiles?: Attachment[];
|
package/dist/editor.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
__async,
|
|
3
3
|
__objRest,
|
|
4
4
|
__spreadValues
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WH3MP2R3.js";
|
|
6
6
|
|
|
7
7
|
// src/editor.tsx
|
|
8
8
|
import { forwardRef, useCallback, useRef, useState } from "react";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
toast,
|
|
20
20
|
FileIcon
|
|
21
21
|
} from "@tipp/ui";
|
|
22
|
-
import ReactQuill from "react-quill";
|
|
22
|
+
import ReactQuill from "react-quill-new";
|
|
23
23
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
24
24
|
var Editor = forwardRef(
|
|
25
25
|
(props, ref) => {
|
|
@@ -64,7 +64,7 @@ var Editor = forwardRef(
|
|
|
64
64
|
const handleButtonClick = useCallback(() => {
|
|
65
65
|
let input = document.createElement("input");
|
|
66
66
|
input.type = "file";
|
|
67
|
-
input.onchange = (event) => __async(
|
|
67
|
+
input.onchange = (event) => __async(null, null, function* () {
|
|
68
68
|
var _a2;
|
|
69
69
|
const file = (_a2 = event.target.files) == null ? void 0 : _a2[0];
|
|
70
70
|
if (!file) {
|
|
@@ -81,7 +81,7 @@ var Editor = forwardRef(
|
|
|
81
81
|
input.click();
|
|
82
82
|
}, [uploadFile]);
|
|
83
83
|
const handleDeleteFile = useCallback(
|
|
84
|
-
(fileUrl) => __async(
|
|
84
|
+
(fileUrl) => __async(null, null, function* () {
|
|
85
85
|
try {
|
|
86
86
|
setFileDeleteLoading((p) => p.add(fileUrl));
|
|
87
87
|
yield deleteFile == null ? void 0 : deleteFile(fileUrl);
|
package/dist/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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';\nimport type { Attachment } from './type';\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 minHeight?: string;\n maxHeight?: string;\n height?: string;\n}\n\nexport const Editor = forwardRef<ReactQuill, TippEditorProps>(\n (props, ref): React.ReactElement => {\n const {\n defaultAttachedFiles,\n defaultTitle,\n defaultValue,\n onClickSave,\n uploadFile,\n deleteFile,\n isLoading,\n SecondaryButton,\n clearEditor,\n minHeight,\n maxHeight,\n height,\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 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 const cssVariables = {\n '--max-height': maxHeight,\n '--min-height': minHeight,\n '--height': height || '100%',\n } as React.CSSProperties;\n\n return (\n <div\n className=\"tipp-ql-wrapper\"\n style={{\n ...cssVariables,\n }}\n >\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
|
+
{"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 ReactQuill from 'react-quill-new';\nimport type { Attachment } from './type';\n\nexport interface TippEditorProps extends ReactQuill.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 minHeight?: string;\n maxHeight?: string;\n height?: string;\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 minHeight,\n maxHeight,\n height,\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 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 const cssVariables = {\n '--max-height': maxHeight,\n '--min-height': minHeight,\n '--height': height || '100%',\n } as React.CSSProperties;\n\n return (\n <div\n className=\"tipp-ql-wrapper\"\n style={{\n ...cssVariables,\n }}\n >\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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/html-container.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\n\ninterface QuillHtmlOutputContainerProps {\n html: string;\n className?: string;\n}\n\nconst QuillHtmlOutputContainer = forwardRef<\n HTMLDivElement,\n QuillHtmlOutputContainerProps\n>(({ html, className }, ref): React.
|
|
1
|
+
{"version":3,"sources":["../src/html-container.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\n\ninterface QuillHtmlOutputContainerProps {\n html: string;\n className?: string;\n}\n\nconst QuillHtmlOutputContainer = forwardRef<\n HTMLDivElement,\n QuillHtmlOutputContainerProps\n>(({ html, className }, ref): React.ReactNode => {\n return (\n <div className=\"ql-snow ql-container read-mode\">\n <div\n className={`ql-editor ${className || ''}`}\n dangerouslySetInnerHTML={{ __html: html }}\n ref={ref}\n />\n </div>\n );\n});\n\nQuillHtmlOutputContainer.displayName = 'QuillHtmlOutputContainer';\n\nexport default QuillHtmlOutputContainer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkC;AAa5B;AANN,IAAM,+BAA2B,yBAG/B,CAAC,EAAE,MAAM,UAAU,GAAG,QAAyB;AAC/C,SACE,4CAAC,SAAI,WAAU,kCACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,aAAa,aAAa,EAAE;AAAA,MACvC,yBAAyB,EAAE,QAAQ,KAAK;AAAA,MACxC;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;AAED,yBAAyB,cAAc;AAEvC,IAAO,yBAAQ;","names":[]}
|