@waterwx/dsh-novel-forge 0.1.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 (50) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +180 -0
  3. package/cordis.patch.yml +13 -0
  4. package/lib/client.js +3924 -0
  5. package/lib/client.js.map +1 -0
  6. package/lib/index.js +3120 -0
  7. package/lib/index.js.map +1 -0
  8. package/lib/types/assets.d.ts +35 -0
  9. package/lib/types/assistant.d.ts +43 -0
  10. package/lib/types/bookshelf.d.ts +35 -0
  11. package/lib/types/client/api.d.ts +68 -0
  12. package/lib/types/client/docx.d.ts +15 -0
  13. package/lib/types/client/index.d.ts +14 -0
  14. package/lib/types/client/locales.d.ts +139 -0
  15. package/lib/types/client/mount.d.ts +9 -0
  16. package/lib/types/client/panel/AssetsTab.d.ts +7 -0
  17. package/lib/types/client/panel/AssistantTab.d.ts +7 -0
  18. package/lib/types/client/panel/BookshelfBar.d.ts +11 -0
  19. package/lib/types/client/panel/NovelPanel.d.ts +13 -0
  20. package/lib/types/client/panel/controller.d.ts +19 -0
  21. package/lib/types/client/panel/helpers.d.ts +8 -0
  22. package/lib/types/client/sidebar-entry.d.ts +13 -0
  23. package/lib/types/docx.d.ts +19 -0
  24. package/lib/types/engine.d.ts +95 -0
  25. package/lib/types/index.d.ts +55 -0
  26. package/lib/types/protocol.d.ts +521 -0
  27. package/lib/types/routes.d.ts +29 -0
  28. package/package.json +105 -0
  29. package/src/assets.ts +518 -0
  30. package/src/assistant.ts +547 -0
  31. package/src/bookshelf.ts +137 -0
  32. package/src/client/api.ts +254 -0
  33. package/src/client/css-modules.d.ts +8 -0
  34. package/src/client/docx.ts +69 -0
  35. package/src/client/index.ts +34 -0
  36. package/src/client/locales.ts +271 -0
  37. package/src/client/mount.tsx +97 -0
  38. package/src/client/panel/AssetsTab.tsx +341 -0
  39. package/src/client/panel/AssistantTab.tsx +188 -0
  40. package/src/client/panel/BookshelfBar.tsx +116 -0
  41. package/src/client/panel/NovelPanel.tsx +990 -0
  42. package/src/client/panel/controller.ts +45 -0
  43. package/src/client/panel/helpers.ts +17 -0
  44. package/src/client/panel/panel.module.css +894 -0
  45. package/src/client/sidebar-entry.ts +122 -0
  46. package/src/docx.ts +83 -0
  47. package/src/engine.ts +1019 -0
  48. package/src/index.ts +184 -0
  49. package/src/protocol.ts +539 -0
  50. package/src/routes.ts +955 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * 书架条:显示所有书,点击切换当前书(继续编译),+ 新建。
3
+ */
4
+ import { useState } from 'react'
5
+ import type { NovelApi } from '../api.ts'
6
+ import type { BookshelfSnapshot } from '../../protocol.ts'
7
+ import css from './panel.module.css'
8
+
9
+ /** Props. */
10
+ export interface BookshelfBarProps {
11
+ api: NovelApi
12
+ shelf: BookshelfSnapshot
13
+ /** 刷新整个面板(切换书后重新拉状态)。 */
14
+ onSwitch: () => void
15
+ }
16
+
17
+ /** 书架条。 */
18
+ export function BookshelfBar({ api, shelf, onSwitch }: BookshelfBarProps) {
19
+ const [creating, setCreating] = useState(false)
20
+ const [name, setName] = useState('')
21
+ const [busy, setBusy] = useState(false)
22
+ const [error, setError] = useState('')
23
+
24
+ const handleCreate = async (): Promise<void> => {
25
+ const bookName = name.trim()
26
+ if (bookName === '') return
27
+ setBusy(true)
28
+ setError('')
29
+ try {
30
+ await api.bookCreate(bookName)
31
+ setCreating(false)
32
+ setName('')
33
+ onSwitch()
34
+ } catch (err) {
35
+ setError((err as Error).message)
36
+ } finally {
37
+ setBusy(false)
38
+ }
39
+ }
40
+
41
+ const handleActivate = async (id: string): Promise<void> => {
42
+ if (id === shelf.activeBookId) return
43
+ setBusy(true)
44
+ try {
45
+ await api.bookActivate(id)
46
+ onSwitch()
47
+ } catch (err) {
48
+ setError((err as Error).message)
49
+ } finally {
50
+ setBusy(false)
51
+ }
52
+ }
53
+
54
+ const handleRemove = async (id: string): Promise<void> => {
55
+ setBusy(true)
56
+ try {
57
+ await api.bookRemove(id)
58
+ onSwitch()
59
+ } catch (err) {
60
+ setError((err as Error).message)
61
+ } finally {
62
+ setBusy(false)
63
+ }
64
+ }
65
+
66
+ return (
67
+ <div className={css.bookshelf}>
68
+ <span className={css.bookshelfLabel}>书架</span>
69
+ <div className={css.bookshelfList}>
70
+ {shelf.books.map(book => (
71
+ <div
72
+ key={book.id}
73
+ className={`${css.bookChip} ${book.id === shelf.activeBookId ? css.bookChipActive : ''}`}
74
+ onClick={() => { void handleActivate(book.id) }}
75
+ title={book.outputDir}
76
+ >
77
+ <span className={css.bookChipName}>{book.bookName}</span>
78
+ <span className={css.bookChipMeta}>{book.hasProject ? `${book.done}/${book.total} 章` : '未开书'}</span>
79
+ <button
80
+ type="button"
81
+ className={css.bookChipRemove}
82
+ title="从书架移除"
83
+ onClick={(e) => { e.stopPropagation(); void handleRemove(book.id) }}
84
+ >
85
+ ×
86
+ </button>
87
+ </div>
88
+ ))}
89
+ {!creating ? (
90
+ <button type="button" className={css.bookAdd} onClick={() => { setCreating(true) }}>
91
+ + 新书
92
+ </button>
93
+ ) : (
94
+ <div className={css.bookCreateForm}>
95
+ <input
96
+ className={css.input}
97
+ style={{ width: 140 }}
98
+ placeholder="书名"
99
+ value={name}
100
+ onChange={e => { setName(e.target.value) }}
101
+ onKeyDown={e => { if (e.key === 'Enter') void handleCreate() }}
102
+ autoFocus
103
+ />
104
+ <button type="button" className={`${css.button} ${css.buttonSmall} ${css.buttonPrimary}`} disabled={busy || name.trim() === ''} onClick={() => { void handleCreate() }}>
105
+ 创建
106
+ </button>
107
+ <button type="button" className={`${css.button} ${css.buttonSmall}`} onClick={() => { setCreating(false) }}>
108
+ 取消
109
+ </button>
110
+ </div>
111
+ )}
112
+ </div>
113
+ {error !== '' && <span style={{ color: 'var(--nf-error)', fontSize: 12 }}>{error}</span>}
114
+ </div>
115
+ )
116
+ }