@yoamigo.com/core 0.1.10 → 0.1.12

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.ts CHANGED
@@ -106,4 +106,393 @@ interface SafeHtmlProps {
106
106
  */
107
107
  declare function SafeHtml({ content, className, mode }: SafeHtmlProps): react_jsx_runtime.JSX.Element;
108
108
 
109
- export { type ContentStoreContextType, type ContentStoreMode, ContentStoreProvider, type ImageFieldValue, SafeHtml, type SafeHtmlProps, YaImage, type YaImageProps, YaText, type YaTextProps, serializeImageValue, useContentStore };
109
+ /**
110
+ * Animation state for a single field
111
+ */
112
+ interface AnimationState {
113
+ fieldId: string;
114
+ status: 'pending' | 'animating' | 'complete';
115
+ startTime: number;
116
+ duration: number;
117
+ onComplete?: () => void;
118
+ }
119
+ /**
120
+ * Configuration for queuing an animation
121
+ */
122
+ interface AnimationConfig {
123
+ duration: number;
124
+ onStart?: () => void;
125
+ onComplete?: () => void;
126
+ }
127
+ /**
128
+ * AI Edit Context value
129
+ */
130
+ interface AIEditContextValue {
131
+ /**
132
+ * Queue an animation for a field.
133
+ * If the field is already animating, the existing animation is cancelled.
134
+ */
135
+ queueAnimation: (fieldId: string, config: AnimationConfig) => void;
136
+ /**
137
+ * Cancel an animation for a field.
138
+ */
139
+ cancelAnimation: (fieldId: string) => void;
140
+ /**
141
+ * Check if a field is currently animating.
142
+ */
143
+ isAnimating: (fieldId: string) => boolean;
144
+ /**
145
+ * Get the animation state for a field.
146
+ */
147
+ getAnimationState: (fieldId: string) => AnimationState | undefined;
148
+ /**
149
+ * Register a listener for animation state changes.
150
+ * Returns an unsubscribe function.
151
+ */
152
+ subscribe: (fieldId: string, listener: () => void) => () => void;
153
+ /**
154
+ * Mark an animation as complete.
155
+ */
156
+ completeAnimation: (fieldId: string) => void;
157
+ }
158
+ /**
159
+ * Hook to access the AI Edit context.
160
+ * Must be used within an AIEditProvider.
161
+ */
162
+ declare function useAIEditContext(): AIEditContextValue;
163
+ /**
164
+ * Optional hook that returns null if not in provider.
165
+ * Useful for components that work both inside and outside the provider.
166
+ */
167
+ declare function useAIEditContextOptional(): AIEditContextValue | null;
168
+ interface AIEditProviderProps {
169
+ children: ReactNode;
170
+ /**
171
+ * Stagger delay between multiple simultaneous animations (ms)
172
+ * Default: 100ms
173
+ */
174
+ staggerDelay?: number;
175
+ }
176
+ /**
177
+ * AI Edit Provider
178
+ *
179
+ * Wrap your app with this to enable AI edit animations.
180
+ * Should be placed above ContentStoreProvider.
181
+ */
182
+ declare function AIEditProvider({ children, staggerDelay }: AIEditProviderProps): react_jsx_runtime.JSX.Element;
183
+
184
+ /**
185
+ * Text Diffing Utilities for AI Edit Animations
186
+ *
187
+ * Computes the difference between two text strings to enable
188
+ * character-by-character typing animations.
189
+ */
190
+ interface TextDiff {
191
+ /** Type of diff - 'simple' for plain text, 'complex' for HTML */
192
+ type: 'simple' | 'complex';
193
+ /** Characters/content to remove */
194
+ deletions: string;
195
+ /** Characters/content to add */
196
+ additions: string;
197
+ /** Unchanged text at the start */
198
+ commonPrefix: string;
199
+ /** Unchanged text at the end */
200
+ commonSuffix: string;
201
+ /** Original old text */
202
+ oldText: string;
203
+ /** Original new text */
204
+ newText: string;
205
+ }
206
+ /**
207
+ * Check if a string contains HTML tags
208
+ */
209
+ declare function containsHtml(text: string): boolean;
210
+ /**
211
+ * Strip HTML tags from a string, preserving text content
212
+ */
213
+ declare function stripHtml(html: string): string;
214
+ /**
215
+ * Compute the difference between two text strings.
216
+ *
217
+ * For simple text (no HTML), returns character-level diff.
218
+ * For HTML content, returns the full old/new for crossfade animation.
219
+ *
220
+ * @example
221
+ * ```ts
222
+ * const diff = computeTextDiff("Hello World", "Hello Universe")
223
+ * // diff.commonPrefix = "Hello "
224
+ * // diff.deletions = "World"
225
+ * // diff.additions = "Universe"
226
+ * // diff.commonSuffix = ""
227
+ * ```
228
+ */
229
+ declare function computeTextDiff(oldText: string, newText: string): TextDiff;
230
+ /**
231
+ * Build an intermediate string during a typing animation.
232
+ *
233
+ * @param diff - The computed text diff
234
+ * @param deleteProgress - Progress through deletion (0-1)
235
+ * @param typeProgress - Progress through typing (0-1)
236
+ * @returns The intermediate string to display
237
+ */
238
+ declare function buildIntermediateText(diff: TextDiff, deleteProgress: number, typeProgress: number): string;
239
+ /**
240
+ * Calculate animation timings based on text length.
241
+ *
242
+ * Uses adaptive timing:
243
+ * - Base: 50ms per character
244
+ * - Scales down for longer texts to stay under maxDuration
245
+ *
246
+ * @param diff - The computed text diff
247
+ * @param options - Timing options
248
+ * @returns Delete duration and type duration in ms
249
+ */
250
+ declare function calculateAnimationTiming(diff: TextDiff, options?: {
251
+ charDelay?: number;
252
+ maxDuration?: number;
253
+ }): {
254
+ deleteDuration: number;
255
+ typeDuration: number;
256
+ };
257
+
258
+ /**
259
+ * Animation Strategies for AI Edit Visualizations
260
+ *
261
+ * Pluggable strategies that define how different content types animate.
262
+ * Each strategy implements the AnimationStrategy interface.
263
+ */
264
+
265
+ /**
266
+ * Generic animation strategy interface.
267
+ * Implement this for custom content types.
268
+ */
269
+ interface AnimationStrategy<T> {
270
+ /** Strategy name for debugging */
271
+ name: string;
272
+ /**
273
+ * Check if this strategy can animate between two values.
274
+ * Return false if the change is too complex or values are identical.
275
+ */
276
+ canAnimate: (oldValue: T, newValue: T) => boolean;
277
+ /**
278
+ * Compute animation metadata from old and new values.
279
+ * This is called once at animation start.
280
+ */
281
+ prepare: (oldValue: T, newValue: T) => AnimationMetadata<T>;
282
+ /**
283
+ * Interpolate between old and new value at a given progress.
284
+ *
285
+ * @param metadata - Precomputed animation metadata
286
+ * @param progress - Animation progress from 0 to 1
287
+ * @returns The interpolated value to display
288
+ */
289
+ interpolate: (metadata: AnimationMetadata<T>, progress: number) => T;
290
+ }
291
+ /**
292
+ * Metadata computed once at animation start.
293
+ * Strategies can extend this with their own data.
294
+ */
295
+ interface AnimationMetadata<T> {
296
+ oldValue: T;
297
+ newValue: T;
298
+ /** Total animation duration in ms */
299
+ duration: number;
300
+ /** Strategy-specific data */
301
+ data?: unknown;
302
+ }
303
+ /**
304
+ * Text animation metadata with diff information
305
+ */
306
+ interface TextAnimationMetadata extends AnimationMetadata<string> {
307
+ data: {
308
+ diff: TextDiff;
309
+ deleteDuration: number;
310
+ typeDuration: number;
311
+ };
312
+ }
313
+ /**
314
+ * Text Typing Strategy
315
+ *
316
+ * Animates text changes character-by-character:
317
+ * 1. Delete phase: Remove old characters one by one
318
+ * 2. Type phase: Add new characters one by one
319
+ *
320
+ * For HTML content, falls back to quick crossfade.
321
+ */
322
+ declare const textTypingStrategy: AnimationStrategy<string>;
323
+ /**
324
+ * Image value type for image animations
325
+ */
326
+ interface ImageValue {
327
+ src: string;
328
+ alt?: string;
329
+ objectFit?: string;
330
+ objectPosition?: string;
331
+ focalPoint?: {
332
+ x: number;
333
+ y: number;
334
+ };
335
+ }
336
+ declare const imageCrossfadeStrategy: AnimationStrategy<ImageValue>;
337
+ /**
338
+ * Link value type for link animations
339
+ */
340
+ interface LinkValue {
341
+ text: string;
342
+ href: string;
343
+ }
344
+ /**
345
+ * Link Transition Strategy
346
+ *
347
+ * Animates link changes with text morphing and href highlight.
348
+ */
349
+ declare const linkTransitionStrategy: AnimationStrategy<LinkValue>;
350
+ /**
351
+ * Get cursor position for text typing animation.
352
+ * Returns null if no cursor should be shown.
353
+ */
354
+ declare function getTextCursorPosition(metadata: TextAnimationMetadata, progress: number): number | null;
355
+
356
+ /**
357
+ * useAIEditAnimation - Generic Animation Hook
358
+ *
359
+ * Component-agnostic hook that any editable component can use
360
+ * to animate content changes with AI edit visualization.
361
+ */
362
+
363
+ /**
364
+ * Animation phase
365
+ */
366
+ type AnimationPhase = 'idle' | 'animating' | 'complete';
367
+ /**
368
+ * Result returned by useAIEditAnimation
369
+ */
370
+ interface AnimationResult<T> {
371
+ /** Current value to render (may be mid-animation) */
372
+ displayValue: T;
373
+ /** True if animation is in progress */
374
+ isAnimating: boolean;
375
+ /** Current animation phase */
376
+ phase: AnimationPhase;
377
+ /** Animation progress from 0 to 1 */
378
+ progress: number;
379
+ /** Cancel the current animation */
380
+ cancel: () => void;
381
+ /** Props to spread on the wrapper element */
382
+ wrapperProps: {
383
+ className: string;
384
+ 'data-ai-editing': boolean;
385
+ };
386
+ }
387
+ /**
388
+ * Options for useAIEditAnimation
389
+ */
390
+ interface AnimationOptions<T> {
391
+ /** Whether animation is enabled (default: true) */
392
+ enabled?: boolean;
393
+ /** Animation strategy to use */
394
+ strategy: AnimationStrategy<T>;
395
+ /** Maximum animation duration in ms (default: 2000) */
396
+ maxDuration?: number;
397
+ /** Callback when animation starts */
398
+ onStart?: () => void;
399
+ /** Callback when animation completes */
400
+ onComplete?: () => void;
401
+ }
402
+ /**
403
+ * Generic animation hook for AI edit visualizations.
404
+ *
405
+ * @param fieldId - Unique identifier for this field
406
+ * @param value - Current value from content store
407
+ * @param options - Animation options including strategy
408
+ * @returns Animation result with display value and state
409
+ *
410
+ * @example
411
+ * ```tsx
412
+ * const { displayValue, isAnimating, wrapperProps } = useAIEditAnimation(
413
+ * 'hero.title',
414
+ * content,
415
+ * { strategy: textTypingStrategy }
416
+ * )
417
+ *
418
+ * return (
419
+ * <div {...wrapperProps}>
420
+ * {displayValue}
421
+ * </div>
422
+ * )
423
+ * ```
424
+ */
425
+ declare function useAIEditAnimation<T>(fieldId: string, value: T, options: AnimationOptions<T>): AnimationResult<T>;
426
+
427
+ /**
428
+ * useAnimatedText - Text-specific Animation Hook
429
+ *
430
+ * Convenience wrapper around useAIEditAnimation for text content.
431
+ * Provides typing animation with cursor position tracking.
432
+ */
433
+
434
+ /**
435
+ * Result returned by useAnimatedText
436
+ */
437
+ interface AnimatedTextResult {
438
+ /** Current text content to display (may be mid-animation) */
439
+ displayContent: string;
440
+ /** True if animation is in progress */
441
+ isAnimating: boolean;
442
+ /** Current animation phase */
443
+ phase: AnimationPhase;
444
+ /** Animation progress from 0 to 1 */
445
+ progress: number;
446
+ /** Cursor position in characters, or null if no cursor */
447
+ cursorPosition: number | null;
448
+ /** CSS class name for wrapper (ya-ai-editing, ya-ai-complete, or empty) */
449
+ wrapperClassName: string;
450
+ /** Cancel the current animation */
451
+ cancel: () => void;
452
+ }
453
+ /**
454
+ * Options for useAnimatedText
455
+ */
456
+ interface AnimatedTextOptions {
457
+ /** Whether animation is enabled (default: true) */
458
+ enabled?: boolean;
459
+ /** Delay per character in ms (default: 50) */
460
+ charDelay?: number;
461
+ /** Maximum animation duration in ms (default: 2000) */
462
+ maxDuration?: number;
463
+ /** Callback when animation starts */
464
+ onStart?: () => void;
465
+ /** Callback when animation completes */
466
+ onComplete?: () => void;
467
+ }
468
+ /**
469
+ * Text-specific animation hook for AI edit visualizations.
470
+ *
471
+ * Provides character-by-character typing animation with cursor tracking.
472
+ *
473
+ * @param fieldId - Unique identifier for this field
474
+ * @param content - Current text content from content store
475
+ * @param options - Animation options
476
+ * @returns Animation result with display content, cursor position, and state
477
+ *
478
+ * @example
479
+ * ```tsx
480
+ * const { displayContent, isAnimating, cursorPosition, wrapperClassName } = useAnimatedText(
481
+ * 'hero.title',
482
+ * content,
483
+ * { enabled: mode === 'inline-edit' && !isEditing }
484
+ * )
485
+ *
486
+ * return (
487
+ * <div className={wrapperClassName}>
488
+ * <SafeHtml content={displayContent} />
489
+ * {isAnimating && cursorPosition !== null && (
490
+ * <span className="ya-typing-cursor" />
491
+ * )}
492
+ * </div>
493
+ * )
494
+ * ```
495
+ */
496
+ declare function useAnimatedText(fieldId: string, content: string, options?: AnimatedTextOptions): AnimatedTextResult;
497
+
498
+ export { type AIEditContextValue, AIEditProvider, type AnimatedTextOptions, type AnimatedTextResult, type AnimationConfig, type AnimationMetadata, type AnimationOptions, type AnimationPhase, type AnimationResult, type AnimationState, type AnimationStrategy, type ContentStoreContextType, type ContentStoreMode, ContentStoreProvider, type ImageFieldValue, type ImageValue, type LinkValue, SafeHtml, type SafeHtmlProps, type TextAnimationMetadata, type TextDiff, YaImage, type YaImageProps, YaText, type YaTextProps, buildIntermediateText, calculateAnimationTiming, computeTextDiff, containsHtml, getTextCursorPosition, imageCrossfadeStrategy, linkTransitionStrategy, serializeImageValue, stripHtml, textTypingStrategy, useAIEditAnimation, useAIEditContext, useAIEditContextOptional, useAnimatedText, useContentStore };