@picked/client 0.0.1-dev.1785305085063 → 0.0.1-dev.1785908062293
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/.tsbuildinfo +1 -0
- package/dist/api-03c5jvVk.js +38 -0
- package/dist/api-CQxCVIrm.cjs +1 -0
- package/dist/cjs/form/index.js +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/plugins/dom-observer/index.js +1 -1
- package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
- package/dist/cjs/server/index.js +1 -1
- package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
- package/dist/docs/explanation/feature-flag-allocation.md +176 -0
- package/dist/docs/explanation/how-picked-works.md +124 -0
- package/dist/docs/explanation/how-pickedql-works.md +76 -0
- package/dist/docs/explanation/pages-and-flows.md +64 -0
- package/dist/docs/explanation/the-content-model.md +77 -0
- package/dist/docs/explanation/the-two-apis.md +68 -0
- package/dist/docs/explanation/why-server-side-rendering.md +76 -0
- package/dist/docs/explanation/workspaces-and-versions.md +71 -0
- package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
- package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
- package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
- package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
- package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
- package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
- package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
- package/dist/docs/how-to/build-a-flow.md +83 -0
- package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
- package/dist/docs/how-to/create-a-project.md +29 -0
- package/dist/docs/how-to/create-an-experience.md +42 -0
- package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
- package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
- package/dist/docs/how-to/define-a-page-layout.md +39 -0
- package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
- package/dist/docs/how-to/install-the-gtm-template.md +84 -0
- package/dist/docs/how-to/install-the-sdk.md +68 -0
- package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
- package/dist/docs/how-to/invite-and-remove-members.md +34 -0
- package/dist/docs/how-to/preview-a-workspace.md +28 -0
- package/dist/docs/how-to/publish-a-workspace.md +30 -0
- package/dist/docs/how-to/read-a-feature-flag.md +101 -0
- package/dist/docs/how-to/register-a-component.md +55 -0
- package/dist/docs/how-to/register-an-action-handler.md +67 -0
- package/dist/docs/how-to/render-a-step-form.md +132 -0
- package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
- package/dist/docs/how-to/reuse-a-section.md +37 -0
- package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
- package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
- package/dist/docs/how-to/run-an-ab-test.md +49 -0
- package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
- package/dist/docs/how-to/server-render-a-page.md +81 -0
- package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
- package/dist/docs/how-to/set-up-mfa.md +69 -0
- package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
- package/dist/docs/how-to/validate-a-field.md +52 -0
- package/dist/docs/how-to/write-a-condition.md +45 -0
- package/dist/docs/how-to/write-a-predicate.md +60 -0
- package/dist/docs/index.md +41 -59
- package/dist/docs/reference/dashboard/actions.mdx +53 -0
- package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
- package/dist/docs/reference/dashboard/conditions.mdx +42 -0
- package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
- package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
- package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
- package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
- package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
- package/dist/docs/reference/dashboard/experiences.mdx +51 -0
- package/dist/docs/reference/dashboard/features.mdx +114 -0
- package/dist/docs/reference/dashboard/fields.mdx +100 -0
- package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
- package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
- package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
- package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
- package/dist/docs/reference/dashboard/projects.mdx +44 -0
- package/dist/docs/reference/dashboard/reports.mdx +43 -0
- package/dist/docs/reference/dashboard/steps.mdx +37 -0
- package/dist/docs/reference/dashboard/team-management.md +29 -0
- package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
- package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
- package/dist/docs/reference/delivery-api/index.md +45 -0
- package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
- package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
- package/dist/docs/reference/glossary.md +173 -0
- package/dist/docs/reference/management-api/authentication.md +74 -0
- package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
- package/dist/docs/reference/management-api/error-handling.md +233 -0
- package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
- package/dist/docs/reference/pickedql/data-sources.md +174 -0
- package/dist/docs/reference/pickedql/dimensions.md +87 -0
- package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
- package/dist/docs/reference/pickedql/index.md +18 -0
- package/dist/docs/reference/pickedql/schema.md +172 -0
- package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
- package/dist/docs/reference/sdk/actions.md +30 -0
- package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
- package/dist/docs/reference/sdk/content-security-policy.md +21 -0
- package/dist/docs/reference/sdk/experiences.md +51 -0
- package/dist/docs/reference/sdk/features.md +233 -0
- package/dist/docs/reference/sdk/fields.md +209 -0
- package/dist/docs/reference/sdk/index.md +68 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
- package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
- package/dist/docs/reference/sdk/plugins/index.md +29 -0
- package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
- package/dist/docs/reference/sdk/predicates.md +43 -0
- package/dist/docs/reference/sdk/ssr/index.md +33 -0
- package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
- package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
- package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
- package/dist/docs/reference/sdk/steps.md +87 -0
- package/dist/docs/reference/tools/chrome-extension.md +16 -0
- package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
- package/dist/docs/reference/tools/mcp.md +88 -0
- package/dist/docs/reference/tools/vite-plugin.md +88 -0
- package/dist/docs/tutorials/first-api-call.md +228 -0
- package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
- package/dist/docs/tutorials/first-experience.mdx +255 -0
- package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
- package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
- package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
- package/dist/esm/form/index.js +2 -4
- package/dist/esm/index.js +225 -186
- package/dist/esm/plugins/dom-observer/index.js +1 -1
- package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
- package/dist/esm/preview/index.js +1 -1
- package/dist/esm/server/index.js +33 -31
- package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
- package/dist/experience-instance-Dej3P1sE.cjs +1 -0
- package/dist/plugin-CHOVsx7Z.js +287 -0
- package/dist/plugin-DsaGXQHx.cjs +1 -0
- package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
- package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
- package/dist/types/client.d.ts +7 -6
- package/dist/types/data-source/api.d.ts +60 -0
- package/dist/types/data-source/api.d.ts.map +1 -0
- package/dist/types/data-source/provider.d.ts +97 -0
- package/dist/types/data-source/provider.d.ts.map +1 -0
- package/dist/types/entities/action/action.d.ts +5 -4
- package/dist/types/entities/action/action.d.ts.map +1 -1
- package/dist/types/entities/component/component.d.ts +6 -5
- package/dist/types/entities/component/component.d.ts.map +1 -1
- package/dist/types/entities/condition/condition.d.ts +5 -5
- package/dist/types/entities/content/content.d.ts +4 -3
- package/dist/types/entities/experience/experience.d.ts +11 -10
- package/dist/types/entities/experience/experience.d.ts.map +1 -1
- package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
- package/dist/types/entities/feature/feature.d.ts +19 -2
- package/dist/types/entities/feature/feature.d.ts.map +1 -1
- package/dist/types/entities/field/field.d.ts +7 -6
- package/dist/types/entities/framework/framework.d.ts +7 -6
- package/dist/types/entities/framework/framework.d.ts.map +1 -1
- package/dist/types/entities/history/history.d.ts +6 -6
- package/dist/types/entities/plugin/plugin.d.ts +3 -2
- package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
- package/dist/types/entities/predicate/predicate.d.ts +4 -3
- package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
- package/dist/types/entities/response/response-validation.d.ts +3 -2
- package/dist/types/entities/response/response.d.ts +12 -11
- package/dist/types/entities/session/session.d.ts +2 -1
- package/dist/types/entities/step/step.d.ts +6 -5
- package/dist/types/exports.d.ts +2 -1
- package/dist/types/exports.d.ts.map +1 -1
- package/dist/types/form/build-responses.d.ts +2 -1
- package/dist/types/form/create-field-evaluator.d.ts +4 -3
- package/dist/types/form/create-field-validation.d.ts +5 -4
- package/dist/types/form/create-form.d.ts +7 -6
- package/dist/types/form/create-submit-pipeline.d.ts +7 -6
- package/dist/types/form/get-step-fields.d.ts +3 -2
- package/dist/types/lifecycle/condition-selection.d.ts +14 -4
- package/dist/types/lifecycle/lifecycle.d.ts +4 -3
- package/dist/types/lifecycle/rules-logic.d.ts +4 -3
- package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
- package/dist/types/picked.d.ts +79 -62
- package/dist/types/picked.d.ts.map +1 -1
- package/dist/types/ping.d.ts +1 -1
- package/dist/types/ping.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
- package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
- package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
- package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
- package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
- package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
- package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
- package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
- package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
- package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
- package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
- package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
- package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
- package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
- package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
- package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
- package/dist/types/plugins/web-components/plugin.d.ts +2 -1
- package/dist/types/plugins/window-object/plugin.d.ts +2 -2
- package/dist/types/preview-channel.d.ts +5 -1
- package/dist/types/preview-receiver/index.d.ts +18 -1
- package/dist/types/preview-receiver/protocol.d.ts +10 -1
- package/dist/types/server/index.d.ts +3 -3
- package/dist/types/server/serialize.d.ts +8 -2
- package/dist/types/server/serialize.d.ts.map +1 -1
- package/dist/types/utils/dom.d.ts +2 -1
- package/dist/types/utils/events.d.ts +6 -6
- package/dist/types/utils/events.d.ts.map +1 -1
- package/dist/types/utils/global-obj.d.ts +1 -1
- package/dist/types/utils/global-obj.d.ts.map +1 -1
- package/dist/types/utils/id.d.ts.map +1 -1
- package/dist/types/utils/logger.d.ts +2 -1
- package/dist/types/utils/logger.d.ts.map +1 -1
- package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
- package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
- package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
- package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
- package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
- package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
- package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
- package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
- package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
- package/dist/types/utils/nodes.d.ts +1 -1
- package/dist/types/utils/picked-config.d.ts +2 -1
- package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
- package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
- package/dist/types/utils/rules-logic.d.ts +6 -2
- package/dist/types/utils/storage.d.ts +1 -1
- package/dist/types/utils/storage.d.ts.map +1 -1
- package/package.json +22 -23
- package/dist/api-CPL40b7A.js +0 -40
- package/dist/api-Dz5rgRgQ.cjs +0 -1
- package/dist/docs/actions.mdx +0 -78
- package/dist/docs/api/authentication.md +0 -376
- package/dist/docs/api/error-handling.md +0 -211
- package/dist/docs/api/index.md +0 -197
- package/dist/docs/api-keys.mdx +0 -40
- package/dist/docs/chrome-extension.md +0 -51
- package/dist/docs/conditions.mdx +0 -59
- package/dist/docs/content/asset-library.mdx +0 -93
- package/dist/docs/content/content-entries.mdx +0 -30
- package/dist/docs/content/layouts.mdx +0 -70
- package/dist/docs/content/pages.mdx +0 -67
- package/dist/docs/content/sections.mdx +0 -33
- package/dist/docs/delivery-api/index.md +0 -46
- package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
- package/dist/docs/experiences.mdx +0 -42
- package/dist/docs/features.mdx +0 -58
- package/dist/docs/fields.mdx +0 -79
- package/dist/docs/flow-builder/building-flows.md +0 -61
- package/dist/docs/flow-builder/condition-builder.md +0 -54
- package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
- package/dist/docs/flow-builder/nodes.md +0 -43
- package/dist/docs/flow-builder/overview.mdx +0 -50
- package/dist/docs/gtm-template.md +0 -69
- package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
- package/dist/docs/image-optimisation-service.md +0 -80
- package/dist/docs/mcp.md +0 -120
- package/dist/docs/pickedql/data-sources.md +0 -145
- package/dist/docs/pickedql/dimensions.md +0 -65
- package/dist/docs/pickedql/index.md +0 -36
- package/dist/docs/pickedql/schema.md +0 -156
- package/dist/docs/pickedql/virtual-functions.md +0 -204
- package/dist/docs/projects.mdx +0 -37
- package/dist/docs/reports.mdx +0 -18
- package/dist/docs/sdk/actions.md +0 -66
- package/dist/docs/sdk/content-security-policy.md +0 -32
- package/dist/docs/sdk/experiences.md +0 -46
- package/dist/docs/sdk/features.md +0 -212
- package/dist/docs/sdk/fields.md +0 -263
- package/dist/docs/sdk/index.md +0 -83
- package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
- package/dist/docs/sdk/plugins/index.md +0 -9
- package/dist/docs/sdk/predicates.md +0 -112
- package/dist/docs/sdk/ssr/index.md +0 -62
- package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
- package/dist/docs/sdk/ssr/serialize.md +0 -86
- package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
- package/dist/docs/sdk/steps.md +0 -434
- package/dist/docs/steps.mdx +0 -44
- package/dist/docs/team-management.md +0 -40
- package/dist/docs/vite-plugin.md +0 -82
- package/dist/docs/workspace-versioning.mdx +0 -28
- package/dist/docs/workspaces.mdx +0 -102
- package/dist/experience-instance-DurC3pE-.cjs +0 -1
- package/dist/plugin-CFXwbXeM.js +0 -247
- package/dist/plugin-m4qekgtA.cjs +0 -1
package/dist/docs/sdk/steps.md
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Steps
|
|
6
|
-
|
|
7
|
-
Render steps with `<StepRouter>` and `<Step>` from `@picked/react` or `@picked/svelte`, and access the active step through `useStep()` / `getStep()`.
|
|
8
|
-
|
|
9
|
-
## How steps work
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
1. **Initialization**: When the experience opens, the SDK starts at the origin node and traverses the graph to find the first step
|
|
14
|
-
2. **Step Entry**: The active step is set and a `step_enter` event is emitted on the event bus
|
|
15
|
-
3. **Field Evaluation**: The step's fields are evaluated — fields with conditions are shown or hidden based on the current state
|
|
16
|
-
4. **User Input**: The user interacts with the step's fields. Client-side validation runs on blur and on submit
|
|
17
|
-
5. **Step Submission**: When the user submits, a `step_submit` event fires and field responses are committed to the client state
|
|
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
|
-
7. **Completion**: When no further steps exist, the experience flow is complete
|
|
20
|
-
|
|
21
|
-
## Step routing
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
:::code-group
|
|
26
|
-
|
|
27
|
-
```svelte [Svelte]
|
|
28
|
-
<script lang="ts">
|
|
29
|
-
import { StepRouter, Step } from '@picked/svelte/router'
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<StepRouter>
|
|
33
|
-
<Step id="welcome">
|
|
34
|
-
<WelcomeScreen />
|
|
35
|
-
</Step>
|
|
36
|
-
|
|
37
|
-
<Step id="contact">
|
|
38
|
-
<ContactForm />
|
|
39
|
-
</Step>
|
|
40
|
-
|
|
41
|
-
<Step id="confirmation">
|
|
42
|
-
<ConfirmationScreen />
|
|
43
|
-
</Step>
|
|
44
|
-
</StepRouter>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```tsx [React]
|
|
48
|
-
import { StepRouter, Step } from '@picked/react/router'
|
|
49
|
-
|
|
50
|
-
function MyExperience() {
|
|
51
|
-
return (
|
|
52
|
-
<StepRouter>
|
|
53
|
-
<Step id="welcome">
|
|
54
|
-
<WelcomeScreen />
|
|
55
|
-
</Step>
|
|
56
|
-
|
|
57
|
-
<Step id="contact">
|
|
58
|
-
<ContactForm />
|
|
59
|
-
</Step>
|
|
60
|
-
|
|
61
|
-
<Step id="confirmation">
|
|
62
|
-
<ConfirmationScreen />
|
|
63
|
-
</Step>
|
|
64
|
-
</StepRouter>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
:::
|
|
70
|
-
|
|
71
|
-
:::note
|
|
72
|
-
All Steps must be wrapped in a router, even if it is a single Step
|
|
73
|
-
:::
|
|
74
|
-
|
|
75
|
-
### Lazy-loaded steps
|
|
76
|
-
|
|
77
|
-
For large experiences, steps can be lazily loaded using dynamic imports:
|
|
78
|
-
|
|
79
|
-
:::code-group
|
|
80
|
-
|
|
81
|
-
```svelte [Svelte]
|
|
82
|
-
<StepRouter>
|
|
83
|
-
<Step id="welcome" component={import('./WelcomeScreen.svelte')} />
|
|
84
|
-
</StepRouter>
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
```tsx [React]
|
|
88
|
-
import { lazy } from 'react'
|
|
89
|
-
|
|
90
|
-
const WelcomeScreen = lazy(() => import('./WelcomeScreen'))
|
|
91
|
-
|
|
92
|
-
<StepRouter>
|
|
93
|
-
<Step id="welcome">
|
|
94
|
-
<WelcomeScreen />
|
|
95
|
-
</Step>
|
|
96
|
-
</StepRouter>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
:::
|
|
100
|
-
|
|
101
|
-
The `component` prop accepts a `Promise<Component>` — the step's content is not loaded until it becomes active.
|
|
102
|
-
|
|
103
|
-
## Accessing step context
|
|
104
|
-
|
|
105
|
-
Inside a `Step` component (or any component rendered within one), call `getStep()` / `useStep()` to access the step's reactive context:
|
|
106
|
-
|
|
107
|
-
:::code-group
|
|
108
|
-
|
|
109
|
-
```svelte [Svelte]
|
|
110
|
-
<script lang="ts">
|
|
111
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
112
|
-
|
|
113
|
-
const { step, fields } = getStep()
|
|
114
|
-
</script>
|
|
115
|
-
|
|
116
|
-
<h1>{$step.label}</h1>
|
|
117
|
-
|
|
118
|
-
{#each $fields as field}
|
|
119
|
-
<label>{field.label}</label>
|
|
120
|
-
<input
|
|
121
|
-
name={field.id}
|
|
122
|
-
value={field.value ?? ''}
|
|
123
|
-
onchange={field.onChange}
|
|
124
|
-
onblur={field.onBlur}
|
|
125
|
-
/>
|
|
126
|
-
{#if field.error && field.touched}
|
|
127
|
-
<p class="error">{field.error.userMessage}</p>
|
|
128
|
-
{/if}
|
|
129
|
-
{/each}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
```tsx [React]
|
|
133
|
-
import { useStep } from '@picked/react/hooks'
|
|
134
|
-
import { useUnit } from 'effector-react'
|
|
135
|
-
|
|
136
|
-
function ContactForm() {
|
|
137
|
-
const { step, fields } = useStep()
|
|
138
|
-
const currentStep = useUnit(step)
|
|
139
|
-
const currentFields = useUnit(fields)
|
|
140
|
-
|
|
141
|
-
return (
|
|
142
|
-
<>
|
|
143
|
-
<h1>{currentStep.label}</h1>
|
|
144
|
-
|
|
145
|
-
{currentFields.map((field) => (
|
|
146
|
-
<div key={field.id}>
|
|
147
|
-
<label>{field.label}</label>
|
|
148
|
-
<input
|
|
149
|
-
name={field.id}
|
|
150
|
-
value={field.value ?? ''}
|
|
151
|
-
onChange={field.onChange}
|
|
152
|
-
onBlur={field.onBlur}
|
|
153
|
-
/>
|
|
154
|
-
{field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
|
|
155
|
-
</div>
|
|
156
|
-
))}
|
|
157
|
-
</>
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
:::
|
|
163
|
-
|
|
164
|
-
`getStep()` (Svelte) / `useStep()` (React) returns a `StepContext` with the following properties:
|
|
165
|
-
|
|
166
|
-
| Property | Type | Description |
|
|
167
|
-
| ---------- | --------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
168
|
-
| `step` | `Store<ExperienceStep>` | Reactive store containing the step's `id` and `label` |
|
|
169
|
-
| `fields` | `Store<FormField[]>` | Reactive store of fields with their current values, errors, and event handlers |
|
|
170
|
-
| `isActive` | `Store<boolean>` (Svelte) / `boolean` (React) | Whether this step is currently active in the router |
|
|
171
|
-
| `form` | Object | Form submission handlers (see [Forms](#forms)) |
|
|
172
|
-
|
|
173
|
-
## Forms
|
|
174
|
-
|
|
175
|
-
When a step has fields, `getStep()` / `useStep()` provides a `form` object for handling submission, validation, and navigation.
|
|
176
|
-
|
|
177
|
-
Both accept an optional callbacks object — `getStep({ onSuccess })` / `useStep({ onSuccess })` — which is the recommended way to react to submission. The available slots are `onBeforeSubmit`, `onSuccess` and `onError`, all covered below.
|
|
178
|
-
|
|
179
|
-
### Handling submission
|
|
180
|
-
|
|
181
|
-
Bind `form.props` to your `<form>` element's `onsubmit` handler:
|
|
182
|
-
|
|
183
|
-
:::code-group
|
|
184
|
-
|
|
185
|
-
```svelte [Svelte]
|
|
186
|
-
<script lang="ts">
|
|
187
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
188
|
-
|
|
189
|
-
const { fields, form } = getStep()
|
|
190
|
-
const isSubmitting = form.submitting
|
|
191
|
-
</script>
|
|
192
|
-
|
|
193
|
-
<form {...form.props}>
|
|
194
|
-
{#each $fields as field}
|
|
195
|
-
<input
|
|
196
|
-
name={field.id}
|
|
197
|
-
value={field.value ?? ''}
|
|
198
|
-
onchange={field.onChange}
|
|
199
|
-
onblur={field.onBlur}
|
|
200
|
-
/>
|
|
201
|
-
{#if field.error && field.touched}
|
|
202
|
-
<p class="error">{field.error.userMessage}</p>
|
|
203
|
-
{/if}
|
|
204
|
-
{/each}
|
|
205
|
-
|
|
206
|
-
<button type="submit" disabled={$isSubmitting}>
|
|
207
|
-
{$isSubmitting ? 'Submitting…' : 'Continue'}
|
|
208
|
-
</button>
|
|
209
|
-
</form>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
```tsx [React]
|
|
213
|
-
import { useStep } from '@picked/react/hooks'
|
|
214
|
-
import { useUnit } from 'effector-react'
|
|
215
|
-
|
|
216
|
-
function StepForm() {
|
|
217
|
-
const { fields, form } = useStep()
|
|
218
|
-
const currentFields = useUnit(fields)
|
|
219
|
-
const isSubmitting = useUnit(form.submitting)
|
|
220
|
-
|
|
221
|
-
return (
|
|
222
|
-
<form {...form.props}>
|
|
223
|
-
{currentFields.map((field) => (
|
|
224
|
-
<div key={field.id}>
|
|
225
|
-
<input
|
|
226
|
-
name={field.id}
|
|
227
|
-
value={field.value ?? ''}
|
|
228
|
-
onChange={field.onChange}
|
|
229
|
-
onBlur={field.onBlur}
|
|
230
|
-
/>
|
|
231
|
-
{field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
|
|
232
|
-
</div>
|
|
233
|
-
))}
|
|
234
|
-
|
|
235
|
-
<button type="submit" disabled={isSubmitting}>
|
|
236
|
-
{isSubmitting ? 'Submitting…' : 'Continue'}
|
|
237
|
-
</button>
|
|
238
|
-
</form>
|
|
239
|
-
)
|
|
240
|
-
}
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
:::
|
|
244
|
-
|
|
245
|
-
Submitting the form:
|
|
246
|
-
|
|
247
|
-
1. Collects field values from the HTML form
|
|
248
|
-
2. Runs `onBeforeSubmit` transform callbacks in series — a throw here aborts the submit before anything is committed
|
|
249
|
-
3. Validates all required fields and field validation rules
|
|
250
|
-
4. Commits the responses to the experience state
|
|
251
|
-
5. Fires `form_submit_success` or `form_submit_error` on the event bus
|
|
252
|
-
6. Runs your `onSuccess` or `onError` callbacks
|
|
253
|
-
7. Navigates to the next step (unless `stopNavigation` is called, and regardless of whether a callback in step 6 failed)
|
|
254
|
-
|
|
255
|
-
### Transforming data before submission
|
|
256
|
-
|
|
257
|
-
Use `onBeforeSubmit` to intercept and transform field data before it is committed. Callbacks run in series, each receiving the output of the previous:
|
|
258
|
-
|
|
259
|
-
:::code-group
|
|
260
|
-
|
|
261
|
-
```svelte [Svelte]
|
|
262
|
-
<script lang="ts">
|
|
263
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
264
|
-
|
|
265
|
-
const { form } = getStep({
|
|
266
|
-
onBeforeSubmit: async (data) => {
|
|
267
|
-
// Normalize email to lowercase before committing
|
|
268
|
-
return {
|
|
269
|
-
...data,
|
|
270
|
-
'email-address': String(data['email-address']).toLowerCase(),
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
})
|
|
274
|
-
</script>
|
|
275
|
-
|
|
276
|
-
<form {...form.props}>{/* ... */}</form>
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
```tsx [React]
|
|
280
|
-
import { useStep } from '@picked/react/hooks'
|
|
281
|
-
|
|
282
|
-
function ContactStep() {
|
|
283
|
-
const { form } = useStep({
|
|
284
|
-
onBeforeSubmit: async (data) => {
|
|
285
|
-
// Normalize email to lowercase before committing
|
|
286
|
-
return {
|
|
287
|
-
...data,
|
|
288
|
-
'email-address': String(data['email-address']).toLowerCase(),
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
return <form {...form.props}>{/* ... */}</form>
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
:::
|
|
298
|
-
|
|
299
|
-
:::warning
|
|
300
|
-
If an `onBeforeSubmit` callback throws, the submit is aborted before anything is committed and the step does not advance. This is deliberate — committing a half-transformed payload would persist wrong-but-plausible data. Use it for transforms and validation, and put side effects such as analytics or backend calls in `onSuccess` instead.
|
|
301
|
-
:::
|
|
302
|
-
|
|
303
|
-
### Success and error callbacks
|
|
304
|
-
|
|
305
|
-
Pass `onSuccess` and `onError` to react to submission outcomes:
|
|
306
|
-
|
|
307
|
-
:::code-group
|
|
308
|
-
|
|
309
|
-
```svelte [Svelte]
|
|
310
|
-
<script lang="ts">
|
|
311
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
312
|
-
|
|
313
|
-
const { form } = getStep({
|
|
314
|
-
onSuccess: ({ data }) => {
|
|
315
|
-
analytics.track('lead_captured', data)
|
|
316
|
-
},
|
|
317
|
-
onError: (errors) => {
|
|
318
|
-
console.error('Validation errors:', errors)
|
|
319
|
-
},
|
|
320
|
-
})
|
|
321
|
-
</script>
|
|
322
|
-
|
|
323
|
-
<form {...form.props}>{/* ... */}</form>
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
```tsx [React]
|
|
327
|
-
import { useStep } from '@picked/react/hooks'
|
|
328
|
-
|
|
329
|
-
function ContactStep() {
|
|
330
|
-
const { form } = useStep({
|
|
331
|
-
onSuccess: ({ data }) => {
|
|
332
|
-
analytics.track('lead_captured', data)
|
|
333
|
-
},
|
|
334
|
-
onError: (errors) => {
|
|
335
|
-
console.error('Validation errors:', errors)
|
|
336
|
-
},
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
return <form {...form.props}>{/* ... */}</form>
|
|
340
|
-
}
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
:::
|
|
344
|
-
|
|
345
|
-
Callbacks are scoped to the component that passes them, and are cleaned up automatically when that component unmounts — no manual teardown is needed. Passing a new inline function on a re-render replaces the previous one rather than adding another, so a single submit runs each callback exactly once.
|
|
346
|
-
|
|
347
|
-
A throwing or rejecting `onSuccess`/`onError` callback cannot block the flow: the step still advances, and the failure is reported on the client event bus as `form_submit_callback_error` so it stays observable.
|
|
348
|
-
|
|
349
|
-
#### Registering callbacks imperatively
|
|
350
|
-
|
|
351
|
-
`form.onSuccess`, `form.onError` and `form.onBeforeSubmit` are also available as an escape hatch, for cases where a callback has to be attached conditionally. They return nothing — cleanup is automatic, as above.
|
|
352
|
-
|
|
353
|
-
```tsx [React]
|
|
354
|
-
function ContactStep({ trackConversions }: { trackConversions: boolean }) {
|
|
355
|
-
const { form } = useStep()
|
|
356
|
-
|
|
357
|
-
if (trackConversions) {
|
|
358
|
-
form.onSuccess(({ data }) => analytics.track('lead_captured', data))
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return <form {...form.props}>{/* ... */}</form>
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
:::warning
|
|
366
|
-
Register from the component body, not from an event handler. A registration made inside a click handler is added each time the handler runs and is only released when the component unmounts, so it accumulates. Prefer the options object above wherever you can.
|
|
367
|
-
:::
|
|
368
|
-
|
|
369
|
-
### Preventing navigation on success
|
|
370
|
-
|
|
371
|
-
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:
|
|
372
|
-
|
|
373
|
-
:::code-group
|
|
374
|
-
|
|
375
|
-
```svelte [Svelte]
|
|
376
|
-
<script lang="ts">
|
|
377
|
-
import { getStep } from '@picked/svelte/hooks'
|
|
378
|
-
import { getExperience } from '@picked/svelte/hooks'
|
|
379
|
-
|
|
380
|
-
const experience = getExperience()
|
|
381
|
-
|
|
382
|
-
const { form } = getStep({
|
|
383
|
-
onSuccess: ({ data, stopNavigation }) => {
|
|
384
|
-
stopNavigation()
|
|
385
|
-
|
|
386
|
-
// Navigate to step based on submitted data
|
|
387
|
-
if (data['plan-type'] === 'enterprise') {
|
|
388
|
-
experience.goToStepById('enterprise-contact')
|
|
389
|
-
} else {
|
|
390
|
-
experience.goToNextStep()
|
|
391
|
-
}
|
|
392
|
-
},
|
|
393
|
-
})
|
|
394
|
-
</script>
|
|
395
|
-
|
|
396
|
-
<form {...form.props}>{/* ... */}</form>
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
```tsx [React]
|
|
400
|
-
import { useStep } from '@picked/react/hooks'
|
|
401
|
-
import { useExperience } from '@picked/react/hooks'
|
|
402
|
-
|
|
403
|
-
function PlanStep() {
|
|
404
|
-
const experience = useExperience()
|
|
405
|
-
|
|
406
|
-
const { form } = useStep({
|
|
407
|
-
onSuccess: ({ data, stopNavigation }) => {
|
|
408
|
-
stopNavigation()
|
|
409
|
-
|
|
410
|
-
// Decide the next step based on submitted data
|
|
411
|
-
if (data['plan-type'] === 'enterprise') {
|
|
412
|
-
experience.goToStepById('enterprise-contact')
|
|
413
|
-
} else {
|
|
414
|
-
experience.goToNextStep()
|
|
415
|
-
}
|
|
416
|
-
},
|
|
417
|
-
})
|
|
418
|
-
|
|
419
|
-
return <form {...form.props}>{/* ... */}</form>
|
|
420
|
-
}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
:::
|
|
424
|
-
|
|
425
|
-
Navigate by step `id` with `goToStepById('<step-id>')`, or by the step's semantic `key` with `goToStepByKey('<step-key>')`. Both jump straight to the matching step node; if no step matches, the call is a no-op.
|
|
426
|
-
|
|
427
|
-
## Best practices
|
|
428
|
-
|
|
429
|
-
- **Give steps meaningful labels**: The `label` is used in analytics events and the dashboard — prefer descriptive names like `"Contact Details"` over `"Step 2"`
|
|
430
|
-
- **Keep steps focused**: Each step should collect a small, related set of information. Prefer more steps over longer forms to reduce abandonment
|
|
431
|
-
- **Use conditionals for branching**: Avoid duplicating steps — model branching logic with `nextConditional()` so shared steps can be reused
|
|
432
|
-
- **Use `stopNavigation` sparingly**: Automatic navigation after submit is the expected behavior. Only disable it when you need explicit control over the next destination
|
|
433
|
-
- **Validate eagerly on blur, not on change**: The SDK follows this pattern automatically — fields show errors after the user leaves them, not as they type
|
|
434
|
-
- **Lazy-load large step components**: Use the `component` prop on `<Step>` with a dynamic import for content that is only shown to a subset of users
|
package/dist/docs/steps.mdx
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Steps
|
|
8
|
-
|
|
9
|
-
A step is a visual screen or card shown to visitors during an experience. Each step holds one or more fields that collect data or display content.
|
|
10
|
-
|
|
11
|
-
<Screenshot
|
|
12
|
-
route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/steps"
|
|
13
|
-
alt="The steps list for a workspace on the Picked dashboard"
|
|
14
|
-
/>
|
|
15
|
-
|
|
16
|
-
## Create a step
|
|
17
|
-
|
|
18
|
-
1. Open your project.
|
|
19
|
-
2. Click **Steps** in the sidebar.
|
|
20
|
-
3. Click **New Step**.
|
|
21
|
-
4. Enter a name and key.
|
|
22
|
-
5. Click **Create**.
|
|
23
|
-
|
|
24
|
-
The key is a unique identifier used in your application. It's set once and can't be changed later.
|
|
25
|
-
|
|
26
|
-
## Configure a step
|
|
27
|
-
|
|
28
|
-
**Name**: The display name shown in the dashboard. Not visible to visitors.
|
|
29
|
-
|
|
30
|
-
**Key**: The programmatic identifier used by your application to reference this step. Not visible to visitors.
|
|
31
|
-
|
|
32
|
-
**Layout Name**: The name of the component layout used to render this step. For example, `card`, `modal`, or `fullscreen`.
|
|
33
|
-
|
|
34
|
-
A step can also carry a **Step Layout**, a reusable CMS schema that backs the step with a Content Entry. See [Page & Step Layouts](/content/layouts).
|
|
35
|
-
|
|
36
|
-
## Assign fields
|
|
37
|
-
|
|
38
|
-
In the flow builder, drag a field from the entity browser onto a step node. The field appears in the step's **Assigned Fields** list in the inspector.
|
|
39
|
-
|
|
40
|
-
You can also view and manage assigned fields by selecting the step node and expanding the **Assigned Fields** section. Click any field to open its inspector.
|
|
41
|
-
|
|
42
|
-
## Reuse steps
|
|
43
|
-
|
|
44
|
-
Steps are project-level entities. You can drag the same step into multiple experience flows. Changes to a step's configuration apply everywhere it's used.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Team management
|
|
6
|
-
|
|
7
|
-
Manage who has access to your organization and what they can do. Organizations are the top-level container for projects and members.
|
|
8
|
-
|
|
9
|
-
## Organizations
|
|
10
|
-
|
|
11
|
-
An organization groups your projects, members, and settings. You can belong to multiple organizations.
|
|
12
|
-
|
|
13
|
-
Switch between organizations using the organization selector in the top of the sidebar.
|
|
14
|
-
|
|
15
|
-
## Invite members
|
|
16
|
-
|
|
17
|
-
1. Open your organization.
|
|
18
|
-
2. Click **Members**.
|
|
19
|
-
3. Click **Invite**.
|
|
20
|
-
4. Enter an email address.
|
|
21
|
-
5. Select a role.
|
|
22
|
-
6. Click **Send Invite**.
|
|
23
|
-
|
|
24
|
-
The invited user receives an email with a link to join your organization. They need to create a Picked account if they don't have one.
|
|
25
|
-
|
|
26
|
-
## Remove members
|
|
27
|
-
|
|
28
|
-
1. Open your organization.
|
|
29
|
-
2. Click **Members**.
|
|
30
|
-
3. Find the member you want to remove.
|
|
31
|
-
4. Click **Remove** next to their name.
|
|
32
|
-
5. Confirm the removal.
|
|
33
|
-
|
|
34
|
-
The member immediately loses access to all projects in the organization.
|
|
35
|
-
|
|
36
|
-
## Roles and permissions
|
|
37
|
-
|
|
38
|
-
Members are assigned roles that control what they can access. Roles determine whether a member can create projects, edit experiences, manage other members, or view reports.
|
|
39
|
-
|
|
40
|
-
Assign the minimum role needed for each member's responsibilities.
|
package/dist/docs/vite-plugin.md
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Vite Plugin
|
|
6
|
-
|
|
7
|
-
`@picked/vite-plugin-picked` integrates Picked into your Vite project. It fetches your project configuration at build time and injects it via Vite's `define`, eliminating the runtime API request. During development it also serves a launcher page for previewing experiences with feature overrides.
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
10
|
-
|
|
11
|
-
:::code-group
|
|
12
|
-
|
|
13
|
-
```bash [npm]
|
|
14
|
-
npm install @picked/vite-plugin-picked
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
```bash [pnpm]
|
|
18
|
-
pnpm add @picked/vite-plugin-picked
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
```bash [yarn]
|
|
22
|
-
yarn add @picked/vite-plugin-picked
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
:::
|
|
26
|
-
|
|
27
|
-
## Setup
|
|
28
|
-
|
|
29
|
-
Add the plugin to your `vite.config.ts`:
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
import { defineConfig } from 'vite'
|
|
33
|
-
import { picked } from '@picked/vite-plugin-picked'
|
|
34
|
-
|
|
35
|
-
export default defineConfig({
|
|
36
|
-
plugins: [
|
|
37
|
-
picked({
|
|
38
|
-
projectId: 'your-project-id',
|
|
39
|
-
}),
|
|
40
|
-
],
|
|
41
|
-
})
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## How It Works
|
|
45
|
-
|
|
46
|
-
### Build-Time Config Injection
|
|
47
|
-
|
|
48
|
-
When Vite starts (both `dev` and `build`), the plugin:
|
|
49
|
-
|
|
50
|
-
1. Fetches your project configuration from the Picked API
|
|
51
|
-
2. Embeds the config directly into your bundle
|
|
52
|
-
3. The SDK reads the embedded config at runtime, skipping the network request
|
|
53
|
-
|
|
54
|
-
When a preview token is present at runtime, the SDK ignores the build-time config and fetches fresh data from the API.
|
|
55
|
-
|
|
56
|
-
### Dev Launcher
|
|
57
|
-
|
|
58
|
-
During development, the plugin serves an HTML page at `/` that lets you:
|
|
59
|
-
|
|
60
|
-
- See all features in your project with their current status
|
|
61
|
-
- Toggle features on/off for local testing
|
|
62
|
-
- Preview experiences with specific feature overrides
|
|
63
|
-
|
|
64
|
-
After the dev server starts, the launcher URL appears alongside Vite's native output:
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
➜ Picked: http://localhost:5173/
|
|
68
|
-
➜ Local: http://localhost:5173/
|
|
69
|
-
➜ Network: use --host to expose
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Options
|
|
73
|
-
|
|
74
|
-
| Option | Type | Default | Description |
|
|
75
|
-
| ---------------- | --------- | ---------------------------- | -------------------------------------------------------- |
|
|
76
|
-
| `projectId` | `string` | — | **Required.** Your Picked project ID. |
|
|
77
|
-
| `apiUrl` | `string` | `https://api.picked.app` | Custom API URL for self-hosted or local API instances. |
|
|
78
|
-
| `disableLauncher`| `boolean` | `false` | Disable the launcher page in both dev and build output. |
|
|
79
|
-
|
|
80
|
-
## Build Output
|
|
81
|
-
|
|
82
|
-
When building for production (`vite build`), the plugin emits an `index.html` file containing the launcher page (unless `disableLauncher` is set). This lets you deploy the launcher alongside your application for stakeholder previews.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: docs
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
import { Screenshot } from '../../components/Screenshot'
|
|
6
|
-
|
|
7
|
-
# Workspace versioning
|
|
8
|
-
|
|
9
|
-
Every publish creates an immutable snapshot of your workspace. The project always serves exactly one version — the *live* version. Rolling back moves the project's live pointer to an earlier snapshot without modifying any data.
|
|
10
|
-
|
|
11
|
-
<Screenshot
|
|
12
|
-
route="/{orgSlug}/{projectId}/publish-history"
|
|
13
|
-
alt="The Publish history page showing published workspace versions with Live and Restore actions"
|
|
14
|
-
hide={['[data-testid="version-row-relative-time"]']}
|
|
15
|
-
/>
|
|
16
|
-
|
|
17
|
-
## Publish history
|
|
18
|
-
|
|
19
|
-
The **Publish history** page lists every published version across all workspaces in the project, newest first. The currently-served version carries a **Live** badge.
|
|
20
|
-
|
|
21
|
-
## Rolling back to a previous version
|
|
22
|
-
|
|
23
|
-
1. Open **Publish history** from the project sidebar.
|
|
24
|
-
2. Find the version you want to restore and click **Restore**.
|
|
25
|
-
3. Review the diff preview — it shows what changes between the current live version and the target.
|
|
26
|
-
4. Click **Restore this version** to confirm.
|
|
27
|
-
|
|
28
|
-
The restored version is immediately live. Your current draft is left untouched.
|