@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
@@ -0,0 +1,209 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Fields
7
+
8
+ Define your fields in code with `createField()`. Check the input with JSON Logic.
9
+ Read the values that a user sends through the step context.
10
+
11
+ ## Define a field
12
+
13
+ Define a field with `createField()` from the
14
+ `@picked/client/plugins/create-experience` package. Each field needs a unique
15
+ identifier, a name, a type, a label, and a count of the values that it takes:
16
+
17
+ ```ts
18
+ import { createField } from '@picked/client/plugins/create-experience'
19
+
20
+ // A text input that the user must fill in.
21
+ export const emailField = createField({
22
+ id: 'email-address',
23
+ name: 'email-address',
24
+ type: 'text',
25
+ label: 'Email Address',
26
+ multiple: false,
27
+ required: true,
28
+ placeholder: 'you@example.com',
29
+ })
30
+
31
+ // A dropdown that takes more than one choice, with fixed options.
32
+ export const communicationMethods = createField({
33
+ id: 'communication-methods',
34
+ name: 'communication-methods',
35
+ type: 'text',
36
+ label: 'Preferred contact methods',
37
+ multiple: true,
38
+ required: true,
39
+ options: [
40
+ {
41
+ id: 'email',
42
+ label: 'Email',
43
+ value: 'email',
44
+ },
45
+ {
46
+ id: 'phone',
47
+ label: 'Phone',
48
+ value: 'phone',
49
+ },
50
+ {
51
+ id: 'sms',
52
+ label: 'SMS',
53
+ value: 'sms',
54
+ },
55
+ ],
56
+ })
57
+ ```
58
+
59
+ ## Field types
60
+
61
+ A field has one of four basic types: `text`, `number`, `boolean`, or `object`.
62
+
63
+ ```ts
64
+ // One text input.
65
+ const nameField = createField({
66
+ type: 'text',
67
+ multiple: false,
68
+ // ...
69
+ })
70
+ ```
71
+
72
+ Give an `options` array to let the user choose more than one value:
73
+
74
+ ```ts
75
+ const nameField = createField({
76
+ type: 'text',
77
+ multiple: true,
78
+ options: [
79
+ {
80
+ id: 'option-one',
81
+ label: 'Option One',
82
+ value: 'product-id-one',
83
+ },
84
+ {
85
+ id: 'option-two',
86
+ label: 'Option Two',
87
+ value: 'product-id-two',
88
+ },
89
+ {
90
+ id: 'option-three',
91
+ label: 'Option Three',
92
+ value: 'product-id-three',
93
+ },
94
+ ],
95
+ })
96
+ ```
97
+
98
+ ## Conditions
99
+
100
+ A field and a field option both work with condition logic:
101
+
102
+ ```ts
103
+ const conditionalField = createField({
104
+ id: 'conditional-field',
105
+ type: 'text',
106
+ condition: {
107
+ invoke: {
108
+ var: 'responses.has-answered-question',
109
+ },
110
+ },
111
+ options: [
112
+ {
113
+ id: 'conditional-option',
114
+ label: 'Conditional Label',
115
+ condition: {
116
+ invoke: {
117
+ var: 'responses.eligible-for-option',
118
+ },
119
+ },
120
+ },
121
+ ],
122
+ })
123
+ ```
124
+
125
+ ## Field policies
126
+
127
+ Use a privacy policy to control how Picked tracks and stores the data of a field:
128
+
129
+ ```ts
130
+ const sensitiveField = createField({
131
+ id: 'ssn',
132
+ name: 'ssn',
133
+ type: 'text',
134
+ label: 'Social Security Number',
135
+ multiple: false,
136
+ required: true,
137
+ policies: {
138
+ doNotTrackValue: true, // Do not send the value to analytics.
139
+ doNotStoreValue: true, // Do not keep the value in browser storage.
140
+ },
141
+ })
142
+ ```
143
+
144
+ **Privacy policies**:
145
+
146
+ - `doNotTrackValue`: keeps the value of the field out of your analytics events. The
147
+ events carry the field ID only.
148
+ - `doNotStoreValue`: stops the SDK, so that it does not put the value in browser
149
+ storage.
150
+
151
+ Use these policies for sensitive data such as a tax number, a credit card number, or
152
+ a password. That data must stay in the browser.
153
+
154
+ Neither policy stops the flow from the use of the value inside the page. A field with both
155
+ policies set still holds its value there, for step validation and for the conditions after
156
+ the step. The policies control what leaves the page: your analytics, and browser
157
+ storage.
158
+
159
+ ## Field metadata
160
+
161
+ Add more text to help the user:
162
+
163
+ ```ts
164
+ const passwordField = createField({
165
+ id: 'password',
166
+ name: 'password',
167
+ type: 'text',
168
+ label: 'Password',
169
+ multiple: false,
170
+ required: true,
171
+ placeholder: 'Enter a strong password',
172
+ description: 'Your password must be at least 8 characters',
173
+ helpText: 'Use a mix of letters, numbers, and symbols for better security',
174
+ })
175
+ ```
176
+
177
+ **Metadata fields**:
178
+
179
+ - `placeholder`: the hint text that an empty input shows.
180
+ - `description`: a short explanation below the label.
181
+ - `helpText`: more guidance, or the requirements, next to the field.
182
+
183
+ ## Read a field value
184
+
185
+ The SDK stores each field response in the experience state. Read a response through
186
+ the `responses` object:
187
+
188
+ :::code-group
189
+
190
+ ```ts [In Conditions]
191
+ // Point at the value from a later field condition.
192
+ const sensitiveField = createField({
193
+ condition: {
194
+ '==': [
195
+ {
196
+ var: 'responses.field-name',
197
+ },
198
+ 'expected-value',
199
+ ],
200
+ },
201
+ })
202
+ ```
203
+
204
+ :::
205
+
206
+ ## Related
207
+
208
+ - [How to validate a field](/how-to/validate-a-field)
209
+ - [Fields](/reference/dashboard/fields) — the dashboard privacy controls.
@@ -0,0 +1,68 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Picked SDK
7
+
8
+ The Picked SDK lets you add a dynamic, personalized experience to your web
9
+ application with very little code.
10
+
11
+ :::tip
12
+ The SDK is framework-agnostic. It works with React, Svelte, Vue, and plain
13
+ JavaScript.
14
+ :::
15
+
16
+ ## Precondition and condition
17
+
18
+ | Category | Question | Description |
19
+ | ------------ | ---------------------- | --------------------------------------------------------------------------------------------- |
20
+ | Precondition | Must Picked start? | Use it to check the environment, to filter by page, or for a feature flag that turns the SDK off completely. |
21
+ | Condition | Is this user eligible? | Use it to divide your users into groups, to enter a user into an A/B test, or to reach one group of users. |
22
+
23
+ ```ts
24
+ const picked = createClient({
25
+ precondition: {
26
+ and: [
27
+ {
28
+ or: [
29
+ {
30
+ invoke: {
31
+ var: 'features.aa-test',
32
+ },
33
+ },
34
+ true,
35
+ ],
36
+ },
37
+ { invoke: { var: 'predicates.shopify-is-product-page' } },
38
+ ],
39
+ },
40
+ condition: {
41
+ invoke: {
42
+ var: 'features.convincely-enabled',
43
+ },
44
+ },
45
+ // The rest of the Picked options go here.
46
+ })
47
+ ```
48
+
49
+ :::warning
50
+ A precondition or a condition that points at a feature flag reads the bucket of that
51
+ feature flag. That read allocates the visitor at that moment.
52
+
53
+ A precondition runs at startup. Picked therefore allocates every visitor to a feature
54
+ flag that a precondition points at, before anything else happens. This includes a
55
+ visitor who never reaches the experience that the feature flag controls.
56
+
57
+ See [Allocation and exposure](/explanation/feature-flag-allocation) before you point a
58
+ precondition at a flag.
59
+ :::
60
+
61
+ See [conditions](/reference/sdk/conditions) for more detail.
62
+
63
+ ## Related
64
+
65
+ - [How to install the SDK](/how-to/install-the-sdk)
66
+ - [How to register a component](/how-to/register-a-component)
67
+ - [About conditions and the logic engine](/explanation/conditions-and-the-logic-engine) —
68
+ what the difference is between a precondition and a condition.
@@ -1,39 +1,21 @@
1
1
  ---
