@revenuecat/purchases-ui-js 2.0.5 → 2.0.6

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.
@@ -29,8 +29,10 @@
29
29
  return true;
30
30
  }
31
31
  });
32
+
33
+ const style = $derived({
34
+ visibility: visible ? "visible" : "hidden",
35
+ });
32
36
  </script>
33
37
 
34
- {#if visible}
35
- <Stack {...props.stack} {onclick} />
36
- {/if}
38
+ <Stack {...props.stack} {onclick} {style} />
@@ -6,6 +6,7 @@
6
6
  PurchaseButton,
7
7
  Stack,
8
8
  Timeline,
9
+ Video,
9
10
  } from "../..";
10
11
  import ButtonNode from "../button/ButtonNode.svelte";
11
12
  import TextNode from "../text/TextNode.svelte";
@@ -15,6 +16,7 @@
15
16
  import Icon from "../icon/Icon.svelte";
16
17
  import TabControl from "../tabs/TabControl.svelte";
17
18
  import TabControlButton from "../tabs/TabControlButton.svelte";
19
+ import TabControlToggle from "../tabs/TabControlToggle.svelte";
18
20
  import Tabs from "../tabs/Tabs.svelte";
19
21
 
20
22
  interface Props {
@@ -31,10 +33,12 @@
31
33
  purchase_button: PurchaseButton,
32
34
  stack: Stack,
33
35
  tab_control_button: TabControlButton,
36
+ tab_control_toggle: TabControlToggle,
34
37
  tab_control: TabControl,
35
38
  tabs: Tabs,
36
39
  text: TextNode,
37
40
  timeline: Timeline,
41
+ video: Video,
38
42
  } satisfies {
39
43
  [key in Component["type"]]: SvelteComponent<
40
44
  Extract<Component, { type: key }>
@@ -19,8 +19,8 @@
19
19
  import { findSelectedPackageId } from "../../utils/style-utils";
20
20
  import { onMount } from "svelte";
21
21
  import { derived, readable, writable } from "svelte/store";
22
- import Sheet from "./Sheet.svelte";
23
22
  import Stack from "../stack/Stack.svelte";
23
+ import Sheet from "./Sheet.svelte";
24
24
 
25
25
  interface Props {
26
26
  paywallData: PaywallData;
@@ -139,7 +139,7 @@
139
139
  </script>
140
140
 
141
141
  <svelte:boundary onerror={onError}>
142
- <div id="paywall" class={paywallClass} {style}>
142
+ <div class={paywallClass} {style}>
143
143
  <Stack {...stack} />
144
144
 
145
145
  {#if sticky_footer}
@@ -159,9 +159,8 @@
159
159
  flex-direction: column;
160
160
  align-items: stretch;
161
161
  height: 100%;
162
- overflow: hidden;
163
162
 
164
- transition-property: filter transform;
163
+ transition-property: filter, transform;
165
164
  transition-duration: 0.1s;
166
165
  transition-timing-function: ease-in-out;
167
166
  transform-origin: center;
@@ -12,6 +12,7 @@
12
12
  mapSize,
13
13
  mapSpacing,
14
14
  px,
15
+ type CSS,
15
16
  } from "../../utils/base-utils";
16
17
  import { getActiveStateProps } from "../../utils/style-utils";
17
18
  import type { Snippet } from "svelte";
@@ -20,10 +21,11 @@
20
21
  interface MiscProps {
21
22
  onclick?: () => void;
22
23
  children?: Snippet;
24
+ style?: CSS;
23
25
  }
24
26
 
25
27
  const props: StackProps & MiscProps = $props();
26
- const { onclick, children } = props;
28
+ const { onclick, children, style } = props;
27
29
 
28
30
  const selectedState = getSelectedStateContext();
29
31
  const {
@@ -49,8 +51,9 @@
49
51
  const getColorMode = getColorModeContext();
50
52
  const colorMode = $derived(getColorMode());
51
53
 
52
- const style = $derived(
54
+ const stackStyle = $derived(
53
55
  css({
56
+ ...style,
54
57
  display: "flex",
55
58
  position: "relative",
56
59
  width: mapSize(size.width),
@@ -91,7 +94,7 @@
91
94
  this={onclick !== undefined ? "button" : "div"}
92
95
  role={onclick !== undefined ? "button" : undefined}
93
96
  {onclick}
94
- {style}
97
+ style={stackStyle}
95
98
  class="stack"
96
99
  >
97
100
  {#if badge}
@@ -1,8 +1,10 @@
1
1
  import type { StackProps } from "../../types/components/stack";
2
+ import { type CSS } from "../../utils/base-utils";
2
3
  import type { Snippet } from "svelte";
3
4
  interface MiscProps {
4
5
  onclick?: () => void;
5
6
  children?: Snippet;
7
+ style?: CSS;
6
8
  }
7
9
  type $$ComponentProps = StackProps & MiscProps;
8
10
  declare const Stack: import("svelte").Component<$$ComponentProps, {}, "">;
@@ -0,0 +1,103 @@
1
+ <script lang="ts">
2
+ import { getColorModeContext } from "../../stores/color-mode";
3
+ import {
4
+ getSelectedStateContext,
5
+ setSelectedStateContext,
6
+ } from "../../stores/selected";
7
+ import type { TabControlToggleProps } from "../../types/components/tabs";
8
+ import { css, mapColor } from "../../utils/base-utils";
9
+ import { getActiveStateProps } from "../../utils/style-utils";
10
+ import { getTabsContext } from "./tabs-context";
11
+
12
+ const props: TabControlToggleProps = $props();
13
+
14
+ const selectedState = getSelectedStateContext();
15
+ const {
16
+ default_value,
17
+ thumb_color_on,
18
+ thumb_color_off,
19
+ track_color_on,
20
+ track_color_off,
21
+ } = $derived.by(() => {
22
+ return {
23
+ ...props,
24
+ ...getActiveStateProps($selectedState, props.overrides),
25
+ };
26
+ });
27
+
28
+ const { isActive, selectTab } = getTabsContext();
29
+ setSelectedStateContext(isActive);
30
+
31
+ const getColorMode = getColorModeContext();
32
+ const colorMode = $derived(getColorMode());
33
+
34
+ const toggleStyle = $derived(
35
+ css({
36
+ background: $isActive
37
+ ? mapColor(colorMode, track_color_on)
38
+ : mapColor(colorMode, track_color_off),
39
+ }),
40
+ );
41
+
42
+ const thumbStyle = $derived(
43
+ css({
44
+ left: $isActive ? "22px" : "2px",
45
+ background: $isActive
46
+ ? mapColor(colorMode, thumb_color_on)
47
+ : mapColor(colorMode, thumb_color_off),
48
+ }),
49
+ );
50
+
51
+ const onclick = () => {
52
+ selectTab("", $isActive ? 0 : 1);
53
+ };
54
+
55
+ const onkeydown = (event: KeyboardEvent) => {
56
+ if (event.code === "Enter" || event.code === "Space") {
57
+ onclick();
58
+ }
59
+ };
60
+ </script>
61
+
62
+ <div
63
+ role="button"
64
+ tabindex="0"
65
+ aria-label="Toggle"
66
+ class="toggle"
67
+ style={toggleStyle}
68
+ {onclick}
69
+ {onkeydown}
70
+ >
71
+ <div class="thumb" style={thumbStyle}></div>
72
+ </div>
73
+
74
+ <style>
75
+ .toggle {
76
+ appearance: none;
77
+
78
+ --height: 31px;
79
+
80
+ position: relative;
81
+ width: 51px;
82
+ height: var(--height);
83
+ border-radius: calc(var(--height) / 2);
84
+ cursor: pointer;
85
+ user-select: none;
86
+ transition: background-color 300ms ease;
87
+ }
88
+
89
+ .thumb {
90
+ --size: 27px;
91
+ position: absolute;
92
+ top: 2px;
93
+ width: var(--size);
94
+ height: var(--size);
95
+ border-radius: 50%;
96
+ box-shadow:
97
+ 0 1px 3px rgba(0, 0, 0, 0.2),
98
+ 0 1px 2px rgba(0, 0, 0, 0.12);
99
+ transition:
100
+ left 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
101
+ background-color 300ms ease;
102
+ }
103
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { TabControlToggleProps } from "../../types/components/tabs";
2
+ declare const TabControlToggle: import("svelte").Component<TabControlToggleProps, {}, "">;
3
+ type TabControlToggle = ReturnType<typeof TabControlToggle>;
4
+ export default TabControlToggle;
@@ -927,3 +927,442 @@
927
927
  type: "tabs",
928
928
  }}
929
929
  />
930
+
931
+ <Story
932
+ name="Toggle"
933
+ decorators={[
934
+ componentDecorator(),
935
+ localizationDecorator({
936
+ defaultLocale,
937
+ localizations: {
938
+ [defaultLocale]: {
939
+ "9snr-lp9lS": "Show family plans",
940
+ izPmeYOm4j: "Show family plans",
941
+ },
942
+ },
943
+ }),
944
+ ]}
945
+ args={{
946
+ background: null,
947
+ control: {
948
+ stack: {
949
+ background: null,
950
+ background_color: null,
951
+ badge: null,
952
+ border: null,
953
+ components: [
954
+ {
955
+ default_value: true,
956
+ id: "gVAl7ORI44",
957
+ name: "",
958
+ thumb_color_off: {
959
+ light: {
960
+ type: "hex",
961
+ value: "#FFFFFF",
962
+ },
963
+ },
964
+ thumb_color_on: {
965
+ light: {
966
+ type: "hex",
967
+ value: "#FFFFFF",
968
+ },
969
+ },
970
+ track_color_off: {
971
+ light: {
972
+ type: "hex",
973
+ value: "#e1e1e5ff",
974
+ },
975
+ },
976
+ track_color_on: {
977
+ light: {
978
+ type: "hex",
979
+ value: "#576CDBff",
980
+ },
981
+ },
982
+ type: "tab_control_toggle",
983
+ },
984
+ ],
985
+ dimension: {
986
+ alignment: "leading",
987
+ distribution: "start",
988
+ type: "vertical",
989
+ },
990
+ id: "hIpAw5JTtG",
991
+ margin: {
992
+ bottom: 0,
993
+ leading: 0,
994
+ top: 0,
995
+ trailing: 0,
996
+ },
997
+ name: "",
998
+ padding: {
999
+ bottom: 0,
1000
+ leading: 0,
1001
+ top: 0,
1002
+ trailing: 0,
1003
+ },
1004
+ shadow: null,
1005
+ shape: {
1006
+ corners: {
1007
+ bottom_leading: 0,
1008
+ bottom_trailing: 0,
1009
+ top_leading: 0,
1010
+ top_trailing: 0,
1011
+ },
1012
+ type: "rectangle",
1013
+ },
1014
+ size: {
1015
+ height: {
1016
+ type: "fit",
1017
+ value: null,
1018
+ },
1019
+ width: {
1020
+ type: "fit",
1021
+ value: null,
1022
+ },
1023
+ },
1024
+ spacing: 0,
1025
+ type: "stack",
1026
+ },
1027
+ type: "toggle",
1028
+ },
1029
+ default_tab_id: "gi3qRZrSKa",
1030
+ id: "zRnUSrsOhj",
1031
+ margin: {
1032
+ bottom: 0,
1033
+ leading: 0,
1034
+ top: 0,
1035
+ trailing: 0,
1036
+ },
1037
+ name: "",
1038
+ padding: {
1039
+ bottom: 16,
1040
+ leading: 16,
1041
+ top: 16,
1042
+ trailing: 16,
1043
+ },
1044
+ shape: {
1045
+ corners: {
1046
+ bottom_leading: 0,
1047
+ bottom_trailing: 0,
1048
+ top_leading: 0,
1049
+ top_trailing: 0,
1050
+ },
1051
+ type: "rectangle",
1052
+ },
1053
+ size: {
1054
+ height: {
1055
+ type: "fit",
1056
+ value: null,
1057
+ },
1058
+ width: {
1059
+ type: "fill",
1060
+ value: null,
1061
+ },
1062
+ },
1063
+ tabs: [
1064
+ {
1065
+ id: "MEOs13s6G8",
1066
+ name: "OFF",
1067
+ stack: {
1068
+ background: null,
1069
+ background_color: null,
1070
+ badge: null,
1071
+ border: null,
1072
+ components: [
1073
+ {
1074
+ background: {
1075
+ type: "color",
1076
+ value: {
1077
+ light: {
1078
+ type: "hex",
1079
+ value: "#f7f7faff",
1080
+ },
1081
+ },
1082
+ },
1083
+ background_color: null,
1084
+ badge: null,
1085
+ border: null,
1086
+ components: [
1087
+ {
1088
+ background_color: null,
1089
+ color: {
1090
+ light: {
1091
+ type: "hex",
1092
+ value: "#000000e6",
1093
+ },
1094
+ },
1095
+ font_name: null,
1096
+ font_size: 14,
1097
+ font_weight: "regular",
1098
+ font_weight_int: 400,
1099
+ horizontal_alignment: "leading",
1100
+ id: "By5e8IBSbf",
1101
+ margin: {
1102
+ bottom: 0,
1103
+ leading: 0,
1104
+ top: 0,
1105
+ trailing: 0,
1106
+ },
1107
+ name: "",
1108
+ padding: {
1109
+ bottom: 0,
1110
+ leading: 0,
1111
+ top: 0,
1112
+ trailing: 0,
1113
+ },
1114
+ size: {
1115
+ height: {
1116
+ type: "fit",
1117
+ value: null,
1118
+ },
1119
+ width: {
1120
+ type: "fit",
1121
+ value: null,
1122
+ },
1123
+ },
1124
+ text_lid: "9snr-lp9lS",
1125
+ type: "text",
1126
+ },
1127
+ {
1128
+ id: "ZRerJx5wLi",
1129
+ name: "",
1130
+ type: "tab_control",
1131
+ },
1132
+ ],
1133
+ dimension: {
1134
+ alignment: "center",
1135
+ distribution: "space_between",
1136
+ type: "horizontal",
1137
+ },
1138
+ id: "ATrU9MBBJx",
1139
+ margin: {
1140
+ bottom: 0,
1141
+ leading: 16,
1142
+ top: 0,
1143
+ trailing: 16,
1144
+ },
1145
+ name: "Switch stack",
1146
+ padding: {
1147
+ bottom: 8,
1148
+ leading: 24,
1149
+ top: 8,
1150
+ trailing: 8,
1151
+ },
1152
+ shadow: null,
1153
+ shape: {
1154
+ corners: null,
1155
+ type: "pill",
1156
+ },
1157
+ size: {
1158
+ height: {
1159
+ type: "fit",
1160
+ value: null,
1161
+ },
1162
+ width: {
1163
+ type: "fit",
1164
+ value: null,
1165
+ },
1166
+ },
1167
+ spacing: 24,
1168
+ type: "stack",
1169
+ },
1170
+ ],
1171
+ dimension: {
1172
+ alignment: "center",
1173
+ distribution: "center",
1174
+ type: "vertical",
1175
+ },
1176
+ id: "tj1QOsrpFb",
1177
+ margin: {
1178
+ bottom: 0,
1179
+ leading: 0,
1180
+ top: 0,
1181
+ trailing: 0,
1182
+ },
1183
+ name: "Tab",
1184
+ padding: {
1185
+ bottom: 0,
1186
+ leading: 0,
1187
+ top: 0,
1188
+ trailing: 0,
1189
+ },
1190
+ shadow: null,
1191
+ shape: {
1192
+ corners: {
1193
+ bottom_leading: 0,
1194
+ bottom_trailing: 0,
1195
+ top_leading: 0,
1196
+ top_trailing: 0,
1197
+ },
1198
+ type: "rectangle",
1199
+ },
1200
+ size: {
1201
+ height: {
1202
+ type: "fit",
1203
+ value: null,
1204
+ },
1205
+ width: {
1206
+ type: "fill",
1207
+ value: null,
1208
+ },
1209
+ },
1210
+ spacing: 16,
1211
+ type: "stack",
1212
+ },
1213
+ type: "tab",
1214
+ },
1215
+ {
1216
+ id: "gi3qRZrSKa",
1217
+ name: "ON",
1218
+ stack: {
1219
+ background: null,
1220
+ background_color: null,
1221
+ border: null,
1222
+ components: [
1223
+ {
1224
+ background: {
1225
+ type: "color",
1226
+ value: {
1227
+ light: {
1228
+ type: "hex",
1229
+ value: "#f7f7faff",
1230
+ },
1231
+ },
1232
+ },
1233
+ background_color: null,
1234
+ badge: null,
1235
+ border: null,
1236
+ components: [
1237
+ {
1238
+ background_color: null,
1239
+ color: {
1240
+ light: {
1241
+ type: "hex",
1242
+ value: "#000000e6",
1243
+ },
1244
+ },
1245
+ font_name: null,
1246
+ font_size: 14,
1247
+ font_weight: "regular",
1248
+ font_weight_int: 400,
1249
+ horizontal_alignment: "leading",
1250
+ id: "xs9GkrXsl9",
1251
+ margin: {
1252
+ bottom: 0,
1253
+ leading: 0,
1254
+ top: 0,
1255
+ trailing: 0,
1256
+ },
1257
+ name: "",
1258
+ padding: {
1259
+ bottom: 0,
1260
+ leading: 0,
1261
+ top: 0,
1262
+ trailing: 0,
1263
+ },
1264
+ size: {
1265
+ height: {
1266
+ type: "fit",
1267
+ value: null,
1268
+ },
1269
+ width: {
1270
+ type: "fit",
1271
+ value: null,
1272
+ },
1273
+ },
1274
+ text_lid: "izPmeYOm4j",
1275
+ type: "text",
1276
+ },
1277
+ {
1278
+ id: "XMUc_WOeWO",
1279
+ name: "",
1280
+ type: "tab_control",
1281
+ },
1282
+ ],
1283
+ dimension: {
1284
+ alignment: "center",
1285
+ distribution: "space_between",
1286
+ type: "horizontal",
1287
+ },
1288
+ id: "PNnFNzZU4M",
1289
+ margin: {
1290
+ bottom: 0,
1291
+ leading: 16,
1292
+ top: 0,
1293
+ trailing: 16,
1294
+ },
1295
+ name: "Switch stack",
1296
+ padding: {
1297
+ bottom: 8,
1298
+ leading: 24,
1299
+ top: 8,
1300
+ trailing: 8,
1301
+ },
1302
+ shadow: null,
1303
+ shape: {
1304
+ corners: null,
1305
+ type: "pill",
1306
+ },
1307
+ size: {
1308
+ height: {
1309
+ type: "fit",
1310
+ value: null,
1311
+ },
1312
+ width: {
1313
+ type: "fit",
1314
+ value: null,
1315
+ },
1316
+ },
1317
+ spacing: 24,
1318
+ type: "stack",
1319
+ },
1320
+ ],
1321
+ dimension: {
1322
+ alignment: "center",
1323
+ distribution: "center",
1324
+ type: "vertical",
1325
+ },
1326
+ id: "Q6oIOhxGOB",
1327
+ margin: {
1328
+ bottom: 0,
1329
+ leading: 0,
1330
+ top: 0,
1331
+ trailing: 0,
1332
+ },
1333
+ name: "Tab",
1334
+ padding: {
1335
+ bottom: 0,
1336
+ leading: 0,
1337
+ top: 0,
1338
+ trailing: 0,
1339
+ },
1340
+ shadow: null,
1341
+ shape: {
1342
+ corners: {
1343
+ bottom_leading: 0,
1344
+ bottom_trailing: 0,
1345
+ top_leading: 0,
1346
+ top_trailing: 0,
1347
+ },
1348
+ type: "rectangle",
1349
+ },
1350
+ size: {
1351
+ height: {
1352
+ type: "fit",
1353
+ value: null,
1354
+ },
1355
+ width: {
1356
+ type: "fill",
1357
+ value: null,
1358
+ },
1359
+ },
1360
+ spacing: 16,
1361
+ type: "stack",
1362
+ },
1363
+ type: "tab",
1364
+ },
1365
+ ],
1366
+ type: "tabs",
1367
+ }}
1368
+ />
@@ -44,14 +44,20 @@
44
44
  }),
45
45
  );
46
46
 
47
- const tab = writable(
48
- tabs.find((tab) => tab.id === default_tab_id) ?? tabs.at(0),
47
+ const selectedTabIndex = writable(
48
+ Math.max(
49
+ 0,
50
+ tabs.findIndex((tab) => tab.id === default_tab_id),
51
+ ),
49
52
  );
50
53
 
54
+ const tab = derived(selectedTabIndex, (value) => tabs[value]);
55
+
51
56
  const selectTab: SelectTab = (tabId, tabIndex) => {
52
- const nextTab = tabs.find((tab) => tab.id === tabId) ?? tabs.at(tabIndex);
53
- if (nextTab !== undefined) {
54
- tab.set(nextTab);
57
+ const foundIndex = tabs.findIndex((tab) => tab.id === tabId);
58
+ const nextIndex = foundIndex !== -1 ? foundIndex : tabIndex;
59
+ if (nextIndex >= 0 && nextIndex < tabs.length) {
60
+ selectedTabIndex.set(tabIndex);
55
61
  }
56
62
  };
57
63
 
@@ -59,6 +65,7 @@
59
65
  control: readable(control),
60
66
  selectedTabId: derived(tab, (tab) => tab.id),
61
67
  selectTab,
68
+ isActive: derived(selectedTabIndex, (value) => value === 1),
62
69
  });
63
70
  </script>
64
71