@somecat/epub-reader 0.1.1 → 0.1.3

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 (3) hide show
  1. package/README.md +87 -2
  2. package/package.json +1 -1
  3. package/style.css +87 -0
package/README.md CHANGED
@@ -17,12 +17,13 @@ import '@somecat/epub-reader/style.css'
17
17
  ## React 18+
18
18
 
19
19
  ```tsx
20
- import { useMemo, useState } from 'react'
20
+ import { useMemo, useRef, useState } from 'react'
21
21
  import { EBookReader } from '@somecat/epub-reader/react'
22
22
  import '@somecat/epub-reader/style.css'
23
23
 
24
24
  export default function Demo() {
25
25
  const [file, setFile] = useState<File | null>(null)
26
+ const ref = useRef(null)
26
27
 
27
28
  return (
28
29
  <div style={{ height: '100vh' }}>
@@ -32,13 +33,46 @@ export default function Demo() {
32
33
  onChange={(e) => setFile(e.target.files?.[0] ?? null)}
33
34
  />
34
35
  <div style={{ height: 'calc(100vh - 40px)' }}>
35
- <EBookReader file={file} />
36
+ <EBookReader ref={ref} file={file} />
36
37
  </div>
37
38
  </div>
38
39
  )
39
40
  }
40
41
  ```
41
42
 
43
+ ### Props
44
+
45
+ > `file` 与 `fileUrl` 同时传入时,优先使用 `file`。
46
+
47
+ | 参数 | 类型 | 默认值 | 说明 |
48
+ | --- | --- | --- | --- |
49
+ | file | `File \| null` | - | 直接传入本地文件(`.epub`) |
50
+ | fileUrl | `string \| null` | - | 传入 URL,组件内部下载并打开(需服务端允许跨域) |
51
+ | className | `string` | - | 根容器额外类名 |
52
+ | style | `React.CSSProperties` | - | 根容器行内样式 |
53
+ | defaultFontSize | `number` | `100` | 非受控字号初始值(百分比) |
54
+ | fontSize | `number` | - | 受控字号(百分比) |
55
+ | onFontSizeChange | `(fontSize: number) => void` | - | 字号变化回调(受控/非受控都会触发) |
56
+ | defaultDarkMode | `boolean` | `false` | 非受控暗黑模式初始值 |
57
+ | darkMode | `boolean` | - | 受控暗黑模式 |
58
+ | onDarkModeChange | `(darkMode: boolean) => void` | - | 明暗变化回调(受控/非受控都会触发) |
59
+ | enableKeyboardNav | `boolean` | `true` | 是否启用键盘左右键翻页、ESC 关闭抽屉 |
60
+ | defaultSearchOptions | `SearchOptions` | `{ matchCase:false, wholeWords:false, matchDiacritics:false }` | 搜索默认选项 |
61
+ | onReady | `(handle: EBookReaderHandle) => void` | - | Core 就绪回调(可拿到完整 handle) |
62
+ | onError | `(error: unknown) => void` | - | 错误回调(初始化/打开/搜索等) |
63
+ | onProgress | `(info: ProgressInfo) => void` | - | 阅读进度回调 |
64
+
65
+ ### Ref(命令式 API)
66
+
67
+ `ref` 暴露的方法:
68
+
69
+ - `prevPage()` / `nextPage()`
70
+ - `prevSection()` / `nextSection()`
71
+ - `goTo(target: string)`
72
+ - `goToFraction(fraction: number)`(`0 ~ 1`)
73
+ - `search(query: string, options?: SearchOptions): Promise<SearchResult[]>`
74
+ - `cancelSearch()` / `clearSearch()`
75
+
42
76
  ## Vue 3
43
77
 
44
78
  ```ts
@@ -68,7 +102,58 @@ export default defineComponent({
68
102
  })
69
103
  ```
70
104
 
