@blorkfield/overlay-core 0.8.7 → 0.8.9

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/README.md CHANGED
@@ -22,13 +22,24 @@ pnpm add @blorkfield/overlay-core
22
22
 
23
23
  ### Tag Based Behavior
24
24
 
25
- Objects don't have fixed types. Instead, their behavior is determined by string tags:
25
+ Objects don't have fixed types. Instead, their behavior is determined by string tags. Import the tag constants to avoid magic strings:
26
26
 
27
- | Tag | Behavior |
28
- |-----|----------|
29
- | `falling` | Object is dynamic and affected by gravity |
30
- | `follow` | Object follows mouse position when grounded |
31
- | `grabable` | Object can be dragged via mouse constraint |
27
+ ```typescript
28
+ import { TAGS, TAG_FALLING, TAG_GRABABLE, TAG_FOLLOW_WINDOW } from '@blorkfield/overlay-core';
29
+
30
+ // Use individual constants
31
+ scene.spawnObject({ tags: [TAG_FALLING, TAG_GRABABLE], ... });
32
+
33
+ // Or destructure from TAGS object
34
+ const { FALLING, GRABABLE } = TAGS;
35
+ scene.spawnObject({ tags: [FALLING, GRABABLE], ... });
36
+ ```
37
+
38
+ | Constant | Value | Behavior |
39
+ |----------|-------|----------|
40
+ | `TAG_FALLING` / `TAGS.FALLING` | `'falling'` | Object is dynamic and affected by gravity |
41
+ | `TAG_FOLLOW_WINDOW` / `TAGS.FOLLOW_WINDOW` | `'follow_window'` | Object follows mouse position when grounded |
42
+ | `TAG_GRABABLE` / `TAGS.GRABABLE` | `'grabable'` | Object can be grabbed and moved with mouse |
32
43
 
33
44
  Without the `falling` tag, objects are static and won't move.
34
45
 
@@ -153,6 +164,11 @@ When a DOM element collapses:
153
164
  - The element's CSS transform is updated each frame to follow physics
154
165
  - Shadow creates a cloned DOM element at the original position
155
166
 
167
+ ```typescript
168
+ // Get the shadow element after collapse (if shadow was configured)
169
+ const shadowEl = scene.getDOMObstacleShadow(id);
170
+ ```
171
+
156
172
  ### Pressure, Shadow, and Click Behavior
157
173
 
158
174
  These options work on any spawned object (shapes, images, or DOM elements):
@@ -225,6 +241,25 @@ const result = await scene.addTTFTextObstacles({
225
241
  });
226
242
  ```
227
243
 
244
+ ### Managing Text Obstacles
245
+
246
+ ```typescript
247
+ // Spawn text that immediately falls (already has 'falling' tag)
248
+ const result = await scene.spawnFallingTextObstacles(config);
249
+ const result = await scene.spawnFallingTTFTextObstacles(config);
250
+
251
+ // Release text obstacles (add 'falling' tag)
252
+ scene.releaseTextObstacles(wordTag);
253
+
254
+ // Release letters one by one with delay
255
+ await scene.releaseTextObstaclesSequentially(wordTag, 100); // 100ms delay
256
+ await scene.releaseTextObstaclesSequentially(wordTag, 100, true); // reverse order
257
+
258
+ // Get debug info for letter positioning
259
+ const debugInfo = scene.getLetterDebugInfo(wordTag);
260
+ const allDebug = scene.getAllLetterDebugInfo();
261
+ ```
262
+
228
263
  ## Effects
229
264
 
230
265
  Effects are persistent spawning mechanisms that create objects over time.
@@ -294,22 +329,45 @@ scene.setEffect({
294
329
  ```typescript
295
330
  // Release objects (make them fall)
296
331
  scene.releaseObject(id);
332
+ scene.releaseObjects([id1, id2]);
297
333
  scene.releaseObjectsByTag('my-text');
298
334
  scene.releaseAllObjects();
299
335
 
300
336
  // Remove objects
301
337
  scene.removeObject(id);
338
+ scene.removeObjects([id1, id2]);
302
339
  scene.removeObjectsByTag('welcome-text');
303
340
  scene.removeAllObjects();
341
+ scene.removeAll(); // Alias for removeAllObjects
342
+ scene.removeAllByTag('tag'); // Alias for removeObjectsByTag
304
343
 
305
344
  // Add or remove tags
306
345
  scene.addTag(id, 'falling');
346
+ scene.addFallingTag(id); // Convenience for adding 'falling' tag
307
347
  scene.removeTag(id, 'grabable');
308
348
 
309
349
  // Get object info
310
350
  const ids = scene.getObjectIds();
311
351
  const tagged = scene.getObjectIdsByTag('falling');
312
352
  const allTags = scene.getAllTags();