2
+ type: reference
2
3
  layout: docs
3
4
  ---
4
5
 
5
6
  # Create Experience Plugin
6
7
 
7
- A plugin to register an array of experiences to the Picked client.
8
+ This plugin registers an array of experiences on the Picked client.
8
9
 
9
- ## Setup Plugin
10
+ ## Define a step
10
11
 
11
- :::code-group
12
-
13
- ```ts [app.ts]
14
- import { createClient } from '@picked/client'
15
- import { createExperiencePlugin } from '@picked/client/plugins/create-experience'
16
- import { funnelExperience } from '../experiences/funnel-experience'
17
- import { widgetExperience } from '../experiences/widget-experience'
18
-
19
- const client = createClient({
20
- projectId: 'your-project-id',
21
- plugins: createExperiencePlugin({
22
- experiences: [funnelExperience, widgetExperience],
23
- }),
24
- })
25
- ```
26
-
27
- :::
28
-
29
- ## Defining Steps
30
-
31
- Steps are defined using `createStep()`. They are added directly to an experience using `experience.addStep()`.
12
+ Define a step with `createStep()`. Add it directly to an experience with
13
+ `experience.addStep()`.
32
14
 
33
15
  ```ts
34
16
  import { createExperience, createStep } from '@picked/client/plugins/create-experience'
35
17
 
36
- // Define standalone steps
18
+ // Define the steps on their own.
37
19
  const welcomeStep = createStep({
38
20
  id: 'welcome',
39
21
  name: 'Welcome',
@@ -44,7 +26,7 @@ const contactStep = createStep({
44
26
  name: 'Contact Details',
45
27
  })
46
28
 
47
- // Define the experience and add steps to build the flow
29
+ // Define the experience, then add the steps to build the flow.
48
30
  const onboardingExperience = createExperience({
49
31
  id: 'onboarding',
50
32
  name: 'User Onboarding',
@@ -55,13 +37,14 @@ onboardingExperience.addStep(welcomeStep)
55
37
  onboardingExperience.addStep(contactStep)
56
38
  ```
