@hapticjs/core 0.2.1 → 0.4.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.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { accessibility, gaming, notifications, presets, system, ui } from './presets/index.js';
1
+ export { accessibility, emotions, gaming, notifications, presets, system, ui } from './presets/index.js';
2
2
 
3
3
  /** A single step in a haptic sequence */
4
4
  interface HapticStep {
@@ -267,6 +267,270 @@ declare class FallbackManager {
267
267
  */
268
268
  declare function detectAdapter(): HapticAdapter;
269
269
 
270
+ /** Options for SoundEngine construction */
271
+ interface SoundEngineOptions {
272
+ enabled?: boolean;
273
+ volume?: number;
274
+ muted?: boolean;
275
+ }
276
+ /** Options for the click sound */
277
+ interface ClickOptions {
278
+ pitch?: 'low' | 'mid' | 'high';
279
+ volume?: number;
280
+ }
281
+ /** Options for the generic tone player */
282
+ interface ToneOptions {
283
+ waveform?: OscillatorType;
284
+ volume?: number;
285
+ decay?: boolean;
286
+ }
287
+ /**
288
+ * Lightweight audio feedback engine using Web Audio API.
289
+ * Produces tiny UI sounds synced with haptics — all procedurally generated.
290
+ */
291
+ declare class SoundEngine {
292
+ private ctx;
293
+ private masterVolume;
294
+ private _muted;
295
+ private _enabled;
296
+ constructor(options?: SoundEngineOptions);
297
+ /** Short click sound */
298
+ click(options?: ClickOptions): Promise<void>;
299
+ /** Ultra-short tick sound */
300
+ tick(): Promise<void>;
301
+ /** Bubbly pop sound — quick frequency sweep high to low */
302
+ pop(): Promise<void>;
303
+ /** Swipe/swoosh sound — noise with quick fade */
304
+ whoosh(): Promise<void>;
305
+ /** Musical chime */
306
+ chime(note?: 'C4' | 'E4' | 'G4' | 'C5'): Promise<void>;
307
+ /** Low buzzer/error tone — two descending tones */
308
+ error(): Promise<void>;
309
+ /** Ascending two-tone success sound */
310
+ success(): Promise<void>;
311
+ /** Subtle tap sound */
312
+ tap(): Promise<void>;
313
+ /** Toggle sound — ascending for on, descending for off */
314
+ toggle(on: boolean): Promise<void>;
315
+ /** Generic tone player */
316
+ playTone(frequency: number, duration: number, options?: ToneOptions): Promise<void>;
317
+ /** Set master volume (0-1) */
318
+ setVolume(volume: number): void;
319
+ /** Mute all sounds */
320
+ mute(): void;
321
+ /** Unmute sounds */
322
+ unmute(): void;
323
+ /** Whether sounds are currently muted */
324
+ get muted(): boolean;
325
+ /** Current master volume */
326
+ get volume(): number;
327
+ /** Whether the engine is enabled */
328
+ get enabled(): boolean;
329
+ /** Close AudioContext and release resources */
330
+ dispose(): void;
331
+ /** Lazily create and return AudioContext, handling autoplay policy */
332
+ private _getContext;
333
+ /** Compute effective volume from master + per-sound volume */
334
+ private _effectiveVolume;
335
+ /** Schedule a tone at a specific AudioContext time */
336
+ private _scheduleTone;
337
+ }
338
+
339
+ /** Options for VisualEngine construction */
340
+ interface VisualEngineOptions {
341
+ enabled?: boolean;
342
+ target?: HTMLElement;
343
+ intensity?: number;
344
+ }
345
+ interface FlashOptions {
346
+ color?: string;
347
+ duration?: number;
348
+ opacity?: number;
349
+ }
350
+ interface ShakeOptions {
351
+ intensity?: number;
352
+ duration?: number;
353
+ }
354
+ interface PulseOptions {
355
+ scale?: number;
356
+ duration?: number;
357
+ }
358
+ interface RippleOptions {
359
+ color?: string;
360
+ size?: number;
361
+ duration?: number;
362
+ }
363
+ interface GlowOptions {
364
+ color?: string;
365
+ duration?: number;
366
+ size?: number;
367
+ }
368
+ interface BounceOptions$1 {
369
+ height?: number;
370
+ duration?: number;
371
+ }
372
+ interface JelloOptions {
373
+ intensity?: number;
374
+ duration?: number;
375
+ }
376
+ interface RubberOptions {
377
+ scaleX?: number;
378
+ scaleY?: number;
379
+ duration?: number;
380
+ }
381
+ interface HighlightOptions {
382
+ color?: string;
383
+ duration?: number;
384
+ }
385
+ /**
386
+ * CSS-based visual feedback effects that complement haptic patterns.
387
+ * Works everywhere including desktop/iOS where vibration is unavailable.
388
+ */
389
+ declare class VisualEngine {
390
+ private _enabled;
391
+ private _target;
392
+ private _intensity;
393
+ private _styleInjected;
394
+ private _cleanups;
395
+ constructor(options?: VisualEngineOptions);
396
+ /** Quick screen flash overlay */
397
+ flash(options?: FlashOptions): void;
398
+ /** CSS shake animation on target */
399
+ shake(options?: ShakeOptions): void;
400
+ /** Scale pulse animation */
401
+ pulse(options?: PulseOptions): void;
402
+ /** Material Design style ripple at coordinates */
403
+ ripple(x: number, y: number, options?: RippleOptions): void;
404
+ /** Box shadow glow effect */
405
+ glow(options?: GlowOptions): void;
406
+ /** Bounce animation on target */
407
+ bounce(options?: BounceOptions$1): void;
408
+ /** Jello/wobble animation */
409
+ jello(options?: JelloOptions): void;
410
+ /** Rubber band scale effect */
411
+ rubber(options?: RubberOptions): void;
412
+ /** Brief background color highlight */
413
+ highlight(options?: HighlightOptions): void;
414
+ /** Change the target element for animations */
415
+ setTarget(element: HTMLElement): void;
416
+ /** Whether the engine is enabled */
417
+ get enabled(): boolean;
418
+ /** Current intensity multiplier */
419
+ get intensity(): number;
420
+ /** Remove all active animations and clean up */
421
+ dispose(): void;
422
+ private _canRun;
423
+ private _getTarget;
424
+ /** Inject a <style> tag for keyframes on first use */
425
+ private _injectStyles;
426
+ /** Ensure a @keyframes rule exists in our style tag */
427
+ private _ensureKeyframes;
428
+ /** Apply a CSS animation to an element and clean up after */
429
+ private _applyAnimation;
430
+ private _removeCleanup;
431
+ }
432
+
433
+ /** Multi-sensory theme preset — configures haptic, sound, and visual behavior */
434
+ interface ThemePreset {
435
+ name: string;
436
+ hapticIntensity: number;
437
+ soundEnabled: boolean;
438
+ soundVolume: number;
439
+ visualEnabled: boolean;
440
+ visualStyle: 'flash' | 'ripple' | 'shake' | 'glow' | 'pulse';
441
+ colors: {
442
+ primary: string;
443
+ success: string;
444
+ error: string;
445
+ warning: string;
446
+ };
447
+ }
448
+ /** Built-in theme presets */
449
+ declare const themes: Record<string, ThemePreset>;
450
+ /**
451
+ * Manages multi-sensory themes that configure haptic, sound, and visual behavior.
452
+ */
453
+ declare class ThemeManager {
454
+ private _current;
455
+ private _registry;
456
+ constructor();
457
+ /** Apply a theme by name or provide a custom preset */
458
+ setTheme(name: string | ThemePreset): void;
459
+ /** Get the current theme preset */
460
+ getTheme(): ThemePreset;
461
+ /** Current theme name */
462
+ get current(): string;
463
+ /** List all available theme names */
464
+ listThemes(): string[];
465
+ /** Register a custom theme preset */
466
+ registerTheme(preset: ThemePreset): void;
467
+ }
468
+
469
+ /** Options for the SensoryEngine */
470
+ interface SensoryEngineOptions {
471
+ haptic?: Partial<HapticConfig>;
472
+ sound?: {
473
+ enabled?: boolean;
474
+ volume?: number;
475
+ muted?: boolean;
476
+ };
477
+ visual?: {
478
+ enabled?: boolean;
479
+ target?: HTMLElement;
480
+ intensity?: number;
481
+ };
482
+ theme?: string | ThemePreset;
483
+ }
484
+ /**
485
+ * Higher-level engine that combines haptic + sound + visual feedback.
486
+ * Ties HapticEngine, SoundEngine, VisualEngine, and ThemeManager together.
487
+ *
488
+ * Usage:
489
+ * const engine = SensoryEngine.create();
490
+ * engine.tap();
491
+ * engine.success();
492
+ * engine.setTheme('gaming');
493
+ */
494
+ declare class SensoryEngine {
495
+ private _haptic;
496
+ private _sound;
497
+ private _visual;
498
+ private _themes;
499
+ constructor(options?: SensoryEngineOptions);
500
+ /** Factory method */
501
+ static create(options?: SensoryEngineOptions): SensoryEngine;
502
+ /** Tap: vibrate + click sound + pulse visual */
503
+ tap(): Promise<void>;
504
+ /** Success: haptic success + success sound + green glow */
505
+ success(): Promise<void>;
506
+ /** Error: haptic error + error sound + red flash */
507
+ error(): Promise<void>;
508
+ /** Warning: haptic warning + warning sound + yellow flash */
509
+ warning(): Promise<void>;
510
+ /** Selection: haptic selection + tick sound + subtle pulse */
511
+ selection(): Promise<void>;
512
+ /** Toggle: haptic toggle + toggle sound + pulse */
513
+ toggle(on: boolean): Promise<void>;
514
+ /** Play a haptic pattern (sound/visual auto-mapped from theme) */
515
+ play(pattern: string | HapticPattern | HapticStep[]): Promise<void>;
516
+ /** Apply a theme by name or preset */
517
+ setTheme(name: string | ThemePreset): void;
518
+ /** Access the underlying HapticEngine */
519
+ get haptic(): HapticEngine;
520
+ /** Access the SoundEngine */
521
+ get sound(): SoundEngine;
522
+ /** Access the VisualEngine */
523
+ get visual(): VisualEngine;
524
+ /** Access the ThemeManager */
525
+ get themes(): ThemeManager;
526
+ /** Configure all engines */
527
+ configure(options: SensoryEngineOptions): void;
528
+ /** Clean up all engines */
529
+ dispose(): void;
530
+ /** Run the appropriate visual effect based on theme style */
531
+ private _runVisual;
532
+ }
533
+
270
534
  /**
271
535
  * No-op adapter — used in SSR, Node, or when no haptic hardware is available.
272
536
  * Silently accepts all calls without doing anything.
@@ -436,6 +700,450 @@ declare function patternToDataURL(input: ExportInput, options?: ExportOptions):
436
700
  */
437
701
  declare function patternFromDataURL(url: string): HapticPattern;
438
702
 
703
+ /** A single recorded tap event */
704
+ interface RecordedTap {
705
+ /** Timestamp in ms relative to recording start */
706
+ time: number;
707
+ /** Intensity from 0.0 to 1.0 */
708
+ intensity: number;
709
+ }
710
+ /** Callback invoked on each tap during recording */
711
+ type TapCallback = (tap: RecordedTap, index: number) => void;
712
+ /**
713
+ * Records tap rhythms and converts them to HPL pattern strings or HapticSteps.
714
+ *
715
+ * Usage:
716
+ * const recorder = new PatternRecorder();
717
+ * recorder.start();
718
+ * recorder.tap(); // user taps...
719
+ * recorder.tap(0.9); // heavy tap
720
+ * recorder.stop();
721
+ * console.log(recorder.toHPL()); // '##..@@'
722
+ */
723
+ declare class PatternRecorder {
724
+ private taps;
725
+ private recording;
726
+ private startTime;
727
+ private stopTime;
728
+ private tapCallbacks;
729
+ private nowFn;
730
+ constructor(options?: {
731
+ now?: () => number;
732
+ });
733
+ /** Whether the recorder is currently recording */
734
+ get isRecording(): boolean;
735
+ /** Total duration of the recording in ms */
736
+ get duration(): number;
737
+ /** Number of taps recorded */
738
+ get tapCount(): number;
739
+ /** Begin recording. Records timestamps of tap events. */
740
+ start(): void;
741
+ /** Register a tap at current time. */
742
+ tap(intensity?: number): void;
743
+ /** Stop recording, return the recorded taps. */
744
+ stop(): RecordedTap[];
745
+ /** Register a callback for each tap (for visual feedback during recording). */
746
+ onTap(callback: TapCallback): void;
747
+ /** Reset the recorder. */
748
+ clear(): void;
749
+ /**
750
+ * Snap taps to a grid for cleaner patterns.
751
+ * @param gridMs Grid size in ms (default 50ms)
752
+ */
753
+ quantize(gridMs?: number): void;
754
+ /**
755
+ * Convert recorded taps to an HPL string.
756
+ *
757
+ * Maps gaps between taps to `.` characters (each 50ms),
758
+ * and tap intensities to `~` (light), `#` (medium), `@` (heavy).
759
+ */
760
+ toHPL(): string;
761
+ /** Convert recorded taps to HapticStep[]. */
762
+ toSteps(): HapticStep[];
763
+ /** Convert recorded taps to a HapticPattern. */
764
+ toPattern(name?: string): HapticPattern;
765
+ }
766
+
767
+ interface SpringOptions {
768
+ /** Spring stiffness 0.5-1.0 */
769
+ stiffness?: number;
770
+ /** Damping factor 0.1-0.9 */
771
+ damping?: number;
772
+ /** Total duration in ms */
773
+ duration?: number;
774
+ }
775
+ interface BounceOptions {
776
+ /** Initial height 0.5-1.0 */
777
+ height?: number;
778
+ /** Bounciness factor 0.3-0.9 */
779
+ bounciness?: number;
780
+ /** Number of bounces */
781
+ bounces?: number;
782
+ }
783
+ interface FrictionOptions {
784
+ /** Surface roughness 0.1-1.0 */
785
+ roughness?: number;
786
+ /** Sliding speed 0.1-1.0 */
787
+ speed?: number;
788
+ /** Total duration in ms */
789
+ duration?: number;
790
+ }
791
+ interface ImpactOptions {
792
+ /** Object mass 0.1-1.0 */
793
+ mass?: number;
794
+ /** Surface hardness 0.1-1.0 */
795
+ hardness?: number;
796
+ }
797
+ interface GravityOptions {
798
+ /** Fall distance 0.3-1.0 */
799
+ distance?: number;
800
+ /** Total duration in ms */
801
+ duration?: number;
802
+ }
803
+ interface ElasticOptions {
804
+ /** Stretch amount 0.3-1.0 */
805
+ stretch?: number;
806
+ /** Snap-back speed 0.3-1.0 */
807
+ snapSpeed?: number;
808
+ }
809
+ interface WaveOptions {
810
+ /** Wave amplitude 0.3-1.0 */
811
+ amplitude?: number;
812
+ /** Wave frequency 0.5-2.0 */
813
+ frequency?: number;
814
+ /** Number of full cycles */
815
+ cycles?: number;
816
+ }
817
+ interface PendulumOptions {
818
+ /** Swing energy 0.3-1.0 */
819
+ energy?: number;
820
+ /** Number of swings */
821
+ swings?: number;
822
+ }
823
+ /** Bouncy spring oscillation — starts heavy, bounces with decreasing intensity */
824
+ declare function spring(options?: SpringOptions): HapticPattern;
825
+ /** Ball bouncing — each bounce is shorter and lighter */
826
+ declare function bounce(options?: BounceOptions): HapticPattern;
827
+ /** Rough surface sliding — continuous but slightly irregular vibration */
828
+ declare function friction(options?: FrictionOptions): HapticPattern;
829
+ /** Collision with surface — sharp initial hit followed by resonance */
830
+ declare function impact(options?: ImpactOptions): HapticPattern;
831
+ /** Falling sensation — accelerating intensity */
832
+ declare function gravity(options?: GravityOptions): HapticPattern;
833
+ /** Rubber band snap — stretch and snap back */
834
+ declare function elastic(options?: ElasticOptions): HapticPattern;
835
+ /** Ocean wave motion — smooth sine-wave-like intensity */
836
+ declare function wave(options?: WaveOptions): HapticPattern;
837
+ /** Swinging motion — intensity peaks at ends, quiet in middle */
838
+ declare function pendulum(options?: PendulumOptions): HapticPattern;
839
+
840
+ /** All physics-based haptic pattern generators */
841
+ declare const physics: {
842
+ readonly spring: typeof spring;
843
+ readonly bounce: typeof bounce;
844
+ readonly friction: typeof friction;
845
+ readonly impact: typeof impact;
846
+ readonly gravity: typeof gravity;
847
+ readonly elastic: typeof elastic;
848
+ readonly wave: typeof wave;
849
+ readonly pendulum: typeof pendulum;
850
+ };
851
+
852
+ /** A middleware that intercepts and transforms haptic patterns before playback */
853
+ type HapticMiddleware = {
854
+ name: string;
855
+ process: (steps: HapticStep[]) => HapticStep[];
856
+ };
857
+ /**
858
+ * Manages a pipeline of middleware that transform haptic patterns.
859
+ *
860
+ * Usage:
861
+ * const manager = new MiddlewareManager();
862
+ * manager.use(intensityScaler(0.5));
863
+ * manager.use(durationScaler(2));
864
+ * const transformed = manager.process(steps);
865
+ */
866
+ declare class MiddlewareManager {
867
+ private middleware;
868
+ /** Register a middleware */
869
+ use(middleware: HapticMiddleware): void;
870
+ /** Remove a middleware by name */
871
+ remove(name: string): void;
872
+ /** Run all middleware in order */
873
+ process(steps: HapticStep[]): HapticStep[];
874
+ /** Remove all middleware */
875
+ clear(): void;
876
+ /** List registered middleware names */
877
+ list(): string[];
878
+ }
879
+ /** Multiplies all intensities by a scale factor, clamped to 0-1 */
880
+ declare function intensityScaler(scale: number): HapticMiddleware;
881
+ /** Multiplies all durations by a scale factor, enforces minimum 20ms */
882
+ declare function durationScaler(scale: number): HapticMiddleware;
883
+ /** Clamps all intensities to [min, max] */
884
+ declare function intensityClamper(min: number, max: number): HapticMiddleware;
885
+ /** Repeats the entire pattern N times */
886
+ declare function patternRepeater(times: number): HapticMiddleware;
887
+ /** Reverses the step order */
888
+ declare function reverser(): HapticMiddleware;
889
+ /** Increases all intensities by 30% and durations by 20% for accessibility */
890
+ declare function accessibilityBooster(): HapticMiddleware;
891
+
892
+ /** User preference profile that scales all haptic feedback */
893
+ type IntensityProfile = {
894
+ name: string;
895
+ /** 0-2 multiplier for vibration intensity */
896
+ hapticScale: number;
897
+ /** 0-2 multiplier for durations */
898
+ durationScale: number;
899
+ /** Whether sound feedback is enabled */
900
+ soundEnabled: boolean;
901
+ /** Sound volume from 0-1 */
902
+ soundVolume: number;
903
+ /** Whether visual feedback is enabled */
904
+ visualEnabled: boolean;
905
+ };
906
+ declare const profiles: Record<string, IntensityProfile>;
907
+ /**
908
+ * Manages user intensity profiles for haptic feedback.
909
+ *
910
+ * Usage:
911
+ * const pm = new ProfileManager();
912
+ * pm.setProfile('strong');
913
+ * const mw = pm.toMiddleware();
914
+ */
915
+ declare class ProfileManager {
916
+ private currentProfile;
917
+ private registry;
918
+ constructor();
919
+ /** Apply a profile by name or custom profile object */
920
+ setProfile(name: string | IntensityProfile): void;
921
+ /** Get the current profile */
922
+ getProfile(): IntensityProfile;
923
+ /** List available profile names */
924
+ listProfiles(): string[];
925
+ /** Register a custom profile */
926
+ registerProfile(profile: IntensityProfile): void;
927
+ /** Convert current profile to a HapticMiddleware (intensity + duration scaling) */
928
+ toMiddleware(): HapticMiddleware;
929
+ /** Current profile name */
930
+ get current(): string;
931
+ }
932
+
933
+ /** Aggregated results per variant */
934
+ interface VariantResult {
935
+ assignments: number;
936
+ events: Record<string, number>;
937
+ }
938
+ /**
939
+ * A/B test different haptic patterns to see which users prefer.
940
+ *
941
+ * Usage:
942
+ * const exp = new HapticExperiment('checkout', { a: 'tap', b: 'success' });
943
+ * const variant = exp.assign('user-123');
944
+ * const pattern = exp.getVariant('user-123');
945
+ * exp.track('user-123', 'conversion');
946
+ */
947
+ declare class HapticExperiment {
948
+ private _name;
949
+ private variants;
950
+ private variantNames;
951
+ private assignments;
952
+ private tracking;
953
+ constructor(name: string, variants: Record<string, string | HapticPattern | HapticStep[]>);
954
+ /** Experiment name */
955
+ get name(): string;
956
+ /**
957
+ * Randomly assign a variant (consistent for same userId via simple hash).
958
+ * If no userId is provided, generates a random assignment.
959
+ */
960
+ assign(userId?: string): string;
961
+ /** Get the assigned variant pattern for a user */
962
+ getVariant(userId?: string): string | HapticPattern | HapticStep[] | undefined;
963
+ /** Track an event for a user */
964
+ track(userId: string, event: string, value?: number): void;
965
+ /** Get aggregated results per variant */
966
+ getResults(): Record<string, VariantResult>;
967
+ /** Clear all tracking data and assignments */
968
+ reset(): void;
969
+ /** Simple string hash for deterministic variant assignment */
970
+ private _hash;
971
+ }
972
+
973
+ /**
974
+ * RhythmSync — sync haptic feedback to audio/music BPM.
975
+ *
976
+ * Provides beat detection via tap tempo, BPM control,
977
+ * and automatic haptic triggering on each beat.
978
+ */
979
+ interface RhythmSyncOptions {
980
+ /** Beats per minute (60-300) */
981
+ bpm?: number;
982
+ /** Global intensity multiplier (0-1) */
983
+ intensity?: number;
984
+ /** HPL pattern string to play on each beat */
985
+ pattern?: string;
986
+ }
987
+ declare class RhythmSync {
988
+ private _bpm;
989
+ private _intensity;
990
+ private _pattern;
991
+ private _isPlaying;
992
+ private _beatCount;
993
+ private _intervalId;
994
+ private _callbacks;
995
+ private _tapTimestamps;
996
+ private _audioElement;
997
+ private _syncEngine;
998
+ private _syncEffect;
999
+ constructor(options?: RhythmSyncOptions);
1000
+ /** Set beats per minute (clamped to 60-300) */
1001
+ setBPM(bpm: number): void;
1002
+ /**
1003
+ * Store an audio element reference for sync.
1004
+ * Since Web Audio API's AnalyserNode isn't reliably available in all
1005
+ * environments, use tapTempo() for BPM detection instead.
1006
+ */
1007
+ detectBPM(audioElement: unknown): void;
1008
+ /**
1009
+ * Tap tempo — call repeatedly to set BPM from tap intervals.
1010
+ * Calculates average BPM from the last 4-8 taps.
1011
+ * Returns the current estimated BPM.
1012
+ */
1013
+ tapTempo(): number;
1014
+ /** Start emitting beats at the current BPM */
1015
+ start(callback?: (beat: number) => void): void;
1016
+ /** Stop the rhythm */
1017
+ stop(): void;
1018
+ /** Register a beat callback */
1019
+ onBeat(callback: (beat: number) => void): void;
1020
+ /**
1021
+ * Auto-trigger a haptic effect on each beat.
1022
+ * Calls engine.tap() by default, or the specified semantic method.
1023
+ */
1024
+ syncHaptic(engine: any, effect?: string): void;
1025
+ /** Current BPM */
1026
+ get bpm(): number;
1027
+ /** Whether rhythm is active */
1028
+ get isPlaying(): boolean;
1029
+ /** Total beats since start */
1030
+ get beatCount(): number;
1031
+ /** Current pattern string */
1032
+ get pattern(): string;
1033
+ /** The attached audio element, if any */
1034
+ get audioElement(): unknown;
1035
+ /** Clean up intervals and callbacks */
1036
+ dispose(): void;
1037
+ private _startInterval;
1038
+ private _stopInterval;
1039
+ }
1040
+
1041
+ /**
1042
+ * MotionDetector — detect device motion (shake, tilt, rotation) as INPUT
1043
+ * to trigger haptic feedback.
1044
+ *
1045
+ * Uses DeviceMotionEvent and DeviceOrientationEvent when available.
1046
+ * Handles SSR gracefully by checking for window/document.
1047
+ */
1048
+ interface MotionDetectorOptions {
1049
+ /** Acceleration magnitude threshold for shake detection (default: 15) */
1050
+ shakeThreshold?: number;
1051
+ /** Tilt angle change threshold in degrees (default: 10) */
1052
+ tiltThreshold?: number;
1053
+ }
1054
+ declare class MotionDetector {
1055
+ private _shakeThreshold;
1056
+ private _tiltThreshold;
1057
+ private _isListening;
1058
+ private _callbacks;
1059
+ private _lastOrientation;
1060
+ private _lastFlipState;
1061
+ private _boundMotionHandler;
1062
+ private _boundOrientationHandler;
1063
+ constructor(options?: MotionDetectorOptions);
1064
+ /** Whether DeviceMotion API is available */
1065
+ get isSupported(): boolean;
1066
+ /** Whether currently listening for motion events */
1067
+ get isListening(): boolean;
1068
+ /**
1069
+ * Request permission for motion events (required on iOS 13+).
1070
+ * Returns true if permission was granted.
1071
+ */
1072
+ requestPermission(): Promise<boolean>;
1073
+ /** Begin listening to device motion and orientation events */
1074
+ start(): void;
1075
+ /** Stop listening to motion events */
1076
+ stop(): void;
1077
+ /** Register callback for shake events. Intensity is 0-1 based on acceleration. */
1078
+ onShake(callback: (intensity: number) => void): void;
1079
+ /** Register callback for tilt changes. Direction x/y are -1 to 1. */
1080
+ onTilt(callback: (direction: {
1081
+ x: number;
1082
+ y: number;
1083
+ }) => void): void;
1084
+ /** Register callback for rotation. Angle in degrees. */
1085
+ onRotation(callback: (angle: number) => void): void;
1086
+ /** Register callback for device flip (face-down/up toggle). */
1087
+ onFlip(callback: () => void): void;
1088
+ /** Remove all listeners and callbacks */
1089
+ dispose(): void;
1090
+ private _handleMotion;
1091
+ private _handleOrientation;
1092
+ }
1093
+
1094
+ /**
1095
+ * HapticA11y — auto-adds haptic feedback to common accessibility interactions.
1096
+ *
1097
+ * Attaches to DOM events (focus, blur, invalid, click) and uses
1098
+ * MutationObserver to watch for dynamically added elements.
1099
+ * Provides subtle, non-intrusive haptic cues for screen interactions.
1100
+ */
1101
+ interface HapticA11yOptions {
1102
+ /** Enable haptic on focus changes (default: true) */
1103
+ focusChange?: boolean;
1104
+ /** Enable haptic on form validation errors (default: true) */
1105
+ formErrors?: boolean;
1106
+ /** Enable haptic on navigation/link clicks (default: true) */
1107
+ navigation?: boolean;
1108
+ /** Enable haptic on alert/notification elements (default: true) */
1109
+ announcements?: boolean;
1110
+ }
1111
+ declare class HapticA11y {
1112
+ private engine;
1113
+ private options;
1114
+ private _isAttached;
1115
+ private _root;
1116
+ private _observer;
1117
+ private _focusChangeCallback;
1118
+ private _formErrorCallback;
1119
+ private _handleFocusIn;
1120
+ private _handleFocusOut;
1121
+ private _handleInvalid;
1122
+ private _handleClick;
1123
+ constructor(engine: any, options?: HapticA11yOptions);
1124
+ /** Whether currently attached and listening */
1125
+ get isAttached(): boolean;
1126
+ /**
1127
+ * Attach to a root element and begin listening for interactions.
1128
+ * Defaults to document.body if no root is provided.
1129
+ */
1130
+ attach(root?: any): void;
1131
+ /** Remove all listeners and stop observing */
1132
+ detach(): void;
1133
+ /** Set a custom handler for focus changes */
1134
+ onFocusChange(callback?: (event: any) => void): void;
1135
+ /** Set a custom handler for form errors */
1136
+ onFormError(callback?: (event: any) => void): void;
1137
+ /** Clean up all listeners, observers, and callbacks */
1138
+ dispose(): void;
1139
+ private _bindHandlers;
1140
+ private _attachListeners;
1141
+ private _removeListeners;
1142
+ private _startObserver;
1143
+ private _stopObserver;
1144
+ private _safeCall;
1145
+ }
1146
+
439
1147
  /** Platform detection utilities */
440
1148
  interface PlatformInfo {
441
1149
  isWeb: boolean;
@@ -460,4 +1168,4 @@ declare function detectPlatform(): PlatformInfo;
460
1168
  */
461
1169
  declare const haptic: HapticEngine;
462
1170
 
463
- export { type AdapterCapabilities, AdaptiveEngine, type EasingFunction, type ExportOptions, type FallbackConfig, FallbackManager, type HPLNode, type HPLNodeType, HPLParser, HPLParserError, type HPLToken, type HPLTokenType, HPLTokenizerError, type HapticAdapter, type HapticConfig, HapticEngine, type HapticPattern, type HapticPatternExport, type HapticStep, type ImpactStyle, IoSAudioAdapter, NoopAdapter, type NotificationType, PatternComposer, type PlatformInfo, type SemanticEffect, type ValidationResult, type VisualFallbackStyle, WebVibrationAdapter, compile, detectAdapter, detectPlatform, exportPattern, haptic, importPattern, optimizeSteps, parseHPL, patternFromDataURL, patternFromJSON, patternToDataURL, patternToJSON, tokenize, validateHPL };
1171
+ export { type AdapterCapabilities, AdaptiveEngine, type BounceOptions, type ClickOptions, type EasingFunction, type ElasticOptions, type ExportOptions, type FallbackConfig, FallbackManager, type FlashOptions, type FrictionOptions, type GlowOptions, type GravityOptions, type HPLNode, type HPLNodeType, HPLParser, HPLParserError, type HPLToken, type HPLTokenType, HPLTokenizerError, HapticA11y, type HapticA11yOptions, type HapticAdapter, type HapticConfig, HapticEngine, HapticExperiment, type HapticMiddleware, type HapticPattern, type HapticPatternExport, type HapticStep, type HighlightOptions, type ImpactOptions, type ImpactStyle, type IntensityProfile, IoSAudioAdapter, type JelloOptions, MiddlewareManager, MotionDetector, type MotionDetectorOptions, NoopAdapter, type NotificationType, PatternComposer, PatternRecorder, type PendulumOptions, type PlatformInfo, ProfileManager, type PulseOptions, RhythmSync, type RhythmSyncOptions, type RippleOptions, type RubberOptions, type SemanticEffect, SensoryEngine, type SensoryEngineOptions, type ShakeOptions, SoundEngine, type SoundEngineOptions, type SpringOptions, ThemeManager, type ThemePreset, type ToneOptions, type ValidationResult, type BounceOptions$1 as VisualBounceOptions, VisualEngine, type VisualEngineOptions, type VisualFallbackStyle, type WaveOptions, WebVibrationAdapter, accessibilityBooster, bounce, compile, detectAdapter, detectPlatform, durationScaler, elastic, exportPattern, friction, gravity, haptic, impact, importPattern, intensityClamper, intensityScaler, optimizeSteps, parseHPL, patternFromDataURL, patternFromJSON, patternRepeater, patternToDataURL, patternToJSON, pendulum, physics, profiles, reverser, spring, themes, tokenize, validateHPL, wave };