353
+
354
+ // Get full object state
355
+ const obj = scene.getObject(id); // Returns ObjectState or null
356
+ const objs = scene.getObjectsByTag('tag'); // Returns ObjectState[]
357
+ ```
358
+
359
+ ## Physics Manipulation
360
+
361
+ ```typescript
362
+ // Apply force to objects
363
+ scene.applyForce(id, { x: 0.01, y: -0.02 });
364
+ scene.applyForceToTag('falling', { x: 0.005, y: 0 });
365
+
366
+ // Set velocity directly
367
+ scene.setVelocity(id, { x: 5, y: -10 });
368
+
369
+ // Set position directly
370
+ scene.setPosition(id, { x: 100, y: 200 });
313
371
  ```
314
372
 
315
373
  ## Mouse Position and Grab API
@@ -352,9 +410,11 @@ const currentGrab = scene.getGrabbedObject(); // Returns ID or null
352
410
 
353
411
  | Method | Returns | Description |
354
412
  |--------|---------|-------------|
355
- | `setFollowTarget('mouse', x, y)` | void | Set mouse position for follow behavior and grab detection |
413
+ | `setFollowTarget(key, x, y)` | void | Set a follow target position (e.g., 'mouse' for grab/follow behavior) |
414
+ | `removeFollowTarget(key)` | void | Remove a follow target |
415
+ | `getFollowTargetKeys()` | string[] | Get all active follow target keys |
356
416
  | `startGrab()` | string \| null | Link entity at current mouse position to mouse, returns entity ID |
357
- | `endGrab()` | void | Unlink currently grabbed entity |
417
+ | `endGrab()` | void | Unlink currently grabbed entity (applies release velocity) |
358
418
  | `getGrabbedObject()` | string \| null | Get ID of currently grabbed entity |
359
419
 
360
420
  ## Configuration
@@ -393,6 +453,34 @@ const scene = new OverlayScene(canvas, {
393
453
  | `floorConfig.segmentWidths` | none | Proportional widths for each segment (array that sums to 1.0) |
394
454
  | `despawnBelowFloor` | 1.0 | Distance below floor to despawn objects (as fraction of height) |
395
455
 
456
+ ### Background Configuration
457
+
458
+ The `background` option supports multiple formats:
459
+
460
+ ```typescript
461
+ // Simple color
462
+ background: '#16213e'
463
+ background: 'transparent'
464
+
465
+ // Full configuration with layers
466
+ background: {
467
+ color: '#16213e', // Base color layer
468
+ image: {
469
+ url: '/images/bg.png',
470
+ sizing: 'cover' // 'stretch' | 'center' | 'tile' | 'cover' | 'contain'
471
+ },
472
+ transparency: {
473
+ mode: 'checkerboard', // Visual indicator for transparent areas
474
+ color1: '#ffffff',
475
+ color2: '#cccccc',
476
+ size: 10
477
+ }
478
+ }
479
+
480
+ // Change background at runtime
481
+ await scene.setBackground({ color: '#000000' });
482
+ ```
483
+
396
484
  ## Pressure Tracking
397
485
 
398
486
  ```typescript
@@ -409,7 +497,11 @@ const allPressure = scene.getAllPressure();
409
497
  const summary = scene.getPressureSummary();
410
498
  ```
411
499
 
412
- ## Update Callbacks
500
+ ## Callbacks and Events
501
+
502
+ ### Update Callback
503
+
504
+ Called every frame with all dynamic object states:
413
505
 
414
506
  ```typescript