57
39
 
58
- Each step requires a `name` that identifies it in analytics events. An `id` is optional — one will be generated automatically if omitted.
40
+ Each step needs a `name`, and your analytics events use that name to identify the
41
+ step. An `id` is optional. Picked makes one for you when you give none.
59
42
 
60
- Steps can be used on multiple experiences.
43
+ You can use the same step on more than one experience.
61
44
 
62
- ### Adding Fields to Steps
45
+ ### Add a field to a step
63
46
 
64
- Fields are defined with `createField()`.
47
+ Define a field with `createField()`.
65
48
 
66
49
  ```ts
67
50
  import { createStep, createField } from '@picked/client/plugins/create-experience'
@@ -77,7 +60,8 @@ const emailField = createField({
77
60
  })
78
61
  ```
79
62
 
80
- Fields are added to a step with `step.addField()`, or an array of `fieldIds` when creating a step:
63
+ Add a field to a step with `step.addField()`. You can also pass an array of
64
+ `fieldIds` when you create the step:
81
65
 
82
66
  ```ts
83
67
  const contactStep = createStep({
@@ -87,7 +71,7 @@ const contactStep = createStep({
87
71
 
88
72
  contactStep.addField(emailField)
89
73
 
90
- //Or
74
+ // Or:
91
75
 
92
76
  const contactStep = createStep({
93
77
  id: 'contact',
@@ -96,9 +80,9 @@ const contactStep = createStep({
96
80
  })
97
81
  ```
98
82
 
99
- ## Using conditions in an experience
83
+ ## Use a condition in an experience
100
84
 
101
- [Conditions](../conditions) are used to define when an experience will become active for the user.
85
+ A [condition](/reference/sdk/conditions) defines when an experience becomes active for the user.
102
86
 
103
87
  ```ts
104
88
  import { createExperience, createStep } from '@picked/client/plugins/create-experience'
@@ -125,8 +109,15 @@ const productPageFunnel = createExperience({
125
109
  })
126
110
  ```
127
111
 
