@papyrus-sdk/core 0.2.14 → 0.2.15-beta.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { DocumentEngine, DocumentLoadInput, TextItem, TextSelection, OutlineItem, PageDestination, ViewMode, UITheme, PageTheme, Locale, SearchResult, Annotation, PapyrusConfig, PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';
1
+ import { DocumentEngine, DocumentLoadInput, TextItem, TextSelection, OutlineItem, PageDestination, ViewMode, UITheme, PageTheme, Locale, SearchResult, Annotation, ReadingMode, ActiveSurface, DocumentLocation, CapabilityState, MobilePrimaryDestination, PapyrusConfig, PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';
2
2
  import * as zustand from 'zustand';
3
3
 
4
4
  declare abstract class BaseDocumentEngine implements DocumentEngine {
@@ -40,6 +40,9 @@ interface ViewerState {
40
40
  locale: Locale;
41
41
  accentColor: string;
42
42
  annotationColor: string;
43
+ annotationOpacity: number;
44
+ inkStrokeWidth: number;
45
+ activeDrawToolPreset: "ink" | "highlight" | "underline";
43
46
  outline: OutlineItem[];
44
47
  sidebarLeftOpen: boolean;
45
48
  sidebarLeftTab: "thumbnails" | "summary";
@@ -57,6 +60,22 @@ interface ViewerState {
57
60
  selectionActive: boolean;
58
61
  toolDockOpen: boolean;
59
62
  mobileChromeVisible: boolean;
63
+ readingMode: ReadingMode;
64
+ activeSurface: ActiveSurface;
65
+ documentLocation: DocumentLocation;
66
+ capabilityState: CapabilityState;
67
+ activeMobileDestination: MobilePrimaryDestination;
68
+ mobileKeyboardOpen: boolean;
69
+ mobileDockVisible: boolean;
70
+ mobileProgressPillVisible: boolean;
71
+ annotationUndoStack: Array<{
72
+ annotations: Annotation[];
73
+ selectedAnnotationId: string | null;
74
+ }>;
75
+ annotationRedoStack: Array<{
76
+ annotations: Annotation[];
77
+ selectedAnnotationId: string | null;
78
+ }>;
60
79
  initializeStore: (config: PapyrusConfig) => void;
61
80
  setDocumentState: (state: Partial<ViewerState>) => void;
62
81
  toggleSidebarLeft: () => void;
@@ -73,9 +92,20 @@ interface ViewerState {
73
92
  prevSearchResult: () => void;
74
93
  triggerScrollToPage: (pageIndex: number) => void;
75
94
  setAnnotationColor: (color: string) => void;
95
+ setAnnotationOpacity: (opacity: number) => void;
96
+ setInkStrokeWidth: (width: number) => void;
97
+ undoAnnotations: () => void;
98
+ redoAnnotations: () => void;
76
99
  setInteractionMode: (mode: "pan" | "select") => void;
77
100
  setSelectionActive: (active: boolean) => void;
78
101
  setAccentColor: (color: string) => void;
102
+ openActiveSurface: (surface: Exclude<ActiveSurface, "none">) => void;
103
+ closeActiveSurface: () => void;
104
+ setDocumentLocation: (location: DocumentLocation) => void;
105
+ setCapabilityState: (capabilityState: CapabilityState) => void;
106
+ openMobileDestination: (destination: MobilePrimaryDestination) => void;
107
+ closeMobileDestination: () => void;
108
+ setMobileKeyboardOpen: (open: boolean) => void;
79
109
  }
80
110
  declare const useViewerStore: zustand.UseBoundStore<zustand.StoreApi<ViewerState>>;
81
111
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DocumentEngine, DocumentLoadInput, TextItem, TextSelection, OutlineItem, PageDestination, ViewMode, UITheme, PageTheme, Locale, SearchResult, Annotation, PapyrusConfig, PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';
1
+ import { DocumentEngine, DocumentLoadInput, TextItem, TextSelection, OutlineItem, PageDestination, ViewMode, UITheme, PageTheme, Locale, SearchResult, Annotation, ReadingMode, ActiveSurface, DocumentLocation, CapabilityState, MobilePrimaryDestination, PapyrusConfig, PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';
2
2
  import * as zustand from 'zustand';
3
3
 
4
4
  declare abstract class BaseDocumentEngine implements DocumentEngine {
@@ -40,6 +40,9 @@ interface ViewerState {
40
40
  locale: Locale;
41
41
  accentColor: string;
42
42
  annotationColor: string;
43
+ annotationOpacity: number;
44
+ inkStrokeWidth: number;
45
+ activeDrawToolPreset: "ink" | "highlight" | "underline";
43
46
  outline: OutlineItem[];
44
47
  sidebarLeftOpen: boolean;
45
48
  sidebarLeftTab: "thumbnails" | "summary";
@@ -57,6 +60,22 @@ interface ViewerState {
57
60
  selectionActive: boolean;
58
61
  toolDockOpen: boolean;
59
62
  mobileChromeVisible: boolean;
63
+ readingMode: ReadingMode;
64
+ activeSurface: ActiveSurface;
65
+ documentLocation: DocumentLocation;
66
+ capabilityState: CapabilityState;
67
+ activeMobileDestination: MobilePrimaryDestination;
68
+ mobileKeyboardOpen: boolean;
69
+ mobileDockVisible: boolean;
70
+ mobileProgressPillVisible: boolean;
71
+ annotationUndoStack: Array<{
72
+ annotations: Annotation[];
73
+ selectedAnnotationId: string | null;
74
+ }>;
75
+ annotationRedoStack: Array<{
76
+ annotations: Annotation[];
77
+ selectedAnnotationId: string | null;
78
+ }>;
60
79
  initializeStore: (config: PapyrusConfig) => void;
61
80
  setDocumentState: (state: Partial<ViewerState>) => void;
62
81
  toggleSidebarLeft: () => void;
@@ -73,9 +92,20 @@ interface ViewerState {
73
92
  prevSearchResult: () => void;
74
93
  triggerScrollToPage: (pageIndex: number) => void;
75
94
  setAnnotationColor: (color: string) => void;
95
+ setAnnotationOpacity: (opacity: number) => void;
96
+ setInkStrokeWidth: (width: number) => void;
97
+ undoAnnotations: () => void;
98
+ redoAnnotations: () => void;
76
99
  setInteractionMode: (mode: "pan" | "select") => void;
77
100
  setSelectionActive: (active: boolean) => void;
78
101
  setAccentColor: (color: string) => void;
102
+ openActiveSurface: (surface: Exclude<ActiveSurface, "none">) => void;
103
+ closeActiveSurface: () => void;
104
+ setDocumentLocation: (location: DocumentLocation) => void;
105
+ setCapabilityState: (capabilityState: CapabilityState) => void;
106
+ openMobileDestination: (destination: MobilePrimaryDestination) => void;
107
+ closeMobileDestination: () => void;
108
+ setMobileKeyboardOpen: (open: boolean) => void;
79
109
  }
80
110
  declare const useViewerStore: zustand.UseBoundStore<zustand.StoreApi<ViewerState>>;
81
111
 
package/dist/index.js CHANGED
@@ -76,6 +76,11 @@ var logStorePerf = (event, payload) => {
76
76
  };
77
77
  var setDocumentStateWindowStart = 0;
78
78
  var setDocumentStateCallsInWindow = 0;
79
+ var getDefaultCapabilityState = () => ({
80
+ status: "unknown",
81
+ values: {},
82
+ errors: []
83
+ });
79
84
  var getDefaultViewerState = () => ({
80
85
  isLoaded: false,
81
86
  pageCount: 0,
@@ -88,6 +93,8 @@ var getDefaultViewerState = () => ({
88
93
  locale: "en",
89
94
  accentColor: "#2563eb",
90
95
  annotationColor: "#fbbf24",
96
+ annotationOpacity: 1,
97
+ inkStrokeWidth: 6e-3,
91
98
  outline: [],
92
99
  sidebarLeftOpen: true,
93
100
  sidebarLeftTab: "thumbnails",
@@ -100,12 +107,40 @@ var getDefaultViewerState = () => ({
100
107
  scrollToPageSignal: null,
101
108
  annotations: [],
102
109
  activeTool: "select",
110
+ activeDrawToolPreset: "ink",
103
111
  selectedAnnotationId: null,
104
112
  interactionMode: "pan",
105
113
  selectionActive: false,
106
114
  toolDockOpen: false,
107
- mobileChromeVisible: true
115
+ mobileChromeVisible: true,
116
+ readingMode: "focus",
117
+ activeSurface: "none",
118
+ documentLocation: {
119
+ kind: "page",
120
+ label: "1/0",
121
+ primaryValue: 1,
122
+ secondaryValue: 0
123
+ },
124
+ capabilityState: getDefaultCapabilityState(),
125
+ activeMobileDestination: "none",
126
+ mobileKeyboardOpen: false,
127
+ mobileDockVisible: true,
128
+ mobileProgressPillVisible: true,
129
+ annotationUndoStack: [],
130
+ annotationRedoStack: []
108
131
  });
132
+ var deriveMobileShellState = ({
133
+ activeMobileDestination,
134
+ mobileKeyboardOpen
135
+ }) => {
136
+ const keyboardOwnsSurface = mobileKeyboardOpen && activeMobileDestination === "search";
137
+ return {
138
+ activeMobileDestination,
139
+ mobileKeyboardOpen,
140
+ mobileDockVisible: !keyboardOwnsSurface,
141
+ mobileProgressPillVisible: !keyboardOwnsSurface
142
+ };
143
+ };
109
144
  var useViewerStore = (0, import_zustand.create)((set, get) => ({
110
145
  ...getDefaultViewerState(),
111
146
  initializeStore: (config) => set(() => {
@@ -121,6 +156,8 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
121
156
  locale: config.initialLocale ?? defaults.locale,
122
157
  accentColor: config.initialAccentColor ?? defaults.accentColor,
123
158
  annotations: config.initialAnnotations ?? defaults.annotations,
159
+ annotationUndoStack: defaults.annotationUndoStack,
160
+ annotationRedoStack: defaults.annotationRedoStack,
124
161
  sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,
125
162
  sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen
126
163
  };
@@ -143,7 +180,19 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
143
180
  }
144
181
  const oldPage = get().currentPage;
145
182
  const oldZoom = get().zoom;
146
- set((prev) => ({ ...prev, ...state }));
183
+ set((prev) => {
184
+ const nextState = { ...prev, ...state };
185
+ if (state.activeMobileDestination !== void 0 || state.mobileKeyboardOpen !== void 0) {
186
+ Object.assign(
187
+ nextState,
188
+ deriveMobileShellState({
189
+ activeMobileDestination: nextState.activeMobileDestination,
190
+ mobileKeyboardOpen: nextState.mobileKeyboardOpen
191
+ })
192
+ );
193
+ }
194
+ return nextState;
195
+ });
147
196
  if (state.currentPage !== void 0 && state.currentPage !== oldPage) {
148
197
  papyrusEvents.emit(import_types.PapyrusEventType.PAGE_CHANGED, {
149
198
  pageNumber: state.currentPage
@@ -166,9 +215,19 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
166
215
  sidebarRightTab: tab || state.sidebarRightTab
167
216
  })),
168
217
  setAnnotationColor: (color) => set({ annotationColor: color }),
218
+ setAnnotationOpacity: (opacity) => set({ annotationOpacity: Math.min(1, Math.max(0.1, opacity)) }),
219
+ setInkStrokeWidth: (width) => set({ inkStrokeWidth: Math.min(0.02, Math.max(25e-4, width)) }),
169
220
  addAnnotation: (ann) => {
170
221
  const shouldAutoSelect = ann.type === "text" || ann.type === "comment";
171
222
  set((state) => ({
223
+ annotationUndoStack: [
224
+ ...state.annotationUndoStack,
225
+ {
226
+ annotations: state.annotations,
227
+ selectedAnnotationId: state.selectedAnnotationId
228
+ }
229
+ ].slice(-50),
230
+ annotationRedoStack: [],
172
231
  annotations: [...state.annotations, ann],
173
232
  selectedAnnotationId: shouldAutoSelect ? ann.id : state.selectedAnnotationId
174
233
  }));
@@ -179,6 +238,14 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
179
238
  updateAnnotation: (id, updates) => {
180
239
  let updatedAnnotation = null;
181
240
  set((state) => ({
241
+ annotationUndoStack: [
242
+ ...state.annotationUndoStack,
243
+ {
244
+ annotations: state.annotations,
245
+ selectedAnnotationId: state.selectedAnnotationId
246
+ }
247
+ ].slice(-50),
248
+ annotationRedoStack: [],
182
249
  annotations: state.annotations.map((a) => {
183
250
  if (a.id !== id) return a;
184
251
  updatedAnnotation = {
@@ -230,6 +297,14 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
230
297
  },
231
298
  removeAnnotation: (id) => {
232
299
  set((state) => ({
300
+ annotationUndoStack: [
301
+ ...state.annotationUndoStack,
302
+ {
303
+ annotations: state.annotations,
304
+ selectedAnnotationId: state.selectedAnnotationId
305
+ }
306
+ ].slice(-50),
307
+ annotationRedoStack: [],
233
308
  annotations: state.annotations.filter((a) => a.id !== id),
234
309
  selectedAnnotationId: state.selectedAnnotationId === id ? null : state.selectedAnnotationId
235
310
  }));
@@ -237,10 +312,73 @@ var useViewerStore = (0, import_zustand.create)((set, get) => ({
237
312
  annotationId: id
238
313
  });
239
314
  },
315
+ undoAnnotations: () => {
316
+ const state = get();
317
+ const previous = state.annotationUndoStack[state.annotationUndoStack.length - 1];
318
+ if (!previous) return;
319
+ set({
320
+ annotations: previous.annotations,
321
+ selectedAnnotationId: previous.selectedAnnotationId,
322
+ annotationUndoStack: state.annotationUndoStack.slice(0, -1),
323
+ annotationRedoStack: [
324
+ ...state.annotationRedoStack,
325
+ {
326
+ annotations: state.annotations,
327
+ selectedAnnotationId: state.selectedAnnotationId
328
+ }
329
+ ].slice(-50)
330
+ });
331
+ },
332
+ redoAnnotations: () => {
333
+ const state = get();
334
+ const next = state.annotationRedoStack[state.annotationRedoStack.length - 1];
335
+ if (!next) return;
336
+ set({
337
+ annotations: next.annotations,
338
+ selectedAnnotationId: next.selectedAnnotationId,
339
+ annotationRedoStack: state.annotationRedoStack.slice(0, -1),
340
+ annotationUndoStack: [
341
+ ...state.annotationUndoStack,
342
+ {
343
+ annotations: state.annotations,
344
+ selectedAnnotationId: state.selectedAnnotationId
345
+ }
346
+ ].slice(-50)
347
+ });
348
+ },
240
349
  setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),
241
350
  setInteractionMode: (mode) => set({ interactionMode: mode }),
242
351
  setSelectionActive: (active) => set({ selectionActive: active }),
243
352
  setAccentColor: (color) => set({ accentColor: color }),
353
+ openActiveSurface: (surface) => set({
354
+ activeSurface: surface,
355
+ readingMode: "modalSurfaceOpen",
356
+ mobileChromeVisible: true
357
+ }),
358
+ closeActiveSurface: () => set({
359
+ activeSurface: "none",
360
+ readingMode: "controlsVisible"
361
+ }),
362
+ setDocumentLocation: (location) => set({ documentLocation: location }),
363
+ setCapabilityState: (capabilityState) => set({ capabilityState }),
364
+ openMobileDestination: (destination) => set((state) => ({
365
+ ...deriveMobileShellState({
366
+ activeMobileDestination: destination,
367
+ mobileKeyboardOpen: state.mobileKeyboardOpen
368
+ })
369
+ })),
370
+ closeMobileDestination: () => set((state) => ({
371
+ ...deriveMobileShellState({
372
+ activeMobileDestination: "none",
373
+ mobileKeyboardOpen: state.mobileKeyboardOpen
374
+ })
375
+ })),
376
+ setMobileKeyboardOpen: (open) => set((state) => ({
377
+ ...deriveMobileShellState({
378
+ activeMobileDestination: state.activeMobileDestination,
379
+ mobileKeyboardOpen: open
380
+ })
381
+ })),
244
382
  setSearch: (query, results) => {
245
383
  set({
246
384
  searchQuery: query,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../engine.ts","../store.ts","../services/event-emitter.ts","../services/search-service.ts"],"sourcesContent":["\nexport * from './engine';\nexport * from './store';\nexport * from './services/search-service';\nexport * from './services/event-emitter';\n","\r\nimport { DocumentEngine, TextItem, OutlineItem, DocumentLoadInput, TextSelection, PageDestination } from '@papyrus-sdk/types';\r\n\r\nexport abstract class BaseDocumentEngine implements DocumentEngine {\r\n abstract load(source: DocumentLoadInput): Promise<void>;\r\n abstract getPageCount(): number;\r\n abstract getCurrentPage(): number;\r\n abstract goToPage(page: number): void;\r\n abstract setZoom(zoom: number): void;\r\n abstract getZoom(): number;\r\n abstract rotate(direction: 'clockwise' | 'counterclockwise'): void;\r\n abstract getRotation(): number;\r\n abstract renderPage(pageIndex: number, target: any, scale: number): Promise<void>;\r\n abstract renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;\r\n abstract getTextContent(pageIndex: number): Promise<TextItem[]>;\r\n abstract getPageDimensions(pageIndex: number): Promise<{ width: number, height: number }>;\r\n abstract selectText(pageIndex: number, rect: { x: number; y: number; width: number; height: number }): Promise<TextSelection | null>;\r\n abstract getOutline(): Promise<OutlineItem[]>;\r\n abstract getPageIndex(dest: PageDestination): Promise<number | null>;\r\n abstract destroy(): void;\r\n}\r\n","import { create } from \"zustand\";\nimport {\n ViewMode,\n Annotation,\n AnnotationReply,\n SearchResult,\n UITheme,\n PageTheme,\n OutlineItem,\n PapyrusEventType,\n PapyrusConfig,\n Locale,\n} from \"@papyrus-sdk/types\";\nimport { papyrusEvents } from \"./services/event-emitter\";\n\nconst perfNow = () =>\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? performance.now()\n : Date.now();\n\nconst isMobilePerfEnabled = () => {\n const perfGlobal = (globalThis as Record<string, unknown>)\n .__PAPYRUS_MOBILE_PERF__;\n if (perfGlobal === true) return true;\n if (!perfGlobal || typeof perfGlobal !== \"object\") return false;\n return (perfGlobal as { enabled?: boolean }).enabled ?? true;\n};\n\nconst logStorePerf = (event: string, payload: Record<string, unknown>) => {\n if (!isMobilePerfEnabled()) return;\n console.log(`[Papyrus Perf][CoreStore] ${event}`, payload);\n};\n\nlet setDocumentStateWindowStart = 0;\nlet setDocumentStateCallsInWindow = 0;\n\ninterface ViewerState {\n isLoaded: boolean;\n pageCount: number;\n currentPage: number;\n zoom: number;\n rotation: number;\n viewMode: ViewMode;\n uiTheme: UITheme;\n pageTheme: PageTheme;\n locale: Locale;\n accentColor: string;\n annotationColor: string;\n outline: OutlineItem[];\n sidebarLeftOpen: boolean;\n sidebarLeftTab: \"thumbnails\" | \"summary\";\n outlineSearchQuery: string;\n sidebarRightOpen: boolean;\n sidebarRightTab: \"search\" | \"annotations\" | \"pages\";\n searchQuery: string;\n searchResults: SearchResult[];\n activeSearchIndex: number;\n scrollToPageSignal: number | null;\n annotations: Annotation[];\n activeTool:\n | \"select\"\n | \"highlight\"\n | \"underline\"\n | \"squiggly\"\n | \"strikeout\"\n | \"text\"\n | \"comment\"\n | \"ink\";\n selectedAnnotationId: string | null;\n interactionMode: \"pan\" | \"select\";\n selectionActive: boolean;\n toolDockOpen: boolean;\n mobileChromeVisible: boolean;\n\n initializeStore: (config: PapyrusConfig) => void;\n setDocumentState: (state: Partial<ViewerState>) => void;\n toggleSidebarLeft: () => void;\n setSidebarLeftTab: (tab: \"thumbnails\" | \"summary\") => void;\n setOutlineSearch: (query: string) => void;\n toggleSidebarRight: (tab?: \"search\" | \"annotations\" | \"pages\") => void;\n addAnnotation: (annotation: Annotation) => void;\n updateAnnotation: (id: string, updates: Partial<Annotation>) => void;\n addAnnotationReply: (annotationId: string, content: string) => void;\n removeAnnotation: (id: string) => void;\n setSelectedAnnotation: (id: string | null) => void;\n setSearch: (query: string, results: SearchResult[]) => void;\n nextSearchResult: () => void;\n prevSearchResult: () => void;\n triggerScrollToPage: (pageIndex: number) => void;\n setAnnotationColor: (color: string) => void;\n setInteractionMode: (mode: \"pan\" | \"select\") => void;\n setSelectionActive: (active: boolean) => void;\n setAccentColor: (color: string) => void;\n}\n\nconst getDefaultViewerState = () => ({\n isLoaded: false,\n pageCount: 0,\n currentPage: 1,\n zoom: 1.0,\n rotation: 0,\n viewMode: \"continuous\" as ViewMode,\n uiTheme: \"light\" as UITheme,\n pageTheme: \"normal\" as PageTheme,\n locale: \"en\" as Locale,\n accentColor: \"#2563eb\",\n annotationColor: \"#fbbf24\",\n outline: [] as OutlineItem[],\n sidebarLeftOpen: true,\n sidebarLeftTab: \"thumbnails\" as const,\n outlineSearchQuery: \"\",\n sidebarRightOpen: false,\n sidebarRightTab: \"search\" as const,\n searchQuery: \"\",\n searchResults: [] as SearchResult[],\n activeSearchIndex: -1,\n scrollToPageSignal: null as number | null,\n annotations: [] as Annotation[],\n activeTool: \"select\" as const,\n selectedAnnotationId: null as string | null,\n interactionMode: \"pan\" as const,\n selectionActive: false,\n toolDockOpen: false,\n mobileChromeVisible: true,\n});\n\nexport const useViewerStore = create<ViewerState>((set, get) => ({\n ...getDefaultViewerState(),\n\n initializeStore: (config) =>\n set(() => {\n const defaults = getDefaultViewerState();\n return {\n ...defaults,\n currentPage: config.initialPage ?? defaults.currentPage,\n zoom: config.initialZoom ?? defaults.zoom,\n rotation: config.initialRotation ?? defaults.rotation,\n viewMode: config.initialViewMode ?? defaults.viewMode,\n uiTheme: config.initialUITheme ?? defaults.uiTheme,\n pageTheme: config.initialPageTheme ?? defaults.pageTheme,\n locale: config.initialLocale ?? defaults.locale,\n accentColor: config.initialAccentColor ?? defaults.accentColor,\n annotations: config.initialAnnotations ?? defaults.annotations,\n sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,\n sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen,\n };\n }),\n\n setDocumentState: (state) => {\n if (isMobilePerfEnabled()) {\n const now = perfNow();\n if (\n setDocumentStateWindowStart === 0 ||\n now - setDocumentStateWindowStart > 1000\n ) {\n setDocumentStateWindowStart = now;\n setDocumentStateCallsInWindow = 0;\n }\n\n setDocumentStateCallsInWindow += 1;\n if (setDocumentStateCallsInWindow === 12) {\n logStorePerf(\"setDocumentState.burst\", {\n calls: setDocumentStateCallsInWindow,\n windowMs: Math.round(now - setDocumentStateWindowStart),\n keys: Object.keys(state),\n });\n }\n }\n\n const oldPage = get().currentPage;\n const oldZoom = get().zoom;\n\n set((prev) => ({ ...prev, ...state }));\n\n if (state.currentPage !== undefined && state.currentPage !== oldPage) {\n papyrusEvents.emit(PapyrusEventType.PAGE_CHANGED, {\n pageNumber: state.currentPage,\n });\n }\n if (state.zoom !== undefined && state.zoom !== oldZoom) {\n papyrusEvents.emit(PapyrusEventType.ZOOM_CHANGED, { zoom: state.zoom });\n }\n if (state.isLoaded === true) {\n papyrusEvents.emit(PapyrusEventType.DOCUMENT_LOADED, {\n pageCount: get().pageCount,\n });\n }\n },\n\n toggleSidebarLeft: () =>\n set((state) => ({ sidebarLeftOpen: !state.sidebarLeftOpen })),\n setSidebarLeftTab: (tab) => set({ sidebarLeftTab: tab }),\n setOutlineSearch: (query) => set({ outlineSearchQuery: query }),\n toggleSidebarRight: (tab) =>\n set((state) => ({\n sidebarRightOpen: tab ? true : !state.sidebarRightOpen,\n sidebarRightTab: tab || state.sidebarRightTab,\n })),\n setAnnotationColor: (color) => set({ annotationColor: color }),\n\n addAnnotation: (ann) => {\n const shouldAutoSelect = ann.type === \"text\" || ann.type === \"comment\";\n set((state) => ({\n annotations: [...state.annotations, ann],\n selectedAnnotationId: shouldAutoSelect\n ? ann.id\n : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_CREATED, {\n annotation: ann,\n });\n },\n\n updateAnnotation: (id, updates) => {\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== id) return a;\n updatedAnnotation = {\n ...a,\n ...updates,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n addAnnotationReply: (annotationId, content) => {\n const nextContent = content.trim();\n if (!nextContent) return;\n\n const reply: AnnotationReply = {\n id: Math.random().toString(36).slice(2, 11),\n annotationId,\n content: nextContent,\n createdAt: Date.now(),\n };\n\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== annotationId) return a;\n const replies = [...(a.replies ?? []), reply];\n updatedAnnotation = {\n ...a,\n replies,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_REPLY_ADDED, {\n annotationId,\n reply,\n annotation: updatedAnnotation,\n });\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n removeAnnotation: (id) => {\n set((state) => ({\n annotations: state.annotations.filter((a) => a.id !== id),\n selectedAnnotationId:\n state.selectedAnnotationId === id ? null : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_DELETED, {\n annotationId: id,\n });\n },\n\n setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),\n setInteractionMode: (mode) => set({ interactionMode: mode }),\n setSelectionActive: (active) => set({ selectionActive: active }),\n setAccentColor: (color) => set({ accentColor: color }),\n\n setSearch: (query, results) => {\n set({\n searchQuery: query,\n searchResults: results,\n activeSearchIndex: results.length > 0 ? 0 : -1,\n });\n papyrusEvents.emit(PapyrusEventType.SEARCH_TRIGGERED, { query });\n },\n\n nextSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const nextIndex =\n (state.activeSearchIndex + 1) % state.searchResults.length;\n const pageIndex = state.searchResults[nextIndex].pageIndex;\n set({\n activeSearchIndex: nextIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n prevSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const prevIndex =\n (state.activeSearchIndex - 1 + state.searchResults.length) %\n state.searchResults.length;\n const pageIndex = state.searchResults[prevIndex].pageIndex;\n set({\n activeSearchIndex: prevIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n triggerScrollToPage: (pageIndex) =>\n set({ scrollToPageSignal: pageIndex, currentPage: pageIndex + 1 }),\n}));\n","\r\nimport { PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';\r\n\r\nexport class PapyrusEventEmitter {\r\n private listeners: Map<PapyrusEventType, Set<PapyrusEventListener<any>>> = new Map();\r\n\r\n on<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): () => void {\r\n if (!this.listeners.has(event)) {\r\n this.listeners.set(event, new Set());\r\n }\r\n this.listeners.get(event)!.add(listener);\r\n\r\n // Return an unsubscribe function\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): void {\r\n const eventListeners = this.listeners.get(event);\r\n if (eventListeners) {\r\n eventListeners.delete(listener);\r\n }\r\n }\r\n\r\n emit<T extends PapyrusEventType>(event: T, payload: EventPayloads[T]): void {\r\n const eventListeners = this.listeners.get(event);\r\n if (eventListeners) {\r\n eventListeners.forEach((listener) => listener(payload));\r\n }\r\n }\r\n}\r\n\r\n// Singleton instance for the core package\r\nexport const papyrusEvents = new PapyrusEventEmitter();\r\n","import { DocumentEngine, SearchResult } from \"@papyrus-sdk/types\";\n\nexport class SearchService {\n private engine: DocumentEngine;\n constructor(engine: DocumentEngine) {\n this.engine = engine;\n }\n\n async search(query: string): Promise<SearchResult[]> {\n const trimmedQuery = query.trim();\n if (!trimmedQuery || trimmedQuery.length < 2) return [];\n const normalizedQuery = this.normalizeForSearch(trimmedQuery);\n if (!normalizedQuery) return [];\n\n if (typeof this.engine.searchText === \"function\") {\n return await this.engine.searchText(trimmedQuery);\n }\n\n const results: SearchResult[] = [];\n const pageCount = this.engine.getPageCount();\n\n for (let i = 0; i < pageCount; i++) {\n const textContent = await this.engine.getTextContent(i);\n const rawPageText = textContent.map((item) => item.str).join(\" \");\n const cleanPageText = this.normalizeWhitespace(\n this.decodeHtmlEntities(this.stripMarkup(rawPageText))\n );\n if (!cleanPageText) continue;\n\n const { normalized, map } = this.normalizeWithMap(cleanPageText);\n if (!normalized) continue;\n\n let pos = normalized.indexOf(normalizedQuery, 0);\n let matchIndex = 0;\n while (pos !== -1) {\n const anchor = map[pos] ?? pos;\n const start = Math.max(0, anchor - 40);\n const end = Math.min(\n cleanPageText.length,\n anchor + trimmedQuery.length + 40\n );\n results.push({\n pageIndex: i,\n text: cleanPageText.substring(start, end),\n matchIndex: matchIndex++,\n });\n pos = normalized.indexOf(normalizedQuery, pos + 1);\n }\n }\n\n return results;\n }\n\n private normalizeForSearch(value: string): string {\n return value\n .toLocaleLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\");\n }\n\n private normalizeWithMap(value: string): {\n normalized: string;\n map: number[];\n } {\n let normalized = \"\";\n const map: number[] = [];\n\n for (let i = 0; i < value.length; i += 1) {\n const next = this.normalizeForSearch(value[i]);\n if (!next) continue;\n normalized += next;\n for (let j = 0; j < next.length; j += 1) {\n map.push(i);\n }\n }\n\n return { normalized, map };\n }\n\n private stripMarkup(value: string): string {\n if (!value) return \"\";\n return value\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \");\n }\n\n private decodeHtmlEntities(value: string): string {\n if (!value) return \"\";\n if (typeof document === \"undefined\") return value;\n\n const textArea = document.createElement(\"textarea\");\n textArea.innerHTML = value;\n return textArea.value;\n }\n\n private normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../index.ts","../engine.ts","../store.ts","../services/event-emitter.ts","../services/search-service.ts"],"sourcesContent":["\nexport * from './engine';\nexport * from './store';\nexport * from './services/search-service';\nexport * from './services/event-emitter';\n","\nimport { DocumentEngine, TextItem, OutlineItem, DocumentLoadInput, TextSelection, PageDestination } from '@papyrus-sdk/types';\n\nexport abstract class BaseDocumentEngine implements DocumentEngine {\n abstract load(source: DocumentLoadInput): Promise<void>;\n abstract getPageCount(): number;\n abstract getCurrentPage(): number;\n abstract goToPage(page: number): void;\n abstract setZoom(zoom: number): void;\n abstract getZoom(): number;\n abstract rotate(direction: 'clockwise' | 'counterclockwise'): void;\n abstract getRotation(): number;\n abstract renderPage(pageIndex: number, target: any, scale: number): Promise<void>;\n abstract renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;\n abstract getTextContent(pageIndex: number): Promise<TextItem[]>;\n abstract getPageDimensions(pageIndex: number): Promise<{ width: number, height: number }>;\n abstract selectText(pageIndex: number, rect: { x: number; y: number; width: number; height: number }): Promise<TextSelection | null>;\n abstract getOutline(): Promise<OutlineItem[]>;\n abstract getPageIndex(dest: PageDestination): Promise<number | null>;\n abstract destroy(): void;\n}\n","import { create } from \"zustand\";\nimport {\n ViewMode,\n Annotation,\n AnnotationReply,\n SearchResult,\n UITheme,\n PageTheme,\n OutlineItem,\n ActiveSurface,\n CapabilityState,\n DocumentLocation,\n PapyrusEventType,\n PapyrusConfig,\n Locale,\n MobilePrimaryDestination,\n MobileShellState,\n ReadingMode,\n} from \"@papyrus-sdk/types\";\nimport { papyrusEvents } from \"./services/event-emitter\";\n\nconst perfNow = () =>\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? performance.now()\n : Date.now();\n\nconst isMobilePerfEnabled = () => {\n const perfGlobal = (globalThis as Record<string, unknown>)\n .__PAPYRUS_MOBILE_PERF__;\n if (perfGlobal === true) return true;\n if (!perfGlobal || typeof perfGlobal !== \"object\") return false;\n return (perfGlobal as { enabled?: boolean }).enabled ?? true;\n};\n\nconst logStorePerf = (event: string, payload: Record<string, unknown>) => {\n if (!isMobilePerfEnabled()) return;\n console.log(`[Papyrus Perf][CoreStore] ${event}`, payload);\n};\n\nlet setDocumentStateWindowStart = 0;\nlet setDocumentStateCallsInWindow = 0;\n\ninterface ViewerState {\n isLoaded: boolean;\n pageCount: number;\n currentPage: number;\n zoom: number;\n rotation: number;\n viewMode: ViewMode;\n uiTheme: UITheme;\n pageTheme: PageTheme;\n locale: Locale;\n accentColor: string;\n annotationColor: string;\n annotationOpacity: number;\n inkStrokeWidth: number;\n activeDrawToolPreset: \"ink\" | \"highlight\" | \"underline\";\n outline: OutlineItem[];\n sidebarLeftOpen: boolean;\n sidebarLeftTab: \"thumbnails\" | \"summary\";\n outlineSearchQuery: string;\n sidebarRightOpen: boolean;\n sidebarRightTab: \"search\" | \"annotations\" | \"pages\";\n searchQuery: string;\n searchResults: SearchResult[];\n activeSearchIndex: number;\n scrollToPageSignal: number | null;\n annotations: Annotation[];\n activeTool:\n | \"select\"\n | \"highlight\"\n | \"underline\"\n | \"squiggly\"\n | \"strikeout\"\n | \"text\"\n | \"comment\"\n | \"ink\";\n selectedAnnotationId: string | null;\n interactionMode: \"pan\" | \"select\";\n selectionActive: boolean;\n toolDockOpen: boolean;\n mobileChromeVisible: boolean;\n readingMode: ReadingMode;\n activeSurface: ActiveSurface;\n documentLocation: DocumentLocation;\n capabilityState: CapabilityState;\n activeMobileDestination: MobilePrimaryDestination;\n mobileKeyboardOpen: boolean;\n mobileDockVisible: boolean;\n mobileProgressPillVisible: boolean;\n annotationUndoStack: Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>;\n annotationRedoStack: Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>;\n\n initializeStore: (config: PapyrusConfig) => void;\n setDocumentState: (state: Partial<ViewerState>) => void;\n toggleSidebarLeft: () => void;\n setSidebarLeftTab: (tab: \"thumbnails\" | \"summary\") => void;\n setOutlineSearch: (query: string) => void;\n toggleSidebarRight: (tab?: \"search\" | \"annotations\" | \"pages\") => void;\n addAnnotation: (annotation: Annotation) => void;\n updateAnnotation: (id: string, updates: Partial<Annotation>) => void;\n addAnnotationReply: (annotationId: string, content: string) => void;\n removeAnnotation: (id: string) => void;\n setSelectedAnnotation: (id: string | null) => void;\n setSearch: (query: string, results: SearchResult[]) => void;\n nextSearchResult: () => void;\n prevSearchResult: () => void;\n triggerScrollToPage: (pageIndex: number) => void;\n setAnnotationColor: (color: string) => void;\n setAnnotationOpacity: (opacity: number) => void;\n setInkStrokeWidth: (width: number) => void;\n undoAnnotations: () => void;\n redoAnnotations: () => void;\n setInteractionMode: (mode: \"pan\" | \"select\") => void;\n setSelectionActive: (active: boolean) => void;\n setAccentColor: (color: string) => void;\n openActiveSurface: (surface: Exclude<ActiveSurface, \"none\">) => void;\n closeActiveSurface: () => void;\n setDocumentLocation: (location: DocumentLocation) => void;\n setCapabilityState: (capabilityState: CapabilityState) => void;\n openMobileDestination: (destination: MobilePrimaryDestination) => void;\n closeMobileDestination: () => void;\n setMobileKeyboardOpen: (open: boolean) => void;\n}\n\nconst getDefaultCapabilityState = (): CapabilityState => ({\n status: \"unknown\",\n values: {},\n errors: [],\n});\n\nconst getDefaultViewerState = () => ({\n isLoaded: false,\n pageCount: 0,\n currentPage: 1,\n zoom: 1.0,\n rotation: 0,\n viewMode: \"continuous\" as ViewMode,\n uiTheme: \"light\" as UITheme,\n pageTheme: \"normal\" as PageTheme,\n locale: \"en\" as Locale,\n accentColor: \"#2563eb\",\n annotationColor: \"#fbbf24\",\n annotationOpacity: 1,\n inkStrokeWidth: 0.006,\n outline: [] as OutlineItem[],\n sidebarLeftOpen: true,\n sidebarLeftTab: \"thumbnails\" as const,\n outlineSearchQuery: \"\",\n sidebarRightOpen: false,\n sidebarRightTab: \"search\" as const,\n searchQuery: \"\",\n searchResults: [] as SearchResult[],\n activeSearchIndex: -1,\n scrollToPageSignal: null as number | null,\n annotations: [] as Annotation[],\n activeTool: \"select\" as const,\n activeDrawToolPreset: \"ink\" as const,\n selectedAnnotationId: null as string | null,\n interactionMode: \"pan\" as const,\n selectionActive: false,\n toolDockOpen: false,\n mobileChromeVisible: true,\n readingMode: \"focus\" as ReadingMode,\n activeSurface: \"none\" as ActiveSurface,\n documentLocation: {\n kind: \"page\" as const,\n label: \"1/0\",\n primaryValue: 1,\n secondaryValue: 0,\n } satisfies DocumentLocation,\n capabilityState: getDefaultCapabilityState(),\n activeMobileDestination: \"none\" as MobilePrimaryDestination,\n mobileKeyboardOpen: false,\n mobileDockVisible: true,\n mobileProgressPillVisible: true,\n annotationUndoStack: [] as Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>,\n annotationRedoStack: [] as Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>,\n});\n\nconst deriveMobileShellState = ({\n activeMobileDestination,\n mobileKeyboardOpen,\n}: Pick<\n ViewerState,\n \"activeMobileDestination\" | \"mobileKeyboardOpen\"\n>): MobileShellState => {\n const keyboardOwnsSurface =\n mobileKeyboardOpen && activeMobileDestination === \"search\";\n\n return {\n activeMobileDestination,\n mobileKeyboardOpen,\n mobileDockVisible: !keyboardOwnsSurface,\n mobileProgressPillVisible: !keyboardOwnsSurface,\n };\n};\n\nexport const useViewerStore = create<ViewerState>((set, get) => ({\n ...getDefaultViewerState(),\n\n initializeStore: (config) =>\n set(() => {\n const defaults = getDefaultViewerState();\n return {\n ...defaults,\n currentPage: config.initialPage ?? defaults.currentPage,\n zoom: config.initialZoom ?? defaults.zoom,\n rotation: config.initialRotation ?? defaults.rotation,\n viewMode: config.initialViewMode ?? defaults.viewMode,\n uiTheme: config.initialUITheme ?? defaults.uiTheme,\n pageTheme: config.initialPageTheme ?? defaults.pageTheme,\n locale: config.initialLocale ?? defaults.locale,\n accentColor: config.initialAccentColor ?? defaults.accentColor,\n annotations: config.initialAnnotations ?? defaults.annotations,\n annotationUndoStack: defaults.annotationUndoStack,\n annotationRedoStack: defaults.annotationRedoStack,\n sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,\n sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen,\n };\n }),\n\n setDocumentState: (state) => {\n if (isMobilePerfEnabled()) {\n const now = perfNow();\n if (\n setDocumentStateWindowStart === 0 ||\n now - setDocumentStateWindowStart > 1000\n ) {\n setDocumentStateWindowStart = now;\n setDocumentStateCallsInWindow = 0;\n }\n\n setDocumentStateCallsInWindow += 1;\n if (setDocumentStateCallsInWindow === 12) {\n logStorePerf(\"setDocumentState.burst\", {\n calls: setDocumentStateCallsInWindow,\n windowMs: Math.round(now - setDocumentStateWindowStart),\n keys: Object.keys(state),\n });\n }\n }\n\n const oldPage = get().currentPage;\n const oldZoom = get().zoom;\n\n set((prev) => {\n const nextState = { ...prev, ...state };\n if (\n state.activeMobileDestination !== undefined ||\n state.mobileKeyboardOpen !== undefined\n ) {\n Object.assign(\n nextState,\n deriveMobileShellState({\n activeMobileDestination: nextState.activeMobileDestination,\n mobileKeyboardOpen: nextState.mobileKeyboardOpen,\n })\n );\n }\n return nextState;\n });\n\n if (state.currentPage !== undefined && state.currentPage !== oldPage) {\n papyrusEvents.emit(PapyrusEventType.PAGE_CHANGED, {\n pageNumber: state.currentPage,\n });\n }\n if (state.zoom !== undefined && state.zoom !== oldZoom) {\n papyrusEvents.emit(PapyrusEventType.ZOOM_CHANGED, { zoom: state.zoom });\n }\n if (state.isLoaded === true) {\n papyrusEvents.emit(PapyrusEventType.DOCUMENT_LOADED, {\n pageCount: get().pageCount,\n });\n }\n },\n\n toggleSidebarLeft: () =>\n set((state) => ({ sidebarLeftOpen: !state.sidebarLeftOpen })),\n setSidebarLeftTab: (tab) => set({ sidebarLeftTab: tab }),\n setOutlineSearch: (query) => set({ outlineSearchQuery: query }),\n toggleSidebarRight: (tab) =>\n set((state) => ({\n sidebarRightOpen: tab ? true : !state.sidebarRightOpen,\n sidebarRightTab: tab || state.sidebarRightTab,\n })),\n setAnnotationColor: (color) => set({ annotationColor: color }),\n setAnnotationOpacity: (opacity) =>\n set({ annotationOpacity: Math.min(1, Math.max(0.1, opacity)) }),\n setInkStrokeWidth: (width) =>\n set({ inkStrokeWidth: Math.min(0.02, Math.max(0.0025, width)) }),\n\n addAnnotation: (ann) => {\n const shouldAutoSelect = ann.type === \"text\" || ann.type === \"comment\";\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: [...state.annotations, ann],\n selectedAnnotationId: shouldAutoSelect\n ? ann.id\n : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_CREATED, {\n annotation: ann,\n });\n },\n\n updateAnnotation: (id, updates) => {\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: state.annotations.map((a) => {\n if (a.id !== id) return a;\n updatedAnnotation = {\n ...a,\n ...updates,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n addAnnotationReply: (annotationId, content) => {\n const nextContent = content.trim();\n if (!nextContent) return;\n\n const reply: AnnotationReply = {\n id: Math.random().toString(36).slice(2, 11),\n annotationId,\n content: nextContent,\n createdAt: Date.now(),\n };\n\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== annotationId) return a;\n const replies = [...(a.replies ?? []), reply];\n updatedAnnotation = {\n ...a,\n replies,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_REPLY_ADDED, {\n annotationId,\n reply,\n annotation: updatedAnnotation,\n });\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n removeAnnotation: (id) => {\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: state.annotations.filter((a) => a.id !== id),\n selectedAnnotationId:\n state.selectedAnnotationId === id ? null : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_DELETED, {\n annotationId: id,\n });\n },\n\n undoAnnotations: () => {\n const state = get();\n const previous =\n state.annotationUndoStack[state.annotationUndoStack.length - 1];\n if (!previous) return;\n set({\n annotations: previous.annotations,\n selectedAnnotationId: previous.selectedAnnotationId,\n annotationUndoStack: state.annotationUndoStack.slice(0, -1),\n annotationRedoStack: [\n ...state.annotationRedoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n });\n },\n\n redoAnnotations: () => {\n const state = get();\n const next = state.annotationRedoStack[state.annotationRedoStack.length - 1];\n if (!next) return;\n set({\n annotations: next.annotations,\n selectedAnnotationId: next.selectedAnnotationId,\n annotationRedoStack: state.annotationRedoStack.slice(0, -1),\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n });\n },\n\n setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),\n setInteractionMode: (mode) => set({ interactionMode: mode }),\n setSelectionActive: (active) => set({ selectionActive: active }),\n setAccentColor: (color) => set({ accentColor: color }),\n openActiveSurface: (surface) =>\n set({\n activeSurface: surface,\n readingMode: \"modalSurfaceOpen\",\n mobileChromeVisible: true,\n }),\n closeActiveSurface: () =>\n set({\n activeSurface: \"none\",\n readingMode: \"controlsVisible\",\n }),\n setDocumentLocation: (location) => set({ documentLocation: location }),\n setCapabilityState: (capabilityState) => set({ capabilityState }),\n openMobileDestination: (destination) =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: destination,\n mobileKeyboardOpen: state.mobileKeyboardOpen,\n }),\n })),\n closeMobileDestination: () =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: \"none\",\n mobileKeyboardOpen: state.mobileKeyboardOpen,\n }),\n })),\n setMobileKeyboardOpen: (open) =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: state.activeMobileDestination,\n mobileKeyboardOpen: open,\n }),\n })),\n\n setSearch: (query, results) => {\n set({\n searchQuery: query,\n searchResults: results,\n activeSearchIndex: results.length > 0 ? 0 : -1,\n });\n papyrusEvents.emit(PapyrusEventType.SEARCH_TRIGGERED, { query });\n },\n\n nextSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const nextIndex =\n (state.activeSearchIndex + 1) % state.searchResults.length;\n const pageIndex = state.searchResults[nextIndex].pageIndex;\n set({\n activeSearchIndex: nextIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n prevSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const prevIndex =\n (state.activeSearchIndex - 1 + state.searchResults.length) %\n state.searchResults.length;\n const pageIndex = state.searchResults[prevIndex].pageIndex;\n set({\n activeSearchIndex: prevIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n triggerScrollToPage: (pageIndex) =>\n set({ scrollToPageSignal: pageIndex, currentPage: pageIndex + 1 }),\n}));\n","\nimport { PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';\n\nexport class PapyrusEventEmitter {\n private listeners: Map<PapyrusEventType, Set<PapyrusEventListener<any>>> = new Map();\n\n on<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return an unsubscribe function\n return () => this.off(event, listener);\n }\n\n off<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.delete(listener);\n }\n }\n\n emit<T extends PapyrusEventType>(event: T, payload: EventPayloads[T]): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.forEach((listener) => listener(payload));\n }\n }\n}\n\n// Singleton instance for the core package\nexport const papyrusEvents = new PapyrusEventEmitter();\n","import { DocumentEngine, SearchResult } from \"@papyrus-sdk/types\";\n\nexport class SearchService {\n private engine: DocumentEngine;\n constructor(engine: DocumentEngine) {\n this.engine = engine;\n }\n\n async search(query: string): Promise<SearchResult[]> {\n const trimmedQuery = query.trim();\n if (!trimmedQuery || trimmedQuery.length < 2) return [];\n const normalizedQuery = this.normalizeForSearch(trimmedQuery);\n if (!normalizedQuery) return [];\n\n if (typeof this.engine.searchText === \"function\") {\n return await this.engine.searchText(trimmedQuery);\n }\n\n const results: SearchResult[] = [];\n const pageCount = this.engine.getPageCount();\n\n for (let i = 0; i < pageCount; i++) {\n const textContent = await this.engine.getTextContent(i);\n const rawPageText = textContent.map((item) => item.str).join(\" \");\n const cleanPageText = this.normalizeWhitespace(\n this.decodeHtmlEntities(this.stripMarkup(rawPageText))\n );\n if (!cleanPageText) continue;\n\n const { normalized, map } = this.normalizeWithMap(cleanPageText);\n if (!normalized) continue;\n\n let pos = normalized.indexOf(normalizedQuery, 0);\n let matchIndex = 0;\n while (pos !== -1) {\n const anchor = map[pos] ?? pos;\n const start = Math.max(0, anchor - 40);\n const end = Math.min(\n cleanPageText.length,\n anchor + trimmedQuery.length + 40\n );\n results.push({\n pageIndex: i,\n text: cleanPageText.substring(start, end),\n matchIndex: matchIndex++,\n });\n pos = normalized.indexOf(normalizedQuery, pos + 1);\n }\n }\n\n return results;\n }\n\n private normalizeForSearch(value: string): string {\n return value\n .toLocaleLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\");\n }\n\n private normalizeWithMap(value: string): {\n normalized: string;\n map: number[];\n } {\n let normalized = \"\";\n const map: number[] = [];\n\n for (let i = 0; i < value.length; i += 1) {\n const next = this.normalizeForSearch(value[i]);\n if (!next) continue;\n normalized += next;\n for (let j = 0; j < next.length; j += 1) {\n map.push(i);\n }\n }\n\n return { normalized, map };\n }\n\n private stripMarkup(value: string): string {\n if (!value) return \"\";\n return value\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \");\n }\n\n private decodeHtmlEntities(value: string): string {\n if (!value) return \"\";\n if (typeof document === \"undefined\") return value;\n\n const textArea = document.createElement(\"textarea\");\n textArea.innerHTML = value;\n return textArea.value;\n }\n\n private normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -49,6 +49,11 @@ var logStorePerf = (event, payload) => {
49
49
  };
50
50
  var setDocumentStateWindowStart = 0;
51
51
  var setDocumentStateCallsInWindow = 0;
52
+ var getDefaultCapabilityState = () => ({
53
+ status: "unknown",
54
+ values: {},
55
+ errors: []
56
+ });
52
57
  var getDefaultViewerState = () => ({
53
58
  isLoaded: false,
54
59
  pageCount: 0,
@@ -61,6 +66,8 @@ var getDefaultViewerState = () => ({
61
66
  locale: "en",
62
67
  accentColor: "#2563eb",
63
68
  annotationColor: "#fbbf24",
69
+ annotationOpacity: 1,
70
+ inkStrokeWidth: 6e-3,
64
71
  outline: [],
65
72
  sidebarLeftOpen: true,
66
73
  sidebarLeftTab: "thumbnails",
@@ -73,12 +80,40 @@ var getDefaultViewerState = () => ({
73
80
  scrollToPageSignal: null,
74
81
  annotations: [],
75
82
  activeTool: "select",
83
+ activeDrawToolPreset: "ink",
76
84
  selectedAnnotationId: null,
77
85
  interactionMode: "pan",
78
86
  selectionActive: false,
79
87
  toolDockOpen: false,
80
- mobileChromeVisible: true
88
+ mobileChromeVisible: true,
89
+ readingMode: "focus",
90
+ activeSurface: "none",
91
+ documentLocation: {
92
+ kind: "page",
93
+ label: "1/0",
94
+ primaryValue: 1,
95
+ secondaryValue: 0
96
+ },
97
+ capabilityState: getDefaultCapabilityState(),
98
+ activeMobileDestination: "none",
99
+ mobileKeyboardOpen: false,
100
+ mobileDockVisible: true,
101
+ mobileProgressPillVisible: true,
102
+ annotationUndoStack: [],
103
+ annotationRedoStack: []
81
104
  });
105
+ var deriveMobileShellState = ({
106
+ activeMobileDestination,
107
+ mobileKeyboardOpen
108
+ }) => {
109
+ const keyboardOwnsSurface = mobileKeyboardOpen && activeMobileDestination === "search";
110
+ return {
111
+ activeMobileDestination,
112
+ mobileKeyboardOpen,
113
+ mobileDockVisible: !keyboardOwnsSurface,
114
+ mobileProgressPillVisible: !keyboardOwnsSurface
115
+ };
116
+ };
82
117
  var useViewerStore = create((set, get) => ({
83
118
  ...getDefaultViewerState(),
84
119
  initializeStore: (config) => set(() => {
@@ -94,6 +129,8 @@ var useViewerStore = create((set, get) => ({
94
129
  locale: config.initialLocale ?? defaults.locale,
95
130
  accentColor: config.initialAccentColor ?? defaults.accentColor,
96
131
  annotations: config.initialAnnotations ?? defaults.annotations,
132
+ annotationUndoStack: defaults.annotationUndoStack,
133
+ annotationRedoStack: defaults.annotationRedoStack,
97
134
  sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,
98
135
  sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen
99
136
  };
@@ -116,7 +153,19 @@ var useViewerStore = create((set, get) => ({
116
153
  }
117
154
  const oldPage = get().currentPage;
118
155
  const oldZoom = get().zoom;
119
- set((prev) => ({ ...prev, ...state }));
156
+ set((prev) => {
157
+ const nextState = { ...prev, ...state };
158
+ if (state.activeMobileDestination !== void 0 || state.mobileKeyboardOpen !== void 0) {
159
+ Object.assign(
160
+ nextState,
161
+ deriveMobileShellState({
162
+ activeMobileDestination: nextState.activeMobileDestination,
163
+ mobileKeyboardOpen: nextState.mobileKeyboardOpen
164
+ })
165
+ );
166
+ }
167
+ return nextState;
168
+ });
120
169
  if (state.currentPage !== void 0 && state.currentPage !== oldPage) {
121
170
  papyrusEvents.emit(PapyrusEventType.PAGE_CHANGED, {
122
171
  pageNumber: state.currentPage
@@ -139,9 +188,19 @@ var useViewerStore = create((set, get) => ({
139
188
  sidebarRightTab: tab || state.sidebarRightTab
140
189
  })),
141
190
  setAnnotationColor: (color) => set({ annotationColor: color }),
191
+ setAnnotationOpacity: (opacity) => set({ annotationOpacity: Math.min(1, Math.max(0.1, opacity)) }),
192
+ setInkStrokeWidth: (width) => set({ inkStrokeWidth: Math.min(0.02, Math.max(25e-4, width)) }),
142
193
  addAnnotation: (ann) => {
143
194
  const shouldAutoSelect = ann.type === "text" || ann.type === "comment";
144
195
  set((state) => ({
196
+ annotationUndoStack: [
197
+ ...state.annotationUndoStack,
198
+ {
199
+ annotations: state.annotations,
200
+ selectedAnnotationId: state.selectedAnnotationId
201
+ }
202
+ ].slice(-50),
203
+ annotationRedoStack: [],
145
204
  annotations: [...state.annotations, ann],
146
205
  selectedAnnotationId: shouldAutoSelect ? ann.id : state.selectedAnnotationId
147
206
  }));
@@ -152,6 +211,14 @@ var useViewerStore = create((set, get) => ({
152
211
  updateAnnotation: (id, updates) => {
153
212
  let updatedAnnotation = null;
154
213
  set((state) => ({
214
+ annotationUndoStack: [
215
+ ...state.annotationUndoStack,
216
+ {
217
+ annotations: state.annotations,
218
+ selectedAnnotationId: state.selectedAnnotationId
219
+ }
220
+ ].slice(-50),
221
+ annotationRedoStack: [],
155
222
  annotations: state.annotations.map((a) => {
156
223
  if (a.id !== id) return a;
157
224
  updatedAnnotation = {
@@ -203,6 +270,14 @@ var useViewerStore = create((set, get) => ({
203
270
  },
204
271
  removeAnnotation: (id) => {
205
272
  set((state) => ({
273
+ annotationUndoStack: [
274
+ ...state.annotationUndoStack,
275
+ {
276
+ annotations: state.annotations,
277
+ selectedAnnotationId: state.selectedAnnotationId
278
+ }
279
+ ].slice(-50),
280
+ annotationRedoStack: [],
206
281
  annotations: state.annotations.filter((a) => a.id !== id),
207
282
  selectedAnnotationId: state.selectedAnnotationId === id ? null : state.selectedAnnotationId
208
283
  }));
@@ -210,10 +285,73 @@ var useViewerStore = create((set, get) => ({
210
285
  annotationId: id
211
286
  });
212
287
  },
288
+ undoAnnotations: () => {
289
+ const state = get();
290
+ const previous = state.annotationUndoStack[state.annotationUndoStack.length - 1];
291
+ if (!previous) return;
292
+ set({
293
+ annotations: previous.annotations,
294
+ selectedAnnotationId: previous.selectedAnnotationId,
295
+ annotationUndoStack: state.annotationUndoStack.slice(0, -1),
296
+ annotationRedoStack: [
297
+ ...state.annotationRedoStack,
298
+ {
299
+ annotations: state.annotations,
300
+ selectedAnnotationId: state.selectedAnnotationId
301
+ }
302
+ ].slice(-50)
303
+ });
304
+ },
305
+ redoAnnotations: () => {
306
+ const state = get();
307
+ const next = state.annotationRedoStack[state.annotationRedoStack.length - 1];
308
+ if (!next) return;
309
+ set({
310
+ annotations: next.annotations,
311
+ selectedAnnotationId: next.selectedAnnotationId,
312
+ annotationRedoStack: state.annotationRedoStack.slice(0, -1),
313
+ annotationUndoStack: [
314
+ ...state.annotationUndoStack,
315
+ {
316
+ annotations: state.annotations,
317
+ selectedAnnotationId: state.selectedAnnotationId
318
+ }
319
+ ].slice(-50)
320
+ });
321
+ },
213
322
  setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),
214
323
  setInteractionMode: (mode) => set({ interactionMode: mode }),
215
324
  setSelectionActive: (active) => set({ selectionActive: active }),
216
325
  setAccentColor: (color) => set({ accentColor: color }),
326
+ openActiveSurface: (surface) => set({
327
+ activeSurface: surface,
328
+ readingMode: "modalSurfaceOpen",
329
+ mobileChromeVisible: true
330
+ }),
331
+ closeActiveSurface: () => set({
332
+ activeSurface: "none",
333
+ readingMode: "controlsVisible"
334
+ }),
335
+ setDocumentLocation: (location) => set({ documentLocation: location }),
336
+ setCapabilityState: (capabilityState) => set({ capabilityState }),
337
+ openMobileDestination: (destination) => set((state) => ({
338
+ ...deriveMobileShellState({
339
+ activeMobileDestination: destination,
340
+ mobileKeyboardOpen: state.mobileKeyboardOpen
341
+ })
342
+ })),
343
+ closeMobileDestination: () => set((state) => ({
344
+ ...deriveMobileShellState({
345
+ activeMobileDestination: "none",
346
+ mobileKeyboardOpen: state.mobileKeyboardOpen
347
+ })
348
+ })),
349
+ setMobileKeyboardOpen: (open) => set((state) => ({
350
+ ...deriveMobileShellState({
351
+ activeMobileDestination: state.activeMobileDestination,
352
+ mobileKeyboardOpen: open
353
+ })
354
+ })),
217
355
  setSearch: (query, results) => {
218
356
  set({
219
357
  searchQuery: query,
@@ -1 +1 @@
1
- {"version":3,"sources":["../engine.ts","../store.ts","../services/event-emitter.ts","../services/search-service.ts"],"sourcesContent":["\r\nimport { DocumentEngine, TextItem, OutlineItem, DocumentLoadInput, TextSelection, PageDestination } from '@papyrus-sdk/types';\r\n\r\nexport abstract class BaseDocumentEngine implements DocumentEngine {\r\n abstract load(source: DocumentLoadInput): Promise<void>;\r\n abstract getPageCount(): number;\r\n abstract getCurrentPage(): number;\r\n abstract goToPage(page: number): void;\r\n abstract setZoom(zoom: number): void;\r\n abstract getZoom(): number;\r\n abstract rotate(direction: 'clockwise' | 'counterclockwise'): void;\r\n abstract getRotation(): number;\r\n abstract renderPage(pageIndex: number, target: any, scale: number): Promise<void>;\r\n abstract renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;\r\n abstract getTextContent(pageIndex: number): Promise<TextItem[]>;\r\n abstract getPageDimensions(pageIndex: number): Promise<{ width: number, height: number }>;\r\n abstract selectText(pageIndex: number, rect: { x: number; y: number; width: number; height: number }): Promise<TextSelection | null>;\r\n abstract getOutline(): Promise<OutlineItem[]>;\r\n abstract getPageIndex(dest: PageDestination): Promise<number | null>;\r\n abstract destroy(): void;\r\n}\r\n","import { create } from \"zustand\";\nimport {\n ViewMode,\n Annotation,\n AnnotationReply,\n SearchResult,\n UITheme,\n PageTheme,\n OutlineItem,\n PapyrusEventType,\n PapyrusConfig,\n Locale,\n} from \"@papyrus-sdk/types\";\nimport { papyrusEvents } from \"./services/event-emitter\";\n\nconst perfNow = () =>\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? performance.now()\n : Date.now();\n\nconst isMobilePerfEnabled = () => {\n const perfGlobal = (globalThis as Record<string, unknown>)\n .__PAPYRUS_MOBILE_PERF__;\n if (perfGlobal === true) return true;\n if (!perfGlobal || typeof perfGlobal !== \"object\") return false;\n return (perfGlobal as { enabled?: boolean }).enabled ?? true;\n};\n\nconst logStorePerf = (event: string, payload: Record<string, unknown>) => {\n if (!isMobilePerfEnabled()) return;\n console.log(`[Papyrus Perf][CoreStore] ${event}`, payload);\n};\n\nlet setDocumentStateWindowStart = 0;\nlet setDocumentStateCallsInWindow = 0;\n\ninterface ViewerState {\n isLoaded: boolean;\n pageCount: number;\n currentPage: number;\n zoom: number;\n rotation: number;\n viewMode: ViewMode;\n uiTheme: UITheme;\n pageTheme: PageTheme;\n locale: Locale;\n accentColor: string;\n annotationColor: string;\n outline: OutlineItem[];\n sidebarLeftOpen: boolean;\n sidebarLeftTab: \"thumbnails\" | \"summary\";\n outlineSearchQuery: string;\n sidebarRightOpen: boolean;\n sidebarRightTab: \"search\" | \"annotations\" | \"pages\";\n searchQuery: string;\n searchResults: SearchResult[];\n activeSearchIndex: number;\n scrollToPageSignal: number | null;\n annotations: Annotation[];\n activeTool:\n | \"select\"\n | \"highlight\"\n | \"underline\"\n | \"squiggly\"\n | \"strikeout\"\n | \"text\"\n | \"comment\"\n | \"ink\";\n selectedAnnotationId: string | null;\n interactionMode: \"pan\" | \"select\";\n selectionActive: boolean;\n toolDockOpen: boolean;\n mobileChromeVisible: boolean;\n\n initializeStore: (config: PapyrusConfig) => void;\n setDocumentState: (state: Partial<ViewerState>) => void;\n toggleSidebarLeft: () => void;\n setSidebarLeftTab: (tab: \"thumbnails\" | \"summary\") => void;\n setOutlineSearch: (query: string) => void;\n toggleSidebarRight: (tab?: \"search\" | \"annotations\" | \"pages\") => void;\n addAnnotation: (annotation: Annotation) => void;\n updateAnnotation: (id: string, updates: Partial<Annotation>) => void;\n addAnnotationReply: (annotationId: string, content: string) => void;\n removeAnnotation: (id: string) => void;\n setSelectedAnnotation: (id: string | null) => void;\n setSearch: (query: string, results: SearchResult[]) => void;\n nextSearchResult: () => void;\n prevSearchResult: () => void;\n triggerScrollToPage: (pageIndex: number) => void;\n setAnnotationColor: (color: string) => void;\n setInteractionMode: (mode: \"pan\" | \"select\") => void;\n setSelectionActive: (active: boolean) => void;\n setAccentColor: (color: string) => void;\n}\n\nconst getDefaultViewerState = () => ({\n isLoaded: false,\n pageCount: 0,\n currentPage: 1,\n zoom: 1.0,\n rotation: 0,\n viewMode: \"continuous\" as ViewMode,\n uiTheme: \"light\" as UITheme,\n pageTheme: \"normal\" as PageTheme,\n locale: \"en\" as Locale,\n accentColor: \"#2563eb\",\n annotationColor: \"#fbbf24\",\n outline: [] as OutlineItem[],\n sidebarLeftOpen: true,\n sidebarLeftTab: \"thumbnails\" as const,\n outlineSearchQuery: \"\",\n sidebarRightOpen: false,\n sidebarRightTab: \"search\" as const,\n searchQuery: \"\",\n searchResults: [] as SearchResult[],\n activeSearchIndex: -1,\n scrollToPageSignal: null as number | null,\n annotations: [] as Annotation[],\n activeTool: \"select\" as const,\n selectedAnnotationId: null as string | null,\n interactionMode: \"pan\" as const,\n selectionActive: false,\n toolDockOpen: false,\n mobileChromeVisible: true,\n});\n\nexport const useViewerStore = create<ViewerState>((set, get) => ({\n ...getDefaultViewerState(),\n\n initializeStore: (config) =>\n set(() => {\n const defaults = getDefaultViewerState();\n return {\n ...defaults,\n currentPage: config.initialPage ?? defaults.currentPage,\n zoom: config.initialZoom ?? defaults.zoom,\n rotation: config.initialRotation ?? defaults.rotation,\n viewMode: config.initialViewMode ?? defaults.viewMode,\n uiTheme: config.initialUITheme ?? defaults.uiTheme,\n pageTheme: config.initialPageTheme ?? defaults.pageTheme,\n locale: config.initialLocale ?? defaults.locale,\n accentColor: config.initialAccentColor ?? defaults.accentColor,\n annotations: config.initialAnnotations ?? defaults.annotations,\n sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,\n sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen,\n };\n }),\n\n setDocumentState: (state) => {\n if (isMobilePerfEnabled()) {\n const now = perfNow();\n if (\n setDocumentStateWindowStart === 0 ||\n now - setDocumentStateWindowStart > 1000\n ) {\n setDocumentStateWindowStart = now;\n setDocumentStateCallsInWindow = 0;\n }\n\n setDocumentStateCallsInWindow += 1;\n if (setDocumentStateCallsInWindow === 12) {\n logStorePerf(\"setDocumentState.burst\", {\n calls: setDocumentStateCallsInWindow,\n windowMs: Math.round(now - setDocumentStateWindowStart),\n keys: Object.keys(state),\n });\n }\n }\n\n const oldPage = get().currentPage;\n const oldZoom = get().zoom;\n\n set((prev) => ({ ...prev, ...state }));\n\n if (state.currentPage !== undefined && state.currentPage !== oldPage) {\n papyrusEvents.emit(PapyrusEventType.PAGE_CHANGED, {\n pageNumber: state.currentPage,\n });\n }\n if (state.zoom !== undefined && state.zoom !== oldZoom) {\n papyrusEvents.emit(PapyrusEventType.ZOOM_CHANGED, { zoom: state.zoom });\n }\n if (state.isLoaded === true) {\n papyrusEvents.emit(PapyrusEventType.DOCUMENT_LOADED, {\n pageCount: get().pageCount,\n });\n }\n },\n\n toggleSidebarLeft: () =>\n set((state) => ({ sidebarLeftOpen: !state.sidebarLeftOpen })),\n setSidebarLeftTab: (tab) => set({ sidebarLeftTab: tab }),\n setOutlineSearch: (query) => set({ outlineSearchQuery: query }),\n toggleSidebarRight: (tab) =>\n set((state) => ({\n sidebarRightOpen: tab ? true : !state.sidebarRightOpen,\n sidebarRightTab: tab || state.sidebarRightTab,\n })),\n setAnnotationColor: (color) => set({ annotationColor: color }),\n\n addAnnotation: (ann) => {\n const shouldAutoSelect = ann.type === \"text\" || ann.type === \"comment\";\n set((state) => ({\n annotations: [...state.annotations, ann],\n selectedAnnotationId: shouldAutoSelect\n ? ann.id\n : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_CREATED, {\n annotation: ann,\n });\n },\n\n updateAnnotation: (id, updates) => {\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== id) return a;\n updatedAnnotation = {\n ...a,\n ...updates,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n addAnnotationReply: (annotationId, content) => {\n const nextContent = content.trim();\n if (!nextContent) return;\n\n const reply: AnnotationReply = {\n id: Math.random().toString(36).slice(2, 11),\n annotationId,\n content: nextContent,\n createdAt: Date.now(),\n };\n\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== annotationId) return a;\n const replies = [...(a.replies ?? []), reply];\n updatedAnnotation = {\n ...a,\n replies,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_REPLY_ADDED, {\n annotationId,\n reply,\n annotation: updatedAnnotation,\n });\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n removeAnnotation: (id) => {\n set((state) => ({\n annotations: state.annotations.filter((a) => a.id !== id),\n selectedAnnotationId:\n state.selectedAnnotationId === id ? null : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_DELETED, {\n annotationId: id,\n });\n },\n\n setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),\n setInteractionMode: (mode) => set({ interactionMode: mode }),\n setSelectionActive: (active) => set({ selectionActive: active }),\n setAccentColor: (color) => set({ accentColor: color }),\n\n setSearch: (query, results) => {\n set({\n searchQuery: query,\n searchResults: results,\n activeSearchIndex: results.length > 0 ? 0 : -1,\n });\n papyrusEvents.emit(PapyrusEventType.SEARCH_TRIGGERED, { query });\n },\n\n nextSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const nextIndex =\n (state.activeSearchIndex + 1) % state.searchResults.length;\n const pageIndex = state.searchResults[nextIndex].pageIndex;\n set({\n activeSearchIndex: nextIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n prevSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const prevIndex =\n (state.activeSearchIndex - 1 + state.searchResults.length) %\n state.searchResults.length;\n const pageIndex = state.searchResults[prevIndex].pageIndex;\n set({\n activeSearchIndex: prevIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n triggerScrollToPage: (pageIndex) =>\n set({ scrollToPageSignal: pageIndex, currentPage: pageIndex + 1 }),\n}));\n","\r\nimport { PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';\r\n\r\nexport class PapyrusEventEmitter {\r\n private listeners: Map<PapyrusEventType, Set<PapyrusEventListener<any>>> = new Map();\r\n\r\n on<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): () => void {\r\n if (!this.listeners.has(event)) {\r\n this.listeners.set(event, new Set());\r\n }\r\n this.listeners.get(event)!.add(listener);\r\n\r\n // Return an unsubscribe function\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): void {\r\n const eventListeners = this.listeners.get(event);\r\n if (eventListeners) {\r\n eventListeners.delete(listener);\r\n }\r\n }\r\n\r\n emit<T extends PapyrusEventType>(event: T, payload: EventPayloads[T]): void {\r\n const eventListeners = this.listeners.get(event);\r\n if (eventListeners) {\r\n eventListeners.forEach((listener) => listener(payload));\r\n }\r\n }\r\n}\r\n\r\n// Singleton instance for the core package\r\nexport const papyrusEvents = new PapyrusEventEmitter();\r\n","import { DocumentEngine, SearchResult } from \"@papyrus-sdk/types\";\n\nexport class SearchService {\n private engine: DocumentEngine;\n constructor(engine: DocumentEngine) {\n this.engine = engine;\n }\n\n async search(query: string): Promise<SearchResult[]> {\n const trimmedQuery = query.trim();\n if (!trimmedQuery || trimmedQuery.length < 2) return [];\n const normalizedQuery = this.normalizeForSearch(trimmedQuery);\n if (!normalizedQuery) return [];\n\n if (typeof this.engine.searchText === \"function\") {\n return await this.engine.searchText(trimmedQuery);\n }\n\n const results: SearchResult[] = [];\n const pageCount = this.engine.getPageCount();\n\n for (let i = 0; i < pageCount; i++) {\n const textContent = await this.engine.getTextContent(i);\n const rawPageText = textContent.map((item) => item.str).join(\" \");\n const cleanPageText = this.normalizeWhitespace(\n this.decodeHtmlEntities(this.stripMarkup(rawPageText))\n );\n if (!cleanPageText) continue;\n\n const { normalized, map } = this.normalizeWithMap(cleanPageText);\n if (!normalized) continue;\n\n let pos = normalized.indexOf(normalizedQuery, 0);\n let matchIndex = 0;\n while (pos !== -1) {\n const anchor = map[pos] ?? pos;\n const start = Math.max(0, anchor - 40);\n const end = Math.min(\n cleanPageText.length,\n anchor + trimmedQuery.length + 40\n );\n results.push({\n pageIndex: i,\n text: cleanPageText.substring(start, end),\n matchIndex: matchIndex++,\n });\n pos = normalized.indexOf(normalizedQuery, pos + 1);\n }\n }\n\n return results;\n }\n\n private normalizeForSearch(value: string): string {\n return value\n .toLocaleLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\");\n }\n\n private normalizeWithMap(value: string): {\n normalized: string;\n map: number[];\n } {\n let normalized = \"\";\n const map: number[] = [];\n\n for (let i = 0; i < value.length; i += 1) {\n const next = this.normalizeForSearch(value[i]);\n if (!next) continue;\n normalized += next;\n for (let j = 0; j < next.length; j += 1) {\n map.push(i);\n }\n }\n\n return { normalized, map };\n }\n\n private stripMarkup(value: string): string {\n if (!value) return \"\";\n return value\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \");\n }\n\n private decodeHtmlEntities(value: string): string {\n if (!value) return \"\";\n if (typeof document === \"undefined\") return value;\n\n const textArea = document.createElement(\"textarea\");\n textArea.innerHTML = value;\n return textArea.value;\n }\n\n private normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../engine.ts","../store.ts","../services/event-emitter.ts","../services/search-service.ts"],"sourcesContent":["\nimport { DocumentEngine, TextItem, OutlineItem, DocumentLoadInput, TextSelection, PageDestination } from '@papyrus-sdk/types';\n\nexport abstract class BaseDocumentEngine implements DocumentEngine {\n abstract load(source: DocumentLoadInput): Promise<void>;\n abstract getPageCount(): number;\n abstract getCurrentPage(): number;\n abstract goToPage(page: number): void;\n abstract setZoom(zoom: number): void;\n abstract getZoom(): number;\n abstract rotate(direction: 'clockwise' | 'counterclockwise'): void;\n abstract getRotation(): number;\n abstract renderPage(pageIndex: number, target: any, scale: number): Promise<void>;\n abstract renderTextLayer(pageIndex: number, container: any, scale: number): Promise<void>;\n abstract getTextContent(pageIndex: number): Promise<TextItem[]>;\n abstract getPageDimensions(pageIndex: number): Promise<{ width: number, height: number }>;\n abstract selectText(pageIndex: number, rect: { x: number; y: number; width: number; height: number }): Promise<TextSelection | null>;\n abstract getOutline(): Promise<OutlineItem[]>;\n abstract getPageIndex(dest: PageDestination): Promise<number | null>;\n abstract destroy(): void;\n}\n","import { create } from \"zustand\";\nimport {\n ViewMode,\n Annotation,\n AnnotationReply,\n SearchResult,\n UITheme,\n PageTheme,\n OutlineItem,\n ActiveSurface,\n CapabilityState,\n DocumentLocation,\n PapyrusEventType,\n PapyrusConfig,\n Locale,\n MobilePrimaryDestination,\n MobileShellState,\n ReadingMode,\n} from \"@papyrus-sdk/types\";\nimport { papyrusEvents } from \"./services/event-emitter\";\n\nconst perfNow = () =>\n typeof performance !== \"undefined\" && typeof performance.now === \"function\"\n ? performance.now()\n : Date.now();\n\nconst isMobilePerfEnabled = () => {\n const perfGlobal = (globalThis as Record<string, unknown>)\n .__PAPYRUS_MOBILE_PERF__;\n if (perfGlobal === true) return true;\n if (!perfGlobal || typeof perfGlobal !== \"object\") return false;\n return (perfGlobal as { enabled?: boolean }).enabled ?? true;\n};\n\nconst logStorePerf = (event: string, payload: Record<string, unknown>) => {\n if (!isMobilePerfEnabled()) return;\n console.log(`[Papyrus Perf][CoreStore] ${event}`, payload);\n};\n\nlet setDocumentStateWindowStart = 0;\nlet setDocumentStateCallsInWindow = 0;\n\ninterface ViewerState {\n isLoaded: boolean;\n pageCount: number;\n currentPage: number;\n zoom: number;\n rotation: number;\n viewMode: ViewMode;\n uiTheme: UITheme;\n pageTheme: PageTheme;\n locale: Locale;\n accentColor: string;\n annotationColor: string;\n annotationOpacity: number;\n inkStrokeWidth: number;\n activeDrawToolPreset: \"ink\" | \"highlight\" | \"underline\";\n outline: OutlineItem[];\n sidebarLeftOpen: boolean;\n sidebarLeftTab: \"thumbnails\" | \"summary\";\n outlineSearchQuery: string;\n sidebarRightOpen: boolean;\n sidebarRightTab: \"search\" | \"annotations\" | \"pages\";\n searchQuery: string;\n searchResults: SearchResult[];\n activeSearchIndex: number;\n scrollToPageSignal: number | null;\n annotations: Annotation[];\n activeTool:\n | \"select\"\n | \"highlight\"\n | \"underline\"\n | \"squiggly\"\n | \"strikeout\"\n | \"text\"\n | \"comment\"\n | \"ink\";\n selectedAnnotationId: string | null;\n interactionMode: \"pan\" | \"select\";\n selectionActive: boolean;\n toolDockOpen: boolean;\n mobileChromeVisible: boolean;\n readingMode: ReadingMode;\n activeSurface: ActiveSurface;\n documentLocation: DocumentLocation;\n capabilityState: CapabilityState;\n activeMobileDestination: MobilePrimaryDestination;\n mobileKeyboardOpen: boolean;\n mobileDockVisible: boolean;\n mobileProgressPillVisible: boolean;\n annotationUndoStack: Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>;\n annotationRedoStack: Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>;\n\n initializeStore: (config: PapyrusConfig) => void;\n setDocumentState: (state: Partial<ViewerState>) => void;\n toggleSidebarLeft: () => void;\n setSidebarLeftTab: (tab: \"thumbnails\" | \"summary\") => void;\n setOutlineSearch: (query: string) => void;\n toggleSidebarRight: (tab?: \"search\" | \"annotations\" | \"pages\") => void;\n addAnnotation: (annotation: Annotation) => void;\n updateAnnotation: (id: string, updates: Partial<Annotation>) => void;\n addAnnotationReply: (annotationId: string, content: string) => void;\n removeAnnotation: (id: string) => void;\n setSelectedAnnotation: (id: string | null) => void;\n setSearch: (query: string, results: SearchResult[]) => void;\n nextSearchResult: () => void;\n prevSearchResult: () => void;\n triggerScrollToPage: (pageIndex: number) => void;\n setAnnotationColor: (color: string) => void;\n setAnnotationOpacity: (opacity: number) => void;\n setInkStrokeWidth: (width: number) => void;\n undoAnnotations: () => void;\n redoAnnotations: () => void;\n setInteractionMode: (mode: \"pan\" | \"select\") => void;\n setSelectionActive: (active: boolean) => void;\n setAccentColor: (color: string) => void;\n openActiveSurface: (surface: Exclude<ActiveSurface, \"none\">) => void;\n closeActiveSurface: () => void;\n setDocumentLocation: (location: DocumentLocation) => void;\n setCapabilityState: (capabilityState: CapabilityState) => void;\n openMobileDestination: (destination: MobilePrimaryDestination) => void;\n closeMobileDestination: () => void;\n setMobileKeyboardOpen: (open: boolean) => void;\n}\n\nconst getDefaultCapabilityState = (): CapabilityState => ({\n status: \"unknown\",\n values: {},\n errors: [],\n});\n\nconst getDefaultViewerState = () => ({\n isLoaded: false,\n pageCount: 0,\n currentPage: 1,\n zoom: 1.0,\n rotation: 0,\n viewMode: \"continuous\" as ViewMode,\n uiTheme: \"light\" as UITheme,\n pageTheme: \"normal\" as PageTheme,\n locale: \"en\" as Locale,\n accentColor: \"#2563eb\",\n annotationColor: \"#fbbf24\",\n annotationOpacity: 1,\n inkStrokeWidth: 0.006,\n outline: [] as OutlineItem[],\n sidebarLeftOpen: true,\n sidebarLeftTab: \"thumbnails\" as const,\n outlineSearchQuery: \"\",\n sidebarRightOpen: false,\n sidebarRightTab: \"search\" as const,\n searchQuery: \"\",\n searchResults: [] as SearchResult[],\n activeSearchIndex: -1,\n scrollToPageSignal: null as number | null,\n annotations: [] as Annotation[],\n activeTool: \"select\" as const,\n activeDrawToolPreset: \"ink\" as const,\n selectedAnnotationId: null as string | null,\n interactionMode: \"pan\" as const,\n selectionActive: false,\n toolDockOpen: false,\n mobileChromeVisible: true,\n readingMode: \"focus\" as ReadingMode,\n activeSurface: \"none\" as ActiveSurface,\n documentLocation: {\n kind: \"page\" as const,\n label: \"1/0\",\n primaryValue: 1,\n secondaryValue: 0,\n } satisfies DocumentLocation,\n capabilityState: getDefaultCapabilityState(),\n activeMobileDestination: \"none\" as MobilePrimaryDestination,\n mobileKeyboardOpen: false,\n mobileDockVisible: true,\n mobileProgressPillVisible: true,\n annotationUndoStack: [] as Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>,\n annotationRedoStack: [] as Array<{\n annotations: Annotation[];\n selectedAnnotationId: string | null;\n }>,\n});\n\nconst deriveMobileShellState = ({\n activeMobileDestination,\n mobileKeyboardOpen,\n}: Pick<\n ViewerState,\n \"activeMobileDestination\" | \"mobileKeyboardOpen\"\n>): MobileShellState => {\n const keyboardOwnsSurface =\n mobileKeyboardOpen && activeMobileDestination === \"search\";\n\n return {\n activeMobileDestination,\n mobileKeyboardOpen,\n mobileDockVisible: !keyboardOwnsSurface,\n mobileProgressPillVisible: !keyboardOwnsSurface,\n };\n};\n\nexport const useViewerStore = create<ViewerState>((set, get) => ({\n ...getDefaultViewerState(),\n\n initializeStore: (config) =>\n set(() => {\n const defaults = getDefaultViewerState();\n return {\n ...defaults,\n currentPage: config.initialPage ?? defaults.currentPage,\n zoom: config.initialZoom ?? defaults.zoom,\n rotation: config.initialRotation ?? defaults.rotation,\n viewMode: config.initialViewMode ?? defaults.viewMode,\n uiTheme: config.initialUITheme ?? defaults.uiTheme,\n pageTheme: config.initialPageTheme ?? defaults.pageTheme,\n locale: config.initialLocale ?? defaults.locale,\n accentColor: config.initialAccentColor ?? defaults.accentColor,\n annotations: config.initialAnnotations ?? defaults.annotations,\n annotationUndoStack: defaults.annotationUndoStack,\n annotationRedoStack: defaults.annotationRedoStack,\n sidebarLeftOpen: config.sidebarLeftOpen ?? defaults.sidebarLeftOpen,\n sidebarRightOpen: config.sidebarRightOpen ?? defaults.sidebarRightOpen,\n };\n }),\n\n setDocumentState: (state) => {\n if (isMobilePerfEnabled()) {\n const now = perfNow();\n if (\n setDocumentStateWindowStart === 0 ||\n now - setDocumentStateWindowStart > 1000\n ) {\n setDocumentStateWindowStart = now;\n setDocumentStateCallsInWindow = 0;\n }\n\n setDocumentStateCallsInWindow += 1;\n if (setDocumentStateCallsInWindow === 12) {\n logStorePerf(\"setDocumentState.burst\", {\n calls: setDocumentStateCallsInWindow,\n windowMs: Math.round(now - setDocumentStateWindowStart),\n keys: Object.keys(state),\n });\n }\n }\n\n const oldPage = get().currentPage;\n const oldZoom = get().zoom;\n\n set((prev) => {\n const nextState = { ...prev, ...state };\n if (\n state.activeMobileDestination !== undefined ||\n state.mobileKeyboardOpen !== undefined\n ) {\n Object.assign(\n nextState,\n deriveMobileShellState({\n activeMobileDestination: nextState.activeMobileDestination,\n mobileKeyboardOpen: nextState.mobileKeyboardOpen,\n })\n );\n }\n return nextState;\n });\n\n if (state.currentPage !== undefined && state.currentPage !== oldPage) {\n papyrusEvents.emit(PapyrusEventType.PAGE_CHANGED, {\n pageNumber: state.currentPage,\n });\n }\n if (state.zoom !== undefined && state.zoom !== oldZoom) {\n papyrusEvents.emit(PapyrusEventType.ZOOM_CHANGED, { zoom: state.zoom });\n }\n if (state.isLoaded === true) {\n papyrusEvents.emit(PapyrusEventType.DOCUMENT_LOADED, {\n pageCount: get().pageCount,\n });\n }\n },\n\n toggleSidebarLeft: () =>\n set((state) => ({ sidebarLeftOpen: !state.sidebarLeftOpen })),\n setSidebarLeftTab: (tab) => set({ sidebarLeftTab: tab }),\n setOutlineSearch: (query) => set({ outlineSearchQuery: query }),\n toggleSidebarRight: (tab) =>\n set((state) => ({\n sidebarRightOpen: tab ? true : !state.sidebarRightOpen,\n sidebarRightTab: tab || state.sidebarRightTab,\n })),\n setAnnotationColor: (color) => set({ annotationColor: color }),\n setAnnotationOpacity: (opacity) =>\n set({ annotationOpacity: Math.min(1, Math.max(0.1, opacity)) }),\n setInkStrokeWidth: (width) =>\n set({ inkStrokeWidth: Math.min(0.02, Math.max(0.0025, width)) }),\n\n addAnnotation: (ann) => {\n const shouldAutoSelect = ann.type === \"text\" || ann.type === \"comment\";\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: [...state.annotations, ann],\n selectedAnnotationId: shouldAutoSelect\n ? ann.id\n : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_CREATED, {\n annotation: ann,\n });\n },\n\n updateAnnotation: (id, updates) => {\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: state.annotations.map((a) => {\n if (a.id !== id) return a;\n updatedAnnotation = {\n ...a,\n ...updates,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n addAnnotationReply: (annotationId, content) => {\n const nextContent = content.trim();\n if (!nextContent) return;\n\n const reply: AnnotationReply = {\n id: Math.random().toString(36).slice(2, 11),\n annotationId,\n content: nextContent,\n createdAt: Date.now(),\n };\n\n let updatedAnnotation: Annotation | null = null;\n set((state) => ({\n annotations: state.annotations.map((a) => {\n if (a.id !== annotationId) return a;\n const replies = [...(a.replies ?? []), reply];\n updatedAnnotation = {\n ...a,\n replies,\n updatedAt: Date.now(),\n };\n return updatedAnnotation;\n }),\n }));\n\n if (updatedAnnotation) {\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_REPLY_ADDED, {\n annotationId,\n reply,\n annotation: updatedAnnotation,\n });\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_UPDATED, {\n annotation: updatedAnnotation,\n });\n }\n },\n\n removeAnnotation: (id) => {\n set((state) => ({\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n annotationRedoStack: [],\n annotations: state.annotations.filter((a) => a.id !== id),\n selectedAnnotationId:\n state.selectedAnnotationId === id ? null : state.selectedAnnotationId,\n }));\n papyrusEvents.emit(PapyrusEventType.ANNOTATION_DELETED, {\n annotationId: id,\n });\n },\n\n undoAnnotations: () => {\n const state = get();\n const previous =\n state.annotationUndoStack[state.annotationUndoStack.length - 1];\n if (!previous) return;\n set({\n annotations: previous.annotations,\n selectedAnnotationId: previous.selectedAnnotationId,\n annotationUndoStack: state.annotationUndoStack.slice(0, -1),\n annotationRedoStack: [\n ...state.annotationRedoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n });\n },\n\n redoAnnotations: () => {\n const state = get();\n const next = state.annotationRedoStack[state.annotationRedoStack.length - 1];\n if (!next) return;\n set({\n annotations: next.annotations,\n selectedAnnotationId: next.selectedAnnotationId,\n annotationRedoStack: state.annotationRedoStack.slice(0, -1),\n annotationUndoStack: [\n ...state.annotationUndoStack,\n {\n annotations: state.annotations,\n selectedAnnotationId: state.selectedAnnotationId,\n },\n ].slice(-50),\n });\n },\n\n setSelectedAnnotation: (id) => set({ selectedAnnotationId: id }),\n setInteractionMode: (mode) => set({ interactionMode: mode }),\n setSelectionActive: (active) => set({ selectionActive: active }),\n setAccentColor: (color) => set({ accentColor: color }),\n openActiveSurface: (surface) =>\n set({\n activeSurface: surface,\n readingMode: \"modalSurfaceOpen\",\n mobileChromeVisible: true,\n }),\n closeActiveSurface: () =>\n set({\n activeSurface: \"none\",\n readingMode: \"controlsVisible\",\n }),\n setDocumentLocation: (location) => set({ documentLocation: location }),\n setCapabilityState: (capabilityState) => set({ capabilityState }),\n openMobileDestination: (destination) =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: destination,\n mobileKeyboardOpen: state.mobileKeyboardOpen,\n }),\n })),\n closeMobileDestination: () =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: \"none\",\n mobileKeyboardOpen: state.mobileKeyboardOpen,\n }),\n })),\n setMobileKeyboardOpen: (open) =>\n set((state) => ({\n ...deriveMobileShellState({\n activeMobileDestination: state.activeMobileDestination,\n mobileKeyboardOpen: open,\n }),\n })),\n\n setSearch: (query, results) => {\n set({\n searchQuery: query,\n searchResults: results,\n activeSearchIndex: results.length > 0 ? 0 : -1,\n });\n papyrusEvents.emit(PapyrusEventType.SEARCH_TRIGGERED, { query });\n },\n\n nextSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const nextIndex =\n (state.activeSearchIndex + 1) % state.searchResults.length;\n const pageIndex = state.searchResults[nextIndex].pageIndex;\n set({\n activeSearchIndex: nextIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n prevSearchResult: () => {\n const state = get();\n if (state.searchResults.length === 0) return;\n const prevIndex =\n (state.activeSearchIndex - 1 + state.searchResults.length) %\n state.searchResults.length;\n const pageIndex = state.searchResults[prevIndex].pageIndex;\n set({\n activeSearchIndex: prevIndex,\n scrollToPageSignal: pageIndex,\n currentPage: pageIndex + 1,\n });\n },\n\n triggerScrollToPage: (pageIndex) =>\n set({ scrollToPageSignal: pageIndex, currentPage: pageIndex + 1 }),\n}));\n","\nimport { PapyrusEventType, PapyrusEventListener, EventPayloads } from '@papyrus-sdk/types';\n\nexport class PapyrusEventEmitter {\n private listeners: Map<PapyrusEventType, Set<PapyrusEventListener<any>>> = new Map();\n\n on<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return an unsubscribe function\n return () => this.off(event, listener);\n }\n\n off<T extends PapyrusEventType>(event: T, listener: PapyrusEventListener<T>): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.delete(listener);\n }\n }\n\n emit<T extends PapyrusEventType>(event: T, payload: EventPayloads[T]): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.forEach((listener) => listener(payload));\n }\n }\n}\n\n// Singleton instance for the core package\nexport const papyrusEvents = new PapyrusEventEmitter();\n","import { DocumentEngine, SearchResult } from \"@papyrus-sdk/types\";\n\nexport class SearchService {\n private engine: DocumentEngine;\n constructor(engine: DocumentEngine) {\n this.engine = engine;\n }\n\n async search(query: string): Promise<SearchResult[]> {\n const trimmedQuery = query.trim();\n if (!trimmedQuery || trimmedQuery.length < 2) return [];\n const normalizedQuery = this.normalizeForSearch(trimmedQuery);\n if (!normalizedQuery) return [];\n\n if (typeof this.engine.searchText === \"function\") {\n return await this.engine.searchText(trimmedQuery);\n }\n\n const results: SearchResult[] = [];\n const pageCount = this.engine.getPageCount();\n\n for (let i = 0; i < pageCount; i++) {\n const textContent = await this.engine.getTextContent(i);\n const rawPageText = textContent.map((item) => item.str).join(\" \");\n const cleanPageText = this.normalizeWhitespace(\n this.decodeHtmlEntities(this.stripMarkup(rawPageText))\n );\n if (!cleanPageText) continue;\n\n const { normalized, map } = this.normalizeWithMap(cleanPageText);\n if (!normalized) continue;\n\n let pos = normalized.indexOf(normalizedQuery, 0);\n let matchIndex = 0;\n while (pos !== -1) {\n const anchor = map[pos] ?? pos;\n const start = Math.max(0, anchor - 40);\n const end = Math.min(\n cleanPageText.length,\n anchor + trimmedQuery.length + 40\n );\n results.push({\n pageIndex: i,\n text: cleanPageText.substring(start, end),\n matchIndex: matchIndex++,\n });\n pos = normalized.indexOf(normalizedQuery, pos + 1);\n }\n }\n\n return results;\n }\n\n private normalizeForSearch(value: string): string {\n return value\n .toLocaleLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\");\n }\n\n private normalizeWithMap(value: string): {\n normalized: string;\n map: number[];\n } {\n let normalized = \"\";\n const map: number[] = [];\n\n for (let i = 0; i < value.length; i += 1) {\n const next = this.normalizeForSearch(value[i]);\n if (!next) continue;\n normalized += next;\n for (let j = 0; j < next.length; j += 1) {\n map.push(i);\n }\n }\n\n return { normalized, map };\n }\n\n private stripMarkup(value: string): string {\n if (!value) return \"\";\n return value\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \" \")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \" \")\n .replace(/<[^>]+>/g, \" \");\n }\n\n private decodeHtmlEntities(value: string): string {\n if (!value) return \"\";\n if (typeof document === \"undefined\") return value;\n\n const textArea = document.createElement(\"textarea\");\n textArea.innerHTML = value;\n return textArea.value;\n }\n\n private normalizeWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papyrus-sdk/core",
3
- "version": "0.2.14",
3
+ "version": "0.2.15-beta.0",
4
4
  "license": "MIT",
5
5
  "keywords": [
6
6
  "papyrus",
@@ -42,7 +42,7 @@
42
42
  "build": "tsup index.ts --dts --format cjs,esm --out-dir dist --clean --sourcemap"
43
43
  },
44
44
  "dependencies": {
45
- "@papyrus-sdk/types": "0.2.6",
45
+ "@papyrus-sdk/types": "0.2.8-beta.0",
46
46
  "zustand": "^5.0.0"
47
47
  }
48
48
  }