@picked/client 0.0.1-dev.1776662399138 → 0.0.1-dev.1776837084253

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 (54) hide show
  1. package/dist/{api-C5p0q172.js → api-6oxKA__k.js} +1 -1
  2. package/dist/{api-CE3ISEsc.cjs → api-CIC-Uysx.cjs} +1 -1
  3. package/dist/cjs/form/index.js +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/create-experience/index.js +1 -1
  6. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  7. package/dist/cjs/plugins/experience-browser-storage/index.js +1 -1
  8. package/dist/cjs/plugins/single-page-app/index.js +1 -1
  9. package/dist/cjs/plugins/web-components/index.js +1 -1
  10. package/dist/cjs/plugins/window-object/index.js +1 -1
  11. package/dist/cjs/server/index.js +1 -1
  12. package/dist/docs/pickedql/data-sources.md +61 -2
  13. package/dist/docs/pickedql/examples.md +84 -0
  14. package/dist/docs/pickedql/index.md +1 -0
  15. package/dist/docs/pickedql/schema.md +28 -0
  16. package/dist/docs/pickedql/virtual-functions.md +40 -3
  17. package/dist/docs/sdk/actions.md +31 -1
  18. package/dist/docs/sdk/conditions.md +14 -8
  19. package/dist/docs/sdk/experiences.md +21 -18
  20. package/dist/docs/sdk/features.md +8 -8
  21. package/dist/docs/sdk/fields.md +9 -9
  22. package/dist/docs/sdk/steps.md +12 -12
  23. package/dist/esm/form/index.js +1 -1
  24. package/dist/esm/index.js +158 -284
  25. package/dist/esm/plugins/create-experience/index.js +1 -1
  26. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  27. package/dist/esm/plugins/experience-browser-storage/index.js +1 -1
  28. package/dist/esm/plugins/single-page-app/index.js +28 -14
  29. package/dist/esm/plugins/web-components/index.js +1 -1
  30. package/dist/esm/plugins/window-object/index.js +1 -1
  31. package/dist/esm/server/index.js +1 -1
  32. package/dist/experience-CNIhapU2.js +136 -0
  33. package/dist/experience-CTEBY-it.cjs +1 -0
  34. package/dist/experience-instance-Cu8oGGr9.cjs +1 -0
  35. package/dist/experience-instance-DIpWYaA6.js +387 -0
  36. package/dist/nodes-2fst8XKi.js +101 -0
  37. package/dist/nodes-DBK4N9YY.cjs +1 -0
  38. package/dist/rules-logic-D7dL30U1.js +263 -0
  39. package/dist/rules-logic-DJhGFqhC.cjs +1 -0
  40. package/dist/types/plugins/single-page-app/plugin.d.ts +15 -4
  41. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/experience-instance-DG9HFNSE.cjs +0 -1
  44. package/dist/experience-instance-DffMstSs.js +0 -486
  45. package/dist/object-C82v79xc.js +0 -25
  46. package/dist/object-CUJOjanb.cjs +0 -1
  47. package/dist/rules-logic-B--rEvGw.js +0 -240
  48. package/dist/rules-logic-D_dZ52-Q.cjs +0 -1
  49. /package/dist/{id-Bv44ilEo.cjs → id-Cg7fVl1O.cjs} +0 -0
  50. /package/dist/{id-CRqy981z.js → id-n2yrHvNo.js} +0 -0
  51. /package/dist/{logger-6z_gb4rA.js → logger-C44jSdYl.js} +0 -0
  52. /package/dist/{logger-fbvQC40v.cjs → logger-CJUj90QX.cjs} +0 -0
  53. /package/dist/{supports-0XIfd4-R.js → supports-B_trw6lj.js} +0 -0
  54. /package/dist/{supports-Dsjg-82e.cjs → supports-CKSVYpQx.cjs} +0 -0
@@ -4,13 +4,15 @@ layout: docs
4
4
 
5
5
  # Conditions
6
6
 
7
- Conditions evaluate of the current state of the Picked client to decide outcomes as defined by the user. Conditions are `JsonLogic`, which will always return the same result given the same input.
7
+ Conditions use JSON Logic to evaluate client state. Use them to gate experience activation, branch step navigation, and control field visibility.
8
8
 
9
- ## Conditions in Experiences
9
+ ## Conditions in experiences
10
10
 
11
- A common method of navigating a Funnel Experiences is using conditions between steps. The condition will evaludate values from the Picked state, and navigation the user based on a boolean value
11
+ A common pattern is using conditions between steps to branch the flow based on form responses:
12
12
 