128
- Navigation between steps is handled with [conditions](../conditions). Use the `create`
112
+ A [condition](/reference/sdk/conditions) also controls the move from one step to the next.
129
113
 
130
114
  ```ts
131
115
  import { createExperience, createStep } from '@picked/client/plugins/create-experience'
132
116
  ```
117
+
118
+ ## Related
119
+
120
+ - [Plugins](/reference/sdk/plugins)
121
+ - [SDK experiences](/reference/sdk/experiences)
122
+ - [Dynamic Experiences](/reference/sdk/plugins/dynamic-experiences) — the dashboard-driven
123
+ alternative.
@@ -0,0 +1,74 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Dynamic Experiences Plugin
7
+
8
+ This plugin reads the configuration of your project from the Picked API at runtime. You can
9
+ therefore control your experiences, feature flags, steps, fields, and conditions from
10
+ the [dashboard](/reference/dashboard/experiences) alone.
11
+
12
+ The plugin reads the configuration of your project and the CMS content of your
13
+ experiences from one source. It does not mix them. Picked gives a configuration and its
14
+ content the same version.
15
+
16
+ ## Options
17
+
18
+ | Option | Type | Default | Description |
19
+ | --- | --- | --- | --- |
20
+ | `mode` | `'bundle' \| 'api'` | see below | Where to read the configuration and the content from. |
21
+ | `apiUrl` | `string` | `https://api.picked.app` | Your own API URL, for a self-hosted or local API. |
22
+ | `projectConfig` | `ProjectConfig` | none | A configuration that you give. The plugin makes no request for it. |
23
+ | `getContent` | `function` | none | A function that you give. The plugin calls it for each experience that uses CMS content. |
24
+
25
+ ### mode
26
+
27
+ | Value | Source | Use it when |
28
+ | --- | --- | --- |
29
+ | `'bundle'` | The data that the [Vite plugin](/reference/tools/vite-plugin) puts in your build | You want no API request when the page loads. |
30
+ | `'api'` | The Picked API, read when the client starts | You want a workspace publish to reach users without a new deployment. |
31
+
32
+ :::code-group
33
+
34
+ ```ts [app.ts]
35
+ import { createClient } from '@picked/client'
36
+ import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
37
+
38
+ const client = createClient({
39
+ projectId: 'your-project-id',
40
+ plugins: [dynamicExperiencesPlugin({ mode: 'bundle' })],
41
+ })
42
+
43
+ client.start()
44
+ ```
45
+
46
+ :::
47
+
48
+ If you do not set `mode`, the plugin uses the build data when the Vite plugin gave it
49
+ some. In every other case it uses the API.
50
+
51
+ ### projectConfig and getContent
52
+
53
+ These two replace the source for you. Keep the configuration and the content at the same
54
+ version when you use them. The plugin cannot make that check for you.
55
+
56
+ ## Preview mode
57
+
58
+ After you [enter preview mode from the dashboard](/reference/dashboard/workspaces#preview), the SDK
59
+ receives a preview token and starts preview mode:
60
+
61
+ - The plugin reads fresh options from the API with that token, for any value of `mode`.
62
+ It does not read the build-time configuration, a `projectConfig` that you give, or the
63
+ cached options.
64
+ - A feature flag decision uses session storage. The decision resets when you close
65
+ the tab.
66
+
67
+ A `getContent` function keeps its place in a preview session, and it receives the token.
68
+ You therefore decide what a preview means for your own content.
69
+
70
+ ## Related
71
+
72
+ - [About how Picked works](/explanation/how-picked-works) — how the plugin resolves your
73
+ options at startup.
74
+ - [About feature flag allocation](/explanation/feature-flag-allocation)
@@ -0,0 +1,29 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Plugins
7
+
8
+ A plugin adds behaviour to the Picked client. Pass one to the `plugins` array of
9
+ `createClient()`.
10
+
11
+ | Plugin | Import | What it does |
12
+ | --- | --- | --- |
13
+ | [Dynamic Experiences](/reference/sdk/plugins/dynamic-experiences) | `@picked/client/plugins/dynamic-experiences` | Reads the published configuration of your project at runtime and registers every experience, step, field, condition, and feature flag. |
14
+ | [Create Experience](/reference/sdk/plugins/create-experience) | `@picked/client/plugins/create-experience` | Registers an experience, a step, and a field that you define in code. |
15
+ | [Window Object](/reference/sdk/plugins/window-object) | `@picked/client/plugins/window-object` | Puts the client on `window.Picked`, which helps when you debug. |
16
+ | Single Page App | `@picked/client/plugins/single-page-app` | Starts the client again on a history event. |
17
+ | React framework | `@picked/react/plugins/framework` | Lets the client render a React component. |
18
+ | Svelte framework | `@picked/svelte/plugins/framework` | Lets the client render a Svelte component. |
19
+ | Devtools | `@picked/svelte/plugins/devtools` | Connects the client to the Chrome extension. |
20
+
21
+ Most applications need a framework plugin and **one** of Dynamic Experiences or Create
22
+ Experience. Dynamic Experiences puts your options in the dashboard; Create Experience
23
+ puts them in code.
24
+
25
+ ## Related
26
+
27
+ - [How to install the SDK](/how-to/install-the-sdk) — where the plugins go.
28
+ - [SDK installation](/reference/sdk) — every client option.
29
+ - [How to debug with the Chrome extension](/how-to/debug-with-the-chrome-extension)
@@ -1,4 +1,5 @@
1
1
  ---
2
+ type: reference
2
3
  layout: docs
3
4
  ---
4
5
 
@@ -17,3 +18,8 @@ const client = createClient({
17
18
  plugins: [windowObjectPlugin()],
18
19
  })
19
20
  ```
21
+
22
+ ## Related
23
+
24
+ - [Plugins](/reference/sdk/plugins)
25
+ - [How to install the SDK](/how-to/install-the-sdk)
@@ -0,0 +1,43 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Predicates
7
+
8
+ A predicate holds reusable condition logic that reads the current state of your
9
+ application. Each predicate is a pure function. It takes a state snapshot, and that
10
+ snapshot holds the responses, the fields, the browser context, and optional
11
+ arguments.
12
+
13
+ ## Use the state snapshot
14
+
15
+ Each predicate takes a `StateSnapshot` object with these properties:
16
+
17
+ ```ts
18
+ interface StateSnapshot {
19
+ client: Picked // The Picked client.
20
+ responses?: Array<{
21
+ // Every response from the user.
22
+ fieldId: string
23
+ value: FieldValue | undefined
24
+ }>
25
+ args?: unknown[]
26
+ fields?: Field[] // Every registered field.
27
+ location?: Location // The browser location: URL, pathname, search, and more.
28
+ document?: Document // The browser document object.
29
+ sessionStorage?: Storage // The browser sessionStorage API.
30
+ localStorage?: Storage // The browser localStorage API.
31
+ }
32
+ ```
33
+
34
+ :::warning
35
+ In server-side rendering, and in any environment that is not a browser, `location`,
36
+ `document`, `sessionStorage`, and `localStorage` are `undefined`.
37
+ :::
38
+
39
+ ## Related
40
+
41
+ - [How to write a predicate](/how-to/write-a-predicate)
42
+ - [About conditions and the logic engine](/explanation/conditions-and-the-logic-engine) —
43
+ why predicates exist.
@@ -0,0 +1,33 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Server-Side Rendering
7
+
8
+ Render a Picked Page on your server so that search engines can read it. Then hydrate
9
+ the page on the client. This page shows the whole shape. The pages after it cover
10
+ each part.
11
+
12
+ ## The server entry point
13
+
14
+ The server helpers live in a dedicated entry point, so a browser bundle never holds
15
+ them:
16
+
17
+ ```ts
18
+ import { serialize, registerProjectConfig } from '@picked/client/server'
19
+ import type { PickedSnapshot } from '@picked/client/server'
20
+ ```
21
+
22
+ Go to [Server Snapshot](/reference/sdk/ssr/serialize) for the `serialize()` reference. Go to
23
+ [Rendering and Hydration](/reference/sdk/ssr/rendering-and-hydration) to connect React and
24
+ Svelte. Go to [Slots and Placements](/reference/sdk/ssr/slots-and-placements) for how a slot
25
+ chooses an experience. If the SDK is new to you, read
26
+ [Installation](/reference/sdk) first.
27
+
28
+ ## Related
29
+
30
+ - [About server-side rendering](/explanation/why-server-side-rendering) — why the snapshot
31
+ exists.
32
+ - [How to server-render a page](/how-to/server-render-a-page)
33
+ - [Server snapshot](/reference/sdk/ssr/serialize)
@@ -0,0 +1,103 @@
1
+ ---
2
+ type: reference
3
+ layout: docs
4
+ ---
5
+
6
+ # Rendering and Hydration
7
+
8
+ Seed a Picked client from the server snapshot, render your slots, and hydrate. This
9
+ page covers React and Svelte.
10
+
11
+ ## React: `PickedProvider`
12
+
13
+ `PickedProvider` gives a client to each component below it. Its props are a union of
14
+ two modes:
15
+
16
+ | Props | Mode | Description |
17
+ | --- | --- | --- |
18
+ | `{ options, snapshot? }` | Create | The provider calls `createClient(options)` and hydrates the client from the snapshot. |
19
+ | `{ client, snapshot? }` | Adopt | The provider uses a client that is there already, such as a global one for the whole application. It can also seed that client from the snapshot. |
20
+
21
+ The provider seeds the client at once, so the server and the first paint on the
22
+ client give the same markup. In the browser the provider calls `client.start()` from
23
+ an effect. `start()` is idempotent, so it changes nothing on a client that already
24
+ started.
25
+
26
+ ```tsx
27
+ import { PickedProvider, ExperienceSlot } from '@picked/react'
28
+
29
+ <PickedProvider options={options} snapshot={snapshot}>
30
+ <ExperienceSlot name="page" />
31
+ </PickedProvider>
32
+ ```
33
+
34
+ ## Svelte: `setPickedContext`
35
+
36
+ `setPickedContext` does the same work in the Svelte style. Call it one time at the
37
+ top of the `<script>` block of a component. It takes the same two modes,
38
+ `{ options, snapshot? }` or `{ client, snapshot? }`, and it returns the client.
39
+
40
+ ```svelte
41
+ <script lang="ts">
42
+ import { ExperienceSlot, setPickedContext } from '@picked/svelte'
43
+
44
+ setPickedContext({ options, snapshot })
45
+ </script>
46
+
47
+ <ExperienceSlot name="page" />
48
+ ```
49
+
50
+ ## Render the page component
51
+
52
+ The SDK does not connect content to a component. You own the component that a Page
53
+ renders. Register it under the name that the Page uses. The Page Layout in the dashboard
54
+ points at that same name. The component reads the resolved entry data
55
+ through a content hook: `useStepContent()` in React, and `getStepContent()` in
56
+ Svelte.
57
+
58
+ :::code-group
59
+
60
+ ```tsx [React]
61
+ import { useStepContent } from '@picked/react/hooks'
62
+
63
+ export function CMSPage() {
64
+ const content = useStepContent()
65
+ if (!content) {
66
+ return <p>Loading page content…</p>
67
+ }
68
+
69
+ const title = typeof content.title === 'string' ? content.title : ''
70
+ return (
71
+ <article>
72
+ <h1>{title}</h1>
73
+ </article>
74
+ )
75
+ }
76
+ ```
77
+
78
+ ```svelte [Svelte]
79
+ <script lang="ts">
80
+ import { getStepContent } from '@picked/svelte/hooks'
81
+
82
+ const content = getStepContent()
83
+ </script>
84
+
85
+ {#if $content}
86
+ <article>
87
+ <h1>{typeof $content.title === 'string' ? $content.title : ''}</h1>
88
+ </article>
89
+ {:else}
90
+ <p>Loading page content…</p>
91
+ {/if}
92
+ ```
93
+
94
+ :::
95
+
96
+ `useStepContent()` returns the `data` object of the entry directly. It returns `null`
97
+ while no content is registered. `getStepContent()` returns a store, and you read it
98
+ with `$content`.
99
+
100
+ ## Related
101
+
102
+ - [How to server-render a page](/how-to/server-render-a-page) — the full example.
103
+ - [Slots and placements](/reference/sdk/ssr/slots-and-placements)