@zjlab-fe/data-hub-ui 0.21.6 → 0.22.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 (226) hide show
  1. package/dist/types/components/tip-tap/extensions/index.d.ts +1 -1
  2. package/es/assets/cardImg.png.js +3 -0
  3. package/es/assets/closeBtn.png.js +3 -0
  4. package/es/assets/icon-tag-header.png.js +3 -0
  5. package/es/assets/source.png.js +3 -0
  6. package/es/components/FileUploader/FileUploadModal.js +24 -0
  7. package/es/components/FileUploader/FileUploader.js +20 -0
  8. package/es/components/FileUploader/FileUploaderImpl/FileUploader.js +34 -0
  9. package/es/components/FileUploader/FileUploaderImpl/FileUploaderContextProvider.js +46 -0
  10. package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiver.css.js +36 -0
  11. package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiver.js +57 -0
  12. package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiverContainer.js +24 -0
  13. package/es/components/FileUploader/FileUploaderImpl/FileUploaderFileReceiverDesc.js +9 -0
  14. package/es/components/FileUploader/FileUploaderImpl/FileUploaderList.js +46 -0
  15. package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItem.js +46 -0
  16. package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemFail.js +21 -0
  17. package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemPaused.js +20 -0
  18. package/es/components/FileUploader/FileUploaderImpl/FileUploaderListItemUploading.js +43 -0
  19. package/es/components/FileUploader/FileUploaderImpl/FileUploaderlListItemFinished.js +32 -0
  20. package/es/components/FileUploader/Locale/translations.js +52 -0
  21. package/es/components/FileUploader/Locale/useTranslate.js +16 -0
  22. package/es/components/FileUploader/UploadStoreProvider/UploadStoreProvider.js +31 -0
  23. package/es/components/FileUploader/UploadStoreProvider/uploadStoreReducer.js +62 -0
  24. package/es/components/FileUploader/UploadStoreProvider/useOnFileAllUploaded.js +31 -0
  25. package/es/components/FileUploader/UploadStoreProvider/useSaveUnfinishedUploads.js +42 -0
  26. package/es/components/FileUploader/UploadStoreProvider/useSetupMergingEvent.js +45 -0
  27. package/es/components/FileUploader/hooks/useCancelUpload.js +40 -0
  28. package/es/components/FileUploader/hooks/useCurrentFile.js +61 -0
  29. package/es/components/FileUploader/hooks/useCurrentFileOnUploading.js +52 -0
  30. package/es/components/FileUploader/hooks/useCurrentFileSetupAndBackUp.js +39 -0
  31. package/es/components/FileUploader/hooks/useFormatFiles.js +64 -0
  32. package/es/components/FileUploader/hooks/useFormatFilesFindDuplicates.js +75 -0
  33. package/es/components/FileUploader/hooks/useFormatFilesRemoveDuplicates.js +21 -0
  34. package/es/components/FileUploader/hooks/useHandleChunkCompletion.js +31 -0
  35. package/es/components/FileUploader/hooks/useOnMounted.js +24 -0
  36. package/es/components/FileUploader/hooks/useOnMountedResumeUnfinished.js +58 -0
  37. package/es/components/FileUploader/hooks/useRetryUpload.js +33 -0
  38. package/es/components/FileUploader/hooks/useUploadChunk.js +46 -0
  39. package/es/components/FileUploader/icons/CloseFilled.js +7 -0
  40. package/es/components/FileUploader/icons/UnkownFileIcon.js +7 -0
  41. package/es/components/FileUploader/icons/UploadIcon.js +7 -0
  42. package/es/components/FileUploader/index.css.js +532 -0
  43. package/es/components/FileUploader/index.js +23 -0
  44. package/es/components/FileUploader/types.js +13 -0
  45. package/es/components/FileUploader/utils/calcDisplaySize.js +20 -0
  46. package/es/components/FileUploader/utils/checkExpiryTime.js +15 -0
  47. package/es/components/FileUploader/utils/createFileToUpload.js +60 -0
  48. package/es/components/FileUploader/utils/fileDB/addFilesToIndexdb.js +14 -0
  49. package/es/components/FileUploader/utils/fileDB/deleteFileInStore.js +18 -0
  50. package/es/components/FileUploader/utils/fileDB/deleteObjectStore.js +25 -0
  51. package/es/components/FileUploader/utils/fileDB/index.js +77 -0
  52. package/es/components/FileUploader/utils/fileDB/openDBAndRetrieveData.js +90 -0
  53. package/es/components/FileUploader/utils/fileDB/retrieveExistingData.js +49 -0
  54. package/es/components/FileUploader/utils/modalConfig.css.js +20 -0
  55. package/es/components/FileUploader/utils/modalConfig.js +32 -0
  56. package/es/components/FileUploader/utils/retrieveAllFiles.js +70 -0
  57. package/es/components/FileUploader/utils/splitFileIntoChunk.js +15 -0
  58. package/es/components/SDK-modal/document-link.js +8 -0
  59. package/es/components/SDK-modal/index.js +25 -0
  60. package/es/components/SDK-modal/index.module.scss.js +49 -0
  61. package/es/components/SDK-modal/inner-modal.js +59 -0
  62. package/es/components/SDK-modal/locale/translations.js +17 -0
  63. package/es/components/apply-perm-modal/index.js +53 -0
  64. package/es/components/apply-perm-modal/index.module.scss.js +96 -0
  65. package/es/components/auth-tag/index.js +23 -0
  66. package/es/components/bench-card/index.js +20 -0
  67. package/es/components/bench-card/index.module.scss.js +48 -0
  68. package/es/components/confirm-again/index.js +15 -0
  69. package/es/components/confirm-again/index.scss.js +37 -0
  70. package/es/components/copy/index.js +41 -0
  71. package/es/components/copy/index.module.scss.js +15 -0
  72. package/es/components/corpus-card/index.js +88 -0
  73. package/es/components/corpus-card/index.module.scss.js +171 -0
  74. package/es/components/feature-card/classNames.js +72 -0
  75. package/es/components/feature-card/components.js +48 -0
  76. package/es/components/feature-card/context.js +13 -0
  77. package/es/components/feature-card/index.css.js +655 -0
  78. package/es/components/feature-card/index.js +48 -0
  79. package/es/components/file-preview/data-table/index.js +94 -0
  80. package/es/components/file-preview/data-table/index.module.scss.js +54 -0
  81. package/es/components/file-preview/excel-preview/index.js +132 -0
  82. package/es/components/file-preview/excel-preview/index.module.scss.js +11 -0
  83. package/es/components/file-preview/excel-preview/utils.js +46 -0
  84. package/es/components/file-preview/img-preview/index.js +18 -0
  85. package/es/components/file-preview/img-preview/index.module.scss.js +17 -0
  86. package/es/components/file-preview/index.js +124 -0
  87. package/es/components/file-preview/index.module.scss.js +32 -0
  88. package/es/components/file-preview/json-preview/index.js +166 -0
  89. package/es/components/file-preview/markdown-preview/index.js +53 -0
  90. package/es/components/file-preview/markdown-preview/index.module.scss.js +1055 -0
  91. package/es/components/file-preview/parquet-preview/index.js +54 -0
  92. package/es/components/file-preview/pdf-preview/index.js +215 -0
  93. package/es/components/file-preview/pdf-preview/index.module.scss.js +16 -0
  94. package/es/components/file-preview/table-preview/index.js +43 -0
  95. package/es/components/file-preview/table-preview/index.module.scss.js +11 -0
  96. package/es/components/file-preview/txt-preview/index.js +24 -0
  97. package/es/components/file-preview/util.js +94 -0
  98. package/es/components/file-uploader/components/circle-progress.css.js +39 -0
  99. package/es/components/file-uploader/components/circle-progress.js +12 -0
  100. package/es/components/file-uploader/components/hooks/use-drop-zone.js +74 -0
  101. package/es/components/file-uploader/components/hooks/use-file-validation.js +52 -0
  102. package/es/components/file-uploader/components/icons.js +19 -0
  103. package/es/components/file-uploader/components/theme.css.js +64 -0
  104. package/es/components/file-uploader/components/uploader-drop-zone.css.js +66 -0
  105. package/es/components/file-uploader/components/uploader-drop-zone.js +74 -0
  106. package/es/components/file-uploader/components/uploader-file-item.css.js +186 -0
  107. package/es/components/file-uploader/components/uploader-file-item.js +63 -0
  108. package/es/components/file-uploader/components/uploader-file-list.css.js +43 -0
  109. package/es/components/file-uploader/components/uploader-file-list.js +27 -0
  110. package/es/components/file-uploader/components/uploader.css.js +20 -0
  111. package/es/components/file-uploader/components/uploader.js +51 -0
  112. package/es/components/file-uploader/components/uploading-status.css.js +52 -0
  113. package/es/components/file-uploader/components/uploading-status.js +54 -0
  114. package/es/components/file-uploader/components/utils/directory-reader.js +65 -0
  115. package/es/components/file-uploader/constants.js +31 -0
  116. package/es/components/file-uploader/context/action-registry.js +69 -0
  117. package/es/components/file-uploader/context/file-state-store.js +83 -0
  118. package/es/components/file-uploader/context/handler-registry.js +119 -0
  119. package/es/components/file-uploader/context/upload-context.js +36 -0
  120. package/es/components/file-uploader/context/upload-provider.js +77 -0
  121. package/es/components/file-uploader/context/upload-reducer.js +21 -0
  122. package/es/components/file-uploader/context/use-upload-engine.js +440 -0
  123. package/es/components/file-uploader/engine/queue-callbacks.js +257 -0
  124. package/es/components/file-uploader/engine/queue-manager.js +195 -0
  125. package/es/components/file-uploader/engine/queue-uploader.js +25 -0
  126. package/es/components/file-uploader/hooks/use-upload.js +327 -0
  127. package/es/components/file-uploader/utils/chunk-handlers.js +66 -0
  128. package/es/components/file-uploader/utils/ensure-handlers.js +53 -0
  129. package/es/components/file-uploader/utils/error-handler.js +84 -0
  130. package/es/components/file-uploader/utils/upload-controllers.js +43 -0
  131. package/es/components/file-uploader/utils/upload-handler.js +68 -0
  132. package/es/components/file-uploader/utils/validate-handlers.js +16 -0
  133. package/es/components/floating-label-input/index.js +46 -0
  134. package/es/components/floating-label-input/index.module.scss.js +30 -0
  135. package/es/components/floating-layer/index.js +15 -0
  136. package/es/components/floating-layer/index.scss.js +31 -0
  137. package/es/components/header/index.js +10 -0
  138. package/es/components/header/index.module.scss.js +16 -0
  139. package/es/components/input-tag/index.js +65 -0
  140. package/es/components/menu/index.js +96 -0
  141. package/es/components/menu/index.module.scss.js +188 -0
  142. package/es/components/model-card/index.js +20 -0
  143. package/es/components/model-card/index.module.scss.js +116 -0
  144. package/es/components/notion-editor/code-block/index.js +18 -0
  145. package/es/components/notion-editor/code-block/languageDetector.js +134 -0
  146. package/es/components/notion-editor/code-block/languages.js +42 -0
  147. package/es/components/notion-editor/index.js +258 -0
  148. package/es/components/notion-editor/index.scss.js +421 -0
  149. package/es/components/notion-editor/parseMarkdown.js +184 -0
  150. package/es/components/operator-chain/components/AddButton.js +20 -0
  151. package/es/components/operator-chain/components/IOCard.js +8 -0
  152. package/es/components/operator-chain/components/SingleCard.js +12 -0
  153. package/es/components/operator-chain/components/VirtualDropdown.js +56 -0
  154. package/es/components/operator-chain/index.js +83 -0
  155. package/es/components/operator-chain/index.module.scss.js +232 -0
  156. package/es/components/permission-editor/index.js +9 -0
  157. package/es/components/permission-editor/permissionEditModal/index.js +37 -0
  158. package/es/components/permission-editor/permissionEditor/index.js +253 -0
  159. package/es/components/permission-editor/permissionEditor/index.module.scss.js +22 -0
  160. package/es/components/permission-editor/permissionViewPopover/index.js +9 -0
  161. package/es/components/popover-select/index.js +42 -0
  162. package/es/components/popover-select/index.module.scss.js +22 -0
  163. package/es/components/radio-card/index.js +24 -0
  164. package/es/components/radio-card/index.scss.js +58 -0
  165. package/es/components/section-heading/classNames.js +22 -0
  166. package/es/components/section-heading/components.js +27 -0
  167. package/es/components/section-heading/context.js +13 -0
  168. package/es/components/section-heading/index.css.js +648 -0
  169. package/es/components/section-heading/index.js +37 -0
  170. package/es/components/status-tag/index.js +31 -0
  171. package/es/components/tag-group-filter/dataSizeFilter.js +100 -0
  172. package/es/components/tag-group-filter/index.js +53 -0
  173. package/es/components/tag-group-filter/index.module.scss.js +134 -0
  174. package/es/components/tag-group-filter/tagFilter.js +19 -0
  175. package/es/components/tag-view/index.js +138 -0
  176. package/es/components/tag-view/index.module.scss.js +56 -0
  177. package/es/components/tag-view/useSize.js +41 -0
  178. package/es/components/tip-tap/bubble-menu.js +47 -0
  179. package/es/components/tip-tap/editor.js +34 -0
  180. package/es/components/tip-tap/extensions/index.js +133 -0
  181. package/es/components/tip-tap/extensions/markdown-paste.js +148 -0
  182. package/es/components/tip-tap/icons/index.js +29 -0
  183. package/es/components/tip-tap/reader.js +15 -0
  184. package/es/components/tip-tap/styles/editor.css.js +863 -0
  185. package/es/components/tip-tap/toolbar/components/color-picker.js +76 -0
  186. package/es/components/tip-tap/toolbar/components/heading-dropdown.js +44 -0
  187. package/es/components/tip-tap/toolbar/components/image-button.js +26 -0
  188. package/es/components/tip-tap/toolbar/components/link-button.js +107 -0
  189. package/es/components/tip-tap/toolbar/components/table-button.js +37 -0
  190. package/es/components/tip-tap/toolbar/components/toolbar-button.js +7 -0
  191. package/es/components/tip-tap/toolbar/index.js +39 -0
  192. package/es/components/uploadDrawer/UploadStoreProvider.js +61 -0
  193. package/es/components/uploadDrawer/fileUploadDrawer.js +66 -0
  194. package/es/components/uploadDrawer/fileUploadDrawerFileDragger.js +71 -0
  195. package/es/components/uploadDrawer/fileUploadDrawerList.js +54 -0
  196. package/es/components/uploadDrawer/fileUploadDrawerListProgressButton.js +54 -0
  197. package/es/components/uploadDrawer/hooks/useCancelUpload.js +37 -0
  198. package/es/components/uploadDrawer/hooks/useFilterFiles.js +107 -0
  199. package/es/components/uploadDrawer/hooks/useFinishUpload.js +33 -0
  200. package/es/components/uploadDrawer/hooks/useFormatFiles.js +54 -0
  201. package/es/components/uploadDrawer/hooks/useProgressButtonRef.js +22 -0
  202. package/es/components/uploadDrawer/hooks/useRemoveFilesInUploadQueue.js +21 -0
  203. package/es/components/uploadDrawer/hooks/useResumeUnfinishedUploads.js +52 -0
  204. package/es/components/uploadDrawer/hooks/useRetryUpload.js +35 -0
  205. package/es/components/uploadDrawer/hooks/useSaveUnfinishedUploads.js +42 -0
  206. package/es/components/uploadDrawer/hooks/useSetupUpload.js +80 -0
  207. package/es/components/uploadDrawer/hooks/useUploadFileToOSS.js +23 -0
  208. package/es/components/uploadDrawer/index.css.js +511 -0
  209. package/es/components/uploadDrawer/index.js +43 -0
  210. package/es/components/uploadDrawer/utils/calcDisplaySize.js +19 -0
  211. package/es/components/uploadDrawer/utils/constant.js +16 -0
  212. package/es/components/uploadDrawer/utils/createFileToUpload.js +51 -0
  213. package/es/components/uploadDrawer/utils/fileDB/deleteFileInStore.js +28 -0
  214. package/es/components/uploadDrawer/utils/fileDB/deleteObjectStore.js +28 -0
  215. package/es/components/uploadDrawer/utils/fileDB/handleAddFilesToDB.js +37 -0
  216. package/es/components/uploadDrawer/utils/fileDB/index.js +9 -0
  217. package/es/components/uploadDrawer/utils/fileDB/openDB.js +111 -0
  218. package/es/components/uploadDrawer/utils/retrieveAllFiles.js +110 -0
  219. package/es/components/uploadDrawer/utils/shouldCreateNewFile.js +13 -0
  220. package/es/components/uploadDrawer/utils/splitFileIntoChunk.js +15 -0
  221. package/es/index.js +42 -1
  222. package/es/lib/utils.js +8 -0
  223. package/lib/index.js +1 -1
  224. package/package.json +164 -154
  225. package/rollup.es.config.mjs +177 -0
  226. package/tsconfig.rollup.json +7 -0