13
13
  ```ts
14
+ import { createExperience } from '@picked/client/plugins/create-experience'
15
+
14
16
  const questionaireFunnel = createExperience({
15
17
  id: 'mini-funnel',
16
18
  // experience config
@@ -30,7 +32,7 @@ const isSigningUpForNewsletter = funnel.addConditional({
30
32
  condition: {
31
33
  '==': [
32
34
  {
33
- var: 'responses.sign-up-for-newsletter-field', // check if response value for the field is true
35
+ var: 'responses.sign-up-for-newsletter-field',
34
36
  },
35
37
  true,
36
38
  ],
@@ -43,11 +45,13 @@ isSigningUpForNewsletter.addTrue(signUserUpToNewsletter)
43
45
  isSigningUpForNewsletter.addFalse(userDoesNotWantNewsletter)
44
46
  ```
45
47
 
46
- ## Conditional Fields
48
+ ## Conditional fields
47
49
 
48
- Fields can be shown or hidden based on previous responses or predicates using JSON Logic conditions:
50
+ Fields can be shown or hidden based on previous responses or [predicates](./predicates) using JSON Logic conditions:
49
51
 
50
52
  ```ts
53
+ import { createField } from '@picked/client/plugins/create-experience'
54
+
51
55
  // Show email field only if user selected "email" as a contact method
52
56
  export const emailField = createField({
53
57
  id: 'email-input',
@@ -60,7 +64,7 @@ export const emailField = createField({
60
64
  in: [
61
65
  'email',
62
66
  {
63
- var: 'responses.communication-methods', // Reference previous field
67
+ var: 'responses.communication-methods',
64
68
  },
65
69
  ],
66
70
  },
@@ -87,11 +91,13 @@ export const mailingAddressField = createField({
87
91
  })
88
92
  ```
89
93
 
90
- ## Field Options with Conditions
94
+ ## Field options with conditions
91
95
 
92
96
  Individual options within a field can also have conditional visibility:
93
97
 
94
98
  ```ts
99
+ import { createField } from '@picked/client/plugins/create-experience'
100
+
95
101
  export const contactMethodsField = createField({
96
102
  id: 'contact-methods',
97
103
  name: 'contact-methods',
@@ -4,38 +4,41 @@ layout: docs
4
4
 
5
5
  # Experiences
6
6
 
7
- Experiences enable you to conditionally show UI components in your application based on custom logic. Each experience defines a component to render, where to inject it in the DOM, and an optional condition that controls when it appears. Experiences support multi-step flows with fields and branching logic, making them ideal for onboarding, surveys, and interactive product tours
7
+ Define experiences in code with `createExperience()`, or load them from the dashboard at runtime with the [Dynamic Experiences Plugin](./plugins/dynamic-experiences).
8
8
 
9
- ## Creating Experiences
9
+ ## Creating experiences
10
10
 
11
11
  ```ts
12
12
  import { createExperience } from '@picked/client/plugins/create-experience'
13
+ import { adaptSvelteComponent } from '@picked/svelte'
14
+ import appCss from '../app.css?inline'
13
15
 
14
16
  export const productPageExperience = createExperience({
15
17
  id: 'product-page-experience',
16
- name: 'Product Page Experience,
18
+ name: 'Product Page Experience',
17
19
  condition: {
18
20
  '==': [
19
- {
20
- var: 'location.pathname',
21
- },
22
- '/product/',
23
- ]
24
- }
21
+ { var: 'location.pathname' },
22
+ '/product/',
23
+ ],
24
+ },
25
25
  targets: [{ selector: 'body', placement: 'after' }],
26
- component: adaptSvelteComponent(import('../ui/ProductPageExperience.svelte', {
27
- css: [appCss],
28
- }),
26
+ component: adaptSvelteComponent(
27
+ import('../ui/ProductPageExperience.svelte'),
28
+ { css: [appCss] },
29
+ ),
29
30
  })
