@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,103 +0,0 @@
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)
@@ -1,80 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Server Snapshot
7
-
8
- `serialize()` finds which experiences match a URL and reads their content on the
9
- server. It returns a snapshot as plain JSON, and you pass that snapshot to the
10
- client.
11
-
12
- ## The `serialize(client, params)` function
13
-
14
- ```ts
15
- import { createClient } from 'picked'
16
- import { serialize } from '@picked/client/server'
17
-
18
- const client = createClient(options)
19
-
20
- const snapshot = await serialize(client, {
21
- projectConfig,
22
- attributes: { location: { pathname: '/promo' } },
23
- })
24
- ```
25
-
26
- `serialize()` does this. It registers the project configuration on the client at once. It
27
- evaluates the condition of each experience against `attributes.location`. It reads
28
- the content for each experience whose steps point at layout content. It removes the
29
- duplicate content blobs, which it finds by their IDs. It then returns a `PickedSnapshot`.
30
-
31
- The content that it reads holds the entries of the steps. It also holds the entries that
32
- a [reference field](/reference/dashboard/content/models#reference-fields) reaches.
33
-
34
- Give `serialize()` one client for each request. It does not support two calls at the
35
- same time on one client.
36
-
37
- ```ts
38
- serialize(client: Picked, params: SerializeParams): Promise<PickedSnapshot>
39
- ```
40
-
41
- ## Parameters
42
-
43
- | Parameter | Type | Default | Description |
44
- | --- | --- | --- | --- |
45
- | `projectConfig` | `ProjectConfig` | required | The published configuration, or the preview configuration, to register and choose against. |
46
- | `attributes.location` | `Partial<SerializeLocation>` | none | The URL fields that go into the selection context, such as `pathname`. |
47
- | `getContent` | `SerializeGetContent` | runtime API | Your own function to read content, in place of the runtime API. |
48
- | `previewToken` | `string` | none | The SDK sends this with the content request, so that preview content resolves during a preview render. |
49
- | `timeoutMs` | `number` | `10000` | The limit for each content request. After the limit, the SDK skips that blob and continues. |
50
-
51
- `SerializeLocation` carries the URL fields `href`, `pathname`, `search`, `hostname`,
52
- `origin`, `protocol`, `port`, `host`, and `hash`. Pass only the fields that your
53
- conditions read.
54
-
55
- ## The snapshot
56
-
57
- ```ts
58
- interface PickedSnapshot {
59
- versionId: string | null
60
- projectConfig: ProjectConfig
61
- content: ContentBlob[]
62
- conditionResults: Record<string, boolean>
63
- }
64
- ```
65
-
66
- | Field | Description |
67
- | --- | --- |
68
- | `versionId` | The project version that the snapshot was chosen against. It is `null` when the version is not known, for example in a preview. |
69
- | `projectConfig` | The options that the server chose with. They travel to the client, so that the client renders against exactly the same options. |
70
- | `content` | The content blobs for the chosen experiences, with the duplicates removed. It holds the entries of the steps, and every entry that a reference field reaches. The server render and the first paint in the browser therefore resolve the same pointers. |
71
- | `conditionResults` | The condition results that the server kept, under a key made from the rule hash. The client then reuses the choice of the server. |
72
-
73
- The snapshot is plain JSON. Write it into your HTML response with `JSON.stringify`
74
- and read it back on the client.
75
-
76
- ## Related
77
-
78
- - [How to server-render a page](/how-to/server-render-a-page)
79
- - [How to render an unpublished preview](/how-to/render-an-unpublished-preview)
80
- - [Content](/reference/sdk/content) — how to read a content record in a component.
@@ -1,113 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Slots and Placements
7
-
8
- A slot is a named mount point. `<ExperienceSlot name="page" />` renders every
9
- experience that points at that slot and whose condition matches.
10
-
11
- ## What a slot is
12
-
13
- The `name` of a slot points at the `.picked-slot-<name>` selector. So
14
- `<ExperienceSlot name="page" />` renders every experience with the target selector
15
- `.picked-slot-page`, when the condition of that experience is active.
16
-
17
- The slot reads the active state of each experience from the seeded snapshot. It
18
- therefore renders at once, both in server-side rendering and at the first paint of
19
- the hydration.
20
-
21
- ```tsx
22
- <ExperienceSlot name="page" />
23
- ```
24
-
25
- ## Props
26
-
27
- | Prop | Type | Default | Description |
28
- | --- | --- | --- | --- |
29
- | `name` | `string` | — | The name of the slot. It points at the `.picked-slot-<name>` selector. |
30
- | `open` | `'rule' \| 'rendered'` | `'rule'` | What an experience does when its `initializeOpen` is empty. `'rule'` keeps it closed. `'rendered'` opens it. A boolean or a rule in `initializeOpen` has the same result with both values. |
31
- | `wrap` | `boolean` | `false` | Puts the output of each experience in a wrapper element. See [The wrapper](#the-wrapper). |
32
-
33
- The slot reads `open` when it mounts an experience.
34
-
35
- ## Point an experience at a slot
36
-
37
- Set the target selector of the experience to `.picked-slot-<name>`. An experience
38
- that points at `.picked-slot-page` renders into `<ExperienceSlot name="page" />`. The
39
- name of the slot and the end of the selector must match.
40
-
41
- ## Placement order
42
-
43
- When more than one experience points at the same slot, they render in this placement
44
- order:
45
-
46
- ```
47
- replace -> before -> prepend -> append -> after
48
- ```
49
-
50
- `replace` wins. An active experience with the `replace` placement renders alone, and
51
- it replaces every other match in the slot. In every other case each active experience
52
- renders, in placement order.
53
-
54
- ## More than one experience in one slot
55
-
56
- The slot collects each experience that points at its selector. It drops each one
57
- whose condition is not active. It then sorts the rest into placement order. When a `replace`
58
- experience is among the active ones, only that experience renders. With no active
59
- `replace`, the slot renders every active experience in the order `before`, `prepend`,
60
- `append`, `after`.
61
-
62
- One Page can therefore take a whole slot with `replace`, while another slot holds
63
- several experiences that use the other placements. A condition decides which
64
- experiences are active. See [Conditions](/reference/dashboard/conditions).
65
-
66
- ## Lifecycle events
67
-
68
- The slot sends these events on the event bus of the client for each experience that it
69
- renders. It sends them only in the browser, and only after the client is ready. The server
70
- render sends no events.
71
-
72
- | Bus event | When it fires | Analytics event |
73
- | --- | --- | --- |
74
- | `experience_initialize` | The slot mounts the experience. | `experience_load` |
75
- | `experience_open` | The experience opens. `open` and `initializeOpen` decide this. | `app_open` |
76
- | `step_enter` | The flow of an open experience arrives at a step. | `step_enter` |
77
- | `experience_unmount` | The slot stops rendering the experience. | None |
78
-
79
- When the slot stops rendering an experience, the open state of that experience does not
80
- change. The slot therefore sends no `experience_close`, and the analytics plugin sends no
81
- `app_close`. After that, the experience sends no events, and its flow stops.
82
-
83
- Each time that the slot mounts an experience, the experience starts closed, and `open` and
84
- `initializeOpen` decide again if it opens. This is also true when the slot mounts the same
85
- experience again, for example after a React `<Activity>` shows it again.
86
-
87
- The flow of an experience continues from its history. When the history of an experience
88
- already ends at a step, the experience opens at that step and the slot sends no
89
- `step_enter` for it.
90
-
91
- Each analytics event has the page URL at the time that the event fires.
92
-
93
- ## The wrapper
94
-
95
- With `wrap`, the slot puts the output of each experience in one element:
96
-
97
- ```html
98
- <div data-picked-experience-id="<experience id>" style="display: contents">
99
- <!-- the experience -->
100
- </div>
101
- ```
102
-
103
- The element has no box of its own, so the layout does not change. The element is in the
104
- document tree, so the selectors `>`, `:first-child`, and `:nth-child()` see it. The
105
- `data-picked-experience-id` attribute holds the ID of the experience. It is the same on the
106
- server and in the browser.
107
-
108
- Without `wrap`, the slot adds no element.
109
-
110
- ## Related
111
-
112
- - [About server-side rendering](/explanation/why-server-side-rendering) — why placements
113
- have an order.
@@ -1,86 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Steps
7
-
8
- Render your steps with `<StepRouter>` and `<Step>` from `@picked/react` or
9
- `@picked/svelte`. Reach the active step through `useStep()` or `getStep()`.
10
-
11
- ## Reach the step context
12
-
13
- Inside a `Step` component, or inside any component that a `Step` renders, call
14
- `getStep()` or `useStep()` to reach the reactive context of the step:
15
-
16
- :::code-group
17
-
18
- ```tsx [React]
19
- import { useStep, useStoreGlobal } from '@picked/react/hooks'
20
-
21
- function ContactForm() {
22
- const { step, fields } = useStep()
23
- const currentStep = useStoreGlobal(step)
24
- const currentFields = useStoreGlobal(fields)
25
-
26
- return (
27
- <>
28
- <h1>{currentStep.label}</h1>
29
-
30
- {currentFields.map((field) => (
31
- <div key={field.id}>
32
- <label>{field.label}</label>
33
- <input
34
- name={field.id}
35
- value={field.value ?? ''}
36
- onChange={field.onChange}
37
- onBlur={field.onBlur}
38
- />
39
- {field.error && field.touched && <p className="error">{field.error.userMessage}</p>}
40
- </div>
41
- ))}
42
- </>
43
- )
44
- }
45
- ```
46
-
47
- ```svelte [Svelte]
48
- <script lang="ts">
49
- import { getStep } from '@picked/svelte/hooks'
50
-
51
- const { step, fields } = getStep()
52
- </script>
53
-
54
- <h1>{$step.label}</h1>
55
-
56
- {#each $fields as field}
57
- <label>{field.label}</label>
58
- <input
59
- name={field.id}
60
- value={field.value ?? ''}
61
- onchange={field.onChange}
62
- onblur={field.onBlur}
63
- />
64
- {#if field.error && field.touched}
65
- <p class="error">{field.error.userMessage}</p>
66
- {/if}
67
- {/each}
68
- ```
69
-
70
- :::
71
-
72
- `getStep()` in Svelte, and `useStep()` in React, return a `StepContext` with these
73
- properties:
74
-
75
- | Property | Type | Description |
76
- | ---------- | --------------------------------------------- | ------------------------------------------------------------------------------ |
77
- | `step` | `Store<ExperienceStep>` | A reactive store that holds the `id` and the `label` of the step |
78
- | `fields` | `Store<FormField[]>` | A reactive store of the fields, with their current values, errors, and handlers |
79
- | `isActive` | `Store<boolean>` (Svelte) / `boolean` (React) | Whether the router holds this step as the active one |
80
- | `form` | Object | The handlers for a form submission. See [Forms](#forms). |
81
-
82
- ## Related
83
-
84
- - [How to render a step form](/how-to/render-a-step-form)
85
- - [How to run code on a form submission](/how-to/run-code-on-a-form-submission)
86
- - [About how Picked works](/explanation/how-picked-works) — why a flow is a graph.
@@ -1,265 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Type Generation
7
-
8
- Picked can generate TypeScript types from your workspace schema so field values, feature keys, content models, and step layouts are typed in your app.
9
-
10
- ## Quick start
11
-
12
- ### 1. Add `picked.config.ts`
13
-
14
- Create a `picked.config.ts` in your project root:
15
-
16
- ```typescript
17
- import { defineConfig } from 'picked/config'
18
-
19
- export default defineConfig({
20
- projectId: 'your-project-id',
21
- typesOutput: './src/picked-env.d.ts',
22
- })
23
- ```
24
-
25
- | Option | Description |
26
- | --- | --- |
27
- | `projectId` | **Required.** Your Picked project id. |
28
- | `typesOutput` | Path for generated types (defaults to `./src/picked-env.d.ts`). |
29
- | `source` | Schema surface to type against: `'published'` (default) or `'preview'`. |
30
- | `previewToken` | Workspace preview token. Required when `source` is `'preview'`, and read only then. |
31
-
32
- The `source` value matches the `x-picked-source` field on the [workspace schema](/reference/delivery-api/workspace-schema) document — it controls whether tooling fetches the published or preview workspace shape.
33
-
34
- A preview token reads one workspace, and it does not expire. Leave both `source` and
35
- `previewToken` out of the committed file, and pick a workspace instead:
36
-
37
- ```bash
38
- picked login
39
- picked workspace use
40
- ```
41
-
42
- That writes the choice, and that workspace's token, to `.picked/settings.json`, which is
43
- per-developer and which Git ignores. Each developer points at their own workspace, and the
44
- committed file holds no token.
45
-
46
- You can also set the values here. Every developer then reads the same workspace:
47
-
48
- ```typescript
49
- export default defineConfig({
50
- projectId: 'your-project-id',
51
- source: 'preview',
52
- previewToken: 'the-workspace-preview-token',
53
- })
54
- ```
55
-
56
- Three places can give the token. Tooling reads the first of them that has one: the
57
- `PICKED_PREVIEW_TOKEN` environment variable, then the workspace that
58
- [`picked workspace use`](/reference/tools/cli) chose, then this `previewToken` option.
59
-
60
- ### 2. Enable the Vite plugin (recommended)
61
-
62
- If you use Vite, add `@picked/vite-plugin-picked`. Type generation runs automatically on `dev` and `build` when `generateTypes` is enabled (the default):
63
-
64
- ```typescript
65
- import { picked } from '@picked/vite-plugin-picked'
66
-
67
- export default defineConfig({
68
- plugins: [picked()],
69
- })
70
- ```
71
-
72
- The project id comes from `picked.config.ts`. A failure stops the
73
- run. See [the plugin reference](/reference/tools/vite-plugin) for `generateTypes` and every
74
- other option.
75
-
76
- ### 3. Or use the CLI
77
-
78
- Install [`picked`](/reference/tools/cli) and run:
79
-
80
- ```bash
81
- picked generate types
82
- ```
83
-
84
- ## Keep the types current
85
-
86
- Commit `picked-env.d.ts`. A workspace changes after you commit it, so the file goes stale,
87
- and stale types describe fields your workspace no longer has.
88
-
89
- Run this check in CI, next to your other checks:
90
-
91
- ```bash
92
- picked generate types --check
93
- ```
94
-
95
- `--check` writes no file. It reads the live workspace schema and compares it with the
96
- committed file. A match gives status `0`. A difference gives status `1` and names the file:
97
-
98
- ```
99
- Types are out of date: /home/runner/work/your-app/src/picked-env.d.ts
100
- ```
101
-
102
- To clear it, run `picked generate types` and commit the result. The check reads no cached
103
- schema, so an API it cannot reach fails the check.
104
-
105
- :::note
106
- `--check` reads the workspace that the resolved configuration names. A CI run that has no
107
- `.picked/settings.json` reads the workspace your committed `picked.config.ts` names.
108
- :::
109
-
110
- ## Workspace selection
111
-
112
- Tooling reads `projectId` and `source` from your committed `picked.config.ts`. The Picked [CLI](/reference/tools/cli) points that tooling at a different project or a draft workspace, and leaves the file as it is. It writes the selection to `.picked/settings.json`, which is per-developer and which Git ignores. That selection supersedes the committed default.
113
-
114
- See [How to switch workspaces](/how-to/switch-workspaces) for the full set of steps.
115
-
116
- ## Generated output
117
-
118
- The generated `picked-env.d.ts` file looks like:
119
-
120
- ```typescript
121
- // GENERATED by `@picked/typegen` — do not edit by hand.
122
- // Reference: `https://docs.picked.app/reference/sdk/type-generation`
123
-
124
- export type WelcomePage = { /* ... */ }
125
- export type FieldValues = { /* ... */ }
126
- export type FeatureKey =
127
- | 'default'
128
- | 'hero'
129
- | 'winter-sale'
130
-
131
- declare module '@picked/client' {
132
- interface PickedSchemaRegistry {
133
- contentModels: {
134
- 'welcome-page': WelcomePage
135
- }
136
- stepContentModels: {
137
- 'intro': 'welcome-page'
138
- }
139
- featureValues: {
140
- 'hero':
141
- | false
142
- | 'hero-a'
143
- | 'hero-b'
144
- }
145
- fieldValues: FieldValues
146
- featureKeys: FeatureKey
147
- }
148
- }
149
- ```
150
-
151
- Commit this file to the version control system, or regenerate it in CI after you publish a workspace change.
152
-
153
- ### Feature flag values
154
-
155
- A Text feature flag declares the values that it can serve, so `useFeatureResult` narrows
156
- the bucket to those values:
157
-
158
- ```typescript
159
- const result = useFeatureResult('hero')
160
- ```
161
-
162
- The `bucket` property then has the type `false | 'hero-a' | 'hero-b'`.
163
-
164
- `featureValues` holds the Text feature flags alone. A Boolean feature flag, and a feature
165
- flag that your application defines, both keep the general `boolean | string` type. The
166
- `FeatureValueFor<'hero'>` type gives the same union on its own.
167
-
168
- ### Assets
169
-
170
- An `asset` field is a union. An asset that the API finds has a `url`, and an asset that
171
- it does not find has no `url`.
172
- [Field values](/reference/delivery-api/workspace-schema#field-values) gives the two shapes.
173
- The `in` operator narrows the union:
174
-
175
- ```tsx
176
- const image = page.hero_image
177
-
178
- return 'url' in image ? <img src={image.url} width={image.width ?? undefined} alt="" /> : null
179
- ```
180
-
181
- ### Content blocks
182
-
183
- Each block type has a `contentBlockKey` property whose type is the key of the block. A
184
- `switch` on that property gives the `data` type of each block:
185
-
186
- ```tsx
187
- for (const section of page.sections ?? []) {
188
- switch (section.contentBlockKey) {
189
- case 'faq':
190
- renderFaq(section.data.items)
191
- break
192
- case 'hero':
193
- renderHero(section.data.headline)
194
- break
195
- }
196
- }
197
- ```
198
-
199
- ### The model of a record
200
-
201
- `isContentOfModel(record, key)` from `@picked/client` returns `true` when the
202
- `contentModelKey` of the record is `key`. In that branch, `record.data` has the generated
203
- type of the model. `ContentRecordOf<'landing-page'>` gives the same record type, and
204
- `ContentModelKeys` holds the keys of the models in the workspace.
205
-
206
- In this example, one component renders the layouts of two models:
207
-
208
- ```tsx
209
- import { isContentOfModel } from '@picked/client'
210
- import { useStepLayoutContent } from '@picked/react/hooks'
211
-
212
- export function Page() {
213
- const record = useStepLayoutContent()
214
-
215
- if (record && isContentOfModel(record, 'landing-page')) {
216
- return <LandingPage content={record.data} />
217
- }
218
-
219
- if (record && isContentOfModel(record, 'standard-page')) {
220
- return <StandardPage content={record.data} />
221
- }
222
-
223
- return null
224
- }
225
- ```
226
-
227
- The check reads `contentModelKey` only. It does not validate `data` against the model.
228
-
229
- ## Keys the application defines
230
-
231
- An application can define a feature, an action, a field, a step, or an experience of its
232
- own. It does this through `createClient` options or through a `register` method. The
233
- workspace has no record of such a key, so the generated types have none either.
234
-
235
- A hook still accepts one. Each key type holds the keys of the workspace and any other
236
- string. Your editor shows the workspace keys, and no local key is an error:
237
-
238
- ```typescript
239
- useFeature('winter-sale') // from the workspace, and suggested
240
- useFeature('summer-sales-experiment') // from createClient, and accepted
241
- ```
242
-
243
- Each key type has a `Known` form that holds the workspace keys alone —
244
- `KnownFeatureKeys`, `KnownActionKeys`, `KnownFieldKeys`, `KnownStepKeys`, and
245
- `KnownExperienceKeys`. Use one where you want the workspace set and nothing else.
246
-
247
- ## Actions that start a workflow
248
-
249
- `WorkflowActionKeys` holds the keys of the actions that start a workflow in the workspace. For one
250
- of these keys, the types of `useAction` and `getAction` give `run`, `status`, `response` and
251
- `error`. For every other key, the types give the action as a function. Without generated types,
252
- and with a schema that has no such actions, `WorkflowActionKeys` is `never`. See
253
- [Actions](/reference/sdk/actions).
254
-
255
- ## Cache
256
-
257
- Type generation writes its artefacts under `.picked/`: the schema JSON and a manifest. The first run adds this directory to `.gitignore` for you.
258
-
259
- ## Related
260
-
261
- - [CLI](/reference/tools/cli) — commands, authentication, and environment variables.
262
- - [How to switch workspaces](/how-to/switch-workspaces) — read a draft workspace on your machine.
263
- - [Vite plugin](/reference/tools/vite-plugin) — the build-time prefetch and the dev launcher.
264
- - [Workspace schema](/reference/delivery-api/workspace-schema) — the schema endpoint.
265
- - [Delivery API](/reference/delivery-api) — the published surface and the preview surface.
@@ -1,16 +0,0 @@
1
- ---
2
- type: reference
3
- layout: docs
4
- ---
5
-
6
- # Chrome Extension
7
-
8
- The extension for the Picked Developer Tools adds a Picked panel to Chrome DevTools.
9
- Use the panel to check and debug your Picked integration on any page that runs the
10
- SDK.
11
-
12
- ![Picked Developer Tools](/chrome-extension-screenshot.jpg)
13
-
14
- ## Related
15
-
16
- - [How to debug with the Chrome extension](/how-to/debug-with-the-chrome-extension)