@@ -0,0 +1,76 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useEditorState } from '@tiptap/react';
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { IconBold, IconHighlight } from '../../icons/index.js';
5
+
6
+ function ColorPicker({ editor, type, tooltip }) {
7
+ const [isOpen, setIsOpen] = useState(false);
8
+ const dropdownRef = useRef(null);
9
+ const colors = [
10
+ '#000000',
11
+ '#374151',
12
+ '#6b7280',
13
+ '#9ca3af',
14
+ '#ef4444',
15
+ '#f97316',
16
+ '#eab308',
17
+ '#22c55e',
18
+ '#14b8a6',
19
+ '#3b82f6',
20
+ '#6366f1',
21
+ '#a855f7',
22
+ '#ec4899',
23
+ '#f43f5e',
24
+ '#84cc16',
25
+ '#06b6d4',
26
+ ];
27
+ // 使用 useEditorState 来同步编辑器状态
28
+ const editorState = useEditorState({
29
+ editor,
30
+ selector: (ctx) => {
31
+ if (type === 'textColor') {
32
+ return {
33
+ isActive: !!ctx.editor.getAttributes('textStyle').color,
34
+ color: ctx.editor.getAttributes('textStyle').color,
35
+ };
36
+ }
37
+ else {
38
+ return {
39
+ isActive: ctx.editor.isActive('highlight'),
40
+ color: ctx.editor.getAttributes('highlight').color,
41
+ };
42
+ }
43
+ },
44
+ });
45
+ useEffect(() => {
46
+ function handleClickOutside(e) {
47
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
48
+ setIsOpen(false);
49
+ }
50
+ }
51
+ document.addEventListener('mousedown', handleClickOutside);
52
+ return () => document.removeEventListener('mousedown', handleClickOutside);
53
+ }, []);
54
+ function handleColorSelect(color) {
55
+ if (type === 'textColor') {
56
+ if (color) {
57
+ editor.chain().focus().setColor(color).run();
58
+ }
59
+ else {
60
+ editor.chain().focus().unsetColor().run();
61
+ }
62
+ }
63
+ else {
64
+ if (color) {
65
+ editor.chain().focus().toggleHighlight({ color }).run();
66
+ }
67
+ else {
68
+ editor.chain().focus().unsetHighlight().run();
69
+ }
70
+ }
71
+ setIsOpen(false);
72
+ }
73
+ return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", style: type === 'textColor' && (editorState === null || editorState === void 0 ? void 0 : editorState.color) ? { color: editorState.color } : {}, children: [type === 'textColor' ? (jsx(IconBold, { style: { borderBottom: `3px solid ${(editorState === null || editorState === void 0 ? void 0 : editorState.color) || '#000'}` } })) : (jsx(IconHighlight, {})), jsx("span", { className: "tip-tap-tooltip", children: tooltip })] }), jsx("div", { className: "tip-tap-dropdown__menu", children: jsxs("div", { className: "tip-tap-color-picker", children: [jsx("button", { className: "tip-tap-color-picker__swatch tip-tap-color-picker__swatch--reset", onClick: () => handleColorSelect(null), title: "\u79FB\u9664\u989C\u8272", type: "button" }), colors.map((color) => (jsx("button", { className: "tip-tap-color-picker__swatch", style: { background: color }, onClick: () => handleColorSelect(color), type: "button" }, color)))] }) })] }));
74
+ }
75
+
76
+ export { ColorPicker };
@@ -0,0 +1,44 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useEditorState } from '@tiptap/react';
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { IconParagraph, IconH1, IconH2, IconH3, IconChevronDown } from '../../icons/index.js';
5
+
6
+ function HeadingDropdown({ editor }) {
7
+ const [isOpen, setIsOpen] = useState(false);
8
+ const dropdownRef = useRef(null);
9
+ const headings = [
10
+ { level: 0, label: '正文', icon: jsx(IconParagraph, {}) },
11
+ { level: 1, label: '标题 1', icon: jsx(IconH1, {}) },
12
+ { level: 2, label: '标题 2', icon: jsx(IconH2, {}) },
13
+ { level: 3, label: '标题 3', icon: jsx(IconH3, {}) },
14
+ ];
15
+ // 使用 useEditorState 来同步编辑器状态
16
+ const editorState = useEditorState({
17
+ editor,
18
+ selector: (ctx) => {
19
+ const currentLevel = headings.find((h) => h.level === 0 ? ctx.editor.isActive('paragraph') : ctx.editor.isActive('heading', { level: h.level }));
20
+ return currentLevel;
21
+ },
22
+ });
23
+ useEffect(() => {
24
+ function handleClickOutside(e) {
25
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
26
+ setIsOpen(false);
27
+ }
28
+ }
29
+ document.addEventListener('mousedown', handleClickOutside);
30
+ return () => document.removeEventListener('mousedown', handleClickOutside);
31
+ }, []);
32
+ function handleSelect(level) {
33
+ if (level === 0) {
34
+ editor.chain().focus().setParagraph().run();
35
+ }
36
+ else {
37
+ editor.chain().focus().toggleHeading({ level }).run();
38
+ }
39
+ setIsOpen(false);
40
+ }
41
+ return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-dropdown__trigger ${editorState && editorState.level !== 0 ? 'tip-tap-dropdown__trigger--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [(editorState === null || editorState === void 0 ? void 0 : editorState.icon) || jsx(IconParagraph, {}), jsx("span", { children: (editorState === null || editorState === void 0 ? void 0 : editorState.label) || '正文' }), jsx(IconChevronDown, { className: "tip-tap-dropdown__arrow" })] }), jsx("div", { className: "tip-tap-dropdown__menu", children: headings.map(({ level, label, icon }) => (jsxs("button", { className: `tip-tap-dropdown__item ${(editorState === null || editorState === void 0 ? void 0 : editorState.level) === level ? 'tip-tap-dropdown__item--active' : ''}`, onClick: () => handleSelect(level), type: "button", children: [jsx("span", { className: "tip-tap-dropdown__item-icon", children: icon }), label] }, level))) })] }));
42
+ }
43
+
44
+ export { HeadingDropdown };
@@ -0,0 +1,26 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useRef } from 'react';
3
+ import { IconImage } from '../../icons/index.js';
4
+
5
+ function ImageButton({ editor }) {
6
+ const fileInputRef = useRef(null);
7
+ function handleFileSelect(e) {
8
+ var _a;
9
+ const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
10
+ if (file) {
11
+ const reader = new FileReader();
12
+ reader.onload = (event) => {
13
+ var _a;
14
+ const result = (_a = event.target) === null || _a === void 0 ? void 0 : _a.result;
15
+ if (typeof result === 'string') {
16
+ editor.chain().focus().setImage({ src: result }).run();
17
+ }
18
+ };
19
+ reader.readAsDataURL(file);
20
+ }
21
+ e.target.value = '';
22
+ }
23
+ return (jsxs(Fragment, { children: [jsxs("button", { className: "tip-tap-btn", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, type: "button", children: [jsx(IconImage, {}), jsx("span", { className: "tip-tap-tooltip", children: "\u63D2\u5165\u56FE\u7247" })] }), jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleFileSelect })] }));
24
+ }
25
+
26
+ export { ImageButton };
@@ -0,0 +1,107 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useEditorState } from '@tiptap/react';
3
+ import { getMarkRange } from '@tiptap/core';
4
+ import { useState, useRef, useEffect } from 'react';
5
+ import { IconLink, IconCheck, IconTrash } from '../../icons/index.js';
6
+
7
+ function LinkButton({ editor }) {
8
+ const [isOpen, setIsOpen] = useState(false);
9
+ const [label, setLabel] = useState('');
10
+ const [url, setUrl] = useState('');
11
+ const dropdownRef = useRef(null);
12
+ const labelInputRef = useRef(null);
13
+ // 使用 useEditorState 来同步编辑器状态
14
+ const editorState = useEditorState({
15
+ editor,
16
+ selector: (ctx) => ({
17
+ isActive: ctx.editor.isActive('link'),
18
+ href: ctx.editor.getAttributes('link').href || '',
19
+ }),
20
+ });
21
+ useEffect(() => {
22
+ function handleClickOutside(e) {
23
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
24
+ setIsOpen(false);
25
+ }
26
+ }
27
+ document.addEventListener('mousedown', handleClickOutside);
28
+ return () => document.removeEventListener('mousedown', handleClickOutside);
29
+ }, []);
30
+ function handleToggleOpen() {
31
+ if (!isOpen) {
32
+ // 打开时:获取选中的文本作为标签,获取链接 URL
33
+ let selectedText = '';
34
+ const { from, to } = editor.state.selection;
35
+ if (editorState === null || editorState === void 0 ? void 0 : editorState.isActive) {
36
+ // 如果当前在链接上,获取整个链接的文本
37
+ const linkType = editor.schema.marks.link;
38
+ const $pos = editor.state.doc.resolve(from);
39
+ const range = getMarkRange($pos, linkType);
40
+ if (range) {
41
+ selectedText = editor.state.doc.textBetween(range.from, range.to, '');
42
+ }
43
+ }
44
+ else {
45
+ // 普通选择文本
46
+ selectedText = editor.state.doc.textBetween(from, to, '');
47
+ }
48
+ setLabel(selectedText || '');
49
+ setUrl((editorState === null || editorState === void 0 ? void 0 : editorState.href) || '');
50
+ setIsOpen(true);
51
+ // 使用 queueMicrotask 代替 setTimeout,更可靠且不需要延迟
52
+ queueMicrotask(() => {
53
+ var _a;
54
+ (_a = labelInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
55
+ });
56
+ }
57
+ else {
58
+ setIsOpen(false);
59
+ }
60
+ }
61
+ function normalizeUrl(inputUrl) {
62
+ const trimmed = inputUrl.trim();
63
+ if (!trimmed)
64
+ return '';
65
+ // 如果已经有协议前缀,直接返回
66
+ if (/^https?:\/\//i.test(trimmed) || /^mailto:/i.test(trimmed) || /^tel:/i.test(trimmed)) {
67
+ return trimmed;
68
+ }
69
+ // 否则添加 https:// 前缀
70
+ return `https://${trimmed}`;
71
+ }
72
+ function handleSubmit() {
73
+ const normalizedUrl = normalizeUrl(url);
74
+ if (normalizedUrl && label) {
75
+ // 插入带标签的链接
76
+ editor
77
+ .chain()
78
+ .focus()
79
+ .insertContent({
80
+ type: 'text',
81
+ text: label,
82
+ marks: [{ type: 'link', attrs: { href: normalizedUrl } }],
83
+ })
84
+ .run();
85
+ }
86
+ else if (normalizedUrl) {
87
+ // 只有 URL,使用现有逻辑
88
+ editor.chain().focus().extendMarkRange('link').setLink({ href: normalizedUrl }).run();
89
+ }
90
+ else {
91
+ // 没有 URL,移除链接
92
+ editor.chain().focus().unsetLink().run();
93
+ }
94
+ setIsOpen(false);
95
+ setLabel('');
96
+ setUrl('');
97
+ }
98
+ function handleRemove() {
99
+ editor.chain().focus().unsetLink().run();
100
+ setIsOpen(false);
101
+ setLabel('');
102
+ setUrl('');
103
+ }
104
+ return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: handleToggleOpen, type: "button", children: [jsx(IconLink, {}), jsx("span", { className: "tip-tap-tooltip", children: "\u94FE\u63A5" })] }), jsx("div", { className: "tip-tap-dropdown__menu", style: { width: 'auto', padding: 0 }, children: jsxs("div", { className: "tip-tap-link-popup", style: { flexDirection: 'column', alignItems: 'stretch' }, children: [jsx("input", { ref: labelInputRef, type: "text", className: "tip-tap-link-popup__input", placeholder: "\u8F93\u5165\u94FE\u63A5\u6587\u672C...", value: label, onChange: (e) => setLabel(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleSubmit(), style: { marginBottom: '8px' } }), jsx("input", { type: "text", className: "tip-tap-link-popup__input", placeholder: "\u8F93\u5165\u94FE\u63A5\u5730\u5740...", value: url, onChange: (e) => setUrl(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleSubmit() }), jsxs("div", { style: { display: 'flex', gap: '4px', marginTop: '8px' }, children: [jsx("button", { className: "tip-tap-link-popup__btn", onClick: handleSubmit, type: "button", children: jsx(IconCheck, {}) }), (editorState === null || editorState === void 0 ? void 0 : editorState.isActive) && (jsx("button", { className: "tip-tap-link-popup__btn tip-tap-link-popup__btn--danger", onClick: handleRemove, type: "button", children: jsx(IconTrash, {}) }))] })] }) })] }));
105
+ }
106
+
107
+ export { LinkButton };
@@ -0,0 +1,37 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useEditorState } from '@tiptap/react';
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { IconTable } from '../../icons/index.js';
5
+
6
+ function TableButton({ editor }) {
7
+ const [isOpen, setIsOpen] = useState(false);
8
+ const [hoveredCell, setHoveredCell] = useState({ row: 0, col: 0 });
9
+ const dropdownRef = useRef(null);
10
+ // 使用 useEditorState 来同步编辑器状态
11
+ const editorState = useEditorState({
12
+ editor,
13
+ selector: (ctx) => ({
14
+ isActive: ctx.editor.isActive('table'),
15
+ }),
16
+ });
17
+ useEffect(() => {
18
+ function handleClickOutside(e) {
19
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
20
+ setIsOpen(false);
21
+ }
22
+ }
23
+ document.addEventListener('mousedown', handleClickOutside);
24
+ return () => document.removeEventListener('mousedown', handleClickOutside);
25
+ }, []);
26
+ function handleInsertTable(rows, cols) {
27
+ editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
28
+ setIsOpen(false);
29
+ }
30
+ return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [jsx(IconTable, {}), jsx("span", { className: "tip-tap-tooltip", children: "\u63D2\u5165\u8868\u683C" })] }), jsx("div", { className: "tip-tap-dropdown__menu", style: { padding: 0 }, children: jsxs("div", { className: "tip-tap-table-menu", children: [jsx("div", { className: "tip-tap-table-menu__label", children: "\u9009\u62E9\u8868\u683C\u5927\u5C0F" }), jsx("div", { className: "tip-tap-table-menu__grid", children: Array.from({ length: 36 }, (_, i) => {
31
+ const row = Math.floor(i / 6) + 1;
32
+ const col = (i % 6) + 1;
33
+ return (jsx("button", { className: `tip-tap-table-menu__cell ${row <= hoveredCell.row && col <= hoveredCell.col ? 'tip-tap-table-menu__cell--active' : ''}`, onMouseEnter: () => setHoveredCell({ row, col }), onClick: () => handleInsertTable(row, col), type: "button" }, i));
34
+ }) }), jsx("div", { className: "tip-tap-table-menu__size", children: hoveredCell.row > 0 ? `${hoveredCell.row} × ${hoveredCell.col}` : '选择大小' })] }) })] }));
35
+ }
36
+
37
+ export { TableButton };
@@ -0,0 +1,7 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+
3
+ function ToolbarButton({ icon, tooltip, onClick, active = false, disabled = false, }) {
4
+ return (jsxs("button", { className: `tip-tap-btn ${active ? 'tip-tap-btn--active' : ''}`, onClick: onClick, disabled: disabled, type: "button", children: [icon, jsx("span", { className: "tip-tap-tooltip", children: tooltip })] }));
5
+ }
6
+
7
+ export { ToolbarButton };
@@ -0,0 +1,39 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useEditorState } from '@tiptap/react';
3
+ import { IconUndo, IconRedo, IconBold, IconItalic, IconUnderline, IconStrikethrough, IconAlignLeft, IconAlignCenter, IconAlignRight, IconListBullet, IconListNumbered, IconQuote, IconCode, IconMinus } from '../icons/index.js';
4
+ import { ToolbarButton } from './components/toolbar-button.js';
5
+ import { HeadingDropdown } from './components/heading-dropdown.js';
6
+ import { ColorPicker } from './components/color-picker.js';
7
+ import { LinkButton } from './components/link-button.js';
8
+ import { ImageButton } from './components/image-button.js';
9
+ import { TableButton } from './components/table-button.js';
10
+
11
+ function Toolbar({ editor, className = '' }) {
12
+ // 使用 useEditorState 来同步编辑器状态
13
+ const editorState = useEditorState({
14
+ editor,
15
+ selector: (ctx) => ({
16
+ // 文本格式
17
+ isBold: ctx.editor.isActive('bold'),
18
+ isItalic: ctx.editor.isActive('italic'),
19
+ isUnderline: ctx.editor.isActive('underline'),
20
+ isStrike: ctx.editor.isActive('strike'),
21
+ // 对齐方式
22
+ isAlignLeft: ctx.editor.isActive({ textAlign: 'left' }),
23
+ isAlignCenter: ctx.editor.isActive({ textAlign: 'center' }),
24
+ isAlignRight: ctx.editor.isActive({ textAlign: 'right' }),
25
+ // 列表
26
+ isBulletList: ctx.editor.isActive('bulletList'),
27
+ isOrderedList: ctx.editor.isActive('orderedList'),
28
+ // 块元素
29
+ isBlockquote: ctx.editor.isActive('blockquote'),
30
+ isCodeBlock: ctx.editor.isActive('codeBlock'),
31
+ // 撤销/重做能力
32
+ canUndo: ctx.editor.can().undo(),
33
+ canRedo: ctx.editor.can().redo(),
34
+ }),
35
+ });
36
+ return (jsxs("div", { className: `tip-tap-toolbar ${className}`, children: [jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconUndo, {}), tooltip: "\u64A4\u9500", onClick: () => editor.chain().focus().undo().run(), disabled: !(editorState === null || editorState === void 0 ? void 0 : editorState.canUndo) }), jsx(ToolbarButton, { icon: jsx(IconRedo, {}), tooltip: "\u91CD\u505A", onClick: () => editor.chain().focus().redo().run(), disabled: !(editorState === null || editorState === void 0 ? void 0 : editorState.canRedo) })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconBold, {}), tooltip: "\u7C97\u4F53", onClick: () => editor.chain().focus().toggleBold().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBold }), jsx(ToolbarButton, { icon: jsx(IconItalic, {}), tooltip: "\u659C\u4F53", onClick: () => editor.chain().focus().toggleItalic().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isItalic }), jsx(ToolbarButton, { icon: jsx(IconUnderline, {}), tooltip: "\u4E0B\u5212\u7EBF", onClick: () => editor.chain().focus().toggleUnderline().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isUnderline }), jsx(ToolbarButton, { icon: jsx(IconStrikethrough, {}), tooltip: "\u5220\u9664\u7EBF", onClick: () => editor.chain().focus().toggleStrike().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isStrike })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsx(HeadingDropdown, { editor: editor }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ColorPicker, { editor: editor, type: "textColor", tooltip: "\u6587\u5B57\u989C\u8272" }), jsx(ColorPicker, { editor: editor, type: "highlight", tooltip: "\u80CC\u666F\u9AD8\u4EAE" })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconAlignLeft, {}), tooltip: "\u5DE6\u5BF9\u9F50", onClick: () => editor.chain().focus().setTextAlign('left').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignLeft }), jsx(ToolbarButton, { icon: jsx(IconAlignCenter, {}), tooltip: "\u5C45\u4E2D\u5BF9\u9F50", onClick: () => editor.chain().focus().setTextAlign('center').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignCenter }), jsx(ToolbarButton, { icon: jsx(IconAlignRight, {}), tooltip: "\u53F3\u5BF9\u9F50", onClick: () => editor.chain().focus().setTextAlign('right').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignRight })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconListBullet, {}), tooltip: "\u65E0\u5E8F\u5217\u8868", onClick: () => editor.chain().focus().toggleBulletList().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBulletList }), jsx(ToolbarButton, { icon: jsx(IconListNumbered, {}), tooltip: "\u6709\u5E8F\u5217\u8868", onClick: () => editor.chain().focus().toggleOrderedList().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isOrderedList })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconQuote, {}), tooltip: "\u5F15\u7528", onClick: () => editor.chain().focus().toggleBlockquote().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBlockquote }), jsx(ToolbarButton, { icon: jsx(IconCode, {}), tooltip: "\u4EE3\u7801\u5757", onClick: () => editor.chain().focus().toggleCodeBlock().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isCodeBlock }), jsx(ToolbarButton, { icon: jsx(IconMinus, {}), tooltip: "\u5206\u5272\u7EBF", onClick: () => editor.chain().focus().setHorizontalRule().run() })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(LinkButton, { editor: editor }), jsx(ImageButton, { editor: editor }), jsx(TableButton, { editor: editor })] })] }));
37
+ }
38
+
39
+ export { Toolbar as default };
@@ -0,0 +1,61 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useReducer } from 'react';
3
+ import { FILE_UPLOAD_STATUS } from './utils/constant.js';
4
+ import 'tslib';
5
+ import { useSaveUnfinishedUploads } from './hooks/useSaveUnfinishedUploads.js';
6
+
7
+ const TEMP_STORE = {};
8
+ const UploadStoreContext = createContext(TEMP_STORE);
9
+ const UploadStoreDispatchContext = createContext(() => null);
10
+ /**
11
+ * @deprecated This component is deprecated and will be removed in future releases.
12
+ */
13
+ function UploadDrawerUploadStoreProvider({ children }) {
14
+ const [uploadStore, dispatch] = useReducer(uploadReducer, {});
15
+ useSaveUnfinishedUploads(uploadStore);
16
+ return (jsx(UploadStoreContext.Provider, { value: uploadStore, children: jsx(UploadStoreDispatchContext.Provider, { value: dispatch, children: children }) }));
17
+ }
18
+ function uploadReducer(uploads, action) {
19
+ switch (action.type) {
20
+ case 'add': {
21
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [] });
22
+ }
23
+ case 'remove_file': {
24
+ const fileList = uploads[action.identifier];
25
+ const fileIndex = fileList.findIndex((p) => p.fileName === action.file.fileName);
26
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList.slice(0, fileIndex), ...fileList.slice(fileIndex + 1)] });
27
+ }
28
+ case 'edit_file': {
29
+ const fileList = uploads[action.identifier];
30
+ const fileIndex = fileList.findIndex((p) => p.fileName === action.file.fileName);
31
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList.slice(0, fileIndex), action.file, ...fileList.slice(fileIndex + 1)] });
32
+ }
33
+ case 'add_file': {
34
+ const fileList = uploads[action.identifier];
35
+ const fileIndex = fileList.findIndex((p) => p.fileName === action.file.fileName);
36
+ if (fileIndex === -1) {
37
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList, action.file] });
38
+ }
39
+ else {
40
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [
41
+ ...fileList.slice(0, fileIndex),
42
+ action.file,
43
+ ...fileList.slice(fileIndex + 1),
44
+ ] });
45
+ }
46
+ }
47
+ case 'add_files': {
48
+ const fileList = uploads[action.identifier];
49
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: [...fileList, ...action.files] });
50
+ }
51
+ case 'clear_finished': {
52
+ const fileList = uploads[action.identifier];
53
+ return Object.assign(Object.assign({}, uploads), { [action.identifier]: fileList.filter((f) => f.fileStatus !== FILE_UPLOAD_STATUS.FINISHED) });
54
+ }
55
+ default: {
56
+ throw Error('Unknown action');
57
+ }
58
+ }
59
+ }
60
+
61
+ export { TEMP_STORE, UploadStoreContext, UploadStoreDispatchContext, UploadDrawerUploadStoreProvider as default };
@@ -0,0 +1,66 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { Drawer, Empty } from 'antd';
4
+ import { useContext, useState, useRef, useEffect } from 'react';
5
+ import { LoadingOutlined } from '@ant-design/icons';
6
+ import { UploadStoreContext, UploadStoreDispatchContext } from './UploadStoreProvider.js';
7
+ import FileUploadDrawerFileDragger from './fileUploadDrawerFileDragger.js';
8
+ import FileUploading from './fileUploadDrawerList.js';
9
+ import { FILE_UPLOAD_STATUS } from './utils/constant.js';
10
+ import { useFormatFiles } from './hooks/useFormatFiles.js';
11
+ import { useUploadFileToOSS } from './hooks/useUploadFileToOSS.js';
12
+ import { useResumeUnfinishedUploads } from './hooks/useResumeUnfinishedUploads.js';
13
+ import { FileUploadDrawerContext } from './index.js';
14
+
15
+ function FileUploadDrawer({ open, identifier, accept, dragAreaDescription, footer, title = '数据上传', showFinished = false, directory = false, onClose, }) {
16
+ var _a, _b;
17
+ const uploadStore = useContext(UploadStoreContext);
18
+ const setUploadsStore = useContext(UploadStoreDispatchContext);
19
+ const { onSuccess } = useContext(FileUploadDrawerContext);
20
+ const formatFiles = useFormatFiles();
21
+ const uploadFileToOSS = useUploadFileToOSS();
22
+ const resumeUnfinishedUploads = useResumeUnfinishedUploads(identifier);
23
+ const [raws, setRaws] = useState([]);
24
+ const currentIdentifier = useRef('');
25
+ useEffect(() => {
26
+ if (currentIdentifier.current === identifier) {
27
+ return;
28
+ }
29
+ // 添加对uploadStoreContext的检测
30
+ if (!uploadStore || !setUploadsStore) {
31
+ console.warn('FileUploadDrawer 必须在 UploadStoreProvider 内使用');
32
+ return;
33
+ }
34
+ currentIdentifier.current = identifier;
35
+ if (!uploadStore[identifier]) {
36
+ setUploadsStore({ type: 'add', identifier });
37
+ }
38
+ resumeUnfinishedUploads();
39
+ }, [identifier, resumeUnfinishedUploads, uploadStore, setUploadsStore]);
40
+ useEffect(() => {
41
+ const fileList = uploadStore[identifier];
42
+ if (!fileList)
43
+ return;
44
+ const shouldUpload = !fileList.some((file) => file.fileStatus === FILE_UPLOAD_STATUS.UPLOADING);
45
+ const fileToUpload = fileList.find((file) => file.fileStatus === FILE_UPLOAD_STATUS.INIT);
46
+ if (shouldUpload && fileToUpload) {
47
+ uploadFileToOSS(fileToUpload, onSuccess);
48
+ }
49
+ }, [identifier, onSuccess, uploadFileToOSS, uploadStore]);
50
+ return (jsxs(Drawer, { className: "mylib-upload-drawer", open: open, title: title, width: 480, onClose: onClose, footer: footer, children: [jsx(FileUploadDrawerFileDragger, { directory: directory, accept: accept, dragAreaDescription: dragAreaDescription, onFileReceived: onFileReceived }), raws.length === 0 && ((_a = uploadStore[identifier]) === null || _a === void 0 ? void 0 : _a.length) === 0 && (jsx(Empty, { className: "mt-20", description: "\u6682\u65E0\u4E0A\u4F20\u5185\u5BB9" })), raws.length > 0 && (jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [jsx(LoadingOutlined, {}), "\u9884\u68C0\u4E0A\u4F20\u6587\u4EF6\u4E2D(", raws.length, ")"] })), ((_b = uploadStore[identifier]) === null || _b === void 0 ? void 0 : _b.length) > 0 && (jsx(FileUploading, { showFinished: showFinished, identifier: identifier }))] }));
51
+ function onFileReceived(files) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ setRaws((prev) => [...prev, ...files]);
54
+ yield formatFiles(files);
55
+ setRaws((prev) => {
56
+ const prevSet = new Set(prev);
57
+ for (const file of files) {
58
+ prevSet.delete(file);
59
+ }
60
+ return [...prevSet];
61
+ });
62
+ });
63
+ }
64
+ }
65
+
66
+ export { FileUploadDrawer as default };
@@ -0,0 +1,71 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
+ import { Flex } from 'antd';
4
+ import { InboxOutlined } from '@ant-design/icons';
5
+ import { useMemo, useRef, useState } from 'react';
6
+ import './utils/constant.js';
7
+ import { retrieveAllFiles } from './utils/retrieveAllFiles.js';
8
+
9
+ const containerClassName = 'border-dashed rounded border bg-gray-50 p-4 hover:border-green-600 border-gray-300';
10
+ function FileUploadDrawerFileDragger({ accept = '', directory = true, dragAreaDescription, onFileReceived, }) {
11
+ // 将accept字符串转换为Set以便快速查找
12
+ const acceptList = useMemo(() => new Set(accept ? accept.split(',') : []), [accept]);
13
+ const fileInputRef = useRef(null);
14
+ const [isDragOver, setIsDragOver] = useState(false);
15
+ // 拖拽相关的事件处理函数
16
+ const handleDragEvents = {
17
+ onDragLeave: () => setIsDragOver(false),
18
+ onDragEnter: (e) => e.preventDefault(),
19
+ onDragOver: (e) => {
20
+ e.preventDefault();
21
+ setIsDragOver(true);
22
+ },
23
+ onDrop: handleDrop,
24
+ };
25
+ return (jsxs(Fragment, { children: [jsxs(Flex, Object.assign({ vertical: true, gap: "1rem", align: "center", className: `${isDragOver ? 'border-green-600' : ''} ${containerClassName}` }, handleDragEvents, { onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: [jsx("p", { className: "text-5xl text-green-600 m-0", children: jsx(InboxOutlined, {}) }), jsx("div", { className: "text-base text-center", children: renderDragAreaDescription() })] })), jsx("input", { ref: fileInputRef, type: "file", accept: accept, hidden: true, multiple: true, onChange: handleInputChange, onClick: () => {
26
+ if (fileInputRef.current) {
27
+ fileInputRef.current.value = ''; // 清空input的value,确保同一文件可以重复上传
28
+ }
29
+ } })] }));
30
+ // 处理文件拖拽
31
+ function handleDrop(e) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ e.preventDefault();
34
+ setIsDragOver(false);
35
+ // 获取所有拖拽的文件或文件夹
36
+ const filePromises = Array.from(e.dataTransfer.items)
37
+ .map((item) => item.webkitGetAsEntry())
38
+ .filter(Boolean)
39
+ .map((entry) => retrieveAllFiles(entry, directory, acceptList));
40
+ // 等待所有文件处理完成
41
+ const results = yield Promise.allSettled(filePromises);
42
+ // 过滤出成功的结果并展平数组
43
+ const files = results
44
+ .filter((result) => result.status === 'fulfilled')
45
+ .flatMap((result) => result.value);
46
+ if (files.length) {
47
+ onFileReceived(files);
48
+ }
49
+ });
50
+ }
51
+ // 处理文件选择
52
+ function handleInputChange() {
53
+ var _a;
54
+ const files = (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.files;
55
+ if (files === null || files === void 0 ? void 0 : files.length) {
56
+ onFileReceived(Array.from(files));
57
+ }
58
+ }
59
+ // 渲染拖拽区域的描述文本
60
+ function renderDragAreaDescription() {
61
+ if (!dragAreaDescription) {
62
+ return jsx("p", { className: "text-base m-0", children: "\u70B9\u51FB\u6216\u62D6\u62FD\u4E0A\u4F20\u6587\u4EF6" });
63
+ }
64
+ if (Array.isArray(dragAreaDescription)) {
65
+ return dragAreaDescription.map((text, index) => (jsx("p", { className: "text-base m-0", children: text }, index)));
66
+ }
67
+ return jsx("p", { className: "text-base m-0", children: dragAreaDescription });
68
+ }
69
+ }
70
+
71
+ export { FileUploadDrawerFileDragger as default };
@@ -0,0 +1,54 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { FileTextOutlined, DeleteOutlined } from '@ant-design/icons';
4
+ import { useContext, useState, useEffect } from 'react';
5
+ import { UploadStoreContext, UploadStoreDispatchContext } from './UploadStoreProvider.js';
6
+ import { FILE_UPLOAD_STATUS } from './utils/constant.js';
7
+ import FileUploadDrawerListProgressButton from './fileUploadDrawerListProgressButton.js';
8
+ import { Flex, Button } from 'antd';
9
+ import { useRetryUpload } from './hooks/useRetryUpload.js';
10
+ import { useCancelUpload } from './hooks/useCancelUpload.js';
11
+
12
+ function FileUploading({ identifier, showFinished, }) {
13
+ const uploadContext = useContext(UploadStoreContext);
14
+ const cancelUpload = useCancelUpload();
15
+ const retryUpload = useRetryUpload();
16
+ const [fileList, setFileList] = useState([]);
17
+ useEffect(() => {
18
+ // 根据条件过滤文件列表
19
+ const filteredList = uploadContext[identifier].filter((file) => {
20
+ // 排除已取消的文件
21
+ if (file.fileStatus === FILE_UPLOAD_STATUS.CANCELED) {
22
+ return false;
23
+ }
24
+ // 如果不显示已完成文件,则排除已完成的文件
25
+ if (showFinished === false && file.fileStatus === FILE_UPLOAD_STATUS.FINISHED) {
26
+ return false;
27
+ }
28
+ return true;
29
+ });
30
+ setFileList(filteredList);
31
+ }, [identifier, showFinished, uploadContext]);
32
+ return (jsx("div", { className: "my-4", children: fileList.map((file) => (jsx(FileListItem, { identifier: identifier, file: file, showFinished: showFinished, onButtonClick: handleButtonClick }, file.fileName))) }));
33
+ // 处理按钮点击事件
34
+ function handleButtonClick(file) {
35
+ file.fileStatus === FILE_UPLOAD_STATUS.PAUSED
36
+ ? retryUpload(file) // 如果文件暂停,则重试上传
37
+ : cancelUpload(file); // 否则取消上传
38
+ }
39
+ }
40
+ function FileListItem({ identifier, file, showFinished, onButtonClick }) {
41
+ const setUploadsStore = useContext(UploadStoreDispatchContext);
42
+ const showDelete = typeof showFinished === 'object' && showFinished.withDelete;
43
+ return (jsx("div", { className: "mb-2 last:mb-0", children: jsxs("div", { className: "px-4 my-2 relative flex justify-between items-center", children: [jsxs(Flex, { align: "center", gap: ".5rem", title: file.fileName, children: [jsx(FileTextOutlined, {}), jsx("span", { className: "truncate w-40", children: file.fileName })] }), jsxs(Flex, { align: "center", gap: ".5rem", children: [jsx(FileUploadDrawerListProgressButton, { status: file.fileStatus, percent: Number(file.percentage.toFixed(0)), onClick: () => onButtonClick(file) }), file.fileStatus === FILE_UPLOAD_STATUS.FINISHED && showDelete && (jsx(Button, { type: "text", size: "large", className: "px-3", disabled: showDelete.disabled, title: `${showDelete.disabled ? '删除-已禁用' : '删除'}`, onClick: () => onDelete(file, showDelete.onDelete), children: jsx(DeleteOutlined, {}) }))] })] }) }));
44
+ function onDelete(file, onDeleteImpl) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ const result = yield onDeleteImpl(file.fileName);
47
+ if (result) {
48
+ setUploadsStore({ type: 'remove_file', identifier, file });
49
+ }
50
+ });
51
+ }
52
+ }
53
+
54
+ export { FileUploading as default };