@revenuecat/purchases-ui-js 3.4.0 → 3.4.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.
- package/dist/components/options/InputMultipleChoice.svelte +11 -1
- package/dist/components/options/InputOption.svelte +29 -2
- package/dist/components/options/InputSingleChoice.svelte +11 -1
- package/dist/components/paywall/Paywall.svelte +4 -1
- package/dist/components/paywall/Paywall.svelte.d.ts +4 -1
- package/dist/components/stack/Stack.svelte +7 -1
- package/dist/stores/hover.d.ts +5 -0
- package/dist/stores/hover.js +10 -0
- package/dist/stores/inputChoice.d.ts +12 -0
- package/dist/stores/inputChoice.js +37 -0
- package/dist/stores/paywall.d.ts +4 -1
- package/dist/stories/paywall-decorator.d.ts +4 -1
- package/dist/types/overrides.d.ts +4 -1
- package/dist/utils/style-utils.d.ts +1 -0
- package/dist/utils/style-utils.js +7 -0
- package/package.json +1 -1
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Node from "../paywall/Node.svelte";
|
|
3
|
+
import {
|
|
4
|
+
createInputChoiceContext,
|
|
5
|
+
setInputChoiceContext,
|
|
6
|
+
} from "../../stores/inputChoice";
|
|
3
7
|
import type { InputMultipleChoiceProps } from "../../types/components/options";
|
|
4
8
|
|
|
5
9
|
const props: InputMultipleChoiceProps = $props();
|
|
6
|
-
const { stack } = props;
|
|
10
|
+
const { stack, field_id } = props;
|
|
11
|
+
|
|
12
|
+
const initialInputChoiceContext = createInputChoiceContext(
|
|
13
|
+
field_id,
|
|
14
|
+
"multiple",
|
|
15
|
+
);
|
|
16
|
+
setInputChoiceContext(initialInputChoiceContext);
|
|
7
17
|
</script>
|
|
8
18
|
|
|
9
19
|
<Node nodeData={stack} />
|
|
@@ -1,18 +1,45 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Stack from "../stack/Stack.svelte";
|
|
3
|
+
import { setHoverStateContext } from "../../stores/hover";
|
|
4
|
+
import { getInputChoiceContext } from "../../stores/inputChoice";
|
|
3
5
|
import { getPaywallContext } from "../../stores/paywall";
|
|
6
|
+
import { setSelectedStateContext } from "../../stores/selected";
|
|
4
7
|
import type { InputOptionProps } from "../../types/components/options";
|
|
8
|
+
import { derived, readable, writable } from "svelte/store";
|
|
5
9
|
|
|
6
10
|
const props: InputOptionProps = $props();
|
|
7
|
-
const { stack } = props;
|
|
11
|
+
const { stack, option_id } = props;
|
|
8
12
|
|
|
9
13
|
const { onButtonAction } = getPaywallContext();
|
|
14
|
+
const inputChoiceContext = getInputChoiceContext();
|
|
15
|
+
|
|
16
|
+
// Derive selected state from context (similar to Package)
|
|
17
|
+
const isSelected = inputChoiceContext
|
|
18
|
+
? derived(inputChoiceContext.selectedOptionIds, (ids) => ids.has(option_id))
|
|
19
|
+
: readable(false);
|
|
20
|
+
setSelectedStateContext(isSelected);
|
|
21
|
+
|
|
22
|
+
const isHovered = writable(false);
|
|
23
|
+
setHoverStateContext(isHovered);
|
|
24
|
+
|
|
25
|
+
const onmouseenter = () => isHovered.set(true);
|
|
26
|
+
const onmouseleave = () => isHovered.set(false);
|
|
10
27
|
|
|
11
28
|
const onclick = () => {
|
|
12
29
|
const actionId = props.triggers?.on_press;
|
|
13
30
|
// Create a workflow action to pass up through the callback
|
|
14
31
|
onButtonAction({ type: "workflow" }, actionId);
|
|
32
|
+
inputChoiceContext?.selectOption(option_id);
|
|
15
33
|
};
|
|
16
34
|
</script>
|
|
17
35
|
|
|
18
|
-
|
|
36
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
37
|
+
<div class="option-wrapper" {onmouseenter} {onmouseleave}>
|
|
38
|
+
<Stack {...stack} {onclick} />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<style>
|
|
42
|
+
.option-wrapper {
|
|
43
|
+
display: contents;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Node from "../paywall/Node.svelte";
|
|
3
|
+
import {
|
|
4
|
+
createInputChoiceContext,
|
|
5
|
+
setInputChoiceContext,
|
|
6
|
+
} from "../../stores/inputChoice";
|
|
3
7
|
import type { InputSingleChoiceProps } from "../../types/components/options";
|
|
4
8
|
|
|
5
9
|
const props: InputSingleChoiceProps = $props();
|
|
6
|
-
const { stack } = props;
|
|
10
|
+
const { stack, field_id } = props;
|
|
11
|
+
|
|
12
|
+
const initialInputChoiceContext = createInputChoiceContext(
|
|
13
|
+
field_id,
|
|
14
|
+
"single",
|
|
15
|
+
);
|
|
16
|
+
setInputChoiceContext(initialInputChoiceContext);
|
|
7
17
|
</script>
|
|
8
18
|
|
|
9
19
|
<Node nodeData={stack} />
|
|
@@ -29,7 +29,10 @@ interface Props {
|
|
|
29
29
|
onReady?: () => void;
|
|
30
30
|
}) => {
|
|
31
31
|
destroy?: () => void;
|
|
32
|
-
update?: (
|
|
32
|
+
update?: (updateParams: {
|
|
33
|
+
selectedPackageId: string;
|
|
34
|
+
onReady?: () => void;
|
|
35
|
+
}) => void;
|
|
33
36
|
};
|
|
34
37
|
maxContentWidth?: string;
|
|
35
38
|
}
|
|
@@ -1,6 +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";
|
|
4
5
|
import { getSelectedStateContext } from "../../stores/selected";
|
|
5
6
|
import type { StackProps } from "../../types/components/stack";
|
|
6
7
|
import { mapBackground } from "../../utils/background-utils";
|
|
@@ -14,7 +15,10 @@
|
|
|
14
15
|
px,
|
|
15
16
|
type CSS,
|
|
16
17
|
} from "../../utils/base-utils";
|
|
17
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
getActiveStateProps,
|
|
20
|
+
getHoverStateProps,
|
|
21
|
+
} from "../../utils/style-utils";
|
|
18
22
|
import type { Snippet } from "svelte";
|
|
19
23
|
import { mapBadge, mapDimension, mapLayerAlignment } from "./stack-utils";
|
|
20
24
|
|
|
@@ -28,6 +32,7 @@
|
|
|
28
32
|
const { onclick, children, style } = props;
|
|
29
33
|
|
|
30
34
|
const selectedState = getSelectedStateContext();
|
|
35
|
+
const hoverState = getHoverStateContext();
|
|
31
36
|
const {
|
|
32
37
|
components,
|
|
33
38
|
size,
|
|
@@ -44,6 +49,7 @@
|
|
|
44
49
|
} = $derived.by(() => {
|
|
45
50
|
return {
|
|
46
51
|
...props,
|
|
52
|
+
...getHoverStateProps($hoverState, props.overrides),
|
|
47
53
|
...getActiveStateProps($selectedState, props.overrides),
|
|
48
54
|
};
|
|
49
55
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
import { readable } from "svelte/store";
|
|
3
|
+
const key = Symbol("hover");
|
|
4
|
+
export function setHoverStateContext(context) {
|
|
5
|
+
setContext(key, context);
|
|
6
|
+
}
|
|
7
|
+
export function getHoverStateContext() {
|
|
8
|
+
const context = getContext(key);
|
|
9
|
+
return context ?? readable(false);
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Readable } from "svelte/store";
|
|
2
|
+
type SelectionMode = "single" | "multiple";
|
|
3
|
+
interface InputChoiceContext {
|
|
4
|
+
fieldId: string;
|
|
5
|
+
mode: SelectionMode;
|
|
6
|
+
selectedOptionIds: Readable<Set<string>>;
|
|
7
|
+
selectOption: (optionId: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function createInputChoiceContext(fieldId: string, mode: SelectionMode): InputChoiceContext;
|
|
10
|
+
export declare function setInputChoiceContext(context: InputChoiceContext): void;
|
|
11
|
+
export declare function getInputChoiceContext(): InputChoiceContext | undefined;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
import { writable } from "svelte/store";
|
|
3
|
+
const key = Symbol("inputChoice");
|
|
4
|
+
export function createInputChoiceContext(fieldId, mode) {
|
|
5
|
+
const selectedOptionIds = writable(new Set());
|
|
6
|
+
const selectOption = (optionId) => {
|
|
7
|
+
selectedOptionIds.update((current) => {
|
|
8
|
+
if (mode === "single") {
|
|
9
|
+
// Single select: replace with new selection
|
|
10
|
+
return new Set([optionId]);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
// Multiple select: toggle the option
|
|
14
|
+
const next = new Set(current);
|
|
15
|
+
if (next.has(optionId)) {
|
|
16
|
+
next.delete(optionId);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
next.add(optionId);
|
|
20
|
+
}
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
fieldId,
|
|
27
|
+
mode,
|
|
28
|
+
selectedOptionIds,
|
|
29
|
+
selectOption,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function setInputChoiceContext(context) {
|
|
33
|
+
setContext(key, context);
|
|
34
|
+
}
|
|
35
|
+
export function getInputChoiceContext() {
|
|
36
|
+
return getContext(key);
|
|
37
|
+
}
|
package/dist/stores/paywall.d.ts
CHANGED
|
@@ -12,7 +12,10 @@ type PaywallContext = Readonly<{
|
|
|
12
12
|
onReady?: () => void;
|
|
13
13
|
}) => {
|
|
14
14
|
destroy?: () => void;
|
|
15
|
-
update?: (
|
|
15
|
+
update?: (params: {
|
|
16
|
+
selectedPackageId: string;
|
|
17
|
+
onReady?: () => void;
|
|
18
|
+
}) => void;
|
|
16
19
|
};
|
|
17
20
|
onButtonAction: (action: Action, actionId?: string) => void;
|
|
18
21
|
uiConfig: UIConfig;
|
|
@@ -4,5 +4,8 @@ export declare function paywallDecorator<TRenderer extends Renderer, TArgs>(wall
|
|
|
4
4
|
onReady?: () => void;
|
|
5
5
|
}) => {
|
|
6
6
|
destroy?: () => void;
|
|
7
|
-
update?: (
|
|
7
|
+
update?: (updateParams: {
|
|
8
|
+
selectedPackageId: string;
|
|
9
|
+
onReady?: () => void;
|
|
10
|
+
}) => void;
|
|
8
11
|
}): DecoratorFunction<TRenderer, TArgs>;
|
|
@@ -11,6 +11,9 @@ type MultipleIntroOffersCondition = {
|
|
|
11
11
|
type SelectedCondition = {
|
|
12
12
|
type: "selected";
|
|
13
13
|
};
|
|
14
|
+
type HoverCondition = {
|
|
15
|
+
type: "hover";
|
|
16
|
+
};
|
|
14
17
|
type ScreenSizeCondition = {
|
|
15
18
|
type: "screen_size";
|
|
16
19
|
operator: ArrayOperator;
|
|
@@ -34,7 +37,7 @@ type SelectedPackageCondition = {
|
|
|
34
37
|
type PromoOfferCondition = {
|
|
35
38
|
type: "promo_offer";
|
|
36
39
|
};
|
|
37
|
-
type OverrideCondition = IntroOfferCondition | MultipleIntroOffersCondition | SelectedCondition | ScreenSizeCondition | OrientationCondition | IntroductoryOfferCondition | SelectedPackageCondition | PromoOfferCondition;
|
|
40
|
+
type OverrideCondition = IntroOfferCondition | MultipleIntroOffersCondition | SelectedCondition | HoverCondition | ScreenSizeCondition | OrientationCondition | IntroductoryOfferCondition | SelectedPackageCondition | PromoOfferCondition;
|
|
38
41
|
/**
|
|
39
42
|
* The reserved properties of an override that should not be included in the override properties
|
|
40
43
|
*/
|
|
@@ -8,4 +8,5 @@ import type { RootPaywall } from "../types/paywall.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function findSelectedPackageId({ stack, sticky_footer, }: RootPaywall): string | undefined;
|
|
10
10
|
export declare const getActiveStateProps: <T extends Component>(selectedState: boolean, overrides?: Overrides<T>) => Partial<T>;
|
|
11
|
+
export declare const getHoverStateProps: <T extends Component>(hoverState: boolean, overrides?: Overrides<T>) => Partial<T>;
|
|
11
12
|
export declare const getIntroOfferStateProps: <T extends Component>(hasIntroOffer: boolean, overrides?: Overrides<T>) => Partial<T>;
|
|
@@ -43,6 +43,13 @@ export const getActiveStateProps = (selectedState, overrides) => {
|
|
|
43
43
|
const override = overrides?.find((override) => override.conditions.find((condition) => condition.type === "selected"));
|
|
44
44
|
return override?.properties ?? {};
|
|
45
45
|
};
|
|
46
|
+
export const getHoverStateProps = (hoverState, overrides) => {
|
|
47
|
+
if (!hoverState) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
const override = overrides?.find((override) => override.conditions.find((condition) => condition.type === "hover"));
|
|
51
|
+
return override?.properties ?? {};
|
|
52
|
+
};
|
|
46
53
|
export const getIntroOfferStateProps = (hasIntroOffer, overrides) => {
|
|
47
54
|
if (!hasIntroOffer) {
|
|
48
55
|
return {};
|