@revenuecat/purchases-ui-js 4.8.8 → 4.8.10

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.
Files changed (40) hide show
  1. package/dist/components/button/ButtonNode.svelte +10 -11
  2. package/dist/components/carousel/Carousel.svelte +37 -9
  3. package/dist/components/carousel/carousel-utils.d.ts +31 -0
  4. package/dist/components/carousel/carousel-utils.js +36 -0
  5. package/dist/components/icon/Icon.svelte +6 -24
  6. package/dist/components/image/Image.svelte +6 -24
  7. package/dist/components/input-text/InputText.svelte +10 -21
  8. package/dist/components/paywall/Paywall.stories.svelte +17 -0
  9. package/dist/components/paywall/Paywall.svelte +11 -0
  10. package/dist/components/paywall/Sheet.svelte +4 -4
  11. package/dist/components/stack/Stack.svelte +9 -28
  12. package/dist/components/tabs/TabControlToggle.svelte +5 -7
  13. package/dist/components/tabs/Tabs.svelte +26 -26
  14. package/dist/components/tabs/fixtures/tab-state-paywall.d.ts +25 -0
  15. package/dist/components/tabs/fixtures/tab-state-paywall.js +432 -0
  16. package/dist/components/text/TextNode.svelte +8 -37
  17. package/dist/components/timeline/Timeline.svelte +6 -25
  18. package/dist/components/timeline/TimelineItem.svelte +4 -4
  19. package/dist/components/video/Video.svelte +8 -25
  20. package/dist/components/web-view/WebView.svelte +6 -23
  21. package/dist/components/web-view/web-view-sdk.d.ts +21 -33
  22. package/dist/components/web-view/web-view-sdk.js +37 -47
  23. package/dist/components/workflows/Workflow.svelte +37 -7
  24. package/dist/components/workflows/fixtures/state-two-page-workflow.d.ts +2 -0
  25. package/dist/components/workflows/fixtures/state-two-page-workflow.js +80 -0
  26. package/dist/stores/condition-context.svelte.d.ts +14 -0
  27. package/dist/stores/condition-context.svelte.js +41 -0
  28. package/dist/stores/state.d.ts +29 -0
  29. package/dist/stores/state.js +136 -0
  30. package/dist/types/components/button.d.ts +2 -0
  31. package/dist/types/components/carousel.d.ts +2 -0
  32. package/dist/types/components/tabs.d.ts +2 -0
  33. package/dist/types/overrides.d.ts +9 -1
  34. package/dist/types/overrides.js +1 -0
  35. package/dist/types/paywall.d.ts +3 -0
  36. package/dist/types/state.d.ts +30 -0
  37. package/dist/types/state.js +11 -0
  38. package/dist/utils/style-utils.d.ts +21 -15
  39. package/dist/utils/style-utils.js +86 -61
  40. package/package.json +1 -1
@@ -1,15 +1,15 @@
1
1
  <script lang="ts">
2
2
  import Stack from "../stack/Stack.svelte";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
3
4
  import { getInputValidationContext } from "../../stores/inputValidation";
4
5
  import { getLocalizationContext } from "../../stores/localization";
5
6
  import { getPaywallContext } from "../../stores/paywall";
6
- import { getSelectedStateContext } from "../../stores/selected";
7
7
  import type { ButtonProps } from "../../types/components/button";
8
8
  import type {
9
9
  ButtonInteractionData,
10
10
  PackageSelectionSheetInteractionData,
11
11
  } from "../../types/paywall-component-interaction";
12
- import { getActiveStateProps } from "../../utils/style-utils";
12
+ import { resolveOverrideProperties } from "../../utils/style-utils";
13
13
  import { fromStore, readable } from "svelte/store";
14
14
  import { isWorkflowButtonInputGated } from "./button-input-gating";
15
15
 
@@ -19,20 +19,19 @@
19
19
  { type: "navigate_to"; destination: "sheet" }
20
20
  >;
21
21
 
22
- const selectedState = getSelectedStateContext();
23
- const { action } = $derived.by(() => {
24
- return {
25
- ...props,
26
- ...getActiveStateProps($selectedState, props.overrides),
27
- };
28
- });
29
-
30
22
  const {
31
23
  emitComponentInteraction,
32
24
  onButtonAction,
33
25
  hideBackButtons,
34
26
  selectedPackageId,
35
27
  } = getPaywallContext();
