@picked/client 0.0.101-next.2 → 0.0.101

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 (147) hide show
  1. package/README.md +34 -158
  2. package/dist/{api-BlRFU0Fi.js → api-BOKA2i46.js} +1 -1
  3. package/dist/{api-AaQeg3Ij.cjs → api-C5jUHF3A.cjs} +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  6. package/dist/cjs/server/index.js +1 -1
  7. package/dist/esm/index.js +2 -2
  8. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  9. package/dist/esm/server/index.js +2 -2
  10. package/dist/{plugin-CVD2TnRC.cjs → plugin-BcB9ah7q.cjs} +1 -1
  11. package/dist/{plugin-DhznDG-h.js → plugin-COWxZiTa.js} +2 -2
  12. package/dist/{preview-unavailable-mW4Pj3Ph.js → preview-unavailable-BJjc3UNr.js} +1 -1
  13. package/dist/{preview-unavailable-xWLCr93y.cjs → preview-unavailable-CV1BonKA.cjs} +1 -1
  14. package/dist/{provider-COb_V-yq.js → provider-CszmtTg3.js} +1 -1
  15. package/dist/{provider-zag5m5GH.cjs → provider-daBChM0G.cjs} +1 -1
  16. package/package.json +5 -5
  17. package/dist/docs/_root.css +0 -101
  18. package/dist/docs/explanation/conditions-and-the-logic-engine.md +0 -94
  19. package/dist/docs/explanation/content-references.md +0 -99
  20. package/dist/docs/explanation/feature-flag-allocation.md +0 -218
  21. package/dist/docs/explanation/how-picked-works.md +0 -124
  22. package/dist/docs/explanation/how-pickedql-works.md +0 -76
  23. package/dist/docs/explanation/pages-and-flows.md +0 -64
  24. package/dist/docs/explanation/the-content-model.md +0 -87
  25. package/dist/docs/explanation/the-two-apis.md +0 -68
  26. package/dist/docs/explanation/why-server-side-rendering.md +0 -76
  27. package/dist/docs/explanation/workspaces-and-versions.md +0 -71
  28. package/dist/docs/how-to/add-a-step-field-or-action.md +0 -43
  29. package/dist/docs/how-to/analytics/index.md +0 -316
  30. package/dist/docs/how-to/archive-or-delete-a-workspace.md +0 -46
  31. package/dist/docs/how-to/authenticate-the-cli.md +0 -101
  32. package/dist/docs/how-to/authenticate-with-a-magic-link.md +0 -47
  33. package/dist/docs/how-to/authenticate-with-a-password.md +0 -59
  34. package/dist/docs/how-to/authenticate-with-an-api-key.md +0 -51
  35. package/dist/docs/how-to/authenticate-with-oauth.md +0 -40
  36. package/dist/docs/how-to/build-a-flow.md +0 -93
  37. package/dist/docs/how-to/call-an-external-api-from-a-workflow.md +0 -102
  38. package/dist/docs/how-to/connect-the-mcp-server.md +0 -46
  39. package/dist/docs/how-to/create-a-content-entry.md +0 -48
  40. package/dist/docs/how-to/create-a-project.md +0 -29
  41. package/dist/docs/how-to/create-an-experience.md +0 -42
  42. package/dist/docs/how-to/create-and-revoke-an-api-key.md +0 -42
  43. package/dist/docs/how-to/debug-with-the-chrome-extension.md +0 -57
  44. package/dist/docs/how-to/define-a-page-layout.md +0 -46
  45. package/dist/docs/how-to/fill-and-publish-a-page.md +0 -66
  46. package/dist/docs/how-to/install-the-gtm-template.md +0 -84
  47. package/dist/docs/how-to/install-the-sdk.md +0 -93
  48. package/dist/docs/how-to/install-the-vite-plugin.md +0 -69
  49. package/dist/docs/how-to/invite-and-remove-members.md +0 -35
  50. package/dist/docs/how-to/point-one-entry-at-another.md +0 -61
  51. package/dist/docs/how-to/preview-a-workspace.md +0 -28
  52. package/dist/docs/how-to/publish-a-workspace.md +0 -30
  53. package/dist/docs/how-to/read-a-feature-flag.md +0 -113
  54. package/dist/docs/how-to/read-a-referenced-entry.md +0 -109
  55. package/dist/docs/how-to/register-a-component.md +0 -55
  56. package/dist/docs/how-to/register-an-action-handler.md +0 -85
  57. package/dist/docs/how-to/register-an-api-that-uses-oauth2.md +0 -107
  58. package/dist/docs/how-to/render-a-step-form.md +0 -131
  59. package/dist/docs/how-to/render-an-unpublished-preview.md +0 -41
  60. package/dist/docs/how-to/retry-a-failed-call-with-a-loop.md +0 -81
  61. package/dist/docs/how-to/reuse-a-section.md +0 -53
  62. package/dist/docs/how-to/reuse-a-step-field-or-action.md +0 -28
  63. package/dist/docs/how-to/roll-back-a-published-version.md +0 -26
  64. package/dist/docs/how-to/run-an-ab-test.md +0 -49
  65. package/dist/docs/how-to/run-code-on-a-form-submission.md +0 -125
  66. package/dist/docs/how-to/server-render-a-page.md +0 -81
  67. package/dist/docs/how-to/set-a-content-security-policy.md +0 -32
  68. package/dist/docs/how-to/set-up-mfa.md +0 -113
  69. package/dist/docs/how-to/switch-workspaces.md +0 -122
  70. package/dist/docs/how-to/upload-and-use-an-asset.mdx +0 -73
  71. package/dist/docs/how-to/validate-a-field.md +0 -52
  72. package/dist/docs/how-to/wait-for-an-action-response.md +0 -182
  73. package/dist/docs/how-to/write-a-condition.md +0 -45
  74. package/dist/docs/how-to/write-a-predicate.md +0 -60
  75. package/dist/docs/index.md +0 -59
  76. package/dist/docs/reference/dashboard/actions.mdx +0 -56
  77. package/dist/docs/reference/dashboard/api-keys.mdx +0 -38
  78. package/dist/docs/reference/dashboard/conditions.mdx +0 -42
  79. package/dist/docs/reference/dashboard/content/asset-library.mdx +0 -63
  80. package/dist/docs/reference/dashboard/content/blocks.mdx +0 -57
  81. package/dist/docs/reference/dashboard/content/content-entries.mdx +0 -95
  82. package/dist/docs/reference/dashboard/content/models.mdx +0 -108
  83. package/dist/docs/reference/dashboard/content/pages.mdx +0 -61
  84. package/dist/docs/reference/dashboard/experiences.mdx +0 -51
  85. package/dist/docs/reference/dashboard/external-apis.md +0 -169
  86. package/dist/docs/reference/dashboard/features.mdx +0 -154
  87. package/dist/docs/reference/dashboard/fields.mdx +0 -106
  88. package/dist/docs/reference/dashboard/flow-builder/canvas.mdx +0 -58
  89. package/dist/docs/reference/dashboard/flow-builder/condition-builder.md +0 -57
  90. package/dist/docs/reference/dashboard/flow-builder/keyboard-shortcuts.md +0 -72
  91. package/dist/docs/reference/dashboard/flow-builder/nodes.md +0 -63
  92. package/dist/docs/reference/dashboard/labels.md +0 -321
  93. package/dist/docs/reference/dashboard/lead-search.md +0 -224
  94. package/dist/docs/reference/dashboard/projects.mdx +0 -44
  95. package/dist/docs/reference/dashboard/reports.mdx +0 -43
  96. package/dist/docs/reference/dashboard/steps.mdx +0 -37
  97. package/dist/docs/reference/dashboard/team-management.md +0 -29
  98. package/dist/docs/reference/dashboard/workflow-runs.md +0 -142
  99. package/dist/docs/reference/dashboard/workflow-templates.md +0 -182
  100. package/dist/docs/reference/dashboard/workflow-test-runs.md +0 -77
  101. package/dist/docs/reference/dashboard/workspace-versioning.mdx +0 -30
  102. package/dist/docs/reference/dashboard/workspaces.mdx +0 -76
  103. package/dist/docs/reference/delivery-api/experience-content.md +0 -152
  104. package/dist/docs/reference/delivery-api/index.md +0 -45
  105. package/dist/docs/reference/delivery-api/preview-caching-crawling.md +0 -79
  106. package/dist/docs/reference/delivery-api/project-config.md +0 -65
  107. package/dist/docs/reference/delivery-api/workspace-schema.md +0 -107
  108. package/dist/docs/reference/glossary.md +0 -201
  109. package/dist/docs/reference/management-api/authentication.md +0 -87
  110. package/dist/docs/reference/management-api/authorization-and-scopes.md +0 -291
  111. package/dist/docs/reference/management-api/error-handling.md +0 -232
  112. package/dist/docs/reference/management-api/pagination.md +0 -192
  113. package/dist/docs/reference/pickedql/data-sources.md +0 -174
  114. package/dist/docs/reference/pickedql/dimensions.md +0 -103
  115. package/dist/docs/reference/pickedql/filtering.md +0 -64
  116. package/dist/docs/reference/pickedql/index.md +0 -18
  117. package/dist/docs/reference/pickedql/schema.md +0 -172
  118. package/dist/docs/reference/pickedql/virtual-functions.md +0 -248
  119. package/dist/docs/reference/sdk/actions.md +0 -154
  120. package/dist/docs/reference/sdk/analytics-events.md +0 -453
  121. package/dist/docs/reference/sdk/conditions.md +0 -147
  122. package/dist/docs/reference/sdk/content-security-policy.md +0 -21
  123. package/dist/docs/reference/sdk/content.md +0 -253
  124. package/dist/docs/reference/sdk/experiences.md +0 -51
  125. package/dist/docs/reference/sdk/features.md +0 -256
  126. package/dist/docs/reference/sdk/fields.md +0 -255
  127. package/dist/docs/reference/sdk/index.md +0 -68
  128. package/dist/docs/reference/sdk/plugins/create-experience.md +0 -123
  129. package/dist/docs/reference/sdk/plugins/dynamic-experiences.md +0 -74
  130. package/dist/docs/reference/sdk/plugins/index.md +0 -29
  131. package/dist/docs/reference/sdk/plugins/window-object.md +0 -25
  132. package/dist/docs/reference/sdk/predicates.md +0 -43
  133. package/dist/docs/reference/sdk/ssr/index.md +0 -33
  134. package/dist/docs/reference/sdk/ssr/rendering-and-hydration.md +0 -103
  135. package/dist/docs/reference/sdk/ssr/serialize.md +0 -80
  136. package/dist/docs/reference/sdk/ssr/slots-and-placements.md +0 -113
  137. package/dist/docs/reference/sdk/steps.md +0 -86
  138. package/dist/docs/reference/sdk/type-generation.md +0 -265
  139. package/dist/docs/reference/tools/chrome-extension.md +0 -16
  140. package/dist/docs/reference/tools/cli.md +0 -292
  141. package/dist/docs/reference/tools/image-optimisation-service.md +0 -104
  142. package/dist/docs/reference/tools/mcp.md +0 -136
  143. package/dist/docs/reference/tools/vite-plugin.md +0 -163
  144. package/dist/docs/tutorials/first-api-call.md +0 -235
  145. package/dist/docs/tutorials/first-experience-in-the-dashboard.mdx +0 -143
  146. package/dist/docs/tutorials/first-experience.mdx +0 -254
  147. package/dist/docs/tutorials/first-server-rendered-page.mdx +0 -186
