@neobyzantine/series-player 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import * as _neobyzantine_types from '@neobyzantine/types';
3
+ import { HistoricalEvent } from '@neobyzantine/types';
4
+ import L from 'leaflet';
5
+
6
+ interface SeriesEntry {
7
+ slug: string;
8
+ title: string;
9
+ date_display?: string;
10
+ color?: string;
11
+ }
12
+ interface AnimationFeatureProperties {
13
+ sort_order: number;
14
+ label?: string;
15
+ narration?: string;
16
+ zoom?: number;
17
+ animation_pause_ms?: number;
18
+ [key: string]: unknown;
19
+ }
20
+ interface AnimationFeature {
21
+ type: 'Feature';
22
+ geometry: {
23
+ type: 'Point';
24
+ coordinates: [number, number];
25
+ };
26
+ properties: AnimationFeatureProperties;
27
+ }
28
+ interface AnimationFeatureCollection {
29
+ type: 'FeatureCollection';
30
+ features: AnimationFeature[];
31
+ }
32
+ interface AnimatorEvents {
33
+ step: {
34
+ index: number;
35
+ total: number;
36
+ props: AnimationFeatureProperties;
37
+ };
38
+ play: undefined;
39
+ pause: undefined;
40
+ reset: undefined;
41
+ complete: undefined;
42
+ }
43
+ type AnimatorEventName = keyof AnimatorEvents;
44
+
45
+ interface SeriesPlayerProps {
46
+ entries: SeriesEntry[];
47
+ onEventLoad: (slug: string) => Promise<HistoricalEvent>;
48
+ apiBase?: string;
49
+ /** Color for map animation pulses. Defaults to active entry color or gold. */
50
+ accentColor?: string;
51
+ ttsEnabled?: boolean;
52
+ autoPlayInterval?: number;
53
+ resolvePortrait?: (path: string) => string;
54
+ sanitizeHtml?: (html: string) => string;
55
+ onEventChange?: (index: number, event: HistoricalEvent) => void;
56
+ height?: string;
57
+ className?: string;
58
+ }
59
+ declare function SeriesPlayer({ entries, onEventLoad, accentColor, ttsEnabled, autoPlayInterval, resolvePortrait, sanitizeHtml, onEventChange, height, className, }: SeriesPlayerProps): React.JSX.Element;
60
+
61
+ interface SeriesStepListProps {
62
+ entries: SeriesEntry[];
63
+ currentIndex: number;
64
+ jumpHistory: number[];
65
+ onSelect: (index: number) => void;
66
+ }
67
+ declare function SeriesStepList({ entries, currentIndex, jumpHistory, onSelect }: SeriesStepListProps): React.JSX.Element;
68
+
69
+ interface SeriesEventPanelProps {
70
+ event: HistoricalEvent | null;
71
+ loading?: boolean;
72
+ error?: string | null;
73
+ accentColor?: string;
74
+ /** Convert storage path to URL — consumer knows the URL scheme. */
75
+ resolvePortrait?: (path: string) => string;
76
+ /** Sanitize HTML before dangerouslySetInnerHTML — consumer provides sanitizer. */
77
+ sanitizeHtml?: (html: string) => string;
78
+ onActorClick?: (actor: _neobyzantine_types.Actor) => void;
79
+ onRelatedClick?: (slug: string) => void;
80
+ className?: string;
81
+ }
82
+ declare function SeriesEventPanel({ event, loading, error, accentColor, resolvePortrait, sanitizeHtml, onActorClick, onRelatedClick, className, }: SeriesEventPanelProps): React.JSX.Element | null;
83
+
84
+ interface AnimatorControlsProps {
85
+ playing: boolean;
86
+ current: number;
87
+ total: number;
88
+ currentStep: AnimationFeatureProperties | null;
89
+ accentColor?: string;
90
+ onPlay: () => void;
91
+ onPause: () => void;
92
+ onReset: () => void;
93
+ onStepForward: () => void;
94
+ onStepBack: () => void;
95
+ }
96
+ declare function AnimatorControls({ playing, current, total, currentStep, accentColor, onPlay, onPause, onReset, onStepForward, onStepBack, }: AnimatorControlsProps): React.JSX.Element | null;
97
+
98
+ type Listener<K extends AnimatorEventName> = (data: AnimatorEvents[K]) => void;
99
+ interface EventAnimatorOptions {
100
+ stepMs?: number;
101
+ ttsEnabled?: boolean;
102
+ }
103
+ /**
104
+ * Step-by-step playback of a GeoJSON feature collection on a Leaflet map.
105
+ * Each Point feature represents one animation step: the map flies to it,
106
+ * a pulsing marker is shown, and optional TTS narration is spoken.
107
+ *
108
+ * Pure TypeScript class — no React. Wire into React via AnimatorDriver (uses useMap()).
109
+ */
110
+ declare class EventAnimator {
111
+ private readonly map;
112
+ private readonly color;
113
+ private readonly stepMs;
114
+ private ttsEnabled;
115
+ current: number;
116
+ playing: boolean;
117
+ private timer;
118
+ private pulseMarker;
119
+ private listeners;
120
+ readonly steps: AnimationFeature[];
121
+ constructor(map: L.Map, geojson: AnimationFeatureCollection, color: string, options?: EventAnimatorOptions);
122
+ get total(): number;
123
+ on<K extends AnimatorEventName>(event: K, fn: Listener<K>): this;
124
+ private emit;
125
+ play(): void;
126
+ pause(): void;
127
+ reset(): void;
128
+ stepForward(): void;
129
+ stepBack(): void;
130
+ setTTS(enabled: boolean): void;
131
+ private goto;
132
+ private schedule;
133
+ private clearPulse;
134
+ private speak;
135
+ }
136
+
137
+ interface AnimatedEventMapProps {
138
+ geojson: AnimationFeatureCollection | null;
139
+ color?: string;
140
+ stepMs?: number;
141
+ ttsEnabled?: boolean;
142
+ onAnimatorReady?: (animator: EventAnimator) => void;
143
+ onStep?: (data: AnimatorEvents['step']) => void;
144
+ onComplete?: () => void;
145
+ center?: [number, number];
146
+ zoom?: number;
147
+ height?: string;
148
+ className?: string;
149
+ }
150
+ declare function AnimatedEventMap({ geojson, color, stepMs, ttsEnabled, onAnimatorReady, onStep, onComplete, center, // Constantinople
151
+ zoom, height, className, }: AnimatedEventMapProps): React.JSX.Element;
152
+
153
+ interface SeriesPlayerState {
154
+ currentIndex: number;
155
+ event: HistoricalEvent | null;
156
+ loading: boolean;
157
+ error: string | null;
158
+ jumpHistory: number[];
159
+ autoPlaying: boolean;
160
+ }
161
+ interface SeriesPlayerActions {
162
+ next(): void;
163
+ prev(): void;
164
+ goTo(index: number): void;
165
+ jumpToRelated(slug: string): void;
166
+ backFromJump(): void;
167
+ toggleAutoPlay(): void;
168
+ }
169
+ declare function useSeriesPlayer(entries: SeriesEntry[], onEventLoad: (slug: string) => Promise<HistoricalEvent>, opts?: {
170
+ onEventChange?: (index: number, event: HistoricalEvent) => void;
171
+ autoPlayInterval?: number;
172
+ }): [SeriesPlayerState, SeriesPlayerActions];
173
+
174
+ export { AnimatedEventMap, type AnimatedEventMapProps, type AnimationFeature, type AnimationFeatureCollection, type AnimationFeatureProperties, AnimatorControls, type AnimatorControlsProps, type AnimatorEventName, type AnimatorEvents, EventAnimator, type EventAnimatorOptions, type SeriesEntry, SeriesEventPanel, type SeriesEventPanelProps, SeriesPlayer, type SeriesPlayerActions, type SeriesPlayerProps, type SeriesPlayerState, SeriesStepList, type SeriesStepListProps, useSeriesPlayer };
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import * as _neobyzantine_types from '@neobyzantine/types';
3
+ import { HistoricalEvent } from '@neobyzantine/types';
4
+ import L from 'leaflet';
5
+
6
+ interface SeriesEntry {
7
+ slug: string;
8
+ title: string;
9
+ date_display?: string;
10
+ color?: string;
11
+ }
12
+ interface AnimationFeatureProperties {
13
+ sort_order: number;
14
+ label?: string;
15
+ narration?: string;
16
+ zoom?: number;
17
+ animation_pause_ms?: number;
18
+ [key: string]: unknown;
19
+ }
20
+ interface AnimationFeature {
21
+ type: 'Feature';
22
+ geometry: {
23
+ type: 'Point';
24
+ coordinates: [number, number];
25
+ };
26
+ properties: AnimationFeatureProperties;
27
+ }
28
+ interface AnimationFeatureCollection {
29
+ type: 'FeatureCollection';
30
+ features: AnimationFeature[];
31
+ }
32
+ interface AnimatorEvents {
33
+ step: {
34
+ index: number;
35
+ total: number;
36
+ props: AnimationFeatureProperties;
37
+ };
38
+ play: undefined;
39
+ pause: undefined;
40
+ reset: undefined;
41
+ complete: undefined;
42
+ }
43
+ type AnimatorEventName = keyof AnimatorEvents;
44
+
45
+ interface SeriesPlayerProps {
46
+ entries: SeriesEntry[];
47
+ onEventLoad: (slug: string) => Promise<HistoricalEvent>;
48
+ apiBase?: string;
49
+ /** Color for map animation pulses. Defaults to active entry color or gold. */
50
+ accentColor?: string;
51
+ ttsEnabled?: boolean;
52
+ autoPlayInterval?: number;
53
+ resolvePortrait?: (path: string) => string;
54
+ sanitizeHtml?: (html: string) => string;
55
+ onEventChange?: (index: number, event: HistoricalEvent) => void;
56
+ height?: string;
57
+ className?: string;
58
+ }
59
+ declare function SeriesPlayer({ entries, onEventLoad, accentColor, ttsEnabled, autoPlayInterval, resolvePortrait, sanitizeHtml, onEventChange, height, className, }: SeriesPlayerProps): React.JSX.Element;
60
+
61
+ interface SeriesStepListProps {
62
+ entries: SeriesEntry[];
63
+ currentIndex: number;
64
+ jumpHistory: number[];
65
+ onSelect: (index: number) => void;
66
+ }
67
+ declare function SeriesStepList({ entries, currentIndex, jumpHistory, onSelect }: SeriesStepListProps): React.JSX.Element;
68
+
69
+ interface SeriesEventPanelProps {
70
+ event: HistoricalEvent | null;
71
+ loading?: boolean;
72
+ error?: string | null;
73
+ accentColor?: string;
74
+ /** Convert storage path to URL — consumer knows the URL scheme. */
75
+ resolvePortrait?: (path: string) => string;
76
+ /** Sanitize HTML before dangerouslySetInnerHTML — consumer provides sanitizer. */
77
+ sanitizeHtml?: (html: string) => string;
78
+ onActorClick?: (actor: _neobyzantine_types.Actor) => void;
79
+ onRelatedClick?: (slug: string) => void;
80
+ className?: string;
81
+ }
82
+ declare function SeriesEventPanel({ event, loading, error, accentColor, resolvePortrait, sanitizeHtml, onActorClick, onRelatedClick, className, }: SeriesEventPanelProps): React.JSX.Element | null;
83
+
84
+ interface AnimatorControlsProps {
85
+ playing: boolean;
86
+ current: number;
87
+ total: number;
88
+ currentStep: AnimationFeatureProperties | null;
89
+ accentColor?: string;
90
+ onPlay: () => void;
91
+ onPause: () => void;
92
+ onReset: () => void;
93
+ onStepForward: () => void;
94
+ onStepBack: () => void;
95
+ }
96
+ declare function AnimatorControls({ playing, current, total, currentStep, accentColor, onPlay, onPause, onReset, onStepForward, onStepBack, }: AnimatorControlsProps): React.JSX.Element | null;
97
+
98
+ type Listener<K extends AnimatorEventName> = (data: AnimatorEvents[K]) => void;
99
+ interface EventAnimatorOptions {
100
+ stepMs?: number;
101
+ ttsEnabled?: boolean;
102
+ }
103
+ /**
104
+ * Step-by-step playback of a GeoJSON feature collection on a Leaflet map.
105
+ * Each Point feature represents one animation step: the map flies to it,
106
+ * a pulsing marker is shown, and optional TTS narration is spoken.
107
+ *
108
+ * Pure TypeScript class — no React. Wire into React via AnimatorDriver (uses useMap()).
109
+ */
110
+ declare class EventAnimator {
111
+ private readonly map;
112
+ private readonly color;
113
+ private readonly stepMs;
114
+ private ttsEnabled;
115
+ current: number;
116
+ playing: boolean;
117
+ private timer;
118
+ private pulseMarker;
119
+ private listeners;
120
+ readonly steps: AnimationFeature[];
121
+ constructor(map: L.Map, geojson: AnimationFeatureCollection, color: string, options?: EventAnimatorOptions);
122
+ get total(): number;
123
+ on<K extends AnimatorEventName>(event: K, fn: Listener<K>): this;
124
+ private emit;
125
+ play(): void;
126
+ pause(): void;
127
+ reset(): void;
128
+ stepForward(): void;
129
+ stepBack(): void;
130
+ setTTS(enabled: boolean): void;
131
+ private goto;
132
+ private schedule;
133
+ private clearPulse;
134
+ private speak;
135
+ }
136
+
137
+ interface AnimatedEventMapProps {
138
+ geojson: AnimationFeatureCollection | null;
139
+ color?: string;
140
+ stepMs?: number;
141
+ ttsEnabled?: boolean;
142
+ onAnimatorReady?: (animator: EventAnimator) => void;
143
+ onStep?: (data: AnimatorEvents['step']) => void;
144
+ onComplete?: () => void;
145
+ center?: [number, number];
146
+ zoom?: number;
147
+ height?: string;
148
+ className?: string;
149
+ }
150
+ declare function AnimatedEventMap({ geojson, color, stepMs, ttsEnabled, onAnimatorReady, onStep, onComplete, center, // Constantinople
151
+ zoom, height, className, }: AnimatedEventMapProps): React.JSX.Element;
152
+
153
+ interface SeriesPlayerState {
154
+ currentIndex: number;
155
+ event: HistoricalEvent | null;
156
+ loading: boolean;
157
+ error: string | null;
158
+ jumpHistory: number[];
159
+ autoPlaying: boolean;
160
+ }
161
+ interface SeriesPlayerActions {
162
+ next(): void;
163
+ prev(): void;
164
+ goTo(index: number): void;
165
+ jumpToRelated(slug: string): void;
166
+ backFromJump(): void;
167
+ toggleAutoPlay(): void;
168
+ }
169
+ declare function useSeriesPlayer(entries: SeriesEntry[], onEventLoad: (slug: string) => Promise<HistoricalEvent>, opts?: {
170
+ onEventChange?: (index: number, event: HistoricalEvent) => void;
171
+ autoPlayInterval?: number;
172
+ }): [SeriesPlayerState, SeriesPlayerActions];
173
+
174
+ export { AnimatedEventMap, type AnimatedEventMapProps, type AnimationFeature, type AnimationFeatureCollection, type AnimationFeatureProperties, AnimatorControls, type AnimatorControlsProps, type AnimatorEventName, type AnimatorEvents, EventAnimator, type EventAnimatorOptions, type SeriesEntry, SeriesEventPanel, type SeriesEventPanelProps, SeriesPlayer, type SeriesPlayerActions, type SeriesPlayerProps, type SeriesPlayerState, SeriesStepList, type SeriesStepListProps, useSeriesPlayer };