react-native-teleflow-prompter 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Muhammet Atmaca (https://muhammetatmaca.com.tr)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # react-native-teleflow-prompter
2
+
3
+ [![npm version](https://img.shields.io/npm/v/react-native-teleflow-prompter.svg?style=flat-square)](https://www.npmjs.com/package/react-native-teleflow-prompter)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg?style=flat-square)](https://www.typescriptlang.org/)
6
+ [![React Native](https://img.shields.io/badge/React%20Native-Compatible-61dafb.svg?style=flat-square)](https://reactnative.dev/)
7
+ [![Expo](https://img.shields.io/badge/Expo-Compatible-black.svg?style=flat-square)](https://expo.dev/)
8
+
9
+ > High-performance 60 FPS teleprompter scrolling engine, Words-Per-Minute (WPM) speed calculator, speech timing math, and mirror optics transform generator for **React Native**, **Expo**, and **Web**.
10
+
11
+ Extracted from and powering the production mobile app [**TeleFlow Prompter**](https://muhammetatmaca.com.tr/apps/teleflow-prompter) by [**Muhammet Atmaca**](https://muhammetatmaca.com.tr/) ([VirelonSoft](https://www.linkedin.com/company/virelonsoft/)).
12
+
13
+ ---
14
+
15
+ ## ✨ Features
16
+
17
+ - 🏎️ **Butter-Smooth 60 FPS Scrolling**: Frame-independent delta timing via `requestAnimationFrame` preventing jitter on low-end devices.
18
+ - ⏱️ **Words-Per-Minute (WPM) Calculator**: Compute exact speech durations based on conversational, presentation, or reading speeds (120–180 WPM).
19
+ - 🪞 **Beam-Splitter Mirror Optics**: Native style transformations (`scaleX: -1`, `scaleY: -1`) for physical teleprompter glass reflection rigs.
20
+ - 🧩 **Zero Dependencies**: Pure TypeScript, ultra-lightweight (< 3 kB gzipped).
21
+ - 📱 **Universal Compatibility**: Works out of the box with React Native (Bare & Expo), React Web, Next.js, and Node.js.
22
+
23
+ ---
24
+
25
+ ## 📦 Installation
26
+
27
+ ```bash
28
+ # npm
29
+ npm install react-native-teleflow-prompter
30
+
31
+ # pnpm
32
+ pnpm add react-native-teleflow-prompter
33
+
34
+ # yarn
35
+ yarn add react-native-teleflow-prompter
36
+ ```
37
+
38
+ ---
39
+
40
+ ## 🚀 Quick Start (React Native & Expo)
41
+
42
+ ```tsx
43
+ import React, { useRef, useEffect } from 'react';
44
+ import { View, Text, ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
45
+ import { useTeleprompter, getMirrorTransform } from 'react-native-teleflow-prompter';
46
+
47
+ export default function PrompterScreen() {
48
+ const scrollViewRef = useRef<ScrollView>(null);
49
+
50
+ const script = `
51
+ Welcome to this presentation. Today we are demonstrating
52
+ the TeleFlow teleprompter engine running smoothly at 60 FPS
53
+ with automatic Words-Per-Minute speed calculation.
54
+ `;
55
+
56
+ const {
57
+ isPlaying,
58
+ scrollOffset,
59
+ progress,
60
+ elapsedSeconds,
61
+ remainingSeconds,
62
+ totalDurationSeconds,
63
+ wpm,
64
+ toggle,
65
+ reset,
66
+ setWpm,
67
+ } = useTeleprompter({
68
+ text: script,
69
+ initialWpm: 145,
70
+ contentHeight: 1200,
71
+ viewportHeight: 500,
72
+ onComplete: () => console.log('Speech finished!'),
73
+ });
74
+
75
+ // Automatically scroll to calculated pixel offset
76
+ useEffect(() => {
77
+ scrollViewRef.current?.scrollTo({ y: scrollOffset, animated: false });
78
+ }, [scrollOffset]);
79
+
80
+ return (
81
+ <View style={styles.container}>
82
+ {/* Mirror transform support for teleprompter glass rigs */}
83
+ <View style={[styles.viewport, getMirrorTransform('none')]}>
84
+ <ScrollView ref={scrollViewRef} scrollEnabled={false}>
85
+ <Text style={styles.scriptText}>{script}</Text>
86
+ </ScrollView>
87
+ </View>
88
+
89
+ {/* Controller HUD */}
90
+ <View style={styles.hud}>
91
+ <Text style={styles.timer}>
92
+ {Math.floor(elapsedSeconds / 60)}:{(elapsedSeconds % 60).toString().padStart(2, '0')} /
93
+ {Math.floor(totalDurationSeconds / 60)}:{(totalDurationSeconds % 60).toString().padStart(2, '0')}
94
+ </Text>
95
+ <Text style={styles.wpm}>{wpm} WPM ({(progress * 100).toFixed(0)}%)</Text>
96
+
97
+ <View style={styles.buttons}>
98
+ <TouchableOpacity onPress={toggle} style={styles.btn}>
99
+ <Text style={styles.btnText}>{isPlaying ? 'Pause' : 'Play'}</Text>
100
+ </TouchableOpacity>
101
+ <TouchableOpacity onPress={reset} style={styles.btn}>
102
+ <Text style={styles.btnText}>Reset</Text>
103
+ </TouchableOpacity>
104
+ <TouchableOpacity onPress={() => setWpm(wpm + 10)} style={styles.btn}>
105
+ <Text style={styles.btnText}>+10 WPM</Text>
106
+ </TouchableOpacity>
107
+ <TouchableOpacity onPress={() => setWpm(wpm - 10)} style={styles.btn}>
108
+ <Text style={styles.btnText}>-10 WPM</Text>
109
+ </TouchableOpacity>
110
+ </View>
111
+ </View>
112
+ </View>
113
+ );
114
+ }
115
+
116
+ const styles = StyleSheet.create({
117
+ container: { flex: 1, backgroundColor: '#0f172a' },
118
+ viewport: { height: 500, padding: 24 },
119
+ scriptText: { color: '#f8fafc', fontSize: 32, lineHeight: 48, fontWeight: '600' },
120
+ hud: { padding: 20, borderTopWidth: 1, borderColor: '#334155' },
121
+ timer: { color: '#38bdf8', fontSize: 20, fontWeight: 'bold' },
122
+ wpm: { color: '#94a3b8', fontSize: 14, marginBottom: 12 },
123
+ buttons: { flexDirection: 'row', gap: 10 },
124
+ btn: { backgroundColor: '#2563eb', paddingVertical: 10, paddingHorizontal: 16, borderRadius: 8 },
125
+ btnText: { color: '#ffffff', fontWeight: 'bold' },
126
+ });
127
+ ```
128
+
129
+ ---
130
+
131
+ ## 🛠️ Standalone Calculation Utilities
132
+
133
+ You can use the math utilities without React or React Native:
134
+
135
+ ```ts
136
+ import {
137
+ countWords,
138
+ calculateDuration,
139
+ calculateWpm,
140
+ calculateScrollVelocity,
141
+ getMirrorTransform,
142
+ chunkScript
143
+ } from 'react-native-teleflow-prompter';
144
+
145
+ // 1. Count words accurately
146
+ const wordCount = countWords("Hello world! Teleprompter math is easy."); // 6
147
+
148
+ // 2. Estimate speech duration (at 150 WPM)
149
+ const durationSeconds = calculateDuration(wordCount, 150); // seconds
150
+
151
+ // 3. Calculate target WPM from fixed video length (e.g., 300 words in 120s)
152
+ const targetWpm = calculateWpm(300, 120); // 150 WPM
153
+
154
+ // 4. Calculate exact scroll velocity (pixels per second)
155
+ const velocity = calculateScrollVelocity(2400, 800, 120); // px/sec
156
+
157
+ // 5. Mirror transform for hardware beam-splitter glass
158
+ const mirrorStyle = getMirrorTransform('horizontal'); // { transform: [{ scaleX: -1 }] }
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 🎙️ Words-Per-Minute (WPM) Benchmark Guide
164
+
165
+ | Speech Type | WPM Range | Typical Use Case |
166
+ | :--- | :--- | :--- |
167
+ | **Deliberate / Slow** | 100 – 125 WPM | Formal speeches, technical training, audiobooks |
168
+ | **Conversational** | 130 – 160 WPM | Video podcasts, YouTube videos, YouTube Shorts / Reels |
169
+ | **Rapid / Energetic** | 165 – 190 WPM | TV broadcast reporting, auctioneers, fast-paced marketing |
170
+
171
+ ---
172
+
173
+ ## 👨‍💻 Author & Credits
174
+
175
+ Developed with ❤️ by **[Muhammet Atmaca](https://muhammetatmaca.com.tr)**:
176
+ - 🌐 **Official Website**: [https://muhammetatmaca.com.tr](https://muhammetatmaca.com.tr)
177
+ - 📱 **TeleFlow Prompter Mobile App**: [View on Portfolio](https://muhammetatmaca.com.tr/apps/teleflow-prompter)
178
+ - 🐙 **GitHub**: [@muhammetatmaca](https://github.com/muhammetatmaca)
179
+ - 💼 **LinkedIn**: [Muhammet Atmaca](https://www.linkedin.com/in/muhammet-atmaca-857481252/)
180
+ - 🏢 **Company**: [VirelonSoft](https://www.linkedin.com/company/virelonsoft/)
181
+
182
+ ---
183
+
184
+ ## 📄 License
185
+
186
+ MIT © [Muhammet Atmaca](https://muhammetatmaca.com.tr)
@@ -0,0 +1,97 @@
1
+ /**
2
+ * react-native-teleflow-prompter
3
+ *
4
+ * High-performance 60fps teleprompter scroll engine, speech timing math,
5
+ * and mirror optics for React Native, Expo, and Web applications.
6
+ *
7
+ * Developed by Muhammet Atmaca (VirelonSoft)
8
+ * Website: https://muhammetatmaca.com.tr
9
+ * Portfolio App: TeleFlow Prompter (https://muhammetatmaca.com.tr/apps/teleflow-prompter)
10
+ * License: MIT
11
+ */
12
+ export type MirrorMode = 'none' | 'horizontal' | 'vertical' | 'both';
13
+ export interface ScriptChunk {
14
+ id: number;
15
+ text: string;
16
+ wordCount: number;
17
+ estimatedDurationSeconds: number;
18
+ }
19
+ export interface TeleprompterOptions {
20
+ /** The text content to be displayed and spoken */
21
+ text: string;
22
+ /** Initial speech speed in Words Per Minute (typical: 130 - 170 WPM) */
23
+ initialWpm?: number;
24
+ /** Total height of the scrollable content view in pixels */
25
+ contentHeight?: number;
26
+ /** Height of the visible screen/viewport in pixels */
27
+ viewportHeight?: number;
28
+ /** Auto-scroll frame rate target (default: 60) */
29
+ fps?: number;
30
+ /** Callback fired when scrolling reaches the end */
31
+ onComplete?: () => void;
32
+ }
33
+ export interface TeleprompterController {
34
+ /** Whether the prompter is currently actively scrolling */
35
+ isPlaying: boolean;
36
+ /** Progress through the text from 0.0 to 1.0 */
37
+ progress: number;
38
+ /** Calculated scroll offset in pixels */
39
+ scrollOffset: number;
40
+ /** Elapsed time in seconds */
41
+ elapsedSeconds: number;
42
+ /** Estimated remaining time in seconds */
43
+ remainingSeconds: number;
44
+ /** Total estimated speech duration in seconds */
45
+ totalDurationSeconds: number;
46
+ /** Current speech speed in words per minute */
47
+ wpm: number;
48
+ /** Total word count of the script */
49
+ wordCount: number;
50
+ /** Start scrolling */
51
+ play: () => void;
52
+ /** Pause scrolling */
53
+ pause: () => void;
54
+ /** Toggle play/pause state */
55
+ toggle: () => void;
56
+ /** Reset prompter to start (0 offset) */
57
+ reset: () => void;
58
+ /** Change speed in Words Per Minute */
59
+ setWpm: (newWpm: number) => void;
60
+ /** Seek directly to a progress position (0.0 to 1.0) */
61
+ seek: (progressRatio: number) => void;
62
+ }
63
+ /**
64
+ * Counts words accurately across multiple languages and whitespace boundaries.
65
+ */
66
+ export declare function countWords(text: string): number;
67
+ /**
68
+ * Calculates estimated speech duration in seconds based on word count and WPM.
69
+ */
70
+ export declare function calculateDuration(wordCount: number, wpm?: number): number;
71
+ /**
72
+ * Calculates the Words Per Minute rate from word count and duration.
73
+ */
74
+ export declare function calculateWpm(wordCount: number, durationSeconds: number): number;
75
+ /**
76
+ * Calculates pixel scroll velocity (pixels per second) needed to finish
77
+ * the entire content within the target duration.
78
+ */
79
+ export declare function calculateScrollVelocity(contentHeight: number, viewportHeight: number | undefined, durationSeconds: number): number;
80
+ /**
81
+ * Returns React Native compatible transform style for beam-splitter mirror optics.
82
+ * Physical teleprompter glass reflects text reversed, requiring horizontal or vertical inversion.
83
+ */
84
+ export declare function getMirrorTransform(mode?: MirrorMode): {
85
+ transform: Array<{
86
+ scaleX?: number;
87
+ scaleY?: number;
88
+ }>;
89
+ };
90
+ /**
91
+ * Splits a long script into digestible chunks with word counts and time estimates.
92
+ */
93
+ export declare function chunkScript(text: string, maxWordsPerChunk?: number): ScriptChunk[];
94
+ /**
95
+ * React Hook providing a high-precision, 60fps auto-scroll controller for teleprompters.
96
+ */
97
+ export declare function useTeleprompter(options: TeleprompterOptions): TeleprompterController;
package/dist/index.js ADDED
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * react-native-teleflow-prompter
4
+ *
5
+ * High-performance 60fps teleprompter scroll engine, speech timing math,
6
+ * and mirror optics for React Native, Expo, and Web applications.
7
+ *
8
+ * Developed by Muhammet Atmaca (VirelonSoft)
9
+ * Website: https://muhammetatmaca.com.tr
10
+ * Portfolio App: TeleFlow Prompter (https://muhammetatmaca.com.tr/apps/teleflow-prompter)
11
+ * License: MIT
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.countWords = countWords;
15
+ exports.calculateDuration = calculateDuration;
16
+ exports.calculateWpm = calculateWpm;
17
+ exports.calculateScrollVelocity = calculateScrollVelocity;
18
+ exports.getMirrorTransform = getMirrorTransform;
19
+ exports.chunkScript = chunkScript;
20
+ exports.useTeleprompter = useTeleprompter;
21
+ const react_1 = require("react");
22
+ /**
23
+ * Counts words accurately across multiple languages and whitespace boundaries.
24
+ */
25
+ function countWords(text) {
26
+ if (!text || typeof text !== 'string')
27
+ return 0;
28
+ const trimmed = text.trim();
29
+ if (!trimmed)
30
+ return 0;
31
+ return trimmed.split(/\s+/).filter(Boolean).length;
32
+ }
33
+ /**
34
+ * Calculates estimated speech duration in seconds based on word count and WPM.
35
+ */
36
+ function calculateDuration(wordCount, wpm = 140) {
37
+ if (wordCount <= 0 || wpm <= 0)
38
+ return 0;
39
+ return Math.round((wordCount / wpm) * 60);
40
+ }
41
+ /**
42
+ * Calculates the Words Per Minute rate from word count and duration.
43
+ */
44
+ function calculateWpm(wordCount, durationSeconds) {
45
+ if (wordCount <= 0 || durationSeconds <= 0)
46
+ return 0;
47
+ return Math.round((wordCount / durationSeconds) * 60);
48
+ }
49
+ /**
50
+ * Calculates pixel scroll velocity (pixels per second) needed to finish
51
+ * the entire content within the target duration.
52
+ */
53
+ function calculateScrollVelocity(contentHeight, viewportHeight = 0, durationSeconds) {
54
+ if (durationSeconds <= 0)
55
+ return 0;
56
+ const scrollableDistance = Math.max(0, contentHeight - viewportHeight);
57
+ return scrollableDistance / durationSeconds;
58
+ }
59
+ /**
60
+ * Returns React Native compatible transform style for beam-splitter mirror optics.
61
+ * Physical teleprompter glass reflects text reversed, requiring horizontal or vertical inversion.
62
+ */
63
+ function getMirrorTransform(mode = 'none') {
64
+ switch (mode) {
65
+ case 'horizontal':
66
+ return { transform: [{ scaleX: -1 }] };
67
+ case 'vertical':
68
+ return { transform: [{ scaleY: -1 }] };
69
+ case 'both':
70
+ return { transform: [{ scaleX: -1 }, { scaleY: -1 }] };
71
+ case 'none':
72
+ default:
73
+ return { transform: [{ scaleX: 1 }, { scaleY: 1 }] };
74
+ }
75
+ }
76
+ /**
77
+ * Splits a long script into digestible chunks with word counts and time estimates.
78
+ */
79
+ function chunkScript(text, maxWordsPerChunk = 40) {
80
+ if (!text)
81
+ return [];
82
+ const words = text.trim().split(/\s+/).filter(Boolean);
83
+ const chunks = [];
84
+ let currentWords = [];
85
+ for (let i = 0; i < words.length; i++) {
86
+ currentWords.push(words[i]);
87
+ const isLastWord = i === words.length - 1;
88
+ const reachedLimit = currentWords.length >= maxWordsPerChunk;
89
+ const endsWithPeriod = /[.!?]$/.test(words[i]);
90
+ if (isLastWord || (reachedLimit && endsWithPeriod) || currentWords.length >= maxWordsPerChunk * 1.5) {
91
+ const chunkText = currentWords.join(' ');
92
+ const chunkCount = currentWords.length;
93
+ chunks.push({
94
+ id: chunks.length + 1,
95
+ text: chunkText,
96
+ wordCount: chunkCount,
97
+ estimatedDurationSeconds: calculateDuration(chunkCount, 140),
98
+ });
99
+ currentWords = [];
100
+ }
101
+ }
102
+ return chunks;
103
+ }
104
+ /**
105
+ * React Hook providing a high-precision, 60fps auto-scroll controller for teleprompters.
106
+ */
107
+ function useTeleprompter(options) {
108
+ const { text, initialWpm = 140, contentHeight = 1000, viewportHeight = 400, onComplete, } = options;
109
+ const wordCount = countWords(text);
110
+ const [wpm, setWpmState] = (0, react_1.useState)(initialWpm);
111
+ const [isPlaying, setIsPlaying] = (0, react_1.useState)(false);
112
+ const [scrollOffset, setScrollOffset] = (0, react_1.useState)(0);
113
+ const totalDurationSeconds = calculateDuration(wordCount, wpm);
114
+ const scrollableDistance = Math.max(0, contentHeight - viewportHeight);
115
+ const lastFrameTimeRef = (0, react_1.useRef)(null);
116
+ const rafIdRef = (0, react_1.useRef)(null);
117
+ const onCompleteRef = (0, react_1.useRef)(onComplete);
118
+ onCompleteRef.current = onComplete;
119
+ const play = (0, react_1.useCallback)(() => {
120
+ setIsPlaying(true);
121
+ }, []);
122
+ const pause = (0, react_1.useCallback)(() => {
123
+ setIsPlaying(false);
124
+ lastFrameTimeRef.current = null;
125
+ }, []);
126
+ const toggle = (0, react_1.useCallback)(() => {
127
+ setIsPlaying((prev) => !prev);
128
+ }, []);
129
+ const reset = (0, react_1.useCallback)(() => {
130
+ setIsPlaying(false);
131
+ setScrollOffset(0);
132
+ lastFrameTimeRef.current = null;
133
+ }, []);
134
+ const setWpm = (0, react_1.useCallback)((newWpm) => {
135
+ if (newWpm > 20 && newWpm <= 400) {
136
+ setWpmState(newWpm);
137
+ }
138
+ }, []);
139
+ const seek = (0, react_1.useCallback)((progressRatio) => {
140
+ const clamped = Math.max(0, Math.min(1, progressRatio));
141
+ setScrollOffset(clamped * scrollableDistance);
142
+ }, [scrollableDistance]);
143
+ // 60 FPS animation loop
144
+ (0, react_1.useEffect)(() => {
145
+ if (!isPlaying || scrollableDistance <= 0 || totalDurationSeconds <= 0) {
146
+ if (rafIdRef.current)
147
+ cancelAnimationFrame(rafIdRef.current);
148
+ lastFrameTimeRef.current = null;
149
+ return;
150
+ }
151
+ const velocityPxPerSec = scrollableDistance / totalDurationSeconds;
152
+ const tick = (now) => {
153
+ if (lastFrameTimeRef.current === null) {
154
+ lastFrameTimeRef.current = now;
155
+ }
156
+ const deltaSeconds = (now - lastFrameTimeRef.current) / 1000;
157
+ lastFrameTimeRef.current = now;
158
+ setScrollOffset((prev) => {
159
+ const next = prev + velocityPxPerSec * deltaSeconds;
160
+ if (next >= scrollableDistance) {
161
+ setIsPlaying(false);
162
+ if (onCompleteRef.current)
163
+ onCompleteRef.current();
164
+ return scrollableDistance;
165
+ }
166
+ return next;
167
+ });
168
+ rafIdRef.current = requestAnimationFrame(tick);
169
+ };
170
+ rafIdRef.current = requestAnimationFrame(tick);
171
+ return () => {
172
+ if (rafIdRef.current)
173
+ cancelAnimationFrame(rafIdRef.current);
174
+ };
175
+ }, [isPlaying, scrollableDistance, totalDurationSeconds]);
176
+ const progress = scrollableDistance > 0 ? Math.min(1, scrollOffset / scrollableDistance) : 0;
177
+ const elapsedSeconds = Math.round(progress * totalDurationSeconds);
178
+ const remainingSeconds = Math.max(0, totalDurationSeconds - elapsedSeconds);
179
+ return {
180
+ isPlaying,
181
+ progress,
182
+ scrollOffset,
183
+ elapsedSeconds,
184
+ remainingSeconds,
185
+ totalDurationSeconds,
186
+ wpm,
187
+ wordCount,
188
+ play,
189
+ pause,
190
+ toggle,
191
+ reset,
192
+ setWpm,
193
+ seek,
194
+ };
195
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "react-native-teleflow-prompter",
3
+ "version": "1.0.0",
4
+ "description": "High-performance 60fps teleprompter scroll engine, WPM calculation, and mirror optics for React Native, Expo, and Web.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc"
15
+ },
16
+ "keywords": [
17
+ "react-native",
18
+ "expo",
19
+ "teleprompter",
20
+ "prompter",
21
+ "teleflow",
22
+ "autoscroll",
23
+ "speech-timer",
24
+ "wpm-calculator",
25
+ "mirror-optics",
26
+ "video-recording",
27
+ "muhammet-atmaca",
28
+ "virelonsoft"
29
+ ],
30
+ "author": {
31
+ "name": "Muhammet Atmaca",
32
+ "email": "muhammetatmaca79@gmail.com",
33
+ "url": "https://muhammetatmaca.com.tr"
34
+ },
35
+ "homepage": "https://muhammetatmaca.com.tr/apps/teleflow-prompter",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/muhammetatmaca/muhammet-atmaca-portfolio.git",
39
+ "directory": "packages/react-native-teleflow-prompter"
40
+ },
41
+ "bugs": {
42
+ "url": "https://muhammetatmaca.com.tr/#contact"
43
+ },
44
+ "license": "MIT",
45
+ "peerDependencies": {
46
+ "react": ">=16.8.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "react": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "@types/react": "^18.2.0 || ^19.0.0",
55
+ "typescript": "~5.9.3"
56
+ }
57
+ }