@picked/client 0.0.1-dev.1777594341273 → 0.0.1-dev.1777597464369

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 (87) hide show
  1. package/dist/{api-DtOVNMSX.js → api-BvbkpgoT.js} +1 -1
  2. package/dist/{api-DWa-ZqA4.cjs → api-DHbW5EXc.cjs} +1 -1
  3. package/dist/cjs/form/index.js +1 -1
  4. package/dist/cjs/index.js +2 -2
  5. package/dist/cjs/plugins/create-experience/index.js +1 -1
  6. package/dist/cjs/plugins/dynamic-experiences/index.js +1 -1
  7. package/dist/cjs/plugins/experience-browser-storage/index.js +1 -1
  8. package/dist/cjs/plugins/history-browser-storage/index.js +1 -1
  9. package/dist/cjs/plugins/responses-browser-storage/index.js +1 -1
  10. package/dist/cjs/plugins/responses-indexeddb/index.js +1 -1
  11. package/dist/cjs/plugins/single-page-app/index.js +1 -1
  12. package/dist/cjs/plugins/web-components/index.js +1 -1
  13. package/dist/cjs/plugins/window-object/index.js +1 -1
  14. package/dist/cjs/server/index.js +1 -1
  15. package/dist/docs/{actions.md → actions.mdx} +7 -0
  16. package/dist/docs/{api-keys.md → api-keys.mdx} +7 -0
  17. package/dist/docs/{conditions.md → conditions.mdx} +7 -0
  18. package/dist/docs/{experiences.md → experiences.mdx} +7 -0
  19. package/dist/docs/{features.md → features.mdx} +7 -0
  20. package/dist/docs/{fields.md → fields.mdx} +7 -0
  21. package/dist/docs/flow-builder/{overview.md → overview.mdx} +7 -0
  22. package/dist/docs/pickedql/data-sources.md +49 -2
  23. package/dist/docs/pickedql/dimensions.md +40 -0
  24. package/dist/docs/pickedql/examples.md +41 -1
  25. package/dist/docs/pickedql/filtering.md +22 -0
  26. package/dist/docs/pickedql/index.md +2 -1
  27. package/dist/docs/pickedql/schema.md +34 -1
  28. package/dist/docs/pickedql/virtual-functions.md +67 -11
  29. package/dist/docs/{projects.md → projects.mdx} +7 -0
  30. package/dist/docs/{reports.md → reports.mdx} +7 -0
  31. package/dist/docs/{steps.md → steps.mdx} +7 -0
  32. package/dist/docs/{workspaces.md → workspaces.mdx} +8 -0
  33. package/dist/esm/form/index.js +36 -13
  34. package/dist/esm/index.js +295 -169
  35. package/dist/esm/plugins/create-experience/index.js +1 -1
  36. package/dist/esm/plugins/dynamic-experiences/index.js +2 -2
  37. package/dist/esm/plugins/experience-browser-storage/index.js +21 -19
  38. package/dist/esm/plugins/history-browser-storage/index.js +17 -15
  39. package/dist/esm/plugins/responses-browser-storage/index.js +21 -19
  40. package/dist/esm/plugins/responses-indexeddb/index.js +37 -35
  41. package/dist/esm/plugins/single-page-app/index.js +16 -38
  42. package/dist/esm/plugins/web-components/index.js +1 -1
  43. package/dist/esm/plugins/window-object/index.js +1 -1
  44. package/dist/esm/server/index.js +1 -1
  45. package/dist/experience-instance-DC2gKwA6.cjs +1 -0
  46. package/dist/experience-instance-DJaNc5Ob.js +486 -0
  47. package/dist/object-C82v79xc.js +25 -0
  48. package/dist/object-CUJOjanb.cjs +1 -0
  49. package/dist/rules-logic-BTIxfrJJ.js +240 -0
  50. package/dist/rules-logic-DNLOv90w.cjs +1 -0
  51. package/dist/types/entities/action/action.d.ts +30 -4
  52. package/dist/types/entities/action/action.d.ts.map +1 -1
  53. package/dist/types/entities/experience-instance/experience-instance.d.ts +4 -2
  54. package/dist/types/entities/experience-instance/experience-instance.d.ts.map +1 -1
  55. package/dist/types/entities/framework/framework.d.ts +0 -2
  56. package/dist/types/entities/framework/framework.d.ts.map +1 -1
  57. package/dist/types/entities/response/response-validation.d.ts +17 -17
  58. package/dist/types/entities/response/response-validation.d.ts.map +1 -1
  59. package/dist/types/form/create-field-evaluator.d.ts.map +1 -1
  60. package/dist/types/form/create-form.d.ts +22 -0
  61. package/dist/types/form/create-form.d.ts.map +1 -1
  62. package/dist/types/form/create-submit-pipeline.d.ts.map +1 -1
  63. package/dist/types/picked.d.ts +3 -1
  64. package/dist/types/picked.d.ts.map +1 -1
  65. package/dist/types/plugins/experience-browser-storage/plugin.d.ts.map +1 -1
  66. package/dist/types/plugins/history-browser-storage/plugin.d.ts.map +1 -1
  67. package/dist/types/plugins/responses-browser-storage/plugin.d.ts.map +1 -1
  68. package/dist/types/plugins/responses-indexeddb/plugin.d.ts.map +1 -1
  69. package/dist/types/plugins/single-page-app/index.d.ts +1 -2
  70. package/dist/types/plugins/single-page-app/index.d.ts.map +1 -1
  71. package/dist/types/plugins/single-page-app/plugin.d.ts +4 -35
  72. package/dist/types/plugins/single-page-app/plugin.d.ts.map +1 -1
  73. package/package.json +1 -1
  74. package/dist/experience-CNIhapU2.js +0 -136
  75. package/dist/experience-CTEBY-it.cjs +0 -1
  76. package/dist/experience-instance-B0tFPMAU.js +0 -396
  77. package/dist/experience-instance-BN0RZG1b.cjs +0 -1
  78. package/dist/nodes-2fst8XKi.js +0 -101
  79. package/dist/nodes-DBK4N9YY.cjs +0 -1
  80. package/dist/rules-logic-D7dL30U1.js +0 -263
  81. package/dist/rules-logic-DJhGFqhC.cjs +0 -1
  82. /package/dist/{id-Cg7fVl1O.cjs → id-Bv44ilEo.cjs} +0 -0
  83. /package/dist/{id-n2yrHvNo.js → id-CRqy981z.js} +0 -0
  84. /package/dist/{logger-C44jSdYl.js → logger-6z_gb4rA.js} +0 -0
  85. /package/dist/{logger-CJUj90QX.cjs → logger-fbvQC40v.cjs} +0 -0
  86. /package/dist/{supports-B_trw6lj.js → supports-0XIfd4-R.js} +0 -0
  87. /package/dist/{supports-CKSVYpQx.cjs → supports-Dsjg-82e.cjs} +0 -0