28
+ const buildConditionContext = useConditionContext();
29
+ const { action, stack } = $derived.by(() => {
30
+ return {
31
+ ...props,
32
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
33
+ };
34
+ });
36
35
  const validationContext = getInputValidationContext();
37
36
  const { getLocalizedString } = getLocalizationContext();
38
37
 
@@ -190,7 +189,7 @@
190
189
  inputSatisfied.current,
191
190
  )}
192
191
  <Stack
193
- {...props.stack}
192
+ {...stack}
194
193
  {onclick}
195
194
  style={isDisabled
196
195
  ? { opacity: "0.4", "pointer-events": "none", cursor: "not-allowed" }
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
3
4
  import { getPaywallContext } from "../../stores/paywall";
4
- import { getSelectedStateContext } from "../../stores/selected";
5
5
  import BackgroundVideoSurface from "../paywall/BackgroundVideoSurface.svelte";
6
6
  import type { CarouselProps } from "../../types/components/carousel";
7
7
  import {
@@ -20,14 +20,20 @@
20
20
  mapSpacing,
21
21
  px,
22
22
  } from "../../utils/base-utils";
23
- import { getActiveStateProps } from "../../utils/style-utils";
23
+ import { resolveOverrideProperties } from "../../utils/style-utils";
24
24
  import { onMount } from "svelte";
25
- import { clamp, getTranslation, mapPageAlignment } from "./carousel-utils";
25
+ import {
26
+ clamp,
27
+ getSwipeTargetPage,
28
+ getTranslation,
29
+ mapPageAlignment,
30
+ } from "./carousel-utils";
26
31
  import CarouselPage from "./CarouselPage.svelte";
27
32
  import PageControl from "./PageControl.svelte";
28
33
 
29
34
  const props: CarouselProps = $props();
30
- const selectedState = getSelectedStateContext();
35
+ const { emitComponentInteraction } = getPaywallContext();
36
+ const buildConditionContext = useConditionContext();
31
37
  const {
32
38
  pages,
33
39
  padding,
@@ -46,13 +52,12 @@
46
52
  } = $derived.by(() => {
47
53
  return {
48
54
  ...props,
49
- ...getActiveStateProps($selectedState, props.overrides),
55
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
50
56
  };
51
57
  });
52
58
 
53
59
  const getColorMode = getColorModeContext();
54
60
  const colorMode = $derived(getColorMode());
55
- const { emitComponentInteraction } = getPaywallContext();
56
61
 
57
62
  const hasVideoBg = $derived(background?.type === "video");
58
63
  const videoSurface = $derived.by(() => {
@@ -220,19 +225,35 @@
220
225
 
221
226
  let startTranslation = $state(0);
222
227
 
228
+ let lastClientX = 0;
229
+
223
230
  function onpointerdown(event: PointerEvent) {
224
231
  const target = event.currentTarget as HTMLElement;
225
232
  target.setPointerCapture(event.pointerId);
226
233
  startTranslation = getTranslation(slider);
227
234
  gestureStartPage = currentPage;
235
+ lastClientX = event.clientX;
228
236
  }
229
237
 
230
238
  function onpointerup(event: PointerEvent) {
231
239
  const target = event.currentTarget as HTMLElement;
232
- target.releasePointerCapture(event.pointerId);
240
+ if (target.hasPointerCapture(event.pointerId)) {
241
+ target.releasePointerCapture(event.pointerId);
242
+ }
233
243
 
234
244
  const translation = getTranslation(slider);
235
- const page = getPageFromTranslation(translation);
245
+
246
+ // Advance at most one page from where the gesture started, based on how
247
+ // far the finger travelled relative to a page's width (see
248
+ // getSwipeTargetPage).
249
+ const page = getSwipeTargetPage({
250
+ startPage: gestureStartPage ?? getPageFromTranslation(translation),
251
+ dragDistance: translation - startTranslation,
252
+ pageWidth,
253
+ pageCount: pages.length,
254
+ loop: carouselPagingLoop,
255
+ });
256
+
236
257
  const destinationPage = normalizePageIndex(page);
237
258
 
238
259
  if (gestureStartPage !== null && gestureStartPage !== destinationPage) {
@@ -249,6 +270,7 @@
249
270
  }
250
271
 
251
272
  gestureStartPage = null;
273
+ currentPage = destinationPage;
252
274
  startTransition(false, 500);
253
275
  moveTo(page);
254
276
  }
@@ -259,11 +281,17 @@
259
281
  return;
260
282
  }
261
283
 
284
+ // Track movement from clientX instead of event.movementX: movementX is 0
285
+ // for touch-derived pointer events in Safari and device-pixel scaled in
286
+ // some Chrome configurations.
287
+ const deltaX = event.clientX - lastClientX;
288
+ lastClientX = event.clientX;
289
+
262
290
  const [min, max] = carouselPagingLoop
263
291
  ? [startTranslation - carouselWidth, startTranslation + carouselWidth]
264
292
  : [-(pages.length - 1) * pageWidth, 0];
265
293
  const translation = getTranslation(slider);
266
- const newTranslation = clamp(translation + event.movementX, min, max);
294
+ const newTranslation = clamp(translation + deltaX, min, max);
267
295
 
268
296
  const page = getPageFromTranslation(newTranslation);
269
297
  currentPage = (page + pages.length) % pages.length;
@@ -1,4 +1,35 @@
1
1
  import type { VerticalAlignment } from "../../types/alignment";
2
2
  export declare function mapPageAlignment(alignment: VerticalAlignment): string;
3
3
  export declare function clamp(value: number, min: number, max: number): number;
4
+ /**
5
+ * Advance one page when the drag passed this fraction of a page's width,
6
+ * matching the iOS SDK carousel. A shorter drag snaps back to the page the
7
+ * gesture started on.
8
+ */
9
+ export declare const PAGE_ADVANCE_THRESHOLD = 0.2;
10
+ /**
11
+ * Decides which page a swipe settles on when the pointer is released.
12
+ *
13
+ * Distance-based (not velocity-based), mirroring the iOS SDK's `handleDragEnd`:
14
+ * a drag past `PAGE_ADVANCE_THRESHOLD` of a page's width advances exactly one
15
+ * page in the swipe direction regardless of speed; a shorter drag stays put.
16
+ * Non-loop carousels clamp at their first and last page; loop carousels may
17
+ * return an index just outside `[0, pageCount)` so the caller can animate into
18
+ * a clone before normalizing.
19
+ *
20
+ * @param startPage Page the gesture started on.
21
+ * @param dragDistance Signed change in slider translation (negative = finger
22
+ * moved left / next page).
23
+ * @param pageWidth Width of a single page in px.
24
+ * @param pageCount Total number of real pages.
25
+ * @param loop Whether the carousel loops.
26
+ */
27
+ export declare function getSwipeTargetPage({ startPage, dragDistance, pageWidth, pageCount, loop, advanceThreshold, }: {
28
+ startPage: number;
29
+ dragDistance: number;
30
+ pageWidth: number;
31
+ pageCount: number;
32
+ loop: boolean;
33
+ advanceThreshold?: number;
34
+ }): number;
4
35
  export declare function getTranslation(element: HTMLElement | null): number;
@@ -11,6 +11,42 @@ export function mapPageAlignment(alignment) {
11
11
  export function clamp(value, min, max) {
12
12
  return Math.max(min, Math.min(value, max));
13
13
  }
14
+ /**
15
+ * Advance one page when the drag passed this fraction of a page's width,
16
+ * matching the iOS SDK carousel. A shorter drag snaps back to the page the
17
+ * gesture started on.
18
+ */
19
+ export const PAGE_ADVANCE_THRESHOLD = 0.2;
20
+ /**
21
+ * Decides which page a swipe settles on when the pointer is released.
22
+ *
23
+ * Distance-based (not velocity-based), mirroring the iOS SDK's `handleDragEnd`:
24
+ * a drag past `PAGE_ADVANCE_THRESHOLD` of a page's width advances exactly one
25
+ * page in the swipe direction regardless of speed; a shorter drag stays put.
26
+ * Non-loop carousels clamp at their first and last page; loop carousels may
27
+ * return an index just outside `[0, pageCount)` so the caller can animate into
28
+ * a clone before normalizing.
29
+ *
30
+ * @param startPage Page the gesture started on.
31
+ * @param dragDistance Signed change in slider translation (negative = finger
32
+ * moved left / next page).
33
+ * @param pageWidth Width of a single page in px.
34
+ * @param pageCount Total number of real pages.
35
+ * @param loop Whether the carousel loops.
36
+ */
37
+ export function getSwipeTargetPage({ startPage, dragDistance, pageWidth, pageCount, loop, advanceThreshold = PAGE_ADVANCE_THRESHOLD, }) {
38
+ const threshold = pageWidth * advanceThreshold;
39
+ let page = startPage;
40
+ if (dragDistance < -threshold) {
41
+ // Finger moved left, content shifts left: next page.
42
+ page += 1;
43
+ }
44
+ else if (dragDistance > threshold) {
45
+ // Finger moved right: previous page.
46
+ page -= 1;
47
+ }
48
+ return loop ? page : clamp(page, 0, pageCount - 1);
49
+ }
14
50
  export function getTranslation(element) {
15
51
  if (element === null) {
16
52
  return 0;
@@ -1,9 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
- import { getOptionalPackageInfoContext } from "../../stores/packageInfo";
4
- import { getPaywallContext } from "../../stores/paywall";
5
- import { getSelectedStateContext } from "../../stores/selected";
6
- import { getOptionalVariablesContext } from "../../stores/variables";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
7
4
  import type { IconProps } from "../../types/components/icon";
8
5
  import {
9
6
  css,
@@ -14,16 +11,10 @@
14
11
  mapSize,
15
12
  mapSpacing,
16
13
  } from "../../utils/base-utils";
17
- import {
18
- evaluateVisibilityConditions,
19
- getActiveStateProps,
20
- } from "../../utils/style-utils";
14
+ import { resolveOverrideProperties } from "../../utils/style-utils";
21
15
 
22
16
  const props: IconProps = $props();
23
- const selectedState = getSelectedStateContext();
24
- const packageInfo = getOptionalPackageInfoContext();
25
- const { selectedPackageId } = getPaywallContext();
26
- const variables = getOptionalVariablesContext();
17
+ const buildConditionContext = useConditionContext({ state: true });
27
18
  const {
28
19
  base_url,
29
20
  formats,
@@ -32,10 +23,11 @@
32
23
  padding,
33
24
  color,
34
25
  icon_background: background,
26
+ visible,
35
27
  } = $derived.by(() => {
36
28
  return {
37
29
  ...props,
38
- ...getActiveStateProps($selectedState, props.overrides),
30
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
39
31
  };
40
32
  });
41
33
 
@@ -56,17 +48,7 @@
56
48
  }),
57
49
  );
58
50
 
59
- const isVisible = $derived(
60
- evaluateVisibilityConditions(
61
- {
62
- selectedPackageId: $selectedPackageId,
63
- packageInfo: $packageInfo,
64
- variables: $variables ?? {},
65
- },
66
- props.overrides,
67
- props.visible,
68
- ),
69
- );
51
+ const isVisible = $derived(visible !== false);
70
52
 
71
53
  const webpUrl = $derived(`${base_url}/${formats.webp}`);
72
54
  const icon = $derived(
@@ -1,9 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
- import { getOptionalPackageInfoContext } from "../../stores/packageInfo";
4
- import { getPaywallContext } from "../../stores/paywall";
5
- import { getSelectedStateContext } from "../../stores/selected";
6
- import { getOptionalVariablesContext } from "../../stores/variables";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
7
4
  import type { ImageProps } from "../../types/components/image";
8
5
  import {
9
6
  css,
@@ -13,19 +10,13 @@
13
10
  mapSize,
14
11
  mapSpacing,
15
12
  } from "../../utils/base-utils";
16
- import {
17
- evaluateVisibilityConditions,
18
- getActiveStateProps,
19
- } from "../../utils/style-utils";
13
+ import { resolveOverrideProperties } from "../../utils/style-utils";
20
14
  import ClipPath from "./ClipPath.svelte";
21
15
  import Overlay from "./Overlay.svelte";
22
16
 
23
17
  const props: ImageProps = $props();
24
18
 
25
- const selectedState = getSelectedStateContext();
26
- const packageInfo = getOptionalPackageInfoContext();
27
- const { selectedPackageId } = getPaywallContext();
28
- const variables = getOptionalVariablesContext();
19
+ const buildConditionContext = useConditionContext({ state: true });
29
20
  const {
30
21
  id,
31
22
  source,
@@ -37,10 +28,11 @@
37
28
  color_overlay,
38
29
  border,
39
30
  shadow,
31
+ visible,
40
32
  } = $derived.by(() => {
41
33
  return {
42
34
  ...props,
43
- ...getActiveStateProps($selectedState, props.overrides),
35
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
44
36
  };
45
37
  });
46
38
 
@@ -122,17 +114,7 @@
122
114
  color_overlay && mapColorMode(colorMode, color_overlay),
123
115
  );
124
116
 
125
- const isVisible = $derived(
126
- evaluateVisibilityConditions(
127
- {
128
- selectedPackageId: $selectedPackageId,
129
- packageInfo: $packageInfo,
130
- variables: $variables ?? {},
131
- },
132
- props.overrides,
133
- props.visible,
134
- ),
135
- );
117
+ const isVisible = $derived(visible !== false);
136
118
  </script>
137
119
 
138
120
  {#if isVisible}
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
3
4
  import { getInputValidationContext } from "../../stores/inputValidation";
4
5
  import { getLocalizationContext } from "../../stores/localization";
5
- import { getOptionalPackageInfoContext } from "../../stores/packageInfo";
6
6
  import { getPaywallContext } from "../../stores/paywall";
7
7
  import { getOptionalVariablesContext } from "../../stores/variables";
8
8
  import { FontWeights, TextAlignments } from "../../types";
@@ -23,11 +23,7 @@
23
23
  getScopedFontFamily,
24
24
  isFontRCFMManaged,
25
25
  } from "../../utils/font-utils";
26
- import {
27
- evaluateVisibilityConditions,
28
- getErrorStateProps,
29
- getFocusStateProps,
30
- } from "../../utils/style-utils";
26
+ import { resolveOverrideProperties } from "../../utils/style-utils";
31
27
  import { replaceVariables } from "../../utils/variable-utils";
32
28
  import type { FormEventHandler, HTMLInputAttributes } from "svelte/elements";
33
29
  import { mapTextColor } from "../text/text-utils";
@@ -38,6 +34,8 @@
38
34
  let error = $state(false);
39
35
  let valid = $state(!props.required);
40
36
 
37
+ const buildConditionContext = useConditionContext({ state: true });
38
+
41
39
  const {
42
40
  placeholder_lid,
43
41
  keyboard_type,
@@ -63,11 +61,14 @@
63
61
  placeholder_horizontal_alignment,
64
62
  placeholder_color,
65
63
  background_color,
64
+ visible,
66
65
  } = $derived.by(() => {
67
66
  return {
68
67
  ...props,
69
- ...getFocusStateProps(focused, props.overrides),
70
- ...getErrorStateProps(error, props.overrides),
68
+ ...resolveOverrideProperties(
69
+ buildConditionContext({ focus: focused, error }),
70
+ props.overrides,
71
+ ),
71
72
  };
72
73
  });
73
74
 
@@ -126,9 +127,7 @@
126
127
  onInputChanged,
127
128
  onSensitiveInputChanged,
128
129
  onReservedAttributeChanged,
129
- selectedPackageId,
130
130
  } = getPaywallContext();
131
- const packageInfo = getOptionalPackageInfoContext();
132
131
 
133
132
  const verticalAlignItems = $derived(
134
133
  vertical_alignment === "top"
@@ -220,17 +219,7 @@
220
219
  keyboard_type === "password" ? "text" : keyboard_type,
221
220
  );
222
221
 
223
- const isVisible = $derived(
224
- evaluateVisibilityConditions(
225
- {
226
- selectedPackageId: $selectedPackageId,
227
- packageInfo: $packageInfo,
228
- variables: $variables ?? {},
229
- },
230
- props.overrides,
231
- props.visible,
232
- ),
233
- );
222
+ const isVisible = $derived(visible !== false);
234
223
 
235
224
  if (validationContext) {
236
225
  $effect(() => {
@@ -32,6 +32,7 @@
32
32
  import { STACK_PAYWALL } from "./fixtures/stack-paywall";
33
33
  import { VARIABLES } from "./fixtures/variables";
34
34
  import { CUSTOM_VARIABLES_PAYWALL } from "./fixtures/custom-variables-paywall";
35
+ import { TAB_STATE_PAYWALL } from "../tabs/fixtures/tab-state-paywall";
35
36
  import { COUNTDOWN_PAYWALL } from "../countdown/fixtures/countdown-paywall";
36
37
  import { mockDateDecorator } from "storybook-mock-date-decorator";
37
38
  import {
@@ -101,6 +102,22 @@
101
102
  }}
102
103
  />
103
104
 
105
+ <Story
106
+ name="State-driven - tab state"
107
+ decorators={[viewportDecorator(375, 640, 0)]}
108
+ play={async ({ canvasElement }) => {
109
+ const annualTab = Array.from(canvasElement.querySelectorAll("button")).find(
110
+ (button) => button.textContent?.includes("Annual"),
111
+ );
112
+ annualTab?.click();
113
+ await waitForAnimations();
114
+ }}
115
+ args={{
116
+ paywallData: TAB_STATE_PAYWALL,
117
+ preferredColorMode: "light",
118
+ }}
119
+ />
120
+
104
121
  <Story
105
122
  name="Sheet"
106
123
  decorators={[viewportDecorator(500, 500, 0)]}
@@ -10,6 +10,11 @@
10
10
  } from "../../stores/inputValidation";
11
11
  import { setLocalizationContext } from "../../stores/localization";
12
12
  import { setPaywallContext } from "../../stores/paywall";
13
+ import {
14
+ PaywallStateStore,
15
+ getPaywallStateContext,
16
+ setPaywallStateContext,
17
+ } from "../../stores/state";
13
18
  import {
14
19
  setVariablesContext,
15
20
  type VariablesStore,
@@ -322,6 +327,12 @@
322
327
  hideBackButtons,
323
328
  });
324
329
 
330
+ // State store: reuse an ancestor store (when nested in a workflow) or create a standalone one.
331
+ const ancestorStateStore = getPaywallStateContext();
332
+ const stateStore = ancestorStateStore ?? new PaywallStateStore();
333
+ stateStore.registerDeclarations(paywallData.state_declarations ?? {});
334
+ if (!ancestorStateStore) setPaywallStateContext(stateStore);
335
+
325
336
  const inputValidationContext = createInputValidationContext();
326
337
  setInputValidationContext(inputValidationContext);
327
338
  setInitialInputSelectionsContext(initialInputSelections);
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
3
4
  import { getPaywallContext } from "../../stores/paywall";
4
- import { getSelectedStateContext } from "../../stores/selected";
5
5
  import BackgroundVideoSurface from "./BackgroundVideoSurface.svelte";
6
6
  import type { SheetProps } from "../../types/components/sheet";
7
7
  import {
@@ -13,18 +13,18 @@
13
13
  videoBackgroundHostStyles,
14
14
  } from "../../utils/video-background-host";
15
15
  import { css, mapSize } from "../../utils/base-utils";
16
- import { getActiveStateProps } from "../../utils/style-utils";
16
+ import { resolveOverrideProperties } from "../../utils/style-utils";
17
17
  import { onMount } from "svelte";
18
18
  import Stack from "../stack/Stack.svelte";
19
19
 
20
20
  const props: SheetProps = $props();
21
21
  const { stack } = props;
22
22
 
23
- const selectedState = getSelectedStateContext();
23
+ const buildConditionContext = useConditionContext({ state: true });
24
24
  const { size, background, background_blur, position } = $derived.by(() => {
25
25
  return {
26
26
  ...props,
27
- ...getActiveStateProps($selectedState, props.overrides),
27
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
28
28
  };
29
29
  });
30
30
 
@@ -1,11 +1,7 @@
1
1
  <script lang="ts">
2
2
  import Node from "../paywall/Node.svelte";
3
3
  import { getColorModeContext } from "../../stores/color-mode";
4
- import { getHoverStateContext } from "../../stores/hover";
5
- import { getOptionalPackageInfoContext } from "../../stores/packageInfo";
6
- import { getPaywallContext } from "../../stores/paywall";
7
- import { getSelectedStateContext } from "../../stores/selected";
8
- import { getOptionalVariablesContext } from "../../stores/variables";
4
+ import { useConditionContext } from "../../stores/condition-context.svelte";
9
5
  import BackgroundVideoSurface from "../paywall/BackgroundVideoSurface.svelte";
10
6
  import type { StackProps } from "../../types/components/stack";
11
7
  import {
@@ -26,11 +22,7 @@
26
22
  px,
27
23
  type CSS,
28
24
  } from "../../utils/base-utils";
29
- import {
30
- evaluateVisibilityConditions,
31
- getActiveStateProps,
32
- getHoverStateProps,
33
- } from "../../utils/style-utils";
25
+ import { resolveOverrideProperties } from "../../utils/style-utils";
34
26
  import type { Snippet } from "svelte";
35
27
  import {
36
28
  mapBadge,
@@ -51,11 +43,10 @@
51
43
  const props: StackProps & MiscProps = $props();
52
44
  const { onclick, children, class: classProp, testId } = props;
53
45
 
54
- const selectedState = getSelectedStateContext();
55
- const hoverState = getHoverStateContext();
56
- const packageInfo = getOptionalPackageInfoContext();
57
- const { selectedPackageId } = getPaywallContext();
58
- const variables = getOptionalVariablesContext();
46
+ const buildConditionContext = useConditionContext({
47
+ state: true,
48
+ hover: true,
49
+ });
59
50
  const {
60
51
  components,
61
52
  size,
@@ -69,11 +60,11 @@
69
60
  shape,
70
61
  shadow,
71
62
  badge,
63
+ visible,
72
64
  } = $derived.by(() => {
73
65
  return {
74
66
  ...props,
75
- ...getHoverStateProps($hoverState, props.overrides),
76
- ...getActiveStateProps($selectedState, props.overrides),
67
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
77
68
  };
78
69
  });
79
70
 
@@ -134,17 +125,7 @@
134
125
 
135
126
  const badgeStyle = $derived(css(mapBadge(badge, border?.width)));
136
127
 
137
- const isVisible = $derived(
138
- evaluateVisibilityConditions(
139
- {
140
- selectedPackageId: $selectedPackageId,
141
- packageInfo: $packageInfo,
142
- variables: $variables ?? {},
143
- },
144
- props.overrides,
145
- props.visible,
146
- ),
147
- );
128
+ const isVisible = $derived(visible !== false);
148
129
  </script>
149
130
 
150
131
  {#if isVisible}
@@ -1,17 +1,15 @@
1
1
  <script lang="ts">
2
2
  import { getColorModeContext } from "../../stores/color-mode";
3
- import {
4
- getSelectedStateContext,
5
- setSelectedStateContext,
6
- } from "../../stores/selected";
3
+ import { useConditionContext } from "../../stores/condition-context.svelte";
4
+ import { setSelectedStateContext } from "../../stores/selected";
7
5
  import type { TabControlToggleProps } from "../../types/components/tabs";
8
6
  import { css, mapColor } from "../../utils/base-utils";
9
- import { getActiveStateProps } from "../../utils/style-utils";
7
+ import { resolveOverrideProperties } from "../../utils/style-utils";
10
8
  import { getTabsContext } from "./tabs-context";
11
9
 
12
10
  const props: TabControlToggleProps = $props();
13
11
 
14
- const selectedState = getSelectedStateContext();
12
+ const buildConditionContext = useConditionContext({ state: true });
15
13
  const {
16
14
  default_value,
17
15
  thumb_color_on,
@@ -21,7 +19,7 @@
21
19
  } = $derived.by(() => {
22
20
  return {
23
21
  ...props,
24
- ...getActiveStateProps($selectedState, props.overrides),
22
+ ...resolveOverrideProperties(buildConditionContext(), props.overrides),
25
23
  };
26
24
  });
27
25