@rajeev02/camera 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.
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ /**
3
+ * @rajeev02/camera — Photo Editor
4
+ * Full photo editing: crop, rotate, adjust, draw, text, stickers, blur, frames, heal, collage
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PhotoEditorController = void 0;
8
+ exports.getCropPresets = getCropPresets;
9
+ /**
10
+ * Photo Editor Controller — manages edit state, history, undo/redo
11
+ */
12
+ class PhotoEditorController {
13
+ constructor(sourceUri) {
14
+ this.textOverlays = [];
15
+ this.stickerOverlays = [];
16
+ this.blurRegions = [];
17
+ this.drawPaths = [];
18
+ this.frame = null;
19
+ this.cropRegion = null;
20
+ this.rotation = 0; // degrees
21
+ this.flipH = false;
22
+ this.flipV = false;
23
+ this.history = [];
24
+ this.historyIndex = -1;
25
+ this.activeFilter = null;
26
+ this.listeners = new Set();
27
+ this.sourceUri = sourceUri;
28
+ this.adjustments = this.getDefaultAdjustments();
29
+ }
30
+ // ---- CROP & TRANSFORM ----
31
+ setCrop(x, y, width, height) {
32
+ this.cropRegion = { x, y, width, height };
33
+ this.addToHistory("crop", { x, y, width, height });
34
+ }
35
+ rotate(degrees) {
36
+ this.rotation = (this.rotation + degrees) % 360;
37
+ this.addToHistory("rotate", { degrees: this.rotation });
38
+ }
39
+ rotateLeft() {
40
+ this.rotate(-90);
41
+ }
42
+ rotateRight() {
43
+ this.rotate(90);
44
+ }
45
+ flipHorizontal() {
46
+ this.flipH = !this.flipH;
47
+ this.addToHistory("flip", { horizontal: true });
48
+ }
49
+ flipVertical() {
50
+ this.flipV = !this.flipV;
51
+ this.addToHistory("flip", { vertical: true });
52
+ }
53
+ straighten(degrees) {
54
+ this.rotation = Math.max(-45, Math.min(45, degrees));
55
+ this.addToHistory("rotate", { degrees });
56
+ }
57
+ setPerspective(topLeft, topRight, bottomLeft, bottomRight) {
58
+ this.addToHistory("perspective", {
59
+ topLeft,
60
+ topRight,
61
+ bottomLeft,
62
+ bottomRight,
63
+ });
64
+ }
65
+ // ---- ADJUSTMENTS ----
66
+ setAdjustment(key, value) {
67
+ this.adjustments[key] = value;
68
+ this.addToHistory("adjust", { key, value });
69
+ }
70
+ resetAdjustments() {
71
+ this.adjustments = this.getDefaultAdjustments();
72
+ }
73
+ getAdjustments() {
74
+ return { ...this.adjustments };
75
+ }
76
+ // ---- FILTER ----
77
+ applyFilter(filterId) {
78
+ this.activeFilter = filterId;
79
+ this.addToHistory("filter", { filterId });
80
+ }
81
+ removeFilter() {
82
+ this.activeFilter = null;
83
+ }
84
+ getActiveFilter() {
85
+ return this.activeFilter;
86
+ }
87
+ // ---- TEXT ----
88
+ addText(overlay) {
89
+ const id = `text_${Date.now()}`;
90
+ this.textOverlays.push({ ...overlay, id });
91
+ this.addToHistory("text", { id, action: "add" });
92
+ return id;
93
+ }
94
+ updateText(id, updates) {
95
+ const t = this.textOverlays.find((o) => o.id === id);
96
+ if (t)
97
+ Object.assign(t, updates);
98
+ }
99
+ removeText(id) {
100
+ this.textOverlays = this.textOverlays.filter((o) => o.id !== id);
101
+ }
102
+ getTextOverlays() {
103
+ return [...this.textOverlays];
104
+ }
105
+ // ---- STICKERS ----
106
+ addSticker(sticker) {
107
+ const id = `sticker_${Date.now()}`;
108
+ this.stickerOverlays.push({ ...sticker, id });
109
+ this.addToHistory("sticker", { id, action: "add" });
110
+ return id;
111
+ }
112
+ updateSticker(id, updates) {
113
+ const s = this.stickerOverlays.find((o) => o.id === id);
114
+ if (s)
115
+ Object.assign(s, updates);
116
+ }
117
+ removeSticker(id) {
118
+ this.stickerOverlays = this.stickerOverlays.filter((o) => o.id !== id);
119
+ }
120
+ getStickers() {
121
+ return [...this.stickerOverlays];
122
+ }
123
+ // ---- DRAWING ----
124
+ startDrawPath(config) {
125
+ this.drawPaths.push({ config: { ...config }, points: [] });
126
+ }
127
+ addDrawPoint(x, y) {
128
+ const current = this.drawPaths[this.drawPaths.length - 1];
129
+ if (current)
130
+ current.points.push({ x, y });
131
+ }
132
+ endDrawPath() {
133
+ this.addToHistory("draw", { pathIndex: this.drawPaths.length - 1 });
134
+ }
135
+ clearDrawing() {
136
+ this.drawPaths = [];
137
+ }
138
+ getDrawPaths() {
139
+ return [...this.drawPaths];
140
+ }
141
+ // ---- BLUR ----
142
+ addBlurRegion(region) {
143
+ const id = `blur_${Date.now()}`;
144
+ this.blurRegions.push({ ...region, id });
145
+ return id;
146
+ }
147
+ removeBlurRegion(id) {
148
+ this.blurRegions = this.blurRegions.filter((r) => r.id !== id);
149
+ }
150
+ getBlurRegions() {
151
+ return [...this.blurRegions];
152
+ }
153
+ // ---- FRAME ----
154
+ setFrame(frame) {
155
+ this.frame = frame;
156
+ }
157
+ removeFrame() {
158
+ this.frame = null;
159
+ }
160
+ getFrame() {
161
+ return this.frame;
162
+ }
163
+ // ---- HISTORY (Undo/Redo) ----
164
+ undo() {
165
+ if (this.historyIndex < 0)
166
+ return false;
167
+ this.historyIndex--;
168
+ this.emit("undo");
169
+ return true;
170
+ }
171
+ redo() {
172
+ if (this.historyIndex >= this.history.length - 1)
173
+ return false;
174
+ this.historyIndex++;
175
+ this.emit("redo");
176
+ return true;
177
+ }
178
+ canUndo() {
179
+ return this.historyIndex >= 0;
180
+ }
181
+ canRedo() {
182
+ return this.historyIndex < this.history.length - 1;
183
+ }
184
+ getHistoryCount() {
185
+ return this.history.length;
186
+ }
187
+ // ---- EXPORT ----
188
+ getEditState() {
189
+ return {
190
+ sourceUri: this.sourceUri,
191
+ adjustments: this.adjustments,
192
+ textOverlays: this.textOverlays,
193
+ stickerOverlays: this.stickerOverlays,
194
+ blurRegions: this.blurRegions,
195
+ drawPaths: this.drawPaths,
196
+ frame: this.frame,
197
+ cropRegion: this.cropRegion,
198
+ rotation: this.rotation,
199
+ flipH: this.flipH,
200
+ flipV: this.flipV,
201
+ activeFilter: this.activeFilter,
202
+ };
203
+ }
204
+ /** Reset all edits */
205
+ resetAll() {
206
+ this.adjustments = this.getDefaultAdjustments();
207
+ this.textOverlays = [];
208
+ this.stickerOverlays = [];
209
+ this.blurRegions = [];
210
+ this.drawPaths = [];
211
+ this.frame = null;
212
+ this.cropRegion = null;
213
+ this.rotation = 0;
214
+ this.flipH = false;
215
+ this.flipV = false;
216
+ this.activeFilter = null;
217
+ this.history = [];
218
+ this.historyIndex = -1;
219
+ }
220
+ on(listener) {
221
+ this.listeners.add(listener);
222
+ return () => this.listeners.delete(listener);
223
+ }
224
+ addToHistory(tool, params) {
225
+ // Remove any redo history
226
+ this.history = this.history.slice(0, this.historyIndex + 1);
227
+ this.history.push({
228
+ id: `action_${Date.now()}`,
229
+ tool: tool,
230
+ timestamp: Date.now(),
231
+ params,
232
+ });
233
+ this.historyIndex = this.history.length - 1;
234
+ }
235
+ emit(event) {
236
+ for (const l of this.listeners) {
237
+ try {
238
+ l(event);
239
+ }
240
+ catch { }
241
+ }
242
+ }
243
+ getDefaultAdjustments() {
244
+ return {
245
+ brightness: 0,
246
+ contrast: 0,
247
+ saturation: 0,
248
+ exposure: 0,
249
+ highlights: 0,
250
+ shadows: 0,
251
+ warmth: 0,
252
+ tint: 0,
253
+ sharpness: 0,
254
+ grain: 0,
255
+ vignette: 0,
256
+ clarity: 0,
257
+ fadeAmount: 0,
258
+ hue: 0,
259
+ };
260
+ }
261
+ }
262
+ exports.PhotoEditorController = PhotoEditorController;
263
+ /** Standard crop presets */
264
+ function getCropPresets() {
265
+ return [
266
+ { id: "free", label: "Free", aspectRatio: null },
267
+ { id: "original", label: "Original", aspectRatio: null },
268
+ { id: "1:1", label: "Square", aspectRatio: 1 },
269
+ { id: "4:3", label: "4:3", aspectRatio: 4 / 3 },
270
+ { id: "3:4", label: "3:4", aspectRatio: 3 / 4 },
271
+ { id: "16:9", label: "16:9", aspectRatio: 16 / 9 },
272
+ { id: "9:16", label: "9:16 (Story)", aspectRatio: 9 / 16 },
273
+ { id: "3:2", label: "3:2", aspectRatio: 3 / 2 },
274
+ { id: "2:3", label: "2:3", aspectRatio: 2 / 3 },
275
+ { id: "aadhaar", label: "Aadhaar Size", aspectRatio: 3.5 / 4.5 },
276
+ { id: "passport", label: "Passport Size", aspectRatio: 3.5 / 4.5 },
277
+ ];
278
+ }
279
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/photo-editor/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@rajeev02/camera",
3
+ "version": "0.1.0",
4
+ "description": "Advanced camera capture & photo editing — filters, crop, adjust, stickers, text, drawing, beauty mode, HDR, panorama",
5
+ "main": "lib/index.js",
6
+ "author": "Rajeev Kumar Joshi <rajeevjoshi91@gmail.com> (https://rajeev02.github.io)",
7
+ "license": "MIT",
8
+ "types": "lib/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "clean": "rm -rf lib",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "keywords": [
15
+ "react-native",
16
+ "camera",
17
+ "photo-editor",
18
+ "filters",
19
+ "capture"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Rajeev02/rajeev-sdk",
24
+ "directory": "packages/camera"
25
+ },
26
+ "homepage": "https://github.com/Rajeev02/rajeev-sdk#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/Rajeev02/rajeev-sdk/issues"
29
+ },
30
+ "files": [
31
+ "lib/",
32
+ "src/",
33
+ "README.md"
34
+ ],
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "peerDependencies": {
39
+ "react": ">=18.3.0",
40
+ "react-native": ">=0.84.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react-native": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "devDependencies": {
48
+ "@types/react": "^19.0.0",
49
+ "typescript": "^5.4.0"
50
+ }
51
+ }
@@ -0,0 +1,334 @@
1
+ /**
2
+ * @rajeev02/camera — Capture Module
3
+ * Full camera abstraction: photo, video, HDR, panorama, timer, burst, night mode
4
+ */
5
+
6
+ export type CameraFacing = "front" | "back";
7
+ export type FlashMode = "off" | "on" | "auto" | "torch";
8
+ export type CaptureMode =
9
+ | "photo"
10
+ | "video"
11
+ | "portrait"
12
+ | "panorama"
13
+ | "night"
14
+ | "burst"
15
+ | "timelapse"
16
+ | "slow_motion"
17
+ | "document";
18
+ export type AspectRatio = "1:1" | "4:3" | "16:9" | "3:2" | "full";
19
+ export type GridType =
20
+ | "none"
21
+ | "rule_of_thirds"
22
+ | "golden_ratio"
23
+ | "square"
24
+ | "crosshair";
25
+
26
+ export interface CameraConfig {
27
+ facing: CameraFacing;
28
+ flash: FlashMode;
29
+ mode: CaptureMode;
30
+ aspectRatio: AspectRatio;
31
+ grid: GridType;
32
+ /** Enable HDR (High Dynamic Range) */
33
+ hdr: boolean;
34
+ /** Enable image stabilization */
35
+ stabilization: boolean;
36
+ /** Timer delay in seconds (0 = no timer) */
37
+ timerSeconds: number;
38
+ /** Zoom level (1.0 = no zoom) */
39
+ zoom: number;
40
+ /** Max zoom level */
41
+ maxZoom: number;
42
+ /** Photo quality (0-100) */
43
+ photoQuality: number;
44
+ /** Video resolution */
45
+ videoResolution: VideoResolution;
46
+ /** Video frame rate */
47
+ videoFps: number;
48
+ /** Enable location tagging */
49
+ geoTag: boolean;
50
+ /** Enable sound on capture */
51
+ shutterSound: boolean;
52
+ /** Enable beauty/face enhancement mode */
53
+ beautyMode: boolean;
54
+ /** Beauty mode intensity (0-100) */
55
+ beautyIntensity: number;
56
+ /** Watermark text (e.g., timestamp, custom text) */
57
+ watermark?: string;
58
+ /** Mirror front camera preview */
59
+ mirrorFrontCamera: boolean;
60
+ }
61
+
62
+ export type VideoResolution = "480p" | "720p" | "1080p" | "2K" | "4K";
63
+
64
+ export interface CapturedMedia {
65
+ id: string;
66
+ uri: string;
67
+ type: "photo" | "video";
68
+ width: number;
69
+ height: number;
70
+ /** File size in bytes */
71
+ sizeBytes: number;
72
+ /** MIME type */
73
+ mimeType: string;
74
+ /** Duration in ms (video only) */
75
+ durationMs?: number;
76
+ /** Thumbnail URI (video) */
77
+ thumbnailUri?: string;
78
+ /** EXIF metadata */
79
+ exif?: ExifData;
80
+ /** Timestamp */
81
+ capturedAt: number;
82
+ }
83
+
84
+ export interface ExifData {
85
+ make?: string;
86
+ model?: string;
87
+ dateTime?: string;
88
+ gpsLatitude?: number;
89
+ gpsLongitude?: number;
90
+ focalLength?: number;
91
+ exposureTime?: string;
92
+ iso?: number;
93
+ aperture?: number;
94
+ flash?: boolean;
95
+ orientation?: number;
96
+ }
97
+
98
+ export interface FocusPoint {
99
+ x: number; // 0-1 normalized
100
+ y: number;
101
+ autoExposure: boolean;
102
+ }
103
+
104
+ export interface CameraCapabilities {
105
+ hasFlash: boolean;
106
+ hasFrontCamera: boolean;
107
+ hasBackCamera: boolean;
108
+ maxZoom: number;
109
+ supportedModes: CaptureMode[];
110
+ supportedResolutions: VideoResolution[];
111
+ supportedFps: number[];
112
+ supportsHdr: boolean;
113
+ supportsNightMode: boolean;
114
+ supportsPortrait: boolean;
115
+ supportsPanorama: boolean;
116
+ supportsSlowMotion: boolean;
117
+ supportsTimelapse: boolean;
118
+ supportsBeautyMode: boolean;
119
+ supportsOpticalZoom: boolean;
120
+ supportedAspectRatios: AspectRatio[];
121
+ }
122
+
123
+ /**
124
+ * Camera Controller — manages camera state, capture, and settings
125
+ */
126
+ export class CameraController {
127
+ private config: CameraConfig;
128
+ private isRecording: boolean = false;
129
+ private recordingStartTime: number = 0;
130
+ private capturedMedia: CapturedMedia[] = [];
131
+ private listeners: Set<(event: CameraEvent) => void> = new Set();
132
+
133
+ constructor(config?: Partial<CameraConfig>) {
134
+ this.config = {
135
+ facing: "back",
136
+ flash: "auto",
137
+ mode: "photo",
138
+ aspectRatio: "4:3",
139
+ grid: "rule_of_thirds",
140
+ hdr: false,
141
+ stabilization: true,
142
+ timerSeconds: 0,
143
+ zoom: 1.0,
144
+ maxZoom: 10.0,
145
+ photoQuality: 90,
146
+ videoResolution: "1080p",
147
+ videoFps: 30,
148
+ geoTag: false,
149
+ shutterSound: true,
150
+ beautyMode: false,
151
+ beautyIntensity: 50,
152
+ mirrorFrontCamera: true,
153
+ ...config,
154
+ };
155
+ }
156
+
157
+ /** Switch between front and back camera */
158
+ flipCamera(): void {
159
+ this.config.facing = this.config.facing === "front" ? "back" : "front";
160
+ this.emit({ type: "camera_flipped", facing: this.config.facing });
161
+ }
162
+
163
+ /** Set capture mode */
164
+ setMode(mode: CaptureMode): void {
165
+ this.config.mode = mode;
166
+ this.emit({ type: "mode_changed", mode });
167
+ }
168
+
169
+ /** Set flash mode */
170
+ setFlash(mode: FlashMode): void {
171
+ this.config.flash = mode;
172
+ }
173
+
174
+ /** Cycle flash mode: off → on → auto */
175
+ cycleFlash(): FlashMode {
176
+ const cycle: FlashMode[] = ["off", "on", "auto"];
177
+ const idx = (cycle.indexOf(this.config.flash) + 1) % cycle.length;
178
+ this.config.flash = cycle[idx];
179
+ return this.config.flash;
180
+ }
181
+
182
+ /** Set zoom level */
183
+ setZoom(zoom: number): void {
184
+ this.config.zoom = Math.max(1.0, Math.min(zoom, this.config.maxZoom));
185
+ }
186
+
187
+ /** Set focus point (tap to focus) */
188
+ setFocusPoint(point: FocusPoint): void {
189
+ this.emit({ type: "focus_set", point });
190
+ }
191
+
192
+ /** Set aspect ratio */
193
+ setAspectRatio(ratio: AspectRatio): void {
194
+ this.config.aspectRatio = ratio;
195
+ }
196
+
197
+ /** Set grid overlay */
198
+ setGrid(grid: GridType): void {
199
+ this.config.grid = grid;
200
+ }
201
+
202
+ /** Toggle HDR */
203
+ toggleHdr(): boolean {
204
+ this.config.hdr = !this.config.hdr;
205
+ return this.config.hdr;
206
+ }
207
+
208
+ /** Toggle beauty mode */
209
+ toggleBeautyMode(): boolean {
210
+ this.config.beautyMode = !this.config.beautyMode;
211
+ return this.config.beautyMode;
212
+ }
213
+
214
+ /** Set beauty intensity */
215
+ setBeautyIntensity(intensity: number): void {
216
+ this.config.beautyIntensity = Math.max(0, Math.min(100, intensity));
217
+ }
218
+
219
+ /** Set timer delay */
220
+ setTimer(seconds: number): void {
221
+ this.config.timerSeconds = seconds;
222
+ }
223
+
224
+ /** Cycle timer: 0 → 3 → 5 → 10 → 0 */
225
+ cycleTimer(): number {
226
+ const cycle = [0, 3, 5, 10];
227
+ const idx = (cycle.indexOf(this.config.timerSeconds) + 1) % cycle.length;
228
+ this.config.timerSeconds = cycle[idx];
229
+ return this.config.timerSeconds;
230
+ }
231
+
232
+ /** Capture a photo (returns mock; native layer does actual capture) */
233
+ capturePhoto(): string {
234
+ const id = `photo_${Date.now()}`;
235
+ this.emit({ type: "capture_started", mediaType: "photo" });
236
+ // Native layer would capture and call onPhotoCaptured
237
+ return id;
238
+ }
239
+
240
+ /** Start video recording */
241
+ startRecording(): void {
242
+ if (this.isRecording) return;
243
+ this.isRecording = true;
244
+ this.recordingStartTime = Date.now();
245
+ this.emit({ type: "recording_started" });
246
+ }
247
+
248
+ /** Stop video recording */
249
+ stopRecording(): void {
250
+ if (!this.isRecording) return;
251
+ this.isRecording = false;
252
+ const durationMs = Date.now() - this.recordingStartTime;
253
+ this.emit({ type: "recording_stopped", durationMs });
254
+ }
255
+
256
+ /** Called by native layer when media is captured */
257
+ onMediaCaptured(media: CapturedMedia): void {
258
+ this.capturedMedia.push(media);
259
+ this.emit({ type: "media_captured", media });
260
+ }
261
+
262
+ /** Get recording state */
263
+ getIsRecording(): boolean {
264
+ return this.isRecording;
265
+ }
266
+
267
+ /** Get recording duration */
268
+ getRecordingDurationMs(): number {
269
+ if (!this.isRecording) return 0;
270
+ return Date.now() - this.recordingStartTime;
271
+ }
272
+
273
+ /** Get current config */
274
+ getConfig(): CameraConfig {
275
+ return { ...this.config };
276
+ }
277
+
278
+ /** Get captured media gallery */
279
+ getCapturedMedia(): CapturedMedia[] {
280
+ return [...this.capturedMedia];
281
+ }
282
+
283
+ /** Subscribe to camera events */
284
+ on(listener: (event: CameraEvent) => void): () => void {
285
+ this.listeners.add(listener);
286
+ return () => this.listeners.delete(listener);
287
+ }
288
+
289
+ /** Get default capabilities (native layer overrides) */
290
+ static getDefaultCapabilities(): CameraCapabilities {
291
+ return {
292
+ hasFlash: true,
293
+ hasFrontCamera: true,
294
+ hasBackCamera: true,
295
+ maxZoom: 10,
296
+ supportedModes: [
297
+ "photo",
298
+ "video",
299
+ "portrait",
300
+ "panorama",
301
+ "night",
302
+ "document",
303
+ ],
304
+ supportedResolutions: ["480p", "720p", "1080p", "4K"],
305
+ supportedFps: [24, 30, 60, 120, 240],
306
+ supportsHdr: true,
307
+ supportsNightMode: true,
308
+ supportsPortrait: true,
309
+ supportsPanorama: true,
310
+ supportsSlowMotion: true,
311
+ supportsTimelapse: true,
312
+ supportsBeautyMode: true,
313
+ supportsOpticalZoom: false,
314
+ supportedAspectRatios: ["1:1", "4:3", "16:9", "3:2", "full"],
315
+ };
316
+ }
317
+
318
+ private emit(event: CameraEvent): void {
319
+ for (const l of this.listeners) {
320
+ try {
321
+ l(event);
322
+ } catch {}
323
+ }
324
+ }
325
+ }
326
+
327
+ export type CameraEvent =
328
+ | { type: "camera_flipped"; facing: CameraFacing }
329
+ | { type: "mode_changed"; mode: CaptureMode }
330
+ | { type: "focus_set"; point: FocusPoint }
331
+ | { type: "capture_started"; mediaType: "photo" | "video" }
332
+ | { type: "recording_started" }
333
+ | { type: "recording_stopped"; durationMs: number }
334
+ | { type: "media_captured"; media: CapturedMedia };