@@ -87,6 +87,46 @@ FROM events
87
87
  WHERE project_id = '{{ your project ID }}'
88
88
  ```
89
89
 
90
+ ## Custom segment with `control_users` / `variant_users`
91
+
92
+ On `events`, `control_users` / `variant_users` / `control_sessions` / `variant_sessions` accept an optional filter string to count only users/sessions matching the given expression in addition to the implicit `variant_type` filter.
93
+
94
+ ```sql
95
+ -- Control users who fired app_initialize, broken down by step
96
+ SELECT
97
+ step_id,
98
+ control_users('event_type=app_initialize') AS control_initialized,
99
+ variant_users('event_type=app_initialize') AS variant_initialized
100
+ FROM events
101
+ WHERE project_id = '{{ your project ID }}'
102
+ AND client_local_date >= '2026-04-01'
103
+ GROUP BY step_id
104
+ ORDER BY control_initialized DESC
105
+ ```
106
+
107
+ The named form (`filter=`) is also supported:
108
+
109
+ ```sql
110
+ SELECT control_users(filter='event_type=form_submit AND step_id=lead-capture') FROM events
111
+ WHERE project_id = '{{ your project ID }}'
112
+ ```
113
+
114
+ ## Conversion rate from nested virtual functions
115
+
116
+ When numerator and denominator come from different segments — e.g., Control users who fired a custom event divided by **all** users (not just Control) — pass virtual function calls directly as conversion-rate args:
117
+
118
+ ```sql
119
+ -- (Control users who fired app_initialize) / (all users, regardless of variant)
120
+ SELECT
121
+ control_conversion_rate(
122
+ control_users('event_type=app_initialize'),
123
+ all_users()
124
+ ) AS control_initialize_rate
125
+ FROM events
126
+ WHERE project_id = '{{ your project ID }}'
127
+ AND client_local_date >= '2026-04-01'
128
+ ```
129
+
90
130
  ## A/B test by device
91
131
 
92
132
  ```sql
