@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.
Files changed (291) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/api-03c5jvVk.js +38 -0
  3. package/dist/api-CQxCVIrm.cjs +1 -0
  4. package/dist/cjs/form/index.js +1 -1
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/plugins/dom-observer/index.js +1 -1
  7. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  8. package/dist/cjs/server/index.js +1 -1
  9. package/dist/docs/explanation/conditions-and-the-logic-engine.md +94 -0
  10. package/dist/docs/explanation/feature-flag-allocation.md +176 -0
  11. package/dist/docs/explanation/how-picked-works.md +124 -0
  12. package/dist/docs/explanation/how-pickedql-works.md +76 -0
  13. package/dist/docs/explanation/pages-and-flows.md +64 -0
  14. package/dist/docs/explanation/the-content-model.md +77 -0
  15. package/dist/docs/explanation/the-two-apis.md +68 -0
  16. package/dist/docs/explanation/why-server-side-rendering.md +76 -0
  17. package/dist/docs/explanation/workspaces-and-versions.md +71 -0
  18. package/dist/docs/how-to/add-a-step-field-or-action.md +43 -0
  19. package/dist/docs/{pickedql/examples.md → how-to/analytics/index.md} +53 -28
  20. package/dist/docs/how-to/archive-or-delete-a-workspace.md +46 -0
  21. package/dist/docs/how-to/authenticate-with-a-magic-link.md +40 -0
  22. package/dist/docs/how-to/authenticate-with-a-password.md +51 -0
  23. package/dist/docs/how-to/authenticate-with-an-api-key.md +51 -0
  24. package/dist/docs/how-to/authenticate-with-oauth.md +40 -0
  25. package/dist/docs/how-to/build-a-flow.md +83 -0
  26. package/dist/docs/how-to/connect-the-mcp-server.md +38 -0
  27. package/dist/docs/how-to/create-a-project.md +29 -0
  28. package/dist/docs/how-to/create-an-experience.md +42 -0
  29. package/dist/docs/how-to/create-and-revoke-an-api-key.md +37 -0
  30. package/dist/docs/how-to/debug-with-the-chrome-extension.md +57 -0
  31. package/dist/docs/how-to/define-a-page-layout.md +39 -0
  32. package/dist/docs/how-to/fill-and-publish-a-page.md +50 -0
  33. package/dist/docs/how-to/install-the-gtm-template.md +84 -0
  34. package/dist/docs/how-to/install-the-sdk.md +68 -0
  35. package/dist/docs/how-to/install-the-vite-plugin.md +56 -0
  36. package/dist/docs/how-to/invite-and-remove-members.md +34 -0
  37. package/dist/docs/how-to/preview-a-workspace.md +28 -0
  38. package/dist/docs/how-to/publish-a-workspace.md +30 -0
  39. package/dist/docs/how-to/read-a-feature-flag.md +101 -0
  40. package/dist/docs/how-to/register-a-component.md +55 -0
  41. package/dist/docs/how-to/register-an-action-handler.md +67 -0
  42. package/dist/docs/how-to/render-a-step-form.md +132 -0
  43. package/dist/docs/how-to/render-an-unpublished-preview.md +41 -0
  44. package/dist/docs/how-to/reuse-a-section.md +37 -0
  45. package/dist/docs/how-to/reuse-a-step-field-or-action.md +28 -0
  46. package/dist/docs/how-to/roll-back-a-published-version.md +26 -0
  47. package/dist/docs/how-to/run-an-ab-test.md +49 -0
  48. package/dist/docs/how-to/run-code-on-a-form-submission.md +125 -0
  49. package/dist/docs/how-to/server-render-a-page.md +81 -0
  50. package/dist/docs/how-to/set-a-content-security-policy.md +32 -0
  51. package/dist/docs/how-to/set-up-mfa.md +69 -0
  52. package/dist/docs/how-to/upload-and-use-an-asset.mdx +73 -0
  53. package/dist/docs/how-to/validate-a-field.md +52 -0
  54. package/dist/docs/how-to/write-a-condition.md +45 -0
  55. package/dist/docs/how-to/write-a-predicate.md +60 -0
  56. package/dist/docs/index.md +41 -59
  57. package/dist/docs/reference/dashboard/actions.mdx +53 -0
  58. package/dist/docs/reference/dashboard/api-keys.mdx +37 -0
  59. package/dist/docs/reference/dashboard/conditions.mdx +42 -0
  60. package/dist/docs/reference/dashboard/content/asset-library.mdx +63 -0
  61. package/dist/docs/reference/dashboard/content/content-entries.mdx +44 -0
  62. package/dist/docs/reference/dashboard/content/layouts.mdx +62 -0
  63. package/dist/docs/reference/dashboard/content/pages.mdx +35 -0
  64. package/dist/docs/reference/dashboard/content/sections.mdx +28 -0
  65. package/dist/docs/reference/dashboard/experiences.mdx +51 -0
  66. package/dist/docs/reference/dashboard/features.mdx +114 -0
  67. package/dist/docs/reference/dashboard/fields.mdx +100 -0
  68. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +58 -0
  69. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +57 -0
  70. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +72 -0
  71. package/dist/docs/reference/dashboard/flow-builder/nodes.md +63 -0
  72. package/dist/docs/reference/dashboard/projects.mdx +44 -0
  73. package/dist/docs/reference/dashboard/reports.mdx +43 -0
  74. package/dist/docs/reference/dashboard/steps.mdx +37 -0
  75. package/dist/docs/reference/dashboard/team-management.md +29 -0
  76. package/dist/docs/reference/dashboard/workspace-versioning.mdx +30 -0
  77. package/dist/docs/reference/dashboard/workspaces.mdx +76 -0
  78. package/dist/docs/{delivery-api → reference/delivery-api}/experience-content.md +17 -5
  79. package/dist/docs/reference/delivery-api/index.md +45 -0
  80. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +79 -0
  81. package/dist/docs/{delivery-api → reference/delivery-api}/project-config.md +15 -6
  82. package/dist/docs/reference/glossary.md +173 -0
  83. package/dist/docs/reference/management-api/authentication.md +74 -0
  84. package/dist/docs/{api → reference/management-api}/authorization-and-scopes.md +70 -47
  85. package/dist/docs/reference/management-api/error-handling.md +233 -0
  86. package/dist/docs/{api → reference/management-api}/pagination.md +36 -20
  87. package/dist/docs/reference/pickedql/data-sources.md +174 -0
  88. package/dist/docs/reference/pickedql/dimensions.md +87 -0
  89. package/dist/docs/{pickedql → reference/pickedql}/filtering.md +17 -6
  90. package/dist/docs/reference/pickedql/index.md +18 -0
  91. package/dist/docs/reference/pickedql/schema.md +172 -0
  92. package/dist/docs/reference/pickedql/virtual-functions.md +237 -0
  93. package/dist/docs/reference/sdk/actions.md +30 -0
  94. package/dist/docs/{sdk → reference/sdk}/conditions.md +15 -5
  95. package/dist/docs/reference/sdk/content-security-policy.md +21 -0
  96. package/dist/docs/reference/sdk/experiences.md +51 -0
  97. package/dist/docs/reference/sdk/features.md +233 -0
  98. package/dist/docs/reference/sdk/fields.md +209 -0
  99. package/dist/docs/reference/sdk/index.md +68 -0
  100. package/dist/docs/{sdk → reference/sdk}/plugins/create-experience.md +25 -34
  101. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +74 -0
  102. package/dist/docs/reference/sdk/plugins/index.md +29 -0
  103. package/dist/docs/{sdk → reference/sdk}/plugins/window-object.md +6 -0
  104. package/dist/docs/reference/sdk/predicates.md +43 -0
  105. package/dist/docs/reference/sdk/ssr/index.md +33 -0
  106. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +103 -0
  107. package/dist/docs/reference/sdk/ssr/serialize.md +77 -0
  108. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +59 -0
  109. package/dist/docs/reference/sdk/steps.md +87 -0
  110. package/dist/docs/reference/tools/chrome-extension.md +16 -0
  111. package/dist/docs/reference/tools/image-optimisation-service.md +104 -0
  112. package/dist/docs/reference/tools/mcp.md +88 -0
  113. package/dist/docs/reference/tools/vite-plugin.md +88 -0
  114. package/dist/docs/tutorials/first-api-call.md +228 -0
  115. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +143 -0
  116. package/dist/docs/tutorials/first-experience.mdx +255 -0
  117. package/dist/docs/tutorials/first-server-rendered-page.mdx +186 -0
  118. package/dist/{dom-BwmTHeT7.js → dom-BqcToNL0.js} +1 -3
  119. package/dist/{dom-CDrHc_j9.cjs → dom-DlLH3FxV.cjs} +1 -1
  120. package/dist/esm/form/index.js +2 -4
  121. package/dist/esm/index.js +225 -186
  122. package/dist/esm/plugins/dom-observer/index.js +1 -1
  123. package/dist/esm/plugins/dynamic-experiences/index.js +3 -3
  124. package/dist/esm/preview/index.js +1 -1
  125. package/dist/esm/server/index.js +33 -31
  126. package/dist/{experience-instance-DOJShRk5.js → experience-instance-DGk11d8a.js} +3 -3
  127. package/dist/experience-instance-Dej3P1sE.cjs +1 -0
  128. package/dist/plugin-CHOVsx7Z.js +287 -0
  129. package/dist/plugin-DsaGXQHx.cjs +1 -0
  130. package/dist/{preview-channel-DW9J8t4B.js → preview-channel-CSr96XAo.js} +1 -1
  131. package/dist/{protocol-DSqOlW2r.js → protocol-C5KkkiZc.js} +1 -1
  132. package/dist/types/client.d.ts +7 -6
  133. package/dist/types/data-source/api.d.ts +60 -0
  134. package/dist/types/data-source/api.d.ts.map +1 -0
  135. package/dist/types/data-source/provider.d.ts +97 -0
  136. package/dist/types/data-source/provider.d.ts.map +1 -0
  137. package/dist/types/entities/action/action.d.ts +5 -4
  138. package/dist/types/entities/action/action.d.ts.map +1 -1
  139. package/dist/types/entities/component/component.d.ts +6 -5
  140. package/dist/types/entities/component/component.d.ts.map +1 -1
  141. package/dist/types/entities/condition/condition.d.ts +5 -5
  142. package/dist/types/entities/content/content.d.ts +4 -3
  143. package/dist/types/entities/experience/experience.d.ts +11 -10
  144. package/dist/types/entities/experience/experience.d.ts.map +1 -1
  145. package/dist/types/entities/experience-instance/experience-instance.d.ts +10 -9
  146. package/dist/types/entities/feature/feature.d.ts +19 -2
  147. package/dist/types/entities/feature/feature.d.ts.map +1 -1
  148. package/dist/types/entities/field/field.d.ts +7 -6
  149. package/dist/types/entities/framework/framework.d.ts +7 -6
  150. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  151. package/dist/types/entities/history/history.d.ts +6 -6
  152. package/dist/types/entities/plugin/plugin.d.ts +3 -2
  153. package/dist/types/entities/plugin/plugin.d.ts.map +1 -1
  154. package/dist/types/entities/predicate/predicate.d.ts +4 -3
  155. package/dist/types/entities/predicate/predicate.d.ts.map +1 -1
  156. package/dist/types/entities/response/response-validation.d.ts +3 -2
  157. package/dist/types/entities/response/response.d.ts +12 -11
  158. package/dist/types/entities/session/session.d.ts +2 -1
  159. package/dist/types/entities/step/step.d.ts +6 -5
  160. package/dist/types/exports.d.ts +2 -1
  161. package/dist/types/exports.d.ts.map +1 -1
  162. package/dist/types/form/build-responses.d.ts +2 -1
  163. package/dist/types/form/create-field-evaluator.d.ts +4 -3
  164. package/dist/types/form/create-field-validation.d.ts +5 -4
  165. package/dist/types/form/create-form.d.ts +7 -6
  166. package/dist/types/form/create-submit-pipeline.d.ts +7 -6
  167. package/dist/types/form/get-step-fields.d.ts +3 -2
  168. package/dist/types/lifecycle/condition-selection.d.ts +14 -4
  169. package/dist/types/lifecycle/lifecycle.d.ts +4 -3
  170. package/dist/types/lifecycle/rules-logic.d.ts +4 -3
  171. package/dist/types/lifecycle/state-snapshot.d.ts +4 -3
  172. package/dist/types/picked.d.ts +79 -62
  173. package/dist/types/picked.d.ts.map +1 -1
  174. package/dist/types/ping.d.ts +1 -1
  175. package/dist/types/ping.d.ts.map +1 -1
  176. package/dist/types/plugins/create-experience/create-experience.d.ts +9 -8
  177. package/dist/types/plugins/create-experience/create-experience.d.ts.map +1 -1
  178. package/dist/types/plugins/create-experience/plugin.d.ts +3 -2
  179. package/dist/types/plugins/create-experience/plugin.d.ts.map +1 -1
  180. package/dist/types/plugins/create-experience/serialization.d.ts.map +1 -1
  181. package/dist/types/plugins/dom-observer/plugin.d.ts +1 -1
  182. package/dist/types/plugins/dynamic-experiences/hash.d.ts +40 -5
  183. package/dist/types/plugins/dynamic-experiences/hash.d.ts.map +1 -1
  184. package/dist/types/plugins/dynamic-experiences/index.d.ts +2 -0
  185. package/dist/types/plugins/dynamic-experiences/index.d.ts.map +1 -1
  186. package/dist/types/plugins/dynamic-experiences/plugin.d.ts +4 -36
  187. package/dist/types/plugins/dynamic-experiences/plugin.d.ts.map +1 -1
  188. package/dist/types/plugins/dynamic-experiences/types.d.ts +42 -11
  189. package/dist/types/plugins/dynamic-experiences/types.d.ts.map +1 -1
  190. package/dist/types/plugins/experience-browser-storage/plugin.d.ts +1 -1
  191. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  192. package/dist/types/plugins/history-browser-storage/plugin.d.ts +1 -1
  193. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  194. package/dist/types/plugins/responses-browser-storage/plugin.d.ts +1 -1
  195. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  196. package/dist/types/plugins/responses-indexeddb/plugin.d.ts +1 -1
  197. package/dist/types/plugins/single-page-app/plugin.d.ts +1 -1
  198. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  199. package/dist/types/plugins/web-components/plugin.d.ts +2 -1
  200. package/dist/types/plugins/window-object/plugin.d.ts +2 -2
  201. package/dist/types/preview-channel.d.ts +5 -1
  202. package/dist/types/preview-receiver/index.d.ts +18 -1
  203. package/dist/types/preview-receiver/protocol.d.ts +10 -1
  204. package/dist/types/server/index.d.ts +3 -3
  205. package/dist/types/server/serialize.d.ts +8 -2
  206. package/dist/types/server/serialize.d.ts.map +1 -1
  207. package/dist/types/utils/dom.d.ts +2 -1
  208. package/dist/types/utils/events.d.ts +6 -6
  209. package/dist/types/utils/events.d.ts.map +1 -1
  210. package/dist/types/utils/global-obj.d.ts +1 -1
  211. package/dist/types/utils/global-obj.d.ts.map +1 -1
  212. package/dist/types/utils/id.d.ts.map +1 -1
  213. package/dist/types/utils/logger.d.ts +2 -1
  214. package/dist/types/utils/logger.d.ts.map +1 -1
  215. package/dist/types/utils/node-tree/get-next-node-from-action.d.ts +2 -1
  216. package/dist/types/utils/node-tree/get-next-node-from-condition.d.ts +2 -1
  217. package/dist/types/utils/node-tree/get-next-node.d.ts +1 -1
  218. package/dist/types/utils/node-tree/get-next-node.d.ts.map +1 -1
  219. package/dist/types/utils/node-tree/get-origin-node.d.ts +1 -1
  220. package/dist/types/utils/node-tree/get-origin-node.d.ts.map +1 -1
  221. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts +1 -1
  222. package/dist/types/utils/node-tree/min-max-steps-to-leaf.d.ts.map +1 -1
  223. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts +1 -1
  224. package/dist/types/utils/node-tree/min-max-steps-to-origin.d.ts.map +1 -1
  225. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts +1 -1
  226. package/dist/types/utils/node-tree/next-reachable-step-nodes.d.ts.map +1 -1
  227. package/dist/types/utils/nodes.d.ts +1 -1
  228. package/dist/types/utils/picked-config.d.ts +2 -1
  229. package/dist/types/utils/rehydrate-scripts.d.ts +6 -0
  230. package/dist/types/utils/rehydrate-scripts.d.ts.map +1 -1
  231. package/dist/types/utils/rules-logic.d.ts +6 -2
  232. package/dist/types/utils/storage.d.ts +1 -1
  233. package/dist/types/utils/storage.d.ts.map +1 -1
  234. package/package.json +22 -23
  235. package/dist/api-CPL40b7A.js +0 -40
  236. package/dist/api-Dz5rgRgQ.cjs +0 -1
  237. package/dist/docs/actions.mdx +0 -78
  238. package/dist/docs/api/authentication.md +0 -376
  239. package/dist/docs/api/error-handling.md +0 -211
  240. package/dist/docs/api/index.md +0 -197
  241. package/dist/docs/api-keys.mdx +0 -40
  242. package/dist/docs/chrome-extension.md +0 -51
  243. package/dist/docs/conditions.mdx +0 -59
  244. package/dist/docs/content/asset-library.mdx +0 -93
  245. package/dist/docs/content/content-entries.mdx +0 -30
  246. package/dist/docs/content/layouts.mdx +0 -70
  247. package/dist/docs/content/pages.mdx +0 -67
  248. package/dist/docs/content/sections.mdx +0 -33
  249. package/dist/docs/delivery-api/index.md +0 -46
  250. package/dist/docs/delivery-api/preview-caching-crawling.md +0 -59
  251. package/dist/docs/experiences.mdx +0 -42
  252. package/dist/docs/features.mdx +0 -58
  253. package/dist/docs/fields.mdx +0 -79
  254. package/dist/docs/flow-builder/building-flows.md +0 -61
  255. package/dist/docs/flow-builder/condition-builder.md +0 -54
  256. package/dist/docs/flow-builder/keyboard-shortcuts.md +0 -66
  257. package/dist/docs/flow-builder/nodes.md +0 -43
  258. package/dist/docs/flow-builder/overview.mdx +0 -50
  259. package/dist/docs/gtm-template.md +0 -69
  260. package/dist/docs/guides/build-a-personalized-page.mdx +0 -143
  261. package/dist/docs/image-optimisation-service.md +0 -80
  262. package/dist/docs/mcp.md +0 -120
  263. package/dist/docs/pickedql/data-sources.md +0 -145
  264. package/dist/docs/pickedql/dimensions.md +0 -65
  265. package/dist/docs/pickedql/index.md +0 -36
  266. package/dist/docs/pickedql/schema.md +0 -156
  267. package/dist/docs/pickedql/virtual-functions.md +0 -204
  268. package/dist/docs/projects.mdx +0 -37
  269. package/dist/docs/reports.mdx +0 -18
  270. package/dist/docs/sdk/actions.md +0 -66
  271. package/dist/docs/sdk/content-security-policy.md +0 -32
  272. package/dist/docs/sdk/experiences.md +0 -46
  273. package/dist/docs/sdk/features.md +0 -212
  274. package/dist/docs/sdk/fields.md +0 -263
  275. package/dist/docs/sdk/index.md +0 -83
  276. package/dist/docs/sdk/plugins/dynamic-experiences.md +0 -58
  277. package/dist/docs/sdk/plugins/index.md +0 -9
  278. package/dist/docs/sdk/predicates.md +0 -112
  279. package/dist/docs/sdk/ssr/index.md +0 -62
  280. package/dist/docs/sdk/ssr/rendering-and-hydration.md +0 -141
  281. package/dist/docs/sdk/ssr/serialize.md +0 -86
  282. package/dist/docs/sdk/ssr/slots-and-placements.md +0 -35
  283. package/dist/docs/sdk/steps.md +0 -434
  284. package/dist/docs/steps.mdx +0 -44
  285. package/dist/docs/team-management.md +0 -40
  286. package/dist/docs/vite-plugin.md +0 -82
  287. package/dist/docs/workspace-versioning.mdx +0 -28
  288. package/dist/docs/workspaces.mdx +0 -102
  289. package/dist/experience-instance-DurC3pE-.cjs +0 -1
  290. package/dist/plugin-CFXwbXeM.js +0 -247
  291. package/dist/plugin-m4qekgtA.cjs +0 -1
@@ -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
@@ -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.
@@ -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.