aksos-react-native-epub-reader 0.0.0-stage → 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.
- package/LICENSE +21 -0
- package/README.md +338 -2
- package/lib/EpubReader.d.ts +63 -0
- package/lib/EpubReader.js +199 -0
- package/lib/EpubReaderView.d.ts +24 -0
- package/lib/EpubReaderView.js +504 -0
- package/lib/assets/page-turn-1.wav +0 -0
- package/lib/assets/page-turn-2.wav +0 -0
- package/lib/assets/page-turn-3.wav +0 -0
- package/lib/assets/page-turn-4.wav +0 -0
- package/lib/engine/html.d.ts +1 -0
- package/lib/engine/html.js +5 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +30 -0
- package/lib/sound.d.ts +1 -0
- package/lib/sound.js +71 -0
- package/lib/themes.d.ts +56 -0
- package/lib/themes.js +166 -0
- package/lib/types.d.ts +133 -0
- package/lib/types.js +2 -0
- package/lib/ui/AppearanceSheet.d.ts +15 -0
- package/lib/ui/AppearanceSheet.js +127 -0
- package/lib/ui/ContentsSheet.d.ts +27 -0
- package/lib/ui/ContentsSheet.js +87 -0
- package/lib/ui/CustomizeSheet.d.ts +16 -0
- package/lib/ui/CustomizeSheet.js +139 -0
- package/lib/ui/Glass.d.ts +15 -0
- package/lib/ui/Glass.js +27 -0
- package/lib/ui/HighlightMenu.d.ts +25 -0
- package/lib/ui/HighlightMenu.js +43 -0
- package/lib/ui/Icons.d.ts +17 -0
- package/lib/ui/Icons.js +193 -0
- package/lib/ui/LineGuide.d.ts +21 -0
- package/lib/ui/LineGuide.js +92 -0
- package/lib/ui/NoteEditor.d.ts +12 -0
- package/lib/ui/NoteEditor.js +61 -0
- package/lib/ui/Scrubber.d.ts +15 -0
- package/lib/ui/Scrubber.js +86 -0
- package/lib/ui/SearchSheet.d.ts +14 -0
- package/lib/ui/SearchSheet.js +67 -0
- package/lib/ui/Sheet.d.ts +19 -0
- package/lib/ui/Sheet.js +38 -0
- package/lib/ui/Slider.d.ts +14 -0
- package/lib/ui/Slider.js +53 -0
- package/package.json +75 -5
- package/src/EpubReader.tsx +256 -0
- package/src/EpubReaderView.tsx +721 -0
- package/src/assets/page-turn-1.wav +0 -0
- package/src/assets/page-turn-2.wav +0 -0
- package/src/assets/page-turn-3.wav +0 -0
- package/src/assets/page-turn-4.wav +0 -0
- package/src/engine/html.ts +2 -0
- package/src/engine/reader.js +1696 -0
- package/src/index.ts +6 -0
- package/src/sound.ts +66 -0
- package/src/themes.ts +188 -0
- package/src/types.ts +138 -0
- package/src/ui/AppearanceSheet.tsx +167 -0
- package/src/ui/ContentsSheet.tsx +144 -0
- package/src/ui/CustomizeSheet.tsx +189 -0
- package/src/ui/Glass.tsx +37 -0
- package/src/ui/HighlightMenu.tsx +64 -0
- package/src/ui/Icons.tsx +246 -0
- package/src/ui/LineGuide.tsx +87 -0
- package/src/ui/NoteEditor.tsx +55 -0
- package/src/ui/Scrubber.tsx +78 -0
- package/src/ui/SearchSheet.tsx +79 -0
- package/src/ui/Sheet.tsx +69 -0
- package/src/ui/Slider.tsx +30 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.NoteEditor = NoteEditor;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
function NoteEditor({ visible, quote, initial, colors, onSave, onCancel }) {
|
|
40
|
+
const [text, setText] = (0, react_1.useState)(initial);
|
|
41
|
+
(0, react_1.useEffect)(() => setText(initial), [initial, visible]);
|
|
42
|
+
return (react_1.default.createElement(react_native_1.Modal, { visible: visible, animationType: "slide", transparent: true, onRequestClose: onCancel },
|
|
43
|
+
react_1.default.createElement(react_native_1.KeyboardAvoidingView, { behavior: react_native_1.Platform.OS === 'ios' ? 'padding' : undefined, style: styles.wrap },
|
|
44
|
+
react_1.default.createElement(react_native_1.Pressable, { style: react_native_1.StyleSheet.absoluteFill, onPress: onCancel }),
|
|
45
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.card, { backgroundColor: colors.sheet }] },
|
|
46
|
+
react_1.default.createElement(react_native_1.View, { style: styles.head },
|
|
47
|
+
react_1.default.createElement(react_native_1.Pressable, { onPress: onCancel, hitSlop: 10 },
|
|
48
|
+
react_1.default.createElement(react_native_1.Text, { style: { color: colors.accent, fontSize: 17 } }, "Cancel")),
|
|
49
|
+
react_1.default.createElement(react_native_1.Text, { style: { color: colors.text, fontSize: 17, fontWeight: '600' } }, "Note"),
|
|
50
|
+
react_1.default.createElement(react_native_1.Pressable, { onPress: () => onSave(text.trim()), hitSlop: 10 },
|
|
51
|
+
react_1.default.createElement(react_native_1.Text, { style: { color: colors.accent, fontSize: 17, fontWeight: '600' } }, "Save"))),
|
|
52
|
+
react_1.default.createElement(react_native_1.Text, { numberOfLines: 3, style: [styles.quote, { color: colors.subtext, borderColor: colors.accent }] }, quote),
|
|
53
|
+
react_1.default.createElement(react_native_1.TextInput, { autoFocus: true, multiline: true, value: text, onChangeText: setText, placeholder: "Add a note", placeholderTextColor: colors.subtext, style: [styles.input, { color: colors.text, backgroundColor: colors.card }] })))));
|
|
54
|
+
}
|
|
55
|
+
const styles = react_native_1.StyleSheet.create({
|
|
56
|
+
wrap: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0.35)' },
|
|
57
|
+
card: { borderTopLeftRadius: 14, borderTopRightRadius: 14, padding: 16 },
|
|
58
|
+
head: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 12 },
|
|
59
|
+
quote: { fontSize: 14, borderStartWidth: 3, paddingStart: 10, marginBottom: 12, fontStyle: 'italic' },
|
|
60
|
+
input: { minHeight: 110, maxHeight: 220, borderRadius: 10, padding: 12, fontSize: 16, textAlignVertical: 'top' }
|
|
61
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
value: number;
|
|
4
|
+
onScrub?: (v: number) => void;
|
|
5
|
+
onComplete: (v: number) => void;
|
|
6
|
+
color: string;
|
|
7
|
+
track: string;
|
|
8
|
+
thumbColor?: string;
|
|
9
|
+
/** hide the thumb for a flat progress bar */
|
|
10
|
+
noThumb?: boolean;
|
|
11
|
+
rtl?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Minimal horizontal slider (no native dependency). */
|
|
14
|
+
export declare function Scrubber({ value, onScrub, onComplete, color, track, thumbColor, noThumb, rtl }: Props): React.JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Scrubber = Scrubber;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
/** Minimal horizontal slider (no native dependency). */
|
|
40
|
+
function Scrubber({ value, onScrub, onComplete, color, track, thumbColor, noThumb, rtl }) {
|
|
41
|
+
const [width, setWidth] = (0, react_1.useState)(1);
|
|
42
|
+
const [drag, setDrag] = (0, react_1.useState)(null);
|
|
43
|
+
const latest = (0, react_1.useRef)({ width: 1, onScrub, onComplete, rtl });
|
|
44
|
+
latest.current = { width, onScrub, onComplete, rtl };
|
|
45
|
+
const startX = (0, react_1.useRef)(0);
|
|
46
|
+
const toValue = (x) => {
|
|
47
|
+
const { width: w, rtl: r } = latest.current;
|
|
48
|
+
const v = Math.max(0, Math.min(1, x / w));
|
|
49
|
+
return r ? 1 - v : v;
|
|
50
|
+
};
|
|
51
|
+
const pan = (0, react_1.useRef)(react_native_1.PanResponder.create({
|
|
52
|
+
onStartShouldSetPanResponder: () => true,
|
|
53
|
+
onMoveShouldSetPanResponder: () => true,
|
|
54
|
+
onPanResponderTerminationRequest: () => false,
|
|
55
|
+
onPanResponderGrant: (e) => {
|
|
56
|
+
startX.current = e.nativeEvent.locationX;
|
|
57
|
+
const v = toValue(startX.current);
|
|
58
|
+
setDrag(v);
|
|
59
|
+
latest.current.onScrub?.(v);
|
|
60
|
+
},
|
|
61
|
+
onPanResponderMove: (_e, g) => {
|
|
62
|
+
const v = toValue(startX.current + g.dx);
|
|
63
|
+
setDrag(v);
|
|
64
|
+
latest.current.onScrub?.(v);
|
|
65
|
+
},
|
|
66
|
+
onPanResponderRelease: (_e, g) => {
|
|
67
|
+
const v = toValue(startX.current + g.dx);
|
|
68
|
+
setDrag(null);
|
|
69
|
+
latest.current.onComplete(v);
|
|
70
|
+
}
|
|
71
|
+
})).current;
|
|
72
|
+
const shown = drag ?? value;
|
|
73
|
+
const frac = rtl ? 1 - shown : shown;
|
|
74
|
+
return (react_1.default.createElement(react_native_1.View, { style: styles.hit, onLayout: (e) => setWidth(e.nativeEvent.layout.width), ...pan.panHandlers },
|
|
75
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.track, { backgroundColor: track }], pointerEvents: "none" },
|
|
76
|
+
react_1.default.createElement(react_native_1.View, { style: { height: 4, backgroundColor: color, width: `${frac * 100}%` } })),
|
|
77
|
+
!noThumb && (react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: [styles.thumb, { backgroundColor: thumbColor || color, left: Math.max(0, Math.min(width - 28, frac * (width - 28))) }] }))));
|
|
78
|
+
}
|
|
79
|
+
const styles = react_native_1.StyleSheet.create({
|
|
80
|
+
hit: { height: 40, justifyContent: 'center' },
|
|
81
|
+
track: { height: 4, borderRadius: 2, overflow: 'hidden', flexDirection: 'row' },
|
|
82
|
+
thumb: {
|
|
83
|
+
position: 'absolute', width: 28, height: 28, borderRadius: 14, top: 6,
|
|
84
|
+
shadowColor: '#000', shadowOpacity: 0.3, shadowRadius: 3, shadowOffset: { width: 0, height: 1 }, elevation: 3
|
|
85
|
+
}
|
|
86
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ChromeColors } from '../themes';
|
|
3
|
+
import type { SearchResult } from '../types';
|
|
4
|
+
interface Props {
|
|
5
|
+
visible: boolean;
|
|
6
|
+
colors: ChromeColors;
|
|
7
|
+
results: SearchResult[];
|
|
8
|
+
searching: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
onSearch: (query: string) => void;
|
|
11
|
+
onPick: (r: SearchResult) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function SearchSheet({ visible, colors, results, searching, onClose, onSearch, onPick }: Props): React.JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.SearchSheet = SearchSheet;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const Icons_1 = require("./Icons");
|
|
40
|
+
const Sheet_1 = require("./Sheet");
|
|
41
|
+
function SearchSheet({ visible, colors, results, searching, onClose, onSearch, onPick }) {
|
|
42
|
+
const [q, setQ] = (0, react_1.useState)('');
|
|
43
|
+
const timer = (0, react_1.useRef)(undefined);
|
|
44
|
+
(0, react_1.useEffect)(() => {
|
|
45
|
+
clearTimeout(timer.current);
|
|
46
|
+
timer.current = setTimeout(() => onSearch(q), 350);
|
|
47
|
+
return () => clearTimeout(timer.current);
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, [q]);
|
|
50
|
+
return (react_1.default.createElement(Sheet_1.Sheet, { visible: visible, colors: colors, onClose: onClose, height: "85%", title: "Search" },
|
|
51
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.field, { backgroundColor: colors.card }] },
|
|
52
|
+
react_1.default.createElement(Icons_1.Icon, { name: "search", color: colors.subtext, size: 20 }),
|
|
53
|
+
react_1.default.createElement(react_native_1.TextInput, { value: q, onChangeText: setQ, placeholder: "Search in book", placeholderTextColor: colors.subtext, style: [styles.input, { color: colors.text }], autoCorrect: false, returnKeyType: "search", onSubmitEditing: () => onSearch(q), clearButtonMode: "while-editing" })),
|
|
54
|
+
react_1.default.createElement(react_native_1.FlatList, { data: results, keyboardShouldPersistTaps: "handled", keyExtractor: (_, i) => String(i), ListHeaderComponent: q.trim().length >= 2 ? (react_1.default.createElement(react_native_1.Text, { style: [styles.count, { color: colors.subtext }] }, searching ? 'Searching...' : `${results.length}${results.length >= 500 ? '+' : ''} results`)) : null, renderItem: ({ item }) => (react_1.default.createElement(react_native_1.Pressable, { onPress: () => onPick(item), style: [styles.row, { borderColor: colors.separator }] },
|
|
55
|
+
react_1.default.createElement(react_native_1.Text, { style: [styles.chapter, { color: colors.accent }], numberOfLines: 1 }, item.chapter),
|
|
56
|
+
react_1.default.createElement(react_native_1.Text, { style: { color: colors.text, fontSize: 15, lineHeight: 21 }, numberOfLines: 3 },
|
|
57
|
+
item.before,
|
|
58
|
+
react_1.default.createElement(react_native_1.Text, { style: { fontWeight: '700', backgroundColor: 'rgba(255,214,10,0.45)' } }, item.match),
|
|
59
|
+
item.after))) })));
|
|
60
|
+
}
|
|
61
|
+
const styles = react_native_1.StyleSheet.create({
|
|
62
|
+
field: { flexDirection: 'row', alignItems: 'center', marginHorizontal: 16, marginBottom: 8, paddingHorizontal: 10, borderRadius: 10, height: 38 },
|
|
63
|
+
input: { flex: 1, marginStart: 6, fontSize: 16, paddingVertical: 0 },
|
|
64
|
+
count: { paddingHorizontal: 20, paddingVertical: 8, fontSize: 13 },
|
|
65
|
+
row: { paddingVertical: 12, paddingHorizontal: 20, borderBottomWidth: react_native_1.StyleSheet.hairlineWidth },
|
|
66
|
+
chapter: { fontSize: 12, fontWeight: '600', marginBottom: 3 }
|
|
67
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ViewStyle } from 'react-native';
|
|
3
|
+
import type { ChromeColors } from '../themes';
|
|
4
|
+
interface Props {
|
|
5
|
+
visible: boolean;
|
|
6
|
+
title?: string;
|
|
7
|
+
subtitle?: string;
|
|
8
|
+
colors: ChromeColors;
|
|
9
|
+
height?: ViewStyle['height'];
|
|
10
|
+
/** 'x' puts a glass close button on the left (Themes, Search); 'check' puts a solid check on the right (Contents, Customize) */
|
|
11
|
+
closeIcon?: 'x' | 'check';
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
/** rendered above the content, e.g. popup menus */
|
|
15
|
+
overlay?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
/** Rounded frosted-glass sheet: the book stays faintly visible behind it. */
|
|
18
|
+
export declare function Sheet({ visible, title, subtitle, colors, height, closeIcon, onClose, children, overlay }: Props): React.JSX.Element;
|
|
19
|
+
export {};
|
package/lib/ui/Sheet.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Sheet = Sheet;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
const Glass_1 = require("./Glass");
|
|
10
|
+
const Icons_1 = require("./Icons");
|
|
11
|
+
/** Rounded frosted-glass sheet: the book stays faintly visible behind it. */
|
|
12
|
+
function Sheet({ visible, title, subtitle, colors, height = '70%', closeIcon = 'x', onClose, children, overlay }) {
|
|
13
|
+
const button = closeIcon === 'check' ? (react_1.default.createElement(react_native_1.Pressable, { onPress: onClose, hitSlop: 10, style: [styles.circle, { backgroundColor: colors.dark ? '#ffffff' : '#000000' }], accessibilityRole: "button", accessibilityLabel: "Done" },
|
|
14
|
+
react_1.default.createElement(Icons_1.Icon, { name: "check", color: colors.dark ? '#000000' : '#ffffff', size: 24, strokeWidth: 2.2 }))) : (react_1.default.createElement(react_native_1.Pressable, { onPress: onClose, hitSlop: 10, accessibilityRole: "button", accessibilityLabel: "Close" },
|
|
15
|
+
react_1.default.createElement(Glass_1.Glass, { dark: colors.dark, background: colors.glass, border: colors.glassBorder, style: styles.circle },
|
|
16
|
+
react_1.default.createElement(Icons_1.Icon, { name: "close", color: colors.text, size: 22 }))));
|
|
17
|
+
return (react_1.default.createElement(react_native_1.Modal, { visible: visible, transparent: true, animationType: "slide", onRequestClose: onClose, statusBarTranslucent: true },
|
|
18
|
+
react_1.default.createElement(react_native_1.Pressable, { style: styles.backdrop, onPress: onClose }),
|
|
19
|
+
react_1.default.createElement(Glass_1.Glass, { dark: colors.dark, background: colors.sheetGlass, border: colors.glassBorder, intensity: 70, style: [styles.sheet, { height }] },
|
|
20
|
+
react_1.default.createElement(react_native_1.View, { style: styles.header },
|
|
21
|
+
closeIcon === 'x' && button,
|
|
22
|
+
react_1.default.createElement(react_native_1.View, { style: styles.titleBox, pointerEvents: "none" },
|
|
23
|
+
!!title && (react_1.default.createElement(react_native_1.Text, { style: [styles.title, { color: colors.text }], numberOfLines: 1 }, title)),
|
|
24
|
+
!!subtitle && react_1.default.createElement(react_native_1.Text, { style: [styles.subtitle, { color: colors.text }] }, subtitle)),
|
|
25
|
+
react_1.default.createElement(react_native_1.View, { style: { flex: 1 } }),
|
|
26
|
+
closeIcon === 'check' && button),
|
|
27
|
+
children,
|
|
28
|
+
overlay)));
|
|
29
|
+
}
|
|
30
|
+
const styles = react_native_1.StyleSheet.create({
|
|
31
|
+
backdrop: { flex: 1, backgroundColor: 'rgba(0,0,0,0.18)' },
|
|
32
|
+
sheet: { borderTopLeftRadius: 34, borderTopRightRadius: 34, paddingTop: 12 },
|
|
33
|
+
header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, minHeight: 52, marginBottom: 6 },
|
|
34
|
+
circle: { width: 44, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center' },
|
|
35
|
+
titleBox: { position: 'absolute', left: 70, right: 70, alignItems: 'center' },
|
|
36
|
+
title: { fontSize: 17, fontWeight: '600' },
|
|
37
|
+
subtitle: { fontSize: 17, marginTop: 14 }
|
|
38
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
value: number;
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
step: number;
|
|
7
|
+
onChange: (v: number) => void;
|
|
8
|
+
color: string;
|
|
9
|
+
track: string;
|
|
10
|
+
thumbColor?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Value slider on top of Scrubber; emits only when the stepped value changes. */
|
|
13
|
+
export declare function Slider({ value, min, max, step, onChange, color, track, thumbColor }: Props): React.JSX.Element;
|
|
14
|
+
export {};
|
package/lib/ui/Slider.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Slider = Slider;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const Scrubber_1 = require("./Scrubber");
|
|
39
|
+
const round = (v, step) => Math.round(v / step) * step;
|
|
40
|
+
/** Value slider on top of Scrubber; emits only when the stepped value changes. */
|
|
41
|
+
function Slider({ value, min, max, step, onChange, color, track, thumbColor }) {
|
|
42
|
+
const last = (0, react_1.useRef)(value);
|
|
43
|
+
const toValue = (f) => +(round(min + f * (max - min), step)).toFixed(4);
|
|
44
|
+
const emit = (f) => {
|
|
45
|
+
const v = toValue(f);
|
|
46
|
+
if (v !== last.current) {
|
|
47
|
+
last.current = v;
|
|
48
|
+
onChange(v);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
last.current = value;
|
|
52
|
+
return react_1.default.createElement(Scrubber_1.Scrubber, { value: (value - min) / (max - min), color: color, track: track, thumbColor: thumbColor, onScrub: emit, onComplete: emit });
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "aksos-react-native-epub-reader",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A complete EPUB reader for React Native and Expo: page curl and slide, themes, highlights, notes, bookmarks, search, line guide, and full right-to-left support (Pashto, Dari, Persian, Arabic, Urdu).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-native",
|
|
7
|
+
"expo",
|
|
8
|
+
"epub",
|
|
9
|
+
"ebook",
|
|
10
|
+
"reader",
|
|
11
|
+
"book",
|
|
12
|
+
"pashto",
|
|
13
|
+
"dari",
|
|
14
|
+
"persian",
|
|
15
|
+
"arabic",
|
|
16
|
+
"rtl",
|
|
17
|
+
"highlight",
|
|
18
|
+
"page-curl"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"main": "lib/index.js",
|
|
22
|
+
"types": "lib/index.d.ts",
|
|
23
|
+
"react-native": "src/index.ts",
|
|
24
|
+
"source": "src/index.ts",
|
|
25
|
+
"files": [
|
|
26
|
+
"src",
|
|
27
|
+
"lib",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build:engine": "node scripts/build-engine.js",
|
|
33
|
+
"build:lib": "node scripts/build-lib.js",
|
|
34
|
+
"typecheck": "tsc -p tsconfig.build.json --noEmit",
|
|
35
|
+
"prepublishOnly": "npm run build:engine \u0026\u0026 npm run build:lib",
|
|
36
|
+
"test:harness": "node test/serve.js"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"expo-audio": "*",
|
|
40
|
+
"expo-blur": "*",
|
|
41
|
+
"expo-screen-orientation": "*",
|
|
42
|
+
"react": "\u003e=18",
|
|
43
|
+
"react-native": "\u003e=0.73",
|
|
44
|
+
"react-native-svg": "\u003e=13",
|
|
45
|
+
"react-native-webview": "\u003e=13"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"expo-audio": {
|
|
49
|
+
"optional": true
|
|
50
|
+
},
|
|
51
|
+
"expo-blur": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"expo-screen-orientation": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/react": "^18.3.0",
|
|
60
|
+
"jszip": "3.10.1",
|
|
61
|
+
"react": "18.3.1",
|
|
62
|
+
"react-native": "0.76.5",
|
|
63
|
+
"react-native-svg": "15.9.0",
|
|
64
|
+
"react-native-webview": "13.12.5",
|
|
65
|
+
"typescript": "^5.6.0"
|
|
66
|
+
},
|
|
67
|
+
"author": "Aksos",
|
|
68
|
+
"homepage": "https://github.com/AhmadNasary/aksos-react-native-epub-reader#readme",
|
|
69
|
+
"repository": {
|
|
70
|
+
"type": "git",
|
|
71
|
+
"url": "git+https://github.com/AhmadNasary/aksos-react-native-epub-reader.git"
|
|
72
|
+
},
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/AhmadNasary/aksos-react-native-epub-reader/issues"
|
|
75
|
+
}
|
|
6
76
|
}
|