@@ -1,81 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to server-render a page
7
-
8
- This guide shows you how to render a Picked Page on your server and hydrate it in the
9
- browser. You need a published Page and a server that renders React or Svelte.
10
-
11
- ## 1. Make the snapshot
12
-
13
- Create one client for each request, then call `serialize()`:
14
-
15
- ```ts
16
- import { createClient } from 'picked'
17
- import { serialize } from '@picked/client/server'
18
-
19
- const client = createClient(options)
20
-
21
- const snapshot = await serialize(client, {
22
- projectConfig,
23
- attributes: { location: { pathname: url.pathname } },
24
- })
25
- ```
26
-
27
- :::warning
28
- Give `serialize()` one client for each request. It does not support two calls at the same
29
- time on one client.
30
- :::
31
-
32
- ## 2. Embed the snapshot
33
-
34
- ```ts
35
- const html = `
36
- <div id="root">${appHtml}</div>
37
- <script>window.__PICKED__ = ${JSON.stringify(snapshot)}</script>
38
- `
39
- ```
40
-
41
- ## 3. Seed the client and render the slot
42
-
43
- :::code-group
44
-
45
- ```tsx [React]
46
- import { PickedProvider, ExperienceSlot } from '@picked/react'
47
-
48
- export function Page({ snapshot }) {
49
- return (
50
- <PickedProvider options={options} snapshot={snapshot}>
51
- <ExperienceSlot name="page" />
52
- </PickedProvider>
53
- )
54
- }
55
- ```
56
-
57
- ```svelte [Svelte]
58
- <script lang="ts">
59
- import { ExperienceSlot, setPickedContext } from '@picked/svelte'
60
-
61
- const { snapshot } = $props()
62
- setPickedContext({ options, snapshot })
63
- </script>
64
-
65
- <ExperienceSlot name="page" />
66
- ```
67
-
68
- :::
69
-
70
- The provider seeds the client at once, so the server HTML and the first paint match.
71
-
72
- ## 4. Point the experience at the slot
73
-
74
- Set the target selector of your Page experience to `.picked-slot-page`, then publish.
75
-
76
- ## Related
77
-
78
- - [About server-side rendering](/explanation/why-server-side-rendering) — why the
79
- snapshot carries condition results.
80
- - [Server snapshot](/reference/sdk/ssr/serialize) — every parameter.
81
- - [Your first server-rendered page](/tutorials/first-server-rendered-page).
@@ -1,32 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to set a Content Security Policy
7
-
8
- This guide shows you how to let the Picked SDK load its resources under a CSP.
9
-
10
- ## Steps
11
-
12
- Add the Picked domains to your policy.
13
-
14
- As an HTTP header:
15
-
16
- ```
17
- Content-Security-Policy: connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;
18
- ```
19
-
20
- Or as a `<meta>` tag:
21
-
22
- ```html
23
- <meta
24
- http-equiv="Content-Security-Policy"
25
- content="connect-src 'self' https://api.picked.app https://evnts.pckd.dev; img-src 'self' https://img.picked-content.com;"
26
- />
27
- ```
28
-
29
- ## Related
30
-
31
- - [Content Security Policy](/reference/sdk/content-security-policy) — what each domain is
32
- for.
@@ -1,113 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to set up MFA
7
-
8
- This guide shows you how to add an authenticator app to an account, and how to sign in
9
- with it. Picked supports TOTP authenticator apps only, such as Google Authenticator.
10
- Every MFA mutation needs authentication.
11
-
12
- ## Who must use MFA
13
-
14
- Picked staff, and every member of an organization that requires MFA, must sign in with an
15
- authenticator app. For these users, most operations return the error code `MFA_REQUIRED`
16
- until the session reaches `AAL2`. The operations that a session at `AAL1` can use are in
17
- [Authenticator assurance levels](/reference/management-api/authentication#authenticator-assurance-levels).
18
- The `user.mfa` field tells you where a user stands:
19
-
20
- ```graphql
21
- query {
22
- user {
23
- mfa { required reason enrolled satisfied }
24
- }
25
- }
26
- ```
27
-
28
- | Field | Meaning |
29
- | --- | --- |
30
- | `required` | The user must hold an `AAL2` session to use the fields that need it. |
31
- | `reason` | `STAFF` or `ORGANIZATION`. Empty when `required` is false. |
32
- | `enrolled` | The user holds a verified authenticator. |
33
- | `satisfied` | The session that made the request meets the requirement. |
34
-
35
- ## 1. Add an authenticator
36
-
37
- ```graphql
38
- mutation {
39
- mfaFactorEnroll(input: { friendlyName: "Work phone" }) {
40
- factor { id factorType status }
41
- totp { qrCode secret uri }
42
- }
43
- }
44
- ```
45
-
46
- A new factor has the status `UNVERIFIED`. Show `qrCode` (SVG markup) for the user to scan,
47
- or `secret` for the user to enter into the app. The API returns it one time only.
48
-
49
- Before it adds the factor, the mutation deletes the caller's factors that are not verified.
50
- But it keeps the two newest of these factors if they are less than 60 seconds old. A
51
- different setup can still use them, for example in a different browser tab. The mutation
52
- also deletes a factor that is not verified and has the `friendlyName` that you give.
53
- Therefore, a setup that did not finish does not stop a new setup.
54
-
55
- ## 2. Open a challenge
56
-
57
- ```graphql
58
- mutation {
59
- mfaChallengeCreate(input: { factorId: "factor-id" }) {
60
- challengeId
61
- expiresAt
62
- }
63
- }
64
- ```
65
-
66
- ## 3. Verify the code
67
-
68
- ```graphql
69
- mutation {
70
- mfaChallengeVerify(input: {
71
- factorId: "factor-id"
72
- challengeId: "challenge-id"
73
- code: "123456"
74
- }) {
75
- session { accessToken refreshToken aal }
76
- }
77
- }
78
- ```
79
-
80
- The session moves to `AAL2`, and the factor status changes to `VERIFIED`. Use the returned
81
- tokens from this point. A wrong code returns `MFA_CHALLENGE_FAILED`.
82
-
83
- ## Sign in with an authenticator
84
-
85
- After `sessionCreate`, the session is at `AAL1`. When `session.user.mfa.enrolled` is
86
- `true`, do steps 2 and 3 against one of the user's verified factors. The query
87
- `user { mfaFactors { id status } }` lists them. When `required` is `true` and `enrolled`
88
- is `false`, do steps 1 to 3.
89
-
90
- ## Remove an authenticator
91
-
92
- ```graphql
93
- mutation {
94
- mfaFactorUnenroll(input: { factorId: "factor-id" }) {
95
- success
96
- }
97
- }
98
- ```
99
-
100
- To remove a verified factor, the session must be at `AAL2`. An `AAL1` session receives
101
- `MFA_REQUIRED`.
102
-
103
- A user who must use MFA always keeps at least one authenticator. A request to remove
104
- their last one fails with `VALIDATION_ERROR`. To replace an authenticator, add the new
105
- one first, then remove the old one. A user with the `users/reset_mfa` scope clears the
106
- last one with `userMfaReset`.
107
-
108
- ## Related
109
-
110
- - [Authentication](/reference/management-api/authentication) — every mutation and the
111
- assurance levels.
112
- - [Authorization and scopes](/reference/management-api/authorization-and-scopes) — who
113
- can reset the MFA of another user.
@@ -1,122 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to switch workspaces
7
-
8
- This guide shows you how to point your local tooling at a different project or workspace.
9
- Your application then renders that workspace's content and types on your machine. It expects
10
- a `picked.config.ts` and the [CLI](/reference/tools/cli).
11
-
12
- Your tooling reads the project and surface named in the committed `picked.config.ts`. The
13
- CLI writes your choice to `.picked/settings.json` instead. That file is per-developer and
14
- Git ignores it, so the committed default stays as it is and one command puts it back.
15
-
16
- See [Workspaces](/reference/dashboard/workspaces) for what Live, Draft, and Archived mean.
17
-
18
- ## 1. Sign in
19
-
20
- ```bash
21
- picked login
22
- ```
23
-
24
- This opens your browser for a one-time OAuth sign-in and stores a session under
25
- `~/.picked/`. Confirm it with `picked whoami`. See
26
- [CLI authentication](/how-to/authenticate-the-cli).
27
-
28
- ## 2. Find a workspace
29
-
30
- ```bash
31
- picked workspace list
32
- ```
33
-
34
- ```
35
- Acme Corp. (acme-corporation)
36
- Storefront [proj_a1b2]
37
- Default Storefront [LIVE] (live)
38
- Checkout rework [DRAFT]
39
- ```
40
-
41
- Note the **project id** (`proj_a1b2`) and the name or the id of the workspace you want.
42
-
43
- ## 3. Switch to the draft
44
-
45
- ```bash
46
- picked workspace use --project proj_a1b2 --workspace ws_draft
47
- ```
48
-
49
- ```
50
- Active workspace: Checkout rework [DRAFT] in project proj_a1b2 (source: preview)
51
- Generated types at /app/src/picked-env.d.ts
52
- ```
53
-
54
- A command that names **one specific workspace** (draft, live, or archived):
55
-
56
- - writes the selection (and its [preview token](/reference/delivery-api/preview-caching-crawling)) to
57
- `.picked/settings.json`,
58
- - switches the resolved `source` to `preview` for that project, and
59
- - regenerates `picked-env.d.ts` from that workspace's schema (skip with `--no-generate`).
60
-
61
- To browse instead, run `picked workspace use` with no flags. The interactive picker lists
62
- every project, with **Published (live version)** and each of its workspaces.
63
-
64
- ## 4. See the draft in your app
65
-
66
- Both readers of the selection use `.picked/settings.json` with no change to your
67
- configuration:
68
-
69
- - **Type generation** now reads the draft schema. Rerun `picked generate types` after more
70
- edits.
71
- - The **[Vite plugin](/reference/tools/vite-plugin)** reads the draft's configuration and
72
- content in development and in a build. It sends the preview token to the
73
- [Delivery API](/reference/delivery-api). Restart the dev server to apply a switch.
74
-
75
- Your application renders the unpublished draft on your machine, with types.
76
-
77
- ## 5. Switch back to live
78
-
79
- ```bash
80
- picked workspace use --project proj_a1b2
81
- ```
82
-
83
- A command that names a project with no `--workspace`, or **Published (live version)** in the
84
- picker, discards the preview token and returns `source` to `published`. To confirm what is
85
- active:
86
-
87
- ```bash
88
- picked status
89
- ```
90
-
91
- ```
92
- Config default: project proj_a1b2 (source: published)
93
- Active selection: none (using the config default).
94
- ```
95
-
96
- ## CI and headless runs
97
-
98
- `.picked/settings.json` is a local, per-developer file. Do not commit it. To choose one
99
- workspace in CI with no selection file, set the environment directly:
100
-
101
- ```bash
102
- PICKED_PROJECT_ID=proj_a1b2 \
103
- PICKED_PREVIEW_TOKEN="$DRAFT_TOKEN" \
104
- picked generate types --check
105
- ```
106
-
107
- `PICKED_PREVIEW_TOKEN` applies only when the resolved `source` is `preview`. See the
108
- [CLI environment variables](/reference/tools/cli#environment-variables) for the full
109
- precedence order.
110
-
111
- :::note
112
- A preview token is a long-lived credential for one workspace. Keep it out of the version
113
- control system, as you do with each other credential. Git ignores `.picked/settings.json`
114
- for this reason, because `picked workspace use` writes a token there.
115
- :::
116
-
117
- ## Related
118
-
119
- - [CLI](/reference/tools/cli) — every command and flag.
120
- - [Workspaces](/reference/dashboard/workspaces) — Live, Draft, and Archived states.
121
- - [Type generation](/reference/sdk/type-generation) — how the schema becomes types.
122
- - [Preview, cache, and crawlers](/reference/delivery-api/preview-caching-crawling) — preview tokens on the Delivery API.
@@ -1,73 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- import { Screenshot } from '../../../components/Screenshot'
7
-
8
- # How to upload and use an asset
9
-
10
- This guide shows you how to put a file in the asset library and point at it from your
11
- content.
12
-
13
- ## 1. Add the field to a layout
14
-
15
- Two field types point at the library:
16
-
17
- - An **Asset** field takes an image, a video, or a document.
18
- - An **HTML** field takes a `.html` file.
19
-
20
- Add one of them to a page layout or a step layout.
21
-
22
- ## 2. Choose a file
23
-
24
- 1. Open the content entry.
25
- 2. Click **Choose file** on the asset field. On a field that holds a value already, click
26
- **Replace**.
27
- 3. Open the **Upload** tab to add a new file.
28
- 4. Open the **Library** tab to use a file that is there already.
29
- 5. Choose your asset.
30
-
31
- <Screenshot
32
- route="/{orgSlug}/{projectId}/design-systems/new"
33
- wait='button:has-text("Upload file")'
34
- click='button:has-text("Upload file")'
35
- selector="[role=dialog]"
36
- alt="The asset picker modal on the Picked dashboard, with the Library tab, its search box, its type filter, and its Sort menu"
37
- renderWidth={1072}
38
- renderHeight={790}
39
- />
40
-
41
- <Screenshot
42
- route="/{orgSlug}/{projectId}/design-systems/new"
43
- wait='button:has-text("Upload file")'
44
- click='button:has-text("Upload file")'
45
- selector="[role=dialog]"
46
- alt="The asset picker modal on the Picked dashboard, with the Library tab, its search box, its type filter, and its Sort menu"
47
- renderWidth={1072}
48
- renderHeight={790}
49
- />
50
-
51
- The detail panel on the right shows the kind, the dimensions, the size, and the upload
52
- date.
53
-
54
- ## 3. Find an asset in a large library
55
-
56
- The **Library** tab has three controls, and the server applies each one across the whole
57
- library:
58
-
59
- - **Search by name** narrows the list by file name while you type.
60
- - The type filter narrows the list to one media type. **All types** is the default.
61
- - **Sort** orders the list by **Name**, **Date created**, or **Date updated**.
62
-
63
- Click **Load more** at the bottom to read the next page of results.
64
-
65
- :::tip
66
- Each row has an **Open in new tab** control. Use it to check an asset again before you
67
- choose it. Your choice in the picker stays as it is.
68
- :::
69
-
70
- ## Related
71
-
72
- - [Asset library](/reference/dashboard/content/asset-library) — the limits, the file
73
- types, and how Picked serves an uploaded file.
@@ -1,52 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to validate a field
7
-
8
- This guide shows you how to check what a visitor enters. Write the rule in JSON Logic. The
9
- `$input` variable holds the current value of the field.
10
-
11
- ## Steps
12
-
13
- Add a `validation` rule to `createField()`:
14
-
15
- ```ts
16
- import { createField } from '@picked/client/plugins/create-experience'
17
-
18
- const quantityField = createField({
19
- id: 'quantity',
20
- name: 'quantity',
21
- type: 'number',
22
- label: 'Quantity',
23
- multiple: false,
24
- required: true,
25
- validation: {
26
- catch: {
27
- or: [
28
- {
29
- and: [
30
- { '>': [{ var: '$input' }, 0] },
31
- { '<=': [{ var: '$input' }, 999] },
32
- ],
33
- },
34
- { throw: 'Please enter a value between 1 and 999' },
35
- ],
36
- },
37
- },
38
- })
39
- ```
40
-
41
- :::tip
42
- The `catch` and `throw` pattern checks that the condition gives `true`. When it does not,
43
- the SDK shows the `throw` message to your visitor.
44
- :::
45
-
46
- The SDK runs the rule on blur and on submit.
47
-
48
- ## Related
49
-
50
- - [SDK fields](/reference/sdk/fields) — every field option.
51
- - [About conditions and the logic engine](/explanation/conditions-and-the-logic-engine) —
52
- the rule format.
@@ -1,182 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to wait for the response of an action
7
-
8
- This guide shows you how to run an action from your application and show its response. You
9
- need an action in your project first, with a key and a workflow that the action starts. See
10
- [Actions](/reference/dashboard/actions).
11
-
12
- The response is the value that the action returns. For an action that starts a workflow in
13
- Picked, the response is the payload of the **Action response** node in the workflow.
14
-
15
- ## 1. Generate the types of your project
16
-
17
- Run type generation. The generated types name the actions that start a workflow. For those
18
- keys, the types of `useAction` and `getAction` include `run`. At runtime, the value includes
19
- `run` for each key. See [Type generation](/reference/sdk/type-generation).
20
-
21
- ## 2. Bind the action to a component
22
-
23
- Call `useAction` in React, or `getAction` in Svelte. Neither runs the action. The action runs
24
- only when you call `run`. The action receives the arguments of `run` in `args`.
25
-
26
- All the components that use the same key and the same experience share one run state. When
27
- one of them calls `run`, all of them show that run.
28
-
29
- :::code-group
30
-
31
- ```tsx [React]
32
- import { useAction } from '@picked/react/hooks'
33
-
34
- function CallbackButton() {
35
- const callback = useAction('request-callback')
36
-
37
- return (
38
- <button onClick={() => void callback.run()} disabled={callback.status === 'running'}>
39
- Get a call back
40
- </button>
41
- )
42
- }
43
- ```
44
-
45
- ```svelte [Svelte]
46
- <script lang="ts">
47
- import { getAction } from '@picked/svelte/hooks'
48
-
49
- const callback = getAction('request-callback')
50
- </script>
51
-
52
- <button onclick={() => $callback.run()} disabled={$callback.status === 'running'}>
53
- Get a call back
54
- </button>
55
- ```
56
-
57
- :::
58
-
59
- ## 3. Show the response
60
-
61
- Read `status`, `response` and `error` for the last run. Compare `response` with the values
62
- that your workflow sends.
63
-
64
- :::code-group
65
-
66
- ```tsx [React]
67
- import { useAction } from '@picked/react/hooks'
68
-
69
- // Reads the status that the workflow sends in its response.
70
- function answerStatus(response: unknown): unknown {
71
- return typeof response === 'object' && response !== null && 'status' in response
72
- ? response.status
73
- : undefined
74
- }
75
-
76
- function CallbackButton() {
77
- const callback = useAction('request-callback')
78
-
79
- if (callback.status === 'failed') return <p>We could not send your request.</p>
80
- if (callback.status === 'succeeded') {
81
- if (answerStatus(callback.response) === 'closed') {
82
- return <p>We call back on weekdays, 8 am to 5 pm.</p>
83
- }
84
- return <p>Thank you. We will call you soon.</p>
85
- }
86
-
87
- return (
88
- <button onClick={() => void callback.run()} disabled={callback.status === 'running'}>
89
- Get a call back
90
- </button>
91
- )
92
- }
93
- ```
94
-
95
- ```svelte [Svelte]
96
- <script lang="ts">
97
- import { getAction } from '@picked/svelte/hooks'
98
-
99
- const callback = getAction('request-callback')
100
-
101
- // Reads the status that the workflow sends in its response.
102
- function answerStatus(response: unknown): unknown {
103
- return typeof response === 'object' && response !== null && 'status' in response
104
- ? response.status
105
- : undefined
106
- }
107
- </script>
108
-
109
- {#if $callback.status === 'failed'}
110
- <p>We could not send your request.</p>
111
- {:else if $callback.status === 'succeeded' && answerStatus($callback.response) === 'closed'}
112
- <p>We call back on weekdays, 8 am to 5 pm.</p>
113
- {:else if $callback.status === 'succeeded'}
114
- <p>Thank you. We will call you soon.</p>
115
- {:else}
116
- <button onclick={() => $callback.run()} disabled={$callback.status === 'running'}>
117
- Get a call back
118
- </button>
119
- {/if}
120
- ```
121
-
122
- :::
123
-
124
- `run` does not reject. It resolves to `{ status: 'succeeded', response }` or to
125
- `{ status: 'failed', error }`.
126
-
127
- ## 4. Run the action outside a component
128
-
129
- Call `client.actions.run` with the action key. It resolves to the response, and it rejects
130
- when the action fails.
131
-
132
- The client registers the actions of your project when it loads the configuration of your
133
- project. For this, the client must have `dynamicExperiencesPlugin`, and you must start the
134
- client. Until the client is ready, `run` rejects with `Action '<key>' is not registered`. A
135
- handler that your application registers in `createClient({ actions })` is available
136
- immediately.
137
-
138
- ```ts
139
- import { createClient } from 'picked'
140
- import { dynamicExperiencesPlugin } from '@picked/client/plugins/dynamic-experiences'
141
-
142
- const picked = createClient({
143
- projectId: 'your-project-id',
144
- plugins: [dynamicExperiencesPlugin()],
145
- })
146
-
147
- picked.start()
148
-
149
- // Waits until the client is ready.
150
- async function whenReady(): Promise<void> {
151
- if (picked.readyStore.getState()) return
152
-
153
- await new Promise<void>((resolve) => {
154
- const subscription = picked.readyStore.updates.watch((ready) => {
155
- if (!ready) return
156
- subscription.unsubscribe()
157
- resolve()
158
- })
159
- })
160
- }
161
-
162
- async function requestCallback(): Promise<void> {
163
- await whenReady()
164
-
165
- try {
166
- const response = await picked.actions.run('request-callback', { timeoutMs: 15_000 })
167
- console.info('Callback response', response)
168
- } catch (error) {
169
- console.warn('Callback request failed', error)
170
- }
171
- }
172
- ```
173
-
174
- Set `timeoutMs` to stop the wait sooner. Set `signal` to stop the wait from your own code.
175
-
176
- ## Related
177
-
178
- - [SDK actions](/reference/sdk/actions) — every outcome, error and limit.
179
- - [How to register an action handler](/how-to/register-an-action-handler) — return a
180
- response from your own handler.
181
- - [How to call an external API from a workflow](/how-to/call-an-external-api-from-a-workflow)
182
- — a workflow that sends a response.
@@ -1,45 +0,0 @@
1
- ---
2
- type: how-to
3
- layout: docs
4
- ---
5
-
6
- # How to write a condition
7
-
8
- This guide shows you how to build a rule in the visual condition builder. The builder
9
- appears on a condition node, on an experience condition, on an initialize-open condition,
10
- and on a field option.
11
-
12
- ## Steps
13
-
14
- 1. Choose the node or the field that takes the condition.
15
- 2. Find the **Logic** section in the inspector.
16
- 3. Choose a data source: **Responses**, **Actions**, **Feature flags**, **Conditions**,
17
- or **Window Location**.
18
- 4. Choose an operator. The choices include equals, not equals, greater than, and
19
- contains.
20
- 5. Enter a value.
21
-
22
- ## Join more than one rule
23
-
24
- 1. Create an AND group or an OR group.
25
- 2. Add your rules inside it.
26
-
27
- With **AND** every rule must match. With **OR** one rule must match. Put a group inside
28
- another group to build a larger rule.
29
-
30
- ## Example
31
-
32
- To show a step only to a visitor who is on one page and who accepted marketing:
33
-
34
- 1. Create an AND group.
35
- 2. Add a rule: **Window Location → pathname** equals `/pricing`.
36
- 3. Add a rule: **Responses → `marketing_opt_in`** equals `true`.
37
-
38
- The group matches only when both rules are true.
39
-
40
- ## Related
41
-
42
- - [About conditions and the logic engine](/explanation/conditions-and-the-logic-engine) —
43
- what a rule can read.
44
- - [Condition builder](/reference/dashboard/flow-builder/condition-builder) — the rule
45
- structure.