105
+ ### Props
106
+
107
+ > `file` 与 `fileUrl` 同时传入时,优先使用 `file`。
108
+
109
+ | 参数 | 类型 | 默认值 | 说明 |
110
+ | --- | --- | --- | --- |
111
+ | file | `File \| null` | - | 直接传入本地文件(`.epub`) |
112
+ | fileUrl | `string \| null` | - | 传入 URL,组件内部下载并打开(需服务端允许跨域) |
113
+ | defaultFontSize | `number` | `100` | 非受控字号初始值(百分比) |
114
+ | fontSize | `number` | - | 受控字号(百分比) |
115
+ | defaultDarkMode | `boolean` | `false` | 非受控暗黑模式初始值 |
116
+ | darkMode | `boolean` | - | 受控暗黑模式 |
117
+ | enableKeyboardNav | `boolean` | `true` | 是否启用键盘左右键翻页、ESC 关闭抽屉 |
118
+ | defaultSearchOptions | `SearchOptions` | `{ matchCase:false, wholeWords:false, matchDiacritics:false }` | 搜索默认选项 |
119
+
120
+ ### Emits / v-model
121
+
122
+ - `ready(handle)` / `error(error)` / `progress(info)`
123
+ - `fontSizeChange(fontSize)` / `darkModeChange(darkMode)`
124
+ - `update:fontSize(fontSize)` / `update:darkMode(darkMode)`(用于 `v-model:fontSize`、`v-model:darkMode`)
125
+
126
+ ### Expose(命令式 API)
127
+
128
+ 组件实例暴露的方法同 React ref:
129
+
130
+ - `prevPage()` / `nextPage()`
131
+ - `prevSection()` / `nextSection()`
132
+ - `goTo(target: string)`
133
+ - `goToFraction(fraction: number)`(`0 ~ 1`)
134
+ - `search(query: string, options?: SearchOptions): Promise<SearchResult[]>`
135
+ - `cancelSearch()` / `clearSearch()`
136
+
137
+ ## 类型说明
138
+
139
+ ### SearchOptions
140
+
141
+ | 字段 | 类型 | 默认值 | 说明 |
142
+ | --- | --- | --- | --- |
143
+ | matchCase | `boolean` | `false` | 匹配大小写 |
144
+ | wholeWords | `boolean` | `false` | 全词匹配 |
145
+ | matchDiacritics | `boolean` | `false` | 匹配变音符号 |
146
+
147
+ ### ProgressInfo
148
+
149
+ | 字段 | 类型 | 说明 |
150
+ | --- | --- | --- |
151
+ | fraction | `number \| undefined` | 进度(`0 ~ 1`) |
152
+ | tocItem | `TocItem \| null \| undefined` | 当前章节信息 |
153
+ | location | `unknown` | 底层定位信息(透传) |
154
+
71
155
  ## 注意事项
72
156
 
73
157
  - 外层容器必须有明确高度(组件内部会使用 `height: calc(100% - 40px)` 给阅读区留出底部进度条)。
74
158
  - 键盘左右方向键翻页:需要组件获得焦点(点击组件区域或 Tab 聚焦)。
159
+ - 使用 `fileUrl` 时,资源需要允许浏览器跨域访问(CORS),否则下载会失败。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@somecat/epub-reader",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A cross-framework EPUB ebook reader component library based on foliate-js",
5
5
  "license": "MIT",
6
6
  "author": "SomeCat <zt@somecat.cn>",
package/style.css CHANGED
@@ -3,6 +3,11 @@
3
3
  --epub-reader-panel-fg: #1f2937;
4
4
  --epub-reader-border: rgba(0, 0, 0, 0.12);
5
5
  --epub-reader-accent: #2563eb;
6
+ --epub-reader-range-track: #e5e7eb;
7
+ --epub-reader-range-fill: #d1d5db;
8
+ --epub-reader-range-thumb-bg: #ffffff;
9
+ --epub-reader-range-thumb-fg: #111827;
10
+ --epub-reader-range-thumb-border: rgba(0, 0, 0, 0.08);
6
11
  --epub-reader-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