30
31
  ```
31
32
 
32
- ## How Experiences Work
33
+ Register experiences using the [Create Experience Plugin](./plugins/create-experience) for code-defined experiences, or the [Dynamic Experiences Plugin](./plugins/dynamic-experiences) to fetch and manage them from the dashboard at runtime.
34
+
35
+ ## How experiences work
33
36
 
34
37
  When an experience is registered, the SDK follows this execution flow:
35
38
 
36
- 1. **Registration**: Experiences are registered to the Picked client using [createExperiencePlugin](./plugins/create-experience.md) for code-defined experiences, or [dynamicExperiencesPlugin](./plugins/dynamic-experiences.md) for dashboard-managed experiences
37
- 2. **Condition Evaluation**: The SDK evaluates the experience's `condition` using the logic engine to determine if it should be shown
38
- 3. **Target Resolution**: The SDK searches the DOM for elements matching the `targets` selectors (e.g., `body`, `.product-page`, `#checkout`)
39
+ 1. **Registration**: Experiences are registered to the Picked client using [createExperiencePlugin](./plugins/create-experience) for code-defined experiences, or [dynamicExperiencesPlugin](./plugins/dynamic-experiences) for dashboard-managed experiences
40
+ 2. **Condition evaluation**: The SDK evaluates the experience's `condition` using the logic engine to determine if it should be shown
41
+ 3. **Target resolution**: The SDK searches the DOM for elements matching the `targets` selectors (e.g., `body`, `.product-page`, `#checkout`)
39
42
  4. **Initialization**: If the condition evaluates to `true` and at least one target element exists, the experience is initialized
40
- 5. **Component Rendering**: The experience's component is rendered and injected into the DOM at the specified target location and placement (before, after, append, prepend, or replace)
41
- 6. **Flow Execution**: If the experience contains steps, fields, and conditionals, users can progress through the multi-step flow with validation and branching logic
43
+ 5. **Component rendering**: The experience's component is rendered and injected into the DOM at the specified target location and placement (before, after, append, prepend, or replace)
44
+ 6. **Flow execution**: If the experience contains steps, fields, and conditionals, users can progress through the multi-step flow with validation and branching logic
@@ -4,9 +4,9 @@ layout: docs
4
4
 
5
5
  # Features
6
6
 
7
- Features enable A/B testing and feature flagging in your application. Each feature defines decision logic that resolves to a `bucket` as either a boolean value (`true`/`false`) or a string value (like `"control"`, `"variant-a"`, or `"variant-b"`). Once a feature is decided, the result is cached in browser storage to ensure consistent user experiences across sessions.
7
+ Define feature flags with a `decide` function that resolves to a bucket value, access results through framework hooks, and invalidate cached decisions by bumping the version.
8
8
 
9
- ## Defining Features
9
+ ## Defining features
10
10
 
11
11
  Define features when creating the Picked client by passing a `features` object. Each feature requires a unique identifier, a versioning key, a human-readable name, and a `decide` function:
12
12
 
@@ -51,7 +51,7 @@ features: {
51
51
  }
52
52
  ```
53
53
 
54
- ## How Features Work
54
+ ## How features work
55
55
 
56
56
  When a feature is registered, the SDK follows this execution order:
57
57
 
@@ -61,7 +61,7 @@ When a feature is registered, the SDK follows this execution order:
61
61
  4. **Storage**: Once resolved, the bucket value is persisted to browser storage for consistency across page loads
62
62
  5. **Event Emission**: A `feature_decide` event is fired on the event bus when a feature is resolved for the first time
63
63
 
64
- ## URL-Based Overrides
64
+ ## URL-based overrides
65
65
 
66
66
  You can override feature decisions via URL search parameters for testing purposes:
67
67
 
@@ -79,7 +79,7 @@ The format is `?picked-feature=<feature-id>:<bucket-value>`.
79
79
 
80
80
  This is useful for QA testing specific feature variants without modifying code. The override is persisted in session storage and will be cleared when the browser tab is closed.
81
81
 
82
- ## Accessing Features
82
+ ## Accessing features
83
83
 
84
84
  Once features are defined, you can access their resolved bucket values in your application code. The SDK provides framework-specific hooks and a framework-agnostic event bus for subscribing to feature decisions.
85
85
 
@@ -132,7 +132,7 @@ function MyComponent() {
132
132
 
133
133
  :::
134
134
 
135
- ## Using Features in Experience Conditions
135
+ ## Using features in experience conditions
136
136
 
137
137
  Features can be used with experience conditions via JSON logic:
138
138
 
@@ -156,7 +156,7 @@ const myExperience = createExperience({
156
156
  })
157
157
  ```
158
158
 
159
- ## Listening to Feature Decisions
159
+ ## Listening to feature decisions
160
160
 
161
161
  Subscribe to the `feature_decide` event to track when features are resolved:
162
162
 