415
507
  scene.onUpdate((data) => {
@@ -420,6 +512,30 @@ scene.onUpdate((data) => {
420
512
  });
421
513
  ```
422
514
 
515
+ ### Lifecycle Events
516
+
517
+ Subscribe to object lifecycle events:
518
+
519
+ ```typescript
520
+ // Object spawned
521
+ scene.on('objectSpawned', (obj) => {
522
+ console.log(`Spawned: ${obj.id}`, obj.x, obj.y);
523
+ });
524
+
525
+ // Object removed
526
+ scene.on('objectRemoved', (obj) => {
527
+ console.log(`Removed: ${obj.id}`);
528
+ });
529
+
530
+ // Objects collided
531
+ scene.on('objectCollision', (a, b) => {
532
+ console.log(`Collision: ${a.id} hit ${b.id}`);
533
+ });
534
+
535
+ // Unsubscribe
536
+ scene.off('objectSpawned', myCallback);
537
+ ```
538
+
423
539
  ## Font Setup
424
540
 
425
541
  ### Bundled Fonts
@@ -496,6 +612,22 @@ Add the font file and reference it in the manifest:
496
612
  }
497
613
  ```
498
614
 
615
+ ### Font API
616
+
617
+ ```typescript
618
+ // Initialize fonts from a directory
619
+ await scene.initializeFonts('/fonts/');
620
+
621
+ // Check initialization status
622
+ if (scene.areFontsInitialized()) {
623
+ // Get available fonts
624
+ const fonts = scene.getAvailableFonts(); // Returns FontInfo[]
625
+ const font = scene.getFontByName('Roboto'); // Returns FontInfo | undefined
626
+ const font = scene.getFontByIndex(0); // Returns FontInfo | undefined
627
+ const defaultFont = scene.getDefaultFont(); // Returns first font or undefined
628
+ }
629
+ ```
630
+
499
631
  ## Logging
500
632
 
501
633
  ```typescript
@@ -536,18 +668,67 @@ The package is written in TypeScript and ships with full type definitions. All c
536
668
 
537
669
  ```typescript
538
670
  import type {
671
+ // Scene configuration
539
672
  OverlaySceneConfig,
673
+ Bounds,
674
+ ContainerOptions,
675
+ FloorConfig,
676
+
677
+ // Object types
540
678
  ObjectConfig,
679
+ DynamicObject,
680
+ ObjectState,
681
+ ShapeConfig,
682
+ ShapePreset,
683
+ DespawnEffectConfig,
684
+
685
+ // Text obstacle types
541
686
  TextObstacleConfig,
687
+ TextObstacleResult,
542
688
  TTFTextObstacleConfig,
689
+ TextAlign,
690
+ TextBounds,
691
+
692
+ // Effect types
543
693
  EffectConfig,
694
+ EffectType,
695
+ EffectObjectConfig,
696
+ BaseEffectConfig,
544
697
  BurstEffectConfig,
545
698
  RainEffectConfig,
546
699
  StreamEffectConfig,
700
+
701
+ // Pressure, weight, shadow, click types
547
702
  PressureThresholdConfig,
548
703
  WeightConfig,
549
704
  ShadowConfig,
550
705
  ClickToFallConfig,
551
- FloorConfig
706
+
707
+ // Background types
708
+ BackgroundConfig,
709
+ BackgroundImageConfig,
710
+ BackgroundImageSizing,
711
+ BackgroundTransparencyConfig,
712
+
713
+ // Font types
714
+ FontInfo,
715
+ FontManifest,
716
+ LoadedFont,
717
+ GlyphData,
718
+
719
+ // Lifecycle types
720
+ LifecycleEvent,
721
+ LifecycleCallback,
722
+ UpdateCallback,
723
+ UpdateCallbackData,
724
+
725
+ // Logging
726
+ LogLevel,
727
+
728
+ // Tags
729
+ Tag
552
730
  } from '@blorkfield/overlay-core';
731
+
732
+ // Tag constants (values, not types)
733
+ import { TAGS, TAG_FALLING, TAG_GRABABLE, TAG_FOLLOW_WINDOW } from '@blorkfield/overlay-core';
553
734
  ```
package/dist/index.cjs CHANGED
@@ -32,6 +32,10 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BackgroundManager: () => BackgroundManager,
34
34
  OverlayScene: () => OverlayScene,
35
+ TAGS: () => TAGS,
36
+ TAG_FALLING: () => TAG_FALLING,
37
+ TAG_FOLLOW_WINDOW: () => TAG_FOLLOW_WINDOW,
38
+ TAG_GRABABLE: () => TAG_GRABABLE,
35
39
  clearFontCache: () => clearFontCache,
36
40
  getGlyphData: () => getGlyphData,
37
41
  getKerning: () => getKerning,
@@ -1547,7 +1551,7 @@ var OverlayScene = class {
1547
1551
  const isDragging = this.grabbedObjectId === entry.id;
1548
1552
  if (!isDragging) {
1549
1553
  for (const tag of entry.tags) {
1550
- const key = tag === "follow" ? "mouse" : tag.startsWith("follow-") ? tag.slice(7) : null;
1554
+ const key = tag === "follow_window" ? "mouse" : tag.startsWith("follow-") ? tag.slice(7) : null;
1551
1555
  if (key) {
1552
1556
  const target = this.followTargets.get(key);
1553
1557
  if (target) {
@@ -2082,8 +2086,8 @@ var OverlayScene = class {
2082
2086
  * Spawn an object synchronously.
2083
2087
  * Object behavior is determined by tags:
2084
2088
  * - 'falling': Object is dynamic (affected by gravity)
2085
- * - 'follow': Object follows mouse when grounded
2086
- * - 'grabable': Object can be dragged
2089
+ * - 'follow_window': Object follows mouse when grounded (walks toward mouse)
2090
+ * - 'grabable': Object can be grabbed and moved with mouse
2087
2091
  * Without 'falling' tag, object is static.
2088
2092
  */
2089
2093
  spawnObject(config) {
@@ -3394,10 +3398,24 @@ var OverlayScene = class {
3394
3398
  this.updateCallbacks.forEach((cb) => cb(data));
3395
3399
  }
3396
3400
  };
3401
+
3402
+ // src/tags.ts
3403
+ var TAG_FALLING = "falling";
3404
+ var TAG_FOLLOW_WINDOW = "follow_window";
3405
+ var TAG_GRABABLE = "grabable";
3406
+ var TAGS = {
3407
+ FALLING: TAG_FALLING,
3408
+ FOLLOW_WINDOW: TAG_FOLLOW_WINDOW,
3409
+ GRABABLE: TAG_GRABABLE
3410
+ };
3397
3411
  // Annotate the CommonJS export names for ESM import in node:
3398
3412
  0 && (module.exports = {
3399
3413
  BackgroundManager,
3400
3414
  OverlayScene,
3415
+ TAGS,
3416
+ TAG_FALLING,
3417
+ TAG_FOLLOW_WINDOW,
3418
+ TAG_GRABABLE,
3401
3419
  clearFontCache,
3402
3420
  getGlyphData,
3403
3421
  getKerning,