@@ -138,7 +178,7 @@ ORDER BY project_local_date, device_category
138
178
  SELECT
139
179
  utm_source,
140
180
  all_users() AS users,
141
- total_purchase_users() AS purchasers
181
+ all_purchase_users() AS purchasers
142
182
  FROM metrics
143
183
  WHERE project_id = '{{ your project ID }}'
144
184
  GROUP BY utm_source
@@ -29,3 +29,25 @@ WHERE project_id = 'your-project-id'
29
29
  :::warning
30
30
  Each query can only filter on a single `project_id`. Queries that reference multiple projects will be rejected.
31
31
  :::
32
+
33
+ ## Reference tables (per-table tenant filter)
34
+
35
+ Queries against the reference tables (`steps`, `experiences`, `projects`) require their own tenant filter so you only see rows belonging to a project you have access to:
36
+
37
+ | Source | Tenant filter |
38
+ |---|---|
39
+ | `steps`, `experiences` | `WHERE project_id = '<project_id>'` |
40
+ | `projects` | `WHERE id = '<project_id>'` (the row's `id` IS the project id) |
41
+
42
+ ```sql
43
+ -- All experiences for one project
44
+ SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
45
+
46
+ -- All steps for one project
47
+ SELECT id, title FROM steps WHERE project_id = 'your-project-id'
48
+
49
+ -- Metadata for one project
50
+ SELECT id, name, timezone FROM projects WHERE id = 'your-project-id'
51
+ ```
52
+
53
+ The small lookup tables (`dim_variant`, `dim_device`, `dim_geo`, `dim_utm`, `dim_product`) are still exempt — they contain no tenant data.
@@ -22,7 +22,7 @@ PickedQL handles table mapping and dimension joins automatically. You write conc
22
22
  1. **Virtual table expansion**: Table names like `metrics` map to underlying data tables
23
23
  2. **Virtual function expansion**: Shorthand functions like `control_users()` expand to full aggregate expressions
24
24
  3. **Auto dimension joins**: References to dimension columns (like `device_category` or `country_code`) trigger automatic `LEFT JOIN` clauses — you never write joins yourself
25
- 4. **Tenant isolation**: Every query must include a `project_id` filter in the `WHERE` clause. PickedQL extracts it and verifies you have permission to access that project
25
+ 4. **Tenant isolation**: Every query must include a tenant filter in the `WHERE` clause — usually `project_id`, but `projects` uses `id` (the row's `id` IS the project id). PickedQL extracts the filter and verifies you have permission to access that project
26
26
  5. **SQL passthrough**: Standard SQL (including `CASE WHEN`, window functions, and subqueries) works alongside virtual functions
27
27
 
28
28
  ## Best practices
@@ -32,4 +32,5 @@ PickedQL handles table mapping and dimension joins automatically. You write conc
32
32
  - **Use `experience_journey` for sankey / funnel charts**: One line of SQL returns `source, target, users` — the 8-CTE scaffold (dedup, top-N path ranking, lagInFrame) is handled internally; pass parameters via `WHERE`
33
33
  - **Don't write JOINs**: PickedQL injects them automatically when you reference dimension columns
34
34
  - **Group by any dimension**: Add dimension columns to `SELECT` and `GROUP BY` freely — required joins are handled for you
35
+ - **Reference table metadata for free**: Use `step_title`, `experience_title`, `project_name` directly in `events` queries — PickedQL auto-joins the `steps`, `experiences`, and `projects` reference tables
35
36
 
@@ -83,6 +83,36 @@ These columns are joined automatically when referenced — no `JOIN` syntax need
83
83
  | `product_name` | dim_product | Product name |
84
84
  | `product_category` | dim_product | Product category |
85
85
  | `product_page` | dim_product | Product page |
86
+ | `step_title` | steps | Step title (joined on `project_id` + `experience_id` + `step_id`) |
87
+ | `experience_title` | experiences | Experience title (joined on `project_id` + `experience_id`) |
88
+ | `project_name` | projects | Project name |
89
+ | `project_timezone` | projects | Project timezone |
90
+
91
+ ## `steps`, `experiences`, `projects`
92
+
93
+ Reference tables describing your Picked configuration. Auto-joined onto `events` when their analyst-facing columns are referenced; require a per-table tenant filter when queried directly.
94
+
95
+ | Source | Real Columns | Analyst Columns (when referenced from `events`) | Tenant filter (when queried directly) |
96
+ |---|---|---|---|
97
+ | `steps` | `id`, `title`, `experience_id`, `project_id`, `organization_id` | `step_title` | `project_id = '…'` |
98
+ | `experiences` | `id`, `title`, `project_id`, `organization_id` | `experience_title` | `project_id = '…'` |
99
+ | `projects` | `id`, `name`, `timezone`, `organization_id` | `project_name`, `project_timezone` | `id = '<project_id>'` |
100
+
101
+ When queried directly, use the real column names:
102
+
103
+ ```sql
104
+ -- List all experiences for a project
105
+ SELECT id, title FROM experiences WHERE project_id = 'your-project-id'
106
+ ```
107
+
108
+ When referenced from `events`, use the prefixed analyst names — joins are injected automatically:
109
+
110
+ ```sql
111
+ SELECT experience_title, step_title, count(*)
112
+ FROM events
113
+ WHERE project_id = 'your-project-id'
114
+ GROUP BY experience_title, step_title
115
+ ```
86
116
 
87
117
  ## `features`
88
118
 
@@ -117,7 +147,10 @@ Aggregated step-transition edges for sankey / funnel charts. Parameters are supp
117
147
  | `num_nodes_after_start` | Integer | | Forward window from start: keep steps where `seq_pos < start_seq + N` (card 4129 semantics). |
118
148
  | `num_nodes_before_target` | Integer | | Backward window from target: keep steps where `seq_pos >= target_seq - N` (card 2740 semantics). Requires `targeting_step`. |
119
149
  | `top_n_path` | Integer | | Keep only the top-N most-walked paths by user count. Defaults to no limit. |
150
+ | `user_cohort_event` | String | | Restrict to users who have at least one `fact_events` row with this `event_type`. Implemented as `user_canonical_id IN (SELECT DISTINCT user_canonical_id FROM fact_events WHERE event_type = '…')`. |
151
+ | `client_local_date` | Date | | Date range filter, pushed into the underlying scan. Supports `=`, `<`, `<=`, `>`, `>=`, `BETWEEN`. |
152
+ | `event_timestamp` | DateTime64 | | Server-side timestamp filter. Same operators as `client_local_date`. |
120
153
 
121
- When both window params are set, both predicates apply (intersection).
154
+ When both window params are set, both predicates apply (intersection). Date filters combine via `AND` with the other params.
122
155
 
123
156
  See [data sources → experience_journey](./data-sources#experience_journey--sankey-ready-step-transitions) for usage examples.
@@ -10,23 +10,53 @@ Virtual functions are shorthand for aggregate expressions. They are **table-awar
10
10
 
11
11
  | Function | Description |
12
12
  |---|---|
13
- | `control_users()` | Unique users in the Control group |
14
- | `variant_users()` | Unique users in the Variant group |
13
+ | `control_users([condition])` | Unique users in the Control group, optionally filtered by a custom condition |
14
+ | `variant_users([condition])` | Unique users in the Variant group, optionally filtered by a custom condition |
15
15
  | `all_users()` | All unique users |
16
- | `control_sessions()` | Unique sessions in the Control group |
17
- | `variant_sessions()` | Unique sessions in the Variant group |
16
+ | `control_sessions([condition])` | Unique sessions in the Control group, optionally filtered by a custom condition |
17
+ | `variant_sessions([condition])` | Unique sessions in the Variant group, optionally filtered by a custom condition |
18
18
  | `all_sessions()` | All unique sessions |
19
19
 
20
+ ### Custom filters on `events`
21
+
22
+ On the `events` table, `control_*`/`variant_*` functions accept **one optional filter argument** to count only users/sessions matching the given expression, in addition to the implicit `variant_type` filter. The argument can be **positional** or **named** (`filter=`).
23
+
24
+ The filter uses the same `column=value` syntax as conversion-rate conditions, with `AND`/`OR` operators and parentheses for grouping.
25
+
26
+ ```sql
27
+ -- Default: all Control users
28
+ SELECT control_users() FROM events
29
+
30
+ -- Custom filter (positional)
31
+ SELECT control_users('event_type=app_initialize') FROM events
32
+ SELECT variant_users('event_type=app_initialize AND step_id=xxx') FROM events
33
+
34
+ -- AND/OR + parentheses
35
+ SELECT control_users('event_type=app_initialize OR event_type=app_load') FROM events
36
+ SELECT control_users('event_type=form_submit AND (step_id=lead-capture OR step_id=xxx)') FROM events
37
+
38
+ -- Sessions
39
+ SELECT control_sessions('event_type=step_enter') FROM events
40
+ SELECT variant_sessions('event_type=step_enter AND step_id=checkout') FROM events
41
+
42
+ -- Named form
43
+ SELECT control_users(filter='event_type=app_initialize AND step_id=xxx') FROM events
44
+ ```
45
+
46
+ :::note
47
+ Custom filters are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions ignore any arguments and use the default Control/Variant filter only.
48
+ :::
49
+
20
50
  ## Conversion metrics
21
51
 
22
52
  | Function | Description |
23
53
  |---|---|
24
- | `total_purchase_users()` | Users who completed a purchase |
54
+ | `all_purchase_users()` | Users who completed a purchase |
25
55
  | `control_purchase_users()` | Control users who purchased (`metrics` only) |
26
56
  | `variant_purchase_users()` | Variant users who purchased (`metrics` only) |
27
- | `total_purchase_sessions()` | Sessions with a purchase (`metrics` only) |
28
- | `total_purchase_orders()` | Unique order count (`metrics` only) |
29
- | `total_cart_add_users()` | Users who added to cart |
57
+ | `all_purchase_sessions()` | Sessions with a purchase (`metrics` only) |
58
+ | `all_purchase_orders()` | Unique order count (`metrics` only) |
59
+ | `all_cart_add_users()` | Users who added to cart |
30
60
 
31
61
  ## Conversion rates
32
62
 
@@ -38,9 +68,9 @@ Virtual functions are shorthand for aggregate expressions. They are **table-awar
38
68
 
39
69
  ### Custom conditions on `events`
40
70
 
41
- On the `events` table, conversion rate functions accept up to **2 optional arguments** to customize the numerator and denominator. Arguments can be **positional** or **named** (`numerator=`, `denominator=`).
71
+ On the `events` table, conversion rate functions accept up to **2 optional arguments** to customize the numerator and denominator. Each argument can be either a **condition expression string** or a **nested virtual function call** (see below). Arguments can be **positional** or **named** (`numerator=`, `denominator=`).
42
72
 
43
- Each argument is a condition expression using `column=value` with `AND`/`OR` operators and parentheses for grouping.
73
+ Each condition expression uses `column=value` with `AND`/`OR` operators and parentheses for grouping.
44
74
 
45
75
  ```sql
46
76
  -- Default: purchase users / all users
@@ -69,8 +99,34 @@ SELECT control_conversion_rate(denominator='step_id=lead-capture') FROM events
69
99
  SELECT conversion_rate_uplift(numerator='event_type=form_submit', denominator='step_id=lead-capture') FROM events
70
100
  ```
71
101
 
102
+ #### Nested virtual functions as numerator / denominator
103
+
104
+ Instead of a condition string, you can pass a **virtual function call** as the numerator or denominator. The inner aggregate is substituted in place — no implicit `variant_type` filter is added on top of it (the nested function controls its own filter).
105
+
106
+ This is the most flexible form when the numerator and denominator have different segments (e.g., Control users who fired event X over **all** users regardless of variant):
107
+
108
+ ```sql
109
+ -- (Control users who fired app_initialize) / (all users)
110
+ SELECT control_conversion_rate(
111
+ control_users('event_type=app_initialize'),
112
+ all_users()
113
+ ) FROM events
114
+
115
+ -- Mix string and nested forms
116
+ SELECT control_conversion_rate(
117
+ 'event_type=form_submit',
118
+ all_users()
119
+ ) FROM events
120
+
121
+ -- Uplift with nested args
122
+ SELECT conversion_rate_uplift(
123
+ control_users('event_type=app_initialize'),
124
+ all_users()
125
+ ) FROM events
126
+ ```
127
+
72
128
  :::note
73
- Custom conditions are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions always use the default purchase / all users definition.
129
+ Custom conditions and nested virtual function args are **not supported on `metrics`** (pre-aggregated data). On `metrics`, these functions always use the default purchase / all users definition.
74
130
  :::
75
131
 
76
132
  ## Visitor segmentation (`metrics` only)
@@ -2,10 +2,17 @@
2
2
  layout: docs
3
3
  ---
4
4
 
5
+ import { Screenshot } from '../../components/Screenshot'
6
+
5
7
  # Projects
6
8
 
7
9
  A project represents one website or app you want to instrument with Picked. Each project has its own set of experiences, entities, and configuration.
8
10
 
11
+ <Screenshot
12
+ route="/{orgSlug}"
13
+ alt="The organization home page on the Picked dashboard, listing the projects in an organization"
14
+ />
15
+
9
16
  ## Create a project
10
17
 
11
18
  You need an organization first. If you don't have one, create it when you sign up.
@@ -2,10 +2,17 @@
2
2
  layout: docs
3
3
  ---
4
4
 
5
+ import { Screenshot } from '../../components/Screenshot'
6
+
5
7
  # Reports
6
8
 
7
9
  Reports show analytics data for your project. Track how visitors interact with your experiences and features.
8
10
 
11
+ <Screenshot
12
+ route="/{orgSlug}/{projectId}/reports"
13
+ alt="The reports list for a project on the Picked dashboard"
14
+ />
15
+
9
16
  ## View report data
10
17
 
11
18
  Open a report to see its analytics. Data updates as new visitor interactions are recorded.
@@ -2,10 +2,17 @@
2
2
  layout: docs
3
3
  ---
4
4
 
5
+ import { Screenshot } from '../../components/Screenshot'
6
+
5
7
  # Steps
6
8
 
7
9
  A step is a visual screen or card shown to visitors during an experience. Each step holds one or more fields that collect data or display content.
8
10
 
11
+ <Screenshot
12
+ route="/{orgSlug}/{projectId}/workspaces/{workspaceId}/steps"
13
+ alt="The steps list for a workspace on the Picked dashboard"
14
+ />
15
+
9
16
  ## Create a step
10
17
 
11
18
  1. Open your project.
@@ -2,10 +2,18 @@
2
2
  layout: docs
3
3
  ---
4
4
 
5
+ import { Screenshot } from '../../components/Screenshot'
6
+
5
7
  # Workspaces
6
8
 
7
9
  A workspace is a version of your project's configuration. Use workspaces to stage changes, preview them, and publish when ready.
8
10
 
11
+ <Screenshot
12
+ route="/{orgSlug}/{projectId}/workspaces"
13
+ alt="The workspaces list inside a project on the Picked dashboard"
14
+ hide={['[data-testid="workspace-row-relative-time"]']}
15
+ />
16
+
9
17
  ## How workspaces work
10
18
 
11
19
  Each project has a workspace that holds your experiences, features, and entity configurations. When you make changes in the dashboard — editing a flow, updating a feature, or modifying an entity — those changes exist in the workspace until you publish.
@@ -1,4 +1,4 @@
1
- import { t as e } from "../../rules-logic-D7dL30U1.js";
1
+ import { t as e } from "../../rules-logic-BTIxfrJJ.js";
2
2
  import { attach as t, combine as n, createEffect as r, createEvent as i, createStore as a, sample as o, split as s } from "effector";
3
3
  //#region src/form/build-responses.ts
4
4
  function c(e, t, n) {
@@ -70,10 +70,16 @@ function m(e, n, i) {
70
70
  staged: i,
71
71
  committed: e.responses.getAllStore
72
72
  },
73
- effect: r(async ({ allFields: t, fieldKeys: n, staged: r, committed: i }) => await p(e, t.filter((e) => n.includes(e.key)), { responses: {
74
- ...i,
75
- ...r
76
- } }))
73
+ effect: r(async ({ allFields: t, fieldKeys: n, staged: r, committed: i }) => {
74
+ let a = new Map(t.map((e) => [e.key, e]));
75
+ return await p(e, n.flatMap((e) => {
76
+ let t = a.get(e);
77
+ return t ? [t] : [];
78
+ }), { responses: {
79
+ ...i,
80
+ ...r
81
+ } });
82
+ })
77
83
  });
78
84
  return o({
79
85
  clock: c.doneData,
@@ -354,7 +360,16 @@ function v({ client: e, experienceInstance: n, formId: c, title: u, stepStore: d
354
360
  clock: g,
355
361
  target: w.executeFx
356
362
  }), o({
357
- clock: [y, w.executeFx.done],
363
+ clock: [
364
+ y,
365
+ w.executeFx.done,
366
+ T.executeFx.fail,
367
+ E.fail,
368
+ D.fail,
369
+ O.fail,
370
+ C.executeFx.fail,
371
+ w.executeFx.fail
372
+ ],
358
373
  fn: () => !1,
359
374
  target: b
360
375
  }), {
@@ -374,7 +389,15 @@ function y(e) {
374
389
  if (t instanceof HTMLInputElement) return t.type === "checkbox" ? t.checked : t.value;
375
390
  if (t instanceof HTMLSelectElement || t instanceof HTMLTextAreaElement) return t.value;
376
391
  }
377
- function b(e, t, r, i) {
392
+ function b(e, t) {
393
+ let n = e.currentTarget;
394
+ if (t.multiple) {
395
+ if (n instanceof HTMLInputElement && n.type === "checkbox" && n.form) return Array.from(new FormData(n.form).getAll(n.name), String);
396
+ if (n instanceof HTMLSelectElement && n.multiple) return Array.from(n.selectedOptions, (e) => e.value);
397
+ }
398
+ return y(e);
399
+ }
400
+ function x(e, t, r, i) {
378
401
  let { client: s, experienceInstance: c } = e, { currentStepStore: l, goToNextStep: u } = c, d = n(l, c, (e, t) => ({
379
402
  stepId: e?.id,
380
403
  experienceId: t.id
@@ -389,7 +412,7 @@ function b(e, t, r, i) {
389
412
  },
390
413
  target: f
391
414
  });
392
- let { fieldInputEvent: h, fieldChangeEvent: _, fieldBlurEvent: b, touchedStore: x, fieldErrorsStore: S, formErrorsStore: C } = g(s, p, f), w = n({
415
+ let { fieldInputEvent: h, fieldChangeEvent: _, fieldBlurEvent: y, touchedStore: x, fieldErrorsStore: S, formErrorsStore: C } = g(s, p, f), w = n({
393
416
  fields: p,
394
417
  responses: s.responses.listStore,
395
418
  staged: f,
@@ -398,20 +421,20 @@ function b(e, t, r, i) {
398
421
  experienceAndStepId: d
399
422
  }, ({ fields: e, responses: t, staged: n, fieldErrors: r, touched: i, experienceAndStepId: a }) => e.map((e) => {
400
423
  let o = (t) => {
401
- let n = y(t);
424
+ let n = b(t, e);
402
425
  n !== void 0 && h({
403
426
  fieldKey: e.key,
404
427
  value: n
405
428
  });
406
429
  }, s = (t) => {
407
- let n = y(t);
430
+ let n = b(t, e);
408
431
  n !== void 0 && _({
409
432
  fieldKey: e.key,
410
433
  value: n
411
434
  });
412
435
  }, c = (t) => {
413
- let n = y(t);
414
- n !== void 0 && b({
436
+ let n = b(t, e);
437
+ n !== void 0 && y({
415
438
  fieldKey: e.key,
416
439
  value: n
417
440
  });
@@ -469,4 +492,4 @@ function b(e, t, r, i) {
469
492
  };
470
493
  }
471
494
  //#endregion
472
- export { l as buildResponsesFromFormData, m as createFieldEvaluator, g as createFieldValidation, b as createForm, v as createSubmitPipeline, y as getEventValue, p as getStepFields };
495
+ export { l as buildResponsesFromFormData, m as createFieldEvaluator, g as createFieldValidation, x as createForm, v as createSubmitPipeline, y as getEventValue, p as getStepFields };