@varykit/vue 0.1.0

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/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # @varykit/vue
2
+
3
+ **Vue 3 composable and component for VaryKit segment-based multivariate testing.**
4
+
5
+ This package works in any Vue 3 app (Vite, plain Vue Router, etc.) with **no Nuxt present**. It depends on `@varykit/core` for bucketing and declares `vue` as a peer dependency.
6
+
7
+ ## The segment model
8
+
9
+ Every visitor is assigned to a **single global segment** (e.g. `control` or `treatment`), persisted in the `vary:segment` cookie. That segment is reused consistently across every element and page — a visitor is never in different segments for different tests.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add @varykit/vue
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### `useSegment(segments, options?)`
20
+
21
+ Resolves the visitor's global segment, persisting it in the `vary:segment` cookie so the assignment is sticky. Returns a reactive `{ segment }` ref.
22
+
23
+ ```vue
24
+ <script setup>
25
+ import { useSegment } from '@varykit/vue'
26
+
27
+ const segments = {
28
+ control: { distribution: 0.5 },
29
+ treatment: { distribution: 0.5 }
30
+ }
31
+
32
+ const { segment } = useSegment(segments)
33
+ </script>
34
+
35
+ <template>
36
+ <p v-if="segment === 'control'">Control content</p>
37
+ <p v-else>Treatment content</p>
38
+ </template>
39
+ ```
40
+
41
+ ### `<VaryShow>`
42
+
43
+ A template-only wrapper around `useSegment()`. Renders its default slot only when the visitor's segment matches the `segment` prop.
44
+
45
+ ```vue
46
+ <script setup>
47
+ import { VaryShow } from '@varykit/vue'
48
+
49
+ const segments = {
50
+ control: { distribution: 0.5 },
51
+ treatment: { distribution: 0.5 }
52
+ }
53
+ </script>
54
+
55
+ <template>
56
+ <VaryShow :segments="segments" segment="control">
57
+ <p>Control content</p>
58
+ </VaryShow>
59
+ </template>
60
+ ```
61
+
62
+ ### Options
63
+
64
+ | Option | Type | Description |
65
+ | ------ | ---- | ----------- |
66
+ | `duration` | `number` | Global default cookie duration in seconds. |
67
+ | `cookieName` | `string` | Override the cookie name (default `vary:segment`). |
68
+
69
+ ## Scope
70
+
71
+ This package owns Vue-specific persistence (`document.cookie`) and reactivity. It never imports from `@varykit/nuxt`.
72
+
73
+ ## License
74
+
75
+ MIT
@@ -0,0 +1,66 @@
1
+ import * as vue from 'vue';
2
+ import { Ref, PropType } from 'vue';
3
+ import { VarySegments } from '@varykit/core';
4
+ export { DEFAULT_DURATION, ResolvedSegment, VarySegmentConfig, VarySegments, resolveSegment, validateSegments } from '@varykit/core';
5
+
6
+ interface UseSegmentOptions {
7
+ duration?: number;
8
+ cookieName?: string;
9
+ }
10
+ interface UseSegmentReturn {
11
+ segment: Ref<string>;
12
+ }
13
+ /**
14
+ * Resolve the visitor's single global segment, persisting it in the
15
+ * `vary:segment` cookie so the assignment is sticky across requests.
16
+ *
17
+ * The same segment is reused across every page and element test.
18
+ */
19
+ declare function useSegment(segments: VarySegments, options?: UseSegmentOptions): UseSegmentReturn;
20
+
21
+ /**
22
+ * Template-only wrapper around `useSegment()`.
23
+ *
24
+ * Renders its default slot only when the visitor's global segment matches
25
+ * the `segment` prop.
26
+ *
27
+ * ```vue
28
+ * <VaryShow :segments="segments" segment="control">
29
+ * <p>Control content</p>
30
+ * </VaryShow>
31
+ * ```
32
+ */
33
+ declare const VaryShow: vue.DefineComponent<vue.ExtractPropTypes<{
34
+ segment: {
35
+ type: StringConstructor;
36
+ required: true;
37
+ };
38
+ segments: {
39
+ type: PropType<VarySegments>;
40
+ required: true;
41
+ };
42
+ duration: {
43
+ type: NumberConstructor;
44
+ default: undefined;
45
+ };
46
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
47
+ [key: string]: any;
48
+ }>[] | null | undefined, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
49
+ segment: {
50
+ type: StringConstructor;
51
+ required: true;
52
+ };
53
+ segments: {
54
+ type: PropType<VarySegments>;
55
+ required: true;
56
+ };
57
+ duration: {
58
+ type: NumberConstructor;
59
+ default: undefined;
60
+ };
61
+ }>> & Readonly<{}>, {
62
+ duration: number;
63
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
64
+
65
+ export { VaryShow, useSegment };
66
+ export type { UseSegmentOptions, UseSegmentReturn };
@@ -0,0 +1,66 @@
1
+ import * as vue from 'vue';
2
+ import { Ref, PropType } from 'vue';
3
+ import { VarySegments } from '@varykit/core';
4
+ export { DEFAULT_DURATION, ResolvedSegment, VarySegmentConfig, VarySegments, resolveSegment, validateSegments } from '@varykit/core';
5
+
6
+ interface UseSegmentOptions {
7
+ duration?: number;
8
+ cookieName?: string;
9
+ }
10
+ interface UseSegmentReturn {
11
+ segment: Ref<string>;
12
+ }
13
+ /**
14
+ * Resolve the visitor's single global segment, persisting it in the
15
+ * `vary:segment` cookie so the assignment is sticky across requests.
16
+ *
17
+ * The same segment is reused across every page and element test.
18
+ */
19
+ declare function useSegment(segments: VarySegments, options?: UseSegmentOptions): UseSegmentReturn;
20
+
21
+ /**
22
+ * Template-only wrapper around `useSegment()`.
23
+ *
24
+ * Renders its default slot only when the visitor's global segment matches
25
+ * the `segment` prop.
26
+ *
27
+ * ```vue
28
+ * <VaryShow :segments="segments" segment="control">
29
+ * <p>Control content</p>
30
+ * </VaryShow>
31
+ * ```
32
+ */
33
+ declare const VaryShow: vue.DefineComponent<vue.ExtractPropTypes<{
34
+ segment: {
35
+ type: StringConstructor;
36
+ required: true;
37
+ };
38
+ segments: {
39
+ type: PropType<VarySegments>;
40
+ required: true;
41
+ };
42
+ duration: {
43
+ type: NumberConstructor;
44
+ default: undefined;
45
+ };
46
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
47
+ [key: string]: any;
48
+ }>[] | null | undefined, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
49
+ segment: {
50
+ type: StringConstructor;
51
+ required: true;
52
+ };
53
+ segments: {
54
+ type: PropType<VarySegments>;
55
+ required: true;
56
+ };
57
+ duration: {
58
+ type: NumberConstructor;
59
+ default: undefined;
60
+ };
61
+ }>> & Readonly<{}>, {
62
+ duration: number;
63
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
64
+
65
+ export { VaryShow, useSegment };
66
+ export type { UseSegmentOptions, UseSegmentReturn };
package/dist/index.mjs ADDED
@@ -0,0 +1,50 @@
1
+ import { ref, defineComponent } from 'vue';
2
+ import { resolveSegment } from '@varykit/core';
3
+ export { DEFAULT_DURATION, resolveSegment, validateSegments } from '@varykit/core';
4
+
5
+ function getCookie(name) {
6
+ if (typeof document === "undefined") return void 0;
7
+ const match = document.cookie.split("; ").find((row) => row.startsWith(`${name}=`));
8
+ return match ? decodeURIComponent(match.slice(name.length + 1)) : void 0;
9
+ }
10
+ function setCookie(name, value, maxAge) {
11
+ if (typeof document === "undefined") return;
12
+ document.cookie = `${name}=${encodeURIComponent(value)}; path=/; max-age=${maxAge}`;
13
+ }
14
+ function useSegment(segments, options = {}) {
15
+ const cookieName = options.cookieName ?? "vary:segment";
16
+ const existingSegment = getCookie(cookieName);
17
+ const resolved = resolveSegment({
18
+ segments,
19
+ existingSegment,
20
+ defaultDuration: options.duration
21
+ });
22
+ setCookie(cookieName, resolved.segment, resolved.duration);
23
+ return { segment: ref(resolved.segment) };
24
+ }
25
+
26
+ const VaryShow = defineComponent({
27
+ name: "VaryShow",
28
+ props: {
29
+ segment: {
30
+ type: String,
31
+ required: true
32
+ },
33
+ segments: {
34
+ type: Object,
35
+ required: true
36
+ },
37
+ duration: {
38
+ type: Number,
39
+ default: void 0
40
+ }
41
+ },
42
+ setup(props, { slots }) {
43
+ const { segment } = useSegment(props.segments, {
44
+ duration: props.duration
45
+ });
46
+ return () => segment.value === props.segment ? slots.default?.() : null;
47
+ }
48
+ });
49
+
50
+ export { VaryShow, useSegment };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@varykit/vue",
3
+ "version": "0.1.0",
4
+ "description": "Vue 3 composable and component for VaryKit element-level multivariate testing.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.mts",
10
+ "import": "./dist/index.mjs"
11
+ }
12
+ },
13
+ "main": "./dist/index.mjs",
14
+ "types": "./dist/index.d.mts",
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "unbuild",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "keywords": [
23
+ "vue",
24
+ "a/b-testing",
25
+ "multivariate",
26
+ "ab-test",
27
+ "experimentation",
28
+ "bucketing",
29
+ "varykit"
30
+ ],
31
+ "dependencies": {
32
+ "@varykit/core": "workspace:*"
33
+ },
34
+ "peerDependencies": {
35
+ "vue": "^3.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.0.0",
39
+ "unbuild": "^3.0.0",
40
+ "vue": "^3.0.0"
41
+ }
42
+ }