@delmaredigital/payload-experiments 0.3.0-rc.4 → 0.4.0-rc.2

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 (299) hide show
  1. package/README.md +122 -27
  2. package/dist/admin/MetricSourceSelect.js +3 -3
  3. package/dist/admin/PlacementStatus.d.ts +3 -0
  4. package/dist/admin/PlacementStatus.js +54 -0
  5. package/dist/admin/PreviewLinks.d.ts +2 -1
  6. package/dist/admin/PreviewLinks.js +2 -2
  7. package/dist/admin/TestsDashboardCards.d.ts +1 -0
  8. package/dist/admin/TestsDashboardCards.js +4 -8
  9. package/dist/admin/TestsNavLink.d.ts +1 -0
  10. package/dist/admin/TestsNavLink.js +4 -10
  11. package/dist/admin/actions/ConfirmDialog.d.ts +2 -1
  12. package/dist/admin/actions/ConfirmDialog.js +2 -2
  13. package/dist/admin/actions/DecideDialog.d.ts +2 -1
  14. package/dist/admin/actions/DecideDialog.js +2 -2
  15. package/dist/admin/api.d.ts +18 -2
  16. package/dist/admin/api.js +47 -2
  17. package/dist/admin/blocks/BlockPanel.d.ts +4 -0
  18. package/dist/admin/blocks/BlockPanel.js +199 -0
  19. package/dist/admin/blocks/TestBlockField.d.ts +5 -0
  20. package/dist/admin/blocks/TestBlockField.js +163 -0
  21. package/dist/admin/blocks/formApi.d.ts +46 -0
  22. package/dist/admin/blocks/formApi.js +159 -0
  23. package/dist/admin/blocks/inject.d.ts +7 -0
  24. package/dist/admin/blocks/inject.js +41 -0
  25. package/dist/admin/blocks/model.d.ts +17 -0
  26. package/dist/admin/blocks/model.js +45 -0
  27. package/dist/admin/blocks/statusCache.d.ts +9 -0
  28. package/dist/admin/blocks/statusCache.js +92 -0
  29. package/dist/admin/blocks/useBlockForm.d.ts +17 -0
  30. package/dist/admin/blocks/useBlockForm.js +46 -0
  31. package/dist/admin/copy/actions.d.ts +2 -0
  32. package/dist/admin/copy/actions.js +9 -0
  33. package/dist/admin/copy/blocks.d.ts +43 -0
  34. package/dist/admin/copy/blocks.js +64 -0
  35. package/dist/admin/copy/common.d.ts +1 -0
  36. package/dist/admin/copy/common.js +1 -1
  37. package/dist/admin/copy/goals.d.ts +2 -0
  38. package/dist/admin/copy/goals.js +4 -1
  39. package/dist/admin/copy/newTest.d.ts +10 -0
  40. package/dist/admin/copy/newTest.js +10 -0
  41. package/dist/admin/copy/pages.d.ts +24 -0
  42. package/dist/admin/copy/pages.js +24 -0
  43. package/dist/admin/copy/readiness.d.ts +23 -3
  44. package/dist/admin/copy/readiness.js +24 -3
  45. package/dist/admin/copy/results.d.ts +1 -0
  46. package/dist/admin/copy/results.js +1 -0
  47. package/dist/admin/copy/testPage.d.ts +4 -0
  48. package/dist/admin/copy/testPage.js +4 -0
  49. package/dist/admin/goals/XpGoalField.d.ts +4 -0
  50. package/dist/admin/goals/XpGoalField.js +168 -0
  51. package/dist/admin/goals/xpGoalField.css +48 -0
  52. package/dist/admin/metricSource.model.d.ts +2 -0
  53. package/dist/admin/metricSource.model.js +4 -0
  54. package/dist/admin/pageCollections.d.ts +10 -0
  55. package/dist/admin/pageCollections.js +20 -0
  56. package/dist/admin/paths.d.ts +9 -0
  57. package/dist/admin/paths.js +9 -0
  58. package/dist/admin/placementStatus.model.d.ts +2 -0
  59. package/dist/admin/placementStatus.model.js +19 -0
  60. package/dist/admin/placements/placementLabels.d.ts +11 -0
  61. package/dist/admin/placements/placementLabels.js +21 -0
  62. package/dist/admin/placements/placementLabels.model.d.ts +13 -0
  63. package/dist/admin/placements/placementLabels.model.js +12 -0
  64. package/dist/admin/placements/usePlacementLabels.d.ts +12 -0
  65. package/dist/admin/placements/usePlacementLabels.js +102 -0
  66. package/dist/admin/results/DataQualityPanel.js +4 -1
  67. package/dist/admin/results/results.model.d.ts +3 -0
  68. package/dist/admin/results/results.model.js +8 -4
  69. package/dist/admin/surface/TestsHome.js +39 -10
  70. package/dist/admin/surface/TestsSurface.js +7 -6
  71. package/dist/admin/surface/contracts.d.ts +6 -5
  72. package/dist/admin/surface/goals/GoalForm.js +71 -44
  73. package/dist/admin/surface/goals/GoalsList.js +5 -4
  74. package/dist/admin/surface/goals/data.js +4 -1
  75. package/dist/admin/surface/goals/goals.model.d.ts +1 -2
  76. package/dist/admin/surface/goals/goals.model.js +1 -3
  77. package/dist/admin/surface/home.model.d.ts +3 -3
  78. package/dist/admin/surface/home.model.js +8 -4
  79. package/dist/admin/surface/newTest/NewTest.js +56 -17
  80. package/dist/admin/surface/newTest/PageWizard.d.ts +7 -0
  81. package/dist/admin/surface/newTest/PageWizard.js +214 -0
  82. package/dist/admin/surface/pagePicker/CopyRoute.d.ts +6 -0
  83. package/dist/admin/surface/pagePicker/CopyRoute.js +53 -0
  84. package/dist/admin/surface/pagePicker/PageCombobox.d.ts +10 -0
  85. package/dist/admin/surface/pagePicker/PageCombobox.js +395 -0
  86. package/dist/admin/surface/pagePicker/pagePicker.css +10 -0
  87. package/dist/admin/surface/pagePicker/pagePicker.model.d.ts +27 -0
  88. package/dist/admin/surface/pagePicker/pagePicker.model.js +25 -0
  89. package/dist/admin/surface/readiness/ActionDialogs.js +99 -64
  90. package/dist/admin/surface/readiness/Banner.js +30 -6
  91. package/dist/admin/surface/readiness/readiness.model.d.ts +8 -1
  92. package/dist/admin/surface/readiness/readiness.model.js +92 -9
  93. package/dist/admin/surface/results/ReleasePages.d.ts +3 -1
  94. package/dist/admin/surface/results/ReleasePages.js +3 -7
  95. package/dist/admin/surface/results/ResultsBody.js +21 -2
  96. package/dist/admin/surface/results/ResultsHeader.js +5 -13
  97. package/dist/admin/surface/results/useResults.d.ts +20 -1
  98. package/dist/admin/surface/test/AdvancedSection.js +111 -104
  99. package/dist/admin/surface/test/GoalSection.js +94 -14
  100. package/dist/admin/surface/test/LengthSection.js +1 -1
  101. package/dist/admin/surface/test/PageHoldout.d.ts +3 -0
  102. package/dist/admin/surface/test/PageHoldout.js +67 -0
  103. package/dist/admin/surface/test/TestPage.js +5 -9
  104. package/dist/admin/surface/test/VersionsSection.js +12 -5
  105. package/dist/admin/surface/test/fields.d.ts +13 -4
  106. package/dist/admin/surface/test/fields.js +46 -14
  107. package/dist/admin/surface/test/jumpToSection.d.ts +1 -1
  108. package/dist/admin/surface/test/jumpToSection.js +4 -3
  109. package/dist/admin/surface/test/pageParts.d.ts +4 -1
  110. package/dist/admin/surface/test/pageParts.js +49 -1
  111. package/dist/admin/surface/test/testPage.css +3 -1
  112. package/dist/admin/surface/testDocument.model.d.ts +1 -0
  113. package/dist/admin/surface/testDocument.model.js +2 -1
  114. package/dist/admin/surface/useTestDocument.d.ts +15 -2
  115. package/dist/admin/surface/useTestDocument.js +53 -15
  116. package/dist/admin/surfaceUrls.d.ts +7 -0
  117. package/dist/admin/surfaceUrls.js +19 -0
  118. package/dist/admin/theme.css +2 -0
  119. package/dist/admin/useApi.d.ts +21 -2
  120. package/dist/admin/useApi.js +3 -5
  121. package/dist/admin/views/CollectionListRedirect.d.ts +1 -0
  122. package/dist/admin/views/CollectionListRedirect.js +1 -1
  123. package/dist/admin/views/ExperimentsRootView.js +28 -133
  124. package/dist/admin/views/GoalEditRedirect.d.ts +4 -0
  125. package/dist/admin/views/GoalEditRedirect.js +14 -0
  126. package/dist/admin/views/GoalsCollectionListView.d.ts +2 -0
  127. package/dist/admin/views/GoalsCollectionListView.js +4 -0
  128. package/dist/admin/views/TestsCollectionListView.d.ts +2 -0
  129. package/dist/admin/views/TestsCollectionListView.js +4 -0
  130. package/dist/admin/views/TestsNavLinkServer.d.ts +1 -0
  131. package/dist/admin/views/TestsNavLinkServer.js +1 -1
  132. package/dist/admin/views/buildSurfaceProps.d.ts +8 -0
  133. package/dist/admin/views/buildSurfaceProps.js +143 -0
  134. package/dist/admin/views/renderCollectionList.d.ts +2 -0
  135. package/dist/admin/views/renderCollectionList.js +34 -0
  136. package/dist/admin/views/renderTestsSurface.d.ts +3 -0
  137. package/dist/admin/views/renderTestsSurface.js +34 -0
  138. package/dist/blocks/bindings.d.ts +3 -0
  139. package/dist/blocks/bindings.js +34 -0
  140. package/dist/blocks/createExperimentBlock.d.ts +6 -0
  141. package/dist/blocks/createExperimentBlock.js +77 -0
  142. package/dist/blocks/formState.d.ts +31 -0
  143. package/dist/blocks/formState.js +146 -0
  144. package/dist/blocks/model.d.ts +41 -0
  145. package/dist/blocks/model.js +34 -0
  146. package/dist/client/ExperimentGroup.d.ts +6 -0
  147. package/dist/client/ExperimentGroup.js +9 -0
  148. package/dist/client/ExperimentsProvider.js +20 -4
  149. package/dist/client/clickGoals.d.ts +4 -0
  150. package/dist/client/clickGoals.js +43 -0
  151. package/dist/collections/experiments/config.js +21 -7
  152. package/dist/collections/experiments/deleteGuard.d.ts +2 -1
  153. package/dist/collections/experiments/deleteGuard.js +12 -1
  154. package/dist/collections/experiments/editability.js +4 -2
  155. package/dist/collections/experiments/pickSlug.d.ts +2 -0
  156. package/dist/collections/experiments/pickSlug.js +8 -0
  157. package/dist/collections/labels.d.ts +3 -0
  158. package/dist/collections/labels.js +20 -0
  159. package/dist/collections/metrics.js +28 -6
  160. package/dist/collections/phases.js +1 -0
  161. package/dist/collections/serialize.js +7 -0
  162. package/dist/db/clickGoals.d.ts +9 -0
  163. package/dist/db/clickGoals.js +22 -0
  164. package/dist/db/delete.d.ts +1 -0
  165. package/dist/db/delete.js +1 -0
  166. package/dist/db/locks.d.ts +8 -0
  167. package/dist/db/locks.js +27 -4
  168. package/dist/db/names.d.ts +4 -0
  169. package/dist/db/names.js +4 -0
  170. package/dist/db/pageBindings.d.ts +4 -0
  171. package/dist/db/pageBindings.js +17 -0
  172. package/dist/db/pageBusy.d.ts +2 -0
  173. package/dist/db/pageBusy.js +10 -0
  174. package/dist/db/pageContent.d.ts +10 -0
  175. package/dist/db/pageContent.js +79 -0
  176. package/dist/db/placements.d.ts +33 -0
  177. package/dist/db/placements.js +54 -0
  178. package/dist/db/slugs.d.ts +8 -0
  179. package/dist/db/slugs.js +40 -0
  180. package/dist/db/snapshots.d.ts +6 -0
  181. package/dist/db/snapshots.js +8 -5
  182. package/dist/endpoints/clickKeys.d.ts +5 -0
  183. package/dist/endpoints/clickKeys.js +17 -0
  184. package/dist/endpoints/events.js +4 -1
  185. package/dist/endpoints/index.js +28 -0
  186. package/dist/endpoints/pages.d.ts +5 -0
  187. package/dist/endpoints/pages.js +120 -0
  188. package/dist/endpoints/placementStatus.d.ts +6 -0
  189. package/dist/endpoints/placementStatus.js +238 -0
  190. package/dist/endpoints/readBody.d.ts +2 -0
  191. package/dist/endpoints/readBody.js +24 -0
  192. package/dist/endpoints/results.js +5 -1
  193. package/dist/endpoints/summary.js +11 -4
  194. package/dist/endpoints/wrapBlock.d.ts +6 -0
  195. package/dist/endpoints/wrapBlock.js +76 -0
  196. package/dist/errors.d.ts +3 -3
  197. package/dist/errors.js +4 -4
  198. package/dist/events/rows.d.ts +1 -1
  199. package/dist/events/rows.js +5 -3
  200. package/dist/exports/adminClient.d.ts +5 -0
  201. package/dist/exports/adminClient.js +5 -0
  202. package/dist/exports/adminRsc.d.ts +3 -0
  203. package/dist/exports/adminRsc.js +3 -0
  204. package/dist/exports/blocks.d.ts +2 -0
  205. package/dist/exports/blocks.js +1 -0
  206. package/dist/exports/client.d.ts +1 -0
  207. package/dist/exports/client.js +1 -0
  208. package/dist/exports/index.d.ts +6 -1
  209. package/dist/exports/index.js +3 -0
  210. package/dist/exports/puck.d.ts +3 -1
  211. package/dist/exports/puck.js +2 -0
  212. package/dist/exports/puckEditor.d.ts +3 -0
  213. package/dist/exports/puckEditor.js +2 -0
  214. package/dist/exports/rsc.d.ts +3 -0
  215. package/dist/exports/rsc.js +2 -0
  216. package/dist/fields/xpGoal.d.ts +3 -0
  217. package/dist/fields/xpGoal.js +16 -0
  218. package/dist/globals/state.js +10 -0
  219. package/dist/goals/cache.d.ts +3 -0
  220. package/dist/goals/cache.js +35 -0
  221. package/dist/goals/fairness.d.ts +40 -0
  222. package/dist/goals/fairness.js +200 -0
  223. package/dist/goals/key.d.ts +4 -0
  224. package/dist/goals/key.js +3 -0
  225. package/dist/goals/picker/clickGoalPicker.model.d.ts +29 -0
  226. package/dist/goals/picker/clickGoalPicker.model.js +45 -0
  227. package/dist/goals/picker/copy.d.ts +16 -0
  228. package/dist/goals/picker/copy.js +15 -0
  229. package/dist/goals/picker/useClickGoalPicker.d.ts +30 -0
  230. package/dist/goals/picker/useClickGoalPicker.js +220 -0
  231. package/dist/goals/validate.d.ts +3 -0
  232. package/dist/goals/validate.js +14 -0
  233. package/dist/hooks/pageGuard.d.ts +5 -1
  234. package/dist/hooks/pageGuard.js +157 -95
  235. package/dist/hooks/puckGoals.d.ts +3 -0
  236. package/dist/hooks/puckGoals.js +38 -0
  237. package/dist/onInit.js +29 -0
  238. package/dist/options.d.ts +2 -0
  239. package/dist/options.js +41 -1
  240. package/dist/plugin.js +50 -43
  241. package/dist/puck/copy.d.ts +1 -0
  242. package/dist/puck/copy.js +1 -0
  243. package/dist/puck/editor/editor.chrome.css +14 -0
  244. package/dist/puck/editor/editor.css +106 -0
  245. package/dist/puck/editor/editor.model.d.ts +4 -2
  246. package/dist/puck/editor/editor.model.js +6 -3
  247. package/dist/puck/editor/integration.d.ts +10 -0
  248. package/dist/puck/editor/integration.js +30 -0
  249. package/dist/puck/editor/xpGoalPuckEditorField.d.ts +7 -0
  250. package/dist/puck/editor/xpGoalPuckEditorField.js +142 -0
  251. package/dist/puck/integration.d.ts +6 -0
  252. package/dist/puck/integration.js +21 -0
  253. package/dist/puck/xpGoalField.d.ts +3 -0
  254. package/dist/puck/xpGoalField.js +6 -0
  255. package/dist/results/health.d.ts +4 -0
  256. package/dist/results/health.js +27 -0
  257. package/dist/results/snapshot.js +15 -2
  258. package/dist/sanitizeReadinessDetail.js +43 -0
  259. package/dist/server/pageKindSeoContract.d.ts +27 -0
  260. package/dist/server/pageKindSeoContract.js +80 -0
  261. package/dist/server/recordContentChange.js +58 -8
  262. package/dist/server/resolveExperimentBlocks.d.ts +5 -0
  263. package/dist/server/resolveExperimentBlocks.js +54 -0
  264. package/dist/server/runResults.js +56 -15
  265. package/dist/server/toClientAssignments.js +2 -1
  266. package/dist/transitions/addMetric.d.ts +2 -1
  267. package/dist/transitions/addMetric.js +28 -1
  268. package/dist/transitions/checkStart.d.ts +14 -1
  269. package/dist/transitions/checkStart.js +92 -8
  270. package/dist/transitions/decide.js +25 -0
  271. package/dist/transitions/deleteExperiment.d.ts +3 -1
  272. package/dist/transitions/deleteExperiment.js +27 -1
  273. package/dist/transitions/kernel.js +4 -0
  274. package/dist/transitions/makeContent.d.ts +5 -0
  275. package/dist/transitions/makeContent.js +39 -11
  276. package/dist/transitions/pageCollection.d.ts +10 -0
  277. package/dist/transitions/pageCollection.js +20 -0
  278. package/dist/transitions/pageVersions.d.ts +10 -0
  279. package/dist/transitions/pageVersions.js +44 -0
  280. package/dist/transitions/phaseRecord.d.ts +1 -0
  281. package/dist/transitions/placementInteractions.d.ts +40 -0
  282. package/dist/transitions/placementInteractions.js +94 -0
  283. package/dist/transitions/placements.d.ts +8 -0
  284. package/dist/transitions/placements.js +148 -1
  285. package/dist/transitions/preflightData.d.ts +2 -2
  286. package/dist/transitions/preflightData.js +137 -5
  287. package/dist/transitions/resolveCaps.d.ts +1 -0
  288. package/dist/transitions/resolveCaps.js +6 -2
  289. package/dist/transitions/start.js +46 -1
  290. package/dist/types/admin.d.ts +1 -1
  291. package/dist/types/assignments.d.ts +1 -0
  292. package/dist/types/contracts.d.ts +15 -0
  293. package/dist/types/endpoints.d.ts +92 -5
  294. package/dist/types/index.d.ts +3 -0
  295. package/dist/types/puck.d.ts +7 -1
  296. package/dist/types/snapshot.d.ts +17 -4
  297. package/dist/types/surface.d.ts +13 -0
  298. package/dist/ui/ui.css +4 -0
  299. package/package.json +8 -1
