@thewhateverapp/tile-sdk 0.11.0 → 0.11.2

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.
@@ -33,6 +33,12 @@ export interface KeyboardState {
33
33
  visible: boolean;
34
34
  height: number;
35
35
  }
36
+ /**
37
+ * Visibility state from parent (for TikTok-style feeds where tiles are preloaded)
38
+ */
39
+ export interface VisibilityState {
40
+ visible: boolean;
41
+ }
36
42
  type NextRouter = {
37
43
  push: (href: string) => void;
38
44
  replace: (href: string) => void;
@@ -49,8 +55,38 @@ export declare class TileBridge {
49
55
  private currentToken;
50
56
  private tokenExpiresAt;
51
57
  private keyboardState;
58
+ private visibilityState;
59
+ private baselineViewportHeight;
60
+ private keyboardDetectionEnabled;
61
+ private lastReportedKeyboardState;
62
+ private viewportDebounceTimer;
63
+ private readonly KEYBOARD_THRESHOLD;
64
+ private readonly DEBOUNCE_MS;
65
+ private inputFocused;
66
+ private focusedElement;
52
67
  constructor(expectedOrigin?: string, router?: NextRouter);
53
68
  private initialize;
69
+ /**
70
+ * Initialize keyboard detection using VisualViewport API and input focus tracking
71
+ * This runs inside the WebView to detect when the soft keyboard appears
72
+ */
73
+ private initializeKeyboardDetection;
74
+ /**
75
+ * Process viewport change and determine keyboard state
76
+ */
77
+ private processViewportChange;
78
+ /**
79
+ * Handle focusin events - input element gained focus
80
+ */
81
+ private handleFocusIn;
82
+ /**
83
+ * Handle focusout events - input element lost focus
84
+ */
85
+ private handleFocusOut;
86
+ /**
87
+ * Check if an element is an input-like element that would trigger keyboard
88
+ */
89
+ private isInputElement;
54
90
  private handleMessage;
55
91
  private handleConfig;
56
92
  private handleResponse;
@@ -64,6 +100,11 @@ export declare class TileBridge {
64
100
  * Handle keyboard state message from parent (mobile app)
65
101
  */
66
102
  private handleKeyboard;
103
+ /**
104
+ * Handle visibility state message from parent (mobile app)
105
+ * Used for TikTok-style feeds where tiles are preloaded but not visible
106
+ */
107
+ private handleVisibility;
67
108
  private sendToParent;
68
109
  /**
69
110
  * Request to navigate to full page view
@@ -252,6 +293,24 @@ export declare class TileBridge {
252
293
  * @returns Unsubscribe function
253
294
  */
254
295
  onKeyboardChange(handler: (state: KeyboardState) => void): () => void;
296
+ /**
297
+ * Get the current visibility state from parent
298
+ * For TikTok-style feeds where tiles may be preloaded but not visible
299
+ * Returns { visible: true } by default (for web/non-mobile platforms)
300
+ */
301
+ getVisibilityState(): VisibilityState;
302
+ /**
303
+ * Check if the tile is currently visible
304
+ * Returns true by default (for standalone tiles not in a feed)
305
+ */
306
+ isVisible(): boolean;
307
+ /**
308
+ * Subscribe to visibility state changes
309
+ * Called when parent sends visibility show/hide events (e.g., TikTok-style feed)
310
+ * @param handler Callback receiving { visible: boolean }
311
+ * @returns Unsubscribe function
312
+ */
313
+ onVisibilityChange(handler: (state: VisibilityState) => void): () => void;
255
314
  /**
256
315
  * Wait for ready state
257
316
  *
@@ -1 +1 @@
1
- {"version":3,"file":"TileBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/TileBridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TileBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/TileBridge.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,18 @@ export class TileBridge {
15
15
  this.tokenExpiresAt = null;
16
16
  // Keyboard state from parent (mobile app)
17
17
  this.keyboardState = { visible: false, height: 0 };
18
+ // Visibility state from parent (for TikTok-style feeds)
19
+ this.visibilityState = { visible: true };
20
+ // VisualViewport tracking for keyboard detection (Plan A)
21
+ this.baselineViewportHeight = 0;
22
+ this.keyboardDetectionEnabled = false;
23
+ this.lastReportedKeyboardState = { visible: false, height: 0 };
24
+ this.viewportDebounceTimer = null;
25
+ this.KEYBOARD_THRESHOLD = 150; // Minimum height change to consider keyboard visible
26
+ this.DEBOUNCE_MS = 100; // Debounce viewport events
27
+ // Input focus tracking (Plan B)
28
+ this.inputFocused = false;
29
+ this.focusedElement = null;
18
30
  this.parentOrigin = expectedOrigin;
19
31
  this.router = router || null;
20
32
  // Auto-detect parent origin based on environment
@@ -66,6 +78,182 @@ export class TileBridge {
66
78
  this.ready = true;
67
79
  // Send ready signal to parent
68
80
  this.sendToParent({ type: 'tile:ready' });
81
+ // Initialize keyboard detection (Plan A: VisualViewport + Plan B: Input Focus)
82
+ this.initializeKeyboardDetection();
83
+ }
84
+ /**
85
+ * Initialize keyboard detection using VisualViewport API and input focus tracking
86
+ * This runs inside the WebView to detect when the soft keyboard appears
87
+ */
88
+ initializeKeyboardDetection() {
89
+ if (typeof window === 'undefined')
90
+ return;
91
+ // Only enable in iframe context (when running in mobile WebView)
92
+ if (!this.isInIframe()) {
93
+ if (this.isDevelopment()) {
94
+ console.log('[TileBridge] Keyboard detection skipped - not in iframe');
95
+ }
96
+ return;
97
+ }
98
+ this.keyboardDetectionEnabled = true;
99
+ // ==================== PLAN A: VisualViewport Detection ====================
100
+ // Use VisualViewport API to detect keyboard by monitoring viewport height changes
101
+ const vv = window.visualViewport;
102
+ if (vv) {
103
+ // Set baseline height (full viewport without keyboard)
104
+ this.baselineViewportHeight = vv.height;
105
+ if (this.isDevelopment() || this.isPreview()) {
106
+ console.log('[TileBridge] ⌨️ Keyboard detection initialized', {
107
+ baselineHeight: this.baselineViewportHeight,
108
+ hasVisualViewport: true,
109
+ });
110
+ }
111
+ // Handler for viewport resize events
112
+ const handleViewportChange = () => {
113
+ if (!this.keyboardDetectionEnabled)
114
+ return;
115
+ // Debounce rapid events
116
+ if (this.viewportDebounceTimer) {
117
+ clearTimeout(this.viewportDebounceTimer);
118
+ }
119
+ this.viewportDebounceTimer = setTimeout(() => {
120
+ this.processViewportChange();
121
+ }, this.DEBOUNCE_MS);
122
+ };
123
+ // Subscribe to resize and scroll events on visualViewport
124
+ vv.addEventListener('resize', handleViewportChange);
125
+ vv.addEventListener('scroll', handleViewportChange);
126
+ }
127
+ else {
128
+ if (this.isDevelopment() || this.isPreview()) {
129
+ console.log('[TileBridge] ⌨️ VisualViewport not available, using focus-only detection');
130
+ }
131
+ }
132
+ // ==================== PLAN B: Input Focus Detection ====================
133
+ // Track when input elements are focused/blurred
134
+ document.addEventListener('focusin', this.handleFocusIn.bind(this));
135
+ document.addEventListener('focusout', this.handleFocusOut.bind(this));
136
+ }
137
+ /**
138
+ * Process viewport change and determine keyboard state
139
+ */
140
+ processViewportChange() {
141
+ const vv = window.visualViewport;
142
+ if (!vv)
143
+ return;
144
+ const currentHeight = vv.height;
145
+ const heightDiff = this.baselineViewportHeight - currentHeight;
146
+ const keyboardVisible = heightDiff > this.KEYBOARD_THRESHOLD;
147
+ const keyboardHeight = keyboardVisible ? Math.round(heightDiff) : 0;
148
+ // Only report if state changed
149
+ if (this.lastReportedKeyboardState.visible !== keyboardVisible ||
150
+ Math.abs(this.lastReportedKeyboardState.height - keyboardHeight) > 10) {
151
+ this.lastReportedKeyboardState = { visible: keyboardVisible, height: keyboardHeight };
152
+ if (this.isDevelopment() || this.isPreview()) {
153
+ console.log('[TileBridge] ⌨️ Keyboard state changed (viewport)', {
154
+ visible: keyboardVisible,
155
+ height: keyboardHeight,
156
+ baselineHeight: this.baselineViewportHeight,
157
+ currentHeight,
158
+ });
159
+ }
160
+ // Send keyboard state to parent (React Native)
161
+ this.sendToParent({
162
+ type: 'tile:keyboard',
163
+ payload: {
164
+ visible: keyboardVisible,
165
+ height: keyboardHeight,
166
+ source: 'viewport',
167
+ },
168
+ });
169
+ }
170
+ // Update baseline when keyboard is hidden (to handle orientation changes)
171
+ if (!keyboardVisible && currentHeight > this.baselineViewportHeight) {
172
+ this.baselineViewportHeight = currentHeight;
173
+ }
174
+ }
175
+ /**
176
+ * Handle focusin events - input element gained focus
177
+ */
178
+ handleFocusIn(event) {
179
+ const target = event.target;
180
+ if (!target)
181
+ return;
182
+ // Check if the focused element is an input-like element
183
+ const isInputLike = this.isInputElement(target);
184
+ if (isInputLike && !this.inputFocused) {
185
+ this.inputFocused = true;
186
+ this.focusedElement = target;
187
+ if (this.isDevelopment() || this.isPreview()) {
188
+ console.log('[TileBridge] ⌨️ Input focused', {
189
+ tagName: target.tagName,
190
+ type: target.type,
191
+ id: target.id,
192
+ });
193
+ }
194
+ // Send focus event to parent
195
+ this.sendToParent({
196
+ type: 'tile:input-focused',
197
+ payload: {
198
+ tagName: target.tagName.toLowerCase(),
199
+ type: target.type || null,
200
+ id: target.id || null,
201
+ },
202
+ });
203
+ }
204
+ }
205
+ /**
206
+ * Handle focusout events - input element lost focus
207
+ */
208
+ handleFocusOut(event) {
209
+ const target = event.target;
210
+ if (!target)
211
+ return;
212
+ // Check if the blurred element is the one we're tracking
213
+ const isInputLike = this.isInputElement(target);
214
+ if (isInputLike && this.inputFocused) {
215
+ // Use setTimeout to check if focus moved to another input
216
+ // If relatedTarget is another input, we stay in "focused" state
217
+ setTimeout(() => {
218
+ const activeElement = document.activeElement;
219
+ const stillFocused = activeElement && this.isInputElement(activeElement);
220
+ if (!stillFocused) {
221
+ this.inputFocused = false;
222
+ this.focusedElement = null;
223
+ if (this.isDevelopment() || this.isPreview()) {
224
+ console.log('[TileBridge] ⌨️ Input blurred');
225
+ }
226
+ // Send blur event to parent
227
+ this.sendToParent({
228
+ type: 'tile:input-blurred',
229
+ payload: {},
230
+ });
231
+ }
232
+ }, 10);
233
+ }
234
+ }
235
+ /**
236
+ * Check if an element is an input-like element that would trigger keyboard
237
+ */
238
+ isInputElement(element) {
239
+ const tagName = element.tagName.toLowerCase();
240
+ // Standard input elements
241
+ if (tagName === 'textarea')
242
+ return true;
243
+ if (tagName === 'select')
244
+ return false; // Select doesn't trigger keyboard
245
+ if (tagName === 'input') {
246
+ const inputType = element.type?.toLowerCase();
247
+ // These input types trigger the keyboard
248
+ const keyboardTypes = ['text', 'email', 'password', 'search', 'tel', 'url', 'number'];
249
+ return !inputType || keyboardTypes.includes(inputType);
250
+ }
251
+ // Contenteditable elements
252
+ if (element.hasAttribute('contenteditable')) {
253
+ const value = element.getAttribute('contenteditable');
254
+ return value === 'true' || value === '';
255
+ }
256
+ return false;
69
257
  }
70
258
  handleMessage(event) {
71
259
  // Validate origin (skip validation in dev and preview)
@@ -101,6 +289,9 @@ export class TileBridge {
101
289
  case 'parent:keyboard':
102
290
  this.handleKeyboard(message.payload);
103
291
  break;
292
+ case 'parent:visibility':
293
+ this.handleVisibility(message.payload);
294
+ break;
104
295
  case 'parent:navigateToPage':
105
296
  this.handleParentNavigate({ target: 'page' });
106
297
  break;
@@ -195,6 +386,27 @@ export class TileBridge {
195
386
  // Emit keyboard update event for listeners
196
387
  this.emitEvent('keyboard:update', this.keyboardState);
197
388
  }
389
+ /**
390
+ * Handle visibility state message from parent (mobile app)
391
+ * Used for TikTok-style feeds where tiles are preloaded but not visible
392
+ */
393
+ handleVisibility(payload) {
394
+ if (payload?.visible === undefined) {
395
+ console.warn('[TileBridge] Invalid visibility payload received');
396
+ return;
397
+ }
398
+ const wasVisible = this.visibilityState.visible;
399
+ this.visibilityState = {
400
+ visible: !!payload.visible,
401
+ };
402
+ if (this.isDevelopment() || this.isPreview()) {
403
+ console.log('[TileBridge] 👁️ Received visibility state', this.visibilityState);
404
+ }
405
+ // Only emit if visibility actually changed
406
+ if (wasVisible !== this.visibilityState.visible) {
407
+ this.emitEvent('visibility:update', this.visibilityState);
408
+ }
409
+ }
198
410
  sendToParent(message) {
199
411
  if (typeof window === 'undefined' || !window.parent)
200
412
  return;
@@ -874,6 +1086,31 @@ export class TileBridge {
874
1086
  onKeyboardChange(handler) {
875
1087
  return this.on('keyboard:update', handler);
876
1088
  }
1089
+ // ============= VISIBILITY API =============
1090
+ /**
1091
+ * Get the current visibility state from parent
1092
+ * For TikTok-style feeds where tiles may be preloaded but not visible
1093
+ * Returns { visible: true } by default (for web/non-mobile platforms)
1094
+ */
1095
+ getVisibilityState() {
1096
+ return { ...this.visibilityState };
1097
+ }
1098
+ /**
1099
+ * Check if the tile is currently visible
1100
+ * Returns true by default (for standalone tiles not in a feed)
1101
+ */
1102
+ isVisible() {
1103
+ return this.visibilityState.visible;
1104
+ }
1105
+ /**
1106
+ * Subscribe to visibility state changes
1107
+ * Called when parent sends visibility show/hide events (e.g., TikTok-style feed)
1108
+ * @param handler Callback receiving { visible: boolean }
1109
+ * @returns Unsubscribe function
1110
+ */
1111
+ onVisibilityChange(handler) {
1112
+ return this.on('visibility:update', handler);
1113
+ }
877
1114
  /**
878
1115
  * Wait for ready state
879
1116
  *
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ export { withTile } from './react/withTile';
7
7
  export { VideoPlayer, useVideoState, Slideshow, useSlideshowState, OverlaySlot, FullOverlay, GradientOverlay, } from './react/overlay';
8
8
  export type { VideoState, VideoControls, VideoContextValue, VideoPlayerProps, SlideImage, SlideshowState, SlideshowControls, SlideshowContextValue, SlideshowProps, SlotPosition, OverlaySlotProps, FullOverlayProps, GradientOverlayProps, } from './react/overlay';
9
9
  export { getTileBridge, TileBridge } from './bridge/TileBridge';
10
- export type { TileMessage, TileConfig, TileTokenData, KeyboardState } from './bridge/TileBridge';
10
+ export type { TileMessage, TileConfig, TileTokenData, KeyboardState, VisibilityState } from './bridge/TileBridge';
11
11
  export { StateClient } from './state/StateClient';
12
12
  export type { TileStats, ViewResponse } from './state/StateClient';
13
13
  export * from './tools';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAEL,WAAW,EACX,aAAa,EAEb,SAAS,EACT,iBAAiB,EAEjB,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAEV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAEhB,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EAEd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGjG,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnE,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAEL,WAAW,EACX,aAAa,EAEb,SAAS,EACT,iBAAiB,EAEjB,WAAW,EACX,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAEV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAEhB,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EAEd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGlH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnE,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import React, { createContext, useContext, useEffect, useRef, useState, useCallback, } from 'react';
3
+ import { getTileBridge } from '../../bridge/TileBridge';
3
4
  const VideoContext = createContext(null);
4
5
  /**
5
6
  * VideoPlayer component with HLS streaming support.
@@ -155,6 +156,39 @@ export function VideoPlayer({ src, autoplay = true, loop = false, muted = true,
155
156
  video.removeEventListener('error', handleError);
156
157
  };
157
158
  }, []);
159
+ // Visibility handling - play/pause based on tile visibility
160
+ // Enables TikTok-style preloaded video tiles that only play when visible
161
+ useEffect(() => {
162
+ const video = videoRef.current;
163
+ if (!video || !autoplay)
164
+ return;
165
+ try {
166
+ const bridge = getTileBridge();
167
+ // Handle visibility changes from parent (mobile app)
168
+ const unsubscribe = bridge.onVisibilityChange((visibilityState) => {
169
+ if (visibilityState.visible) {
170
+ // Tile became visible - play the video
171
+ video.play().catch(() => { });
172
+ }
173
+ else {
174
+ // Tile became hidden - pause the video
175
+ video.pause();
176
+ }
177
+ });
178
+ // Check initial visibility state
179
+ if (!bridge.isVisible()) {
180
+ // If not visible on mount, pause any autoplay
181
+ video.pause();
182
+ }
183
+ return () => {
184
+ unsubscribe();
185
+ };
186
+ }
187
+ catch {
188
+ // Bridge not available (e.g., in SSR or outside TileProvider)
189
+ // Video will just use autoplay behavior
190
+ }
191
+ }, [autoplay]);
158
192
  const contextValue = {
159
193
  state,
160
194
  controls: { play, pause, toggle, seek, setVolume, setMuted },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thewhateverapp/tile-sdk",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "SDK for building interactive tiles on The Whatever App platform",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",