7
12
  --epub-reader-radius: 10px;
8
13
  --epub-reader-bottom-bar-height: 40px;
@@ -18,6 +23,11 @@
18
23
  --epub-reader-panel-fg: #e5e7eb;
19
24
  --epub-reader-border: rgba(255, 255, 255, 0.14);
20
25
  --epub-reader-accent: #60a5fa;
26
+ --epub-reader-range-track: #2a2a2a;
27
+ --epub-reader-range-fill: #3a3a3a;
28
+ --epub-reader-range-thumb-bg: #ffffff;
29
+ --epub-reader-range-thumb-fg: #111827;
30
+ --epub-reader-range-thumb-border: rgba(0, 0, 0, 0.12);
21
31
  --epub-reader-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
22
32
  }
23
33
 
@@ -109,6 +119,44 @@
109
119
  z-index: 20;
110
120
  }
111
121
 
122
+ .epub-reader__loading {
123
+ position: absolute;
124
+ inset: 0;
125
+ z-index: 80;
126
+ display: flex;
127
+ flex-direction: column;
128
+ align-items: center;
129
+ justify-content: center;
130
+ gap: 10px;
131
+ background: color-mix(in srgb, var(--epub-reader-panel-bg) 65%, transparent);
132
+ backdrop-filter: blur(6px);
133
+ }
134
+
135
+ .epub-reader__spinner {
136
+ width: 28px;
137
+ height: 28px;
138
+ border-radius: 50%;
139
+ border: 3px solid var(--epub-reader-range-track);
140
+ border-top-color: var(--epub-reader-accent);
141
+ animation: epub-reader-spin 0.9s linear infinite;
142
+ }
143
+
144
+ .epub-reader__loading-text {
145
+ font-size: 12px;
146
+ font-weight: 700;
147
+ color: var(--epub-reader-panel-fg);
148
+ letter-spacing: 0.2px;
149
+ }
150
+
151
+ @keyframes epub-reader-spin {
152
+ from {
153
+ transform: rotate(0deg);
154
+ }
155
+ to {
156
+ transform: rotate(360deg);
157
+ }
158
+ }
159
+
112
160
  .epub-reader__drawer {
113
161
  position: absolute;
114
162
  top: 0;
@@ -466,6 +514,45 @@
466
514
 
467
515
  .epub-reader__mprogress .epub-reader__range {
468
516
  width: 100%;
517
+ appearance: none;
518
+ -webkit-appearance: none;
519
+ height: 12px;
520
+ border-radius: 999px;
521
+ outline: none;
522
+ background: var(--epub-reader-range-track);
523
+ }
524
+
525
+ .epub-reader__mprogress .epub-reader__range::-webkit-slider-runnable-track {
526
+ height: 12px;
527
+ border-radius: 999px;
528
+ background: var(--epub-reader-range-track);
529
+ }
530
+
531
+ .epub-reader__mprogress .epub-reader__range::-webkit-slider-thumb {
532
+ appearance: none;
533
+ -webkit-appearance: none;
534
+ width: 22px;
535
+ height: 22px;
536
+ border-radius: 50%;
537
+ background: var(--epub-reader-range-thumb-bg);
538
+ border: 1px solid var(--epub-reader-range-thumb-border);
539
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
540
+ margin-top: -5px;
541
+ }
542
+
543
+ .epub-reader__mprogress .epub-reader__range::-moz-range-track {
544
+ height: 12px;
545
+ border-radius: 999px;
546
+ background: var(--epub-reader-range-track);
547
+ }
548
+
549
+ .epub-reader__mprogress .epub-reader__range::-moz-range-thumb {
550
+ width: 22px;
551
+ height: 22px;
552
+ border-radius: 50%;
553
+ background: var(--epub-reader-range-thumb-bg);
554
+ border: 1px solid var(--epub-reader-range-thumb-border);
555
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
469
556
  }
470
557
 
471
558
  .epub-reader__mprogress-percent {