@@ -1,15 +1,19 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../../surfaceUrls.js';
3
4
  import { fetchAllDocs } from '../../../lib/fetchAllDocs.js';
4
5
  import { useEffect, useRef, useState } from 'react';
5
6
  import { useRouter } from 'next/navigation.js';
6
7
  import { formatAdminURL } from 'payload/shared';
7
8
  import { NEW_TEST_COPY as C } from '../../copy/newTest.js';
8
9
  import { CreateRefused, createTest } from '../../../puck/editor/createTest.js';
10
+ import { PageWizard } from './PageWizard.js';
9
11
  import './newTest.css';
10
12
  export function NewTest({ surface, pages }) {
11
13
  const router = useRouter();
12
14
  const [step, setStep] = useState('kind');
15
+ const [kind, setKind] = useState('flag');
16
+ const [created, setCreated] = useState();
13
17
  const [pointId, setPointId] = useState('');
14
18
  const point = surface.flagPoints.find((item)=>item.id === pointId);
15
19
  const [unitType, setUnitType] = useState('visitor');
@@ -50,23 +54,32 @@ export function NewTest({ surface, pages }) {
50
54
  layerRetry
51
55
  ]);
52
56
  async function submit() {
53
- if (inFlight.current || !point || !name.trim()) return;
57
+ if (inFlight.current || kind === 'flag' && !point || !name.trim()) return;
54
58
  inFlight.current = true;
55
59
  setPending(true);
56
60
  setError('');
57
61
  try {
58
62
  const { id } = await createTest(surface.apiRoute, {
59
- kind: 'flag',
60
- unitType,
63
+ kind,
64
+ unitType: kind === 'page' ? 'visitor' : unitType,
61
65
  name,
62
- flagPoint: point.id,
63
- ...layer === undefined ? {} : {
66
+ ...kind === 'flag' ? {
67
+ flagPoint: point.id
68
+ } : surface.pageCollections?.length === 1 ? {
69
+ pageCollection: surface.pageCollections[0].slug
70
+ } : {},
71
+ ...kind !== 'flag' || layer === undefined ? {} : {
64
72
  layer
65
73
  },
66
74
  ...hypothesis.trim() ? {
67
75
  hypothesis
68
76
  } : {}
69
77
  });
78
+ if (kind === 'page') {
79
+ setCreated(id);
80
+ setPending(false);
81
+ return;
82
+ }
70
83
  router.push(formatAdminURL({
71
84
  adminRoute: surface.adminRoute,
72
85
  path: `/experiments/${encodeURIComponent(String(id))}`
@@ -77,6 +90,10 @@ export function NewTest({ surface, pages }) {
77
90
  setPending(false);
78
91
  }
79
92
  }
93
+ if (created !== undefined) return /*#__PURE__*/ _jsx(PageWizard, {
94
+ id: created,
95
+ surface: surface
96
+ });
80
97
  const collections = [
81
98
  ...new Set(pages?.map((page)=>page.collection))
82
99
  ];
@@ -102,15 +119,37 @@ export function NewTest({ surface, pages }) {
102
119
  /*#__PURE__*/ _jsx("span", {
103
120
  children: C.blockMeaning
104
121
  }),
105
- surface.descriptions?.block ? /*#__PURE__*/ _jsx("span", {
106
- children: surface.descriptions.block
122
+ surface.admin?.descriptions?.block ? /*#__PURE__*/ _jsx("span", {
123
+ children: surface.admin?.descriptions?.block
124
+ }) : null
125
+ ]
126
+ }) : null,
127
+ surface.pageCollections?.length ? /*#__PURE__*/ _jsxs("button", {
128
+ type: "button",
129
+ className: "xp-new-test-card",
130
+ onClick: ()=>{
131
+ setKind('page');
132
+ setStep('name');
133
+ },
134
+ children: [
135
+ /*#__PURE__*/ _jsx("strong", {
136
+ children: C.page
137
+ }),
138
+ /*#__PURE__*/ _jsx("span", {
139
+ children: C.pageMeaning
140
+ }),
141
+ surface.admin?.descriptions?.page ? /*#__PURE__*/ _jsx("span", {
142
+ children: surface.admin?.descriptions?.page
107
143
  }) : null
108
144
  ]
109
145
  }) : null,
110
146
  surface.flagPoints.length > 0 ? /*#__PURE__*/ _jsxs("button", {
111
147
  type: "button",
112
148
  className: "xp-new-test-card",
113
- onClick: ()=>setStep('setting'),
149
+ onClick: ()=>{
150
+ setKind('flag');
151
+ setStep('setting');
152
+ },
114
153
  children: [
115
154
  /*#__PURE__*/ _jsx("strong", {
116
155
  children: C.setting
@@ -118,14 +157,14 @@ export function NewTest({ surface, pages }) {
118
157
  /*#__PURE__*/ _jsx("span", {
119
158
  children: C.settingMeaning
120
159
  }),
121
- surface.descriptions?.setting ? /*#__PURE__*/ _jsx("span", {
122
- children: surface.descriptions.setting
160
+ surface.admin?.descriptions?.setting ? /*#__PURE__*/ _jsx("span", {
161
+ children: surface.admin?.descriptions.setting
123
162
  }) : null
124
163
  ]
125
164
  }) : null
126
165
  ]
127
166
  }),
128
- pages === undefined && !surface.flagPoints.length ? /*#__PURE__*/ _jsx("p", {
167
+ pages === undefined && !surface.flagPoints.length && !surface.pageCollections?.length ? /*#__PURE__*/ _jsx("p", {
129
168
  children: C.unavailable
130
169
  }) : null
131
170
  ]
@@ -156,7 +195,10 @@ export function NewTest({ surface, pages }) {
156
195
  /*#__PURE__*/ _jsx("a", {
157
196
  href: page.editorUrl,
158
197
  children: C.open
159
- })
198
+ }),
199
+ page.editor === 'blocks' ? /*#__PURE__*/ _jsx("p", {
200
+ children: C.blocksHandoff
201
+ }) : null
160
202
  ]
161
203
  }, `${typeof page.id}:${page.id}`))
162
204
  }),
@@ -331,13 +373,10 @@ export function NewTest({ surface, pages }) {
331
373
  type: "button",
332
374
  disabled: pending,
333
375
  onClick: ()=>{
334
- if (step === 'kind') router.push(formatAdminURL({
335
- adminRoute: surface.adminRoute,
336
- path: '/experiments'
337
- }));
376
+ if (step === 'kind') router.push(surfaceUrls.home(surface.adminRoute));
338
377
  else {
339
378
  setError('');
340
- setStep(step === 'name' ? 'setting' : 'kind');
379
+ setStep(step === 'name' && kind === 'flag' ? 'setting' : 'kind');
341
380
  }
342
381
  },
343
382
  children: C.back
@@ -0,0 +1,7 @@
1
+ import type { DocId } from '../../../types/contracts.js';
2
+ import type { SurfaceProps } from '../contracts.js';
3
+ /** One session stays mounted across Collection, all page steps and Review. */
4
+ export declare function PageWizard({ id, surface }: {
5
+ id: DocId;
6
+ surface: SurfaceProps;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,214 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import { useRouter } from 'next/navigation.js';
5
+ import { formatAdminURL } from 'payload/shared';
6
+ import { useTestDocument } from '../useTestDocument.js';
7
+ import { CopyRoute } from '../pagePicker/CopyRoute.js';
8
+ import { PageCombobox } from '../pagePicker/PageCombobox.js';
9
+ import { testPageCollection, controlFirst } from '../pagePicker/pagePicker.model.js';
10
+ import { NEW_TEST_COPY as C } from '../../copy/newTest.js';
11
+ import { READINESS_COPY } from '../../copy/readiness.js';
12
+ import { TEST_PAGE } from '../../copy/testPage.js';
13
+ import { SURFACE_COPY } from '../../copy/surface.js';
14
+ import { pageStepCopy } from '../../copy/pages.js';
15
+ import { READINESS, nextStep, pageReadinessContext, readinessArm } from '../readiness/readiness.model.js';
16
+ import { FieldErrors } from '../test/fields.js';
17
+ import { SaveStatus } from '../readiness/SaveStatus.js';
18
+ import { createApi } from '../../api.js';
19
+ import { useTransition } from '../readiness/useTransition.js';
20
+ /** One session stays mounted across Collection, all page steps and Review. */ export function PageWizard({ id, surface }) {
21
+ const router = useRouter();
22
+ const collections = surface.pageCollections ?? [];
23
+ const [step, setStep] = useState(collections.length > 1 ? 'collection' : 'control');
24
+ const test = useTestDocument(id, {
25
+ apiRoute: surface.apiRoute,
26
+ refetchPreflightOnFocus: step === 'review'
27
+ });
28
+ const testUrl = formatAdminURL({
29
+ adminRoute: surface.adminRoute,
30
+ path: `/experiments/${encodeURIComponent(String(id))}`
31
+ });
32
+ const transition = useTransition(test, ()=>router.push(testUrl));
33
+ useEffect(()=>{
34
+ if (step === 'review') void test.refreshPreflight();
35
+ }, [
36
+ step,
37
+ test.refreshPreflight
38
+ ]);
39
+ const leave = ()=>router.push(testUrl);
40
+ if (test.loadState === 'loading') return /*#__PURE__*/ _jsx("p", {
41
+ role: "status",
42
+ children: TEST_PAGE.loading
43
+ });
44
+ if (!test.doc || test.loadState !== 'ready') return /*#__PURE__*/ _jsxs("div", {
45
+ children: [
46
+ /*#__PURE__*/ _jsx("p", {
47
+ role: "alert",
48
+ children: test.loadState === 'forbidden' ? TEST_PAGE.forbidden : test.loadState === 'missing' ? TEST_PAGE.missing : TEST_PAGE.error
49
+ }),
50
+ /*#__PURE__*/ _jsx("button", {
51
+ type: "button",
52
+ onClick: ()=>void test.reload(),
53
+ children: TEST_PAGE.retry
54
+ }),
55
+ /*#__PURE__*/ _jsx("button", {
56
+ type: "button",
57
+ onClick: leave,
58
+ children: C.backToTest
59
+ })
60
+ ]
61
+ });
62
+ const doc = test.doc;
63
+ const collection = testPageCollection(collections, doc, test.preflight?.pagePlacements);
64
+ const arms = controlFirst(doc.arms).filter((arm)=>arm.kind !== 'holdout');
65
+ const steps = [
66
+ ...collections.length > 1 ? [
67
+ 'collection'
68
+ ] : [],
69
+ ...arms.map((arm)=>arm.key),
70
+ 'review'
71
+ ];
72
+ const arm = arms.find((item)=>item.key === step);
73
+ const ctx = pageReadinessContext(doc, test.preflight, surface);
74
+ const next = nextStep(test.preflight, ctx);
75
+ const ready = Boolean(test.preflight && !test.preflightPending && !test.preflightError && test.preflight.checks.every((check)=>check.ok));
76
+ const busy = test.hasUnsaved || test.saving === 'saving' || transition.busy;
77
+ const jump = (section, key)=>{
78
+ if (section === 'versions') setStep(key ?? arms.find((item)=>!item.pageTarget)?.key ?? 'control');
79
+ else router.push(`${testUrl}#section-${section}`);
80
+ };
81
+ const picker = arm && collection ? /*#__PURE__*/ _jsx(PageCombobox, {
82
+ collection: collection,
83
+ test: test,
84
+ armKey: arm.key,
85
+ apiRoute: surface.apiRoute
86
+ }, `${collection.slug}/${arm.key}`) : null;
87
+ return /*#__PURE__*/ _jsxs("div", {
88
+ className: "xp-new-test xp-page-wizard",
89
+ children: [
90
+ /*#__PURE__*/ _jsx("h2", {
91
+ children: step === 'collection' ? C.collection : step === 'review' ? C.review : arm?.kind === 'control' ? C.original : pageStepCopy(arm?.label ?? '')
92
+ }),
93
+ /*#__PURE__*/ _jsx(SaveStatus, {
94
+ test: test
95
+ }),
96
+ test.errors._section ? /*#__PURE__*/ _jsx("p", {
97
+ role: "alert",
98
+ children: test.errors._section
99
+ }) : null,
100
+ step === 'collection' ? /*#__PURE__*/ _jsxs("fieldset", {
101
+ children: [
102
+ /*#__PURE__*/ _jsx("legend", {
103
+ children: C.collection
104
+ }),
105
+ collections.map((entry)=>/*#__PURE__*/ _jsxs("label", {
106
+ children: [
107
+ /*#__PURE__*/ _jsx("input", {
108
+ type: "radio",
109
+ name: "page-collection",
110
+ checked: doc.pageCollection === entry.slug,
111
+ disabled: busy,
112
+ onChange: ()=>{
113
+ test.stage({
114
+ pageCollection: entry.slug
115
+ });
116
+ void test.commit();
117
+ }
118
+ }),
119
+ entry.label
120
+ ]
121
+ }, entry.slug))
122
+ ]
123
+ }) : step === 'review' ? /*#__PURE__*/ _jsxs(_Fragment, {
124
+ children: [
125
+ test.preflightError ? /*#__PURE__*/ _jsx("p", {
126
+ role: "alert",
127
+ children: test.preflightError
128
+ }) : null,
129
+ /*#__PURE__*/ _jsx("ul", {
130
+ children: test.preflight?.checks.map((check, index)=>{
131
+ if (!Object.hasOwn(READINESS, check.code)) return check.ok ? null : /*#__PURE__*/ _jsx("li", {
132
+ children: SURFACE_COPY.next
133
+ }, `${check.code}/${index}`);
134
+ const row = READINESS[check.code];
135
+ const sentence = row.next(check.detail, ctx);
136
+ const label = typeof row.nextStep === 'function' ? row.nextStep(check.detail, ctx) : row.nextStep;
137
+ return sentence && !check.ok ? /*#__PURE__*/ _jsxs("li", {
138
+ children: [
139
+ sentence,
140
+ label ? /*#__PURE__*/ _jsx("button", {
141
+ type: "button",
142
+ onClick: ()=>jump(row.section, readinessArm(check.code, check.detail, ctx)),
143
+ children: label
144
+ }) : null
145
+ ]
146
+ }, `${check.code}/${index}`) : null;
147
+ })
148
+ }),
149
+ ready ? /*#__PURE__*/ _jsx("p", {
150
+ children: READINESS_COPY.ready
151
+ }) : null,
152
+ /*#__PURE__*/ _jsx("button", {
153
+ type: "button",
154
+ disabled: busy || test.preflightPending || !test.preflight,
155
+ onClick: ()=>{
156
+ if (ready) void transition.run(()=>createApi(surface.apiRoute).start(id));
157
+ else if (next) jump(next.section, next.arm);
158
+ },
159
+ children: ready ? C.start : C.finishSetup
160
+ }),
161
+ transition.error ? /*#__PURE__*/ _jsx("p", {
162
+ role: "alert",
163
+ children: transition.error
164
+ }) : null
165
+ ]
166
+ }) : arm?.kind === 'control' ? /*#__PURE__*/ _jsxs(_Fragment, {
167
+ children: [
168
+ /*#__PURE__*/ _jsx("p", {
169
+ children: C.originalHelp
170
+ }),
171
+ picker
172
+ ]
173
+ }) : collection ? /*#__PURE__*/ _jsx(CopyRoute, {
174
+ collection: collection,
175
+ children: picker
176
+ }) : null,
177
+ arm ? /*#__PURE__*/ _jsx(FieldErrors, {
178
+ test: test,
179
+ path: `arms.${doc.arms.findIndex((item)=>item.key === arm.key)}.pageTarget`
180
+ }) : null,
181
+ /*#__PURE__*/ _jsxs("div", {
182
+ className: "xp-new-test-actions",
183
+ children: [
184
+ /*#__PURE__*/ _jsx("button", {
185
+ type: "button",
186
+ disabled: busy,
187
+ onClick: ()=>{
188
+ const previous = steps[steps.indexOf(step) - 1];
189
+ if (previous) setStep(previous);
190
+ else leave();
191
+ },
192
+ children: C.back
193
+ }),
194
+ /*#__PURE__*/ _jsx("button", {
195
+ type: "button",
196
+ disabled: busy,
197
+ onClick: leave,
198
+ children: C.backToTest
199
+ }),
200
+ step !== 'review' ? /*#__PURE__*/ _jsx("button", {
201
+ type: "button",
202
+ disabled: busy || step === 'collection' && !collection,
203
+ onClick: ()=>setStep(steps[steps.indexOf(step) + 1] ?? 'review'),
204
+ children: C.next
205
+ }) : null
206
+ ]
207
+ }),
208
+ test.errors.pageCollection ? /*#__PURE__*/ _jsx("p", {
209
+ role: "alert",
210
+ children: test.errors.pageCollection
211
+ }) : null
212
+ ]
213
+ });
214
+ }
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { PageCollection } from './pagePicker.model.js';
3
+ export declare function CopyRoute({ collection, children }: {
4
+ collection: PageCollection;
5
+ children?: ReactNode;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1,53 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { PAGE_COPY as C, openCollectionCopy, openOriginalCopy } from '../../copy/pages.js';
4
+ export function CopyRoute({ collection, children }) {
5
+ const link = /*#__PURE__*/ _jsx("a", {
6
+ href: collection.copyUrl,
7
+ target: "_blank",
8
+ rel: "noopener",
9
+ children: collection.copyLabel ?? openCollectionCopy(collection.label)
10
+ });
11
+ return /*#__PURE__*/ _jsxs("div", {
12
+ className: "xp-copy-route",
13
+ children: [
14
+ /*#__PURE__*/ _jsx("div", {
15
+ className: "xp-copy-route-action"
16
+ }),
17
+ collection.copyHint ? /*#__PURE__*/ _jsxs(_Fragment, {
18
+ children: [
19
+ /*#__PURE__*/ _jsxs("p", {
20
+ children: [
21
+ collection.copyHint,
22
+ ' ',
23
+ link
24
+ ]
25
+ }),
26
+ /*#__PURE__*/ _jsx("p", {
27
+ children: C.ownAddress
28
+ })
29
+ ]
30
+ }) : /*#__PURE__*/ _jsxs("ol", {
31
+ children: [
32
+ /*#__PURE__*/ _jsxs("li", {
33
+ children: [
34
+ openOriginalCopy(collection.label),
35
+ ' ',
36
+ link
37
+ ]
38
+ }),
39
+ /*#__PURE__*/ _jsx("li", {
40
+ children: C.duplicateStep
41
+ }),
42
+ /*#__PURE__*/ _jsx("li", {
43
+ children: C.ownAddress
44
+ })
45
+ ]
46
+ }),
47
+ /*#__PURE__*/ _jsx("p", {
48
+ children: C.thenChoose
49
+ }),
50
+ children
51
+ ]
52
+ });
53
+ }
@@ -0,0 +1,10 @@
1
+ import type { TestDocApi } from '../contracts.js';
2
+ import type { PageCollection } from './pagePicker.model.js';
3
+ import './pagePicker.css';
4
+ /** One input owns focus; list options are navigated through aria-activedescendant. */
5
+ export declare function PageCombobox({ collection, test, armKey, apiRoute }: {
6
+ collection: PageCollection;
7
+ test: TestDocApi;
8
+ armKey: string;
9
+ apiRoute: string;
10
+ }): import("react").JSX.Element;