@@ -206,7 +206,7 @@ features: {
206
206
 
207
207
  For features managed through the dashboard, versioning is handled automatically — the dashboard appends the version number to the cache key used by the SDK.
208
208
 
209
- ## Best Practices
209
+ ## Best practices
210
210
 
211
211
  - **Use `session` storage for temporary tests**: Set `storage: 'session'` for short-lived experiments that shouldn't persist across browser sessions
212
212
  - **Keep `decide` functions fast**: The function blocks experience rendering, so avoid heavy computations or slow network calls
@@ -4,9 +4,9 @@ layout: docs
4
4
 
5
5
  # Fields
6
6
 
7
- Fields are used to store data for a Picked instance. Fields can be added to steps or forms and rendered as inputs, or have their values directly set.
7
+ Define fields in code with `createField()`, validate input with JSON Logic, and read submitted values through step context.
8
8
 
9
- ## Defining Fields
9
+ ## Defining fields
10
10
 
11
11
  Define fields using `createField()` from the `@picked/client/plugins/create-experience` package. Each field requires a unique identifier, name, type, label, and cardinality:
12
12
 
@@ -52,7 +52,7 @@ export const communicationMethods = createField({
52
52
  })
53
53
  ```
54
54
 
55
- ## How Fields Work
55
+ ## How fields work
56
56
 
57
57
  When a field is registered and used in an experience:
58
58
 
@@ -63,7 +63,7 @@ When a field is registered and used in an experience:
63
63
  5. **Storage**: Valid responses are stored in the experience state under `responses[field.name]`
64
64
  6. **Reference**: Field values can be referenced in subsequent field conditions, step conditions, or experience logic via `{ var: 'responses.field-name' }`
65
65
 
66
- ## Field Types
66
+ ## Field types
67
67
 
68
68
  Fields support four primitive types, `text`, `number`, `boolean` and `object`:
69
69
 
@@ -129,7 +129,7 @@ const conditionalField = createField({
129
129
  })
130
130
  ```
131
131
 
132
- ## Field Validation
132
+ ## Field validation
133
133
 
134
134
  Validate user input using JSON Logic rules. The `$input` variable contains the current field value:
135
135
 
@@ -179,7 +179,7 @@ const quantityField = createField({
179
179
  The `catch`/`throw` pattern in JSON Logic validates that the condition evaluates to `true`. If it doesn't, the `throw` message is displayed to the user.
180
180
  :::
181
181
 
182
- ## Field Policies
182
+ ## Field policies
183
183
 
184
184
  Control how field data is tracked and stored using privacy policies:
185
185
 
@@ -205,7 +205,7 @@ const sensitiveField = createField({
205
205
 
206
206
  Use these policies for sensitive data like SSNs, credit cards, or passwords that should only exist client-side.
207
207
 
208
- ## Field Metadata
208
+ ## Field metadata
209
209
 
210
210
  Enhance user experience with additional descriptive text:
211
211
 
@@ -229,7 +229,7 @@ const passwordField = createField({
229
229
  - `description`: Brief explanation shown below the label
230
230
  - `helpText`: Additional guidance or requirements displayed near the field
231
231
 
232
- ## Accessing Field Values
232
+ ## Accessing field values
233
233
 
234
234
  Field responses are stored in the experience state and can be accessed via the `responses` object:
235
235
 
@@ -251,7 +251,7 @@ const sensitiveField = createField({
251
251
 
252
252
  :::
253
253
 
254
- ## Best Practices
254
+ ## Best practices
255
255
 
256
256
  - **Use semantic IDs and names**: Name fields descriptively (e.g., `email-address` not `field1`) for easier debugging and analytics
257
257
  - **Match type to data**: Use `number` for numeric values, not `text`, to enable proper validation and comparison
@@ -4,9 +4,9 @@ layout: docs
4
4
 
5
5
  # Steps
6
6
 
7
- Steps are the building blocks of an experience. Each step represents a single screen or stage in a multi-step journey.
7
+ Render steps with `<StepRouter>` and `<Step>` from `@picked/react` or `@picked/svelte`, and access the active step through `useStep()` / `getStep()`.
8
8
 
9
- ## How Steps Work
9
+ ## How steps work
10
10
 
11
11
  When an experience starts, its steps are connected in a directed node graph. The SDK traverses this graph to determine which step to display:
12
12
 
@@ -18,7 +18,7 @@ When an experience starts, its steps are connected in a directed node graph. The
18
18
  6. **Navigation**: The SDK follows the edge from the current step node to the next, traversing any conditionals or actions before arriving at the next step
19
19
  7. **Completion**: When no further steps exist, the experience flow is complete
20
20
 
21
- ## Step Routing
21
+ ## Step routing
22
22
 
23
23
  `StepRouter` listens to the experience's current step state and activates the matching `Step` by its `id`. Each `Step` registers itself on mount and unregisters on unmount, so lazy-rendered tabs or drawers work automatically.
24
24
 
@@ -72,7 +72,7 @@ function MyExperience() {
72
72
  All Steps must be wrapped in a router, even if it is a single Step
73
73
  :::
74
74
 
75
- ### Lazy-Loaded Steps
75
+ ### Lazy-loaded steps
76
76
 
77
77
  For large experiences, steps can be lazily loaded using dynamic imports:
78
78
 
@@ -100,7 +100,7 @@ const WelcomeScreen = lazy(() => import('./WelcomeScreen'))
100
100
 
101
101
  The `component` prop accepts a `Promise<Component>` — the step's content is not loaded until it becomes active.
102
102
 
103
- ## Accessing Step Context
103
+ ## Accessing step context
104
104
 
105
105
  Inside a `Step` component (or any component rendered within one), call `getStep()` / `useStep()` to access the step's reactive context:
106
106
 
@@ -123,7 +123,7 @@ Inside a `Step` component (or any component rendered within one), call `getStep(
123
123
  onchange={field.onChange}
124
124
  onblur={field.onBlur}
125
125
  />
126
- {#if field.error && field.touched
126
+ {#if field.error && field.touched}
127
127
  <p class="error">{field.error.userMessage}</p>
128
128
  {/if}
129
129
  {/each}
@@ -168,13 +168,13 @@ function ContactForm() {
168
168
  | `step` | `Store<ExperienceStep>` | Reactive store containing the step's `id` and `label` |
169
169
  | `fields` | `Store<FormField[]>` | Reactive store of fields with their current values, errors, and event handlers |
170
170
  | `isActive` | `Store<boolean>` (Svelte) / `boolean` (React) | Whether this step is currently active in the router |
171
- | `form` | Object | Form submission handlers (see Forms section) |
171
+ | `form` | Object | Form submission handlers (see [Forms](#forms)) |
172
172
 
173
173
  ## Forms
174
174
 
175
175
  When a step has fields, `getStep()` / `useStep()` provides a `form` object for handling submission, validation, and navigation.
176
176
 
177
- ### Handling Submission
177
+ ### Handling submission
178
178
 
179
179
  Bind `form.props` to your `<form>` element's `onsubmit` handler:
180
180
 
@@ -249,7 +249,7 @@ Submitting the form:
249
249
  5. Fires `form_submit_success` or `form_submit_error` on the event bus
250
250
  6. Navigates to the next step (unless `stopNavigation` is called)
251
251
 
252
- ### Transforming Data Before Submission
252
+ ### Transforming data before submission
253
253
 
254
254
  Use `form.onBeforeSubmit` to intercept and transform field data before it is committed. Callbacks run in series, each receiving the output of the previous:
255
255
 
@@ -293,7 +293,7 @@ function ContactStep() {
293
293
 
294
294
  :::
295
295
 
296
- ### Success and Error Callbacks
296
+ ### Success and error callbacks
297
297
 
298
298
  Register callbacks for submission outcomes using `form.onSuccess` and `form.onError`:
299
299
 
@@ -347,7 +347,7 @@ function ContactStep() {
347
347
 
348
348
  Callbacks registered via `onSuccess` and `onError` are automatically cleaned up when the component unmounts — no manual teardown is needed.
349
349
 
350
- ### Preventing Navigation on Success
350
+ ### Preventing navigation on success
351
351
 
352
352
  By default, the experience advances to the next step after a successful submission. Call `stopNavigation()` inside `onSuccess` to prevent this, for example when you need to handle navigation manually:
353
353
 
@@ -401,7 +401,7 @@ function PlanStep() {
401
401
 
402
402
  :::
403
403
 
404
- ## Best Practices
404
+ ## Best practices
405
405
 
406
406
  - **Give steps meaningful labels**: The `label` is used in analytics events and the dashboard — prefer descriptive names like `"Contact Details"` over `"Step 2"`
407
407
  - **Keep steps focused**: Each step should collect a small, related set of information. Prefer more steps over longer forms to reduce abandonment
@@ -1,4 +1,4 @@
1
- import { t as e } from "../../rules-logic-B--rEvGw.js";
1
+ import { t as e } from "../../rules-logic-D7dL30U1.js";
2
2
  import { attach as t, combine as n, createEffect as r, createEvent as i, createStore as a, sample as o, split as s } from "effector";
3
3
  //#region src/form/build-responses.ts
4
4
  function c(e, t, n) {