@revenuecat/purchases-ui-js 4.4.0 → 4.5.1

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.
@@ -41,6 +41,7 @@
41
41
  keyboard_type,
42
42
  capitalize,
43
43
  field_id,
44
+ reserved_attribute,
44
45
  required,
45
46
  size,
46
47
  padding,
@@ -74,7 +75,15 @@
74
75
  }
75
76
 
76
77
  const value = input.value.trim();
77
- onInputChanged?.(field_id, value);
78
+ if (reserved_attribute) {
79
+ if (!onReservedAttributeChanged) {
80
+ console.error("onReservedAttributeChanged is not set");
81
+ } else {
82
+ onReservedAttributeChanged(reserved_attribute, value);
83
+ }
84
+ } else {
85
+ onInputChanged?.(field_id, value);
86
+ }
78
87
  }
79
88
 
80
89
  const oninput: FormEventHandler<HTMLInputElement> = (event) => {
@@ -90,7 +99,12 @@
90
99
 
91
100
  const getColorMode = getColorModeContext();
92
101
  const colorMode = $derived(getColorMode());
93
- const { uiConfig, onInputChanged, selectedPackageId } = getPaywallContext();
102
+ const {
103
+ uiConfig,
104
+ onInputChanged,
105
+ onReservedAttributeChanged,
106
+ selectedPackageId,
107
+ } = getPaywallContext();
94
108
  const packageInfo = getOptionalPackageInfoContext();
95
109
 
96
110
  const wrapperStyle = $derived(
@@ -49,6 +49,7 @@
49
49
  setPackageInfoContext,
50
50
  } from "../../stores/packageInfo";
51
51
  import type { WalletButtonRender } from "../../types/wallet";
52
+ import type { ReservedAttribute } from "../../types/components/input-text";
52
53
 
53
54
  /**
54
55
  * Props are captured once at mount and are not reactive to subsequent changes.
@@ -90,6 +91,10 @@
90
91
  value: string,
91
92
  actionId?: string,
92
93
  ) => void;
94
+ onReservedAttributeChanged?: (
95
+ reservedAttribute: ReservedAttribute,
96
+ value: string,
97
+ ) => void;
93
98
  maxContentWidth?: string;
94
99
  initialInputSelections?: InitialInputSelections;
95
100
  /**
@@ -133,6 +138,7 @@
133
138
  uiConfig,
134
139
  walletButtonRender,
135
140
  onInputChanged,
141
+ onReservedAttributeChanged,
136
142
  hideBackButtons = false,
137
143
  maxContentWidth,
138
144
  initialInputSelections = {},
@@ -297,6 +303,7 @@
297
303
  onNavigateToUrl: onNavigateToUrlClicked,
298
304
  onButtonAction,
299
305
  onInputChanged,
306
+ onReservedAttributeChanged,
300
307
  walletButtonRender,
301
308
  uiConfig,
302
309
  hideBackButtons,
@@ -7,6 +7,7 @@ import type { PaywallData } from "../../types/paywall";
7
7
  import type { UIConfig } from "../../types/ui-config";
8
8
  import { type CustomVariables, type PackageInfo, type VariableDictionary } from "../../types/variables";
9
9
  import type { WalletButtonRender } from "../../types/wallet";
10
+ import type { ReservedAttribute } from "../../types/components/input-text";
10
11
  /**
11
12
  * Props are captured once at mount and are not reactive to subsequent changes.
12
13
  * The paywall should be remounted to reflect new prop values.
@@ -41,6 +42,7 @@ interface Props {
41
42
  hideBackButtons?: boolean;
42
43
  walletButtonRender?: WalletButtonRender;
43
44
  onInputChanged?: (fieldId: string, value: string, actionId?: string) => void;
45
+ onReservedAttributeChanged?: (reservedAttribute: ReservedAttribute, value: string) => void;
44
46
  maxContentWidth?: string;
45
47
  initialInputSelections?: InitialInputSelections;
46
48
  /**
@@ -311,7 +311,9 @@
311
311
  playbackMutedOverride = true;
312
312
  });
313
313
  applyVideoPlaybackFlags();
314
- void el.play().catch(() => {});
314
+ // Do not call el.play() here. A non-user-initiated play() call after a
315
+ // failed unmute corrupts the media element state machine on certain WebKit
316
+ // versions, leaving native controls unresponsive. Let the user tap to resume.
315
317
  });
316
318
  });
317
319
  };
@@ -321,14 +323,20 @@
321
323
  playingUnmuteListener = null;
322
324
  tryRestoreAudioAfterMutedAutoplay();
323
325
  };
324
- playingUnmuteListener = onPlayingAfterMutedBootstrap;
325
- el.addEventListener("playing", onPlayingAfterMutedBootstrap, {
326
- once: true,
327
- });
328
326
 
327
+ // Call muted play before registering the `playing` listener. The listener is
328
+ // registered only inside p2.then() — after muted play is confirmed started.
329
+ // Registering before p2 resolves risks the listener surviving indefinitely if
330
+ // p2's promise hangs (a known WebKit bug on certain devices), causing it to
331
+ // fire on user-initiated play and sabotage playback via the unmute restore flow.
329
332
  const p2 = el.play();
330
333
  if (p2 !== undefined) {
331
334
  p2.then(() => {
335
+ if (cancelled || mute_audio || unmuteAfterMutedStartHandled) return;
336
+ playingUnmuteListener = onPlayingAfterMutedBootstrap;
337
+ el.addEventListener("playing", onPlayingAfterMutedBootstrap, {
338
+ once: true,
339
+ });
332
340
  // `playing` may have fired before our listener ran; retry unmute once playback exists.
333
341
  queueMicrotask(() => {
334
342
  if (
@@ -345,8 +353,13 @@
345
353
  }
346
354
  tryRestoreAudioAfterMutedAutoplay();
347
355
  });
348
- }).catch(() => {
349
- clearPlayingUnmuteListener();
356
+ });
357
+ } else {
358
+ // p2 undefined: older iOS that doesn't return a promise from play().
359
+ // Register the listener directly — it's the only available signal.
360
+ playingUnmuteListener = onPlayingAfterMutedBootstrap;
361
+ el.addEventListener("playing", onPlayingAfterMutedBootstrap, {
362
+ once: true,
350
363
  });
351
364
  }
352
365
  }
@@ -8,6 +8,7 @@
8
8
  import type { VariableDictionary } from "../../types/variables";
9
9
  import type { WalletButtonRender } from "../../types/wallet";
10
10
  import type { UIConfig } from "../../types/ui-config";
11
+ import type { ReservedAttribute } from "../../types/components/input-text";
11
12
  interface Props {
12
13
  paywallComponents: WorkflowScreen | null | undefined;
13
14
  selectedLocale?: string;
@@ -29,6 +30,10 @@
29
30
  value: string,
30
31
  actionId?: string,
31
32
  ) => void;
33
+ onReservedAttributeChanged?: (
34
+ reservedAttribute: ReservedAttribute,
35
+ value: string,
36
+ ) => void;
32
37
  onCompleteWorkflowNavigate?: (
33
38
  args: CompleteWorkflowNavigateArgs,
34
39
  ) => void | Promise<void>;
@@ -49,6 +54,7 @@
49
54
  variablesPerPackage,
50
55
  initialInputSelections = {},
51
56
  onInputChanged,
57
+ onReservedAttributeChanged,
52
58
  onCompleteWorkflowNavigate,
53
59
  walletButtonRender,
54
60
  safeAreaFallbackColor,
@@ -78,6 +84,7 @@
78
84
  {onComponentInteraction}
79
85
  {onPurchaseClicked}
80
86
  {onInputChanged}
87
+ {onReservedAttributeChanged}
81
88
  {walletButtonRender}
82
89
  {safeAreaFallbackColor}
83
90
  onError={(error) => {
@@ -6,6 +6,7 @@ import type { WorkflowScreen } from "../../types/workflow";
6
6
  import type { VariableDictionary } from "../../types/variables";
7
7
  import type { WalletButtonRender } from "../../types/wallet";
8
8
  import type { UIConfig } from "../../types/ui-config";
9
+ import type { ReservedAttribute } from "../../types/components/input-text";
9
10
  interface Props {
10
11
  paywallComponents: WorkflowScreen | null | undefined;
11
12
  selectedLocale?: string;
@@ -20,6 +21,7 @@ interface Props {
20
21
  variablesPerPackage?: Record<string, VariableDictionary>;
21
22
  initialInputSelections?: InitialInputSelections;
22
23
  onInputChanged?: (fieldId: string, value: string, actionId?: string) => void;
24
+ onReservedAttributeChanged?: (reservedAttribute: ReservedAttribute, value: string) => void;
23
25
  onCompleteWorkflowNavigate?: (args: CompleteWorkflowNavigateArgs) => void | Promise<void>;
24
26
  walletButtonRender?: WalletButtonRender;
25
27
  safeAreaFallbackColor?: ColorScheme | null;
@@ -1,4 +1,5 @@
1
1
  import type { Action } from "../types/components/button";
2
+ import type { ReservedAttribute } from "../types/components/input-text";
2
3
  import type { ComponentInteractionData } from "../types/paywall-component-interaction";
3
4
  import type { UIConfig } from "../types/ui-config";
4
5
  import type { PackageInfo, VariableDictionary } from "../types/variables";
@@ -21,6 +22,7 @@ type PaywallContext = Readonly<{
21
22
  emitComponentInteraction: (data: ComponentInteractionData) => void;
22
23
  onNavigateToUrl?: (url: string) => void;
23
24
  onInputChanged?: (fieldId: string, value: string, actionId?: string) => void;
25
+ onReservedAttributeChanged?: (reservedAttribute: ReservedAttribute, value: string) => void;
24
26
  walletButtonRender?: WalletButtonRender;
25
27
  onWalletButtonReady?: (walletButtonAvailable?: boolean) => void;
26
28
  onButtonAction: (action: Action, actionId?: string) => void;
@@ -4,6 +4,7 @@ import type { ColorGradientScheme } from "../colors";
4
4
  import type { Overrides } from "../overrides";
5
5
  export type InputTextCapitalizeType = "none" | "sentences" | "words" | "characters";
6
6
  export type InputTextKeyboardType = "decimal" | "email" | "numeric" | "tel" | "text" | "url";
7
+ export type ReservedAttribute = "$email" | "$displayName" | "$phoneNumber";
7
8
  export interface InputTextProps extends BaseComponent {
8
9
  type: "input_text";
9
10
  visible?: boolean | null;
@@ -11,6 +12,7 @@ export interface InputTextProps extends BaseComponent {
11
12
  keyboard_type: InputTextKeyboardType;
12
13
  capitalize: InputTextCapitalizeType;
13
14
  field_id: string;
15
+ reserved_attribute?: ReservedAttribute | null;
14
16
  required: boolean;
15
17
  size: SizeType;
16
18
  padding: Spacing;
package/dist/types.d.ts CHANGED
@@ -122,3 +122,4 @@ export declare enum StackDistribution {
122
122
  export type { WorkflowScreen } from "./types/workflow";
123
123
  export type { ColorScheme } from "./types/colors";
124
124
  export type { ComponentInteractionData, ComponentInteractionType, OnComponentInteraction, } from "./types/paywall-component-interaction";
125
+ export type { ReservedAttribute } from "./types/components/input-text";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@revenuecat/purchases-ui-js",
3
3
  "description": "Web components for Paywalls. Powered by RevenueCat",
4
4
  "private": false,
5
- "version": "4.4.0",
5
+ "version": "4.5.1",
6
6
  "author": {
7
7
  "name": "RevenueCat, Inc."
8
8
  },